最近、ある自動組版のプログラムを書いています。プログラムは大まかに2つの部分に分かれます。【1】は自動組版、【2】は組版後のInDesignデータを抽出し元の入稿データと比較するものです。自動組版する際、いくつかの外字を指定の字形に置換する必要があります、逆に、抽出する際、元に戻してから比較する必要があります。【1】と【2】の外字処理部分は共通のデータ(dictに定義)を使用しているため、このデータと他のいくつかの共通設定を、単独のjsxスクリプトに書き込んでからインポート(include)します。
ここで悪夢が始まります。
デバッグ中に、非常に妙な事が発生しました。
InDesign から抜き出したデータ(リスト)を csv に書き込むと、csv の総行数が常に list.length よりも3行少ないことがわかりました。調査の結果、足りない 3 行にはすべて外字が含まれていることがわかりました。
プログラムを最小限に抑えると、おおよそ次のようになります:
外字の置換リストは、myReplaceList.jsx ファイルに書かれています。
const replaceList = { "a": "あ", "吉野家": "𠮷野家", "i": "い", //他の置換対象... }
その後、組版プログラム(仮に testScript.jsx とします)にこのファイルをインポートします。
#include myReplaceList.jsx // for (var k in replaceList) { $.writeln(k, ":", replaceList[k]); } // writeTxtFile(replaceList); // function writeTxtFile(dict) { var fileObj = new File("~/Desktop/myReplaceList.txt"); fileObj.encoding = "UTF-8"; if (fileObj.open("w")) { for (var k in dict) { fileObj.writeln(k, ":", replaceList[k]); } fileObj.close(); } else { alert("Failed to open data file."); } }
コンソールに出力したり、txt ファイルに書き込んだりすると、次のようになります!1 行不足しています(replaceList辞書内の𠮷野家のデータが欠落しています)!
デバッグ中、replaceList は次のようになります。
𠮷野家の行を注釈してみたら、問題なくなる。"Failed to retrieve variables" を検索しましたが、役立つ情報は見つかりませんでした。
さらに調査を進めるために(プログラムをさらに最小限にする)、myReplaceList.jsx の replaceList 変数を直接 testScript.jsx に書き込むと、次のようになります。
何の問題もありません。
ここまでで、1 日を費やしました。問題がなんとなくわかった:外字を外部jsxファイルに定義すると、includeする時に問題が発生する可能性があります。
原因を特定するために、再度調査範囲を縮小します。以下のコードを config.jsx ファイルに保存する。
const myChar = "𠮷";
メインの処理プログラムにconfig.jsxをinclude:
#include config.jsx //外部で定義した変数を参照する $.writeln("myChar: ", myChar);//なにも表示されない $.writeln("myChar === 𠮷: ", myChar === "𠮷");//false $.writeln("myChar.toSource(): ", myChar.toSource());//(new String("\uD842"))
myCharを直接にメインプログラム内部で定義する:
const myChar = "𠮷"; //本スクリプトで定義した変数を参照する $.writeln("myChar: ", myChar);//myChar: 𠮷 $.writeln("myChar === 𠮷: ", myChar === "𠮷");//true $.writeln("myChar.toSource(): ", myChar.toSource());//(new String("\uD842\uDFB7"))
この2つの結果を比較してみたら、toSource()の結果に注目すようようになった。外部jsxをincludeする際、サロゲートペア文字について、なぜか後半のサロゲート(今回の例だと:\uDFB7)が無視されてしまう。この時点、直ぐにconfig.jsxをutf-16に再保存してみると、予想通りに問題消えた!(普段はvscode使っていて、defaultはutf-8なのです)
更に掘ってみると、下記のことに辿り着いた:
・外部jsxをutf-8で保存する場合、includeする際、サロゲートペア文字の後半サロゲートが無くなる。
・外部jsxをutf-16で保存する場合、問題ない。
・同じjsxファイル内で定義する場合、utf-8でも16でも問題ない。
※因みに、Pythonで試してみたが、問題ないです。(Pythonで自動組版する際、通常通り使えばいいです)
結論:共通のjsxファイルを定義する際、utf-16で保存すると無難でしょう。