最終更新日 2025-02-18

「jsmode」と「レンダリング枠」との相互通信

「jsmodeの変数等の内容」⇔「レンダリング枠の内容」を、
ファイルで情報をやりとりするのではなく、
通信でテキストをやりとりするにはどうすればよいのでしょうか?

HttpServer (HTML←編集ペイン)

「HTML側」から「秀丸の編集ペインの情報」などを読取る

JavaScript:*** というブックマークレットを送信 (編集ペイン→HTML)

秀丸の編集ペイン側からHTML側へと送る
(主体が違うだけで情報の流れは上と同じ)

window.chrome.webview.postMessage (HTML→編集ペイン)

HTML側から編集ペイン側へと情報を送る

HttpServerオブジェクトを使いましょう。

test.mac
jsmode "WebView2\\" + currentmacrofilename;

js {
debuginfo(2);

if (typeof(server) != "undefined") {
    server.close();
}

var server = hidemaru.createHttpServer(async (req, res) => {

    let url = req.url;
    // ここはパッチだと思って!!
    if (typeof (url) != "string") {
        url = await req.url;
    }

    if (url == "/text") {
        res.writeHead(200);//OK
        res.write("編集エリアの文字数は、" + gettotaltext().length + "文字");
        res.end("requested url:" + url);
    } else {
        res.writeHead(404);//Not found
        res.end("");
    }
});

server.listen(0); //ランダムなポート
let port = server.port;

if (port == 0 ) {
    console.log("サーバー構築失敗");
}

function callBackFunc(message_text) {
    console.log(message_text);
}

function makeUrl(htmlFullPath, funcid, portNumber) {
    let absoluteUrl = new URL(htmlFullPath);
    let params = new URLSearchParams();
    params.set("port", String(portNumber));
    params.set("func", String(funcid));
    absoluteUrl.search = new URLSearchParams(params).toString();
    return absoluteUrl;
}

function main() {

    let funcid = hidemaru.getFunctionId(callBackFunc);
    let url = makeUrl(currentmacrodirectory() + "\\" + "test.html", funcid, port);

    renderpanecommand({
        target: "test",
        url: url,
        show: 1,
    });
}

main();

} // js

HTML 側

test.html
<!DOCTYPE html>
<html>
<head>
    <title>test.html</title>
</head>
<body>
    <button onclick="fetchData()">データを取得</button>
    <button onclick="postData()">データを送信</button>
    <div id="output">最初の文字</div>
 
    <script>
    // ファイルURLからポート番号を取得
    let urlParams = new URLSearchParams(window.location.search);
    let port = Number(urlParams.get('port'));
    let func = Number(urlParams.get('func'));
 
    async function postData() {
        let message_obj = {
            text: "あいうえお",
        };
        let message_json = JSON.stringify(message_obj);
        window.chrome.webview.postMessage({funcid:func, message:message_json});
    }
 
    function fetchData() {
        if (!port) {
            output.innerText = "ポート番号が指定されていません。";
            return;
        }
        const url = `http://localhost:${port}/text`;
 
        fetch(url)
            .then(response => {
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                return response.text();
            })
            .then(data => {
                output.innerText = data;
            })
            .catch(error => {
                output.innerText = "エラーが発生しました: " + error;
            });
    }
    </script>
</body>
</html>