ReVIEWの外部ファイル取り込み(プリプロセッサ)

 ReVIEWではドキュメントの中に、外部のテキストファイルの内容やコマンドの結果を取り込む方法が用意されています。ReVIEWドキュメントの中を検索しながら編集しなくても、外部ファイルを差し替えればすべての参照箇所が書き換えられます。

特定の単語を差し込む

 まずは簡単な単語差し込みを試してみましょう。ReVIEWドキュメントと同じ階層に「name.txt」というテキストファイルを用意してください。「name.txt」の中身は自分の名前を書いておきます。
f:id:seuzo:20120309173744p:image
f:id:seuzo:20120309173759p:image
 ReVIEWドキュメントの方は「name.txt」を参照するためにインライン要素@<include>{pathname}を使います。たとえば、実際にはこうなります。

私が担当の@<include>{name.txt}です。

f:id:seuzo:20120309174456p:image
 このReVIEWドキュメントからHTMLを生成すると、「name.txt」の内容を差し込みしました。
f:id:seuzo:20120309174913p:image
 このname.txtにはReVIEW記法が使えます。テキストの差し込みが行われた後に、ReVIEW記法が評価されているようです。
f:id:seuzo:20120309175307p:image
f:id:seuzo:20120309175310p:image
 ちなみに、@<include>{pathname}はパスを理解するので、「name.txt」がimagesディレクトリの中にあれば、@<include>{images/name.txt}と書けるでしょう。

段落を含んだ文章を差し込む

 @<include>{pathname}はあくまでインライン要素として文中に差し込むためのコマンドです。別管理されたコードリストなどの外部ファイルの内容など、複数行の段落にわたるブロックとして取り込みたいときには、ちょっと手順を踏む必要があります。

(1)外部ファイルを用意する
 ここでは「script.rb」というテキストファイルを用意しました。
f:id:seuzo:20120309232059p:image
f:id:seuzo:20120309232008p:image

(2)オリジナルReVIEWドキュメントにファイル指定する
 オリジナルReVIEWドキュメント「ch02_org.re」の中の挿入位置に下記マーキングをします。

#@mapfile(script.rb)
#@end

f:id:seuzo:20120309232544p:image

(3)review-preprocコマンドで外部ファイルをマージする
 ターミナルから下記review-preprocコマンドをタイプします。

$ review-preproc ch02_org.re > ch02.re

 プリプロセッサで生成した「ch02.re」を見てみましょう。
f:id:seuzo:20120309233133p:image
 「script.rb」の内容が「ch02.re」の中に挿入されているのがわかります。あとで「script.rb」の中を修正したとしても、プリプロセッサで再マージすれば常に新しいReVIEWドキュメントが生成されます。「#@mapfile(script.rb)」と「#@end」の行は「ch02.re」内に残っていますが、「review-compile」コマンドで変換時、EPUBXMLなどの最終生成物には残りません。
 一連の手順を図にするとこんな感じになります。
f:id:seuzo:20120309233811p:image
 「#@mapfile(pathname)」で展開されるテキスト中にあるタブ文字は、すべてスペースに変換されますから注意してください。もしタブ文字のままであったら、表組みのTSVなども差し込みできるのになあ... と思います。

外部ファイルの一部だけを利用する

 外部ファイルの一定の範囲だけを選択的に差し込むためには

#@maprange(filepath, rangename)
#@end

を使うらしいのですが、ちょっとよくわかっていません。MLでそれらしい議論もあるのですが...
外部ファイルを読み込む記法 - qwik.jp/review
 詳細が分かり次第、追記したいと思います。
(追記:2012-06-06T16:17:57+0900)http://qwik.jp/review/81.html で高橋征義さんによってmaprange()の使い方が解説されていました。以下テストしてみました。

(1)外部ファイルの取り込みたい部分を「#@range_begin(rangename)」から「#@range_end(rangename)」で囲います。*1
 ここでは「script04.rb」というファイル内で「config」というラベル名で範囲を指定しました。
f:id:seuzo:20120606185136p:image

(2)オリジナルReVIEWドキュメントにファイルとラベルを指定する
f:id:seuzo:20120606185625p:image

