最終更新日 2025-03-18

JavaScriptの文字列を.NETの文字列に

概要

.NET の Stringでのみ利用可能な.NETメソッド群を利用するには、javascriptの文字列を.NETの文字列に変換する必要があります。
これはなかなか気づきにくい方法となりますので、ここではその手法を紹介します。

javascriptの文字列を.NETの文字列に変換

#JS = loaddll( hidemarudir + @"\hmJS.dll" );
if ( !#JS ) { message "hmJS.dllが読み込めない"; }
 
#r = dllfuncw( #JS, "DoString", 

""""""""""""""""""""""""""""""""""""""""""""""""""
Object.prototype.toClr = function () {
    return host.newVar(this.valueOf());
}

function ToDotNetString(jsText) {
    return jsText.toClr();
}

var dotNetStr = ToDotNetString("養⽼の滝⼊⼝駐⾞場");
dotNetStr.Normalize(clr.System.Text.NormalizationForm.FormKC);

hm.OutputPane.Output(b);

""""""""""""""""""""""""""""""""""""""""""""""""""
);

freedll( #JS );

このようにすることで、javascriptの文字列を.NETの文字列に変換し、.Normalizeメソッドを利用することが出来るようになりました。

サロゲートペアなどまでも考慮した、文字列の捜査

#JS = loaddll( hidemarudir + @"\hmJS.dll" );
if ( !#JS ) { message "hmJS.dllが読み込めない"; }
 
#r = dllfuncw( #JS, "DoString", 

""""""""""""""""""""""""""""""""""""""""""""""""""
Object.prototype.toClr = function () {
    return host.newVar(this.valueOf());
}

function toNETString(jsText) {
    
    return jsText.toClr();
}

function getTargetString() {
    return gettotaltext();
}

var walker = clr.System.Globalization.StringInfo.GetTextElementEnumerator(toNETString("養ぎ⽼の滝⼊⼝駐⾞場"));

while (walker.MoveNext())
{
    var jsText = walker.GetTextElement();
    var dnText = toNETString(jsText);
    var normalizedText = dnText.Normalize(clr.System.Text.NormalizationForm.FormKC);
    hm.OutputPane.Output(normalizedText);
}


""""""""""""""""""""""""""""""""""""""""""""""""""
);

freedll( #JS );

サロゲートペアなどまでも考慮した、文字列の捜査も可能です。

応用例。サロゲートペアや異体文字などをできるだけ、よく利用される範囲の文字にする

#JS = loaddll( hidemarudir + @"\hmJS.dll" );
if ( !#JS ) { message "hmJS.dllが読み込めない"; }
  
#r = dllfuncw( #JS, "DoString", 
 
""""""""""""""""""""""""""""""""""""""""""""""""""
Object.prototype.toClr = function () {
    return host.newVar(this.valueOf());
}

function main() {
 
    var srcText = gettotaltext();
 
    var srcTextArray = srcText.split("\n");

    for(var ix=0; ix < srcTextArray.length; ix++) {
        srcTextArray[ix] = normalizeLine(srcTextArray[ix]);
    }

    var dstText = srcTextArray.join("\n");

    if (srcText != dstText) {
        settotaltext(dstText);
    }
}

function normalizeLine(text) {

    // 行全体がSJISの範疇に収まるなら、そのまま採用
    if (canConvertSJIS(text)) {
        return text;
    }

    // JavaScriptの文字列を.NETの文字列に変換し、
    var netSrcText = text.toClr();
    // 合成文字やサロゲートペアも考慮した、ウォーカー(捜査オブジェクト)を構築
    var walker = clr.System.Globalization.StringInfo.GetTextElementEnumerator(netSrcText);
 
    // 変換結果
    var dstText = "";
 
    // 次の文字が存在する限りにおいて、次の文字へと移動
    while (walker.MoveNext())
    {
        // 文字を取得。「複数の文字」で「1つの文字を形成」している場合、その複数を全部まとめて取得
        var jsText = walker.GetTextElement();
 
        // 特殊な正規化をしつつ、変換結果に追加していく
        dstText += customNormalize(jsText);
    }

    return dstText;
}

// 1文字ずつに対して処理する特殊な正規化
function customNormalize(jsText) {
 
    // SJISに収まるならそのまま採用
    if (canConvertSJIS(jsText)) { 
        return jsText;
    }
 
    // NFCで正規化をトライ
    var dnText = jsText.toClr();
    var normNFC = dnText.Normalize(clr.System.Text.NormalizationForm.FormC);
    // なんか文字が変化してるならまぁそのまま採用。多分よく使う文字に変換されたんだろう。
    if (jsText != normNFC) {
        return normNFC;
    }
 
    // 仕方がないので、NFKCで変換
    var normNFKC = dnText.Normalize(clr.System.Text.NormalizationForm.FormKC);
    return normNFKC;
}
 
// SJISに変換して、元へともどした時、同じ文字なら、SJISに収まる文字
function canConvertSJIS(text) {
    try {
        if (!this.encoder) {
            this.encoder = clr.System.Text.Encoding.GetEncoding("Shift_JIS");
        }
        var encodedBytes = this.encoder.GetBytes(text);
        var decodedText = this.encoder.GetString(encodedBytes);
        return text == decodedText;
    } catch(e) {}
 
    return false;
}
 
main();
 
""""""""""""""""""""""""""""""""""""""""""""""""""
);
 
freedll( #JS );

このように.NETの文字列とjavascriptを経由して、秀丸エディタの編集文字をうまく編集することが可能です。