DTPab

印刷やデザイン、アドビ製アプリやスクリプトなど、雑多な技術ブログ

InDesignのExtendScriptでルビを実装しよう

1年は早いもので、今年も残すところあと1ヶ月となりました。そう、12月といえばクリスマス、クリスマスといえばアドベントカレンダー! ということで、この記事はDTPアドベントカレンダー2日目の記事になります。
前回の記事はTen_Aさんの『INDESIGNで圧縮ファイルを操作しよう(^-^)/』でした。

一番最初ですからゆる〜く行きますねw

言葉通りゆる〜く……なかったですね(平常運転)!

さて、僕の記事はTen_A先生の内容よりも少しだけゆるいので、ともかく構えずに楽しんでください。InDesignでルビを振る作業をスクリプトでどう行うかをかんたんに解説します。

スクリプトでルビを適用する最低限の要素

InDesignにおけるルビの適用は例えば下記のように行います。

var doc = app.activeDocument;
var sel = doc.selection[0]; //文字を選択しているという前提

sel.rubyFlag = true;
sel.rubyString = "ほげ";

このスクリプトを文字を選択した状態で実行すると、選択した文字に対して「ほげ」というルビが振られます。
CharacterオブジェクトをはじめとするTextオブジェクトにはrubyFlagプロパティとrubyStringプロパティが用意されており、rubyFlagtrueにするとrubyStringに設定されている文字列がルビとして適用される、という仕組みです。この2つさえ設定すれば、最低限、ルビを適用することが可能です。

ただInDesignでGUI(マウス操作)から設定するルビとちょっと違うと感じませんか?

f:id:uske_S:20191202014140p:plain
InDesignのルビ設定ダイアログ

InDesignから直接ルビを適用する場合、ルビ設定ダイアログにルビの文字列を入力してOKボタンを押した段階で、先の2つのプロパティが設定された状態になります。
スクリプトではルビの文字列(rubyString)が設定されただけではルビが表示されない、ということだけ覚えておいてください。

ルビ設定に関する主なオプション

モノルビ/グループルビ

rubyTypeを設定します。値はEnum*1です。

設定 Enum
モノルビ RubyTypes.PER_CHARACTER_RUBY 1249013859
グループルビ RubyTypes.GROUP_RUBY 1249011570
/** サンプルコード
 *  2つの親文字に対してモノルビを設定する
 */

var doc = app.activeDocument;
var sel = doc.selection[0]; //2文字選択しておく

sel.rubyFlag = true;
sel.rubyString = "ほ げ";
sel.rubyType = RubyTypes.PER_CHARACTER_RUBY;

位置

rubyPositionを設定します。こちらも値はEnumです。

設定 Enum
上 / 右 RubyKentenPosition.ABOVE_RIGHT 1248551282
下 / 左 RubyKentenPosition.BELOW_LEFT 1248551532
/** サンプルコード
 *  ルビの位置を親文字の左にする(縦組みの場合)
 */

var doc = app.activeDocument;
var sel = doc.selection[0];

sel.rubyFlag = true;
sel.rubyString = "ほげ";
sel.rubyPosition = RubyKentenPosition.BELOW_LEFT;

文字色

rubyFillというプロパティを設定します。FillはおそらくFillColorの略です。値はスウォッチオブジェクトそのものか、スウォッチ名(String型)で設定できます。

/** サンプルコード
 *  ルビの塗り色を設定する
 */

var doc = app.activeDocument;
var sel = doc.selection[0];

sel.rubyFlag = true;
sel.rubyString = "ほげ";
sel.rubyFill = "C=100 M=0 Y=0 K=0";

ただし、以下のスウォッチをスウォッチ名(String型)で指定する場合は特定の表記にする必要があります。

スウォッチ名 スクリプトで指定するString型
[なし] 'None'
[黒] 'Black'
[紙色] 'Paper'
[レジストレーション] 'Registration'

応用編

文字列に合わせて設定を変更する

ルビは状況(親文字)に応じて、モノルビかグループルビを切り替える必要があります。その判断をすべてスクリプトに委ねることはできません。したがって、そこは作業者に選択させる必要が出てきます。
例えば、『Word文書の体裁(ルビ・文字飾り・脚注など)をInDesignに反映する』(mottainaiDTP)で紹介されているWordマクロを利用して、Wordから下記のようなテキストが用意できたとします。