(3)review-preprocコマンドで外部ファイルをマージする

$ review-preproc ch04_org.re > ch04.re

 「ch04.re」は指定範囲が取り込まれているのが分かります。
f:id:seuzo:20120606185853p:image
f:id:seuzo:20120606190422p:image

コマンドの実行結果を取り込む

 「#@mapoutput(コマンド) 〜 #@end」を使えば、コマンドの実行結果を取り込むことができます。
 たとえば、今年の年号を表記する時などはこのように書くことができます。

#@mapoutput(date +"%Y")
#@end

f:id:seuzo:20120311220524p:image
 review-preprocコマンド後には展開されてこうなります。
f:id:seuzo:20120311220810p:image
 review-compileでHTMLを生成するとこうなります。
f:id:seuzo:20120311221012p:image

 コマンドで展開できるのは、既存のアプリケーションだけではありません。テキストを返すものならば、自作のスクリプトでもよいのです。たとえば、昨日こちらのアップした「特定のTweet引用時の正書法」をつかってみましょう。

#@mapoutput(ruby19 cite_a_tweet.rb "https://twitter.com/#!/never4get_jp/status/178718486745452544")
#@end

f:id:seuzo:20120311222418p:image
 review-preprocコマンド後には展開されてこうなります。
f:id:seuzo:20120311222850p:image
 review-compileでHTMLを生成するとこうなります。
f:id:seuzo:20120311223217p:image

*1:この目印のためのマーキングは「^#@range_begin(.+?)」でなければなりません。行頭から「#」始まりである必要があります。#がコメント扱いになる言語に最適化されています

特定のTweet引用時の正書法

英語論文で特定のツイート引用時の正書法について書かれているブログ記事を拝見しました。
英語論文におけるツイートの正しい引用のしかた[MLAスタイル]:エディテック:ITmedia オルタナティブ・ブログ

この正書法に則るために、なんどもコピペするのがめんどい人のためのrubyスクリプト(要nokogiri)

#!/usr/bin/ruby
# -*- coding: utf-8 -*-

require "open-uri"
require 'nokogiri'

if ARGV.length != 1 then
  puts "Error: No parameter."
  exit
end

