最終更新日 2025-03-07

秀丸の「編集ペインの文字色」と「背景」を「個別ブラウザ枠」へと反映する

秀丸の編集領域の「文字色」や「背景色」を「個別ブラウザ」へと反映するには、どうすればよいのでしょうか?
HTMLというものは、「文字色」と「背景色」だけではなく、他にも様々な要素があるため、
文字色と背景色を反映させるにしても、「その組み合わせがライトモードに近いのか?」「ダークモードに近いのか?」を自動判定し、
それに基づいて全体のカラーリングを変更する必要があります。

テーマカラーも変えることで、リンクの色やボタンの色も変わっていることに注目。

編集ペインの「文字色」と「背景色」の組み合わせはライトモードに近い。
だから、「ライトモードの色セット」をベースにしつつ、文字色と背景色を反映。

編集ペインの「文字色」と「背景色」の組み合わせはダークモードに近い。
だから、「ダークモードの色セット」をベースにしつつ、文字色と背景色を反映。

「実質的なカラーモード」と「文字色」と「背景色」を伝達する

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

js {

debuginfo(2);

function isLightOrDarkMode(backgroundColor, textColor) {
    // 色をRGBに変換する関数 (HEX, RGB, HSLなど様々な形式に対応)
    function convertToRgb(rgb) {
        // HEX形式 (#RRGGBB)
        const r = parseInt(rgb.substring(0, 2), 16);
        const g = parseInt(rgb.substring(2, 4), 16);
        const b = parseInt(rgb.substring(4, 6), 16);
        return { r, g, b };
    }

    const bgRgb = convertToRgb(backgroundColor);
    const textRgb = convertToRgb(textColor);

    // 相対輝度を計算する関数
    function calculateRelativeLuminance(rgb) {
        const a = [rgb.r, rgb.g, rgb.b].map(v => {
            v /= 255;
            return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
        });
        return 0.2126 * a[0] + 0.7152 * a[1] + 0.0722 * a[2];
    }

    const backgroundLuminance = calculateRelativeLuminance(bgRgb);
    const textLuminance = calculateRelativeLuminance(textRgb);

    // コントラスト比を計算
    const contrastRatio = (Math.max(backgroundLuminance, textLuminance) + 0.05) / (Math.min(backgroundLuminance, textLuminance) + 0.05);

    // コントラスト比が低い場合は、判定不能とする
    if (contrastRatio < 1.5) {
        return "Indeterminate"; // 判定不能
    }

    // 背景色と文字色の輝度に基づいて、ライトモード/ダークモードを判定
    if (backgroundLuminance > textLuminance) {
        return "LightMode";
    } else {
        return "DarkMode";
    }
}

function getTextColor() {
    let textTextColorBGR = getconfigcolor(0, 0);
    let hexTextColorBGR = sprintf("%06X", textTextColorBGR);
    let hexTextColorRGB = hexTextColorBGR.replace(/(..)(..)(..)/, "$3$2$1");
    return hexTextColorRGB;
}

function getBackColor() {
    let textBackColorBGR = getconfigcolor(0, 1);
    let hexBackColorBGR = sprintf("%06X", textBackColorBGR);
    let hexBackColorRGB = hexBackColorBGR.replace(/(..)(..)(..)/, "$3$2$1");
    return hexBackColorRGB;
}

let backColor = getBackColor();
let textColor = getTextColor();

console.log("文字色;"+ textColor);
console.log("背景色:"+ backColor);

let isDarkMode = darkmode();

// しかし、実際に秀丸の編集ペインで指定している白・黒に基づいて、「実質的にはどちらなのか?」を上書きする。
let colorMode = isLightOrDarkMode(backColor, textColor);
if (colorMode == "LightMode") {
    isDarkMode = 0;
}
if (colorMode == "DarkMode") {
    isDarkMode = 1;
}


function makeUrl(htmlFullPath, darkMode, textColor, backColor) {
    // ベースURL
    const baseUrl = htmlFullPath;

    // URLSearchParamsオブジェクトを作成
    const params = new URLSearchParams({
        darkMode,
        textColor,
        backColor,
    });

    // URLオブジェクトを作成し、検索パラメータを設定
    const absoluteUrl = new URL(baseUrl);
    absoluteUrl.search = params.toString();

    return absoluteUrl;
}

// 対象のHTML
let absoluteUrl = makeUrl(`${currentmacrodirectory()}\\test.html`, isDarkMode, textColor, backColor);

// 個別ブラウザ枠として開く
browserpanecommand(
{
    target: "_each",
    url : absoluteUrl,
    initialize: "async",
    show: 1
}
);

} // js
    

HTML側

HTML側は受け取った情報を元に、「ドキュメントのテーマカラー」「文字色」「背景色」を設定する、といった形になります。
テーマカラーを変え忘れると、「文字色」と「背景色」だけが変わり、他のコンポーネントが変わらない、といった歪なことになるので注意しましょう。

test.html
<html>
<head>
<style>
[hm-theme-color="dark"] {
    color-scheme: dark;
}
[hm-theme-color="light"] {
    color-scheme: light;
}
</style>
</head>
<body>
通常テキスト:あああ
<div>リンク:<a href="aaa">bbbb</a></div>
<div>ボタンなど:<button value="OK">OK</button></div>
<script>
const urlSearchParams = new URLSearchParams(window.location.search);
const isDarkMode = Number(urlSearchParams.get('darkMode'));
const backColor = urlSearchParams.get('backColor');
const textColor = urlSearchParams.get('textColor');
// カラーが明示されたら、セッションストレージを更新
if (isDarkMode) {
    targetColor = isDarkMode ? 'dark' : 'light';
    // 対象のテーマカラーで表示
    document.documentElement.setAttribute('hm-theme-color', targetColor);
}

document.body.style.backgroundColor = "#" + backColor; // # を追加するのを忘れずに
document.body.style.color = "#" + textColor; // # を追加するのを忘れずに

</script>
</body>
</html>