大きな〓三毛猫《みけねこ》でした。

モノルビとして設定するにしても親文字と振られるルビとの対応関係をスクリプトに委ねることはできませんし、グループルビとして設定するならそう指定しなければいけない、そんな状態です。
こういうケースでは、ダイアログを用意して、作業者に入力させる、もしくは選択させるという方法がベストでしょう。

var doc = app.activeDocument;
var sel = doc.selection[0];

//親文字とルビをセットで検索
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = "〓(.+?)《(.+?)》";
var tgt = sel.findGrep();

//親文字とルビを切り分け
app.findGrepPreferences.findWhat = "(?<=〓)(.+?)(?=《)";
var parentChar = tgt[0].findGrep();
app.findGrepPreferences.findWhat = "(?<=《)(.+?)(?=》)";
var rubyChar = tgt[0].findGrep();

//ダイアログによる任意設定
var dlg = new Window('dialog {alignChildren: ["fill", "center"]}', 'ルビ設定サンプル');
var dlgItems = [
    dlg.add('editText {preferredSize: [150, -1], text:"'+rubyChar[0].contents+'"}'),
    dlg.add('staticText {text: "'+parentChar[0].contents+'"}'),
    dlg.add('radioButton {text: "モノルビ"}'),
    dlg.add('radioButton {text: "グループルビ"}'),
    dlg.add('button', undefined, '実行', {name: 'ok'})
];
dlgItems[0].title = "ル ビ:";
dlgItems[1].title = "親文字:";
dlgItems[2].value = true;
dlgItems[4].onClick = function() {
    dlg.close(1);
};
if (dlg.show() !== 1 || !dlgItems[0]) {
    exit();
}
var myRubyType = "";
if (dlgItems[3].value) {
    myRubyType = "PER_CHARACTER_RUBY";
} else {
    myRubyType = "GROUP_RUBY";
}

//親文字にルビを設定
parentChar[0].properties = {
    rubyFlag: true,
    rubyString: dlgItems[0].text,
    rubyType: RubyTypes[myRubyType]
};

//後処理
app.findGrepPreferences.findWhat = "〓|《.+?》";
app.changeGrepPreferences.changeTo = "";
tgt[0].changeGrep();

空白文字に注意

スクリプトでルビを振るのはとても便利な半面、InDesignのGUIで制御されて適用できない空白文字に対するルビが、スクリプトでならできてしまいます。

f:id:uske_S:20191202014522p:plain
空白文字へルビが適用できる

ルビは適用できているのに、GUIでルビの設定を開くとグレーアウトして修正できません。

f:id:uske_S:20191202014541p:plain
ダイアログではルビ設定部分がグレーアウト

こうなってしまうと、スクリプトからしか制御できないデータになってしまいます。
自分以外の作業者がデータに触れる機会が1%でもあるなら、このようなデータを作ってしまわないよう、特にスクリプトを作る側が注意する必要があります。スクリプトは非常に強力なツールで作業時間を大きく削減できる可能性を秘めていますが、データの安全性や作業の再現性などは注意深く観察し、検証しないといけません。後で大きな問題を残すことになりかねないからです。

まとめ

  • スクリプトからルビを適用するにはrubyFlagrubyStringという最低限2つのプロパティを設定すればよい
  • ルビ設定の各種オプションはすべて用意されているので必要に応じて設定する
  • モノルビかグループルビか、モノルビの区切り箇所を決めることは機械的に判断できないためダイアログなどで作業者に選択/入力させる必要が出てくる
  • スクリプトでは空白文字にルビを振ることができてしまうので注意

以上が2019年のDTPアドベントカレンダーの記事です。基本的な部分と、実用的な部分と、そこそこ楽しんでもらえたのではないかと思います!(自己満

最後に…

最後に、今年の技術書典で頒布した初めての同人誌も実はルビに関するものを書いています。

f:id:uske_S:20190910220948p:plain
InDesign × Google Apps Script -ルビ振りAPI編

uske-s.hatenablog.com

こちらもぜひご覧ください!

次回はお〜まちさんのOfficeアプリ向けAdobe CCアドインの話みたいです。お楽しみに!

*1:お〜まちさんの言葉を借りると「列挙値」。いくつか用意された選択肢の中からしか値をセットできない特殊なタイプです