my_uri = ARGV[0].dup #パラメータは.dupしないと変更できない。
if my_uri =~ %r{^https://twitter.com/.+/status/\d+$} then
  my_uri.sub!(%r{^https://twitter.com/#!/}, "https://twitter.com/")
else
  puts "Error: Is not Twitter-uri."
  exit
end


#XHTMLのパース
doc = Nokogiri::HTML(open(my_uri))

#XPathで各エレメントから文字列を取り出す
my_fullname = doc.search('div[@class="full-name"]').text.to_s#ユーザーフルネーム
my_id = doc.search('meta[@name="page-user-screen_name"]').attribute('content').to_s#ユーザーID
my_entry_content = doc.search('span[@class="entry-content"]').text.to_s#エントリー内容
my_time = doc.search('span[@class="published timestamp"]').attribute('data').to_s#エントリー時間
my_time.sub!(/^{time:'(.+)'\}/) {$1}


#書式にあわせてprint
print "#{my_fullname} (@#{my_id}). “#{my_entry_content}” #{my_time}. Tweet.\n#{my_uri}\n"

パーマリンクを指定して実行すると、こんな感じになります。
f:id:seuzo:20120310173443p:image
本当はTwitter APIでとってくればXMLでより正確にtextを取れるのかもしれないけど、とりあえずclass名とかで取れています。まあ、日付をパースしなおして日本時間にしてもいいかな。
もし万が一、ちゃんと使う人がいるようだったら -j オプションで日本語引用風にするとか考えます。
とりあえず。

Illustratorの「ドキュメントを SVG として保存.jsx」をちょっと改造して「ドキュメントを PNG として保存.jsx」にする

 印刷用のIllustratorドキュメントをWeb用(とかEPUB用)にPNGフォーマットへ変換したい時ってあります。ひとつづつドキュメントを開いて、「Webおよびデバイス用に保存」ダイアログを出し、プリセットを選んで変更し、名前を付けて保存... って数百点もやってられっか! と泣きながら作業している人も多いでしょう。
 Illustratorの「ファイル」メニューの「スクリプト」-「ドキュメントを SVG として保存」ってのはあるんだけどなー、と思った人もいるかもしれません。それ、ちょっと改造するとPNG書出しもできる子になりますよ! というお話。初めての人向きにステップバイステップで説明してみます。
 この「ドキュメントを SVG として保存」のスクリプトそのものはどこにあるかというと、Mac環境だとたいてい「/Applications/Adobe Illustrator CS5/Presets.localized/ja_JP/スクリプト/ドキュメントを SVG として保存.jsx」にあります。このファイルを複製して「ドキュメントを PNG として保存.jsx」と名前をつけておいてください。
f:id:seuzo:20120308221810p:image
 複製したファイルをExtendScript Toolkitで開くとこんな感じになっているはずです。
f:id:seuzo:20120308222728p:image
 左上の対象アプリケーションのポップアップを「Adobe Illustrator CS5」に直して、さあカイゾーだ!@|@

(1)ダイアログの文字列を変更する

 書出し用の保存フォルダを選択するダイアログと、最後の作業完了ダイアログに「SVG」という文字が出てきます。完全に見た目の問題ですが、気分が悪いので、さっさと変えちゃいましょう。
 31行目と52行目にある「SVG」という文字を「PNG」に変更します。
f:id:seuzo:20120308235420p:image
 これらを変更することで、ダイアログ内の文字が変更されるようになります。
f:id:seuzo:20120308235256p:image

(2)保存拡張子の変更

 保存する時に自動で「.png」拡張子をつけるようにします。44行目の「.svg」を「.png」に変更してください。
f:id:seuzo:20120308225732p:image

(3)書出しタイプの変更

 書出しタイプをSVGからPNG24に変更します。47行目の「ExportType.SVG」を「ExportType.PNG24」に変更します。
f:id:seuzo:20120308230204p:image
 ちなみに、ExportTypeは他にも「JPEG」や「GIF」「PHOTOSHOP」なども選べます。詳しくはExtendScript Toolkitのオブジェクトモデルビューアで確認してください。
f:id:seuzo:20120308230430p:image

(4)オプションを指定

 PNG24の書出しオプションをいくつか設定します。67行目の「function」から82行目の「}」までをざっくり下記と入れ替えてください。

function getOptions()
{
	// Create the required options object
	var options = new ExportOptionsPNG24();
    
    options.antiAliasing = true;//アンチエイリアス処理
    options.artBoardClipping = false;//オブジェクトのみ
    options.horizontalScale = 200;//200%拡大
    options.verticalScale = 200;//200%拡大
    	
	return options;
}

f:id:seuzo:20120308231044p:image
 原寸で印刷用に描かれたイラストは、Webブラウザなどで見るとけっこう小さく見えてしまいます。文字なども含まれるでしょうから、ここでは200%拡大で書き出しています。
 ちなみにPNG24の他の設定については、オブジェクトモデルビューアで確認できます。
f:id:seuzo:20120308231506p:image

(5)バグの修正

 SVG書出しの場合はこれで終わりなのですが、PNG書出しでは、なぜかうまく書き出されません。書き出すドキュメントが最前面にないと、同じものを書き出してしまうバグがあるようです(舌打ちっ
 42行目に1行追加してください。

sourceDoc.activate();

f:id:seuzo:20120308232227p:image

(6)テスト

 じゃあ動かしてみましょう! 改造したスクリプトを保存し、書出しをしたい複数のドキュメントを開いてください。ExtendScript Toolkitから直接動かしてもいいですし、Illustratorを再起動させれば、メニューからアクセスできるようになっているはずです。


 スクリプトに馴れてくると、いちいちダイアログなしで閉じられたらいいなーとか、ソース元フォルダを指定するだけで.ai拡張子をもつファイルだけ処理してくれるようになったらいいなーとか、いろいろヨッキューが高まってくるかもしれません。まあ、そういうリビドーを感じればしめしめ...

ReVIEWの自動採番やプレフィックス、番号参照を制御する

 以下の記事はReVIEW ML(要アカウント)でKADOさんにお教えいただいたことを、自分なりにメモしたものです。


 例えば、このようなReVIEWマーキングしたテキストを用意したとします。
f:id:seuzo:20120306165636p:plain
 これをまあ、スタイルシート以外のオプションをつけないで、review-compileしてHTML変換します。

$ review-compile --target html --stylesheet=main.css ch01.re > ch01.html

 HTMLだと変換後にすぐに確認できます*1
f:id:seuzo:20120307131111p:plain
 ReVIEWは当初、技術書を書くために設計されたので、下記の自動採番や番号参照などがデフォルトになっています。

  • 見出しのプレフィックスと採番
  • (図|表|リスト)のプレフィックスと採番
  • (図|表|リスト)の番号参照

見出しのプレフィックスを変更する

 章見出し(h1)のプレフィックスがデフォルトで「第n章 」になっています。これを「chapter n 」変更してみましょう。
 ReVIEWドキュメントと同じ階層に「locale.yaml」という名前のテキストファイルを用意します。このテキスト内容を下記の通りにしてみてください。

locale: ja
chapter: "chapter %d"
chapter_postfix: " "

f:id:seuzo:20120307135609p:plain
 このファイルを設置し終えたら、先ほどと同じコマンドでHTMLを生成してみます。
f:id:seuzo:20120307135728p:plain
 「第1章 」が「chapter 1 」になっていますね。.yaml上の「locale: ja」は日本語環境であるロケールを、「chapter: 」がh1要素のプレフィックス文字列を、「%d」が章番号の自動採番を、「chapter_postfix: 」がchapterプレフィックスと見出しとの間の文字列をそれぞれ表しています。
 YAMLのキーと値の初期値は「lib/review/i18n.yaml」にあります。GitHubでいうとこちら

 現在、定義されているキーの簡単な意味はこんな感じです。

キー 初期値 意味
image 図版(とその参照)の最初に置かれるプレフィックス
table 表(とその参照)の最初に置かれるプレフィックス
list リスト コードリスト(とその参照)の最初に置かれるプレフィックス
chapter 第%d章 章見出しのプレフィックス
chapter_postfix " " 章見出しのプレフィックスと見出しとの間にはさむ文字列"
numberless_image "図:" 自動採番をつけない「indepimage」マーキングを使った時の、図キャプションプレフィックス
format_number "%s.%d" 番号参照のフォーマット
format_number_header "%s.%d:" キャプションプレフィックスのフォーマット
format_number_without_chapter "%d" --level=0で章番号の自動採番をしなかった時、番号参照で使われるフォーマット
format_number_header_without_chapter "%d:" --level=0で章番号の自動採番をしなかった時、キャプションプレフィックスのフォーマット
caption_prefix " " キャプションプレフィックスとキャプションの間にはさむ文字列
caption_prefix_idgxml " " キャプションプレフィックスとキャプションの間にはさむ文字列(idgxmlを選んだ時)
ruby_prefix "(" rubyタグに非対応のデバイスでルビを開くとき、ルビ開始文字を表す文字列(rpタグに入る文字列)
ruby_postfix ")" rubyタグに非対応のデバイスでルビを開くとき、ルビ終了文字を表す文字列(rpタグに入る文字列)

見出しやキャプションのプレフィックスを抑制する

 技術書以外では見出しやキャプションのプレフィックスが不要な場合も多くあります。上の表を参考に、見出しやキャプションのプレフィックスをすべて生成しないようにしてみましょう。「locale.yaml」をこのように変更してみます。

locale: ja
image: ""
table: ""
list: ""
chapter: ""
chapter_postfix: ""
numberless_image: ""
format_number: ""
format_number_header: ""
format_number_without_chapter: ""
format_number_header_without_chapter: ""
caption_prefix: ""
caption_prefix_idgxml: ""

ruby_prefixとruby_postfix以外をすべて空文字列にしてみました。この時、生成したHTMLはこうなります。
f:id:seuzo:20120308001326p:plain
 自動採番をすべて空文字列にしているので、本文中の番号参照も空になるのを注意してください。
 ここで節見出しに「1.1 」という自動採番が残ってしまっているのにお気づきでしょうか。この部分を制御するには、review-compileコマンドに見出しレベルを追加するオプション「--level」が必要です。「--level=3」とすれば項見出しまでの自動採番を追加し、「--level=2」であれば節見出しまで、「--level=1」ならば章見出しのみ、「--level=0」では見出しの自動採番は追加されなくなります。つまり、この場合は「--level=1」以下を指定すればよいことになります。

$ review-compile --target html --level=0 --stylesheet=main.css ch01.re > ch01.html

f:id:seuzo:20120308003042p:plain

見出しの自動採番は追加しないが、図の参照番号やキャプションのプレフィックスは必要な場合

 先ほどのようにすべてを削除するのではなくて、図の参照番号やキャプションのプレフィックスは使いたいという場合もあります。この場合ですと、「--level=0」だけで目的は果たせそうです。「locale.yaml」ファイルを削除(またはリネーム)してください。生成したHTMLはこのようになるはずです。
f:id:seuzo:20120308005053p:plain

*1:xmlにしてInDesign流しても同じです

段分割にこんな使い方があったなんて!

InDesign CS5の段分割というと、こんな感じの箇条書きのデモばかり紹介されています。

もうちょっと段分割を使うと、こんなことできるんだよね、という例を紹介しましょう。まずはこれ、画像とキャプションをひとつのストーリーの中で回り込みのように配置できます。


こちらも画像とキャプションですが、それぞれを2段で並べてます。

ただし、ビデオの後半を見るとわかるように、段分割される最終行に「段落分離禁止オプション」が設定されていると、正しく段分割できません。まあ、段分割しようって時は「段落分離禁止オプション」をオフにしておいてください。←たいてい気づかずに「あれ? なんでできないんだろう?」と悩んだりするんですが^^

参照

段分割といえば...

いき♂さんがレポートされているこのバグ:段分割の最終行の改行を削除すると分割が解除され、さらにゴミみたいな設定が残りつづけるバグは、CS5.5でも修正されていません。さて、CS6では修正されるのでしょうか

選択した画像イメージを任意の大きさ(%)に拡大縮小して、フレームを内容に合わせる

/*
    選択した画像イメージを任意の大きさ(%)に拡大縮小して、フレームを内容に合わせる
    
    2012-03-01  とりあえず
*/


////////////////////////////////////////////設定
#target "InDesign"
var my_scale = 85;//縮小拡大率(%)

////////////////////////////////////////////エラー処理 
function myerror(mess) { 
  if (arguments.length > 0) { alert(mess); }
  exit();
}


////////////////////////////////////////////以下メイン実行
////////////////まずは選択しているもののチェック
if (app.documents.length === 0) {myerror("ドキュメントが開かれていません")}
var my_doc = app.documents[0];
if (my_doc.selection.length === 0) {myerror("画像を選択してください")}
var my_selection = my_doc.selection;

for( var i = 0; i < my_selection.length; i++) {
    var tmp_obj = my_selection[i];
    var my_class =tmp_obj.reflect.name;
    if (my_class === "Image" ) {
        tmp_obj.horizontalScale = my_scale;
        tmp_obj.verticalScale = my_scale;
        tmp_obj.parent.fit(FitOptions.FRAME_TO_CONTENT );
    } else if ("Rectangle, Oval, Polygon".match(my_class)) {
        if (tmp_obj.images.length === 1) {
            tmp_obj.images[0].horizontalScale = my_scale;
            tmp_obj.images[0].verticalScale = my_scale;
            tmp_obj.fit(FitOptions.FRAME_TO_CONTENT );
        }
    }
}

InDesignの正規表現で^行頭をクリップボードの内容と置き換えると文字が消える

 InDesignでは以前から、行頭位置「^」が置換文字列と置き換わらないバグがありました。
 置換文字列に通常のテキストではなくて「クリップボードの内容」を指定すると、行頭の1文字目が消失します。

 こちらも以前のバージョンから修正されていませんね。見出しなどに対してインラインを挿入する時によく使うテクニックなのに残念です。
 回避方法としては:

検索:^(.)
置換:~c$1

などとすればいいんですが、気持ち悪すぎます。「すべてを置換」もできたりできなかったりだし。
 InDesignのバグってもう直らない運命にあるのでしょうか...