Re:VIEW ナレッジベース

Re:VIEW 開発者の立場から、Re:VIEW のカスタマイズおよび「よくある質問と回答」をまとめています。

Re:VIEW のセットアップおよび基本的な使い方については、Re:VIEW 公式の 各ドキュメント をまず参照してください (特に Re:VIEWクイックスタートガイドRe:VIEWフォーマットガイド)。

Re:VIEWを取り巻く環境

このナレッジベースへのご意見・ご要望については、 https://github.com/reviewml/reviewknowledge-ja の issue 投稿、または Twitter @kmuto までお寄せください。

リリースに関する情報

2023/6/29 by @kmuto

Re:VIEW 5.8 での変更点

Re:VIEW 5.8 において 5.7 から変更した点について解説します。


2023年6月29日に、Re:VIEW 5 系のマイナーバージョンアップ「Re:VIEW 5.8.0」をリリースしました。

今回も修正メインの小幅なリリース……ではあるのですが、このトレンドに乗るしかない、というMermaid対応を別のライブラリと組み合わせて実現したのがトピックです。


既知の問題

現時点ではありません。


インストール

新規インストールの場合

$ gem install review

更新の場合

$ gem update review

既存プロジェクトのバージョンアップ追従

既存のプロジェクトを 5.8 に更新するには、Re:VIEW 5.8 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 5.8.0 に更新します **
config.yml: 'review_version' を '5.0' に更新しますか? [y]/n 
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.7.0/gems/review-5.8.0/templates/latex/review-jsbook/review-base.sty) で置き換えら
れます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.7.0/gems/review-5.8.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、変更点について理由を挙げながら解説します。

新機能

//graph 命令でMermaid記法によるグラフ記述ができるようになりました

Webブラウザ上で動作するJavaScriptベースの図形描画ツール「Mermaid」に対応しました。EPUBやLaTeXではJavaScriptが動かないので、外部ライブラリからWebブラウザを内部で呼び出して画像化するという力技です。

このためにplaywright-runnerというgemを自作しました。

現時点ではLinux以外の動作は確認していません。

doc/format.ja.mdにもありますが、ここでその手順を示します。

  1. プロジェクトに次のように package.json を作成します(既存のファイルがあるときには、dependencies"playwright"〜 の行を追加します)。

    {
      "name": "book",
      "dependencies": {
        "playwright": "^1.32.2"
      }
    }
    
  2. Playwrightライブラリをインストールします。npm がない場合は、Node.js の環境をセットアップしてください。

    npm install
    
  3. PlaywrightライブラリをRubyから呼び出すモジュールである playwright-runner をインストールします。

    gem install playwright-runner
    
  4. (オプション) EPUBにはSVG形式を作成する必要がありますが、SVGに変換するには、poppler に含まれる pdftocairo コマンドが必要です。Debianおよびその派生物では以下のようにしてインストールできます。

    apt install poppler-utils
    
  5. (オプション) デフォルトでは図の周囲に大きめの余白ができてしまいます。これを詰めるには、TeXLiveに含まれる pdfcrop コマンドが必要です。Debianおよびその派生物では以下のようにしてインストールできます。

    apt install texlive-extra-utils
    

プロジェクトの config.yml を適宜調整します。デフォルト値は以下のとおりです。

playwright_options:
  playwright_path: "./node_modules/.bin/playwright"
  selfcrop: true
  pdfcrop_path: "pdfcrop"
  pdftocairo_path: "pdftocairo"
  • playwright_path: playwrightコマンドのパスを相対パスまたは絶対パスで指定する

  • selfcrop: playwright-runner の画像切り出しを使う。pdfcrop が不要になるが、周囲に余白が生じる。pdfcrop を使うときには false に設定する

  • pdfcrop_path: pdfcrop コマンドのパス。selfcroptrue のときには無視される

  • pdftocairo_path: pdftocairo コマンドのパス

Re:VIEW側の記法としては //graph[ID][mermaid][キャプション] または //graph[ID][mermaid] となりますが、このIDに基づき、images/html/ID.svg(EPUBの場合)や images/latex/ID.pdf(LaTeX PDFの場合)が生成されます。

_images/mermaid.pngMermaid記述からの生成例

完了待ちのロジックに謎なところが多く、たまに真っ白な画像ファイルができてしまうことがありますが、Mermaidで図を描きたいという方はぜひお試しいただいて感想をください。

バグ修正

EPUBMaker: 自動生成される部の内容に<title>が入らないのを修正しました

catalog.ymlで部をreファイルではなく見出し文字列で指定した場合、EPUBMakerが自動で部のためのHTMLファイルを作成します。このときに<title>情報が空になっていたのを修正し、部の見出し文字列が入るようにしました。

機能強化

PDFMaker: @<href>命令で長いURLを記述したときに、ページをはみ出さずに折り返すようにしました

長いURLを入れたときに従来はページからはみ出すことがありましたが、提供のスタイルを調整し、単語単位ではなくページ幅で折り返すようになりました。

こちらはmunepiさんに修正をいただきました、いつもありがとうございます!

終わりに

Re:VIEWを業務に組み込む目論見はまだできていないのですが、開発駆動力のアップはしたいですね。開発会議が必要〜〜。

Enjoy!

2023/2/28 by @kmuto

Re:VIEW 5.7 での変更点

Re:VIEW 5.7 において 5.6 から変更した点について解説します。


2023年2月28日に、2023年最初となるRe:VIEW 5 系のマイナーバージョンアップ「Re:VIEW 5.7.0」をリリースしました。中身をガッツリ変える気合いが足りなくてメジャー5系が長いですね。

今回のバージョン 5.7 は、不具合の修正を行いました。


既知の問題

現時点ではありません。


インストール

新規インストールの場合

$ gem install review

更新の場合

$ gem update review

既存プロジェクトのバージョンアップ追従

既存のプロジェクトを 5.7 に更新するには、Re:VIEW 5.7 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 5.7.0 に更新します **
config.yml: 'review_version' を '5.0' に更新しますか? [y]/n 
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.7.0/gems/review-5.7.0/templates/latex/review-jsbook/review-base.sty) で置き換えら
れます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.7.0/gems/review-5.7.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、変更点について理由を挙げながら解説します。

バグ修正

Windows において、review-init -w の実行時にバインドアドレスを省略したときにエラーが発生するのを修正しました

がんばったわりに知名度の低い機能なのですが、Re:VIEWバージョン4からは、review-init -w プロジェクト名とすると、Webブラウザ上でTeX版面レイアウトをして設定に盛り込むことができます。

ただ、Windowsネイティブ環境のRubyでは、Linux/Unixと違って全部のインターフェイスにバインドするつもりでバインドアドレスに「0」を指定すると動かないという問題がありました。ウィザードモード自体はIPv4範囲内でよかろうと判断して、「0.0.0.0」をデフォルト値に変更しました。バインドアドレスとポートは--bind--portで変更できます。

PDFMaker: //blankline でページをまたいだときに、ページの先頭に空行が入るのを抑制しました

空行を強制的に入れる//blankline命令ですが、TeX PDFの紙面でページをまたいだときのページ先頭に空行が入る、というのはほとんどの場合は期待しない挙動です。ページ先頭時のように、入れるべきではないところに置かれた場合は空行配置を無視するように変更しました。

EPUBMaker: MathJax で数式を表現する際に、<, >, & を変換し、HTML のエラーが出ないようにしました

MathJaxはHTML上にTeXの数式を記述するとレンダリングしてくれる便利なライブラリです。Re:VIEWではimgmath: mathjaxとするとこのモードが有効になります。

TeX数式でたまに登場する<, >, &を使うと妙な挙動になっていたのですが、これらはHTML上で表現する際に実体参照(&lt;, &gt;, &amp;)に変換すべきものでした。

なお、MathJaxはJavaScriptプログラムのため、EPUBでは利用できません。残念ですね。

非互換の変更

動作検証済みバージョンを Ruby 2.7 以降としました

Re:VIEW自体は問題なかったのですが、コードテストのほうの互換性保持が困難になったため、Ruby 2.5・Ruby 2.6についてはテスト対象から除き、今後このバージョンで動かなくなっても諦めることにしました。

2.7以降の固有の機能については、RuboCop先生の提言に従って入りかけはしたのですが、入れてもコード品質の満足だけでユーザーへの価値創造にはつながらないと判断して見送っています。

とはいえ、メジャーバージョンが変わるタイミングでは2.7以降となる可能性があります(Debian stableのRubyがまだ2.7のため、このバージョンでの動作は当面保証されます)。

EPUMaker: EPUB の検証ルールに従い、EPUB の目次に表紙へのリンクを含めました

1月にリリースされたEPUBcheck v5.0.0でRe:VIEWから生成されるEPUBをチェックしてみると、表紙ファイルへのリンク不在でエラー指摘されるようになりました。

容易・無難な対策として、目次から表紙へのリンクを張り、EPUBチェックが通るようにしました。

その他

Ruby 3.2 を動作検証テスト対象に含めました

Ruby 2.5、2.6をテスト対象から捨てた代わりに、3.2が新たに仲間となりました。

RuboCop 1.45.1 の指摘を反映しました

RuboCop先生にまたビシビシと指摘をいただきました。

終わりに

今回の Re:VIEW 5.7 もやや小幅な修正に留まりました。前回の5.6の最後で「公私で手一杯」と触れましたんですが、転職活動から転職・新しい職への必死順応で、Re:VIEWについては最低限のことしかできなかったなぁ…という感慨です。

Enjoy!

2022/10/29 by @kmuto

Re:VIEW 5.6 での変更点

Re:VIEW 5.6 において 5.5 から変更した点について解説します。


2022年10月29日に、Re:VIEW 5 系のマイナーバージョンアップである「Re:VIEW 5.6.0」をリリースしました。

今回のバージョン 5.6 は、不具合の修正と、いくつかの機能向上、ドキュメントの更新を行いました。


既知の問題

現時点ではありません。


インストール

新規インストールの場合

$ gem install review

更新の場合

$ gem update review

既存プロジェクトのバージョンアップ追従

既存のプロジェクトを 5.6 に更新するには、Re:VIEW 5.6 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 5.6.0 に更新します **
config.yml: 'review_version' を '5.0' に更新しますか? [y]/n 
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.7.0/gems/review-5.6.0/templates/latex/review-jsbook/review-base.sty) で置き換えら
れます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.7.0/gems/review-5.6.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、新規に導入した機能や変更点について理由を挙げながら解説します。

新機能

IDGXMLBuilder: //texequation@<m>imgmath math_formatに対応しました

ほかのビルダでは数式の画像変換に対応していたのですが、InDesign 用の IDGXMLBuilder だけまだ対応しませんでした。今回で対応しています。最近の InDesign では SVG にも対応していますので、PDF か SVG で書き出すのがよいでしょう。

LATEXBuilder: @<icon>用のマクロとしてreviewiconマクロを追加し、 reviewincludegraphicsマクロの代わりに使うようにしました

これまで TeX 変換時にはインライン図版の @<icon> 命令を \reviewincludegraphics マクロに展開していたのですが、これだと使い分けや設定がしづらいという意見があり、\reviewicon マクロを導入してそれを使うようにしました。

ルビ文字列の前後のスペースを削除するようにしました

ルビ命令 @<ruby> で区切り文字「,」の前後のスペースをビルダによって削除したりしなかったりと揺れていたので、スペースは自動削除することで統一しました。

非互換の変更

LATEXBuilder: 囲み記事の見出しとして ■メモ の代わりに MEMO, NOTICE, CAUTION 等を使うようにしました

review-jsbook スタイルを使っているときに、//note//tip などの囲み類の見出しがすべて「メモ」となってしまっていたのをやめて、「NOTE」「TIP」「INFORMATION」「WARNING」「IMPORTANT」「CAUTION」「NOTICE」「MEMO」と表現するようにしました。

この見出しは locale.yml で変更できます。例を示します。

locale: ja
note_head: 注記
tip_head: 小技
info_head: 情報
warning_head: 警告
important_head: 重要
caution_head: 危険
notice_head: 注意
memo_head: メモ

なお、TeX 以外のビルダではこの見出しは使われません。

ドキュメント

ドキュメント format.mdformat.ja.md を更新しました

機能としては昔からあったのですがそういえばドキュメントのほうを更新していなかった、という命令について記載したり、少し整理を行いました。

  • 上付き @<sup>、下付き @<sub> を説明

  • 箇条書きネストについて少し追記、//olnum を説明

  • 中央揃え //centering と 右揃え //flushright を説明

  • //raw および @<raw> を非推奨化

本当は全体的に書き直したり、初期サンプルドキュメントも用意したいところではありますが。

終わりに

今回の Re:VIEW 5.6 もやや小幅な修正に留まりました。

前回同様にここ数ヶ月も公私で手一杯になっていて、あまり手がつけられませんでした。とはいえ、今回で少し便利になったり混乱を招きそうなところを手当てできたりはしたので良かったと思います。

Enjoy!

2022/6/29 by @kmuto

Re:VIEW 5.5 での変更点

Re:VIEW 5.5 において 5.4 から変更した点について解説します。


2022年6月29日に、Re:VIEW 5 系のマイナーバージョンアップである「Re:VIEW 5.5.0」をリリースしました。

今回のバージョン 5.5 は、不具合の修正と、節・項参照機能の強化を行いました。


既知の問題

現時点ではありません。


インストール

新規インストールの場合

$ gem install review

更新の場合

$ gem update review

既存プロジェクトのバージョンアップ追従

既存のプロジェクトを 5.5 に更新するには、Re:VIEW 5.5 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 5.5.0 に更新します **
config.yml: 'review_version' を '5.0' に更新しますか? [y]/n 
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.7.0/gems/review-5.5.0/templates/latex/review-jsbook/review-base.sty) で置き換えら
れます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.7.0/gems/review-5.5.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、新規に導入した機能や変更点について理由を挙げながら解説します。

新機能

節や項を参照するインライン命令として、 @<secref> , @<sec> , @<sectitle> を追加しました

節や項の参照にはこれまで @<hd> という命令を用意していましたが、これは「節や項の番号+タイトル」、たとえば「1.2 テスト」というように展開するものです。

章の場合は @<chapref> (章番号+タイトル、例:「1章 入門」)、@<chap> (章番号のみ、例:1章)、@<title> (タイトルのみ、例:入門) という3つのパターンがあるので、これと同じように節や項についても番号だけ、あるいはタイトルだけを展開する命令がほしいという要望を受けて実装しました。

  • @<secref>:これまでの @<hd> と同じく、節や項の番号+タイトル。例:「1.2 テスト」

  • @<sec>:節や項の番号のみ。例:1.2。なお、番号を付けないレベルの項の場合はエラーになります。

  • @<sectitle>:タイトルのみ。例:テスト

ハイパーリンクも有効です。

バグ修正

テストエラーを修正しました

ユーザーには関係がありませんが、自動テストで環境によってはひっかかるところに手当てをしました。

review-update コマンドがエラーになるのを修正しました

作業フォルダを更新する review-update コマンドが、date ライブラリの取り込みができていなくてエラーになっていたようです。しかしこれまで報告がなかったということは、review-update はほぼ使われていない……?(5系は安定していてあまり review-update で更新が必須のものもないですし、3→4→5のようなメジャー更新でない限りは使う必要がないかもしれませんが)

その他

rexml がバンドル gem 扱いになったので、gemspec に追加しました

XML まわりの処理をしている rexml ライブラリですが、変わらず Ruby 標準扱いではあるものの、バンドル gem という扱いになったそうなので、gemspec に入れておくようにしました。

終わりに

今回の Re:VIEW 5.5 は小幅な修正に留まりました。

改善や機能強化したいことはいろいろあるのですが、本業が忙しくて今回はまったく手がつけられませんでしたね……。ブロック命令の文字列返し化をしたいなとかパーサも書き換えたいなとかモヤモヤしますが、そうなると全体を作り変えたほうが…というのと、review-ext.rb が全部ダメになるので悩むところではあります。うむむ。

Enjoy!

2022/2/28 by @kmuto

Re:VIEW 5.4 での変更点

Re:VIEW 5.4 において 5.3 から変更した点について解説します。


2022年2月28日に、Re:VIEW 5 系のマイナーバージョンアップである「Re:VIEW 5.4.0」をリリースしました。

今回のバージョン 5.4 は、5.3 で発見された不具合の修正と、テキスト化の際の利便性の向上、EPUB / CSS 組版向けのカスタマイズ割り込みの強化などを施しています。


既知の問題

現時点ではありません。


インストール

新規インストールの場合

$ gem install review

更新の場合

$ gem update review

既存プロジェクトのバージョンアップ追従

既存のプロジェクトを 5.4 に更新するには、Re:VIEW 5.4 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 5.4.0 に更新します **
config.yml: 'review_version' を '5.0' に更新しますか? [y]/n 
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.7.0/gems/review-5.4.0/templates/latex/review-jsbook/review-base.sty) で置き換えら
れます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.7.0/gems/review-5.4.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、新規に導入した機能や変更点について理由を挙げながら解説します。

新機能

Re:VIEW に関する質問の受け付けに対応する GitHub Discussions を開始しました

Re:VIEW の実装に何か変化があったわけではないのですが、GitHub Discussions という場を設けました。

内容的に issue にするにはためらいがあるというときに、質問の場として使っていただければと思います。

生産的な場にしたいので、ご投稿の前には Re:VIEW Discussions 日本語でのご案内 をご覧になるようお願いします。

非互換の変更

EPUBMaker: opf ファイルの manifest 内の item を ID 文字列の辞書順でソートするようにしました

opf ファイルは EPUB のコンテンツ情報を管理するファイルですが、この中に manifest/item という項目があり、ここに EPUB ファイル内で保有しているファイル一覧が列挙されています。これまでの EPUBMaker では素朴にファイルシステムから Ruby のファイル取得 API で得られたファイル一覧を使っていたのですが、数式画像をリビルドしたり、ファイルシステム環境がそもそも違ったりすると、この順序が変わることがあります(ファイル取得 API のほうでは順序を保証していない)。

epdiff ツールなどでEPUB の差分を確認したいときにこの opf ファイルの不要な差分にわずらわされるのを避けるため、辞書順(a〜z順)にソートするようにしてから opf ファイルに書き出すようにしました。

これまでのバージョンとは非互換ではあるのですが、内容的にこれが何か副作用を起こす可能性はないでしょう。

TextMaker: 表の見出しセル行を太字表現(★〜☆)にするのではなく、見出しセル行と通常セル行の区切り線を入れるようにしました

rake textreview-textmaker で作るテキストファイルにおいて、これまでは表の見出しセルを太字表現にしていました。ただ実際の利用シーンではむしろ、見出しセル自体には装飾を付けず、通常セルとの間に区切り線を入れることのほうが大半……というか100%です。

そこで、今回のバージョンで、デフォルトを見出し装飾なし・区切り線ありに変更しました。従来の太字表現に戻すには textmaker セクションの th_bold パラメータを true に設定してください。

reファイル

//table{
A	B
---------------
C	D
//}

従来のテキスト変換後(および textmaker/th_bold:true 時)

◆→開始:表←◆
★A☆	★B☆
C	D
◆→終了:表←◆

Re:VIEW 5.4.0以降のテキスト変換後

◆→開始:表←◆
A	B
------------
C	D
◆→終了:表←◆
TextMaker: //indepimage 命令の出力結果を //image に合わせました

これまでテキスト化の際には //indepimage はファイルが見つからなくても { //} の中身があろうとなかろうと無視していました。制作の用途で使うときには、図版は後から作成したり、図版予定位置に「この画像を使ってこう加工しておいて」という指示を入れておくことがよくあります。//image ではそのために { //} の中身を指示情報扱いとして書き出していたので、//indepimage もこれに合わせました。

reファイル(図版ファイルはどちらも存在しない)

//image[図1][キャプション]{
fig1.pngの左上を切り出してください。
//}

//indepimage[概念図]{
PowerPointファイル1枚目から作図願います。
1.は①としてください。
//}

従来(indepimageの内容コメントが無視される)

◆→開始:図←◆
fig1.pngの左上を切り出してください。

図1.1 キャプション
◆→終了:図←◆

◆→画像 概念図←◆

Re:VIEW 5.4.0以降

◆→開始:図←◆
fig1.pngの左上を切り出してください。

図1.1 キャプション
◆→終了:図←◆

◆→開始:図←◆
PowerPointファイル1枚目から作図願います。
1.は①としてください。
◆→終了:図←◆
TextMaker: //imgtable 命令の出力結果を //image および //table に合わせました

図版ファイルを表代わりに配置する //imgtable ですが、これもテキスト化では内容が従来無視されていました。//indepimage 同様に表示するようにします。

reファイル

//imgtable[figtable1][キャプション]{
table.xlsx 2つめのシートから作図願います。
アミ色はK10%にしてください。
//}

従来(キャプションしか入らない)

表1.1 キャプション

Re:VIEW 5.4.0以降

◆→開始:表←◆
表1.1 キャプション

table.xlsx 2つめのシートから作図願います。
アミ色はK10%にしてください。
◆→終了:表←◆
ハイライト有効時に、//source 命令もハイライト対象として中身をエスケープしないようにしました

ハイライト(highlight)有効時、PDFMaker および EPUBMaker において //list//emlist//cmd//listnum//emlistnum はハイライト対象となっていましたが、同じプログラムコード提示用命令である //source についてはハイライト対象から漏れていましたので、これを追加しました。

ハイライトをもともと使っていない、あるいはハイライトを使っているが //source を使っていない、のであれば特に影響はありません。ハイライト対象から外れていることを期待して //source を使っていたケースでは、後述の review-ext.rb での差し戻し指示が必要です。

ハイライト対象になるとどうなるかというと、reファイル→コンパイラ→ビルダ(LATEXBuilder / HTMLBuilder)と渡るときに、コンパイラでは本来行っている文字のエスケープやインライン命令の処理などを何も行わず、ビルダに引き渡します。ビルダは渡ってきたものを外部のハイライトプログラム(istings.sty、pygments、rouge など)に処理を委ねます。

エスケープやインライン命令の処理をしたものをハイライトプログラムに渡してしまうと、たとえば < だったところが PDFMaker なら \textless{}、EPUB なら &lt; のようにエスケープされた文字がそのまま出てしまうことになります。

逆に言うと、既存の挙動では、プログラムコード内でインライン命令(太字など)を使いたいときにはハイライトを使えない、ということです。

//list//emlist ではハイライトを使いたい(インライン命令は使わない)が、//cmd//source ではインライン命令を使いたい(ハイライトは使わない)という場合は、以下のように review-ext.rb を使ってハイライト対象を制限することで対処できます。

module ReVIEW
  module CompilerOverride
    def non_escaped_commands
      if @builder.highlight?
        %i[list emlist listnum emlistnum] # cmdとsourceを除く
      else
        []
      end
    end
  end

  class Compiler
    prepend CompilerOverride
  end
end

バグ修正

Ruby 3.1 で YAML のエラーが発生するのを修正し、互換性も持たせました

お待たせいたしました。いくつか報告をいただいていたとおり、以前のバージョンの Re:VIEW を Ruby 3.1 で使おうとすると、Date に関する YAML エラーという現象が発生していました。

メジャーアップデートならともかくマイナーアップデートでライブラリに非互換の挙動を入れるのはいかがなものかという気持ちはありますが、Ruby 3.1 以降でも動作するように修正を行いました。

Ruby の古いバージョンを切り捨てる、gem を使う、という方法も提案されていたのですが、小さめのコードで新旧バージョン両方への対応ができたのでほっとしています。

とはいえ、今後も Ruby 側のライブラリの変更で互換性保持が困難となる可能性はありますし、いつまでも Ruby バージョンの古いものに引きずられるのも開発の阻害となります。今回はまだ Ruby 2.5 をサポートしますが、Re:VIEW の次のメジャーバージョンアップでは Ruby 2.7 以上をサポート対象にすることにして、Ruby 2.5 向けの具体的な対応はしなくなる予定です。

rbenv/gem/bundler を常用する方には Ruby も関連物もどんどん上げていけばいいのでは?という意見もあるのでしょうけれども、私自身は Debian GNU/Linux ディストリビューションの配布物信頼性・安定性のほうに重きを置いているので、せめて Debian stable および oldstable でサポートされている期間はその収録 Ruby バージョンについて Re:VIEW でも対応する対象にしたいと考えています。(Node.js などを見てると Long-Time-Support な OS ディストリビューション公式とは相性が悪くなる風潮が強いなぁという印象ですが。)

EPUBMaker: epub:type=cover が大扉や奥付に入るのを修正しました

epubcheck でもひっかからないしリーダーにも影響しないという些末なことではあるのですが、EPUB の表紙ファイルには epub:type=cover という属性を入れることが推奨されています。これが処理の関係で大扉や奥付にも入ってしまっていましたので、削除しました。

無効な urnid の例がサンプルとして示されているのを削除しました

config.yml のコメントアウトした設定で urnid パラメータに対し

# urnid: urn:uuid:http://example.com/book-title/

としていましたが、これを実際に使おうとすると epubcheck でエラーになります。urnid の内容はランダムな UUID が入るのでそもそも有効にする意味はないのですが、どうしても同じ UUID で作り直したいというときのサンプルとして上記は不適切なので、以下のように例示を置き換えました。

# urnid: urn:uuid:ffffffff-ffff-ffff-ffff-ffffffffffff

当然ながら実際に固定の UUID で使いたいというときには、別の妥当な値に変更する必要があります。Re:VIEW での UUID の生成は以下と同じです。

$ ruby -e 'require "securerandom"; puts SecureRandom.uuid'
2b0987ec-a155-4d70-998e-6507b87e49a9
config.yml の YAML 構文にエラーがあったときに例外ではなく妥当なエラーを返すようにしました

config.yml の YAML ファイルはだいぶ大きいため、インデントを誤ったり : を付けたセクションを有効にしたけれども下位をコメントアウトのままにしてしまったりといったケースがあります。このときに例外が発生して捕捉し損ねていたため、バックトレース付きのエラーになってしまっていました。

この例外を捕捉し、正しく(?)エラーを返すようにしました。

ただ、Ruby の YAML 処理を行う Psych ライブラリ、および YAML の性質上、YAML の構文エラーについてはかなりざっくりした列・行の提示だけで、解決のヒントにあまり寄与してくれない傾向です。変更容易性と評価容易性を合わせ持たせるのはどうしたらよいですかねぇ……(JSON 管理で GUI/Web 設定とすればエラーは減らせると思うのですが、ちょっとした変更のたびに Web ブラウザというのもという気分もあり)。

IDGXMLMaker: secttags を有効にしている状態で前付や後付がエラーになるのを修正しました

IDGXML を使っていてかつ secttags(見出しレベル登場に応じて、chapter, sect, sect2, …と構造要素で囲む)を有効にしているという非常にレアな状況ではあるのですが、このときに前付や後付のように章番号が存在しない箇所でエラーが発生していました。エラーにせず chapter 構造で囲むように修正しています。

なお、多くは語りませんが、中間処理では構造要素を使うにしても、InDesign にインポートする前には構造タグ類は除去することをお勧めします。

ドキュメント

GitHub Discussions について README.md に記載しました

冒頭で言及した GitHub Discussions について記載しました。

その他

RuboCop 1.25.1 の指摘を反映しました

恒例の Rubocop 先生対応です。

終わりに

今回の Re:VIEW 5.4 では、大きな新機能は入れませんでした。新規・既存のユーザーにとっては、Ruby 3.1 以上への対応が一番大きなところでしょうか。

テキスト化周りの機能強化については、業務用で review-ext.rb をやりくりしていたのをようやくこのたびマージできたので、私自身にとってはかなりのメリットがあります。

CSS 組版向けの機能は今回でいろいろ入れたのですが、具体的にこれらの機能を活用しての Vivliostyle.js や AntennaHouse Formatter、VersaType Converter といった CSS 組版ソフトウェア向けの具体的な参照実装をお見せしていないので、わかりにくいところかもしれません。業務では AntennaHouse Formatter、VersaType Converter の実装を保有しているものの、業務利用デザイン合わせなので参照実装として出すわけにもいかず、ページデザインレイアウトから考えないといけないのが頭の痛いところです。このあたりは紙面デザイナー / CSS デザイナーの方の参戦を期待したいですね。

Enjoy!

2021/10/29 by @kmuto

Re:VIEW 5.3 での変更点

Re:VIEW 5.3 において 5.2 から変更した点について解説します。


2021年10月29日に、Re:VIEW 5 系のマイナーバージョンアップである「Re:VIEW 5.3.0」をリリースしました。

今回のバージョン 5.3 は、5.2 で発見された不具合の修正と、縦書き周りの強化などを施しています。


既知の問題

現時点ではありません。


インストール

新規インストールの場合

$ gem install review

更新の場合

$ gem update review

既存プロジェクトのバージョンアップ追従

既存のプロジェクトを 5.3 に更新するには、Re:VIEW 5.3 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 5.3.0 に更新します **
config.yml: 'review_version' を '5.0' に更新しますか? [y]/n 
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-5.3.0/templates/latex/review-jsbook/review-base.sty) で置き換えら
れます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-5.3.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、新規に導入した機能や変更点について理由を挙げながら解説します。

新機能

後注のサポートを追加しました

脚注に類似したものとして、後注(文末注)の機能を追加しました。

//endnote 命令で後注内容を記述し、@<endnote> 命令で後注を参照します。実際に後注一覧を配置する箇所には、//printendnotes 命令を使います。

 …
ビルダはRe:VIEW形式の原稿ファイルを「HTML」や「LaTeX」などに変換する変換器のことです@<endnote>{builder}。

//endnote[builder][HTML, LaTeX, TOP, IDGXMLを主要なビルダとしています。]

==== 注
//printendnotes

//printendnotes は同一 re ファイル内に記述する必要があります。つまり、章単位で後注を出力することはできますが、書籍全体で最後に1つの後注を出力する、ということはできません。

また、後注は一覧を出力するのみで見出しは付けないので、上記の例のように必要に応じて見出し、あるいは //blankline などで空行を入れる、といった表現をとることになります。

バグ修正

新しい jlreq において ifthen パッケージに非依存になったことによるエラーを修正しました

review-jlreq.cls の基底クラスとしている jlreq.cls は実装がどんどん変わるので、わりと追従が大変です…。jlreq.cls で ifthen パッケージを読み込んでいる前提にしていたのが読み込まなくなったので、review-jlreq.cls で自前で読み込むようにしました。

review-jsbook と新しい TeXLive 2020 以降の組み合わせにおいて、隠しノンブルがすべて1になってしまう問題を修正しました

かなりの人が「古い(古臭い?)変わらないもの」だと思っている TeX カーネルですが、これも実はわりとどんどん変わっています。日本語 TeX や日本語クラスファイルではそれを必死に追従してくれているわずかなボランティアが支えている、というわりと危機的な状況だったりしますね。

で、最近の TeX カーネルでフック周りが変更されて review-jsbook が隠しノンブル打ちの前提にしていた everypage パッケージが動作しなくなりました。ひとまず everypage-1x という後方互換パッケージが提供されているので、このパッケージが入っていればそれを使うようにしました。

TeX カーネルのさらなる変更であまり未来はない対処の可能性があり、review-jsbook をいつか諦めて review-jlreq 1本にしていったほうがいい、という判断になるかもしれません(とはいえ review-jlreq も jlreq の変化についていくのが厳しいところがありますが…)。

coverimage パラメータに実際に存在しないファイルを指定したときに例外エラーが発生するのを修正しました
titlefile・creditfile・profile パラメータに存在しないファイルを指定したときに警告を表示するようにしました

どちらもファイル指定をミスしたときに、妥当なメッセージではなくバックトレース例外を出してしまっていました。トレースの最初のほうを見ればファイル指定が間違ったんだな、とわかりはするのですが、捕捉できることなのにバックトレースを出すのは気持ちが悪いので、そのあたりのケアを入れました。

なお、coverimage は存在しなかった場合にエラーにしますが、titlefile・creditfile・profile について警告までとしているのは、昔の名残りで PDFMaker 利用時には拡張子を .tex に書き換えて探してみる、というロジックを入れていたために、見つからないときのエラーが妙なことになってしまうのでした。今は固有に分けたいなら pdfmaker セクションの下に記述する、別ファイルにして inherit を使うといった手法もあるので、ちょっと負債化しています。

review-jlreq で @<tcy> 命令がエラーになるのを修正しました。縦中横の TeX 表現側での抽象名に \reviewtcy マクロを使うようにしました

jlreq には縦中横について固有の命令があったので、いったん抽象化を挟むことにしました。

review-vol および review-index の例外エラーを修正しました

無効な yaml ファイル名を指定したり、catalog.yml 内に無効なファイル名の指定があったときにバックトレース例外を出していたのを捕捉して妥当なエラーを出すようにしました。

数式ビルドエラーが出たときに __IMGMATH_BODY__.tex のコピーを忘れているのを修正しました

EPUBMaker において数式の画像化でエラーが出たときに __IMGMATH__.tex をエラー解析用に images/_review_math フォルダにコピーしていたのですが、この TeX ファイルから参照している実体 __IMGMATH_BODY__.tex をコピーしていなかったので、解析できない……というしょうもない状態になっていました。

//beginchild//endchild 命令でエラーが起きたときにエラー位置の表示がされていなかったのを修正しました

箇条書き内入れ子を表現するための //beginchild//endchild 命令で構造のエラー(ネスト化されていないなど)があったとき、エラーがあった、というのを報告してもどの箇所かという行番号を示していませんでした。

エラーが発覚した時点の re ファイル内行番号を出力するよう修正しました。

//graph 命令を使うとビルドエラーになるのを修正しました

ユーザーからのご報告ではじめて発覚したのですが、IndexBuilder 導入以来 //graph はちゃんと動いていなかった模様です。業務で画像の動的生成は数式以外ではまずしないので、私のほうでは気付きにくいのでした。

epubmaker.rb で未定義の変数を参照している箇所を修正しました

以前のリファクタリングの影響で漏れがありました。あまり到達しない箇所なので気付かなかった模様。

review-catalog-converter がエラーになるのを修正しました

Re:VIEW 2 より前に作った書籍案件の EPUB 付き増刷、という作業でカタログファイルの持ち方をさすがに変えたい…と思って実行したら気付きました。

機能強化

脚注 (//footnote)・後注(//endnote) を定義したけれども参照(@<fn>@<endnote>)していないときに警告するようにしました

脚注や後注については、定義をしても @<fn>@<endnote> で参照しないと出力から抜けることになるのですが、単純に編集者側の参照漏れでした!ということが何件か立て続けに発生したこともあり、未参照のものについて警告を出すようにしてみました。

紙面全体に画像を貼り込む \includefullpagegraphics マクロを縦書きにも対応するようにしました

tate オプションで縦書き表現可能な review-jlreq ですが、表紙配置にも使っている \includefullpagegprahics が縦配置の計算に対応していなかったので、@munepi さんに修正していただきました(いつもありがとうございます!)。

plantuml の jar ファイル探索先を作業フォルダのほか、/usr/share/plantuml/usr/share/java からも探すようにしました

UML 図を描く plantuml が Debian 11 bullseye でパッケージ化されていたので、作業フォルダになくても、システムにインストールされていたらそれを使うようにしてみました。Homebrew でもできないかなと思ったんですが、/usr/local/Cellar/バージョン になっていて同定できないので今回は諦め。plantuml コマンドを呼ぶようにしたほうがよいかもという気はしていますが、そうすると今度は Windows でにっちもさっちもとなりそうです。

ドキュメント

format.ja.md, format.md: SVG数式を作成するコマンドラインの間違いを修正しました

pdftocairo で SVG を作るときには -singlefile は必要ないし、-svg より -%t でタイプを取り込むようにしたほうがいいよね、ということで修正しました。pdftocairo、PNG と SVG でだいぶ挙動が違う感じです。

mac OS と Linux で共通に使えて品質の良い PDF→SVG 変換器がほしいですねぇ(mac だと sips、Linux だと pdftocairo が現状安定)。

その他

Windows 版 Ruby 2.7 のテストを追加しました

パッチをいただいたので Windows 版 Ruby 2.7 もビルドテスト対象になりました。

Rubocop 1.22.1 に対応しました

恒例の Rubocop 先生対応です。

終わりに

今回の Re:VIEW 5.3 では新機能はほぼなく、5.2 以前にあった縦書き周りの不具合や、理由がユーザーにはよくわからない予想外のエラーへの対処といった使い勝手の向上が中心となりました。

縦書きはほかにも要望をいくつか頂いていて issue にもあるんですが、EPUB はともかくとして TeX においてはニッチで非日本語圏開発者にとってなじみも動機もないので、tcolorbox の座標系が変なのとかはちょっとどうにもならない感じがあります。基本が縦になっている中に横方向のを置く、みたいなこともかなり手間がかかる印象で、1ページ全体になるものなら \includefullpagegraphics、それを超える複雑なものについては InDesign か、Vivliostyle.js や AHFormatter などによる CSS 組版、といった使い分けが必要になるかなと思っています。

コロナ禍の見通しはまだ手探りといった状況で、対面での開発ミーティングをしづらいため、がっつりした開発駆動をかけにくい状況にあります。来年には何かできるといいんですけどね。

Enjoy!

2021/6/29 by @kmuto

Re:VIEW 5.2 での変更点

Re:VIEW 5.2 において 5.1 から変更した点について解説します。


2021年6月29日に、Re:VIEW 5 系のマイナーバージョンアップである「Re:VIEW 5.2.0」をリリースしました。

今回のバージョン 5.2 は、5.1 で発見された不具合の修正と、新機能を数点導入しています。


既知の問題

現時点ではありません。


インストール

新規インストールの場合

$ gem install review

更新の場合

$ gem update review

既存プロジェクトのバージョンアップ追従

既存のプロジェクトを 5.2 に更新するには、Re:VIEW 5.2 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 5.2.0 に更新します **
config.yml: 'review_version' を '5.0' に更新しますか? [y]/n 
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-5.2.0/templates/latex/review-jsbook/review-base.sty) で置き換えら
れます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-5.2.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、新規に導入した機能や変更点について理由を挙げながら解説します。

新機能

EPUBMaker: CSS 組版向けに、見出しの存在に応じて <section> で階層化する機能を追加しました

5.1 で Vivliostyle CLI の呼び出し機能を追加しましたが、Vivliostyle の CSS スタイルテーマを適用しやすいよう、見出しに応じて <section> HTML タグ構造を付けるオプションを用意しました。config.yml で以下のように epubmaker セクションの use_sectiontrue に指定します。

…
epubmaker:
  use_section: true
 …

Vivliostyle の考える HTML 構造と Re:VIEW の書き出す HTML 構造は完全には一致しないので、必ずしもすべてのテーマが完全流用できるとは限らないのですが、移植しやすいようにはなったはずです。Re:VIEW CSS 組版でも活用してみてください。

バグ修正

PDFMaker: Ruby 2.6 以上でテンプレートの引数についての警告が出る問題を修正しました

Ruby 2.6 以上の ERB ライブラリで obsolete 化したメソッドがある影響で、警告が出ていました。

次の Re:VIEW 6 の頃にはすでに EOL となっている Ruby 2.5 についてのサポートを停止することも考えるべきか…ただ、今の Debian stable (Ruby 2.5 利用) が Debian oldstable になってそれもしばらくしてからでないとなかなか勇気が出ないところではあります。

EPUBMaker: Docker 環境においてファイルがコピーされず空になる問題を修正しました

Linux の Docker 環境固有で、FileUtils.cp でコピーする際、preserve: true を付けないと0バイトファイルになるというちょっとよくわからない現象があります。おまじない的なのが気に入りませんが、Re:VIEW 側ではあまりどうにもならなそうなので、ひとまず安全側に倒しました。

縦中横を正しく表示する CSS 設定を追加しました

デフォルトの CSS ファイルで、縦中横の定義が不十分でした。

PDFMaker: 新しい TeXLive との組み合わせで pxjahyper のオプション競合エラーが発生するのを修正しました

新しい TeXLive + pxjahyper + plautopatch の組み合わせにおいて、ドライバ (dvipdfmx など) 定義が競合してエラーになるという問題がありました。ドライバは初回 class 定義か自動で見るのが今どきということで、もう不要となる定義を削除しています。

PDFMaker: 画像が見つからないときにコンパイルエラーになるのを修正しました

画像が見つからないときに missing なんとか という文字列を書き出していたのですが、エスケープをしていなかったので、ファイル名にアンダースコアがあったりするとエラーになっていました。

擬似プログラムコード化もやめたので、見つからないときの見た目はちょっと変わります。

機能強化

警告とエラーを出力する際の処理を改善しました

内部コードの話ですが、error! (すぐに終了) および app_error (ApplicationError 例外を上げる) メソッドを導入しました。IDGXMLMaker などで今までは途中でエラーがあったのに Maker がエラー終了しないということがあったことも対策しています。

PDFMaker: ビルドのために画像ファイルをコピーする際、実コピーではなくシンボリックリンクを利用して処理を高速化するオプションを追加しました

十数程度の画像ファイルだと気にならないことですが、これが数GBオーダーで百を超えるファイルみたいな制作物が相手だと、ビルド時のファイルのコピー、ビルド後の削除という処理だけでかなりの時間を費してしまうという問題がありました。Unix 系 OS において実コピーの代わりにシンボリックリンクを使うことで、この時間を大幅に短縮できます。以下で有効化します。

 …
pdfmaker:
  use_symlink: true
  …
PDFMaker: review-jlreq で serial_pagination=true, openany を指定したときには前付の後の空ページが入らないようにしました

serial_pagination=true は前付大扉からのアラビア数字通し、openany は奇数偶数どちらのページからでも章などを開始できるようにする、という TeX クラスファイルのドキュメントオプションですが、前付が奇数で終わったときに openany を付けていても必ず白ページが入るという現象がありました。

これはもともとの jlreq、およびそれがさらに元にしている TeX の標準ドキュメントクラスの挙動です。前付のノンブル (ページ番号) はローマ数字を前提としていて、それが奇数で終わり、本章のノンブルアラビア数字1から始まるというときには、間に1つ白ページを入れないとページの左右とノンブルの意図する左右がずれてしまうからです。

しかし、serial_pagination が有効な場合は前付からずっとアラビア数字で通しているので、白ページを入れる意味はありません。ということで、2つのオプションが指定されたときには白ページを入れないようにしました。

なお、review-jlreq は TeXLive 2018 ではいくつかの問題 (隠しノンブルが壊れた状態になるなど) があるため、最低でも TeXLive 2019 との組み合わせ、できれば TeXLive 2020 や TeXLive 2021 で使うことを推奨します。

その他

GitHub Actions まわりを修正しました

PR トリガまわりなどを調整しました。

review-preproc: リファクタリングを行いました

ごちゃごちゃしていたコードをリファクタリングし、綺麗にしてもらいました。

入れ子の箇条書きの処理をリファクタリングしました

Builder で持たせていた処理を、Compiler 側に寄せました。既存の review-ext.rb は修正が必要になるかもしれません。

Rubocop 1.12 に対応しました

恒例の Rubocop 先生対応です。

各ビルダの builder_init_file メソッドで最初に super で基底 builder の builder_init_file を実行するようにしました

何か全ビルダで初期実行をさせたいときには、Builderbuilder_init_file を上書きするようにするとよいでしょう。

PDFMaker: FileUtils ライブラリを内部で使う際に、明示記法の FileUtils.foobar を使うようにしました

なぜか1箇所だけ include FileUtils で省略していたけど、関係性がわかりにくくなるだけなのと、review-ext.rb でエラーになりそうなので、普通に FileUtils.foobar 記法にしました。

終わりに

今回の Re:VIEW 5.2 では主に 5.1 からのリファクタリング、安定化を進めました。

次のバージョン予定としてはそろそろ Re:VIEW 6 もよさそうかなという感じもしますし、TeX や CSS のテーマなんかも募って入れてみるのもよいかなと考えたりはしています。

Enjoy!

2021/2/28 by @kmuto

Re:VIEW 5.1 での変更点

Re:VIEW 5.1 において 5.0 から変更した点について解説します。


2021年2月28日に、Re:VIEW 5 系のマイナーバージョンアップである「Re:VIEW 5.1.0」をリリースしました。

今回のバージョン 5.1 は、5.0 で発見された不具合の修正と、新機能を数点導入しています。


既知の問題

  • ほかに Re:VIEW gem をインストールしていない状態で review-preproc を実行したときにエラーになる問題が発見されました。Re:VIEW 5.1.1 をリリース済みです。(2021/3/4)


インストール

新規インストールの場合

$ gem install review

更新の場合

$ gem update review

既存プロジェクトのバージョンアップ追従

既存のプロジェクトを 5.1 に更新するには、Re:VIEW 5.1 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 5.1.0 に更新します **
config.yml: 'review_version' を '5.0' に更新しますか? [y]/n 
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-5.1.0/templates/latex/review-jsbook/review-base.sty) で置き換えら
れます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-5.1.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、新規に導入した機能や変更点について理由を挙げながら解説します。

新機能

CSS 組版ソフトウェア Vivliostyle CLI を呼び出す Rake ルールを追加しました

ブラウザを使った CSS 組版ソフトウェア Vivliostyle のコマンドライン UI である Vivliostyle CLI が公開されましたが、少し試してみたところわりと簡単にこれで Re:VIEW から PDF を作るルールを書けることがわかったので、Rakefile のデフォルトルールに追加してみました。

Vivliostyle CLI をインストールした環境 (npm install -g @vivliostyle/cli) で、rake vivliostyle:build または rake vivliostyle で PDF を作成、rake vivliostyle:preview でブラウザのプレビューが開きます。

仕組みとしては、rake epub で EPUB ファイルをまず作り、それから Vivliostyle CLI を呼び出して PDF 変換します。

rake 実行時に、以下の環境変数で Vivliostyle CLI の制御ができるようにしています。

  • REVIEW_VSCLI: vivliostyle のコマンドパス。パスの通ったところに vivliostyle-cli を展開していないときにはこれで絶対パスを指定するとよいでしょう(デフォルトは vivliostyle)。

  • REVIEW_VSCLI_USESANDBOX: サンドボックスを使うことを強制するオプション。REVIEW_VSCLI_USESANDBOX=true など何か値が入っていればサンドボックスを使うようになります。デフォルトは空、つまりサンドボックスを使わない (--no-sandbox) モードにしています。危ないのかもしれませんが、Re:VIEW を使っている時点でどっちにしろシェルを使えて何でもできるわけですし、Chrome をすでに動かしている状態で --no-sandbox なしだと意味がとてもわかりづらいエラーになるので、デフォルトでサンドボックスなしにしました。

  • REVIEW_VSCLI_PDF: 出力 PDF 名。デフォルトは TeX PDFと同じく、環境変数 REVIEW_BOOK の値または book に、.pdf を付けたファイル名です。

  • REVIEW_VSCLI_OPTIONS: Vivliostyle CLI に渡すほかのオプション。デフォルトは空です。-s で紙サイズを指定、press-ready npm モジュールをインストールしている環境では -p で印刷所入稿可能な PDF/X-1a にする、といったいろいろなオプションが Vivliostyle CLI で用意されています。詳細については Vivliostyle CLI のドキュメントを参照してください。

style.css の表紙画像の設定があまり適していないようで、サンプルファイルそのままだと表紙は一部だけの表示になってしまいますね。実際に利用するシーンでは、Vivliostyle テーマなどを流用して CSS ファイルを用意するのがよさそうです。

PDFMaker: config.ymlboxsetting パラメータを新設し、column・note・memo・tip・info・warning・important・caution・notice の囲み飾りを事前定義のものや独自に作成したものから選択およびカスタマイズできるようにしました

PDFMaker における各飾りの変更は LaTeX がわかっていればもともとさほど難しくはないことではあったのですが、今回カスタマイズのインターフェイスをもうちょっとまじめに取り組んでみました。

_images/tcbox-1.pngデフォルト提供の囲み飾り

pdfmaker セクションの下位セクションとして boxsetting を用意し、ここで各囲みを設定できます。

pdfmaker:
   …
  boxsetting:
    note:
      style: squarebox

boxsetting の下位で column・note・memo・tip・info・warning・important・caution・notice のそれぞれを設定できます。style は定義済みまたはカスタムで作成した囲み飾りの名前です。

  • squarebox: シンプルな矩形囲み。

  • squaresepcaptionbox: キャプション部分を分離した矩形囲み。

  • folderbox: キャプションがフォルダのような形状の囲み。

  • clipbox: キャプションがクリップ留めのような形状の囲み。

  • dottedbox: ドットで囲んだ囲み。

  • bothsidelinebox: 左右両端に線が付いた囲み(上下に線はなし)。

  • leftsidelinebox: 左に線が付いた囲み(上下・右に線はなし)。

  • outerarcbox: 四隅を黒く塗った囲み。

  • marker: 「!」マーク付きのページ風の囲み。

設定方法や装飾など、いろいろと悩むことがあったのですが、まぁ妥当かなというところに落ち着いたと思います。当初は ascolorbox をそのまま使えばよいかと考えていたのですが、タイトルなしにしたときに崩れたりエラーになる、パラメータがあまり一貫していない、そもそも上流でもう保守されていない模様といった問題があり、簡単に流用できそうなものだけ使わせていただく程度に留めました。

実装としては tcolorbox スタイルをそのまま利用しており、新設の sty/review-tcbox.sty で定義しています。このファイルを直接書き換えなくても、簡単な設定範囲であれば tcolorbox のオプション形式でデフォルトから上書きしたり新たに挙動を追加したりすることができます。options はキャプションなしの囲みに対するオプション、options_with_caption はキャプションありの囲みに対するオプション(指定しなかった場合は options と同じものが適用)です。

pdfmaker:
   …
  boxsetting:
    note:
      style: squarebox
      options: "colback=black!5!white"
      options_with_caption: "colbacktitle=black!25!white"

パラメータについては sty/review-tcbox.sty に少し説明を記載しているので、参照してみてください。

提供したものからのカスタマイズには LaTeX および tcolorbox の知識 (や制限・注意事項) が必要なことは変わりません。一番に重要なことは執筆ですから、カスタマイズにあまり深入りしないようにしましょう。知識が不足しているがどうしてもカスタマイズが必要、ということであれば詳しい人に有償か無償かはともかく依頼することをお勧めします。

もっと良いものを作れるぜ! という方はぜひ追加コードを PR ください。

挿入箇所を示す @<ins>、削除箇所を示す @<del> の2つのインライン命令を追加しました

実は HTML に合わせて昔から実装は存在したのですが、ドキュメントに明記していなかったのと、一部のビルダで対応していなかったのを、この機に対応させました。

EPUBMaker, WebMaker: 数式表現手法として MathJax をサポートし、数式表現手法を math_format パラメータで選択するようにしました

Web の世界で TeX 数式を表現する方法として、JavaScript を利用した MathJax が準標準となっている感があります。

math_format: mathjax パラメータを設定すると、EPUBMaker, WebMaker において数式部分を MathJax を使った形になるようにしました。

配布用の EPUB では外部ファイルの読み込みを要するので EPUB 検査を通らないこと、またほとんどの EPUB リーダーでは JavaScript を実行できないので意味が薄いです。しかし、EPUB をベースにした CSS 組版では強力な数式表現手段となるでしょう。

_images/mathjax.pngMathJaxを有効にした例

従来の画像化には、math_format: imgmath を、MathML を使いたいときは math_format: mathml を指定します。

旧来の imgmath パラメータは obsolete となります(ただし、互換性を維持するため math_format: imgmath になるよう内部処理します)。

非互換の変更

EPUBMaker: urnid パラメータのデフォルト値のプレフィクスを、urn:uid から urn:uuid に変更しました

実は実装の最初からどうも間違っていたようです。とはいえ、urn:uid も urn:uuid もまともに EPUB リーダーで使われていた感じはなさそうですし、流通用には isbn のほうを使うから顕在化もしないし……。壮大な仕様というのはえてしてこういうものでしょうか。

PDFMaker: 長い脚注がページ分断されないようにしました

review-jsbook, review-jlreq はともに、ある程度長い脚注でうまく紙面収めができないと判断したときには脚注を分断して収めようとします。とはいえ、論文ではなく普通の書籍だと「下アキが大きい紙面になる」vs「脚注がページ分断される」の選択を迫られたときには前者のほうを選ぶのが一般的な気がするので、デフォルトをアキが大きくなってでも脚注を分断しないほうに倒しました。

具体的にはクラスファイルのほうで

\interfootnotelinepenalty\@M

を設定しています。紙面収めの綺麗さを優先してページ分断を許容したいときには、review-custom.sty に以下を指定して戻してやればよいでしょう。

\interfootnotelinepenalty=100

バグ修正

contentdir を設定しているときに WebMaker, review-vol, review-index がエラーになるのを修正しました

pandoc2review による Markdown ファイルの併用 での実装をしているときに発見したバグです(pandoc2review、自分でいうのも何ですが神ツールですね、これは)。

WebMaker: images/html 図版フォルダが見つけられないのを修正しました

こちらはご指摘いただいて直しました。ありがとうございます。

PDFMaker: 用語リストの見出しで chapterlink がおかしな結果になるのを修正しました

これもご指摘いただきました。description 環境はいろいろ特殊で厄介です。

PDFMaker: 索引に {, }, | が含まれているときにエラーや奇妙な文字に変換されるのを修正しました

これもあわせてご指摘いただいたものですね。内部処理コードがどんどん mendex 特化していくのがちょっと気になるところではあるのですが、現状 mendex 以上の索引ツールがないのも事実であります。

review-vol: 不正な見出しがあったときに妥当なエラーメッセージを出力するようにしました
review-vol, review-index が不正なファイルを受け取ったときのエラー処理を修正しました

どちらも特定ケースにおいて内部エラーで捕捉できずバックトレースになってしまうことがあるのを修正しました。

PDFMaker: after_makeindex フックを LaTeX コンパイル後ではなく mendex 実行後に実行するように修正しました

これじゃ意味ないじゃーんという実行順序になっていたのを直しました。

PDFMaker: //image のキャプションが空だったときに内部エラーではなく図番号が出力されるように修正しました

Re:VIEW 5 での実装変更で想定漏れしていました。

EPUBMaker: author などの静的ファイルを指示したときに、ファイルが存在しないと内部エラーを起こしていたのを修正しました

自分で使っていると、ファイルを用意してから config.yml をいじる、という順序なのでこういうのは気付きにくいですね。検査とコピーをメソッド化して、必ず確認するようにしました。

機能強化

tty-logger gem パッケージがインストールされている場合、Re:VIEW の各 Maker コマンドの進行状態をアイコンおよびカラーで示すようにしました

Vivliostyle CLI の出力のステータスの色分けがうらやましかったので、Re:VIEW でもちょっと実装を入れてみました。良いね!

_images/ttylogger.pngtty-loggerによる表示

あくまでもログ出力のヘッダ色付けをするだけで、くるくる回ったりはしませんが。以前にtahahashimさんにロガーを分離していただいていたおかげで、実装は容易でした。tty-logger gem は gem install review のときに一緒にインストールされるはずですが、入らなかったら gem install tty-logger でインストールしてください(この gem がなければ普通に以前と同じ出力になります)。

PDFMaker: クラスファイルで \RequirePackage{plautopatch} を最初に評価するようにしました

日本語LaTeXの新常識2021 によると plautopatch を取り込むのがトレンドらしいので、review-jsbook, review-jlreq クラスファイルの冒頭で読み込むようにしてみました。

MARKDOWNBuilder: @<hd> をサポートしました

MARKDOWNBuilder でサポートしていなかったのに対処しました。とはいえ、Markdown 自体では表現の幅に限界があるので、他章参照とかは厳しいです。

Re:VIEW ドキュメントファイルに不正なエスケープシーケンス文字が含まれているときにエラーを出すようにしました

^H などの隠れ制御文字は LaTeX でわかりにくいエラーになるので、ファイルの評価時にこのチェックを入れるようにしました。

= の数が6を超える見出し扱いの行があるときにエラーを出すようにしました

原稿で区切りのつもりで使われた「========」のような行が意図しない形で内部エラーになるので、異常見出しっぽくなりそうだったら捕捉してエラーを出すようにしました。

なお、実際リテラルにこれを使いたい、というときには、先頭にスペースを入れる(トリミングされるので問題ない)、@<embed>{=}======= のように先頭をembedにするといった方法が考えられます。

ドキュメント

画像探索の際に各 Maker が参照するサブフォルダ名について記載しました

そういえばビルダについては記載しているけど Maker のはちゃんと説明入れていないね、ということで記載しました。

その他

EPUBMaker: EPUB ライブラリ一式を lib/epubmaker から lib/review/epubmaker に移動し、リファクタリングしました

これまで「ほかのソフトウェアでも使えるように」と内部的に分離していた EPUB ライブラリですが、もう Re:VIEW くらいしか使っておらんだろうということで併合しました。内部的にはかなり大掛かりな修正です。takahashim さんありがとうございました!

EPUBMaker: テストを追加しました

EPUBMaker のテストがいろいろ足りていなかったのをこの機会に増強しました。

PDFMaker: いくつかの処理をリファクタリングしました
IDGXMLMaker: いくつかの処理をリファクタリングしました
MakerHelper: いくつかの処理をリファクタリングしました
ライブラリの相対パスの参照方法をリファクタリングしました
ReVIEW::LineInput クラスをリファタクタリングしました

恒例のリファクタリングで見通し改善を図っています。

数式画像生成処理を ReVIEW::ImgMath クラスにまとめました

ビルダによってちょっとバラバラだった部分をクラスで共通化しました。

テンプレート処理を ReVIEW::Template.generate メソッドに統一しました

PDFMaker, EPUBMaker で分かれていたテンプレート処理を統一しました。

GitHub Actions で TeX コンパイルのテストも行うようにしました

もともと TeX コンパイルテスト自体はテストユニットとして持っており、手元環境ではテスト実行していたのですが、Actions のほうにも TeXLive 入りの環境を用意してテストするようにしました。

Rubocop 1.10 に対応しました

恒例の Rubocop 先生対応です。

サンプル syntax-book の重複 ID を修正しました

サンプルで重複 ID の警告がうるさいので、サンプルを修正しました。

Copyright を2021年に更新しました

Re:VIEW の原形が作られたのは2002年なので、来年はいよいよ20周年ですね。

Ruby 3.0 でのテストを実行するようにしました

現物はまだ使っていないのですが、とりあえずテストベースでは何も問題は起きていないようです。

不安定な Pygments のテストを抑制しました

Actions の環境でどうにもカラーハイライタの Pygments(Python プログラム)の挙動が安定せず、うまくいったり空になったりで変なので、テストから外しました。コード自体はあまり手を付けない箇所なので、そう壊れるところはないですし。

WebTocPrinter: テストのエラーを修正しました

ライブラリファイルを1つ明示的に読み込むようにしました。

テストのターゲットを指定しやすいようにしました

テストユニットも増えてきたので、rake test[target] でテスト時に指定しやすいようにしました。

終わりに

今回の Re:VIEW 5.1 では 5.0 で積み残していた EPUB ライブラリの移行のほか、いろいろと気になっていた部分に手を付けてみました。Vivliostyle CLI を使った CSS 組版、囲み装りの選択機能など、いろいろと皆さんのチャレンジ、カスタマイズしがいのありそうなリリースになったと思います。

次のバージョン予定としては lib/review の中が多すぎるようになってきたのでフォルダ構成を変更したり、EPUB ライブラリをさらにバラして EPUBMaker に統合したりといったまたちょっと大掛りなことをする見込みで、メジャーバージョンアップとなるかもしれません。

Enjoy!

2020/10/29 by @kmuto

Re:VIEW 5.0 での変更点

Re:VIEW 5.0 において 4 系から変更した点について解説します。


Re:VIEW は定期的に機能向上のためのリリースを続けていますが、2020年10月29日にメジ ャーバージョン改訂となる「Re:VIEW 5.0.0」をリリースしました。

バージョン3 → 4が1年でしたが、今回もバージョン4 → 5は1年なので、今のところ1年ごとにメジャーバージョン改訂をしているんですね。4.3 ではなく 5 としたのは、やはり内部実装を大きく変更していることによります。

多数の改良を施していますが、外部に見えやすい実装の目玉としては、永らく切望されていた「入れ子」の対応があります。


既知の問題

現在はまだありません。


インストール

新規インストールの場合

$ gem install review

更新の場合

$ gem update review

既存プロジェクトのバージョンアップ追従

Re:VIEW 3〜4のプロジェクトについては基本的に後方互換性を保持しているため、Re:VIEW 5.0 でもそのまま利用できます(review-ext.rb での拡張をしていない状態で何か問題が出たとすれば、それはバグですのでご報告いただければと思います)。せいぜい、major version of configuration file is different.というメッセージが出るくらいでしょうか。

警告メッセージを出したくない、あるいは後述の機能の中で TeX 関連の機能向上を反映させたいといった理由で既存のプロジェクトを 5.0 に更新するには、Re:VIEW 5.0 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 5.0.0 に更新します **
config.yml: 'review_version' を '5.0' に更新しますか? [y]/n 
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-5.0.0/templates/latex/review-jsbook/review-base.sty) で置き換えら
れます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-5.0.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、新規に導入した機能や変更点について理由を挙げながら解説します。

新機能

review-jsbook / review-jlreq クラスに、cover_fit_page オプションを追加しました

Re:VIEWでは、表紙画像は紙面相当サイズ(および塗り足しサイズ加味)であることを想定し、実寸で中央配置しています。これは商業印刷においてデザイナーの設計のとおりを再現するための必須の措置です。

しかし、同人誌においては紙面サイズの画像を用意する、というのは意外と大変なようで、(画像サイズが不正確なために)画像がはみ出す、うまく置けないといったユーザーのtweetをたびたび目にしていました(ピクセル単位では操作できても、mm単位で指定できてかつ手軽に入手できる画像ソフトウェアが少ないことも一因かもしれません)。

この対策として Re:VIEW 5.0 では、review-jsbook, review-jlreq クラスのオプションとして、新たに cover_fit_page オプションを追加しました。texdocumentclass パラメータに cover_fit_page=true を付加すると、画像サイズがどのようなものであっても仕上がりサイズに拡大(あるいは拡縮)して表紙に貼り込みます。

あくまでも仕上がりサイズであり、塗り足し領域までは拡大しないので、表紙も含めて印刷をするときには、塗り足し領域まで含めた実寸の画像を用意するようにしてください。

小さな囲み要素 (//note, //memo, //tip, //info, //warning, //important, //caution, //notice) の中で、//image などのブロック命令を含めたり、および箇条書きを入れたりできるようになりました

@takahashimさんの尽力で、//note などの囲み要素の中にほかのブロックや、箇条書きを入れる、いわゆる入れ子の機能が実装されました。

//note{
これまで段落しか入れられなかったのが

 * 箇条書きを
 * 入れたり

//image[note-fig1][note内の画像を入れたりできる]{
//}

//}

このブロック入れ子を許容しているのは //note, //memo, //tip, //info, //warning, //important, //caution, //notice に限定しています(表の中に表みたいな用途には使えません)。また、//note の中にさらに //note//tip を入れるといったことも禁止しています。

なお、review-ext.rb の拡張で類似のことを利用したいときには、defminicolumn で定義します。

箇条書きの入れ子を指示する命令として //beginchild, //endchild という1行命令を追加しました(実験的)

こちらは説明どおり、箇条書きの入れ子です。箇条書きの子にしたいものを //beginchild//endchild で囲むと、前に位置する箇条書きの子要素になります。

 1. 番号箇条書きAの1.

//beginchild

 * 番号箇条書きAの子となる中黒箇条書き

番号箇条書きAの文章続き

//endchild

 2. 番号箇条書きAの2.

//beginchild//endchild は必ず対になる必要があります。//beginchild で作った子の中にさらに //beginchild//endchild の孫、あるいはさらにひ孫を作っても構いません(ただ、LaTeX 等において深さの限界があります)。

ほかに良い文法があればよかったのですが、インデントを使うことはしたくないというポリシーがあり、いささか不格好ながら単一命令を使った手法をとることにしました。

この箇条書きの入れ子機能は実験的です 。今後のバージョンで挙動を変えたり廃止したりする可能性があります。

非互換の変更

review-jlreq.cls における hiddenfolio の配置を、jlreqtrimmarkssetup を使って実装するように変更しました。以前のバージョンとは位置や表示に若干の違いがあります

同人誌印刷等で使われるノドの隠しノンブル(隠れていないのに隠しとは……という不思議な感じですが)の表現について、これまで review-jlreq では review-jsbook と同じものを使っていたのですが、review-jlreq でより適切な手法として jlreqtrimmarksetup を使うようにしました。これに伴い、ちょっと見た目が変わっています。

review-jlreq を使っている方はまだ少ないでしょうし、この隠しノンブルの表示の変化も利用において大きな影響はないものと思います。

chapterlink パラメータのデフォルト値を true (有効) にしました

WebMaker および EPUB での章・項の参照や、図表・リスト・式・参考文献の参照などをハイパーリンク化する chapterlink パラメータはこれまで null(無効)をデフォルトにしていたのですが、実際の Web・EPUB というメディアにおいてはハイパーリンクであるほうが実用的です。

Re:VIEW 5.0 からこのパラメータのデフォルト値を true(有効)にしました。ハイパーリンクになるのが望ましくないときには、chapterlink: null を使ってください。

TeX PDF においては media=ebook のときのみ、章・項・参考文献の参照がハイパーリンク化されます。

バグ修正

PDFMaker: 同名で拡張子違いの図版ファイルがあるときに、位置がずれる問題を修正しました

これまで PDFMaker では、extractbb というコマンドを内部で呼び出し、TeX PDF コンパイルの補助情報として画像ファイルのサイズを書き出していました。問題は、この補助情報ファイルがファイル名に拡張子 .xbb を付けたものであることです。たとえば同じフォルダに画像ファイル「fig1.png」「fig1.pdf」が置かれていたとき、片方に対して作られた fig1.xbb は、もう1つの fig1.xbb で上書きされてしまいます。上書きされてしまったほうが TeX PDF で使うべき正しいものだった場合、ずれた結果になってしまうわけです。

xbb 補助情報は昔の TeX 環境では必要な措置でしたが、最近(といってもTeXLive 2015 以降)はもうこの補助情報ファイルがなくても内部的に必要なファイルにのみ extractbb を実行するようになっています。

もはや TeXLive 2014 は対応する必要もないかと思われるので、Re:VIEW 5.0 では extractbb コマンドの明示呼び出しを止めました。これにより、同名拡張子違いの画像ファイルが存在しても問題なく適切に配置されます。

PDFMaker: 著者名 (aut) パラメータが空のときにエラーになる問題を修正しました

自分の利用範囲だとまずないケースだったので、こういうのは見落としますね…。

PDFMaker: //indepimage 命令で画像が存在せず、かつ ID に TeX のエスケープ対象となる文字を含んでいるとエラーが起きる問題を修正しました

2つの条件が合わないと発生しない、レアケースでした。

なお後述しますが、Re:VIEW 5.0 では、ID に TeX あるいは EPUB に悪影響を及ぼす可能性がある文字があるときには警告されるようになっています。

PDFMaker: booktitlenameaut パラメータに TeX のエスケープ対象となる文字を入れると PDF メタ情報がおかしくなる問題を修正しました

PDF には書名や著者名などを PDF メタ情報として入れていましたが、このエスケープが二重エスケープになっていました。

対策の副作用で、PDF メタ情報が入るのは texdocumentclass パラメータに media=ebook を付けているときのみとなります。

内部的には PDF の生のメタ情報を書き込むのではなく、TeX の hyperref パッケージの hypersetup 命令を使って指定しています。このため、hyperref の機能を実質的にオフにしている media=print の状態では作用できません。

WebMaker: HTML テンプレートで nil が入ってしまうのを修正しました

WebMaker の HTML テンプレートに不具合があったので修正しています。

PDFMaker: 章番号を非表示にするとエラーで失敗するのを修正しました

locale.yml で chapter: "" のように何も表示しないようにしたときにエラーになるのに対処しました。

MarkdownBuilder: note 等の中の段落を改行区切りではなく空行区切りにしました

Markdown 変換ってどのくらい使っている方いるんでしょうね……。ともあれミニコラム内での複数段落表現が Re:VIEW と一致するようになりました。

機能強化

図表などのアイテムでエラーが発生したときの表示を詳細にしました

ID が重複したときのメッセージの詳細が不明瞭だったので、より詳しい情報を出すようにしました。

これまで:
WARN review-epubmaker: warning: duplicate ID: fig1 (#<ReVIEW::Book::Index::Item:0x000055943be68488>)

Re:VIEW 5.0
WARN review-epubmaker: warning: duplicate ID: fig1 (#<ReVIEW::Book::Index::Item:0x0000560877fe01c0 @id="fig1", @number=2, @caption="ある図", @path=nil, @index=nil>)
PDFMaker: @<hd> 命令で展開した項・段について、media=ebook のときにはハイパーリンクになるようにしました

これまで @<hd> を TeX に展開した \reviewsecref ではリンク情報自体は渡していたものの何も使っていなかったのですが、TeX hyperrefパッケージでのハイパーリンクにする調整を行い、有効化しました。

HTMLBuilder および IDGXMLBuilder において、文字列のエスケープを従来の cgi/util の代わりにより高速な cgi/escape が利用できるときにはそれを利用するようにしました。また、ReVIEW::HTMLUtils.escape も書き換えられました

ほとんどの場合は関係ありませんが、「'」文字の取り扱いが変わります。Re:VIEW 4 系までは変換してもそのまま「'」が使われていたのに対し、Re:VIEW 5.0 では「&#39;」と実体参照になります。

フックで HTML ファイルを書き換えるなどの加工をしていたときには注意してください。

@<icon> 命令の利用時に ID の重複の警告が出るのを抑制しました

アイコンなどのインライン画像を挿入する @<icon> では同じファイルを使い回すことも多いため、いちいち重複の警告を出すのを止めました。

不正なエンコーディングのファイルを受け取ったときに妥当なエラー表示をするようにしました

Re:VIEW の re ファイルは UTF-8 エンコーディングのみのサポートとしていますが、Shift JISなどの他エンコーディングのファイルを受けたときにわかりにくい内部エラーを返していました。

エンコーディング問題のエラーを検出して、コンパイルエラー(invalid byte sequence in UTF-8)を出すようにしました。

IndexBuilder を導入しました

内部実装的には Re:VIEW 5.0 での最も大きな変更です

これまで図表等の番号の管理および参照はその都度対象ファイルを解析する方法でしたが、IndexBuilder はまずプロジェクト全体を走査し、以降の各ビルダのために番号を保持して提供します。

review-ext.rb でブロック命令やインライン命令のメソッドを追加していた場合、IndexBuilder クラス (またはその基底クラスである Builder クラス) にも追加が必要です。番号を使っていなければ「何もしない」空のメソッドを定義するだけでよいでしょう。

ID やラベルに以下の文字または空白文字が含まれていると、TeX のコンパイルあるいは生成される EPUB においてエラーが発生するため、これらの文字が含まれているときには警告を出すようにしました

いろいろ調べた結果、TeX と EPUB のどちらかあるいは両方で ID に入っていると厄介なことになる(TeX のコンパイルが通らない、EPUB チェックが通らない)のは、空白と、#、%、\、{、}、[、]、~、/、$、'、"、|、*、?、&、<、>、` でした。

これらのいずれかの文字が使われていたときには警告を出します。

ドキュメント

format.ja.md と format.md のタイプミスを修正しました

ご指摘ありがとうございます!

makeindex.ja.md のサンプル結果の誤りを修正しました

ご指摘ありがとうございます!

その他

Rubocop 0.92.0 に対応しました

恒例ですね。あまり好みに合わないのは disable にしていますが。

Re:VIEW::Compiler 内の @strategy は実際はビルダなので、@builder という名前に変更しました

内部の話なのであまり影響はないかもしれませんが、review-ext.rb で Compiler 部分を書き換えていたときには、@strategy@builder にするか、@strategy = @builder と代入するかの対処が必要になるでしょう。

Rubocop-performance 1.7.1 に対応しました

こちらも先と同様です。

syntax-book サンプルドキュメントの Gemfile を更新しました

古かったので更新しています。

ImageMagick における GhostScript の呼び出しが非推奨となったため、テストを除去しました

ImageMagick も GhostScript もセキュリティ問題がぽろぽろ出るのは同程度な感じがしますが、Debian の ImageMagick はデフォルトでの GhostScript 呼び出しを止めたようで、テストが動かないケースが出てきました。

ImageMagick の policy.xml で戻せばいいという話ではありますが、テストにそれを求めても仕方がないので、テスト自体を除去しています。あまり変化のあるところでもないですし。

一部のテストユニットの不要な標準エラー出力を抑制しました

rake test したときにちょこちょこ標準エラー出力が出ていたのを抑制しています。

Compilable モジュールの代わりに、Chapter および Part のスーパークラスとなる BookUnit 抽象クラスを導入しました

内部表現の調整です。review-ext.rb でカウンタを独自に作っていた場合は影響があるかもしれません。

ReVIEW::Book::Base.load をやめ、ReVIEW::Book::Base.load または ReVIEW::Book::Base.new を使うようにしました。ReVIEW::Book::Base.load:config オプションを加えました

こちらも中身の整理です。テストなどもしやすくなったはず。

内部のパラメータの汎用構成のために ReVIEW::Configure.create コンストラクタを導入しました

これでパラメータ構成はだいぶ綺麗になったはずですが、EPUBMaker が昔の独立ライブラリを引きずっていてまだ完全には綺麗にできていないですね。次の TODO です。

WebMaker: 使われていない clean_mathdir メソッドを削除しました

整理したら、いらなくなりました。

catalog.yml の解析を ReVIEW::Book::Base.new の中で最初に実行するようにしました

これまでは ReVIEW::Book::Base.catalog を呼び出したときにまだ解析してなかったら初めて解析する、という仕組みだったようです。あえて動的読み込みをする必要もないので、最初に解析するようにします。

ファイルの書き出しで可能なところは File.write を使うようにしました

書き出しのコードが少しシンプルになりました。

Builder クラスの builder_init メソッドを削除し、initialize を使うようにしました

もともと何だったんだろうこれ、というメソッドですが、拡張されるときも普通は builder_init_file を使っていると思いますので、影響はほぼないでしょう。

終わりに

今回の Re:VIEW 5.0 ではかなり改修を行いましたが、EPUB ライブラリの改修や、scaffold の仕組みなどいくつか TODO で残してしまったものがあります。文法のほうはだいぶ固まったかなという気はしますが(表という不倶戴天の難敵はありますが…)、今後も定期的な改善を継続していきます。お楽しみに。

2020/6/29 by @kmuto

Re:VIEW 4.2 での変更点

Re:VIEW 4.2 において Re:VIEW 4.1 から変更した点について解説します。


2020年6月29日に、Re:VIEW 4 系のマイナーバージョンアップである「Re:VIEW 4.2.0」をリリースしました。

今回のバージョン 4.2 は、発見された不具合の修正と、新機能を数点導入しています。


既知の問題

現時点では報告はありません。


既存プロジェクトのバージョンアップ追従

既存のプロジェクトを更新するには、Re:VIEW 4.2 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 4.2.0 に更新します **
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-4.2.0/templates/latex/review-jsbook/review-base.sty) で置き換えられます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-4.2.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、新規に導入した機能や変更点について理由を挙げながら解説します。

新機能

図・表・リスト・式のキャプションの位置を内容の上側・下側どちらにするかを指定する caption_position パラメータを追加しました

これまでキャプション位置は、次のように固定でした。

  • 図(//image): コンテンツの下

  • 表(//table)、リスト(//list, //listnum, //emlist, //emlistnum, //source, //cmd, //box)、式(//texequation):コンテンツの上

紙面表現においてこれと異なる形にするには review-ext.rb 等を使って書き換える必要がありました。

新たに caption_position パラメータを導入し、コンテンツの上・下どちらにキャプションを置くかを指定できるようにしました。

caption_position:
  image: bottom
  table: top
  list: top
  equation: top

値は top(上)または bottom(下)のいずれかです。list はリスト類すべて、式は texequation ではなく equation で指定することに注意してください。

なお、デフォルトから変更したときの見た目について、提供する LaTeX スタイルファイルでは関知していません。必要に応じて適宜調整してください。また、LaTeX でハイライトコードを使っている場合、キャプションの位置はマクロ側でしか調整できないことにも注意してください。

非互換の変更

review-vol を再構成しました・review-index を再構成しました

いろいろ挙動が怪しかったこの2つのコマンドを全面的に書き換えました。これまで使っている人は原作者の青木さんと私くらいだったのではないかと思うので、大きく変わっているといってもピンとこないかもしれません。

review-vol は各章ファイルのサイズ(バイト・文字数・行数・想定ページ数)と章見出しを表示するツールですが、以前のバージョンは部ファイルに対応してない、見出しにインライン命令が使えないなど、いろいろと不便なところがありました。これらに対応すべき全体を書き換えています。

これに伴い、以下の変更があります。

  • 部を指定したときに部の下にある各章のサイズを結合して表示する機能はなくなりました。

  • -P, --directory オプションによるフォルダ指定はなくなりました。

$ review-vol
  1KB    378C    26L   1P  pre01 ......... 前書き
  0KB      0C     0L   0P  部扉見出し ......... 第I部  部扉見出し
  7KB   2929C   128L   7P  ch01 .......... 第1章  章見出し
  1KB    175C     5L   1P  part2 ......... 第II部  部見出し■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
 14KB   7898C   336L  14P  ch02 .......... 第2章  長い章見出し■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
  7KB   2584C    77L   7P  ch03 .......... 第3章  コラム
  1KB    197C    21L   1P  appA .......... 付録A  付録の見出し
  1KB    211C     5L   1P  bib ........... 参考文献
=============================
 28KB  14372C   598L  28P

review-index は各章の見出し類を目次として表示します。以前のバージョンでは review-vol 同様に文字数や行数などを表示していましたが、目次を知りたいという目的では不要なので、詳細オプション(-d)を付けたときのみそれらを出すようにしました。また、インライン命令の処理なども改善しています。特定の章のみを表示したいときには Maker 系と同じく -y オプションで指定できるようにしました。ほか、-l(見出しの深さ)、--noindent(インデントしない)のオプションがあります。

$ review-index
前書き
第I部 部扉見出し
第1章 章見出し
  1.1 節見出し
    1.1.1 項見出し……に脚注を入れるとTeXではエラー
      1.1.1.1 段見出し
  1.2 長い節見出し■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
    1.2.1 長い項見出し■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
      1.2.1.1 長い段見出し■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
    1.2.2 採番する項見出し
  1.3 箇条書き
 …

$ review-index -y ch02 (2章だけ表示)
第2章 長い章見出し■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
  2.1 ブロック命令
    2.1.1 ソースコード
    2.1.2 図
    2.1.3 表
    2.1.4 囲み記事
  2.2 LaTeX式
 …

$ review-index -y ch02 -l 2 (2レベルまでの表示)
第2章 長い章見出し■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
  2.1 ブロック命令
  2.2 LaTeX式
  2.3 インライン命令

$ review-index -y ch02 -l 2 --noindent (インデントなし)
第2章 長い章見出し■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
2.1 ブロック命令
2.2 LaTeX式
2.3 インライン命令

$ review-index -y ch02 -l 2 -d (詳細情報)
=============================
  5361C   163L    10P  ch02
-----------------------------
    52C     1L   0.0P  第2章 長い章見出し■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
  2995C   114L   6.1P    2.1 ブロック命令
   509C    14L   0.8P    2.2 LaTeX式
  1805C    34L   2.5P    2.3 インライン命令

review-vol と review-index で文字数などに違いがあるのは、review-vol はファイルの Re:VIEW 命令をほとんど解析・変換せずに算出しているのに対し、review-index はテキストビルダ(PLAINTEXTBuilder)を経由して実際に近い文字数で算出していることが理由です。つまり、review-index のほうがより正確な値を得られますが、ファイル内に構文エラーがあると、そこで算出処理が終了してしまいます。

review-vol で(たとえ中身が少々壊れていても)おおまかに章間のバランスを見極め、review-index で目次構成レベルで詳細に確認する、という使い方をお勧めします。

バグ修正

重複する @non_parsed_commands 宣言を削除しました

compiler.rb ファイル内の initalizedo_compile メソッドの両方で @non_parsed_commands を重複定義していました。結局のところどちらで定義するのも挙動的によろしくないことがわかり、メソッド non_escaped_commands を用意してその返却値を使うようにしました。

review-ext.rb で挙動を変えていたときには注意してください。

WebMaker、TextMaker で数式画像が作成されない問題を修正しました

これは Re:VIEW 4.2 開発中に仕込んでしまったバグの修正ですね。4.1→4.2リリース版という更新プロセスならそもそも問題ないはずです。

機能強化

imgmath での数式画像の作成処理を最適化し、高速化しました

100個程度の数式の入った書籍ではこれまで顕在化していなかったのですが、500 以上になると妙に時間がかかるな…と思っていたら、数式を全部リストアップしたところまではよかったのですが、重複を削除せずに愚直に1つずつ画像を作っては上書きしていました(特に pdfcrop で切り出すところが遅い)。

重複を取り除いてから画像を作成するようにして高速化しました。

なお、この開発で上記の「WebMaker、TextMaker で数式画像が作成されない問題を修正しました」の原因になったバグを仕込んでしまっていました…。

デフォルト以外の固有の YAML 設定を PDFMaker に引き渡したいときのために、layouts/config-local.tex.erb ファイルが存在すればそれを評価・読み込みするようにしました

Re:VIEW 3 以降、YAML 設定値は config.erb 経由で引き渡し、この config.erb で宣言した TeX マクロの値を、クラスファイルやスタイルファイルで参照する、という仕組みになっています。

ただ、ここで引き渡せる YAML 設定値は config.erb で定義しているもののみであり、それ以上のものについてはフックスクリプトでなんとかするか、layouts フォルダに layout.tex.erb を置いてこれを書き換えるという方法をとるしかありませんでした。いずれもやや大袈裟です。

Re:VIEW 4.2 でも仕組みは変わりませんが、layouts フォルダに config-local.tex.erb というファイルを置いたら、それを config.erb の後に評価・読み込みするようにしました。

YAML ファイルが以下だとして

…
mycustom:
  mystring: HELLO_#1
  mybool: true

layouts/config-local.tex.erb はたとえば次のようになります。

\def\mystring{<%= escape(@config['mycustom']['mystring']) %>}
<%- if @config['mycustom']['mybool'] -%>
\def\mybool{true}
<%- end -%>

これは最終的に次のように展開されます。

 …
\makeatother
%% BEGIN: config-local.tex.erb
\def\mystring{HELLO\textunderscore{}\#1}
\def\mybool{true}
%% END: config-local.tex.erb

\usepackage{reviewmacro}
 …

こうして定義されたマクロをスタイルファイルなどで参照します。

なお、YAML 設定の引き渡しは、文字列のエスケープ、シリアライズの手段、エラーの対処など考えるべきことが多数あります。既存の config.erb やスタイルファイルなどがどのようになっているか、参考にしてください。

その他

GitHub Actions を eregon/use-ruby-action から ruby/setup-ruby に切り替えました

自動ビルドの GitHub Actions で使っていたアクションが不安定だったため、別のアクションに切り替えました。

テストの際、samples フォルダ内にあるビルド成果物を無視するようにしました

samples の sample-book や syntax-book にビルド中間ファイルが残っていると、これらを使うテストに失敗していました。テストでは一時フォルダにサンプル一式をコピーしてビルドする、という仕組みにしていたのですが、中間ファイルまでコピーして失敗していたというオチです。コピー対象から中間ファイルを除外することで対処しています。

終わりに

今回の Re:VIEW 4.2 では review-vol/review-index の再構成以外に大きな修正というほどのものはありませんでしたが、次のバージョンでは、文法にも関わるやや大きめの変更を計画しています(そのため、おそらく次バージョンは 5.0 となりそうです)。お楽しみに。

2020/2/29 by @kmuto

Re:VIEW 4.1 での変更点

Re:VIEW 4.1 において Re:VIEW 4.0 から変更した点について解説します。


2020年2月29日に、令和最初の版となる「Re:VIEW 4.1.0」をリリースしました。

このバージョン 4.1 では、前回リリースの 4.0 で発見された不具合の修正を行うとともに、いくつかの改良を施しています。


既知の問題

現時点では報告はありません。


既存プロジェクトのバージョンアップ追従

既存のプロジェクトを更新するには、Re:VIEW 4.1 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 4.1.0 に更新します **
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-4.1.0/templates/latex/review-jsbook/review-base.sty) で置き換えられます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-4.1.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、新規に導入した機能や変更点について理由を挙げながら解説します。

新機能

表のセル区切りの文字を table_row_separator パラメータで変更できるようにしました

これまで Re:VIEW の表のセル区切りは「1つ以上の物理タブ」としていましたが、他のマークアップ言語で作った表をなるべくそのまま配置したいといったケースを考慮して、config.yml への設定パラメータを追加しました。

パラメータに指定可能な値は、tabs (1個以上のタブ、デフォルト)、singletab (1文字のタブ文字区切り)、spaces (1文字以上のスペースまたはタブ文字の区切り)、 verticalbar ("0個以上の空白 | 0個以上の空白" の区切り) です。

実際には spaces あるいは verticalbar あたりが使いそうなものでしょうか。ただ、スペース文字区切りにすると当然セル内にスペース文字を入れることができなくなる(厳密には @<embed>{ } を入れるといった方法もありますが)ので、設計思想的にはセルの区切りとしてはタブを使うことを推奨しています。

当初は任意の正規表現にしようかと思っていたのですが、「将来的に文法ジェネレータによるパーサに置き換えるときに任意表現が混ざると辛い」ということで限定しました。もっと別のものにしたいときには適宜 review-ext.rb を使って Builder#table_row_separator_regexp を置き換えればよいでしょう。

PDFMaker, EPUBMaker, WEBMaker, TEXTMaker, IDGXMLMaker: 全ファイルでなく変換対象ファイルを指定するための -y(または--only)オプションを追加しました

業務では類似の場面に特製の処理をしており、汎用実装は難しいかなと思っていたことなのですが、maker のロジックを眺めていたらわりと簡単にできそうなことに気付き、実装してみました。

review-pdfmaker -y ch01.re,ch02.re config.yml のように特定の re ファイルだけを指定してビルド対象にできます。rake の場合も REVIEW_PDF_OPTIONS="-y ch01.re,ch02.re" rake pdf というように環境変数経由で指定できます。.reは省略できるので、-y ch01,ch02 でも構いません。

章番号や相互参照などはそのまま保たれているので、大規模な書籍の中からある章を集中的に作業するときなどには特に便利に使えるでしょう。

config.yml のコメント行を含めないようにする --without-config-comment オプションを review-init に追加しました

Re:VIEW の機能拡張とともに config.yml の説明コメントがどんどん長くなっており、必須設定項目が見辛くなっています。

本質的な解決ではありませんが、ひとまず review-init コマンドにオプションを追加し、コメント行を除いた config.yml を書き出せるようにしました。

PDFMaker: pdfmaker セクションに use_original_image_size パラメータを新設しました。デフォルトでは //image, //indepimage, //imgtable で挿入する画像において、metrics の指定がないときには版面の横幅に合うよう拡縮しますが、use_original_image_size パラメータを true に設定すると、拡縮なしで原寸のまま配置します

なんでそもそもこうだったんだっけ、という気もしていますが、Re:VIEW の //image 等で入れた図版は版面の横幅に合わせるようになっており、メトリクスオプションの scale や width で版面横幅比に基づく拡縮をする、というのがデフォルトの挙動です。たぶん画像の解像度や貼り付けたときの大きさなどを気にしない人が多い、という想定からこうされたのかな……という推測をしています。

しかし業務案件においては、図版は紙面・版面サイズを考えた上で実寸で配置するのが普通です。実際私の業務案件でも、//image などのところは置き換えて、版面合わせなどをしないようにしていました。

最近は図版の作り方にも慣れたユーザーも増えてきたようなので、版面幅合わせをしないようにするパラメータを今回導入しました。

use_original_image_size: true

デフォルト値は null (横幅合わせをする) です。

非互換の変更

PDFMaker: config.yml の image_scale2width パラメータを、直下から pdfmaker セクションの下に属するように変更しました

影響がいろいろありそうなので少しずつですが、Maker 固有のものはその Maker のセクション下に移動していこうかなと思っています。

ただ、Maker のセクションにあるパラメータは、その Maker が呼ばれたときに、直下にあった既存のパラメータを上書きするという処理になっているので、実のところごっそり移動しても影響はほとんどないのかも、という気もしてきました。

バグ修正

PDFMaker: Re:VIEW 3 系のプロジェクトとの後方互換処理の誤りを修正しました

3 系のプロジェクトでの後方互換向けに covermatter の定義処理を加えたら、コンパイルエラーが発生するようになってしまっていました。

TeX力が足りないですね……。ロジックをちょっと書き換えました。

PDFMaker: review-jlreq を LuaLaTeX でコンパイルしたときのエラーを修正しました

LuaLaTeX だと PDF 系のメタ情報の書き方がいろいろ違っていました。まだ LuaLaTeX は実験程度だったので、実行検証が甘かったです。後述の「その他」にあるとおり、upLaTeX や LuaLaTeX でサンプルをビルドテストすることで、今後の互換性破壊を防ぐようにしました。

PDFMaker: 索引が目次に含まれない問題を修正しました

索引機能を有効にしたときに、TeX のコンパイルが1回不足していたため、索引はできたけれどもそれが目次には含まれていない、という現象が発生していました。索引があるときには都合2回のコンパイルを実行するように変更しました。

RSTBuilder: メソッドの引数の誤りで変換に失敗する問題を修正しました

4.0 でビルダまわりのリファクタリングをしたときに、RSTBuilder だけ漏れがあり、エラーになっていました。リソースの問題で、コアビルダ以外は見過ごしが発生しがちですね……。

IDGXMLBuilder: 表に関する警告を出すときの誤りを修正しました

4.0 でのリファクタリングで、警告処理部分に修正漏れがありました。警告が出ずにランタイムエラーが出て判明、というよくあるパターンです。

IDGXMLMaker: フィルタプログラムにエラーが発生したときの処理の誤りを修正しました

これも同じですね。

PDFMaker: media=ebook のときに、見出し等に @<code>@<tt> のようなコード書体の命令を使うとビルドに失敗する問題を修正しました

4.0 でコード折り返しを入れて、見出しに入れることや目次にそれが入ることにも対応できていたのですが、media=ebook だと hyperref パッケージの機能でこれが PDF しおり (ブックマーク) に入ったときに展開に失敗してしまう、という問題です (しかもエラーがまたわかりにくい……)。

しおりに入る危なそうなマクロは、しおりの文字列を前処理する \pdfstringdefPreHook 内ですべて単なる文字列に置換する、という対処をとりました。

PDFMaker: MeCab がインストールされていないときにエラーになるのを警告に変更しました

もともと警告にしていたつもりだったのですが、エラーに遷移してしまっていたようです。

IDGXMLBuilder: //imgtable が正しく動作しなかったのを修正しました

4.0 のリファクタリングでの対処漏れでした。

PDFMaker: 索引が1つも登録されていない状態で makeindex を有効にするとエラーになるのを修正しました

普通は索引を入れてから有効にする、という手順をやっていたので気付いていませんでした。Maker の -y オプションを追加していたら発見したという経緯です。

PDFMaker: 説明箇条書き (:) の見出しに脚注を入れると消えてしまうのを修正しました

TeX の description の \item[] に展開したときに、[] 内でボックスが作られるので、そこに脚注のテキストを入れてしまうと脚注が出ないことになります。手元で使っていたときも説明箇条書き見出し内に脚注があるパターンはあったのですが、いずれも InDesign 案件で、この現象に気付いていませんでした。

とりあえず、説明箇条書き見出し内の脚注は footnotemark/footnotetext で対処するようにしました。

review-index: @<w> が見出しに使われているときにエラーになるのを修正しました

review-index は簡略化版の目次パーサを使っており、外部参照をするようなインラインがうまく動作しません。ひとまず @<w> について対処しました。

なお、review-vol も同じ目次パーサを使っており、こちらは今度はインライン命令がそのまま見出しに出てしまうという、またビミョーな実装状態になっています。

外部参照やインライン命令の解決をまじめにやるには、簡略化していない正規のパーサを使うように書き換える必要があり、将来TODOとしました (#1485)。

機能強化

PDFMaker: 問題報告の解析に役立つよう、提供する cls、sty ファイルについてバージョンを付けるようにしました

実行にはあまり関係がないことですが、エラービルドログにも示されるので、解析のときにはこういうのが役立ちますね。

Dockerfile を更新しました

デファクトスタンダードな vvakame/review の Dockerfile にほぼ準拠した形で更新しました。

IDGXMLMaker: フィルタプログラムの標準エラー出力を警告扱いで出力するようにしました

4.0 から導入した IDGXMLMaker ですが、フィルタプログラムの標準エラー出力を捨てていたので何が起きたのかよくわからない……という問題がありました (問題のないコンテンツとフィルタで使っていたのを移植したので、問題があったときのテストが不足)。エラー出力を拾うようにしました。

.gitignore ファイルに 〜-idgxml フォルダ を追加しました

IDGXMLMaker が作成する一時フォルダなので、コミット対象から外すようにしています。

//source 命令は全ビルダでオプションを省略できるようになりました

IDGXMLMaker だけ、//source のオプション省略ができませんでした。ほかに合わせて省略できるようにしました。

Ruby 2.7 をテスト対象に加えました

新たにリリースされた Ruby 2.7 もテスト対象にしました。互換性保持のため、まだ当分は固有の新機能を使うことはありません (Rubocop さんがまたうるさくなりそうですが……)。

word_files パラメータは配列で複数の単語 CSV ファイルを受け付けるようになりました

@<w> の展開文字列を列挙する word_files パラメータはこれまで単一ファイルしか指定できませんでした。共通+書籍固有 みたいに複数ファイルを指定したい、ということで、配列も指定できるようになりました。

同じ単語が複数ファイルに存在する場合は、後に指定にしたファイルの内容で上書きされます。

EPUBMaker: 見出しが1つもない .re ファイルについて警告を出すようにしました

EPUB においては、目次を内部で構築する都合上、ファイル内に見出しが必ず1つは必要です。

見出しを入れたくないときには、=[notoc] (目次に入れない) や =[nodisp] (目次に入れず表示もしない) を使用してください。

ドキュメント

奥付に関係する contact (連絡先)および colophon_order (項目の掲載順序)についてのドキュメントを設定ファイルサンプル config.yml.sample に追加しました

これらの機能は実は昔から機能としては用意していたのですが、ドキュメント化していませんでした。

やっぱり YAML ファイルの設定インターフェイスがほしいような……と思いつつ、コメント部分の保持などが難しいんですよねぇ。

quickstart.ja.md, quickstart.md を Re:VIEW 4 の内容に更新しました

3 系のままだったので更新しました。

サンプル syntax-book を更新しました

機能拡張したことなどに合わせて、ビルドテストを兼ねて厄介そうなパターンをいくつか追加しました。

README.md を更新しました

maker まわりや年数などの更新です。

図版のビルダ固有オプション :: の記法を format.ja.md, format.md に記載しました

これも機能は昔からあったけれどもドキュメント化していませんでした。使い方としてはこんな感じです。

//image[fig1][0.5倍にした図です][html::style="transform: scale(0.5);",latex::scale=0.5]

その他

Rubocop 0.78.0 の指摘に対応しました

いつものとおりです。Rubocop は新しいバージョンで機能が追加されるのはいいのですが、古いバージョンのパラメータをすぐ obsolete 化して非互換にしてしまうのはいかがなものか……。

LaTeX の実行環境がある場合、PDF のビルドテストをより厳密に実行するようにしました
  • サンプル: sample-book・syntax-book

  • クラス: review-jsbook・review-jlreq

  • コンパイラ: upLaTeX・LuaLaTeX

  • 出力: print・ebook

という全組み合わせでサンプルのコンパイルを実行し、ビルドエラーがないことを確認できるテストユニットを加えました。CI には LaTeX 実行環境はないので無視されるだけですが、手元で勘に頼らずに全組み合わせを確認できるようになったので、今後の安全なスタイルファイル改善に役立つはずです。

ビルドテストを Travis CI から GitHub Actions に切り替えました

Travis CI が不安定でまた非常に遅くなるなどいろいろと開発の障害になっていたため、@takahashim さんにより GitHub Actions への切り替え作業が行われました。これまでの Travis CI だとごく些末な PR でもマージの判断に20分近くのビルド待ちを要していたのですが、今の GitHub Actions だと2分かからず完了するので、とても便利になりました。

IDGXMLBuilder のコードリストの処理をリファクタリングしました

IDGXML のコードリストまわりは歴史的経緯でほかのビルダよりもだいぶゴチャゴチャしていたのですが、いろいろと整理をしました。

サンプル syntax-book に入っていた review-ext.rb はもう不要なので削除しました

@<balloon> 命令が一部のビルダにない時代の互換性のために入れていたものですが、すでに全ビルダに入っているので削除しました。

IDGXMLMaker, TextMaker のテストを追加しました

サンプルドキュメントに対しての Maker 実行が成功するかどうかを確認するようにしました。

Index 関連の処理をリファクタリングしました

この Index は索引ではなくて、ChapterIndex とか ImageIndex などの採番管理のほうのクラスのことです。作りがごちゃごちゃしていたのがだいぶ整理されました。

なお、将来的に Index まわりは大きく変わる予定です。

現状は各ビルダが「参照された時点」で初めて相手先のファイルを見にいくという仕組みになっており、Index の種類によって何度も繰り返されています。これを今後 IndexBuilder というものを導入して、これがプロジェクト全体を最初に探索して Index を記録管理し、各ビルダはその記録に照会をかける、という目論見です。進捗については @takahashim さんいかがでしょう、ということで…… (#1384)。

jsclasses パッケージを 2020/02/02 バージョンに更新しました

新しい LaTeX2e での実装変更で、日本語フォントまわりにも影響が生じることになりました。新旧両方の LaTeX2e に対応した jsclasses のバージョンが発表されたため、Re:VIEW 内包のコピーも追従更新しました。Re:VIEW にとっては具体的には jsbook.cls が更新の対象です。

終わりに

今回の Re:VIEW 4.1 では、新機能をいくつか入れはしていますが、4.0 の不具合の修正やテストの拡充などの安定性を重視しています。バージョン4はもとより、バージョン2、3系を使い続けている方も、ぜひ導入してお使いいただければと思います!

2019/10/29 by @kmuto

Re:VIEW 4.0 での変更点

Re:VIEW 4.0 において 3 系から変更した点について解説します。


Re:VIEW は定期的に機能向上のためのリリースを続けていますが、2019年10月29日にメジャーバージョン改訂となる「Re:VIEW 4.0.0」をリリースしました。

バージョン 3.0 は2018年11月のリリース (Re:VIEW 3 からの LaTeX 処理 を参照) で、マイナーリリースも 3.1, 3.2 だけだったので、だいぶ早いメジャーバージョン改訂です。

実のところ、表面的には、いくつか便利になった・バグが修正されたというくらいで、バージョン3からはそれほど大きな変化というものはありません。

しかし、このバージョンでは Re:VIEW の内部実装をかなり変更しており、review-ext.rb を使って Re:VIEW の挙動を変更・拡張していたプロジェクトには多大な影響が出る可能性が見込まれます。そのため、メジャーバージョンの改訂という形で、内部実装の大きな非互換があることを表すことにしました。


既知の問題

Re:VIEW 3 系のプロジェクトをそのまま利用しようとすると、./__REVIEW_BOOK__.tex:79: LaTeX Error: Missing \begin{document}. のようなエラーが発生する

後方互換性を提供するマクロに不備がありました (#1414)。

すべて更新してよければ、後述の review-update コマンドを使ってください。

既刊書などで 4.0 のマクロでの変化を避けたい場合には、以下の2行からなるマクロを review-custom.sty に追加してください。

\DeclareRobustCommand{\reviewincludegraphics}[2][]{%
  \includegraphics[#1]{#2}}
media=ebook を使うと、「! TeX capacity exceeded, sorry [input stack size=5000]」なるエラーになります

見出し内に @<code>@<tt> を使っており、かつハイパーリンクを有効にするとマクロの解決に失敗します。

次の内容を sty/review-custom.sty に記述することでエラーを回避できます(Re:VIEW 4.1 で反映予定です)。

\g@addto@macro\pdfstringdefPreHook{%
  \def\reviewbreakall#1{#1}}

既存プロジェクトのバージョンアップ追従

既存のプロジェクトを更新するには、Re:VIEW 4.0 をインストール後、プロジェクトフォルダ内で review-update コマンドを実行してください。

$ review-update
** review-update はプロジェクトを 4.0.0 に更新します **
config.yml: 'review_version' を '4.0' に更新しますか? [y]/n 
プロジェクト/sty/review-base.sty は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-4.0.0/templates/latex/review-jsbook/review-base.sty) で置き換えられます。本当に進めますか? [y]/n 
プロジェクト/sty/review-jsbook.cls は Re:VIEW バージョンのもの (/var/lib/gems/2.5.0/gems/review-4.0.0/templates/latex/review-jsbook/review-jsbook.cls) で置き換えられます。本当に進めますか? [y]/n 
完了しました。

続いて、リリースノートをベースに、新規に導入した機能や変更点について理由を挙げながら解説します。

新機能

IDGXML ファイルをまとめて生成する、review-idgxmlmaker を導入しました

maker を唯一用意していなかった InDesign 向けの IDGXML 形式ですが、このたびようやく導入しました。

review-idgxmlmaker [オプション] 設定yamlファイル

オプションは次の2つです。

  • -w : 版面の幅を mm 単位で指定します。表の幅の設計時に利用されます。

  • -f フィルタファイル: IDGXML データを加工するフィルタプログラムを指定します。フィルタは標準入力で IDGXML データを受け付け、標準出力に加工結果を戻すように作成しておく必要があります。ファイル名を知りたいときには、環境変数 REVIEW_FNAME が渡っているので、それを使うようにしてください。

review-textmaker は、imgmath パラメータが有効になっている場合に、数式を画像化するようになりました

HTML/EPUB 向けに提供していた TeX 数式の画像ファイル化ですが、textmaker でも利用できるようにしました。数式の画像ファイル化の詳細については、Re:VIEW フォーマットガイド を参照してください。

Re:VIEW で作るつもりではなくても、数式ファイルをまとめて作りたいという用途に便利です。

review-init に -w オプションを指定することで、Web ブラウザ上で TeX のレイアウトができるウィザードモードを用意しました

今から考えるとウィザードってなんか古い感じもするなという気もしますが、まぁウィンドウモードでもなんとでも考えていただければ。ともかく、LaTeX用の最初の版面設計をWebブラウザ上でできるようにしてみました。プロジェクトを作成するときに -w オプションを付けます。

review-init -w プロジェクト名

これで、デフォルトでは TCP 18000 ポートで Web サーバが起動するので、http://localhost:18000/ に接続することで版面設計ができます。あと、電子版用の config-ebook.yml も作ります。実装をがんばったので、褒め称えてもいいんですよ!!

_images/wizard.pngウィザードモード

ポート等を変更したいときには --port ポート番号--bind バインドアドレス を指定できます。Docker の場合には docker コマンドに -p 18000:18000 オプションを指定すれば、ホスト側の 18000 ポートに接続して同様に http://localhost:18000/ で開けるはずです。

現時点のバージョンではこの設定インターフェイスは「新規作成」のみで、「既存のプロジェクトに対する再設定」はできません。将来もっといろいろと Web ブラウザ上で設定ということになると、Node.js 等を利用した大掛かりなものになって、review.gem とは分離した形になるかもしれません。ただ、コメント付きの YAML ファイルの再設定を安全にこなすのは正直良い方法が思い浮かばないです。

実験的実装として、複数行から段落を結合する際に、前後の文字の種類に基づいて空白文字の挿入を行う機能を追加しました

もともとの Re:VIEW の仕様として、複数行で段落を表現している場合、テキストや IDGXML 等に変換したときには組版処理向けに「単純に結合」していたのですが、英語の文章だったりするとスペースが消えてしまい、うまくないことになります。

this is a
pen.
↓
this is apen.

前後を見て日本語なら入れないようにすればいいのでは? と単純に考えてしまいますが、日本語の文字とはという定義に始まり(たとえば句読点やパンクチュエーションなどの扱い)、そこに Re:VIEW 命令が来た場合にどうするかといったいろいろと頭の痛い問題があります。

Re:VIEW 公式のスタンスとしては、段落内のスペースを確実に表現したいのであれば「1行1段落にする」ことを推奨します。TeX の場合だと問題ないように見えるのですが、これは TeX のエンジンが文字カテゴリを判断して結合時に空白の挿入有無を決めてくれているからです。HTML や IDGXML、テキストなどほかの表現方式では、そういうエンジン側への委託はできません。

今回、実験的に Mozilla Firefox の行結合ロジックを少し改変し (Firefox のやり方だとちょっと空白が余分に入りすぎると思われるため)、実装してみました。この機能を利用するには、Unicode の文字カテゴリ判断をするための unicode-eaw gem をインストールした上で、config.yml に join_lines_by_lang: true を追加します。

非互換の変更

通常の利用では使われることがないので、review-init の実行時に空の layouts フォルダを作成するのをやめました

layouts/layout.html.erb や layouts/layout.tex.erb を置いて枠組みを変えることができるんですが、HTML のほうはあまり変えるようなものでもなく、TeX のほうは Re:VIEW 3 で設定が全部 TeX マクロ化されて枠組みのほうを変える必要はなくなっています。

ということで、普通使わない空フォルダがあっても仕方がないので、今回から review-init ではこのフォルダは作成しません。もちろん必要であれば、任意に layouts フォルダを作ってファイルを置き、枠組みを変えることは引き続き可能です。

PDFMaker: @<code>@<tt>@<tti>@<ttb> で空白文字が消えてしまう問題を修正しました。および利便性のために、文字列が版面からあふれるときに途中で改行するようにもしました

Re:VIEW 3 で LaTeX 変換した際にコード類を \texttt のようにベタに書くのではなく \reviewtt のように抽象化した名前をいったん経由するようにしたのですが、そうすると空白文字が消されてしまうという罠があるのでした。LaTeX 難しい。

@zr_tex8r さんからマクロの実装例をいただき、@<code>@<tt>@<tti>@<ttb> において、空白文字の保持および、版面からあふれそうになったら折り返すようになりました。

//texequation//embed//graph はもともとインライン命令を許容しないので、内容のエスケープもしないようにしました。また、末尾に余計な空行が加わるのも防ぐようにしました

記載のとおりです。非互換変更というよりは、これまでが不具合だったと言えるので、ある意味バグ修正ですね。

PDFMaker: コラム内での使用を考えて、表の配置のデフォルトを htp (指定位置→ページ上→独立ページの順に試行) から H (絶対に指定位置) にしました (review-style.sty の \floatplacement{table} の値)

後方互換性を考えて review-jsbook では表の位置を htp にしていたのですが、コラム等の囲み内で使えないのはやっぱり気付きにくくてよくないので、図と同様に H をデフォルトにしました。

プロジェクトの sty/review-style.sty で定義しているので、昔の状態に戻したければこのファイルを変更してください。

PDFMaker: コードリスト内では和文欧文間の空きを 1/4 文字ではなく 0 にするようにしました

review-jsbook・review-jlreq において和文・欧文間は 1/4 文字空きが入るのがデフォルト (xkanjiskip 設定) なのですが、コードリスト内だとこの空きが入ると半角スペースのように見えて気になるので、コードリスト内ではこの空きが入らないようにしました。

rsty/review-style.sty の \reviewlistxkanjiskip で定義している (\z@ で 0 にしている) ので、必要であればこの値を変更してください。

config.yml の目次を制御する toc パラメータの値は、これまで null (false、目次は作らない) でしたが、一般的な利用方法を鑑みて、デフォルトを true (目次を作る) に切り替えました

書籍を作る人は普通目次を入れるでしょうし、EPUB では目次はいらないというのが通説だったのですが、Kindle では物理目次必須ということで、true をデフォルトにするほうが妥当という判断です。

バグ修正

review-jlreq がタイプミスのために一部の jlreq.cls バージョンで正しく動作しないのを修正しました

jlreq.cls がまだムービングターゲットで、後方互換性をとるのがなかなか難しいのですが、Debian 10 に入っている jlreq.cls 20190115 バージョンは最低限サポートします。

re ファイルが改行コード CR で記述されたときに不正な結果になるのを修正しました

CR コードを使っているケースは少なめかもしれませんが、macOS のエディタ保存で生じることがあるようです。Ruby の IO クラスが改行コードまわりをうまくやってくれるので、簡単なパッチで済みました。

PDFMaker: review-jlreq において //cmd のブロックがページをまたいだときに文字色が黒になって見えなくなってしまうのを修正しました

tcolorbox マクロの設定をミスしていました。

PDFMaker: @<column> で「コラム」ラベルが重複して出力されるのを修正しました

なぜこれまで気付かなかったのか不思議ですね……。

PDFMaker: gentombow.sty と jsbook.cls は review-jsbook の場合のみコピーするようにしました

review-jlreq 向けの改善です。

PDFMaker: LuaLaTeX で review-jlreq を使ったときに壊れた PDFDocumentInformation ができる問題を修正しました

PDF メタ情報を入れるのに upLaTeX 向けには special マクロを使っていたのですが、LuaLaTeX ではこれがおかしな挙動につながってしまっていました。エラーにはならないし、evince などでもわからないのでしばらく苦戦しました。

結局 LuaLaTeX の場合は hyperref の hypersetup を使って記述することにしましたが、副作用として hyperref はクラスファイルパラメータで media=ebook のときしか読み込まないので、media=print のときだとメタ情報は入らないことになります。

PDFMaker: review-jlreq で偶数ページに隠しノンブルが入らなかったのを修正しました

隠しノンブルはトンボのバナー機能を流用して入れているのですが、review-jlreq のトンボを司る jlreq-trimmarks.sty の仕様が変わって奇数ページにしか入らなくなってしまったのが原因でした。

いささか泥縄的な対処で回避しています。将来的には #1397 で登録しているように jlreqtrimmarkssetup で置き換えるつもりではあります。

機能強化

IDGXML ビルダで @<em> および @<strong> をサポートしました

ビルダ間の統一が目的です。

PDFMaker: コードブロックの各行の処理を code_line, code_line_num のメソッドに切り出しました

リファクタリングの一貫です。これでコードブロック処理がだいぶ読みやすくなり、扱いやすくなりました。

PDFMaker: デフォルトのコンパイルオプションに -halt-on-error を追加しました。TeX のコンパイルエラーが発生したときに即終了することで問題が把握しやすくなります

これまでは TeX コンパイル時にエラーが出てもひとまず最後まで進んでしまっていたため、結局どこでエラーが出たのかを調べるのが大変でした。早期にエラー終了することで、メッセージを見て原因の追跡がこれまでよりも容易になると思います。

PDFMaker: コラム内に脚注 (@<fn>) があるときの挙動がコラムの実装手段によって異なり、番号がずれるなどの問題を起こすことがあるため、脚注の文章 (//footnote) はコラムの後に置くことを推奨します。コラム内に脚注文章が存在する場合は警告するようにしました

review-jsbook ではコラムに framed を使っているので顕在化しないのですが、review-jlreq、あるいはサードパーティのスタイルで tcolorbox のような囲みスタイルをコラムに適用している場合にこの問題が発生します。

Re:VIEW のデフォルト挙動では、コラム内かどうかにかかわらず脚注は本文から連続した番号を使いますが、脚注のテキスト部を tcolorbox を使ったコラムブロックの中に入れてしまうと、脚注番号がアルファベットa, b, c…の形になります。脚注番号3がcになる、というくらいであればまだ被害は少ないのですが、脚注番号が27以上になっていると、アルファベットzよりも大きくなるため、カウンタエラーになります。

そこで、コラム内に脚注テキスト部を発見したときに警告を出すようにしました。コラム脚注のテキスト部は、次のようにコラムを閉じた後ろに置くようにしてください。

===[column] コラム
文章@<fn>{c1}

//footnote[c1][コラム脚注] ←×

===[/column]

//footnote[c1][コラム脚注] ←○
YAML ファイルのエラーチェックを強化しました

YAMLに何もエントリがないときには捕捉できずにランタイムエラーを起こしてしまっていたのを、捕捉して妥当なエラーメッセージを出すようにしました。

そのほか、イレギュラーパターンへの対処として次のような変更もしています。

  • stylesheet パラメータで指定されたCSSファイルが存在しないときにランタイムエラーになっていたのを修正。

  • aut パラメータが空の場合に PDFMaker がエラーになるので、デフォルト値 ["anonymous"] を適用。

  • bookname パラメータのデフォルト値 を book に。

  • texstyle パラメータのデフォルト値を ["reviewmacro"] に。

  • stylesheet パラメータのデフォルト値を [] に。

Logger での表示時に標準の progrname を使うようにしました

ロガーへの出力にこれまでメッセージ出力側でプログラム名を入れていたのを、Logger 自体に任せるようになりました。

PDFMaker: 電子版の作成時に、表紙のページ番号を偶数とし、名前を「cover」にするようにしました

media=ebook で作成する電子版 PDF において、表紙のページ番号の名前が1、また奇数ページなので続く大扉(奇数)の前に白ページが入るというのがこれまでの挙動でした。

少々悩んだのですが、表紙を偶数ページ扱い(0ページ)として大扉との間に白ページが入らないようにし、また名前を「cover」にするように変更しました。

また、この挙動に合わせて \frontmatter の前に \covermatter というマクロを呼ぶようにしました。

名前は次のマクロで定義しています。

\def\@coverpagezero#1{cover}
PDFMaker: generate_pdf メソッドのリファクタリングを行いました

このメソッドでは YAML ファイルを引数に取っていたんですが、ロジックを追いかけてみたら依存関係を除去できそうだったのでリファクタリングしてみました。

これで @config パラメータ連想配列と @basedir だけで generate_pdf を呼び出せるようになったので、YAML ファイルなしでも (たとえば JSON のパースなどをして) PDF を作ることができるようになったわけです。Re:VIEW 公式のほうでは特段の必要性もないので変わらず YAML ファイルを使い続けますが、サードパーティの開発としては面白いこともできるのではないかと思います。

プロジェクトの新規作成時に登録除外ファイル一覧の .gitignore ファイルを置くようにしました

プロジェクトを全部 git add してコミット、というときに一時ファイルが追加されるのを防ぐための抑止ファイル .gitignore を review-init 時にプロジェクトに置くようにしました。

ドキュメント

sample-book の README.md を更新しました

サンプルファイルの sample-book, syntax-book はファイルの重複管理を避けるために rake のルールで Re:VIEW 本体から TeX スタイルファイルのコピーをするようにしています。そのため、 review-pdfmaker の直接呼び出しだとルールが実行されず、エラーになってしまいます。

サンプルファイルの実行については rake pdf のように rake 経由での呼び出しをするようドキュメントを変更しました。

通常のプロジェクトにおいても、直接 review-pdfmaker 等を実行するより rake を使ったほうが何かと利点があるのでお勧めします。

review-jsbook の README.md に jsbook.cls のオプションの説明を追加しました

review-jsbook がベースとしている jsbook.cls 自体のオプションおよび review-jsbook の場合のそれらのオプションの有効無効についての説明を加えました。

新規プロジェクトの sty/README.md にコピーされるので、参照してみてください。

その他

ほとんどは内部実装のリファクタリングです。つまり、普通のユーザーには影響しませんが、review-ext.rb で拡張・挙動変更をしている場合には影響が及んでいる可能性があります。

メソッド引数のコーディングルールを統一しました

引数があるときは原則としてカッコを付けるようにしました。

Catalog#{chaps,parts,predef,postdef,appendix} は String ではなく Array を返すようにしました

昔の設定ファイルに即したメソッドを、今の設定配列型に合わせたというところです。扱いとして妥当になりました。

YAML ファイルの読み込みに safe_load を使うようにしました

deprecatedなので。

table メソッドをリファクタリングし、ビルダ個々の処理を簡略化しました

表についてはビルダ間で似たようなことをそれぞれで必死に実装しているところがあり、見通しが悪いものになっていました。そこで、表の表現を Builder クラスで次の3つのメソッドに分けました。

  • table_begin: 表本体の始まり (LaTeX なら \begin{reviewtable}、HTML なら <table>)

  • table_rows: 表の各行 (中で tr→th/td と呼ぶ)

  • table_end: 表本体の終わり (LaTeX なら \end{reviewtable}、HTML なら </table>)

これにより、各ビルダは Builder クラスの table メソッドの呼び出しをほぼそのまま利用できます。たとえば HTML ビルダの table メソッドは以下のようにすっきりしました。

    def table(lines, id = nil, caption = nil)
      if id
        puts %Q(<div id="#{normalize_id(id)}" class="table">)
      else
        puts %Q(<div class="table">)
      end
      super(lines, id, caption)
      puts '</div>'
    end
XXX_headerXXX_body まわりをリファクタリングしました

上記の table もそうですが、これまでブロック命令を展開する XXX, XXX_header, XXX_body のメソッドの実装範囲がビルダごとに微妙に差異があり、共通化を妨げていました。XXX_header にキャプションのほかにブロック全体の囲みを表すものがあったりなかったりといった具合です。

命名に少し悩んだのですがあまり実装をいじらない範囲という方針を立てて、次のように役割分担をすることにしました。

  • XXX: ブロック命令自体。キャプション (XXX_header) およびボディ (XXX_body) の呼び出しと、ブロックのキャプションおよびボディを何かで囲むときにはそれを担う。

  • XXX_header: キャプションを出力する。

  • XXX_body: ボディ部を出力する。

擬似コードで表すと次のような構造になります。

def XXX(lines, caption = nil, ...)
  ブロック開始の文字列出力や処理

  XXX_header(caption)
  XXX_body(caption, lines, ...)

  ブロック終了の文字列出力や処理
end

def XXX_header(caption)
  キャプションの出力
end

def XXX_body(caption, lines, ...)
  ボディ部の出力
end
Builder#highlight? メソッドを HTMLBuilder 以外でも利用できるようにしました

HTML ビルダのみが持っていたハイライト利用可否の確認メソッドを共通化しました。といっても今のところ HTML ビルダと LaTeX ビルダ以外は false を返すのみですが。

mkchap* と mkpart* まわりをリファクタリングしました

Chapter や Part のコンストラクタを Book::Base から分けて見通しをよくしました。

Travis CI で rubygems を更新しないようにしました

テストが変になるようなので。

Index まわりをリファクタリングしました

ReVIEW::Book::Index から Item クラスまわりを分離しました。

samples フォルダのサンプルドキュメントに review-jlreq のための設定を追加しました

review-jlreq が壊れていないかのテストとして、samples フォルダの2つとも review-jlreq でテストできるようにしました (REVIEW_TEMPLATE=review-jlreq REVIEW_CONFIG_FILE=config-jlreq.yml rake pdf)。

用語リストは : の前にスペースを入れることを強く推奨するようにしました。スペースがない場合、警告されます

: を使った用語リスト箇条書きについては、地の文との区別のために行頭スペースを入れることを推奨します。将来的には、行頭にスペース文字なしで : が使われているときに警告なしに単に地の文にする可能性があります。

2018/11/17, 2018/11/30 by @kmuto

Re:VIEW 3 からの LaTeX 処理

Re:VIEW 3 で最も大きく変更した LaTeX まわりの処理について解説します。


Re:VIEW は定期的に機能向上のためのリリースを続けてきましたが、2018年11月30日にリリースしたメジャーバージョン改訂となる「Re:VIEW 3.0.0」では、特に LaTeX の対応について大きな変更を加えました。

同人誌の制作などで Re:VIEW が採用されることが増えてきたものの、印刷仕様を無視してそのまま印刷所に出してしまってトラブルになっていたり、場当たりの対策が一部に広まってしまったりなど、憂慮する事態を見聞きするようになっています。「目的のために十分な背景知識のある人が書き換えて利用する」という Re:VIEW ユーザーの当初の想定から、より一般化されて特に手軽な印刷入稿データ制作ツールとして普及している状況を鑑み、Re:VIEW+LaTeX で制作される PDF のデフォルトの設定を「印刷入稿に(おおむね)安全」となるように改訂しています。

過去との互換性

大きく変えるとはいえ、商業印刷用途に使うことも前提としている Re:VIEW では、過去との互換性を壊すことについては慎重に考えています。

config.yml パラメータの review_version2 (Re:VIEW 2 のプロジェクト)のときには、バージョン2のモードとして動作するようにし、できるだけ生成結果がこれまでと変わらないようにしています。

ですので、バージョン2モードでは、以下の内容のほとんどは当てはまりません。

バージョン2→バージョン3の更新は、review-update コマンドで実施できます。重要なプロジェクトの場合は慎重に更新し、生成結果に不都合な差異が発生していないか、再調整が必要かどうかを確認しましょう。

review-jsbook クラスファイルの導入

Re:VIEW 3 では、@munepixyz さんの尽力により、従来使われていた素の jsbook クラスファイルに代わり、それを機能拡張する review-jsbook クラスを導入しました。

config.yml でのデフォルトの設定は次のとおりです。

texdocumentclass: ["review-jsbook", "media=print,paper=a5"]

設定のほとんどは、TeX マクロを書かずとも "media=print,paper=a5" のところを調整するだけで済みます。たとえば電子配布用の PDF を作りたいなら次のようにします。

texdocumentclass: ["review-jsbook", "media=ebook,paper=a5"]

jsbook を使っていた既存のプロジェクトは、パラメータを含め、review-update コマンドで review-jsbook に移行できます。

メディア指定

media=<メディア> で出力形式を指定します。

print(デフォルト)の場合は印刷用の出力になります。「デジタルトンボ・トンボあり」「表紙なし」「ハイパーリンクなし」「隠しノンブル指定の場合は隠しノンブル配置」

ebook の場合は電子配布用の出力になります。「デジタルトンボ・トンボなし」「表紙あり」「ハイパーリンクあり」「隠しノンブルなし」

紙サイズ指定

paper=<紙サイズ> で仕上がりの紙サイズを指定します。一般的な同人誌制作であれば a5 または b5 になるでしょう。規定しているサイズは a3〜a6、b4〜b6(JIS 寸法)、a4var、b5var、letter、legal、executive です(そのまま jsbook に渡されます)。

変形判を使いたいときには、paperwidth=<横幅>,paperheight=<縦幅> を指定します(paperwidth=182mm,paperheight=235mm など)。ただし、paperwidthpaperheight を使った場合には、jsbook の自動設計に委ねられないため、版面設計オプションも必要です。

トンボ指定

media=print のときには、印刷のために、トンボおよびデジタルトンボが配置されます(gentombow.sty によって処理されます)。

トンボのオプションは2つあります。

  • tombopaper=<紙サイズ>(デフォルトはひとまわり大きな定型)

  • 塗り足し幅 bleed_margin=<幅>(デフォルトは 3mm)

紙サイズはデフォルトで paper 指定の紙サイズのひとまわり大きな定型サイズが選定されます。任意で、a0〜a10、b0〜b10(JIS 寸法)、c0〜c10、a4var、b5var、letter、executiveも指定できます。

トンボについて詳しくは、jsbook ベースのドキュメントにトンボおよびデジタルトンボを配置する を参照してください。

基本版面設計

デフォルトでは版面(本文領域)の設計は jsbook に委ねられますが、jsbook の見た目を変えたいという声はよく見聞きします。一般的な書籍紙面のデザイン手法と同じやり方で、版面設計をパラメータ指定できます。省略したパラメータの扱いは jsbook に委ねられます。

  • fontsize=<文字サイズ> - 基本の本文の文字サイズ(デフォルトは 10pt)

  • baselineskip=<行送り> - 基本の本文の行送り

  • line_length=<字詰> - 基本の本文の1行あたりの文字数

  • number_of_lines=<行数> - 基本の本文のページあたりの行数

  • head_space=<天> - 仕上がり上から版面までの幅

  • gutter=<ノド> - 仕上がり綴じ側から版面までの幅

_images/layout.png基本版面設計

fontsize の文字サイズは pt、Q、mm といった単位付きで指定できます。ただし、jsbook の挙動に合わせるため、8pt, 9pt, 10pt, 11pt, 12pt, 14pt, 17pt, 20pt, 21pt, 25pt, 30pt, 36pt, 43pt のいずれか近いサイズに丸められます(丸めが望ましくなければ、本文や見出しのサイズを review-custom.sty にマクロで指定する必要があります)。

line_length の字詰には単位が必要です。一般的な全角文字の文字数で表すなら、35zw(35文字ぶん)のように指定します。

どのように設計するかは、センスと経験が必要です。特に行間や天・地・ノド・小口の余白をあまり狭くすると、読みづらいものになりがちです。

その他、次のようなオプションパラメータもあります。

  • linegap=<幅> - baselineskip の代わりに、基本の本文の文字サイズに指定の幅を加算したものを行送りとする

  • headheight=<幅> - ヘッダ部の高さ

  • headsep=<幅> - ヘッダの下端と版面上端の間隔

  • footskip=<幅> - 版面下端とフッタ下端の間隔

ページ番号に関する調整

ページ番号の付け方には同人誌固有の状況があるため、調整のためのパラメータを設けました。

startpage=<ページ番号> で大扉からの開始ページ番号を指定できます(デフォルトは1)。たとえば 3(iii)ページからにしたければ、startpage=3 とします。

大扉からアラビア数字にしなければいけないという指定がある場合は、serial_pagination=true を指定します。これで、大扉がアラビア数字1(startpage で数値は変更可能)となり、書籍の最後までアラビア数字で通します。

さらに、同人誌印刷所によっては「隠しノンブル」を要求されることがあります。これは、製本確認のために、全面画像や白ページであっても通しのページ番号をノドなどに小さく隠して入れることを意味します。hiddenfolio パラメータで隠しノンブルの設置の有無を指定できます。なお、hiddenfolio パラメータは media=ebook のときには無視されます。

hiddenfolio パラメータの値は印刷所名のプリセットとして用意しています。塗り足しの調整も含めています。

  • hiddenfolio=default - ノド上部(トンボの外)にページ番号を小さく配置

  • hiddenfolio=nikko-pc - ノド中央にページ番号を小さく配置

  • hiddenfolio=marusho-ink - 塗り足し5mm、ほかは日光企画に同じ

  • hiddenfolio=shippo - ねこのしっぽ社用。設定は日光企画に同じ

_images/folio.pnghiddenfolio=nikko-pc での隠しノンブル

これ以外のものが必要であれば、review-jsbook.cls の \@namedef{@makehiddenfolio@…} といった箇所を参照し、このファイルに追加してください。

隠しノンブルのページ番号はアラビア数字で通す必要があるのが普通と思われるため、hiddenfolio を使うときには、serial_pagination=true も一緒に指定する必要があるでしょう。

表紙

印刷入稿のときには、表紙は背や裏表紙を含めたファイルとして、本文とは別に入稿するのが一般的です。そのため、media=print のときには表紙を付けないようにしています。表紙込みでの入稿 PDF を作成したいときには、cover=true を指定します。

texdocumentclass: ["review-jsbook", "media=print,paper=a5,cover=true"]

現実にあるかどうかはともかく、同様に電子版で表紙なしにしたいときには次のようにします。

texdocumentclass: ["review-jsbook", "media=ebook,paper=a5,cover=false"]

従来の Re:VIEW では、表紙に画像を指定している場合、その画像を紙面に合わせて拡縮していました。しかし、この方法では、「フチなしで仕上げるために、トンボ付きのときに塗り足し領域まで含めて配置する」といったページ全面を使うときの印刷の常道を利用できません。

そのため、Re:VIEW 3 では指定画像は原寸と見なし、そのまま中央合わせで貼り付けます。

_images/border2.png中央合わせ

既存の画像が原寸でない場合は、大きくはみ出してしまったり、あるいは小さくなってしまったりすることがあるため、適宜調整が必要です。対処方法は 電子版用の表紙の画像を指定しましたが、はみ出してしまいます(あるいは小さすぎてフチができてしまいます) を参照してください。

EPUB と TeX PDF で表紙画像を分けたいときには、config.yml で個別に指定できます。

coverimage: EPUB用の画像
 ...
pdfmaker:
  coverimage: TeX PDF用の画像
便利マクロ

いくつかの便利マクロも review-jsbook で提供しています。

表紙の中央配置でも使用しているのが、\includefullpagegraphics マクロです。

\includefullpagegraphics[オプション]{images/画像ファイル}

オプションは LaTeX の graphicx パッケージの \includegraphics と同じです。該当ページを白ページにして、中央合わせで全面に貼り付けます。挿絵などで利用するとよいでしょう。

#@# 挿絵を配置
//embed[latex]{
\includefullpagegraphics{images/sasie.pdf}
//}

印刷仕様に合わせた塗り足し付きの PDF を指定するのが最も妥当です。Illustrator AI ファイルも指定できますが、PDF 互換機能を有効にしたものであること、隠しレイヤーを使っていないことという条件が付きます。

ページを合わせるための空のページを作るマクロを用意しています。

  • \oneblankpage - 指定箇所で改ページし、白ページを1つ作って改ページする

  • \clearoddpage - 次のページが偶数ページになるように、必要なら改ページする(次のページが奇数ページになるようにするのは \cleardoublepage

//tsize で表の幅を明記する際に、セルの段落表現として既存の p(左寄せ・均等配置あり)のほかに L(左寄せ・均等配置なし)、C(中央寄せ)、R(右寄せ)を使えます。

//tsize[|latex||p{25mm}|L{25mm}|C{20mm}|R{15mm}|]
//table{
普通の左寄せ・均等あり   左寄せ・均等なし   中央寄せ    右寄せ
//}

review-jlreq クラスファイルの導入

review-jlreq.cls は、日本語組版処理の要件 の仕様に基づくクラスファイル jlreq.cls を Re:VIEW 向けに拡張したものです。

review-init --latex-template=review-jlreq プロジェクト名 とすると review-jlreq クラスを使用するプロジェクトが用意されます。

前述の review-jsbook のドキュメントクラスオプションはほぼ同じものが利用できます。

元となる jlreq.cls 自体がまだ開発段階であることやフォント設定等も必要なことから、review-jsbook と異なり、jlreq.cls はセットではインストールされません。別途 jlreq クラスファイルの GitHub から展開する(2018年11月時点では abenori_dev ブランチ推奨)などしてインストールする必要があります。

「開発段階」と書いたように、jlreq.cls および review-jlreq.cls は review-jsbook ほどの完成度はありません。LuaLaTeX 対応や紙面表現のカスタマイズ性など、jlreq.cls が jsbook に優れる点は多くあります。ただ、現時点では使用にあたっては TeX の十分な知識が必要であり、また「日本語組版処理の要件の実装」という性質上、要件から外れるような機能は対応されない(review-jlreq 側で対応できそうなものであれば可能性はありますが)ことに注意が必要です。

レイアウトファイルのマクロ化

従来の layout.tex.erb は、Ruby の埋め込みコード、Re:VIEW マクロと TeX マクロの紐付け、装飾、TeX コンパイラやスタイルの分岐など、あらゆるものが混在していました。内容を書き換えるのはわかりづらく、LuaLaTeX などのほかのモダンなコンパイラに変えたりするのも大きな苦難となります。

Re:VIEW 3 の layout.tex.erb は全面的に書き換えられました。Ruby の埋め込みコードが利用できることに変わりはありませんが、ほとんどの設定は TeX のマクロで表現されるようになります。そのため、TeX の知識は必要となるものの、値の判定・分岐や、後からの書き換えなどは以前よりもずっと容易です。

また、書籍におけるいくつかの文書構造の段階で割り込める「フック」のマクロも準備しており、ユーザーが任意に定義して挙動を調整できるようになっています。

layout.tex.erb の Ruby の埋め込みコード部分はプリアンブルの以下の箇所だけとなりました。

\documentclass[<%= @documentclassoption %>]{<%= @documentclass %>}
<%= latex_config %>
<%- if @config['texstyle'] -%>
<%-   [@config['texstyle']].flatten.each do |x| -%>
\usepackage{<%= x %>}
<%-   end -%>
<%- end -%>

\begin{document}

latex_config は、config.yml の内容を TeX マクロに変換する Re:VIEW の内部メソッドです。変換ルールは Re:VIEW の templates/latex/config.erb に記述されていますが、config.yml のうち TeX やメタ情報に関する設定内容を \review@〜 という名前のマクロで定義しています(通常は単純な文字列です)。

\begin{document} から書籍内容を構成するマクロ呼び出しが始まります。マクロは次の順序で(定義されていれば)呼ばれていきますが、実際の内容は sty/review-base.sty に定義されています。

  1. \reviewbegindocumenthook - 文書開始直後に実行するフック。デフォルトは空

  2. \reviewcoverpagecont - 表紙の配置処理

  3. \reviewfrontmatterhook - 前付直前のフック。デフォルトは章番号の消去と \frontmatter の呼び出し

  4. \reviewtitlepagecont - 大扉の配置処理

  5. \revieworiginaltitlepagecont - 原書大扉の配置処理

  6. \reviewcreditfilecont - 権利表記の配置処理

  7. \reviewprefacefiles - 前付(PREDEF)の TeX ファイル呼び出し

  8. \reviewtableofcontents - 目次の配置処理

  9. \reviewmainmatterhook - 本文直前のフック。デフォルトは章番号の装飾と \mainmatter の呼び出し

  10. \reviewchapterfiles - 本文(CHAPS)の TeX ファイル呼び出し

  11. \reviewappendixhook - 付録直前のフック。デフォルトは章番号の付録化と \reviewappendix(実体は \appendix)の呼び出し

  12. \reviewappendixfiles - 付録(APPENDIX)の TeX ファイル呼び出し

  13. \reviewbackmatterhook - 後付直前のフック。デフォルトは \backmatter の呼び出し

  14. \reviewpostdeffules - 後付(POSTDEF)の TeX ファイル呼び出し

  15. \reviewprintindex - 索引の配置処理

  16. \reviewadvfilepagecont - 広告ページの配置処理

  17. \reviewcolophonpagecont - 奥付の配置処理

  18. \reviewbackcovercont - 裏表紙の配置処理

  19. \reviewenddocumenthook - 文書終了直前に実行するフック。デフォルトは空

なお、プロジェクトの layouts フォルダに layout.tex.erb を置けば任意に書き換えられることに変わりはありません。TeX の挙動に悩んでしまうようであれば、埋め込み Ruby コード側で処理するようにしてもよいでしょう。

クラスファイルやスタイルファイルをプロジェクトにコピー

上記のマクロ化とあわせ、Re:VIEW バージョンが変わったときに生成結果が変わるということを防ぐため、Re:VIEW のクラスファイルやスタイルファイルはプロジェクトの sty フォルダにコピーするようにしました。

新しい Re:VIEW バージョンがリリースされ、望んでその更新に追従したいときには、プロジェクト内で review-update コマンドを実行すれば最新のものに更新されます。

review-init コマンド実行時にプロジェクトの sty フォルダには次のようなファイルが作成されます。

  • クラスファイル(*.cls。review-jsbook.cls や jsbook.cls など)

  • 支援スタイルファイル(gentombow.sty, istings.sty, jumoline.sty など)

  • reviewmacro.sty - 下記3ファイルを束ねるスタイルファイル

  • review-base.sty - Re:VIEW 固有マクロと TeX マクロとを結び付ける定義

  • review-style.sty - 主に見た目の設定

  • review-custom.sty - ユーザーが任意にマクロの定義などをする場所

どのファイルを書き換えても構いませんが、review-update コマンドで上書きされることがあるため、一般にはその対象外となる review-custom.sty で既存のマクロの置き換えなどをするのがよいでしょう(\renewcommand, \renewenvironment, \def などを使用)。

その他の LaTeX まわりの改良

一時生成ファイル名を変更

これまでレイアウトファイル layout.tex.erb をもとに一時生成ファイルは book.tex という名前にしていたのですが、これだとプロジェクトに book.re というファイルがあると失敗するという恥ずかしい不具合がありました。

そのため、__REVIEW_BOOK__.tex という新たな名前に置き換えています。フックなどで book.tex を書き換えていた場合には変更が必要です。

なお、__REVIEW_BOOK__.re というファイル名を使われるとまた同じ問題が発生しますが、良い子は真似をしないはずです!

コマンド名とコマンドオプションを明確に分離

Windows 環境などのために、config.yml における外部コマンド指定の texcommand, dvicommand, makeindex_command パラメータに空白文字を許容するようにしています。

この影響で、これらのパラメータ内にコマンドオプションも入れてしまうという横着はできなくなりました。texoptions, dvioptions, makeindex_options に正しく設定する必要があります。

@<m> 前後のスペースを除去

@<m> で数式の前後にスペースを入れていたのを止めました。スペースを入れなくても文字間のグルー(空き)は TeX が適切に判断しますし、スペースを入れてしまうと前後が句読点だったときに奇妙な空きができてしまいます。

なお、まだあまり知られていないようなのですが、Re:VIEW バージョン 2.4 から導入済みの @<m>$〜$ または @<m>|〜| という記法で、 内で } をエスケープせずにリテラルに利用できます。つまり、@<m>{\frac{1\}{2\}} とせずに @<m>$\frac{1}{2}$ という書き方ができます。@<m> に限らず任意のインライン命令でこの記法は利用可能です。

正常動作時のログメッセージの非表示

従来のバージョンでは PDFMaker 実行時にどばっと TeX コンパイラからのコンパイルログが出ていましたが、正常動作時にはログを出さないようにしました。

また、エラーが起きたときにそこで止まってユーザーの判断を待つのではなく(プロンプトを出したところで解決はできず意味がない)、そのまま終了にするモードをデフォルト設定としました。

エラーのときにはログが出ますが、このログから原因がいまいちわかりにくいというのは LaTeX の仕様もあり、Re:VIEW 側ではどうにもならないところではあります。PDFMaker の --debug フラグまたは config.yml の debug: true でデバッグモードにして、保持される一時フォルダ(book-pdf など)の中身を追う必要があるかもしれません。

インライン装飾の抽象化

たとえば @<b> から \textbf のように直接に LaTeX の装飾表現マクロに変換するのではなく、@<b>\reviewbold とし、\reviewbold\textbf のデフォルトの紐付けは sty/review-base.sty で行うようにしました。装飾表現は、以下の抽象化されたマクロ名となります。

  • \reviewkw, \reviewami, \reviewem, \reviewstrong, \reviewballoon, \reviewunderline, \reviewit, \reviewbold, \reviewcode, \reviewtt, \reviewtti, \reviewttb

sty/review-custom.sty で \renewcommand を使って任意のものに置き換えることができます。

コードリストの変更

//emlist//list などから変換されるコード類を、\begin{reviewlistblock}\end{reviewlistblock} 環境で囲むようにしました。任意の前後空きの調整に使うことを想定していますが、デフォルトのスタイルではこの環境自体は何もしません。

また、コードハイライタとして入手やライセンスが不明瞭だった jlistings ではなく、plistings パッケージを採用しています。

表紙と大扉の設定の分離

config.yml には cover(表紙)と titlepage(大扉)のパラメータがありますが、従来のバージョンでは独立しておらず、titlepage を null にすると表紙も出なくなる、という問題がありました。

従来バージョンと非互換の変更ではありますが、普通に考えるとこの仕様のほうが妥当でしょう。

note などの囲み要素の個別環境化

//note//caution などに対し、従来はすべて reviewminicolumn という環境マクロに割り当てていましたが、個別の環境を用意してそれらに割り当てるようになりました。

  • reviewnote, reviewmemo, reviewtip, reviewinfo, reviewwarning, reviewimportant, reviewcaution, reviewnotice

ただし、sty/review-base.sty のデフォルトでは、いずれも reviewminicolumn を使うだけの設定になっています。必要に応じて固有の内容に置き換える必要があります。

ハイパーリンク有効時の装飾

ドキュメントクラスファイルオプションで media=ebook としたときには相互参照やURLインクなどがハイパーリンク化されますが、従来はデフォルトで色囲み付きになっていました。

Re:VIEW 3 ではデフォルトで一切の装飾なしにしています。これは sty/review-style.sty の以下の設定に基づきます。

\hypersetup{hidelinks}

必要なら sty/review-custom.sty で再度 \hypersetup を使って変更も可能です。

dvi ウェア実行のスキップ対応

review-jsbook, review-jlreq ともに現時点では upLaTeX コンパイラの使用を前提としています。しかし、レイアウトファイルの項でも述べたとおり、(クラスファイルやスタイルファイルなども変更する前提ですが)ユーザーの判断で LuaLaTeX などの別のコンパイラを使用可能にすることは Re:VIEW 3 で対応したい機能の1つでした。

upLaTeX では PDF を生成するのに dvi ウェア(通常 dvipdfmx)を必要としますが、LuaLaTeX のように PDF を自前で生成できる場合には、dvicommand: null とすれば dvi ウェアの呼び出しをスキップできるようにしました。

Re:VIEW が内包する TeX のコンパイル〜PDF 生成の外部コマンド呼び出し実装はあまり満足のいくものではないため、今後は llmk などのルールベースの外部ツールに委ねていく可能性があります。

図表の配置指定

//image//table で作成される図表をその場に置くのかフロートで移動するのを許容するのかを変更するのに、従来は review-ext.rb で挙動を書き換える必要がありましたが、\floatplacement マクロで定義できるようにしました。デフォルトは sty/review-style.sty で以下のように設定しています。

\floatplacement{figure}{H}
\floatplacement{table}{htp}
式キャプションと参照

//texequation//texequation[ID][キャプション]{ //} の記法を追加しました。ID とキャプションを指定すると、式番号が付き、「式1.1 キャプション」のように展開されます。参照するには @<eq>{ID} あるいは @<eq>{章|ID} です。

キャプション+式は reviewequationblock 環境で囲まれます。デフォルトはあまり綺麗な見た目とは言い難いので、適宜置き換えるとよいでしょう。

この式番号表現は、式の横に「(1)」のように入れる TeX の標準の式番号表現方法とは異なることに注意してください。TeX の式番号表現を使いたいときには、review-ext.rb で //texequation 命令を書き換えるか、あるいはそもそも TeX で原稿を作ることを検討しましょう。

部の中の見出し

従来は部の中で下位の見出しを許容していなかったため、下位見出しを使うとレベルにかかわらず新たな部見出しとなってしまっていました。Re:VIEW 3 では下位見出しを使ったときに「I.1」のようになるようにしました。

これは部の場合には内容を reviewpart 環境で囲むことで対処しています。

おわりに

Re:VIEW 3 では、前提知識がなくても印刷入稿における最低限の安全を確保すべく改良をしました。実際の入稿においては印刷所の入稿仕様をよく読み込むなど、さらに注意が必要ですが、少しでも入稿事故が防がれ、良い本が作られればと思います。ご安全に!

review-ext.rb による拡張

2018/7/30, 2020/12/20 by @kmuto

Re:VIEW のモンキーパッチによる拡張の基本

review-ext.rb をプロジェクトに置くことで、Re:VIEW のロジックを上書きできます。新しい命令を追加したり、既存の命令の挙動を変更したりするのに使えます。


review-ext.rb

プロジェクトに review-ext.rb という名前のファイルを置くと、review-pdfmaker などの Re:VIEW の各コマンドの実行時にこのファイルが取り込まれ、Re:VIEW 自身が書き換えられます(モンキーパッチと呼びます)。

使いすぎに注意する必要はありますが、独自の新しい命令を追加したり、既存の命令で不都合に思われる挙動を変更したりできます。

review-ext.rb は Re:VIEW の Ruby ロジックを書き換える都合上、当然ながら Ruby のプログラムファイルです。基本構造は次のとおりです。

module ReVIEW
  module BuilderOverride
    # 「Builder」のメソッドへの上書き・追加など
  end

  class Builder
    prepend BuilderOverride  # これでBuilderに上書きが反映される
  end
end

最初の module ReVIEW と最後の end で全体を囲みます。

この中には module BuilderOverrideend と、class Builderend の 2 つのブロックがあります。

前者が上書き用の定義で、後者が既存のビルダクラスに適用するための定型の記述です。BuilderOverride という名前はわかりやすさのためにこうしていますが、実際に使用するときにはほかの既存の名前と競合しなければ任意の名前でかまいません。

ビルダとは、原稿ファイル(.re)から変換するルールおよび手続きを定義したクラスです。Re:VIEW がサポートする変換形式に合わせて、代表としては以下のものがあります。

  • Builder(builder.rb):以下の各ビルダの基底クラス。主に全ビルダに新規の命令を追加したいときにこれを拡張することになるでしょう。

  • IndexBuilder (indexbuilder.rb) :Re:VIEW 5.0 から導入されたクラスで、実際の各ビルダに通す前に図表などの番号の管理を行うクラス。

  • HTMLBuilder(htmlbuilder.rb):epubmaker や webmaker で使っている HTML 変換のビルダクラス。

  • LATEXBuilder(latexbuilder.rb):pdfmaker で使っている LaTeX 変換のビルダクラス。

  • IDGXMLBuilder(idgxmlbuilder.rb):InDesign XML 変換のビルダクラス。

  • TOPBuilder(topbuilder.rb):textmaker で使っている装飾付きプレインテキスト変換のビルダクラス。

  • PLAINTEXTBuilder(plaintextbuilder.rb):textmaker で使っている装飾なしプレインテキスト変換のビルダクラス。

各ビルダのクラス定義ファイルは、Re:VIEW ソースの lib/review/ にあります。

ここでは全ビルダの基底クラスである BuilderBuilderOverride の定義内容で上書きする、ということになります(Ruby の prepend 命令が実際の上書きの調整をします)。

警告! 警告!

Re:VIEW の内部ロジックはメジャーバージョンはもとより、マイナーバージョンでも頻繁に変更されています。

review-ext.rb で Re:VIEW のロジックを書き換える場合、書き換えた Re:VIEW バージョンに束縛されることに注意してください。別の Re:VIEW バージョンに移行したときには、review-ext.rb にも修正が必要となる可能性が高いと考えてください。

既存の命令の書き換え(インライン命令)

インライン命令の書き換えは容易です。同名のメソッドおよび同じ数の引数で定義し直すだけです。インライン命令のメソッドは文字列を返すようにします。ビルダにおいて、インライン命令のメソッド名は inline_ から始まります。

HTML/EPUB での脚注参照記号は「*番号」ですが、これを変更してみます。HTMLBuilder では以下のようになっています。

★本当はこれはi18n.ymlの仕事にすべき?

   def inline_fn(id)
      if @book.config['epubversion'].to_i == 3
        %Q(<a id="fnb-#{normalize_id(id)}" href="#fn-#{normalize_id(id)}" class="noteref" epub:type="noteref">*#{@chapter.footnote(id).number}</a>)
      else
        %Q(<a id="fnb-#{normalize_id(id)}" href="#fn-#{normalize_id(id)}" class="noteref">*#{@chapter.footnote(id).number}</a>)
      end
    rescue KeyError
      error "unknown footnote: #{id}"
    end

<†番号>」になるように変更してみます。review-ext.rb を以下のように書きます。

module ReVIEW
  module HTMLBuilderOverride
    def inline_fn(id)
      if @book.config['epubversion'].to_i == 3
        %Q(<a id="fnb-#{normalize_id(id)}" href="#fn-#{normalize_id(id)}" class="noteref" epub:type="noteref">&lt;†#{@chapter.footnote(id).number}&gt;</a>)
      else
        %Q(<a id="fnb-#{normalize_id(id)}" href="#fn-#{normalize_id(id)}" class="noteref">&lt;†#{@chapter.footnote(id).number}&gt;</a>)
      end
    rescue KeyError
      error "unknown footnote: #{id}"
    end
  end

  class HTMLBuilder
    prepend HTMLBuilderOverride
  end
end

元々のメソッドの挙動を呼び出したいときには、super メソッドを使います。文字列が返ってくるので、必要に応じて加工し、また文字列を返すようにします。上記のコードを単純な文字列置換に変えてみた例を示します。

module ReVIEW
  module HTMLBuilderOverride
    def inline_fn(id)
      super(id).sub('>*', '>&lt;†').sub('</a>', '&gt;\&')
    end
  end

  class HTMLBuilder
    prepend HTMLBuilderOverride
  end
end

既存の命令の書き換え(ブロック命令)

ブロック命令の書き換えも、同名のメソッドおよび同じ数の引数で定義し直すだけです。//footnote 命令側の脚注記号も変えてみましょう。HTMLBuilder での実装は以下のようになっています。

    def footnote(id, str)
      if @book.config['epubversion'].to_i == 3
        puts %Q(<div class="footnote" epub:type="footnote" id="fn-#{normalize_id(id)}"><p class="footnote">[*#{@chapter.footnote(id).number}] #{compile_inline(str)}</p></div>)
      else
        puts %Q(<div class="footnote" id="fn-#{normalize_id(id)}"><p class="footnote">[<a href="#fnb-#{normalize_id(id)}">*#{@chapter.footnote(id).number}</a>] #{compile_inline(str)}</p></div>)
      end
    end

先ほどの review-ext.rb に上書きのメソッドを追加します。

module ReVIEW
  module HTMLBuilderOverride
    def inline_fn(id)
      if @book.config['epubversion'].to_i == 3
        %Q(<a id="fnb-#{normalize_id(id)}" href="#fn-#{normalize_id(id)}" class="noteref" epub:type="noteref">&lt;†#{@chapter.footnote(id).number}&gt;</a>)
      else
        %Q(<a id="fnb-#{normalize_id(id)}" href="#fn-#{normalize_id(id)}" class="noteref">&lt;†#{@chapter.footnote(id).number}&gt;</a>)
      end
    rescue KeyError
      error "unknown footnote: #{id}"
    end

    def footnote(id, str)
      if @book.config['epubversion'].to_i == 3
        puts %Q(<div class="footnote" epub:type="footnote" id="fn-#{normalize_id(id)}"><p class="footnote">&lt;†#{@chapter.footnote(id).number}&gt; #{compile_inline(str)}</p></div>)
      else
        puts %Q(<div class="footnote" id="fn-#{normalize_id(id)}"><p class="footnote">&lt;<a href="#fnb-#{normalize_id(id)}">†#{@chapter.footnote(id).number}</a>&gt; #{compile_inline(str)}</p></div>)
      end
    end
  end

  class HTMLBuilder
    prepend HTMLBuilderOverride
  end
end

インライン命令と異なり、ブロック命令では戻り値はなく、puts(改行あり)またはprint(改行なし)メソッドを使って結果を直接に出力します……正確に言うと、デフォルトの puts/print メソッドを書き換えて、StringIO クラスの @output というオブジェクト(擬似的にファイルのように見せたオブジェクト)に追加書き出しをしています。

このため、super メソッドで元々のメソッドの挙動を呼び出して結果を受け取る、ということが困難です。一般的な書き方としては、super メソッドを使わず、元々のメソッドを丸ごとコピーして必要な箇所を書き換える、ということになるでしょう。

初期化の追加

各ビルダでは、変換前に builder_init_file という初期化メソッドが最初に呼び出されます。何らかのフラグやカウンタを追加したり、ネットワークやデータベース、ローカルファイルからデータを読み込んだりといった処理をしたいときには、この初期化メソッドに処理を追加します。

LaTeX で初出の @<img> 参照箇所は太字にする(最初に「図1.1」という参照が出たところを太字にし、以降は「図1.1」と出ても地のままにする)という例を示します。

module ReVIEW
  module LATEXBuilderOverride
    def builder_init_file
      super
      @img_used = {}
    end

    def inline_img(id)
      s = super(id)
      if @img_used[id]
        s
      else
        @img_used[id] = true
        "{\\bfseries\\sffamily #{s}}"
      end
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

1点注意として、review-epubmaker や review-pdfmaker などのコマンド内では、各章(re ファイル)について毎回ビルダが呼ばれます。ネットワークからデータセットをダウンロードするといったケースでは、ダウンロード済みかどうかを判定するロジックを入れたり、初期化側ではなく maker の提供するフック(フックで LaTeX 処理に割り込む を参照)で事前ダウンロードをするようにしたりといった対処が必要になるかもしれません。

結果全体の書き換え

LaTeX 変換のデフォルトで使われる upLaTeX コンパイラは UTF-8 に対応していますが、UTF-8 のすべての文字が使えるというわけではありません。たとえば絵文字の領域は利用できないので、文中の「🍣」(Ux1f363、寿司)は変換すると空白文字の扱いになってしまいます。

手軽な対策として、🍣に対応する画像ファイルを用意しておき、変換時にこれを使うように置換することを考えます。

各ビルダの変換の最終結果の文字列は、result メソッドの返り値が書き出されます。たとえば builder.rb では以下のように定義されています。

    def result
      solve_nest(@output.string)
    end

LATEXBuilder もこれをそのまま継承しています(HTMLBuilderIDGXMLBuilder はもう少し追加の処理をしています)。@output はブロック命令でも言及した StringIO クラスのオブジェクトで、ビルダ内で puts あるいは print で吐き出した結果文字列がここに蓄積されています。string メソッドで全文字列を取り出し、最終結果として返します。

この最終結果に画像化のための置換工程を1つ加えます。

module ReVIEW
  module LATEXBuilderOverride
    def result
      super.gsub('🍣', '\includegraphics[width=1zw]{images/1f363.pdf}')
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

命令の追加(インライン命令)

インライン命令を新たに追加するには、Compiler クラスの definline メソッドを使って宣言します。たとえば Builderkaibun という文字列を逆転させるインライン命令を追加してみましょう。

module ReVIEW
  module BuilderOverride
    Compiler.definline :kaibun

    def inline_kaibun(s)
      s.reverse
    end
  end

  class Builder
    prepend BuilderOverride
  end
end

これで、@<kaibun>{あいうえお} のように re ファイルに記述すると、「おえういあ」と表現されます。全ビルダに共通する命令を追加したいときには、基底となる Builder に追加する必要があります。

インライン命令は1つの文字列を引数に取ります。kwruby のような引数を複数取っているように見える命令を実現するには、メソッドの実装ロジック内で引数の文字列を自前で分解し、解釈する必要があります。

命令の追加(ブロック命令)

ブロック命令の追加も Compiler クラスのメソッドを使って宣言しますが、ブロックのコンテンツ({ //})を取るかどうかで使うメソッドが異なります。

  • コンテンツを取る:defblock メソッド

  • コンテンツを取らない:defsingle メソッド(footnote など)

宣言記法は以下のとおりです。

Compiler.defblock :命令名, オプション数 [, ブロックなし許容]
Compiler.defsingle :命令名, オプション数

オプション数に、ブロック命令が取るパラメータ([ ] で記述するもの)の数を指定します。何も取らないなら 0、1つ取るなら 1、あるいは0〜2個まで取る可能性があるなら 0..2 のように可変長の数も指定できます。

defblock では、「ブロックなし許容」のところに true を指定すると、ブロックコンテンツ({ //})を省略することもできるようになります。デフォルトは false で、ほとんどのブロック命令ではブロックコンテンツを取ることが要求されています。

HTMLBuildermarquee というブロック命令を追加してみます。この命令は HTML の marquee タグに展開されます。0 または 1 つのオプションを取り、オプションが指定されたらそのまま behavior 属性に渡すようにします。

module ReVIEW
  module IndexBuilderOverride
    Compiler.defblock :marquee, 0..1

    def marquee(lines, behavior=nil)
      # nil
    end
  end

  class IndexBuilder
    prepend IndexBuilderOverride
  end

  module HTMLBuilderOverride
    Compiler.defblock :marquee, 0..1

    def marquee(lines, behavior=nil)
     opt = ''
     opt = %Q( behavior="#{behavior}")
     puts "<marquee#{opt}>#{split_paragraph(lines).join("\n")}</marquee>"
    end
  end

  class HTMLBuilder
    prepend HTMLBuilderOverride
  end
end

Re:VIEW 5.0 以降において、あるビルダ向けに命令を新設したときには、中身は適当でよいので IndexBuilder、または全ビルダの基底クラスである Builder にも定義が必要です。上記では IndexBuilder に追加しました。

ブロック命令の実装用メソッド(ここでは marquee)の1つめの引数にブロックコンテンツが渡されます。split_paragraph はコンテンツを空行を段落の区切りと見なして段落に分割するメソッドです。

以下のように re ファイルに書いて rake web を実行して結果を見てみましょう(超ウザいですね!!)。

//marquee{
たのしい!

たのしい!
//}

//marquee[alternate]{
たのしい!

たのしい!
//}

その他の拡張

より高度な命令を作りたいという場合には、Re:VIEW の完全なコードリーディングが必要になるでしょう。いくつかのヒントを提示しておきます。

  • 相互参照可能なカウンタを持つブロック要素を追加したい:Index クラスを継承したカウンタの定義や、初期化ロジックへの追加、参照インライン命令での他章参照時の処理など、広範囲での作業が必要です。また、カウンタ収集時のロジックの理由で、ブロック命令の名前の始まが既存のブロック命令の始まりと重ならないようにする必要があります(たとえば image2 といった名前だと既存の image にカウンタ収集を奪われて動作しない)。imagelist の実装を追跡してみてください。

  • コラムのようなパターンを追加したい:これは実は簡単で、XX_begin(level, label, caption)XX_end(level) の対となるメソッドを定義しておけば、==[XX] の新たな見出し記法ができあがります。

  • 「1.」や「*」のような箇条書きを追加したい:ビルダではなく、コンパイラ(Compiler クラスの do_compile メソッド)を書き換える必要があります。フックのような後処理で対応したほうが妥当かもしれません。

2018/7/30 by @kmuto

@<bidx> などの装飾表示と索引を併せ持つインライン命令を追加する

太字出力+索引語とする @<bidx> などのインライン命令を追加します。


Re:VIEW の索引用命令としては @<hidx>{語句}@<idx>{語句} の2つを用意しています。前者は「語句」を単に索引に登録します(なお、pdfmaker 以外は、独自に後処理を加えない限り索引は機能しません)。これに対し、後者は索引に登録しつつ、紙面にも表示します。

@<hidx>{α}と@<idx>{β}
  ↓ これを変換すると……
とβ

索引
α  1
β  1

実装者としては「idx」というのはあまり名前がよくなかったな、と反省があるのですが、意外と便利に使っている方もいらっしゃるようです。

ただ、Re:VIEW は現状ではインライン命令を入れ子にすることはできないため、@<b>{語句} などの装飾された語句に対して @<idx> を使うことはできず、@<b>{語句} の前なり後なりに別途 @<hidx>{語句} を置く必要があります。

× @<b>{@<idx>{太字語句}}
○ @<hidx>{太字語句}@<b>{太字語句}

そこで、@<bidx>{太字語句} で上記相当を実現できるようにしてみます。ついでに @<iidx>@<ttidx> も追加してしまいましょう(……といったように装飾の数だけ増えてしまう上にわかりにくいので、ちょっと Re:VIEW のコアには入れづらいのでした)。

review-ext.rb は次のようになります。

module ReVIEW
  module BuilderOverride
    # bidx, iidx, ttidx 命令を追加
    Compiler.definline :bidx
    Compiler.definline :iidx
    Compiler.definline :ttidx

    def inline_bidx(s)
      inline_hidx(s) + inline_b(s)
    end

    def inline_iidx(s)
      inline_hidx(s) + inline_i(s)
    end

    def inline_ttidx(s)
      inline_hidx(s) + inline_tt(s)
    end
  end

  class Builder
    prepend BuilderOverride
  end
end

これで、どのビルダにも適用される @<bidx>@<iidx>@<ttidx> ができました。

@<bidx>{BOLD}, @<iidx>{ITALIC}, @<ttidx>{TYPEWRITER}
 ↓ LaTeX変換
\index{BOLD}\reviewbold{BOLD}, \index{ITALIC}\reviewit{ITALIC}, \index{TYPEWRITER}\reviewtt{TYPEWRITER}

なお、基本的にはこのように索引登録が前、表示語句が後の順序にするのが適切です。さもないと、表示語句の途中でページが変わった場合、索引の参照先が分断された後ろ側のページになってしまうからです(Re:VIEW 3.0.0preview1 時点ではこれが逆になっているので、適切なほうに修正するか考え中です)。

ただし段落開始直後の場合は、表示語句が前、索引登録が後の順序のほうが安全です。その段落がページの先頭に配置される場合、索引の参照先が1つ前のページに置かれてしまう可能性があります。

2018/12/15 by @kmuto

コードリストブロック内でファイルの取り込みやコマンド実行を動的に行う

list や cmd などのコードリストブロック内で、Re:VIEW 変換時にファイルを読み込んだり実行結果を取り込んだりするようにしてみます。


Re:VIEW には、別ファイルの内容を取り込んだり外部コマンドの実行結果を取り込んだりする「preproc」という機能がもともと用意されています。

ただ、これは Re:VIEW 変換(review-pdfmaker, review-epubmaker, review-compile など)時に動的に行われるものではなく、その名のとおりプリプロセスとして re ファイルを書き換えるものです。

より動的に、Re:VIEW 変換をしたタイミングで別のファイルを読み込む、外部コマンドの実行結果を取り込むことを実現するために、review-ext.rb でコードリスト処理に割り込む例を示します。

注意

何かを動的に読み込む・実行するということは、制作環境を束縛することになります。たとえば商業出版物の原稿にこの機能を利用してしまうと、その原稿を受け取った編集者ほか制作関係者も執筆環境と同一の環境を用意しないと一貫性を取れなくなってしまいます。

あくまでも本人あるいはグループで閉じた環境で利用する程度に留めたほうがよいでしょう。

方針

説明を簡潔にするために、以下のような方針とします。

  • LaTeX ビルダ(pdfmaker)と HTML ビルダ(epubmaker/webmaker)のみに対処

  • コードハイライト(highlight パラメータ)機能を使わない前提

  • LaTeX ビルダではすべてのコードリストブロックに対処するが、HTML ビルダでは listnum, emlistnum は対処しない(これらの実装が現時点でイマイチなため(★#1231))

コードリストブロック内で使える擬似命令は次のような記法とします。

  • !!load ファイルパス:指定のファイルの内容を取り込む。文字エンコーディングは UTF-8、改行コードは re ファイルと同一であること

  • !!exec コマンドライン...:指定のコマンドラインを実行し、標準出力を取り込む。出力の文字エンコーディングは UTF-8、改行コードは re ファイルと同一であること

たとえば次のように書きます。

//list[test1][test1.js]{
!!load samples/test1.js
//}

//cmd{
# テスト1の実行
!!exec node samples/test1.js
# テスト2の実行
!!exec node samples/test2.js
//}

!!load または !!exec から始まっていない行は普通のコードリストとしてそのまま出力されます。

review-ext.rb の作成

LaTeX ビルダでは common_code_block メソッドにコードリストブロックのコード部処理が集約されているので、この処理に割り込むだけで済みます。内容はエスケープ済みの文字列配列になっているので、一度アンエスケープして擬似命令を探し、またエスケープするというだけです。

HTML ビルダでは HTMLUtils モジュールの highlight メソッドがコード部処理です。同様にアンエスケープして擬似命令を探し、またエスケープに戻します。

module ReVIEW
  # list系環境内で
  #
  #  !!load 内容を取り込みたいファイルパス
  #  !!exec 標準出力を取り込みたい実行命令
  #
  # というディレクティブを使えるようにする
  module LATEXBuilderOverride
    def common_code_block(id, lines, command, caption, _lang)
      lines2 = []
      lines.each do |l|
        if l =~ /\A!!(load|exec)\s+/
          method = $1
          arg = unescape($'.chomp)
          if method == 'load'
            error "no such file: #{arg}" unless File.exist?(arg)
            lines2 += File.readlines(arg).map {|s| escape(s) }
          else # exec
            out, status = Open3.capture2e(arg)
            error "failed to run command: #{arg}\n#{out}" unless status.success?
            lines2 += out.split("\n").map {|s| escape(s) }
          end
        else
          lines2.push(l)
        end
      end

      super(id, lines2, command, caption, _lang)
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end

  module HTMLUtilsOverride
    # XXX:listnum, emlistnum はだいぶ変えないとダメ

    def highlight(ops)
      lines2 = []
      ops[:body].split("\n").each do |l|
        if l =~ /\A!!(load|exec)\s+/
          method = $1
          arg = unescape($'.chomp)
          if method == 'load'
            error "no such file: #{arg}" unless File.exist?(arg)
            lines2 += File.readlines(arg).map {|s| escape(s) }
          else # exec
            out, status = Open3.capture2e(arg)
            error "failed to run command: #{arg}\n#{out}" unless status.success?
            lines2 += out.split("\n").map {|s| escape(s) }
          end
        else
          lines2.push(l)
        end
      end

      ops[:body] = lines2.join("\n")
      super(ops)
    end
  end

  class HTMLBuilder
    prepend HTMLUtilsOverride
  end
end

samples/test1.jssamples/test2.js を用意して、先の例を実行してみます。

_images/list-exec.png擬似命令の実行

うまくできましたね。

LaTeX ビルダでハイライト有効の場合に対応するには、common_code_block_lst メソッドに割り込む必要があります。練習問題として挑戦してみるとよいでしょう。

2020/1/5, 2020/10/29 by @kmuto

複雑な箇条書きの入れ子に対応する

数字箇条書きの入れ子や、箇条書き内に図表やコードリストを入れるなど、複雑な入れ子に対処します。


Re:VIEW 5 以降の話

箇条書きの途中で //beginchild//endchild で入れ子にしたい範囲を囲むことで、入れ子箇条書きを構成できます。よって、以降の話については特に読み進める必要はありませんが、記法と手段としてはおおむね類似しているので、参考にはなるかもしれません。

Re:VIEW 4 以前の話

Re:VIEW の箇条書き命令にはいわゆるナカグロ箇条書き(*)、番号箇条書き(1.〜)、説明箇条書き(:)がありますが、***** を指定できるナカグロ箇条書き以外は、その中に子の箇条書きを入れることができません。ナカグロ箇条書きにおいても、その中に番号箇条書きを子として持つということはできませんし、図表やコードリスト、複数の段落といったものを子に抱えることもできません。

Re:VIEW の記法を壊さずに、入れ子を綺麗に表現するというのは困難です。とはいえ、実際の執筆や翻訳においてはどうしてもこのような表現が必要になることもあります。

ここでは入れ子構造のヒントを人間が指定することで、入れ子表現を可能にする手法を示します。

#現状ではだいぶ汚いのと、命令を誤って記述したときに特に TeX の場合は不明瞭なエラーしか出せないという問題があり、Re:VIEW の公式の機能としてはまだ導入しづらい状態です。

child 命令の導入

人間がヒントを与えるために、//child という単一ブロック命令を導入します。この命令の書式は以下のとおりです。

  • //child[ul]//child[/ul]:この範囲は、直前のナカグロ箇条書きの子となる

  • //child[ol]//child[/ol]:この範囲は、直前の番号箇条書きの子となる

  • //child[dl]//child[/dl]:この範囲は、直前の説明箇条書きの子となる

HTML タグと同じ名前なので、これ自体は混乱はないでしょう。

Re:VIEW 原稿に入れると以下のようになります。対応関係さえできていれば、入れ子を重ねても問題ありません(ただ、箇条書きの入れ子の深さの限界についてはブラウザや LaTeX など処理系に依存します)。

 1. 
 2. 

//child[ol]

 1. 

//child[ol]

 1. 
 2. 

 * 
 * 

//child[/ol]

 2. 

 * 
 * 

//child[/ol]

 3. 

 : 
	親説明


//child[dl]

 : 
	子説明

//child[dl]

 1. 

 * 

//child[ul]

曾孫の段落

//emlist{
曾孫のコードリスト
//}

//child[/ul]

//child[/dl]

子の段落

//emlist{
子のコードリスト
//}

//child[/dl]

いろいろと入れ子にしているのでややこしいですが、構造は次のようになっています。

1.      親
2.      親
        1.      子
                1.      孫
                2.      孫
                ●      孫
                ●      孫
        2.      子
        ●      子
        ●      子
3.      親

親
        親説明
        子
                子説明
                1.      孫
                ●      孫
                        曾孫の段落
                        曾孫のコードリスト
        子の段落
        子のコードリスト

child 命令の実装

いつものように、実装はプロジェクトフォルダ内の review-ext.rb に記述します。

module ReVIEW
  module BuilderOverride
    Compiler.defsingle :child, 1

    def child(tag)
      @children ||= []
      puts "♬→#{tag}←♬"
      if tag.start_with?('/')
        if @children.empty?
          error "#{tag} is shown but there isn't any opened //child"
        elsif @children[-1] != tag.sub('/', '')
          error "#{tag} is shown but previous '#{@children[-1]}' is not closed yet"
        else
          @children.pop
        end
      else
        unless %w(dl ol ul).include?(tag)
          error "#{tag} is invalid value for //child (dl, ol, or ul)"
        end
        @children.push(tag)
      end
    end
  end

  class Builder
    prepend BuilderOverride
  end

  module LATEXBuilderOverride
    def solve_nest(s)
      s = s.
            gsub("\\end{description}\n\n♬→dl←♬\n", "\n").
            gsub('♬→/dl←♬', '\\end{description}←END♬').
            gsub("\\end{itemize}\n\n♬→ul←♬\n", "\n").
            gsub('♬→/ul←♬', '\\end{itemize}←END♬').
            gsub("\\end{enumerate}\n\n♬→ol←♬\n", "\n").
            gsub('♬→/ol←♬', '\\end{enumerate}←END♬').
            gsub("\\end{description}←END♬\n\n\\begin{description}", '').
            gsub("\\end{itemize}←END♬\n\n\\begin{itemize}", '').
            gsub("\\end{enumerate}←END♬\n\n\\begin{enumerate}", '').
            gsub('←END♬', '')

      if s =~ /♬→(.+?)←♬/
        error "Last //child[#{$1}] isn't closed yet."
      end

      s
    end

    def result
      solve_nest(super)
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end

  module HTMLBuilderOverride
    def solve_nest(s)
      s = s.
            gsub("</dd>\n</dl>\n♬→dl←♬", '').
            gsub('♬→/dl←♬', "</dd>\n</dl>←END♬").
            gsub("</li>\n</ul>\n♬→ul←♬", '').
            gsub('♬→/ul←♬', "</li>\n</ul>←END♬").
            gsub("</li>\n</ol>\n♬→ol←♬", '').
            gsub('♬→/ol←♬', "</li>\n</ol>←END♬").
            gsub("</dl>←END♬\n<dl>", '').
            gsub("</ul>←END♬\n<ul>", '').
            gsub("</ol>←END♬\n<ol>", '').
            gsub('←END♬', '')

      if s =~ /♬→(.+?)←♬/
        error "Last //child[#{$1}] isn't closed yet."
      end

      s
    end

    def result
      solve_nest(super)
    end
  end

  class HTMLBuilder
    prepend HTMLBuilderOverride
  end

  module IDGXMLBuilderOverride
    def solve_nest(s)
      s = s.
            gsub("</dd></dl>♬→dl←♬", '').
            gsub('♬→/dl←♬', "</dd></dl>←END♬").
            gsub("</li></ul>♬→ul←♬", '').
            gsub('♬→/ul←♬', "</li></ul>←END♬").
            gsub("</li></ol>♬→ol←♬", '').
            gsub('♬→/ol←♬', "</li></ol>←END♬").
            gsub("</dl>←END♬<dl>", '').
            gsub("</ul>←END♬<ul>", '').
            gsub("</ol>←END♬<ol>", '').
            gsub('←END♬', '')

      if s =~ /♬→(.+?)←♬/
        error "Last //child[#{$1}] isn't closed yet."
      end

      s
    end

    def result
      solve_nest(super)
    end
  end

  class IDGXMLBuilder
    prepend IDGXMLBuilderOverride
  end

  module PLAINTEXTBuilderOverride
    def solve_nest(s)
      lines = []
      @children = []
      s.split("\n").each do |l|
        if l =~ /\A♬→(dl|ul|ol)←♬/
          @children.push($1)
          lines.push('♬→END←♬')
        elsif l =~ /\A♬→\/(dl|ul|ol)←♬/
          @children.pop
          lines.push('♬→END←♬')
        else
          lines.push("\t" * @children.size + l)
        end
      end

      s = lines.join("\n").gsub(/\n*♬→END←♬\n*/, "\n")

      if s =~ /♬→(.+?)←♬/
        error "Last //child[#{$1}] isn't closed yet."
      end

      s
    end

    def result
      solve_nest(super)
    end
  end

  class PLAINTEXTBuilder
    prepend PLAINTEXTBuilderOverride
  end
end

LaTeX、HTML(EPUB)、IDGXML、装飾テキストおよびプレインテキストいずれにも対応します。

実際に LaTeX PDF を作ってみると以下のように期待の結果が得られます(コードリストの見た目に使っているデフォルトの網掛けはインデントに対応していないため、中の文字が妥当にインデントされていることのほうに注目してください)。

_images/nest-tex.png箇条書き入れ子の LaTeX PDF での確認

HTML は以下のようになります。

_images/nest-html.png箇条書き入れ子の HTML での確認

実装の説明

見てのとおり、child ブロック命令の内容を「♬→指定文字列←♬」に置き換えておき、後は各ビルダの最終出力前に、次のように置換していくだけです(「♬」は単に地の文に登場しなさそうな文字というだけで、他の文字でも構いません)。

  1. 本物の箇条書きの閉じ+開き♬ があったら、本物の箇条書き閉じを消す

  2. 閉じ♬ があったら、箇条書き閉じ+END♬ を入れる

  3. 箇条書き閉じ+END♬の後、同じ名前の本物の箇条書き開き があったら、箇条書きの閉じ・開きともに消す(継続と見なす)

  4. END♬ を消す

  5. まだ♬が残っていたら何かおかしい。開き漏れはブロック命令側で対処済みなので、おそらく閉じ漏れと見てエラー

箇条書きを閉じる際、もしその次の箇条書きが同じ種類であれば、継続と見なす、というのがちょっとした細工といったところでしょうか。

LaTeX に関連する長めの Tips

2018/8/9, 2018/11/16, 2019/3/12, 2020/1/5 by @kmuto

図表のフロートを制御する

図表のフロートの配置の挙動をデフォルトから変更する例を示します。


LaTeX において、キャプション付きの図や表は、「フロート」という1つのかたまりして扱われます。その名のとおり浮動的なもので、本文とはいくぶん切り離されて、版面上に空いている箇所に配置されます。

Re:VIEW のデフォルトのスタイルでは、このフロートは以下の挙動になるように定義しています。

  • 図:必ず指定した位置に配置。入らなければ大きな余白を恐れずに改ページして配置

  • 表:指定した位置に「配置できそうなら」配置。入らなければ次ページ先頭に配置し、表の後ろにあった文は余白を埋めるまで入る(バージョン 3 まで)。Re:VIEW 4 以降は図と同じ挙動。

_images/flow1.pngRe:VIEWのデフォルトの図表配置ルール

この挙動により、たとえば次のような場面で悩むことになるかもしれません。

  • 表が次のページに行きやすい(バージョン 4 より前)

  • 図の下に余白ができやすい(バージョン 4.0 以降は表も)

  • デザイン上、図表は必ず版面上端に揃えたいのにできない

スタイルの図表のフロートの挙動を定義し直すことで、これらの問題に対処することができます。

Re:VIEW 3 以降の場合

Re:VIEW 3 以降では、図表の設定を review-style.sty で指定できます。プロジェクトの sty/reiew-style.sty ファイルを見ると、次のように記述されているはずです。

Re:VIEW 4 以上の場合、

\floatplacement{figure}{H}
\floatplacement{table}{H}

Re:VIEW 3 の場合、

\floatplacement{figure}{H}
\floatplacement{table}{htp}

table が表の指定、figure が図の指定で、「H」や「htp」となっているのが位置指定です。

  • H:絶対に指定箇所に置く(float.sty の効果)

  • h:できれば指定箇所に置く。少しでも無理ならあきらめて次の候補へ

  • t:版面上端に置く

  • b:版面下端に置く

  • p:単独のページに置く

たとえばフロートは必ず上端に置く、という設定にしたければ次のようになります。

\floatplacement{table}{t}
\floatplacement{figure}{t}

あるいは図表はたとえ空きができても必ずそこに置くというのであれば、次のようにします。

\floatplacement{figure}{H}
\floatplacement{table}{H}

Re:VIEW 2 以前の場合

Re:VIEW 2 ベースの場合は table_header メソッドに [h] が決めうちで記述されてしまっているので、次のような review-ext.rb をプロジェクトフォルダに置いて上書きします。

module ReVIEW
  module LATEXBuilderOverride
    def table_header(id, caption)
      # \begin{table}[h]の[h]を削除
      if id.nil?
        if caption.present?
          @table_caption = true
          @doc_status[:caption] = true
          puts "\\begin{table}%%#{id}"
          puts macro('reviewtablecaption*', compile_inline(caption))
          @doc_status[:caption] = nil
        end
      else
        if caption.present?
          @table_caption = true
          @doc_status[:caption] = true
          puts "\\begin{table}%%#{id}"
          puts macro('reviewtablecaption', compile_inline(caption))
          @doc_status[:caption] = nil
        end
        puts macro('label', table_label(id))
      end
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

そしてプロジェクトフォルダの sty/reviewmacro.sty に以下のように記述します。

\renewenvironment{reviewimage}{%
  \begin{figure}
    \begin{center}}{%
    \end{center}
  \end{figure}}

\floatplacement{table}{H}
\floatplacement{figure}{H}

調整したいときは

箇所によって調整したい場合、いくつかの方法(ID を見て TeX ソースファイルでの配置指定を書き換えるなど)がありますが、「一時的に floatplacement を変更し、配置を終えたら元に戻すような生 LaTeX コードを埋め込む」という方法が最も簡単です。たとえば次のようにします(fig1-1 図版を紙面の上=tに配置し、元の H に戻します)。

…

//embed[latex]{
\floatplacement{figure}{t}
//}

//image[fig1-1][上に配置したい図]{
//}

//embed[latex]{
\floatplacement{figure}{H}
//}

…

フロートの挙動はなかなか厄介で、少し文字の調整をしたつもりが後続のフロート要素に影響して調整し直しになってしまうことがままあります。印刷の結果を最優先にするのであれば、図も表もどちらも「H」に設定しておき、re ファイル側で図表の位置を変えてしまったほうが扱いやすいでしょう。

また、h・t・b・p指定による自動配置の場合、たまに流れが詰まって章の最後で吐き出されてしまったりすることがあります。途中で強制的に吐き出すには、次のように \clearpage 命令を適宜埋め込む必要があります。

//embed[latex]{
\clearpage
//}

2018/8/11 by @kmuto

見栄えが悪い箇所を「少しだけ」調整する

@<embed> および //embed 命令により、TeX PDF の見た目を調整します。

★キャプチャを入れたい


LaTeX は独自のルールに従っておおむね綺麗に見える紙面を生成してくれますが、ときにはいささか見苦しいものを作り出すことがあります。たとえば @<tt> で表現される段落内等幅コードを多用すると、文字間がスカスカになったり、本文領域(版面)からはみ出したりといったことが起きがちです。

また、紙面化すると「ここで改ページできると後が綺麗なのに」「ここであとわずかだけ版面が広がれば収まるのに」ということもままあります。

re ファイル内に生の LaTeX マクロを埋め込むことでこれらを調整できます。ただし re ファイルの可視性は低下するので、使いすぎには注意しましょう。

生の LaTeX マクロを入れる

生の指示を埋め込む方法として、インライン命令としては @<embed>{|ビルダ名|〜}、ブロック命令としては //embed[ビルダ名]{ //} があります。ビルダ名はここでは「latex」と入れます。

〜〜@<embed>{|latex|\allowbreak }〜〜
〜〜

//embed[latex]{
\clearpage
//}

〜〜

LaTeX の記法では } を多用するため、インライン命令でそれらを \} といちいちエスケープするのはわずらわしいかもしれません。代替となるフェンス記法を使って表現するとよいでしょう(フェンス記号には $| がありますが、| はビルダ名の指定と衝突するため、$ のみを利用できます)。

@<embed>{|latex|\vspace{-0.5\Cvs\}} (通常の記法)

@<embed>$|latex|\vspace{-0.5\Cvs}$ ($によるフェンス記法)

//embed のブロック命令では //} までの範囲がそのまま使われるので、フェンス記法はもともとありません。

段落途中の折り返しを調整する

段落がスカスカになっていたり、はみ出したり、ひとかたまりになっていてほしい語句が泣き別れてしまっていたりといった箇所を調整するには、折り返しできそうな箇所に \allowbreak マクロを埋め込みます。

例(元々の見た目):
〜〜りんごが二    ←(「二」と「個」が泣き別れて読みにくい)
個あります。
原稿:
〜〜りんごが二個あります。
 ↓
〜〜りんごが@<embed>{|latex|\allowbreak }二個あります。
例(指定後):
〜 〜 りんごが    ←(「二」の前で改行。空いたぶんは文字間の調整で自動で埋められる)
二個あります。

後続の文字が誤って TeX マクロ名の続きとして扱われないよう、\allowbreak と後ろにスペースを入れています(TeX のコンパイラが適正に判断するので、物理的なスペースが紙面結果に入ることはありません)。

@<tt> インライン命令を使った長い等幅コード表記文字列は、1つのかたまりとして扱われるので、スカスカの段落や版面はみ出しの主因となります。これを途中で分けたいときには、インライン命令の入れ子はできないので、文字列自体を分割する必要があります。

〜〜@<tt>{LongLongLongLongLongLongLongLongLongLongLongLongLongAgo}〜〜
  ↓
〜〜@<tt>{LongLongLongLongLongLong}@<embed>{|latex|\allowbreak }@<tt>{LongLongLongLongLongLongLongAgo}〜〜

\allowbreak マクロは「そこで改行するのが妥当そう」と判断されたときに使われますが、これがうまくいかず、それでも絶対に改行したいという場合には \linebreak マクロを使いましょう。

なお、@<href> で作った URL の箇所については、re ファイルへの命令だけでは途中で分断することはできません。直接 TeX ファイルを書き換える必要があります。

要素間の間隔を調整する

図表やコードリストなど、要素どうしの組み合わせによっては、間隔の空き量が広すぎ、あるいは狭すぎになることがあります。本来はスタイルを調整すべきであり、場当たり的な対処ではあるものの、間隔を調整する指示マクロを埋め込むことができます。

//embed[latex]{
\vspace{0.5\Cvs}
//}

\vspace は垂直方向に空きを入れるマクロです。値の「0.5\Cvs」は0.5行ぶんの高さの空きを追加することを意味します。値を負の値にすれば、上方向に狭くするということになります。単位は \Cvs のほかに mmpt を指定できます。

改ページを強制する

「この見出しの手前で改ページすると綺麗になる」といったときには、\clearpage マクロを埋め込みます。

//embed[latex]{
\clearpage
//}

段落の途中でどうしても改ページしたい場合は、均等配置を保持するためにたとえば以下のように指定します。

〜〜りんごが@<embed>{|latex|\linebreak\clearpage\noindent }二個あります。

版面を伸ばす

「あともう少しだけ版面を伸ばせれば……」というときには、\enlargethispage マクロをそのページを含む箇所のどこかに設置します。たとえば5mm下方向に伸ばすには、以下の命令を re ファイル内に記します。

//embed[latex]{
\enlargethispage{5mm}
//}

一般に、版面の伸縮は避けるべきです。基本のレイアウトルールから逸脱しますし、その後ページの内容が変わったのに以前に伸縮していた箇所をそのままにしていると奇妙なはみ出しやページ送りが発生することになります。

ページ調整の最終段階で、やむを得ない場合にのみ使うようにしましょう。

フックによる TeX ファイルの変更

以下のような調整は、re ファイルへの埋め込みでは解決できず、生成される TeX ファイルを途中で変更する必要があります。

  • 長いURLの改行調整

  • 見出しの改行調整

  • 目次の調整

  • 索引の調整

これらの調整方法については、フックで LaTeX 処理に割り込む を参照してください。

2018/8/11 by @kmuto

フックで LaTeX 処理に割り込む

review-pdfmaker での PDF 生成は複数の段階からなりますが、フックを使って途中で割り込み、紙面を調整できます。

★キャプチャを入れたい


フックのタイミング

review-pdfmaker を実行すると、以下のように内部で処理が進みます。

  1. 作業用の一時フォルダが生成される。

  2. latex ビルダで reファイルから LaTeX ファイル(拡張子 .tex)に変換し、一時フォルダに配置する。

  3. プロジェクトフォルダの sty サブフォルダの内容や、images サブフォルダが一時フォルダにコピーされる。

  4. システムまたはプロジェクトフォルダの layouts サブフォルダにあるレイアウトファイル layout.tex.erb が評価された後、一時フォルダに __REVIEW_BOOK__.tex(Re:VIEW 3 以上)または book.tex(Re:VIEW 2以前)という名前で配置される。

  5. 一時フォルダ内に移動する。

  6. hook_beforetexcompile パラメータにプログラムが指定されていればそれを実行する。

  7. LaTeX コンパイラを 2 回実行する(LaTeX は複数回のコンパイルで紙面を完成させる仕組み)。

  8. hook_beforemakeindex パラメータにプログラムが指定されていればそれを実行する。

  9. 索引処理を有効にしているなら索引プログラムを実行する。

  10. hook_aftermakeindex パラメータにプログラムが指定されていればそれを実行する。

  11. LaTeX コンパイラを 1 回実行する。

  12. hook_aftertexcompile パラメータにプログラムが指定されていればそれを実行する。

  13. dvi ファイルが生成されていれば dvi から PDF に変換するプログラムを実行する。

  14. hook_afterdvipdf パラメータにプログラムが指定されていればそれを実行する。

  15. PDF ファイル __REVIEW_BOOK__.pdf または book.pdf を、bookname パラメータで指定した本来の名前にしてプロジェクトフォルダに配置する。

  16. 一時フォルダを消去する。

太字で示した箇所がフック処理の箇所です。config.yml で pdfmaker の下位設定として定義します。

 …
pdfmaker:
  hook_beforetexcompile: プログラムのパス
 …

フックは、それぞれ以下のような用途を想定しています。

  • hook_beforetexcompile:re ファイルから変換された tex ファイルを加工する。デフォルトでコピーされるものに加えて、さらにファイルをコピーする。

  • hook_beforemakeindex:索引を有効にしている場合、索引情報ファイル __REVIEW_BOOK__.idx または book.idx が生成されるので、これを索引ツールに渡す前に加工する。

  • hook_aftermakeindex:索引を有効にしている場合、索引ツールを経て索引 TeX ファイル __REVIEW_BOOK__.ind または book.ind が生成されるので、これを LaTeX コンパイラに渡す前に加工する。

  • hook_aftertexcompile:目次を加工するなど、最終段階の状態にさらに処理を加える。

  • hook_afterdvipdf:PDF をさらに加工する(グレースケール化する、別の PDF と合体させるなど)。

フックプログラムの構成

フックのパラメータに指定するプログラムは、実行形式になっていれば何でもかまいません。プログラムには、その呼び出し時に引数が2つ渡されます。

  • 引数1:一時フォルダのパス

  • 引数2:プロジェクトフォルダのパス

引数を受けて処理するフックプログラムは、通常は Ruby スクリプトあるいはシェルスクリプトで書くのが簡単でしょう。たとえば以下のようになります。

#!/usr/bin/env ruby
File.write("#{ARGV[1]}/hook.log",
           "一時フォルダのパス:#{ARGV[0]}\n" +
           "プロジェクトフォルダのパス:#{ARGV[1]}\n")

ファイルには実行形式属性(chmod +x)を付けておく必要があります。実行形式属性がないと、単に無視されて実行されません。

上記のプログラムコードをプロジェクトフォルダに hook_beforetexcompile.rb という名前で置き、config.yml で以下のように指定します。

 …
pdfmaker:
  hook_beforetexcompile: ./hook_beforetexcompile.rb
 …

rake pdf を実行すると、TeX のコンパイル直前にフックが動き、この例の場合はプロジェクトフォルダに hook.log というファイルができます。

一時フォルダのパス:/tmp/book-pdf-20180811-31959-1m19hdf
プロジェクトフォルダのパス:/home/kmuto/review-samples/test

★Windows Dockerだとパーミッションはどう見える?

★Windowsネイティブだとスクリプト起動ができないのでruby.exeを指定する必要だが、hookパラメータはオプションまでの指定はできない構造。バッチファイルを呼ぶようにしてそこで引数解析してruby.exe+スクリプトに渡す、といった対処が必要になると予想。

デバッグモード

config.yml でデバッグモードにすると、プロジェクトフォルダに「booknameの値-pdf」が作られ、そこが一時フォルダとなります。デバッグモードでは、この一時フォルダは消去されません。

debug: true

フックによる変更がうまくできているかどうかを確認するため、最初はデバッグモードにしておくとよいでしょう。

デバッグモードでないときには、一時フォルダはプロジェクトフォルダとは異なるフォルダ(たとえば /tmp 内)に作られることに注意してください。

フックの例

以下では、フックを使った「長い文字列の折り返し」の例をいくつか示します。

見出しの折り返し

見出しが長いときには版面に合わせて自動で折り返されますが、人間が見たときにより妥当な位置で折り返したいことがあります。たとえば ch1.re からの生成結果が以下のようになっていたとします。

1.5 サーバーとクライア
     ント

↓ 理想

1.5 サーバーと
     クライアント

見栄えが悪い箇所を「少しだけ」調整する では段落内で @<embed> インライン命令を使うことで \allowbreak を入れる例を示しましたが、見出しは目次や柱にも使われるので、TeX ファイルでの加工が必要です。

config.yml で debug パラメータを true にして一時フォルダの ch1.tex を見てみます。

 …
\section{サーバーとクライアント}
 …

LaTeX (のクラスファイル)では、目次や柱に使う見出しと、その場所で表現する加工した見出しを別個に指定することができます。ここでは、以下のように変えるのが目標です。[]内が目次や柱用の見出し、{}内がその場所で表現する見出しです。\\ はそこで改行する(均等割にせず強制改行)という意味です。

 …
\section[サーバーとクライアント]{サーバーと\\クライアント}
 …

ch1.tex を加工するフックプログラム hook_beforetexcompile.rb を作成します。

#!/usr/bin/env ruby
File.open("#{ARGV[0]}/ch1.tex", 'r+') do |f|
  s = f.read.sub('\section{サーバーとクライアント}',
                 '\section[サーバーとクライアント]{サーバーと\\\\\クライアント}')
  f.rewind
  f.print s
end

短く表現するために少々トリッキーな書き換えをしていますが、要するに単純にファイル内容の文字列置換をして書き出しているだけです。重複したエスケープ表現のため、\\ ではなく \\\\\ とする必要があります。

実行権限を付けたら、config.yml で指定します。

 …
pdfmaker:
  hook_beforetexcompile: ./hook_beforetexcompile.rb
 …

これで、見出しが指定どおりに折り返されるでしょう。

★より妥当な長さの見出し例にしたい

目次の折り返し

config.yml で toc: true を指定すると目次が生成されますが、目次の内容はページ参照が含まれるので最終段階まで確定しません。そのため、 hook_aftertexcompile で調整します。

目次ファイルは __REVIEW_BOOK_.tex (Re:VIEW 3 以降)または book.tex (Re:VIEW 2 以前)として生成されています。

 …
\contentsline {section}{\numberline {1.5}サーバーとクライアント}{20}{section.1.5}
 …

\numberline {1.5}サーバーとクライアント」の部分がそのまま整形(ページ参照は「20」)されて表現されるので、折り返しを調整するにはここを加工します。

また、hook_aftertexcompile の後には LaTeX のコンパイルは行われないので、フックプログラムの中でコンパイルも実行するようにします。

以下の hook_aftertexcompile.rb を作成します(Re:VIEW 2 以下の場合は __REVIEW_BOOK__book に置き換えてください)。

#!/usr/bin/env ruby
File.open("#{ARGV[0]}/__REVIEW_BOOK__.toc", 'r+') do |f|
  s = f.read.sub('{1.1}サーバーとクライアント}',
                 '{1.5}サーバーと\\\\\クライアント}')
  f.rewind
  f.print s
end

system('uplatex -interaction=nonstopmode -file-line-error __REVIEW_BOOK__.tex')

例のごとく実行権限を付けたら、config.yml で呼び出しの設定をします。

 …
pdfmaker:
 …
  hook_aftertexcompile: ./hook_aftertexcompile.rb
 …

これで、目次が折り返されるようになります。

URL の折り返し

@<href> 命令で指定した URL は、\url{〜} という LaTeX のマクロに置き換えられ、等幅コードと同じルールで表現されます。紙面の都合で途中で改行するには、その箇所の \url{〜}\href{URL}{紙面表現} に置き換える必要があります。

ch1.tex の \url マクロの箇所を加工するフックプログラム hook_beforetexcompile.rb を示します。

#!/usr/bin/env ruby
File.open("#{ARGV[0]}/ch1.tex", 'r+') do |f|
  s = f.read.sub('\url{https://ja.wikipedia.org/wiki/マークアップ言語}',
                 '\href{https://ja.wikipedia.org/wiki/マークアップ言語}{https://ja.wikipedia.org/wiki/マー\allowbreak クアップ言語}')
  f.rewind
  f.print s
end

文章に変更があると改行の方針も変わる可能性があります。このような調整は、文章が確定した制作終盤に行うのがよいでしょう。

2018/8/20, 2018/11/16 by @kmuto

jsbook ベースのドキュメントにトンボおよびデジタルトンボを配置する

jsbook クラス由来の PDF に正しいトンボを設定する方法を示します。


ざっくり結論から (1)

Re:VIEW 3 から、デフォルトの review-jsbook および別案の review-jlreq いずれのクラスにおいても、デフォルトでトンボおよびデジタルトンボが配置されます。

  • review-jsbook では以下で紹介する gentombow パッケージがプロジェクトにコピーされ、それが使われます。インストールは不要です。

  • review-jlreq では jlreq クラスの jlreq-trimmarks スタイルが使われます。

ということで、Re:VIEW 3 以降の場合は、ここからの内容を気にする必要はほぼありません。

ざっくり結論から (2)

背景などどうでもいいのでともかく jsbook ベースで正しいデジタルトンボを入れる方法を示せ、というせっかちな方のために、jsbook ベースのレイアウトに以下の手順でデジタルトンボを配置できます。

  1. プロジェクトの sty フォルダの reviewmacro.sty(Re:VIEW 2 以前)に、以下を追加します。

    \usepackage[pdfbox]{gentombow}
    
  2. gentombow パッケージがすでに入っている環境であれば、これだけで正しいデジタルトンボが入ります。

  3. 不幸にして ! LaTeX Error: File 'gentombow.sty' not found. と返されてしまったら、以下のいずれかの方法でパッケージまたは sty ファイルをインストールします。

  • 方法A:TeXLive 環境であれば、tlmgr コマンドを使い、tlmgr install gentombow を実行してインストールする。

  • 方法B:https://github.com/aminophen/gentombow から gentombow.sty をダウンロードし、プロジェクトの sty フォルダにコピーする。

jsbook の tombow オプションは?

jsbook クラスにも tombow オプションがありますが、これだけでは単に紙面に「トンボのような画像」を入れているにすぎません。正しいデジタルトンボを入れるには上記のように gentombow パッケージなどを使う必要があります。

デジタルトンボとは

「デジタルトンボ」は DTP ソフトウェアなどの正式な用語ではないのですが、組版関係では一般に使われる俗語です。

印刷用の紙面には、以下の2つの矩形サイズが関わってきます。

  • 実際の書籍の紙サイズ(仕上がりといいます)。A5 や B5 といったよく耳にするサイズです。商業刊行では B5 から縦などの一部を切り詰めた B5 変というサイズもあります(B5 変には明確な規定はなく、出版社によって任意です)。

  • その周囲数 mm 外側の矩形(塗り足し領域、裁ち落とし、ドブなどといいます)。家庭用プリンタと異なり、印刷所では大きな紙に複数のページを印刷し、そこから仕上がりサイズに合わせて断裁します。印刷・断裁の精度にもよりますが、物理的な紙というものを相手にしている都合上、すべてのページが必ずミクロな単位で同じ位置になるとは限らず、若干のずれが生じることがあります(一般にオフセット印刷のほうが精度が高く、オンデマンド印刷のほうが低くなります)。この誤差を吸収するのが塗り足し領域で、いわゆる「ふちなし印刷」のようなことを実現するには、ふちなしにしたい対象をこの領域まで配置しておく必要があります。通常 3mm です。

人間向けにこの2つのサイズ情報を紙に表したのが、以下のマークです。

_images/tombow.pngトンボ

その形状から「トンボ」(英語では trim mark)と呼び、角の内側で判型、外側で塗り足し領域の範囲を示しています。形状が違ったり縦横の中央を表すセンタートンボが入ったりすることもありますが、人間用の位置見当情報であるということに変わりありません。

デジタルトンボは、このトンボの情報をデジタルデータとして PDF 内で表現したものです。印刷所の印刷処理においてこのデジタルトンボ情報が解釈されることで、入稿者・印刷所双方で紙面の置き方に齟齬が生じないようになります。

デジタルの紙面データ、つまり PDF の場合はもう1つ、ビューアで表示するときの領域もあります。よって、デジタルトンボは以下の3つの矩形情報で構成されます。

  • TrimBox:仕上がり領域の矩形

  • BleedBox:塗り足し領域の矩形

  • MediaBox:ビューアでの表示、およびビューアから素朴に「印刷」を実行したときの用紙サイズとなる矩形。このほかに ArtBox というのもあるが通常は同一値

デジタルトンボは PDF のメタ情報として埋め込まれているものであり、gentombow パッケージで見える紙面上のトンボは単に人間向けの画像にすぎません。

デジタルトンボは Acrobat の表示設定で「アートサイズ、仕上がりサイズ、裁ち落としサイズを表示」を有効にすることで確認できます。

_images/acro-tombo.pngデジタルトンボの視覚化

poppler ライブラリの pdfinfo コマンドで調べることもできます(単位は point なので、mm にするには 0.352778 を掛けます)。

$ pdfinfo -box book.pdf
Title:          Re:VIEWサンプル書籍
 …
Page size:      515.91 x 728.5 pts
Page rot:       0
MediaBox:           0.00     0.00   515.91   728.50
CropBox:            0.00     0.00   515.91   728.50
BleedBox:          39.68    58.11   476.22   670.39
TrimBox:           48.19    66.61   467.72   661.89
ArtBox:             0.00     0.00   515.91   728.50
File size:      147227 bytes
 …

トンボのカスタマイズ

再び gentombow パッケージに戻ると、いくつかのオプションで設定をカスタマイズできます。

\usepackage[pdfbox]{gentombow}

最初から pdfbox オプションを示したとおり、このオプションはデジタルトンボを付けることを意味します。これがなければ単にトンボ画像を配置するのみでデジタルトンボ情報は埋め込まれません。よって、オプションといっても実際には必須の指定と言えます。

オプションは , で区切って複数指定できます。

以下の3つのオプションはいずれか1つを選びます。

  • tombow:デフォルトに同じ。トンボおよびジョブ情報を出力する。

  • tombo:トンボのみを出力し、ジョブ情報は出力しない。

  • mentuke:トンボ・ジョブ情報ともに出力しない。

MediaBox のサイズはもともとの仕上がりサイズからひと回り大きな定型サイズが自動で選定されるようになっていますが、別のサイズを使いたいときには、上記の tombowtombomentuke と組み合わせてサイズを指定します。

% ジョブ情報なしのトンボで、A4をMediaBoxとする
\usepackage[pdfbox,tombo-a4]{gentombow}

サイズは a0a10b0b10(ISO ではなく JIS 寸法)、c0c10letterexecutivea4varb5var が用意されています。

塗り足しの幅はデフォルトで 3mm になっています。これを 5mm にする場合は以下のような設定マクロを加えます。

\settombowbleed{5mm}

塗り足しの幅を含め、印刷所によってそれぞれに規定があるので、入稿仕様は必ず確認しましょう。

2018/9/24 by @kmuto

前付(PREDEF)、後付(POSTDEF)の図表採番を本章同様にリセットする

jsbook を使ったテンプレートを利用していて、図表を前付や後付で多用する場合、番号のリセットがうまく効きません。これを修正する方法を示します。


採番で発生する奇妙な挙動

Re:VIEW の前付(PREDEF)や 後付(POSTDEF)に re ファイルを割り当て、かつそれぞれで採番付きの図表(image や table)を使った場合、一般的な jsbook 基盤のテンプレートを使っていると次のような挙動になります。

  • 図1、図2、……のような採番になる

  • しかし、通常の章では章が変わるごとに番号のカウントが1に戻るのに対し、前付は re ファイルが変わってもカウントは戻らず、前のファイルでの採番の続きとなる

  • さらに悪いことに後付は CHAPS で割り当てられた最後の章の採番を引き継ぐ

これは通常は意図に反する挙動でしょう。

jsbook と chapter の挙動

LaTeX の内面で見ていくと、次のようになっています。

  • 前付は \frontmatter、本文は \mainmatter、後付は \backmatter という3つのマクロ宣言で切り分けられている(章として扱うかどうか、ページ番号をどう表現するかなどがここで設定される)

  • figure や 表 table のカウンタは、chapter に依存してカウントされる

  • 各見出しは \chapter マクロで表され、この中で「mainmatter 内なら \refstepcounter{chapter}」によってカウンタをリセットする。それ以外の場合はリセットしない

2018年9月時点の jsbook.cls (2018/06/23 バージョン) でも対処されておらず、またこれを変更すると既存の文書に影響が大きいことから、「仕様」と判断されます。

なお、Re:VIEW の図表参照(@<img>@<table>)のほうは、TeX から導く \ref マクロではなく、Re:VIEW の時点で決定した番号をそのままの文字列(リテラル)で書き出しているので、参照側は前付・後付でも「正しい」番号になります。

対処方法A

おそらく現時点では最も妥当な方法と思われます。ただし、jsbook.cls 側の変更があったときには不整合が生じる可能性があります。

\chapter マクロで mainmatter 以外でも \refstepcounter{chapter} でリセットするようにします。ただ、これだけでは前付・後付に「章番号」が付いてしまうので、ダミーの番号を入れて隠す、という手順を入れます。

sty/review-custom.sty(Re:VIEW 3 系)または reviewmacro.sty(Re:VIEW 2 以前)に次のように追加します。

\renewcommand\frontmatter{% frontmatter再定義
  \if@openright
    \cleardoublepage
  \else
    \clearpage
  \fi
  \@mainmatterfalse
  \pagenumbering{roman}%
  \setcounter{chapter}{-100}% 前付用のダミー章番号を追加する
}

\renewcommand\mainmatter{%
    \cleardoublepage
  \@mainmattertrue
  \pagenumbering{arabic}%
  \setcounter{chapter}{0}% mainmatterで章番号をいったんリセットする
}

\renewcommand\backmatter{%
  \if@openright
    \cleardoublepage
  \else
    \clearpage
  \fi
  \@mainmatterfalse%
  \setcounter{chapter}{-100}% 後付用のダミー章番号を追加する
}

\def\@chapter[#1]#2{%
  \ifnum \c@secnumdepth >\m@ne
    \if@mainmatter
      \refstepcounter{chapter}%
      \typeout{\@chapapp\thechapter\@chappos}%
      \addcontentsline{toc}{chapter}%
        {\protect\numberline
        % {\if@english\thechapter\else\@chapapp\thechapter\@chappos\fi}%
        {\@chapapp\thechapter\@chappos}%
        #1}%
    \else%
      \refstepcounter{chapter}\phantomsection% mainmatter以外でもカウンタリセット
      \addcontentsline{toc}{chapter}{#1}\fi
  \else
    \addcontentsline{toc}{chapter}{#1}%
  \fi
  \chaptermark{#1}%
  \addtocontents{lof}{\protect\addvspace{10\jsc@mpt}}%
  \addtocontents{lot}{\protect\addvspace{10\jsc@mpt}}%
  \if@twocolumn
    \@topnewpage[\@makechapterhead{#2}]%
  \else
    \@makechapterhead{#2}%
    \@afterheading
  \fi}

対処方法B

本質的な解決ではありませんが、対処方法Aよりも場当たりに対処する方法もあります。

図表がある前付や後付の re ファイルに、カウンタの強制リセットを挿入します。見出しの直後にでも入れておくとよいでしょう。

= (見出し)
//embed[latex]{
\setcounter{figure}{0}
\setcounter{table}{0}
//}

対処方法C

jsbook.cls 以外の新規に作成されたドキュメントクラスファイル(jlreq など)では、この問題が発生しないと思われます。

2018/11/7 by @kmuto

部が存在するときのしおりのレベルを調整する

部が存在するときの PDF のしおり(ブックマーク)の階層化の不都合を修正します。


本記事は、Re:VIEW 3 以上の機能に依存します。

PDF のしおり(ブックマーク)は、TeX の hyperref パッケージを使用して実現しています。一般的な章のみで構成されている書籍では、これで問題ありません。

.
├── 前書き
├── 1章
│    ├── 1.1節
│    └── 1.2節
├── 2章
│    └── 2.1節
├── 3章
└── 付録A

しかし、部が入ると、部の下位に部以外のしおりが収録されてしまう現象が発生します。

.
├── 前書き
├── I部
│    ├── 1章
│    │    ├── 1.1節
│    │    └── 1.2節
│    └── 2章
│          └── 2.1節
└── II部
      ├── 3章
      └── 付録A ←これ以降がII部に入るのは意図していない!

これは、hyperref パッケージのレベル付けに起因しています。後ろに hyperref が振るレベルの番号を付けてみると、以下のようになります。

.
├── 前書き (0)
├── 1章 (0)
│    ├── 1.1節 (1)
│    └── 1.2節 (1)
├── 2章 (0)
│    └── 2.1節 (1)
├── 3章 (0)
└── 付録A (0)
.
├── 前書き (0)
├── I部 (-1) ←部のレベルは-1
│    ├── 1章 (0)
│    │    ├── 1.1節 (1)
│    │    └── 1.2節 (1)
│    └── 2章 (0)
│          └── 2.1節 (1)
└── II部 (-1)
      ├── 3章 (0)
      └── 付録A (0) ←II部のレベル-1より大きいため下位

これに自動で対処するのは困難です。TeX 側はシステムとしては部や章などの構造については関知せず、Re:VIEW 側でも部の「終わり」を判断して何かを差し込むような機構は持っていません。何かマクロを用意しようにも、すべてに通用するような汎用化はやりづらい箇所です。

ただ、対処方法は考えられます。

  • 手法A:部が終わった後の全見出しのレベル数を1つ減算する(章を-1とする)

  • 手法B:部構造の場合は部以下の全見出しのレベル数に1つ加算する(部を0、章を1とする)。部構造が終わったら元に戻す

まず、sty フォルダの review-custom.sty に以下のような支援マクロを追加します。

\def\resettoclevel{%オリジナルのレベル
\def\toclevel@part{-1}
\def\toclevel@chapter{0}
\def\toclevel@section{1}
\def\toclevel@subsection{2}
\def\toclevel@subsubsection{3}
\def\toclevel@paragraph{4}
\def\toclevel@subparagraph{5}
}

\def\uptoclevel{%部以下の見出しレベルを1つ大きくする
\def\toclevel@part{0}
\def\toclevel@chapter{1}
\def\toclevel@section{2}
\def\toclevel@subsection{3}
\def\toclevel@subsubsection{4}
\def\toclevel@paragraph{5}
\def\toclevel@subparagraph{6}
}

\def\downtoclevel{%章以下の見出しレベルを1つ小さくする
\def\toclevel@part{-1}
\def\toclevel@chapter{-1}
\def\toclevel@section{1}
\def\toclevel@subsection{2}
\def\toclevel@subsubsection{3}
\def\toclevel@paragraph{4}
\def\toclevel@subparagraph{5}
}

手法Aは次のような戦略です。

.
├── 前書き (0)
├── I部 (-1)
│    ├── 1章 (0)
│    │    ├── 1.1節 (1)
│    │    └── 1.2節 (1)
│    └── 2章 (0)
│          └── 2.1節 (1)
├── II部 (-1)
      └── 3章 (0)
(※ここからレベルの付け方を-1する)
└── 付録A (0→-1) ←II部のレベル-1と同じになったのでII部の枠から抜ける

ちょうど付録の直前に呼び出される \reviewappendixhook マクロが用意されているので、この中で \downtoclevel を呼び出すようにします。review-custom.sty に以下を追加します(中身の最初の2行は、review-base.sty で定義されていた内容です)。

\def\reviewappendixhook{
  \renewcommand{\chaptermark}[1]{\markboth{\appendixname\thechapter~##1}{}}
  \reviewappendix
  \downtoclevel
}

これで簡単に実現できました。

手法Bは次のような戦略です。

.
├── 前書き (0)
(※ここからレベルの付け方を+1する)
├── I部 (-1→0)
│    ├── 1章 (0→1)
│    │    ├── 1.1節 (1→2)
│    │    └── 1.2節 (1→2)
│    └── 2章 (0→1)
│          └── 2.1節 (1→2)
├── II部 (-1→0)
      └── 3章 (0→1)
(※ここでレベルの付け方を戻す)
└── 付録A (0) ←II部のレベル0と同じになったのでII部の枠から抜ける

こちらの手法では、(上記の図の用途だけならフックに書いてもよいのですが)re ファイルのほうにレベル変更を埋め込みます。

I部の見出しが始まる前に、\uptoclevel マクロを呼び出すようにします。I部の re ファイルの先頭に生の TeX マクロを embed 命令で埋め込みます。

//embed[latex]{
\uptoclevel
//}

= I部の見出し
 …

レベル変更の部構造が終わったら、レベルを元に戻します。ここでは3章の末尾で戻すことにしましょう。3章の re ファイルの末尾に \resettoclevel マクロを embed 命令で埋め込みます。


= 3章の見出し
 …
(末尾)
//embed[latex]{
\resettoclevel
//}

これで、部構造の中だけレベルが変わります。

手法A・Bどちらを選ぶかは、部構造の複雑さによります。付録や後付が部に吸収されてしまって困るというだけであれば、手法Aで十分です。部の中に入ったり入らなかったりする章がある、のように複雑な部構造を持つ場合は、手法Bを使うことになるでしょう。

2018/11/18, 2022/3/29 by @kmuto

使用書体の変更(upLaTeX 編)

ここでは Re:VIEW+upLaTeX に限定して書体の変更方法を説明します。


書体を変えると独自性を出せますが、CSS や InDesign とは違い、TeX の書体変更はなかなか深遠……というよりも調べるほどによくわからなくなり、「そのままでいいか」となりがちです。

LuaTeX コンパイラで LuaLaTeX-ja 環境を使えば任意の TrueType/OpenType のフォントを利用できますが、一般に使われているテンプレートの review-jsbook は upLaTeX コンパイラ向けです。ここでは、upLaTeX で簡易にフォントを変更できる pxchfon パッケージを使います。

利用するフォントの準備

さて、フォントを差し替えるにあたっては、利用するフォントは「TeX のファイル管理システム」から見えている必要があります。OS やほかのアプリケーションでは見えている、だけではダメなことに注意してください。

kpsewhich フォントファイル名(たとえば kpsewhich HiraMinPro-W3.otf)で返ってこなかったら、そのフォントは TeX からまだ使えません。kpsewhich -show-path="opentype fonts" で表示されるパスのいずれかにフォントを移動・あるいはリンクした後、mktexlsr コマンドでファイルデータベースを更新します。

なお、フォントファイル名は英数字にしておくのが無難です。

  • 当然ながらフォントの配布ライセンスは守る必要があります。

  • 埋め込み禁止のフォントは使用できません。

  • 等幅であることを前提としており、プロポーショナルフォントは利用できません。

pxchfon パッケージの基本

pxchfon パッケージは、dvipdfmx の実行時に埋め込むべきフォントを設定することで、フォントを切り替えます。TeXLive には kanji-config-updmap-sys というデフォルトの埋め込み和文フォントを設定するツールがありますが、pxchfon パッケージは TeX ソース個別に設定できます。

なお、vvakame/review Docker イメージでは、デフォルトで「原の味」フォントを和文埋め込みフォントとしています。

プリセットを使う

最も簡単なのは、kanji-config-updmap-sys と同等のプリセットを指定する方法です。フォントファイル名はプリセットの内容に合わせる必要があります。プリセットで想定しているファイル名の詳細は、texdoc pxchfon でドキュメントを参照してください。sty/review-custom.sty に次の書式で追加します。

\usepackage[プリセット名]{pxchfon}
  • haranoaji:原の味フォント

  • ms-hg:MS系フォント+HGフォント

  • ipa-hg:IPAフォント+HGフォント

  • ipaex-hg:IPAexフォント+HGフォント

  • moga-mobo:Mogaフォント+Moboフォント

  • moga-mobo-ex:MogaExフォント+MoboExフォント

  • moga-maruberi:Mogaフォント+モトヤLマルベリ

  • ume: 梅フォント

  • kozuka-pro:小塚フォントPro

  • kozuka-pr6:小塚フォントPr6

  • kozuka-pr6n:小塚フォントPr6N

  • hiragino-pro:ヒラギノ6書体Pro/Std+明朝W2

  • hiragino-pron:ヒラギノ6書体ProN/StdN+明朝W2

  • hiragino-elcapitan-pro:ヒラギノ(macOS El Capitan版)Pro/Std+明朝W2

  • hiragino-elcapitan-pron:ヒラギノ(macOS El Capitan版)ProN/StdN+明朝W2

  • morisawa-pro:モリサワ7書体Pro

  • morisawa-pr6n:モリサワ7書体Pr6N

  • yu-win:遊書体(Windows 8版)

  • yu-win10:遊書体(Windows 10版)

  • yu-osx:遊書体(macOS版)

  • sourcehan:源ノ明朝+源ノ角ゴシック(otf)。TeXLive 2017 の dvipdmfx が必要

  • sourcehan-otc:源ノ明朝+源ノ角ゴシック(otc)。TeXLive 2017 の dvipdmfx が必要

  • sourcehan-jp:源ノ明朝+源ノ角ゴシック(JP otf)。TeXLive 2017 の dvipdmfx が必要

  • noto:Noto(otf)。TeXLive 2017 の dvipdmfx が必要

  • noto-otc:Noto(otc)。TeXLive 2017 の dvipdmfx が必要

個別に指定する

プリセットの代わりに、以下の書体について個別に設定することもできます。

  • \setminchofont:明朝・デフォルト(\mcfamily

  • \setlightminchofont:明朝・細ウェイト(\mcfamily\ltseries

  • \setmediumminchofont:明朝・中ウェイト(\mcfamily\mdseries

  • \setboldminchofont:明朝・太ウェイト(\mcfamily\bfseries

  • \setgothicfont:ゴシック・通常ウェイト(\gtfamily

  • \setmediumgothicfont:ゴシック・中ウェイト(\gtfamily\mdseries

  • \setboldgothicfont:ゴシック・太ウェイト(\gtfamily\bfseries

  • \setxboldgothicfont:ゴシック・極太ウェイト(\gtfamily\ebseries

  • \setmarugothicfont:丸ゴシック(\mgfamily

いずれも設定の記法は次のとおりです。

\set〜font{フォント名.otf}% 単一OpenTypeの場合
\set〜font{フォント名.ttf}% 単一TrueTypeの場合
\set〜font[番号]{フォント名.ttc}% TTC形式の場合はフォント番号

Re:VIEW 側の設定

review-jsbook のデフォルトの文字装飾設定では、明朝・ゴシックのシンプルなものしか利用していません。本文に「明朝・通常ウェイト(\setminchofont)」、見出しや強調(@<b>)などには「ゴシック・通常ウェイト(\setgothicfont)」が使われます。

本文以外を調整するには、各装飾設定でファミリおよびウェイトを指定する必要があります。上記の \set〜font の列挙で「(\gtfamily\bfseries)」のように記載していたのがその指定です。

@<i> に丸文字を割り当て

和文にはイタリックがかからないので、代わりにモリサワの「じゅん101」の丸文字を割り当ててみます。sty/review-custom.sty には次のように追加します。

\setmarugothicfont{A-OTF-Jun101Pro-Light.otf}
\renewcommand{\reviewit}[1]{\textit{\mgfamily #1}}

_images/pxchfon-italic.pngイタリック装飾内の和文を丸文字に変更

見出しのフォント変更

ゴシック・極太ウェイトにモリサワの UD 新ゴPr6N Heavy を割り当て、それを見出しで使うには、以下のようにします。

\setxboldgothicfont{A-OTF-UDShinGoPr6N-Heavy.otf}
\renewcommand{\headfont}{\sffamily\gtfamily\ebseries}

_images/pxchfon-title1.png見出しの和文を極太に変更

実際には欧文も変更しないと見た目に一貫性がありません。とはいえ、まじめに妥当な欧文書体を探して変更するのもいささか面倒です。

和文フォント内にある従属欧文を使うことはあまりお勧めされませんが、見出しに限るなら使ってもさほど違和感はないでしょう。pxchfon パッケージの読み込み時に relfont オプションを付けておき、従属欧文フォント使用前に \userelfont を使って使用宣言します。

\usepackage[relfont]{pxchfon}
 …
\setxboldgothicfont{A-OTF-UDShinGoPr6N-Heavy.otf}
\renewcommand{\headfont}{\userelfont\sffamily\gtfamily\ebseries}

_images/pxchfon-title2.png見出しの欧文を従属欧文に変更

さらなる沼へ

さらに深みに挑みたい方向けに、いくつかのポインタを挙げておきます(以下にもあるとおり pxchfon パッケージ開発者 @zr_tex8r さんのブログは特に参考になります)。

2018/12/6, 2018/12/9, 2018/12/10, 2018/12/15 by @kmuto

Re:VIEW 向け日本語 TeX Live 環境のセットアップ(Linux、macOS、Windows)

OS のパッケージに頼らず、TeX Live の最新版をインストールする方法を説明します。


TeX Live は、TeX とそれにまつわる環境一式を提供する巨大な集合体です。

インストールに必要な作業自体はそう難しくはないのですが、デフォルトでは「すべて」をインストールしようとするために膨大な容量と時間を消費するほか、ネットワークからのダウンロードではエラーで失敗することも多々あります。日本語で Re:VIEW を利用する上では使わないであろうファイルもたくさんあります。

ここでは「Re:VIEW の PDF 変換が通りさえすればよい」という割り切りのもとで TeX Live のセットアップ手順を紹介します。

  • 執筆時点の TeX Live 2018 に基づいています。

  • Debian GNU/Linux・Ubuntu Linux、macOS、Windows 10 を前提にしています。

  • TeX コンパイラには upLaTeX を利用することを前提とします。特にフォントの設定については LuaLaTeX のほうがシステムフォントの探索などでのトラブルが少ないのですが、現状の Re:VIEW の基本設定では upLaTeX コンパイラをデフォルトとしています。

  • Debian GNU/Linux、Ubuntu Linux で OS のパッケージを利用して最小構成を構築したい場合は、Re:VIEW image for Docker の Dockerfile の内容が参考になるでしょう。

説明の都合で、Windows のインストールは本記事の後のほうに記しています。

TeX Live のインストール(Linux・macOS)

TeX Live のインストーラは install-tl という名前のファイルです。Linux・macOS いずれでも、サイトから「install-tl-unx.tar.gz」をダウンロードします。

ここではホームの Download フォルダにダウンロードしたとします。ターミナルを開いて以下のように tar.gz アーカイブファイルを展開し、そのフォルダに移動します。

$ cd ~/Download
$ tar xvf install-tl-unx.tar.gz
install-tl-20181205/...
 ...
$ cd install-tl-*

次に、この中の install-tl を root 権限で実行します。

$ sudo ./install-tl

(最近は安定していて再現性がないのですが、このあとの工程でパッケージのダウンロードおよび検証に失敗するようであれば、ダウンロード先を明示してみると解決するかもしれません。たとえば JAST ミラーであれば、sudo ./install-tl --repository http://ftp.jaist.ac.jp/pub/CTAN/systems/texlive/tlnet/ と指定します。)

_images/tl-menu1.pngTeX Live インストーラメインメニュー

テキストベースのインストーラの画面が開きます。デフォルトではスキームに scheme-full が選択されていて、すべてのパッケージファイルがインストールされてしまう(5.6GB にもなる)ので、まずはこれを変更します。

メニューにあるとおり S と入れて Enter キーを押します。

スキームの選択になります。TeX のスタイルなど個々の機能や拡張はパッケージとして配布されています。TeX Live ではこのパッケージを言語あるいは TeX コンパイラなどの目的単位にグループ化し、コレクションと呼んでいます。さらにこのコレクションを、依存関係も考慮してユーザー向けにもう少しわかりやすい選択肢としてまとめたものがスキームです。

ここではスキームを最小のものにするために「e. minimal scheme」を選ぶことにします。e、Enter キーと押します。これで e 行が [X] となるので、R、Enter キーと押してメニューに戻ります。

_images/tl-menu2.pngスキームの選択

メインメニューから今度はコレクションを選ぶため、C、Enter キーと押します。

コレクションの一覧が表示されます。スキームを最小にしたので、「a. Essential programs and files」だけに [X] とチェックが付いている状態です。Re:VIEW で日本語利用を使う範囲で見回して、以下を使うことにします。「fundamental」のように外すとまずいのでは? と怖くなるかもしれませんが、依存関係でこれらは自動で選ばれるので問題ありません。

  • c. TeX auxiliary programs

  • f. Recommended fonts

  • x. Japanese (依存関係で m. Chinese/Japanese/Korean (base) も入る)

  • E. LaTeX additional packages (依存関係で F. LaTeX recommended packages、D. LaTeX fundamental packages も入る)

これらにチェックを付けるため「cfxE」とまとめて記入し、Enter キーを押します。

_images/tl-menu3.pngコレクションの選択

必要であればほかに以下を加えるのもよいでしょう。

  • e. Additional fonts:いろいろな欧文フォントを利用したい場合

  • G. LuaTeX packages: LuaTeX を使いたい場合

R、Enter キーと押してメインメニューに戻ります。

次はオプションを設定します。O、Enter キーでオプションメニューに移動します。

_images/tl-menu4.pngオプションの設定

以下の2つのオプションは TeX のドキュメントやソースコードのインストール設定ですが、Re:VIEW から TeX を利用するだけであれば使うことがないでしょう(レイアウトをいろいろ変更したいというときには、これらのオプションはそのままにしておくべきです! texdoc コマンドを使って TeX のドキュメントを参照できます。ネットのつまみ食いはお腹を壊します)。

  • D. install font/macro doc tree

  • S. install font/macro source tree

D、Enter キー、S、Enter キーでチェックを外し、R、Enter キーでメインメニューに戻ります。

これで Re:VIEW を動かすに足る最小構成ができました。I、Enter キーでダウンロードとインストールを実行します。ブロードバンドであれば、20〜30分ほどでダウンロードとセットアップが完了します。

_images/tl-menu5.pngTeX Live のインストール完了

最後のメッセージにあるとおり、プログラムは /usr/local/texlive/<TeX Liveバージョン>/bin/<アーキテクチャ名> フォルダに用意されるので、ここにパスを通す必要があります。たとえば次のようにホームフォルダの .bashrc に追加します(これはパスの先頭に TeX Live へのパスを通します)。

$ echo "PATH=/usr/local/texlive/2018/bin/x86_64-darwin:$PATH" >> ~/.bashrc (macOSの場合)
$ echo "PATH=/usr/local/texlive/2018/bin/x86_64-linux:$PATH" >> ~/.bashrc (Linuxの場合)

ターミナルを開き直し、TeX Live がインストールされていることを確認しましょう。

$ uplatex --version
e-upTeX 3.14159265-p3.8.1-u1.23-180226-2.6 (utf8.uptex) (TeX Live 2018)
kpathsea version 6.3.0
ptexenc version 1.3.6
Copyright 2018 D.E. Knuth.
There is NO warranty.  Redistribution of this software is
covered by the terms of both the e-upTeX copyright and
the Lesser GNU General Public License.
For more information about these matters, see the file
named COPYING and the e-upTeX source.
Primary author of e-upTeX: Peter Breitenlohner.

Re:VIEW のプロジェクトで rake pdf を実行して、正常に PDF が生成されることも確認します。

  • コレクションの選定は、@munepixyz さんが作られている最小プロファイルを参考。

  • XeTeX パッケージは過去 dvipdfmx コマンドの実行に必要だったが、整理されて dvipdfmx パッケージが基本コレクションに収録されるようになったので、XeTeX を使うのでなければ選択する必要はなくなっている模様。

Ghostscript のインストール(Linux・macOS)

以降のフォントの自動設定をしたかったり、あるいはドキュメント内で eps 形式のファイルを使いかったりするときには、TeX Live とは別に、Postscript インタプリタの Ghostscript が必要です。

Debian GNU/Linux や Ubuntu Linux の場合は deb パッケージをインストールします。

$ sudo apt-get install ghostscript

macOS の場合は Homebrew を導入した上でインストールするのがよいでしょう。

$ brew install ghostscript

パッケージの追加と TeX Live の更新

後からパッケージが必要になったり、あるいは不要になったので削除したかったりといったときの TeX Live のパッケージ管理は tlmgr コマンドで行います。

また、本記事でインストールされる TeX Live は「開発の最新」のものであるため、まれに「壊れていて奇妙なエラーになる」ものがインストールされることがあります。たいていは該当のマクロパッケージの更新で修正されます。

sudo tlmgr アクション

よく使うであろうアクションを以下に示します。

  • list:関知しているパッケージ一覧を表示します。頭に i が付いているのがインストール済みのパッケージです。

  • info パッケージ名:パッケージの情報を表示します。

  • install パッケージ名:パッケージをインストールします。

  • remove パッケージ名:パッケージを削除します。

  • search 検索語句:検索語句をパッケージ名や説明に含むパッケージを探します。

  • update --list:更新可能なパッケージを報告します。

  • update --all:更新可能なパッケージの更新を実行します。

  • update --self:tlmgr 自体を更新します。

コレクションやスキームもパッケージの一種なので、tlmgr install collection-コレクション名tlmgr install scheme-スキーム名 でまとめてインストールすることも可能です。

Linux で sudo コマンドを使う場合、secure_path 設定に TeX Live のパスを追加する必要があるかもしれません。visudo コマンドで以下のようにパスを加えておきましょう。

Defaults  secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
 ↓
Defaults  secure_path="/usr/local/texlive/2018/bin/x86_64-linux:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

フォントの設定(macOS)

生成される PDF の日本語フォント(リュウミンや中ゴシックなど)の代替書体には、デフォルトで IPA フォントが割り当てられています。macOS のシステムにデフォルトでインストールされているヒラギノフォントを利用するには、もう少し設定が必要です。

現時点で macOS で最も手軽にヒラギノフォントを設定する方法として、@munepixyz さんが作成されている「[改訂第7版]LaTeX2e美文書作成入門 ヒラギノフォントパッチ」があります。名前からは『LaTeX2e美文書作成入門』(技術評論社)専用ツールに見えますが、install-tl で構築した TeX Live 環境にもそのまま適用可能です。

パッチリリースページ https://github.com/munepi/bibunsho7-patch/releases から、最新の dmg ファイルをダウンロードします。

_images/patch1.pngBibunsho7-patchのダウンロード

執筆時点では Bibunsho7-patch-1.3-20181128.dmg が最新だったので、これをダウンロードしました。ダウンロードした dmg ファイルを開き、この中の Patch.app を実行します。

ファイル情報が表示されますが、「Patchを開く」をクリックして進みます(このとき、インターネットからダウンロードしたアプリケーションへの警告が示されることがありますが、仕方がないので「開く」を押して進みます)。

_images/patch2.pngPatchの実行

ヒラギノフォントの設定に必要な処理がひととおり行われ、終了すると「完了」と表示されます。

_images/patch3.pngヒラギノフォントの自動設定処理

これで、デフォルトの日本語はヒラギノの明朝・ゴシックに自動で切り替わります。

  • 設定は /usr/local/texlive/texmf-local フォルダに対して行われます。

  • macOS のヒラギノフォントの形式および置き方は、macOS の今後の更新によって変化する可能性があります。TeX Live 開発元はヒラギノフォントの利用を何ら推奨していないことに注意してください。

フォントの設定(macOS+一部手作業)

上記の Bibunsho7-patch の内部で実行されていることも含めて、パッチプログラムによらず手動で行う方法、および別のフォントセットに切り替える方法を説明します。

これには cjk-gs-integrate-macos というパッケージが便利です。外部の商業フォントファイルを使用する cjk-gs-integrate-macos のようなパッケージは、TeX Live の主リポジトリとは分離された TLContrib というリポジトリに置かれています。

まずそのリポジトリを使うよう tlmgr コマンドで設定します。

$ sudo tlmgr repository add http://contrib.texlive.info/current tlcontrib
$ sudo tlmgr pinning add tlcontrib '*'

続いてパッケージをインストールします。

$ sudo tlmgr install japanese-otf-nonfree japanese-otf-uptex-nonfree ptex-fontmaps-macos cjk-gs-integrate-macos

念のために、フォントのリンクファイルやエイリアスファイルなどを綺麗にします。

$ sudo cjk-gs-integrate --link-texmf --cleanup

そして、macOS のシステムのフォントファイルを TeX Live から利用できるようにリンクします(-macos と付くことに注意してください)。

Mojave の場合:

$ sudo cjk-gs-integrate --fontdef-add=cjkgs-macos-highsierra.dat --link-texmf --force

Hight Sierra までの場合:

$ sudo cjk-gs-integrate-macos --link-texmf

リンクしたファイルを TeX のプログラムから見つけられるよう、ファイルデータベースを更新します。

$ sudo mktexlsr

これで準備ができました。次に kanji-config-updmap-sys コマンドでヒラギノを利用するよう設定しますが、macOS のバージョンによりマップ名が異なります。

High Sierra 以降の場合:

$ sudo kanji-config-updmap-sys --jis2004 hiragino-highsierra-pron

Sierra 以前の場合:

$ sudo kanji-config-updmap-sys --jis2004 hiragino-elcapitan-pron
  • --jis2004 オプションは、JIS2004 の例示字形を使う指定です(二点しんにょうなど)。

  • 「pron」の pro は Adobe-Japan 1-4 以降準拠の文字セットに準拠しており、n は JIS2004 字形を使っているという意味です。一般には Adobe-Japan 1-6 準拠の Pr6 あるいは Pr6N のフォントを使うことになるでしょう。

これで出来上がりです。Re:VIEW プロジェクトをコンパイルして、書体が変わることを確認しましょう。

小塚やモリサワのフォントを購入あるいは購読しているならば、それを使うこともできます。システムにこれらのフォントが入っていれば、cjk-gs-integrate-macos コマンドの実行で /usr/local/texlive/texmf-local/fonts/opentype/cjk-gs-integrate フォルダにフォントファイルへのリンクができています。macOS のヒラギノフォントの置き方および字形は macOS のバージョンによって変わることがあるため、可能ならば変化の少ないそれらの商用フォントを利用したほうが妥当です。

kanji-config-updmap-sys コマンドの status オプションで利用可能か調べられます。

$ sudo kanji-config-updmap-sys status
CURRENT family for ja: hiragino-elcapitan-pron
Standby family : hiragino-elcapitan
Standby family : ipa
Standby family : ipaex
Standby family : kozuka
Standby family : kozuka-pr6n
Standby family : morisawa
Standby family : morisawa-pr6n
Standby family : ms-osx
Standby family : toppanbunkyu-sierra

変更するには表示されているファミリ名を指定します。以下ではモリサワ Pr6N ファミリに変更しています。

$ sudo kanji-config-updmap-sys morisawa-pr6n
kanij-config-updmap-sys のフォントセット候補

kanji-config-updmap-sys コマンドで示されるフォントセット候補をまとめておきます。セットで利用するフォントが見つからない場合は候補には表示されません。/usr/local/texlive/texmf-local/fonts 下位フォルダにフォントファイルを入れているはずなのに表示されないときには、sudo mktexlsr で TeX のファイル探索データベースを更新し直してみてください。

  • ms-hg:MS 系フォント + HG フォント

  • ipa-hg:IPA フォント + HG フォント

  • ipaex-hg:IPAex フォント + HG フォント

  • moga-mobo:Moga フォント + Mobo フォント

  • moga-mobo-ex:MogaEx フォント + MoboEx フォント

  • moga-maruberi:Moga フォント + モトヤ L マルベリ

  • kozuka-pro:小塚フォント Pro

  • kozuka-pr6:小塚フォント Pr6

  • kozuka-pr6n:小塚フォント Pr6N

  • hiragino-pro:ヒラギノ6書体 Pro/Std + 明朝 W2

  • hiragino-pron:ヒラギノ6書体 ProN/StdN + 明朝 W2

  • hiragino-elcapitan-pro:ヒラギノ(macOS El Capitan版)Pro/Std + 明朝 W2

  • hiragino-elcapitan-pron:ヒラギノ(macOS El Capitan版)ProN/StdN + 明朝 W2

  • morisawa-pro:モリサワ7書体 Pro

  • morisawa-pr6n:モリサワ7書体 Pr6N

  • yu-win:遊書体(Windows 8 版)

  • yu-win10:遊書体(Windows 10 版)

  • yu-osx:遊書体(macOS 版)

フォントの設定(Linux+商用フォント)

cjk-gs-integrate-macos はありませんが、Linux でもおおむね macOS と考え方は同じです。

macOS の手順と同じように TLContrib から japanese-otf-nonfree および japanese-otf-uptex-nonfree パッケージをインストールします。

$ sudo tlmgr repository add http://contrib.texlive.info/current tlcontrib
$ sudo tlmgr pinning add tlcontrib '*'
$ sudo tlmgr install japanese-otf-nonfree japanese-otf-uptex-nonfree

購入済みあるいは購読している小塚やモリサワ・ヒラギノのフォントを、/usr/share/fonts または /usr/local/share/fonts に入れておきます。サブフォルダを作成してもかまいません。

次に、cjk-gs-integrate でリンクを作成します。このツールの挙動としては、/usr/local/texlive/TeX Liveバージョン/texmf-dist/fonts/misc/cjk-gs-integrate フォルダにある dat ファイルに定義されているフォント名と合致した場合には、シンボリックリンクが作られます。うまく作られないときには、dat ファイルと照合して、元ファイルのファイル名が正しいかを確認しましょう。

$ OSFONTDIR=/usr/local/share/fonts// sudo -E cjk-gs-integrate --link-texmf

ここでは環境変数 OSFONTDIR で /usr/local/share/fonts を追加探索パスとしています(// は下位サブフォルダもすべて探索するという意味です)。また、環境変数を尊重するよう sudo コマンドには -E オプションを付けました。

実行が済んだら、リンクしたファイルを TeX のプログラムから見つけられるよう、ファイルデータベースを更新します。

$ sudo mktexlsr

kanji-config-updmap-sys コマンドでマップを設定します。

$ sudo kanji-config-updmap-sys status (利用可能なマップを一覧)
$ sudo kanji-config-updmap-sys --jis2004 morisawa-pr6n (JIS2004のモリサワフォント)
  • ★/usr/local/share/fontsがfontconfigに設定されているのはDebian系だけだろうか。RH系でもそうならcjk-gs-integrate自体で/usr/local/share/fontsをデフォルトで探索に加えてくれるよう要望すべきか?

フォントの設定(Linux+Noto フォント)

Google とAdobe が作成した Noto CJK フォント は、オープンソースライセンスの高品質なフォントです。Google では Noto Serif CJK・Noto Sans CJKという名前、Adobe では源ノ明朝・源ノ角ゴシックという名前で配布されていますが、実体としては同じです。

Noto CJK にはその名前のとおり中国語・日本語・韓国語の字形が含まれますが、ここではひとまず日本語のみに絞って設定する方法を紹介しておきます。まず、Serif(明朝体)と Sans(ゴシック体)の2つのフォントをダウンロードします。

/usr/local/texlive/texmf/fonts/opentype に適当にフォルダを作って、ダウンロードした zip ファイルを展開します(OS で利用できるように別フォルダに置いた場合には、そこからシンボリックリンクを張ります)。たとえば次のようになります。

.
├── noto-sanscjk
│   ├── LICENSE_OFL.txt
│   ├── NotoSansCJKjp-Black.otf
│   ├── NotoSansCJKjp-Bold.otf
│   ├── NotoSansCJKjp-DemiLight.otf
│   ├── NotoSansCJKjp-Light.otf
│   ├── NotoSansCJKjp-Medium.otf
│   ├── NotoSansCJKjp-Regular.otf
│   ├── NotoSansCJKjp-Thin.otf
│   ├── NotoSansMonoCJKjp-Bold.otf
│   ├── NotoSansMonoCJKjp-Regular.otf
│   └── README
└── noto-serifcjk
    ├── LICENSE_OFL.txt
    ├── NotoSerifCJKjp-Black.otf
    ├── NotoSerifCJKjp-Bold.otf
    ├── NotoSerifCJKjp-ExtraLight.otf
    ├── NotoSerifCJKjp-Light.otf
    ├── NotoSerifCJKjp-Medium.otf
    ├── NotoSerifCJKjp-Regular.otf
    ├── NotoSerifCJKjp-SemiBold.otf
    └── README

TeX のファイルデータベースを更新するために mktexlsr コマンドを実行します。

$ sudo mktexlsr

Noto フォントは kanji-config-updmap-sys の選択肢にはないので、使用書体の変更(upLaTeX 編) にあるとおり pxchfon パッケージを使います。Re:VIEW のプロジェクトの sty/review-custom.sty に次のように追加します。

\usepackage[noto]{pxchfon}

JIS2004 字形にする場合は、config.yml の texdocumentclass パラメータに jis2004 オプションを追加します。

texdocumentclass: ["review-jsbook", "media=print,paper=a5"]
  ↓
texdocumentclass: ["review-jsbook", "media=print,paper=a5,jis2004"]

_images/noto.pngJIS2004 字形の Noto フォント表示

TeX Live のインストール(Windows)

ここでは Windows 10 へ TeX Live をインストールする方法を説明します。

サイトから install-tl-windows.exe をダウンロードし、実行します。

(こちらも、このあとの工程でパッケージのダウンロードおよび検証に失敗するようであれば、ダウンロード先を明示してみると解決するかもしれません。たとえば JAST ミラーであれば、コマンドプロンプトを開き、cd コマンドでダウンロードしたフォルダに移動した上で、install-tl-windows --repository http://ftp.jaist.ac.jp/pub/CTAN/systems/texlive/tlnet/ と指定します。)

「不明な発行元」の警告が表示されることがありますが、仕方がないので継続して実行しましょう。

ミニインストーラが起動します。

_images/tl-win1.pngTeX Live ミニインストーラの起動

デフォルトでは「Simple install (big)」が選ばれていますが、「Custom install」にチェックして「Next>」ボタンをクリックします。次に「Install」をクリックして先に進みます。しばらく待つと本番の GUI インストーラが起動します。

_images/tl-win2.pngTeX Live インストーラ画面と警告

管理者権限を与えていないために現在のユーザー用にしか導入できない警告が表示されますが、通常は現在のユーザーが使えれば問題ないでしょう。「続行」をクリックします。

いろいろなメニューがありますが、基本的には先の Linux・macOS と設定する項目は変わりません。

  • スキーム:「最小限スキーム」を選択

  • 導入コレクション:「TeX外部プログラム」「推奨されるフォント」「日本語」「LaTeX追加パッケージ」を選択(「不可欠なプログラムとファイル」「Windows限定サポートプログラム」はデフォルトで選択済み)。「追加フォント」「LuaTeXパッケージ」は必要に応じて

  • fontとmacroのdocツリーを導入:不要なら「いいえ」

  • fontとmacroのソースツリーを導入:不要なら「いいえ」

_images/tl-win3.pngTeX Live インストーラでの設定

選択し終えたら、「TeX Liveの導入」をクリックします。インストールが完了すると、C:\texlive\2018 に TeX Live が構築されます。インストーラメニューで記載があったように、パスは設定済みなので、すぐに利用できます。

日本語フォントセットの変更は、Linux・macOS と同様に kanji-config-updmap-sys を使えます。

_images/tl-win4.png日本語フォントセットの変更

ms は MS 明朝・ゴシック、yu-win10 は Windows 10 バンドルの遊書体です。ただし、バンドル版の遊書体はそれを埋め込みで利用した場合の頒布行動に対して可とも不可とも明示されておらず、極めて曖昧な状態に置かれています。

新しいコマンドプロンプトを開き、Re:VIEW プロジェクトをビルドできることを確認します。 _images/tl-win5.pngMS 明朝・ゴシック埋め込みでのプレビュー

モリサワなどのフォントがインストールされている場合は TLContrib から前掲の手順でセットアップします。

> tlmgr repository add http://contrib.texlive.info/current tlcontrib
> tlmgr pinning add tlcontrib '*'
> tlmgr install japanese-otf-nonfree japanese-otf-uptex-nonfree
> cjk-gs-integrate --link-texmf
> mktexlsr
> kanji-config-updmap-sys status
> kanji-config-updmap-sys --jis2004 マップ名

Noto フォントの利用は「フォントの設定(Linux+Noto フォント)」に同じです。texmf-local のパスはデフォルトのインストールでは C:\texlive\texmf-local なので読み替えて実行します。

  • Windows 向けにはいわゆる角藤版 TeX と呼ばれる W32TeX も広く使われていますが、ここでは説明の統一のために TeX Live を使うことにしました。

  • Ghostscriptは必要?(epsは使わない前提で)

  • tlmgr pinningでwarningが出るのはOK?

  • cjk-gs-integrate は only partial support for Windows! だがどこの部分がパーシャル?

  • Windowsの場合、cjk-gs-integrateはgsなしでも動く模様。ただしすごく時間がかかる?

2018/12/24 by @kmuto

review-jsbook.cls の基本版面設計

Re:VIEW 3 で導入した review-jsbook.cls クラスでの版面設計の算出方法を紹介します。


Re:VIEW 3 からの LaTeX 処理 の「基本版面設計」で言及したとおり、新しく導入された review-jsbook.cls クラスでは、パラメータで本文領域である版面を設計できます。デフォルトでは jsbook そのままの余白が広い紙面となっているため、これを変えたいというときには版面設計が必要になります。

版面設計の考え方

版面設計の基本的な考え方はいくつかあります。

ページあたりの文字数が重要であれば、次のようになるでしょう(プランA)。

  1. 1行あたりの文字数と行数を任意に決める(行あたりの文字数×行数で1ページあたりの文字数が求められる)。

  2. 本文文字サイズと行送り(行のベースラインとベースラインの間隔)を任意に決める。

  3. 上記から求められる長方形の版面を紙面内のどこに配置するかを、天およびノドからの相対位置で任意に決める。

  4. ヘッダ領域やフッタ領域を任意に決める。

本文の文字サイズから決めるのであれば、次のとおりです(プランB)。

  1. 本文文字サイズと行送り(行のベースラインとベースラインの間隔)を任意に決める。

  2. 1行あたりの文字数と行数を任意に決める。

  3. 長方形の版面を紙面内のどこに配置するかを、天およびノドからの相対位置で任意に決める。

  4. ヘッダ領域やフッタ領域を任意に決める。

余白から決めていきたいなら、少々ややこしいですが次のようになります(プランC)。

  1. 天・ノド・地・小口を任意に決める。

  2. 本文文字サイズと行送り(行のベースラインとベースラインの間隔)を任意に決める。

  3. 仕上がり紙面サイズ・文字サイズ・行送り・天・ノド・地・小口から、1行あたりの文字数と行数の近似値を算出する。

  4. ヘッダ領域やフッタ領域を任意に決める。

版面の位置および余白をどの程度にするのが妥当かというだけでもデザイン論議になるほどの内容であるため、ここでは行送りや余白の値の妥当さについては考えないことにしています。いろいろな本を見てみて、気に入ったものがあればそのサイズを計測して真似してみるところから始めるのがよいでしょう。

Re:VIEW での版面設計の設定

ではそれぞれのプランに基づいた Re:VIEW での設定手順を考えます。ここでは紙面は A5(paper=a5)を使うことにします。何も指定をしていない状態では、次のような版面になっています。

_images/layout-a-0-s.pngデフォルトの版面

プランA〜Cのそれぞれのアプローチを進めてみましょう(あえて結果は同じにしています)。

とその前に、Re:VIEW 3.0 の review-jsbook.cls には jsbook.cls 固有の理由で行数計算が1行不足してしまいます。sty/review-jsbook.cls の334行を以下のように変更してください(3.1 で修正予定です)。

  \addtolength\textheight{1H}
    ↓
  \addtolength\textheight{\dimexpr\topskip-\Cht}%%adjustment for jsbook.cls's \topskip
ページあたりの文字数から設計(プランA)

最初に、ページあたりおよそ900文字を収めたいと考えました。

ただ、実際には行あたり文字数×行数を考えると、うまい具合にバランスのよい長方形ができて900に近いという値を求めるには少々経験が必要になります。Web などでサンプルを見ながら考えると、「行あたり31文字×29行」だと899文字、許容範囲になりそうです。

指定すべきこのパラメータとしては line_length=31zw,number_of_lines=29 となります。zw はいわゆる全角幅で、日本語での文字数を考えるのに便利なのでここではこの単位を使っています。

_images/layout-a-1-s.png列と行を指定

次に紙面で許容される範囲の文字サイズと行送りを考えます。標準は文字サイズ 10pt・行送り16pt ですが、少し大きくして文字サイズ 11pt、行送り 17.5pt(fontsize=11pt,baselineskip=17.5pt)としてみます。

_images/layout-a-2-s.png文字サイズと行送りを指定

(実はこの「文字サイズ」には暗部があります。詳しくはプランCで説明します。)

版面ができたので、紙面のどこに置くかを考えます。中心合わせとさして変わりませんが、天15mm、ノド17mmとしてみました(head_space=15mm,gutter=17mm)。

_images/layout-a-3-s.png天とノドを指定

ヘッダ領域に柱、フッタ領域にノンブル(ページ番号)も置いてみました。

_images/layout-a-4-s.pngヘッダとフッタを表示

版面を調整した結果、版面とノンブルとの間が狭く感じられます。逆に柱はページの上に置かれすぎているようにも感じます。ヘッダ下部と版面上部の間を2mm、フッタ上部と版面下部の間を7mmに設定してみます(headsep=2mm,footskip=7mm)。

_images/layout-a-5-s.pngヘッダとフッタの相対位置を指定

完成です! config.yml のパラメータは次のようになります(印刷物用には media=print としてください)。

texdocumentclass: ["review-jsbook", "media=ebook,paper=a5,line_length=31zw,number_of_lines=29,fontsize=11pt,baselineskip=17.5pt,head_space=15mm,gutter=17mm,headsep=2mm,footskip=7mm"]
本文の文字サイズから設計(プランB)

標準は文字サイズ 10pt・行送り16pt ですが、少し大きくして文字サイズ 11pt、行送り 17.5pt(fontsize=11pt,baselineskip=17.5pt)とすることにしました。

_images/layout-b-1-s.png文字サイズと行送りを指定

デフォルトよりもう少し広げて、行あたり31文字×29行にします(line_length=31zw,number_of_lines=29)。

_images/layout-b-2-s.png列と行を指定

紙面のどこに置くかを考えます。天15mm、ノド17mmとします(head_space=15mm,gutter=17mm)。

_images/layout-b-3-s.png天とノドを指定

これでプランAと同様になったので、同じようにヘッダとフッタの間隔を調整します(headsep=2mm,footskip=7mm)。

_images/layout-b-4-s.pngヘッダとフッタの相対位置を指定

config.yml のパラメータは次のようになります(印刷物用には media=print としてください)。実際にはパラメータの順序は問わないので、プランAのように書いても同じことです。

texdocumentclass: ["review-jsbook", "media=ebook,paper=a5,fontsize=11pt,baselineskip=17.5pt,line_length=31zw,number_of_lines=29,head_space=15mm,gutter=17mm,headsep=2mm,footskip=7mm"]
余白から設計(プランC)

ここまできたら、プランCもおおよそ予測がつくのではないでしょうか。

版面の天を15mm、ノドを17mmとし、地は17mm、小口は21mm程度にしたいとします。地と小口は厳密にその値になるとは限りません。今パラメータとして指定できるのは天とノドだけです(head_space=15mm,gutter=17mm)。

_images/layout-c-1-s.png天とノドを指定

文字サイズ 11pt、行送り 17.5pt(fontsize=11pt,baselineskip=17.5pt)とすることにしました。

_images/layout-c-2-s.png文字サイズと行送りを指定

1行あたりの文字数と行数を近似値で算出します。横書きなので、次のように計算します。

  • 1行あたりの文字数=((仕上がり紙面横幅)−(ノド)−(小口))÷(文字サイズ)=((148mm)-(17mm)−(21mm))÷(11pt×0.962216×0.961≒10.17pt=3.56967mm)≒30.815文字

  • 行数=((仕上がり紙面縦幅)−(天)−(地))÷(行送り)=((210mm)−(15mm)−(17mm))÷(17.5pt=6.1425mm)≒28.978行

よって、おおむね1行あたり31文字、29行にするとよさそうです(line_length=31zw,number_of_lines=29)。

_images/layout-c-3-s.png列と行を指定

さて、「文字サイズ」には暗部がある、と先述したとおり、文字サイズの式が異様ですね。実は 11pt と指定したつもりでも、一般的なDTPソフトウェアで作る 11pt とは違うのです。

  • 0.962216という謎の係数その1は、和文文字に掛けられる縮小です。11ptと指定したのはあくまでも欧文文字の値であり、和欧間でバランスよくなるように和文文字(私たちがここで文字数と考えたいもの)には縮小がかけられます。よって、和文のほうは11ptではなく、約10.584376ptになります。

  • さらに続く0.961という謎の係数その2は、jsbook で和文文字に掛けられる縮小です(これもバランスが理由です)。上記の係数その1にさらに加えて縮小されます。よって、11ptと指定しましたが、和文文字(文字数として考えたいもの!)は約10.17ptになります。

  • また、TeXのpt値は、DTPで一般的な「1pt=72分の1インチ、0.353mm」ではなく、英米ポイントの「1pt=72.27分の1、0.351mm」です。ややこしい。よって、もともと通常のDTPソフトよりもわずかに小さくなります。

最後の pt 値の違い以外は、TeX というよりも jsbook クラス側の設計によるものであることに注意してください。たとえば jlreq / review-jlreq クラスの場合、和欧のデフォルトの比率は1になっています。

jsbook クラスで作成した従来のデータとの互換性を考え、ややこしいことはやむを得ないとして review-jsbook クラスでも jsbook のこの単位系をそのまま使っています(より厳密にはそのまま jsbook クラスに任せています)。

ヘッダとフッタの間隔を調整し(headsep=2mm,footskip=7mm)、完成です。

_images/layout-c-4-s.pngヘッダとフッタの相対位置を指定

config.yml のパラメータは次のようになります。

texdocumentclass: ["review-jsbook", "media=ebook,paper=a5,head_space=15mm,gutter=17mm,fontsize=11pt,baselineskip=17.5pt,line_length=31zw,number_of_lines=29,headsep=2mm,footskip=7mm"]

このように、プランA〜Cは異なるアプローチをとりましたが、いずれも最後は同じパラメータとなりました。

2019/3/17 by @kmuto

カスタムなページ(権利表記、広告や裏表紙など)の挿入

Re:VIEW がデフォルトで提供している、書籍に関するいくつかの生ファイルの取り込みスポットとその書き方を説明します。


EPUB や PDF での書籍を形成する際、Re:VIEW の範疇を超えた任意のレイアウトのページを入れる必要が生じることがあります。Re:VIEW は以下の箇所について(re ファイルではなく)HTML や TeX ソースなどの生のファイルを取り込む機能を提供しています。

  • titlefile: 大扉(※これは Re:VIEW 側が一応デフォルトのものを提供します)

  • originaltitlefile: 翻訳書での原書大扉

  • creditfile: 権利表記

  • profile: プロフィール

  • advfile: 広告

  • colophon: 奥付(※これは Re:VIEW 側が一応デフォルトのものを提供します)

  • backcover: 裏表紙

これらは本文ほど決まったレイアウトがなく、汎用化しづらいものです。大扉と奥付は Re:VIEW がデフォルトのものを一応提供はするものの、もっと任意の形にしたいこともあるでしょう。

EPUB での任意ファイルの挿入

EPUB 向けの任意ファイルは、単純な HTML と少し違い、EPUB 向けの XHTML 形式で記述する必要があります。特に注意することとして、HTML タグの省略は禁止されているので、img タグなどの単一タグは <img /> のように閉じる必要があります。

EPUB向けの XHTML ファイルの雛型はたとえば以下のようになります。config.yml で debug: true を指定して EPUB を作成し、book-epub フォルダの中身から適当な HTML ファイルをコピーして使う、でもよいでしょう。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xmlns:ops="http://www.idpf.org/2007/ops" xml:lang="ja">
<head>
  <meta charset="UTF-8" />
  <link rel="stylesheet" type="text/css" href="style.css" />
  <meta name="generator" content="Re:VIEW" />
  <title>プロフィール</title>
</head>
<body>
<div class="profile">
<h3>りびゅー太郎</h3>
<p><img src="images/reviewtaro.png" class="left" />
りびゅー太郎は、Re:VIEWの非公式ゆるキャラである。</p>
</div>
</body>
</html>

EPUB の場合は title タグの内容は無視されます。div タグで囲む必要も特にありませんが、CSS で固有の装飾をするときには囲んでおいたほうが指定しやすいでしょう。画像ファイルは別途 images フォルダに入れておきましょう。

上記の内容をプロジェクトフォルダ(config.yml と同じフォルダ)に profile.xhtml という名前で保存しておき、これをプロフィールページとして使うように config.yml に設定します。EPUB と PDF で別々のファイルを使いたいので、ここでは epubmaker セクションの下で設定することにします。

 …
epubmaker:
  profile: profile.xhtml
 …

これで、rake epub または review-epubmaker config.yml により生成される EPUB にプロフィールページが含まれるようになります。

ほかの取り込みパラメータも、パラメータ名が違うだけでやり方は同じです。

PDF(LaTeX)での任意ファイルの挿入

PDFMaker でファイルを差し込むには、LaTeX で記述されたファイルを用意します。ただし、プリアンプルや \begin{document}\end{document} は含みません。

ただ、LaTeX で「任意のレイアウト」を実現するには、それなりに LaTeX/TeX の知識を必要としますし、ベースのレイアウトのくびきから逃れるだけでも大変なので、何らかの方法で差し込み用の PDF を用意し、それを貼り込むのが最も簡単でしょう。

たとえば仕上がりと同じ紙サイズでのプロフィールの PDF「profile.pdf」を images フォルダに置き、以下の内容をプロジェクトフォルダに profile.tex という名前で保存します。

\includefullpagegraphics{images/profile.pdf}

これをプロフィールページとして使うように config.yml の pdfmaker セクションに設定します。

 …
pdfmaker:
  profile: profile.tex
 …

これで、rake pdf または review-pdfmaker config.yml により生成される PDF にプロフィールページが含まれるようになります。

2019/8/16 by @kmuto

コードブロック内で自動改行する

emlist などのコード系のブロック命令内で自動で折り返し改行する方法を示します。


list や emlist、listnum などのコード系のブロック命令内で1行が長いとき、折り返されずに紙面からはみ出してしまうことがよくあります。Web ブラウザのように自動で判断して紙面の妥当なところで折り返してほしいところですが、TeX でこれに対処するのは極めて困難です。

次のコードを例に、いくつかの回避策を示します。

//emlist{
@<b>{give up about handling inline-op}
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890あいうえお1234567890あいうえお1234567890あいうえお1234567890あいうえお1234567890あいうえお1234567890あいうえお
あいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえお
αΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓ
!"#$%&'()~=~|-^\`{+*}<>?_@[;:],./
//}

//emlistnum{
@<b>{give up about handling inline-op}
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
1234567890あいうえお1234567890あいうえお1234567890あいうえお1234567890あいうえお1234567890あいうえお1234567890あいうえお
あいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえおあいうえお
αΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓαΒΓ
!"#$%&'()~=~|-^\`{+*}<>?_@[;:],./
//}

_images/linebreak-init.png長いコードははみ出す

物理的に改行を入れる

最も単純な方法は、コードに直接改行を入れることです。

明確で、インライン命令も利用可能なので、可能であればこの手法が最も妥当です。

しかし、「自動的に折り返したい」というこの記事の趣旨に合わないのと、//emlistnum//listnum のように各行頭に行番号が付く場合は普通に改行するとそこにも行番号が付いてしまって困るという問題があります。

ただし、行番号が付いていてもこの物理改行の方法で対処する場合は、「強制改行して行番号の幅だけスペースを入れる」という方法があります。強制改行には @<br>{} を使えますが、EPUB も作る場合はそちらにも影響してしまうので、以下のように @<embed> 命令を使うのがよいでしょう。

//emlistnum{
12345678901234567890123456789012345678901234567890123456789012345678901234@<embed>$|latex|\linebreak\hspace*{5ex}$56789012345678901234567890
//}

\hspace*{5ex} は、行頭であってもかまわず(*)、「x」の文字幅5つぶん(5ex)の水平方向スペース(hspace)を作る LaTeX マクロです。5ex の部分は実際のレイアウトに合わせて調整する必要があるかもしれません。

コードハイライトの副次的な機能で自動改行する

コードハイライト (キーワード太字にしたりするなど) の listings マクロを使うと、その副次的な機能として単語間で折り返しをしてくれます。

コードハイライトを有効にするには、config.yml の以下の箇所を有効にします。

highlight:
  latex: "listings"

行の折り返しはマクロが勝手に行いますが、ある程度指示したいときには、行の途中に空白文字を埋め込むとよいでしょう。

//emlistnum{
1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 12345@<embed>{|latex| }67890 1234567890 1234567890 1234567890
//}

listings マクロは行番号表現も提供しています。

_images/linebreak-listings.pngコードハイライトの利用

コードハイライトを有効にする代償として、コード内のインライン命令は動かず、すべてエスケープされた文字となってしまいます(図中の \reviewbold)。

対策のヒントは以下の記事に少し示しています。

また、行中に単語の区切りが見つからないと、折り返しできずにやはりはみ出してしまいます。

文字数を見て折り返す

Re:VIEW PR#1368 が反映された Re:VIEW 3.3 以上が必要ですが、コードの各行の処理部分に割り込み、文字の幅を数えて折り返し位置になったら折り返し文字を入れて改行するという方法があります。

Re:VIEW のデフォルトでは、各行の処理部分は code_line (行番号なし)、code_line_num (行番号あり) として以下のように定義されています。

def code_line(_type, line, _idx, _id, _caption, _lang)
  detab(line) + "\n"
end

def code_line_num(_type, line, first_line_num, idx, _id, _caption, _lang)
  detab((idx + first_line_num).to_s.rjust(2) + ': ' + line) + "\n"
end

各行の処理部分を書き換えるには、以下のような review-ext.rb ファイルをプロジェクトに置きます。

module ReVIEW
  module LATEXBuilderOverride
    # gem install unicode-display_width
    require 'unicode/display_width'
    require 'unicode/display_width/string_ext'

    CR = '→' # 送り出し文字。LaTeXコードも可
    ZWSCALE = 0.875 # 和文・欧文の比率。\setlength{\xkanjiskip}{\z@} しておいたほうがよさそう

    def split_line(s, n)
      # 文字列を幅nで分割
      a = []
      l = ''
      w = 0
      s.each_char do |c|
        cw = c.display_width(2) # Ambiguousを全角扱い
        cw *= ZWSCALE if cw == 2
        
        if w + cw > n
          a.push(l)
          l = c
          w = cw
        else
          l << c
          w += cw
        end
      end
      a.push(l)
      a
    end

    def code_line(type, line, idx, id, caption, lang)
      # _typeには'emlist'などが入ってくるので、環境に応じて分岐は可能
      n = 64
      n = 60 if @doc_status[:column]
      a = split_line(unescape(detab(line)), n)
      # インラインopはこの時点でもう展開されたものが入ってしまっているので、escapeでエスケープされてしまう…
      escape(a.join("\x01\n")).gsub("\x01", CR) + "\n"
    end

    def code_line_num(type, line, first_line_num, idx, id, caption, lang)
      n = 60
      n = 56 if @doc_status[:column]
      a = split_line(unescape(detab(line)), n)
      (idx + first_line_num).to_s.rjust(2) + ': ' + escape(a.join("\x01\n    ")).gsub("\x01", CR) + "\n"
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

ここでは紙面はA5、emlist 等の TeX 側のスタイルはデフォルトから変えていないものとします。

別の紙サイズを使用していたりスタイル変更をしている場合は、code_linecode_line_numn の値を適宜調整する必要があります。

Unicode での文字の幅の判定のために unicode-display_width という gem を使っているので、gem install unicode-display_width でインストールしておきましょう。

この文字折り返しの結果は次のとおりです。

_images/linebreak-ext.png文字幅ベースの折り返し

だいぶいい感じになりましたね!

ただ、和文欧文が入り交じった箇所では、ずれてしまっています。これは、コード内でも和欧間のスペースが効いているためです。

たとえば以下のように sty/review-base.sty に xkanjiskip をゼロにする設定(\setlength{\xkanjiskip}{\z@})を加えることで、この和欧間スペースをなくせます。

\newenvironment{reviewemlist}{%
  \medskip\small\begin{shaded}\setlength{\xkanjiskip}{\z@}\setlength{\baselineskip}{1.3zw}\begin{alltt}}{%
  \end{alltt}\end{shaded}}

_images/linebreak-final.png文字幅ベースの折り返し(完成版)

コードハイライトと同様の理由で、インライン命令は利用できません。とはいえ、少し工夫すれば(汎用的ではないにせよ)エスケープされたインライン命令を復帰させることもできるでしょう。

code_linecode_line_num のメソッドの1つめの引数 type には、emlist などのブロック命令名が渡ってきているので、命令ごとに異なるレイアウトを使っているときには、type の値に応じて n の値を調整するということも可能です。

定数 CR には折り返し文字を入れますが、TeX マクロをここに入れることもできます。行末ではなく行頭側に入れる、あるいは両方に別々の折り返し文字を入れる、といったことも工夫次第ですので、挑戦してみるのもよいでしょう。

番外編

逆に、たとえば id の情報を見て、特定の id であれば \scalebox{倍率}[1]{} で囲んで長体にして収める、という方法も思いつきますね。

def code_line(type, line, idx, id, caption, lang)
  if id == 'list1' # IDがlist1だったら、80%長体をかける
    '\scalebox{0.8}[1]{' + detab(line) + "}\n"
  else
    super(type, line, idx, id, caption, lang)
  end
end

2019/8/23 by @kmuto

TeX 実行時のエラーを読み解く

Re:VIEW から TeX 経由の PDF 生成の途中でエラーが発生したときの、原因の調べ方を説明します。


TeX 実行の流れ

最初に、Re:VIEW から TeX 経由で PDF を生成するときに、どういうプロセスになっているのかを理解しておく必要があります。デフォルトでは以下のような流れです。

  1. 作業用一時フォルダが生成される。これはシステムのテンポラリフォルダにランダムな名前で作成されて途中でエラーがあっても必ず最後に消されてしまうが、 config.yml で debug: true にしていた場合はプロジェクトフォルダ内に <booknameの名前>-pdf という名前で作られ、消されない。

  2. re ファイルが逐次 .tex 拡張子の LaTeX ファイルに変換され、一時フォルダ内に置かれる。

  3. 各 .tex ファイルをとりまとめる __REVIEW_BOOK__.tex が置かれ、さらにプロジェクトフォルダの sty サブフォルダの中身、および images フォルダの図版ファイル群が一時フォルダ内にコピーされる。

  4. images フォルダの図版ファイル群に対して extractbb コマンド (見つからなければ ebb コマンド) が実行され、ファイルの縦横サイズが .xbb ファイルに記録される。

  5. __REVIEW_BOOK__.tex ファイルに対して config.yml の texcommandtexoptions を合体させたコマンドが実行される。つまり、uplatex -interaction=nonstopmode -file-line-error __REVIEW_BOOK__.tex が実行される。これで、__REVIEW_BOOK__.dvi というファイルができる。

  6. 相互参照や目次などの解決のため、5.は3回繰り返し実行される。

  7. __REVIEW_BOOK__.dvi ファイルに対して dvicommanddvioptions を合体させたコマンドが実行される。つまり、dvipdfmx -d 5 -z 9 __REVIEW_BOOK__.dvi が実行される。これで、__REVIEW_BOOK__.pdf というファイルができる。

  8. 一時フォルダ内の __REVIEW_BOOK__.pdf ファイルを、プロジェクトフォルダに <booknameの名前>.pdf という名前でコピーする。

  9. debug: true でない場合は一時フォルダを消去する。

.re→.tex 変換 (ステップ2.) は Re:VIEW の管轄なので、ここで文法エラーであったり図版ファイルが不足していたりなどの明確な問題を発見したときには Re:VIEW のレベルでエラーが発生し、re ファイルの行番号も添えられるので簡単に解決できるはずです。

これに対し、5.〜7. の時点でエラーが発生したときには、すでに Re:VIEW の手を離れています。

  • マクロの解釈およびページ組み立ては uplatex の段階です。

  • フォントの実際の埋め込みは、dvipdfmx の段階です。

  • 図版ファイルの変換 (eps→PDF など) および実際の埋め込みは、dvipdfmx の段階です。

なお、rake コマンドを使っている場合は最後に (See full trace by running task with --trace) と表示されることがありますが、これは rake ルールの解析目的のオプションなので、Re:VIEW の実行処理の解析の役には立ちません。

エラーの確認

.re→.tex 変換の段階 (上記ステップ2.〜4.)

前述したように、.re→.tex変換中のエラーについては Re:VIEW が返答するので、エラーの確認は容易です。

ファイルのコピーや extractbb の実行についてもエラーメッセージから判断できるでしょう(パーミッションの問題や、実行コマンドがパスに存在しないなど)。

dvi→PDF 変換の段階(ステップ7.)

dvipdfmx でありがちなのは、フォントの設定 (フォントが実際に TeX が探せる場所に存在しないか、mktexlsr コマンドの実行忘れで更新されていない、絵文字など対応外の文字を使っているなど) か、画像変換 (フォントの埋め込まれていない日本語 eps 図版があり、PDF 変換に使う Ghostscript が対応していないなど) に関係するエラーです。

dvipdfmx は一番最後のプロセスなので、エラー時の画面出力からおおむね判断できるはずです。

TeX コンパイルの段階(ステップ5.)

そして、本記事の主眼であり、最もわかりにくいであろうものが、TeX コンパイル段階でのエラーです。

原因究明のとっかかりとしては、次のような設定をしてみるとよいでしょう。

  • debug: true にする。エラー時には行番号が示されることがありますが、これは re ファイルではなく変換された .tex ファイルについての行番号なので、解析のために一時作業フォルダを消さずに保持するようにしておきます。

  • -halt-on-error を加える。Re:VIEW 3.3 以降からはデフォルトのオプションになりますが、それより前の Re:VIEW バージョンを使っているときには、config.yml の texoptionstexoptions: "-interaction=nonstopmode -file-line-error -halt-on-error" とします(行頭の # も取ります)。これにより、TeX コンパイル時にエラーが発生したらその時点で実行を打ち切り、すぐに終了することで、エラーメッセージがスクロールで流れることなく確認できます。

TeX コンパイルエラーの読み方と試行錯誤

上記の設定をした上での TeX コンパイル時のエラーは、次のような形で表示されます。

./foo.tex:5: Extra }, or forgotten $.
l.5 \frac{1}{2}}
                
Output written on __REVIEW_BOOK__.dvi (2 pages, 2328 bytes).
Transcript written on __REVIEW_BOOK__.log.

rake aborted!
Command failed with status (1): [review-pdfmaker config.yml...]
lib/tasks/review.rake:103:in `block in <top (required)>'
Tasks: TOP => pdf => book.pdf
(See full trace by running task with --trace)

./foo.tex:5: Extra }, or forgotten $. が停止に至ったエラーの理由表示で、この場合は foo.tex の 5 行目で「Extra }, or forgotten $.」なるエラーになったことがわかります。その後に実際の 5 行目の内容が示されています。

debug: true にしていれば、プロジェクトフォルダ内に <booknameの名前>-pdf の一時作業フォルダ(特に設定した覚えがなければ book-pdf)が残っており、その中の foo.tex を調べることができます(以下の行番号は便宜的に付けたものです)。

1: \chapter{数式の誤り}
2: \label{chap:foo}
3: 
4: \begin{equation*}
5: \frac{1}{2}}
6: \end{equation*}

re ファイルを直して再度 rake pdf を実行して、でももちろんよいのですが、問題のケースによってはこのような .tex ファイルを直接編集してコンパイルが通るよう試行錯誤しなければならないこともあります。

ここではエラーメッセージのとおり、} が1つ多いのが原因なので、5行目の末尾から } を1つ削除して通るかどうか試してみます。

5: \frac{1}{2}

コンパイルしてみます。

$ uplatex -interaction=nonstopmode -file-line-error -halt-on-error __REVIEW_BOOK__.tex
 …
Output written on __REVIEW_BOOK__.dvi (5 pages, 5340 bytes).
Transcript written on __REVIEW_BOOK__.log.
$

今度はエラーが起きませんでした。元々の re ファイルにちゃんと修正を反映しましょう。

dvi だけでなく、PDF の生成もしてプレビューを確認したければ、次のように実行します。

$ dvipdfmx -d 5 -z 9 __REVIEW_BOOK__.dvi

これで、__REVIEW_BOOK__.pdf ができます。

検査範囲の絞り込み

{ } の対応関係ミスや、利用しているマクロのエラーの場合は、エラー報告された行とは別のところが原因なこともままあります。

.tex ファイル内の途中に \endinput を入れると、そこで入力を打ち切り、次のファイルの読み込みに移ります。これを使って、問題の箇所を絞り込むことができます。たとえば次のようにした場合、ブロック3以降はコンパイル対象から外されます。

(…ブロック1…)

(…ブロック2…)

\endinput

(…ブロック3…)

また、時間がかかるので章単位で削っておきたいというときは、catalog.yml でコメントアウトしておくという方法もありますが、コメントアウトしたところへの相互参照があると Re:VIEW の変換時点でエラーになってしまうという問題があります。

__REVIEW_BOOK__.tex\input{foo.tex} となっている箇所を \include{foo} (.tex も付けない)のように置換し、\begin{document} の前で \includeonly{foo} のようにすると、foo.tex だけを取り込むようになります(複数指定したい場合は \includeonly{foo,bar} のように , で区切ります)。

\include は強制改ページが発生するなどの副作用がいくらかあるために Re:VIEW では採用していないのですが、問題調査のときには便利でしょう。

Re:VIEW でありがちな TeX エラー

Re:VIEW から TeX に変換するという手順では、おかしな TeX マクロを書き出したり、エスケープすべき文字をエスケープし忘れたり、といったことはあまり起きません。そのため、review-jsbook などの十分に枯れたテンプレート(クラス・スタイルファイル)を使っていて、カスタマイズも特にしていないという状況において、出現するエラーはある程度限られたものになるはずです。

制御文字の混入
foo.tex:4: Package inputenc Error: Unicode character ^^H (U+0008)
l.4 ほげほ^^H
               げほげほげ

Visual Studio Code などで執筆・編集中に、何かの拍子で制御文字が入ってしまうことがあるようです。re ファイルに入ってしまっている制御文字を削除してください。

コラム内の図表
[1]

./__REVIEW_BOOK__.tex:134: LaTeX Error: Float(s) lost.

現時点の Re:VIEW のデフォルト構成においては、コラムに ID・キャプション付きの表を入れると、このようなエラーになります。コラムという囲まれた要素の中にフロート配置(.tex ファイル上で書いた位置を無視して独立して版面の上や下に置くことができる)をしようとしたためです。

sty/review-style.sty の末尾のほうにある \floatplacement{table}{htp}\floatplacement{table}{H} と変えることで、表は書いたとおりの箇所に配置されるようになり、コラム内でも問題なく利用できます。

図のほうはもともと \floatplacement{figure}{H} と定義しており、この問題はデフォルトの設定から変えなければ問題ありません。

コラム内の脚注テキスト
foo.tex:647: LaTeX Error: Counter too large.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.647 ...otetext[28]{\url{https://reviewml.org/}}

このエラーは Re:VIEW のデフォルト構成では通常見ることはありませんが、以下のような状況において発生します。

  • techbooster のテンプレートのように、コラムに tcolorbox 環境を使っている

  • かつ、コラムブロックの中で脚注を使っている

  • かつ、コラムのブロックの「中」に //footnote も含んでいる

Re:VIEW 3 からはコラムや図・キャプションなどに入っている脚注をできるだけ正しく出力できるようにしています(古い Re:VIEW バージョンでは、脚注を入れたつもりでも TeX の処理の都合で出力に含まれないというケースがよくありました)。

ただ、コラムに tcolorbox 環境を使っている場合は、//footnote がコラムブロックの「中」にあるか「外」にあるかで挙動がまったく変わってしまいます。

対策を先に言うと、コラムの脚注の //footnote は、==[/column] のようなそのコラムの終了見出しの「後ろ」に置くべきです。

本文@<fn>{foo}

//footnote[foo][本文の脚注内容]

==[column] コラム
ほげほげ@<fn>{bar}

//footnote[bar][コラムの脚注内容] ←×

==[/column]

//footnote[bar][コラムの脚注内容] ←○

技術的な説明は以下のとおりです。

  • 通常の脚注は @<fn>//footnote の情報をもとに \footnote{脚注内容} というマクロにして @<fn> の箇所に置きます。

  • これに対し、コラムなどの「処理的に厄介」な脚注は、@<fn>\footnotemark//footnote\footnotetext[脚注番号]{脚注内容} というマクロにします。

  • 標準の framed 環境であれば \footnotetext は環境の中にあろうが外にあろうが問題ありません。普通に本文から継続した番号で、アラビア数字でカウントされます(上記の例では foo は注1、bar は注2)。

  • これに対し、tcolorbox 環境では、\footnotetext は環境の内外で挙動が違います。環境の外にある場合(上記の例では○)は、本文から継続した番号で、アラビア数字でカウントされます(上記の例では foo は注1、bar は注2)。しかし、環境の中にある場合(上記の例では×)は、本文から継続した番号ではあるのですが、何も設定しない限り a, b, cとしてカウントされます。コラム単位でカウントがリセットされるなら(EPUB とは違う結果になるにせよ)まだましなのですが、悪いことに脚注の番号は本文から継続しているので、上記の例で言えば foo は注1、bar は注bになります。また、脚注は紙面下部ではなく、コラムの囲みの末尾に入ります。

  • aから始まる番号表現ではz(27)までしか利用できないので、脚注番号の値が28以上になった状態でコラム内に \footnotetext があると「Counter too large.」というエラーが起きます。

  • review#1379

数式の記述ミス

//texequation@<m> の数式命令や、//embed@<embed> のような生データ命令は、Re:VIEW の文法チェックの範囲外なので、誤った記述は TeX のコンパイルエラーや異常な結果に直結します。

数式でありがちなのは、{} の指定漏れや過多で囲みの数が合わないことによるエラーです。

閉じ側が多い(または開き側が少ない)とき(\frac{1}{2}} として } が1つ多い)はまだわかりやすいのですが、

./math.tex:5: Extra }, or forgotten $.
l.5 \frac{1}{2}}

開き側が多いとき({\frac{1}{2} として { が1つ多い)は、後続行になって初めてエラーになるため、わかりにくくなります。

./math.tex:6: You can't use `\eqno' in math mode.
\endmathdisplay@a ...\df@tag \@empty \else \veqno 
                                                  \alt@tag \df@tag \fi \ifx ...
l.6 \end{equation}

逆に、閉じ側が少ないとき({\frac{1}{2 として末尾の } が不足)は、ヒントっぽいものはあるものの、エラー行は全然違うところになります。

./__REVIEW_BOOK__.tex:119: File ended while scanning use of \frac .
<inserted text> 
                \par 
l.119 \reviewchapterfiles

数式や embed によるエラーは多岐にわたり、また Re:VIEW の範疇を超えるので、TeX Wiki のエラーメッセージについての説明などを参照してください。

マクロの不具合

sty フォルダのクラスファイルやスタイルファイルに定義されたマクロに問題があるケースも、もちろんあります。Re:VIEW に添付されているものは、既知の問題で新しいバージョンでは修正済みかもしれません。

また、サードパーティから配布されるような Re:VIEW の古いバージョンに基づくクラス・スタイルファイルを使っている場合、Re:VIEW 側の変換するマクロ名や記述などの変更で互換性がなくなっている可能性もあります。

Illegal parameter number in definition of...Missing control sequence inserted.Undefined control sequence.Illegal unit of measure (pt inserted). Missing number, treated as zero. などのエラーが出たときにはそのような可能性があります。

Re:VIEW の新しいリリースバージョンで、サードパーティのクラス・スタイルファイルを使っていないのにこのようなエラーに遭遇したときには、Re:VIEW のクラス・スタイルファイルの不具合と思われますので、GitHub issues または Twitter @kmuto までご報告ください。

文字が落ちる

エラーは出ないものの、PDF を作ってみると特定の文字が消失している、という現象があるかもしれません。文字が消えた箇所については、debug: true の状態で一度実行して一時作業フォルダを吐き出しておき、その中で dvipdfmx __REVIEW_BOOK__.dvi を実行してみると、「Tried to set a nonexistent character in a virtual font」というメッセージが出ているでしょう。

デフォルトで使用している upLaTeX は Unicode 範囲の文字を扱えるようになっていますが、Unicode のすべての文字を受け入れて出力できるというわけではありません。

どのような文字を出そうとしているかによって、\CID でフォント内のキャラクタ ID から呼び出す、専用のマクロを使う、画像化して @<icon> などで入れる、など対応はさまざまです。

最近流行りの絵文字も文字欠落の代表的な例です。Re:VIEW での絵文字の利用方法については、Re:VIEW + upLaTeX で絵文字を使うを参照してください。

2019/8/24 by @kmuto

Re:VIEW + upLaTeX で絵文字を使う

Re:VIEW + upLaTeX の環境で絵文字を使うための手順を紹介します。


Unicode に絵文字が取り込まれたことで、ネット文化では🍣だの🤔だのやりたい放題の感がありますが、Re:VIEW + upLaTeX でそのままこれを利用しようとすると「PDF から全部消えてる…😱」という厳しい結果が待っています。

@zr-tex8r さん作の BXcolormoji というパッケージを使うと、画像化された絵文字を埋め込むことができます。

BXcoloremoji のインストール

BXcoloremoji/Release から、最新版の zip または tar.gz ファイルをダウンロードし、README.md のインストール手順に従ってインストールします。

Linux/macOS の場合、ごく単純には ~/texmf/tex/latex のフォルダを作り、ここにアーカイブファイルを展開しておけばよいでしょう。

BXcoloremoji パッケージの利用宣言

インストールした BXcoloremoji を利用するため、プロジェクトの sty/review-custom.sty にパッケージの利用宣言を追加します。

\usepackage{bxcoloremoji}

いくつかのオプションを付けることも可能ですが(ドキュメントを参照)、通常はこれだけで十分です。

絵文字を使うための設定

re ファイルに適当に絵文字を入れるだけでは BXcoloremoji のマクロの対象になりません。tex ファイル化する際の最終結果を書き換えるか、あるいは絵文字用の Re:VIEW のインライン命令を追加するかのどちらかが必要です。ここでは絵文字を使うということを強く意識するために後者のインライン命令を追加する方法をとることにします。プロジェクトに置く review-ext.rb は以下のとおりです。

module ReVIEW
  module BuilderOverride
    Compiler.definline :emoji

    def inline_emoji(s)
      s
    end
  end

  class Builder
    prepend BuilderOverride
  end

  module LATEXBuilderOverride
    def inline_emoji(s)
      "\\coloremoji{#{s}}"
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

@<emoji>{絵文字} というインライン命令を追加しました。ほかのビルダではそのまま絵文字を通すようにし、LaTeX ビルダでは BXcoloremoji で提供される \coloremoji マクロに絵文字を渡します。

  • EPUB の場合、PC やタブレットであれば問題ありませんが、Kindle 端末のような専用デバイスでは絵文字はまともに表示されない可能性が高いことに注意してください(結局 BXcoloremoji がやっているような画像化の措置が必要かもしれません)。

  • InDesign の場合、絵文字の利用はまだリスクが高いです。絵文字などをそのまま利用できる OpenType-SVG をサポートする InDesign や Illustrator はある程度新しいバージョンに限られるので、商業出版刊行しようという原稿の場合は、利用する前に本当に使ってよいか制作関係者に確認すべきです。

  • 絵文字を指定する際に、直接その文字を @<emoji> 命令内に書き込むのではなく、\coloremojiucs マクロを使って符号値列や短縮名で指定する、という方法もあります(ほかのビルダ向けにはなんとかして元の絵文字を構築する必要がありますが)。

絵文字を埋め込んだ例を以下に示します。

_images/emoji.png絵文字の利用例

絵文字の使いすぎには注意しましょう 😱😱😱

2020/7/24 by @kmuto

参考文献にthebibliography環境を利用する

Re:VIEW の //bibpaper 命令を LaTeX の thebibliography 環境に対応付ける例を示します。


Re:VIEW の参考文献に使う //bibpaper および @<bib> 命令は、各ビルダで共通化するためにかなり簡素なものとなっています。LaTeX では参考文献に thebibliography 環境を使うのが一般的なので、これに適合するように変更してみましょう。

原稿の例

参考文献の bib.re ファイルは以下のように書くことにします。

= 参考文献

//embed[latex]{
\begin{thebibliography}{99}
//}

//bibpaper[RvIn][Re:VIEW+InDesign制作技法]{
武藤健志(著)、@<b>{『Re:VIEW+InDesign制作技法』}(達人出版会)、2016年
//}

//bibpaper[Cloud_19][Cloud Native DevOps with Kubernetes 2019]{
John Arundel, Justin Domingus, @<i>{Cloud Native DevOps with Kubernetes}, O'Reilly Media, Inc., 2019

邦訳は須田一輝(監訳)、渡邉了介(訳)、『Kubernetes で実践するクラウドネイティブ DevOps』(オライリー・ジャパン)、2020年
//}

//embed[latex]{
\end{thebibliography}
//}

参考文献の thebibliography 環境の開始・終了を //embed 命令を使って記述しています。//bibpaper 命令の記法はデフォルトの Re:VIEW の書き方とは少し変えており、1つめの引数が ID、2つめの引数はメモ(何を書いても無視される)。{//} の中に段落形式で書誌情報を記載します。

\begin{thebibliography}{99}{99} は、別に99個の何かというわけではなく、参考文献の箇条書き表記をするときに「99」というリテラルな文字の幅をラベル幅に転用するというだけです。参考文献の数が1桁なら {9} としてもよいでしょう。

著者名・書籍名・出版社・刊行年月日 などや ISBN や URL を表記するかどうか、およびその順番などは、書き手なり刊行する出版社なりでハウスルールが異なりますので、ルールに従って揃えておきましょう。

参照する re ファイルのほうは、普通に以下のようになります。//bibpaper で指定した ID を @<bib> 命令に入れるだけです。

= 本文

@<bib>{RvIn}と@<bib>{Cloud_19}を参照。

review-ext.rb の変更

//bibpaper 命令の記法を変えているので、それに応じて Re:VIEW の挙動を review-ext.rb で変更します。

module ReVIEW
  module LATEXBuilderOverride
    def bibpaper(lines, id, caption)
      puts %Q(\\bibitem{bib:#{id}} #{split_paragraph(lines).join("\n\n")})
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

参考文献を Re:VIEW の LaTeX ビルダで扱う際にbib: + ID としている以外はとりたてて注目するところはありません。LaTeX の bibitem マクロにその ID および段落内容を入れているだけです。

review-custom.sty の変更

現状では、「参考文献見出しが多重に登場してしまう」「本文の引用側が \cite 命令ではなくリテラルな番号に展開されている」という2つの問題があります。

sty/review-custom.sty ファイルで挙動を変更しましょう。review-jsbook.cls を使っている前提での記述例を示します。

% for user-defined macro
\renewenvironment{thebibliography}[1]{%
  %\global\let\presectionname\relax
  %\global\let\postsectionname\relax
  %\chapter*{\bibname}\@mkboth{\bibname}{}%
  %\addcontentsline{toc}{chapter}{\bibname}%
   \list{\@biblabel{\@arabic\c@enumiv}}%
        {\settowidth\labelwidth{\@biblabel{#1}}%
         \leftmargin\labelwidth
         \advance\leftmargin\labelsep
         \@openbib@code
         \usecounter{enumiv}%
         \let\p@enumiv\@empty
         \renewcommand\theenumiv{\@arabic\c@enumiv}}%
   \sloppy
   \clubpenalty4000
   \@clubpenalty\clubpenalty
   \widowpenalty4000%
   \sfcode`\.\@m}
  {\def\@noitemerr
    {\@latex@warning{Empty `thebibliography' environment}}%
   \endlist}

\renewcommand{\reviewbibref}[2]{\cite{#2}}

jsbook.cls の thebilbiography 環境の定義をコピーして \renewenvironment で再定義することにし、定義の最初の4行にある見出し設置部分をコメントアウトしています。

\reviewbibref は2つの引数をとるマクロで、#1 にはリテラルな番号、#2 には(bib:付きの) ID が入っています。デフォルトは #1 を利用しているのですが、ここでは \cite マクロで #2 のほうを取るように変更しました。

変更結果

これで設定は終わりです。rake pdf の結果を見てみましょう。

_images/bib1.pngthebibliography環境を使った参考文献

うまくいっているようです。参照側は以下のようになっています。

_images/cite1.png参考文献の引用

texdocumentclass パラメータで media=ebook を有効にしておくと、参照側からクリックしてハイパーリンクも飛ぶようになっているはずです。

番号でなくラベルを表記する

上記の例では頭から順に番号を振りましたが、[RvIn] のようにラベル文字列を使った表記方法も書籍や論文においてはよく見かけます。//bibpaper の ID をそのまま利用する形で実装してみましょう。このときの review-ext.rb は次のとおりです。

module ReVIEW
  module LATEXBuilderOverride
    def bibpaper(lines, id, caption)
      puts %Q(\\bibitem[#{escape(id)}]{bib:#{id}} #{split_paragraph(lines).join("\n\n")})
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

\bibitem マクロの頭にエスケープした ID 文字列を入れています。

番号でなく文字列のラベルの場合は幅が大きくとるので、bib.re での thebibliography 環境のラベル幅を広げておきましょう。aaaaaaaaa の数は実際のラベルに応じて増減させてください。

= 参考文献

//embed[latex]{
\begin{thebibliography}{aaaaaaaaa}
//}

…(略)…
//}

結果は以下のとおりです。

_images/bib2.pngthebibliography環境を使った参考文献(ラベル)

_images/cite2.png参考文献の引用(ラベル)

2020/8/16 by @kmuto

コードブロックに長体(横方向の縮小変形)をかける

//emlist などのコードブロックに縮小変形をかけて1行に収める方法を紹介します。


コードブロック内で自動改行するで少しだけ触れたのですが、LaTeX の \scalebox マクロを使うとコードブロックに長体、つまり横方向の縮小変形をかけて行あたりの文字数を増やすことができます。

ハイライトが有効になっている場合は listings マクロに関わらないといけないのでここでは説明を省略し、ハイライトは使わない前提で話を進めます。

原稿の例

//emlist{
1234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890
//}

これをビルドすると、次のように少しあふれています。そしてこれは1行であることに意味があり、自動改行はしたくないとしましょう。

_images/listscale-over.png行がアミからあふれている

//listscale 命令の導入

そこで、コードブロックの長体率を指定するために、新たに //listscale 命令を追加することにします。review-ext.rb は次のとおりです。

module ReVIEW
  module BuilderOverride
    Compiler.defsingle :listscale, 1
    def listscale(scale) # 何もしない
    end
  end

  class Builder
    prepend BuilderOverride
  end

  module LATEXBuilderOverride
    def listscale(scale)
      # 長体率を指定
      @list_scale = scale
    end

    def common_code_block(id, lines, command, caption, _lang)
      @doc_status[:caption] = true
      captionstr = nil
      unless @book.config.check_version('2', exception: false)
        puts '\\begin{reviewlistblock}'
      end
      if caption.present?
        if command =~ /emlist/ || command =~ /cmd/ || command =~ /source/
          captionstr = macro(command + 'caption', compile_inline(caption))
        else
          begin
            if get_chap.nil?
              captionstr = macro('reviewlistcaption', "#{I18n.t('list')}#{I18n.t('format_number_header_without_chapter', [@chapter.list(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
            else
              captionstr = macro('reviewlistcaption', "#{I18n.t('list')}#{I18n.t('format_number_header', [get_chap, @chapter.list(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
            end
          rescue KeyError
            error "no such list: #{id}"
          end
        end
      end
      @doc_status[:caption] = nil

      if caption_top?('list') && captionstr
        puts captionstr
      end

      body = ''
      lines.each_with_index do |line, idx|
        if @list_scale # ここで//listscaleの値を利用して長体化
          body.concat(yield("\\scalebox{#{@list_scale}}[1]{#{line}}", idx))
        else
          body.concat(yield(line, idx))
        end
      end
      @list_scale = nil
      puts macro('begin', command)
      print body
      puts macro('end', command)

      if !caption_top?('list') && captionstr
        puts captionstr
      end

      unless @book.config.check_version('2', exception: false)
        puts '\\end{reviewlistblock}'
      end
      blank
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

だいぶ長いですが、ポイントは以下のとおりです。

  • BuilderOverride モジュールで single 命令の //listscale を定義し、基底ビルダ では何もしない(LATEXBuilder 以外のビルダ、つまり HTMLBuilder などのほかのビルダで単に無視するようにする)。

  • LATEXBuilder 用の LATEXBuilderOverride モジュールで、//listscale の効果の実体を定義する。といっても、@list_scale に指定の縮小率を入れるだけ。

  • コードブロックの共通メソッドである common_code_block をコピーし、書き換える。提示のものは Re:VIEW 4.2 時点のもので、ちょっと大きめになっている。具体的に書き換えるのは lines.each_with_index の中で、@list_scale が定義されていれば \scalebox{縮小率}[1]{行の内容} と書き出すようにする。[1] は縦方向の縮小率で、1はつまり縮小をかけないということ。なお、//listscale の値もそうだが、1より大きいものを入れれば縮小ではなく「拡大となる。

  • lines.each_with_index のブロックが終わったら @list_scale を nil にして、次のコードブロックに影響が及ばないようにする。

変更結果

これで、//listscale[縮小率] という命令が誕生しました。普通の emlist、長体 95%(0.95)にした同じ emlist、普通の emlistnum (行番号付き)、長体 90%(0.9)にした同じ emlistnum でどうなるか見てみましょう。

//emlist{
1234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890
//}

//listscale[0.95]
//emlist{
1234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890
//}

//emlistnum{
1234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890
//}

//listscale[0.9]
//emlistnum{
1234567890123456789012345678901234567890123456789012345678901234567890
1234567890123456789012345678901234567890123456789012345678901234567890
//}

_images/listscale.png長体でうまく収まっている

うまくいきました!

2020/12/20 by @kmuto

表の自由度をHTMLを使って掴み取る

Re:VIEW および LaTeX の記述方法では難しい表を、HTML 化して Web ブラウザから画像化することで対処します。


以前から述べている「日本人の表好きすぎる問題」はいまだとどまるところを知りませんが、かといって Re:VIEW の記法上の理由と、LaTeX の表表現の根幹思想による制約という2つの問題があり、なかなか完璧な解決方法というものは思い付きません。

LaTeX ではどうにも解決の糸口が見えないので、もう少し表については柔軟な HTML を使うことを考えました。re ファイル内の表にいろいろと擬似タグによる指示を入れておいたものを HTML 化して、Web ブラウザによるレンダリングを画像化して受け取り、表の代わりに貼り付けておこうというアイデアです。

使いすぎは健康を損ねるので、説明はざっくりにしておきます。

まずは実行例

ひとまず完成した review-ext.rb を挙げておきます。

# -*- coding: utf-8 -*-
# ブラウザで動的にTeX用表画像を作成するための //htmltable, //rawhtmltable
# Copyright 2020 Kenshi Muto
module ReVIEW
  require 'review/htmlbuilder'

  module BuilderOverride
    Compiler.defblock :htmltable, 0..3
    Compiler.defblock :rawhtmltable, 0..3

    def htmltable(lines, id = nil, caption = nil, metrics = nil)
      table(lines, id = nil, caption = nil)
    end

    def rawhtmltable(lines, id = nil, caption = nil, metrics = nil)
      table(lines, id = nil, caption = nil)
    end
  end

  class Builder
    prepend BuilderOverride
  end

  module IndexBuilderOverride
    def htmltable(lines, id = nil, caption = nil, metrics = nil)
      check_id(id)
      if id
        item = ReVIEW::Book::Index::Item.new(id, @table_index.size + 1, caption)
        @table_index.add_item(item)
      end
    end

    def rawhtmltable(lines, id = nil, caption = nil, metrics = nil)
      check_id(id)
      if id
        item = ReVIEW::Book::Index::Item.new(id, @table_index.size + 1, caption)
        @table_index.add_item(item)
      end
    end
  end

  class IndexBuilder
    prepend IndexBuilderOverride
  end

  module CompilerOverride
    def initialize(builder)
      super(builder)
      @non_parsed_commands += %i[rawhtmltable]
    end
  end

  class Compiler
    prepend CompilerOverride
  end

  module HTMLBuilderOverride
    def htmltable(lines, id = nil, caption = nil, metrics = nil)
      if id
        puts %Q(<div id="#{normalize_id(id)}" class="table htmltable">)
      else
        puts %Q(<div class="table htmltable">)
      end
      super(lines, id, caption)
      puts '</div>'
    end

    def rawhtmltable(lines, id = nil, caption = nil, metrics = nil)
      if id
        puts %Q(<div id="#{normalize_id(id)}" class="table rawhtmltable">)
      else
        puts %Q(<div class="table rawhtmltable">)
      end
      puts lines.join("\n")
      puts '</div>'
    end

    def cellattr(str)
      return [str, ''] if str !~ /\A<\?dtp table/
      attr = []
      str.match(/<\?dtp table (.+) \?>/) do |m|
        str = $'
        m[1].split(',').each do |kv|
          k, v = kv.split('=', 2)
          k = 'class' if k == 'cellstyle'
          attr.push(%Q(#{k}="#{v}"))
        end
      end
      return [str, ' ' + attr.join(' ')]
    end

    def th(str)
      return '' unless str.present?

      str, attr = cellattr(str)
      "<th#{attr}>#{str}</th>"
    end

    def td(str)
      return '' unless str.present?

      str, attr = cellattr(str)
      "<td#{attr}>#{str}</td>"
    end
  end

  class HTMLBuilder
    prepend HTMLBuilderOverride
  end

  module LATEXBuilderOverride
    def make_htmlimgtable(type, id)
      @book.config['builder'] = 'html'
      chapterlink = @book.config['chapterlink']
      @book.config['chapterlink'] = nil
      compiler = Compiler.new(HTMLBuilder.new)
      File.write('__REVIEW_HTMLTABLE__.html', compiler.compile(@book.chapter(@chapter.name)))
      @book.config['chapterlink'] = chapterlink
      @book.config['builder'] = 'latex'

      require 'puppeteer'

      unless Dir.exist?(File.join('images', '__htmltable__'))
        Dir.mkdir(File.join('images', '__htmltable__'))
      end

      Puppeteer.launch(headless: true) do |browser|
        page = browser.pages.first || browser.new_page
        page.viewport = Puppeteer::Viewport.new(width: 1400, height: 1200, device_scale_factor: 2)
        page.goto("file://#{Dir.pwd}/__REVIEW_HTMLTABLE__.html##{id}")
        page.focus("div.#{type}##{id} table")
        overlay = page.S("div.#{type}##{id} table")
        overlay.screenshot(path: File.join('images', '__htmltable__', "#{@chapter.name}-#{id}.png"))
      end
    end

    def common_htmltable(type, lines, id, caption, metrics)
      blank
      if caption.present?
        puts "\\begin{table}%%#{id}"
      end

      error "#{type} needs id." unless id

      make_htmlimgtable(type, id)

      begin
        if caption_top?('table') && caption.present?
          table_header(id, caption)
        end
      rescue KeyError
        error "no such table: #{id}"
      end

      puts '\begin{reviewtable}{c}'
      command = 'reviewincludegraphics'

      if metrics.present?
        puts "\\#{command}[#{metrics}]{images/__htmltable__/#{@chapter.name}-#{id}.png}"
      else
        puts "\\#{command}[scale=0.4]{images/__htmltable__/#{@chapter.name}-#{id}.png}"
      end
      puts '\end{reviewtable}'

      if caption.present?
        unless caption_top?('table')
          table_header(id, caption)
        end
        puts '\end{table}'
      end
      blank
    end

    def htmltable(lines, id = nil, caption = nil, metrics = nil)
      common_htmltable('htmltable', lines, id, caption, metrics)
    end

    def rawhtmltable(lines, id = nil, caption = nil, metrics = nil)
      common_htmltable('rawhtmltable', lines, id, caption, metrics)
    end

    def result
      File.unlink('__REVIEW_HTMLTABLE__.html') if File.exist?('__REVIEW_HTMLTABLE__.html')
      super
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

かなり大きい時点で、不吉な臭いがしますね。Re:VIEW 5.0 向けですが、以降のバージョンで使えなくなる可能性もあります。

解説は後にするとして、次のようなreファイルを用意しました。

= htmltableのテスト

//htmltable[kakuteiA][確定申告書A]{
-----------------
@<dtp>{table rowspan=5,cellstyle=earning}所得金額	給与	区分	@<dtp>{table cellstyle=input}□□□	①	@<dtp>{table cellstyle=input}□□□□□□□□□
.	@<dtp>{table colspan=3}雑	.	.	②	@<dtp>{table cellstyle=input}□□□□□□□□□
.	@<dtp>{table colspan=3}配当	.	.	③	@<dtp>{table cellstyle=input}□□□□□□□□□
.	@<dtp>{table colspan=3}一時	.	.	④	@<dtp>{table cellstyle=input}□□□□□□□□□
.	@<dtp>{table colspan=3}合計@<br>{}(①+②+③+④)	.	.	⑤	@<dtp>{table cellstyle=input}□□□□□□□□□
//}

style.css は次のようにしています。

div.htmltable table, div.rawhtmltable table {
  padding-right: 0.25em;
  padding-bottom: 0.25em;
  margin-right: 0.5em;
  margin-bottom: 0.5em;
}

td.input {
  font-size: 1.2em;
  color: #efd4af;
}

td.earning {
  background-color: #02b4f2;
  color: white;
}

Ta-da! 結果は次のとおりです。

_images/htmltable1.png確定申告書A

reファイル側を先に解説しておくと、

  • 表セルの先頭で @<dtp> 命令を使い、table でその表セルについての指示を入れておく。複数の指示があるときには , で区切る。

  • colspan=数字 で右方向のセル結合、rowspan=数字 で下方向のセル結合を行う。結合「される」側のセルは、「.」を入れておく (空扱いになる)。なお、結合ではなく本当に「空欄」のセルを用意したいときには全角スペース( )を入れておくとよい。

  • cellstyle=スタイル名 でセルのスタイル名を入れる。実際にはここでは HTML の class 属性の値にそのまま置き換えている。

cellstyle で class に置換されるので、実のところ CSS 側で何でもやりたい放題ですね。

review-ext.rb の説明

実行の流れとしては、以下のとおりです。

  1. //htmltable が登場したら、その章を HTML ビルダによって __REVIEW_HTMLTABLE__.html として書き出す。

  2. Web ブラウザを操作する Puppeteer を実行する。Ruby で閉じたかったので、ここでは google-chrome-stable または chromium を操作できる puppeteer-ruby gem パッケージを採用した。

  3. puppeteer-ruby で 1. の HTML ファイルをブラウザに開き、htmltable の表要素を ID に基づいて探す。

    1. で見つかった要素範囲を画像キャプチャし、images/__htmltable__章-ID.png に保存する。

  4. TeX ファイル側には 4. の画像ファイルを指定した \reviewincludegraphics を書き込む。

    1. に戻り、//htmltable が終わるまで繰り返す。全部終わったら __REVIEW_HTMLTABLE__.html を削除する。

手順2.にあるとおり、お手元での実行には puppeteer-ruby gem パッケージ、およびブラウザ環境が必要です (Debian GNU/Linux 以外での実行は不明です)。

gem install puppeteer-ruby
  • page.viewport で解像度・および画質を設定しています。うまく収まらない場合にはこのあたりを調整してみるとよいでしょう。

  • //htmltable はキャプションは省略できますが、ID は必須です (これに基づいて探すので)。

  • 今は PNG にしていますが、スクリーンショットではなく、PDF を「印刷」するように変えれば検索可能なものにはなりそうです。ただ Chrome/Chromium で OTF 混じりのものを PDF 化すると Type3 になって印刷所に送れないものになるので気乗りしないのと、要素だけを印刷する方法がすぐにはわからなかったので手を付けませんでした。

  • //htmltable でメトリックを指定しなかったときには scale=0.4 を指定しています。本文および page.viewport で指定したスケールの兼ね合いではこのくらいがおおむね合っているのではないかと思います。

  • セル内は普通の re ファイルなので、@<b>@<chap> など任意のインライン命令を記述できます。

  • @<dtp>{table 〜} の指定では、cellstyle を除いて「キー=値」をそのまま HTML の th, td 要素に渡しているだけなので「@<dtp>{table align=right}」なども可能です。valign は CSS でないとできないですし、結局 CSS でやったほうが自然ですが。

  • で、実は EPUB のほうもこれで普通にセル結合やセルスタイル設定できるようになりますね。

  • CSS の div.htmltable の妙なマージン、パディングですが、これを入れないと要素を切り出しキャプチャしたときに切れてしまうことがあります。入れてもダメなときもあり、謎ですね……。

  • //htmltable が呼ばれるたびに毎回 HTML を作り直して Puppeteer を呼び出すのは明らかにパフォーマンスが悪いです。よりまじめに作るなら、IndexBuilder//htmltable があるというフラグを立てたら、builder_init_file で HTML および Puppeteer インスタンスを作成する、という具合でしょうか。

  • なお、執筆時点ではまだリリース前で今のGitHub master にある Re:VIEW 5.1(?) を使うと、config.yml に math_format: mathjax とするだけで表中の @<m>//texequation の TeX 数式も綺麗に入れられます。

CSS スタイルの div.htmltable のフォントを TeX 側で使っているフォントに合わせれば、より近い見た目になるでしょう (文字組の手法が異なるので完全に一致することはありませんが)。たとえば筆者の環境では TeX 組版のデフォルトを「Latin Modern + モリサワリュウミン」としているので、CSS を以下のようにします。

div.htmltable {
  font-family: "Latin Modern Roman", "A-OTF Ryumin Pr6N";
  …
}

_images/htmltable2.pngフォント変更

TeX で作られたキャプション部分と表の書体で違和感がなくなりました。

もっと自由を!?

もっと自由に書きたいというときのために、//rawhtmltable 命令も使えます。

//rawhtmltable[freedom][自由すぎる表]{
<table>
<tr><th rowspan="2"></th><th colspan="2">データMAX 5G with Dazon</th></tr>
<tr><th>通常</th><th>2GB以下の場合</th></tr>
<tr><th>2年契約 適用時 <b>[1]</b></th><td>9,180円</td><td>7,700円</td></tr>
<tr><th>家族割プラス</th><td colspan="2"><table>
  <tr><th>2人</th><td>-500円</td></tr>
  <tr><th>3人</th><td>-1,000円</td></tr>
  <tr><th>4人 <b>[2]</b></th><td>-2,020円</td></tr>
  </table></td></tr>
<tr><th>スマートバリュー <b>[3]</b></th><td colspan="2">-1,000円</td></tr>
<tr><th>スマホ応援割 <b>[4]</b><span class="note">※翌月から6カ月間</span></th><td colspan="2">-1,400円</td></tr>
<tr><th>5Gスタート割 <b>[5]</b><span class="note">※翌月から12カ月間</span></th><td colspan="2">-1,000円</td></tr>
</table>

_images/htmltable3.png自由すぎる表

re 形式からは離れるので、Re:VIEW のインライン命令・ブロック命令は使えません。

LaTeX 上では table 環境で囲んではいるものの、実はHTML のほうでは <table> を使う必要すらなく、本当に任意です。使いすぎにはご注意ください。

2020/12/23 by @kmuto

mintedを使ったコードハイライト

minted パッケージを利用して LaTeX 上でも精緻なコードハイライトを施します。


コードハイライト

今やプログラミングにおいて、メソッド名や変数、キーワードといった種類に応じてコードに色付け・書体変更などを行う「コードハイライト」は、エディタやビューアに当たり前の機能となっています。

Re:VIEW でのコードハイライトは、highlight パラメータを有効にし、HTML/EPUB の場合は html: "rouge" または html: "pygments" を使えば Rouge gem または pygments.rb gem パッケージのおかげでかなり良い感じのコードハイライトになります。

_images/minted-html.pngRouge による HTML でのコードハイライト

これに対し、PDFMaker (LaTeX) のほうは latex: "listings" をすれば一応 plistings および listings パッケージの働きによってハイライトはされますが、HTML のほうに比べると物足りない感じがあります。

_images/minted-2-listings.pnglistings による LaTeX でのコードハイライト

これがすべて TeX のマクロで、文字列を解析してハイライトを実現しているというのは賞賛に値するのですが、カスタマイズを挟み込むのは至難です。

LaTeX でコードハイライトを行う別の方法として、「minted」というパッケージがあります。このパッケージは、Python プログラムのコードハイライタ Pygments を内部で呼び出します。HTML で利用していた pygments.rb も内部で Pygments を呼び出しているので、合わせておけば同じ結果を得られることになります。

準備

minted パッケージは TeXLive に標準でインストールされているので、追加インストールは不要です。

Pygments は、Python 環境をセットアップ済みであれば、pip install pygments でインストールできます (Debian GNU/Linux などでは apt-get install python3-pygments でもインストールできますが、だいぶ古いものが入ってしまいます)。

また、この記事では GitHub と同じコードハイライトスタイルを使いたいので、pygments-style-extras Python パッケージも pip コマンドでインストールします。が、手元ではこのパッケージについて pip コマンドでうまくインストールできなかったので、開発リポジトリ から styles/github.py を取得して直接 Pygments ライブラリのフォルダにコピーしてしまいました。

Pygments がインストールできたかは、次のように確認できます。

$ pygmentize -V
Pygments version 2.4.2, (c) 2006-2019 by Georg Brandl.

次に、プロジェクトの config.yml の変更です。

minted は TeX コンパイル中に内部で外部コマンドを呼び出します。TeX では信頼できない外部コマンド呼び出しを推奨しておらず、そのままではエラーになってしまうので、コンパイラにこの制約を緩めてもらいます (セキュリティ的にはよくないのでしょうが、Re:VIEW のビルドができる時点ですでにやりたい放題の環境ですよね)。texoptions パラメータにコンパイラからの任意の外部コマンド呼び出しを許可する設定 -shell-escape を追加します。

texoptions: "-interaction=nonstopmode -file-line-error -halt-on-error -shell-escape"

コードハイライトも有効にしておきます。highlight/latex に何かが入っていればよいので、listings のままで構いません。

highlight:
  html: "rouge"
  latex: "listings"

スタイルの設定

コードハイライトスタイルにはいろいろな流派があります。GitHub スタイルもそうですし、Visual Studio Code、XCode、Emacs、Vim などのエディタのハイライトもそれぞれ違っています。Pygments は各種のハイライトスタイルに対応しており、次のコマンドで調べられます。

$ pygmentize -L styles

なお、先に GitHub スタイルを追加したと述べましたが、この一覧には出てこないようでした。スタイル名は「github」です。ちなみに、Jupyter Notebookには「manni」が近い気がしています。

minted パッケージの読み込みと、スタイルの設定を プロジェクトの sty/review-custom.sty に定義します。

% for user-defined macro
\usepackage{minted}
\usemintedstyle{github}

minted のデフォルトのルールに従ってコードは適当に整形されますが、サンプルとして Ruby、Python、Emacs Lisp のコードハイライトについて明示的に sty/review-custom.sty に定義しておくことにします。minted には多数のオプション指定があるので、詳細については texdoc minted を参照してください。最初の色設定 (\definecolor) は minted 固有ではなく、背景色に使いたい明るい灰色を定義しています。

 …

\definecolor{lightshadecolor}{gray}{0.95}

% Rubyリスト環境の事前定義
\setminted[ruby]{fontsize={\fontsize{8pt}{12pt}},breaklines=true,breakanywhere=true,frame=single}
% Pythonリスト環境の事前定義
\setminted[python]{fontsize={\fontsize{9pt}{14pt}},showspaces=true,breaklines=true,breakanywhere=true,bgcolor=lightshadecolor}
% Emacs Lispリスト環境の事前定義
\setminted[elisp]{breaklines=true,breakanywhere=true,frame=lines}

review-ext.rb の配備

では、毎度おなじみ、プロジェクトフォルダに置く review-ext.rb です。

# -*- coding: utf-8 -*-
# リストをpygments + mintedでハイライトする
# Copyright 2020 Kenshi Muto
module ReVIEW
  module CompilerOverride
    def non_escaped_commands
      if @builder.highlight?
        # デフォルトは %i[list emlist listnum emlistnum cmd]
        # cmdをハイライトから除外してみる
        %i[list emlist listnum emlistnum]
      else
        []
      end
    end
  end

  class Compiler
    prepend CompilerOverride
  end

  module LATEXBuilderOverride
    def builder_init_file
      super
      @predefined_mint_style = %w[python ruby]
    end

    def cmd(lines, caption = nil, lang = nil)
      # cmdについてはハイライトなし版のみを使う
      blank
      common_code_block(nil, lines, 'reviewcmd', caption, lang) { |line, idx| code_line('cmd', line, idx, nil, caption, lang) }
    end

    # リスト環境をcommon_minted_codeに任せる。言語のデフォルトにshを設定しておく
    def emlist(lines, caption = nil, lang = 'sh')
      common_minted_code(nil, 'emlist', nil, lines, caption, lang)
    end

    def emlistnum(lines, caption = nil, lang = 'sh')
      common_minted_code(nil, 'emlist', line_num, lines, caption, lang)
    end

    def list(lines, id, caption, lang = 'sh')
      common_minted_code(id, 'list', nil, lines, caption, lang)
    end

    def listnum(lines, id, caption, lang = 'sh')
      common_minted_code(id, 'list', line_num, lines, caption, lang)
    end

    def common_minted_code(id, command, lineno, lines, caption, lang)
      blank
      puts '\\begin{reviewlistblock}'
      if caption.present?
        if command =~ /emlist/ || command =~ /cmd/ || command =~ /source/
          captionstr = macro('review' + command + 'caption', compile_inline(caption))
        else
          begin
            if get_chap.nil?
              captionstr = macro('reviewlistcaption', "#{I18n.t('list')}#{I18n.t('format_number_header_without_chapter', [@chapter.list(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
            else
              captionstr = macro('reviewlistcaption', "#{I18n.t('list')}#{I18n.t('format_number_header', [get_chap, @chapter.list(id).number])}#{I18n.t('caption_prefix')}#{compile_inline(caption)}")
            end
          rescue KeyError
            error "no such list: #{id}"
          end
        end
      end
      @doc_status[:caption] = nil

      if caption_top?('list') && captionstr
        puts captionstr
      end

      body = lines.inject('') { |i, j| i + detab(j) + "\n" }
      args = ''
      if lineno
        args = "linenos=true,firstnumber=#{lineno}"
      end
      puts %Q(\\begin{minted}[#{args}]{#{lang}})
      print body
      puts %Q(\\end{minted})

      if !caption_top?('list') && captionstr
        puts captionstr
      end

      puts '\\end{reviewlistblock}'
      blank
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

コードハイライトは //list//listnum//emlist//emlistnum に適用されるようにしました。コマンド実行例に使うことを想定している //cmd については、インライン命令で @<b> を使うことが多いなどの理由でハイライトから外しています。

インライン命令とコードハイライトはとても相性が悪く、ハイライトルールをインライン命令の内容が壊してしまうほか、インライン命令の命令部分がそのまま出力に出てしまいます。これを回避しようとすると pygmentize のラッパーを書くといった作業が必要になり、記事の範疇を超えてしまうので省略します。インライン命令とコードハイライトの問題は HTML でも同じです。

元々の Re:VIEW のメソッド実装から変えていることとしては、

  • Compiler#non_escaped_commands メソッド定義でハイライト対象コードブロックから cmd を除外

  • LATEXBuilder#cmd はハイライト判定を無視して、ハイライトなしのほうのロジックだけを実装

  • LATEXBuilder#emlist などそれ以外のコードリストメソッドは common_minted_code メソッドの呼び出しに変更。省略時のデフォルト言語は元々では nil だが、今回の実装では何らかの明示が必要なので sh (シェルスクリプト) に

  • LATEXBulder#common_minted_code で minted 環境でコードを出力する。\begin{minted}[オプション]{Lexer名} \end{minted} が基本形。num 付きのときには \begin{minted}[linenos=true,firstnumer=最初の番号] というオプションを付けることで行番号が自動で付くようになる

minted 環境の「Lexer名」は、Re:VIEW のコードリストの「言語名」として渡します。

//emlist[][ruby]{ ←rubyがLexer名として渡される
//list[auctexel][auctex.el][elisp]{ ←elispがLexer名として渡される

Pygments にどのような Lexer名が用意されているかは、次のコマンドで調べられます。

pygmentize -L lexer

sty/review-custom.sty で事前定義したスタイルは、この Lexer名と対応しています。

実行!

サンプルとして次のような minted.re ファイルから PDF を作ってみます。

= mintedによるコードハイライト

//cmd[コマンドラインはエスケープなしで普通にRe:VIEWタグ利用]{
> @<b>{ls デスクトップ/test}
file1  file2  {}_  @<chap>{minted}
//}

//embed[latex]{
%\clearpage
//}

//emlist[Pythonのハイライトコード(GitHubフレーバー)][python]{
def f(x):
  y = x ** 2
  return y
//}

//firstlinenum[3]
//emlistnum[行番号付きのハイライトコード][python]{
def f(x):
  y = x ** 2
  return y
//}

//emlist[][ruby]{
#!/usr/bin/env ruby
class MegaGreeter
  attr_accessor :names

  # オブジェクトを作成
  def initialize(names = "World")
    @names = names
  end

  # みんなに挨拶
  def say_hi
    if @names.nil?
      puts "..."
    elsif @names.respond_to?("each")
      # @namesは何らかのリスト…イテレーションしよう!
      @names.each do |name|
        puts "Hello #{name}!"
      end
    else
      puts "Hello #{@names}!"
    end
  end

  # みんなにさよなら
  def say_bye
    if @names.nil?
      puts "..."
    elsif @names.respond_to?("join")
      # カンマでリスト要素を結合
      puts "Goodbye #{@names.join(", ")}.  Come back soon!"
    else
      puts "Goodbye #{@names}.  Come back soon!"
    end
  end
end
//}

//list[auctexel][auctex.el][elisp]{
;;; auctex.el
;;
;; This can be used for starting up AUCTeX.  The following somewhat
;; strange trick causes tex-site.el to be loaded in a way that can be
;; safely undone using (unload-feature 'tex-site).
;;
(autoload 'TeX-load-hack
  (expand-file-name "tex-site.el" (file-name-directory load-file-name)))
(TeX-load-hack)
//}

//listnum[tssample][TypeScriptのサンプル][ts]{
class Car {
  drive() {
    // hit the gas
  }
}
//}

結果は次のとおりです。

_images/minted-3.pngminted の例 (cmdとPythonコード)

_images/minted-4.pngminted の例 (Rubyコード)

_images/minted-5.pngminted の例 (Emacs LispコードとTypeScriptコード)

良い感じです。言語に基づいてコードハイライトがそれぞれ変わっていることがわかります。また、Python・Ruby・Emacs Lisp は先にスタイルをカスタマイズしているので、フォントサイズ・スペースの明示化・囲みや背景などもそれぞれ違っていますね。

繰り返しますが、minted には多数のオプション指定があるので、詳細については texdoc minted を参照して、好みの形に合わせていくとよいでしょう。

余談とヒント

Re:VIEW のインラインコード表現である codett についても、\mintinline を使うようにすればいちおうハイライトはできるでしょう。ただ、Re:VIEW記法レベルでは言語の指定方法がありません。言語が決めうちであれば簡単ですが、任意のものを使いたいというときには @<code>{|python|print(x**2)} のように言語指定したものを解析するロジックを作る必要があるでしょう。

minted は中で都度 pygmentize を呼び出しているので、リストの個数が多くなるとかなり遅くなります。一度解析したものはキャッシュされるので、複数回の TeX コンパイル実行のうち遅いのは1回目だけのはずですが、それでも大きな本になるとわりと辛くはなります。ドキュメントシステムの Sphinx では Python ネイティブであるほかに TeX ソースを作る時点でハイライト適用済みなものに変換するという手段を取っていて高速なので、似たような形にできればもっと高速化を図れそうです。

ハイライトのスタイルによっては、白黒化したときにとても見辛くなる可能性があります。また、スタイルの色は RGB ですが、CMYK 刷り、あるいは2色刷りにするときには許容される CMYK 値になるように pygments / minted に割り込んで変更する必要があります。

2021/9/30 by @kmuto

章扉を画像で差し替える

凝った章扉にしたいときに、TeX でがんばるのではなく、別途作成しておいた AI ファイルや PDF ファイルで差し替える方法を紹介します。


review-jsbook、review-jlreq はいずれもデフォルトの章の表現はシンプルで、商業書籍によくあるような1ページ独立のページ (章扉) にもなっていません。章扉にすること自体はさほど難しくはないのですが、それでも商業書籍のような凝った見た目の章扉にしようとTeXでがんばろうとすると、考えないといけないことが多すぎて挫折することになるでしょう。

このようなときには、WYSIWYG なツール、たとえば Illustrator や Photoshop などを使って PDF を作成し、それで差し替えるのが最も手軽です(ほかのツールでもよいのですが、ピクセル値ではなく実寸のmm単位を使って作成できる必要があります)。

もちろん、TeX で全体 PDF を作ってから手動で差し替えることもできますが、ビルドのたびに差し替え作業をするのは手間ですよね。

実装

実装サンプルとして、chaptobira を用意しています。この中の book-built.pdf が実際にビルド済みの PDF なので、確認してみてください。

_images/tobira-1.png扉の差し替え例

章扉ファイルの用意

章扉は、Illustrator で作成し、本文の1〜3章に合わせて images フォルダに chapter1.ai、chapter2.ai、chapter3.ai という3つを作りました。ここでは仕上がりサイズが A5 としたので、Illustrator で A5 用紙を選択し、印刷用に塗り足し 3mm も付けています。

ここで、見出しの文字列やリード文も ai ファイル内に直接入れています。このため、文字を修正したいときには re ファイルではなく Illustrator で ai ファイルを修正する必要があります。その代わりとして、TeX の制約に囚われることなく自由な表現ができます。

説明が後になりましたが、実際には取り込み時には Illustrator の ai ファイルのネイティブな情報ではなく、ai ファイル内の互換表示用 PDF 情報が使われています。おおむねこれで問題ないのですが、レイヤーで非表示にしていたものは無視して表示されるなどの現象があるので、そのような構成になっている場合は横着せずに pdf ファイルを書き出す必要があります。

Photoshop の場合は、psd ファイルは TeX ドライバ側が対応していないので、pdf ファイルで書き出す必要があります。

クラスファイルの選択とマクロ設定

Re:VIEW には jsbook を基底とする review-jsbook と、jlreq を基底とする review-jlreq の2つのクラスがありますが、見出しの変更などカスタマイズをするには review-jlreq のほうがずっと容易です。本実装でも review-jlreq を採用しています。

もし手元で新規に review-jlreq を使ったプロジェクトを作りたいときは、review-init --latex-template=review-jlreq プロジェクト名 のように指定してください。

次に、sty/review-custom.sty において、章表現マクロの \chapter を jlreq が用意している TobiraHeading 形式に変更します。TobiraHeading の中では format パラメータで紙面表現を設定するのですが、ここで章番号(\thechapter)に基づいて用意済みの章扉ファイルを紙面全体に貼り付けるようにします。

\RenewTobiraHeading{chapter}{0}{
  type = han,
  label_format={\thechapter },
  format = { \ifnum \thechapter>0 \includefullpagegraphics{images/chapter\thechapter.ai} \else #2 \fi }
}

章扉が PDF ファイルであれば、format パラメータの chapter\thechapter.aichapter\thechapter.pdf にするだけです。

ifnum は章番号が1以上であれば章扉ファイルを、そうでなければそのまま見出しを書き出すようにしていますが、あくまで念のためです(実際、そのまま見出しを書き出すだけでは困りますし)。

これで実際ビルドしてみると、章扉は確かに置き換えられます。が、目次タイトルが「そのまま書き出す」ことに気付くでしょう。現時点の jlreq では目次タイトルを \chapter で表現しているため、変更のあおりを受けてしまうのでした(ちなみに章番号は0です。ifnum 定義がなければファイルがないエラーになるところでした)。

この対策として、TobiraHeading に変える前の、もともとの chapter 表現内容をバックアップし、目次内ではそれをリストアして使うようにしておきます。

% \chapterを書き換える前に現在のをバックアップ
\SaveHeading{chapter}{\restoreoldchapter}

\RenewTobiraHeading{chapter}{0}{
 …
}

% 目次のchapterは昔のを使う
\let\orgtableofcontents\tableofcontents
\renewcommand{\tableofcontents}{\restoreoldchapter\orgtableofcontents}
ビルド

ここまでできたら、以降はとり立てて変わることはありません。rake pdf で PDF が生成されます。当然ながら、用意している数以上に章が増えると、TeX のコンパイルエラー(画像が見つからない)になります。

ヒント

  • format パラメータには番号や見出し文字列も引数で渡されているので、章扉ファイルを使わない、あるいは章扉ファイルは背景だけにして、あとは TeX でがんばることも可能ではあります。\textpos を使って絶対位置指定する方法や、TikZ を利用する方法も考えられます。

  • たとえばエピグラフを入れたいというとき、jlreq.cls の見出しは副題をサポート(\chapter{見出し}[副題])していて format パラメータにも渡されるので、これを活用するのがよいかもしれません。Re:VIEW からこれにどう展開するかについては、review-ext.rb で headline メソッドを書き換えることになるでしょう。副題に入れるエピグラフ文字列群は review-ext.rb でついでに定義してしまうか、テキストファイルで用意しておいて読み込むことが考えられます。

EPUB に関連する長めの Tips

2019/2/11 by @kmuto

ハイライト内でのインライン命令の処理

コードハイライト内でどうしてもインライン命令を使いたいときに強引に処理するパッチを紹介します。


EPUBMaker および WebMaker では、config.yml で以下のように設定すると、コード群に対してコードハイライト(コード内容に基づいて色や字形で装飾し、わかりやすくする)をかけることができます。

highlight:
  html: "rouge"

_images/highlight1.pngコードハイライト

問題点

しかし、このコードハイライトには1つ大きな問題があります。以下のようなコードはどうなるでしょうか。

//emlist[][ruby]{
def hello
  @<i>{コードをここに書く}
end
//}

_images/highlight2.pngインライン命令付きのコードハイライト(HTML タグが文字化されてしまった)

おっと……インライン命令の @<i> が HTML の i タグに展開されたところまでは想定どおりだったのですが、さらにエスケープされてリテラルに表示されてしまいました。おまけに、コードハイライタがこの部分をエラーとしてエラー装飾にしています。

review-ext.rb による挙動の変更

ということで、いささか無理矢理感があるのですが、インライン命令を処理する実装を作ってみました。

ハイライトエスケープのreview-ext.rb をダウンロードし、作業フォルダに配置することで、EPUBMaker / WebMaker ではハイライト内のインライン命令がそのまま使えるようになります。

_images/highlight3.pngインライン命令付きのコードハイライト(正常表示)

内部処理をざっと説明すると、以下のとおりです。

  • HTMLBuilder の場合には embed だけでなく list や emlist などのリストブロック命令も、最初の時点ではインライン命令処理を行わないようにする。

  • Compiler#textメソッドに2つめの配列引数を追加し、指定があるときにはインライン命令の展開内容をそこに保存し、代替文字として \x01 文字を入れておく。

  • HTMLBuilder の各リストブロック命令実装内でインライン命令処理を行い、インライン命令の展開内容は配列に格納しておく。ハイライトの処理が終わったら \x01 の箇所を配列から戻す。

  • コードハイライタは \x01 の箇所をエラーにするので、配列から戻す際についでにエラー表現の span タグは消しておく。

  • ついでに、リストブロック命令に言語指定がなかった場合はハイライトしないようにしておく。そうではなく明示的に「none」だったらハイライトしない、としたかったら 174 行目をコメントアウト、175 行目のほうのコメントを解除とするとよい。

だいぶ汚いやり方なので、現時点ではこの実装を Re:VIEW 自体に取り込むのは消極的です。入れるとすれば、パーサ自体を書き換えと一緒のタイミングとなるでしょう。

余談:PDFMaker でのハイライト内のインライン命令処理

現状、PDFMaker(LaTeX)のほうは、ハイライト内のインライン命令処理についての汎用的な対応は困難です。コードの解析が LaTeX のマクロ処理時に行われるため、HTML のように割り込んで対処するということができないからです。

汎用性には欠けそうですが、アイデアをいくつか示しておきます(一部は実際筆者が特定業務向けに実装したものもあります)。

  • plistings 環境で mathescape=true とし、$ $ にインライン命令の内容を書き込むようにする。リテラルな $ の処理が必要。

  • コード表現に minted マクロを使う。minted は内部で pygmentize 命令を呼び出すが、代わりに \MintedPygmentize マクロで途中で割り込みをかけるコマンドを呼び出すようにし、インライン命令に手当てする。外部コマンド呼び出しのため、texoptions パラメータに --shell-escape を追加する必要もある。

  • 事前に Re:VIEW 側で pygmentize を行って LaTeX 向けにハイライトおよびインライン命令を処理し、これを加工した上で fvextra マクロなどを使って表現する(注:rouge はまだ LaTeX フォーマッタを保有していない)。

その他の長めの Tips

2018/9/29, 2018/12/15 by @kmuto

生成した PDF の印刷所入稿

Re:VIEW を使って PDF を気軽に生成することはできますが、印刷所で印刷してもらって製本するという場合は、家庭用のプリンタで印刷してコピー本を作るのとは異なり、十分な注意と配慮が必要です。


「入稿」ということ

(主に書籍にまつわる)何らかのデータを誰かから引き渡されるという「入稿」という言葉は、作業者の立場や状況によってさまざまに変わりますが、本記事では書籍のデータを印刷(および製本)してもらうために印刷所に渡すことを 入稿 と表現することにします。

印刷所での印刷、製本は、家庭用のプリンタで印刷してコピー本を作るのとは異なる世界です。よく理解しないまま入稿すると、印刷所を困らせるだけでなく、想定していたのと全然違う、とても売りに出せない本が出来上がってしまうかもしれません。

Re:VIEW を使った書籍の入稿においては、1冊ぶんのまとまった PDF を印刷所に入稿するのが普通です。これを PDF 入稿 と一般に呼んでいます。LaTeX(pdfmaker)や CSS(ブラウザ出力など)を使った組版の場合は、もともと1冊ぶんのまとまった PDF が作成されるはずです。InDesign の場合は章単位でドキュメントファイルが分かれることがありますが、ブック機能などを使って1冊ぶんにまとめた PDF を作ります。

なお、背も付くようなボリュームの場合は、表紙・背・裏表紙を1枚にした PDF も別途入稿しますが、本記事ではこれについては説明を省略します。

印刷所の入稿仕様に従う

どの印刷所も、入稿にあたってはそれぞれのハウスルールを定めています。これを 入稿仕様 といいます。入稿にあたっては、この仕様を正しく守っていることが大前提です。

主な入稿仕様としては、たとえば以下のようなものがあります。

  • PDF のバージョンおよび対応標準形式

  • 色の持ち方

  • 推奨解像度

  • 塗り足し範囲やトンボの設置

  • ページ番号の付け方

入稿仕様に違反しても印刷所でなんとかしてくれることはありますが、それはあくまでも印刷所の善意に乗っかっているに過ぎません。皆さんも、設計で整数型としているのに文字列型の値を渡されたらイラッとしますし、保証できませんよ?と思いますよね。

特に PDF 入稿の場合は、印刷所の側には元データがなく修正できることが限られるので、入稿仕様に合致しているかどうかの責任はすべて入稿者側にあります。

紙面サイズの決定

家庭用プリンタの縮小印刷とは異なり、印刷所に入稿する PDF の仕上がり紙サイズは 実寸 である必要があります。つまり、B5 の書籍にしたければ B5 実寸でレイアウトされていなければなりませんし、A5 にしたければ同様に A5 実寸でなければなりません。A4 で作ったものを印刷所で適当に縮小してくれる、ということはありません。

LaTeX で紙面サイズを設定する方法については、 LaTeX の紙面サイズを変更するにはどうしたらよいですか? を参照してください。

Re:VIEW 3 から、texdocumentclass パラメータの paper= オプションで紙面サイズを容易に変更できるようになっています。

CSS 組版を使用し、ブラウザから B 列の用紙(B5 など)に出力する場合は、注意が必要です。B 列には大きさが若干異なる ISO と JIS の二種類の規格があり、日本の紙は JIS に基づいていますが、ブラウザの PDF 出力ドライバによっては ISO 規格の値を使用してずれが生じる可能性があります。

  • JIS B5:182×257mm

  • ISO B5:176×250mm

検査方法

現在どのサイズなのかを確実に判断するには、Adobe Acrobat Pro DC(無料の Reader ではなく、編集機能などを持つ有償商品)の「印刷工程」→「ページボックスを設定」→「仕上がりサイズ」などを使います。

_images/papersize_m.png仕上がりサイズ確認

あるいは、フリーソフトウェアとしては Poppler が入っている場合は pdfinfo コマンドで調べることもできます(Debian や Ubuntu の場合は poppler-utils パッケージ)。

以下は LaTeX から生成し、トンボの付いていない A5 紙面の PDF の例です。単位は point で表示されます(mm にするには 0.352778 を掛けます)。計算丸めなどもあるため、小数点第一位程度の精度で判断すればよいでしょう。

$ pdfinfo -box book.pdf
 …
Page size:      419.53 x 595.28 pts
Page rot:       0
MediaBox:           0.00     0.00   419.53   595.28
CropBox:            0.00     0.00   419.53   595.28
BleedBox:           0.00     0.00   419.53   595.28
TrimBox:            0.00     0.00   419.53   595.28
ArtBox:             0.00     0.00   419.53   595.28
 …

後述のデジタルトンボが付いている場合は、以下のようになります(仕上がり A5 紙面を A4 メディア中央に配置した状態)。

$ pdfinfo -box book.pdf
 …
Page size:      595.28 x 841.89 pts (A4)
Page rot:       0
MediaBox:           0.00     0.00   595.28   841.89
CropBox:            0.00     0.00   595.28   841.89
BleedBox:          79.37   114.80   515.90   727.08
TrimBox:           87.87   123.31   507.40   718.58
ArtBox:             0.00     0.00   595.28   841.89
 …

この場合仕上がりサイズとして見るべきは TrimBox の値で、幅 507.40 - 87.87 = 419.53、高さ 718.58 - 123.31 = 595.27 で正しく A5 であることがわかります。

一般に使うであろう代表的なサイズを以下にまとめておきます。

  • A4:210×297mm、595.28×841.89 pts

  • A5:148×210mm、419.53×595.28pts

  • B5(JIS):182×257mm、515.91×728.50pts

綴じ方の決定

一般的な書籍は、左右のどちらか片方を綴じることで、本としての体裁となります。左側を綴じることを 左綴じ・左開き といい、技術書など横書きの書籍では通常こちらを使います。右側を綴じることを「右綴じ・右開き」といい、縦書きの書籍に通常使います。

LaTeX や InDesign は、方向によって適切な綴じ情報を PDF に含めるので、これを気にする必要は通常ありません。

入稿時に綴じ指定を逆にしてしまうと、「横書きなのに右綴じ」のような泣くに泣けない本ができてしまいます(通常は印刷所から本当にそうするつもりなのか確認が来るとは思いますが……)。

検査方法

Acrobat Pro の場合は、「ファイル」→「プロパティ」→「詳細設定」→「読み上げオプション」に「綴じ方」という項目があり、「左」「右」の現在の設定値があります。切り替えも可能です。

_images/toji_m.png綴じ方の情報

  • pdfinfo などのツールで調べる方法は不明です。iText ライブラリでは、ビューアオブジェクトのプリファレンス PdfName.DIRECTION から調べられるようです。

ページ数

本にするには、最低限、偶数 にする必要があります。

さらに、印刷所では1枚の大きな紙に複数のページを一度に印刷してそれを裁断するという工程をとるため、無駄を防ぐために基準の枚数セットが決まっています。2、4、8、16、32 といった枚数セットのどれに従うかは印刷所によります。そして、入稿する PDF のページ数はこの枚数セットの倍数に揃えなければなりません。

たとえば枚数セットが 4 となっている場合、80 ページであれば 4 の倍数なので適切ですが、82 ページだと倍数でないため不適切です。

ページが不足しているときには何か埋め草を作る、逆に多いときには内容を削る・紙面を調整する(見栄えが悪い箇所を「少しだけ」調整する を参照)などの対処をします。

検査方法

PDF の全ページ数はビューアのページ数表示から判断することもできますが、pdfinfo コマンドを使うこともできます。

$ pdfinfo book.pdf
 …
Pages:          80
 …

前付にローマ数字を使っている場合はうっかりその数え漏れをすることがあるので、物理的な全ページ数を確認できるこのコマンドを併用するとよいでしょう。

トンボ

PDF の入稿の場合、一般に仕上がりと塗り足し領域情報からなる デジタルトンボ を付けることが推奨されます。仕上がりサイズのままでも入稿を受け付ける印刷所もありますが、紙面の上下左右いっぱいにかかる要素があるときには、白フチができてしまうなどの問題が生じます。

_images/border.png塗り足し有無の違い

LaTeX を使用しているときには jsbook ベースのドキュメントにトンボおよびデジタルトンボを配置する が参考になるでしょう。Re:VIEW 3 では、media=print 時には自動でデジタルトンボが設置されます。

InDesign の場合には標準でトンボ・デジタルトンボを設置する機能があります。

CSS を使ったブラウザ出力 PDF の場合は、ブラウザ側からは妥当なデジタルトンボを埋め込めないので、生成された PDF を別途 LaTeX あるいは InDesign に貼り付けるなどしてデジタルトンボを設置します。

塗り足し領域の幅については、入稿仕様に記されています。通常は 3mm ですが、印刷所や製本方法によっては 5mm のときもあります。

検査方法

Acrobat Pro の表示設定で「アートサイズ、仕上がりサイズ、裁ち落としサイズを表示」を有効にすると表示上で確認できます。「印刷工程」→「ページボックスを設定」からはより詳細な数値を得られます。

_images/showbox_m.png「ページボックスを設定」での確認

前出の pdfinfo コマンドの -box オプションでも確認できます。

$ pdfinfo -box book.pdf
 …
Page size:      595.28 x 841.89 pts (A4)
Page rot:       0
MediaBox:           0.00     0.00   595.28   841.89
CropBox:            0.00     0.00   595.28   841.89
BleedBox:          79.37   114.80   515.90   727.08
TrimBox:           87.87   123.31   507.40   718.58
ArtBox:             0.00     0.00   595.28   841.89
 …

Page size および MediaBox・CropBox・ArtBox は同じ値で、ビューア向けのサイズ(ここでは A4)、TrimBox は書籍の仕上がりのサイズ(ここでは A5)です。BleedBox が塗り足し領域で、TrimBox の外周 3mm(8.5 point)になっています。

通しのページ番号(ノンブル)

同人誌印刷所によっては、製本検査のためと思われますが、ページ番号(ノンブル)に以下のうちのいくつか、あるいは全項目を採用するよう、制限を設けていることがあります。

  • ローマ数字は使わず、アラビア数字のみで先頭ページから順に振る(1 または 3 始まり)

  • 白紙のページにも振る

  • なるべく入れたくないとしても、ノドに小さく入れるなどの対処をする

LaTeX でアラビア数字のみで振る方法については、jsbook ベースのテンプレートで、ページを頭からの通し番号にするにはどうしたらよいですか?に一例を挙げています。

Re:VIEW 3 では、texdocumentclass パラメータに startpage=1,serial_pagination=true,hiddenfolio=nikko-pc といったオプション指定を付けることで、アラビア数字の通しページおよび隠しノンブルを実現できます。

フォント

PDF 入稿では、フォントはすべて「埋め込み」または「アウトライン」のいずれかにする必要があります。Re:VIEW のデフォルトの LaTeX 設定、InDesign では埋め込みになっているはずです。

また、PDF 内の文字表現方法としては、Type1、Type3、CID があります。詳細はここでは説明しませんが、PDF 入稿にあたっては以下のルールがあります。

  • 欧文は Type1 か CID を使う

  • 和文は CID を使う

  • Type3 は使ってはならない

PDF 紙面内で使っている文字がどの形式になるかは、フォントファイルや組版ソフトウェアによって異なりますが、Re:VIEW のデフォルトの LaTeX 設定や InDesign では Type1 または CID になるはずです。

これに対し、2018年9月時点で、Chrome ブラウザから生成した PDF では、OpenType フォントを使っている文字は(不適切な)Type3 形式になります。TrueType フォントの場合は CID 形式になるようです。Type3 形式の文字は、印刷の面では描画品質が低い・PDF 処理をする印刷機では異常なエラーを起こすことがあるために利用できないほか、電子的に配布する場合でも、表示品質が低い、文字情報が不足しているので検索できないことがある、といった問題があります。

Type3 が含まれている PDF のままでは入稿できないため、以下のいずれかの対応が必要です。

  • 問題のないフォントファイルや設定に変更する(Chrome ブラウザの生成であればたとえば TrueType フォントにする)

  • 全体をアウトライン化あるいは画像化する。macOS の プレビュー.app で保存し直す、または InDesign に貼り付けることで、PDF の Type3 フォントをアウトラインに変換できます(テキスト化・検索などはできなくなります)。

なお、LaTeX や InDesign でも、不適切なフォント設定(埋め込みでない・Type3 であるなど)の EPS や PDF 形式の図版を貼り付けると、当然ながら同じ問題が生じます。

検査方法

Acrobat Pro の「ファイル」→「プロパティ」→「フォント」で、PDF 内の使用フォント情報を一覧できます。フォント名のところに「埋め込みサブセット」と付いており、種類が「Type1」か「Type1(CID)」であれば問題ありません。

_images/fonts_m.pngPDF内の使用フォント一覧

  • 種類に「TrueType」 というものが出ることもありますが、こちらも埋め込みになっていれば問題ないようです。

また、Poppler のツールの中に、pdffonts というコマンドがあります。これを使って調べることもできます。

$ pdffonts book.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
RLTGDT+URWGothicL-Demi               Type 1C           WinAnsi          yes yes no      11  0
YFGDGA+NotoSansCJKjp-Black-Identity-H CID Type 0C       Identity-H       yes yes yes     13  0
CAPSZS+NotoSansCJKjp-Bold-Identity-H CID Type 0C       Identity-H       yes yes yes     18  0
 …

type の列が「Type 1」「CID」「TrueType」といったものになっており、かつ emb(埋め込み)の列がすべて「yes」になっていれば問題ありません。

次のように出てしまったら Type3 を含んでいるため、修正する必要があります。

$ pdffonts type3.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
[none]                               Type 3            Custom           yes no  yes   1311  0
[none]                               Type 3            Custom           yes no  yes    616  0
 …

フォントが埋め込まれていない場合は次のように emb 列が no となり、やはり修正する必要があります。

$ pdffonts noembed.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
 …
Ryumin-Light-Identity-H              CID Type 0        Identity-H       no  no  no       6  0
 …

PDF の色は、紙面印刷用の CMYK または 画面表示用の RGB のいずれかで表現されます。

CMYK は、C=シアン、M=マゼンタ、Y=イエロー、K=キー(一般には黒インク)の版を重ねることで色を表現します。黒は K 100%、白は CMYK いずれも 0% となります。

RGB は、R=レッド、G=グリーン、B=ブルーの原色を重ねることで色を表現します。黒は RGB いずれも 0%、白は RGB いずれも100%となります。

ビューアの画面で見る場合は CMYK の PDF でも通常は RGB に変換されるので、ぱっと見では違いがわかりませんが、入稿にあたっては大きな違いがあることに注意が必要です。PDF 入稿に使うのは、通常 CMYK のほうです(最近は一部の印刷所では RGB 直接の印刷にも対応しています。入稿仕様を確認してください)。

InDesign も LaTeX も CMYK・RGB どちらにも対応していますが、通常は CMYK を使うようになっており、黒は K 版で表されます。ただし、貼り付けた図版が RGB の場合、その箇所は RGB と混在することになります。

  • 図版ファイルを CMYK 化(白黒印刷の場合は K 版のみ)する。ただし、PDF・EPS・JPEG・TIFF のファイルは CMYK を表現できますが、PNG は RGB のみの表現なので別の画像形式に変換する必要があります。

  • PDF を最後に CMYK 化(白黒印刷の場合は K 版のみ)する

ブラウザから出力される PDF は RGB になっていることがあります。そのため、入稿仕様に CMYK と書かれていたら、CMYK にする必要があり、また白黒印刷用途であれば K 版のみ(グレースケール化)にしなければなりません。

Acrobat Pro のプリフライト機能を利用して RGB→CMYK 変換、あるいはカラー→グレースケール変換ができます。その際、カラープロファイルについて印刷所から特に指定がなく、設定が不明なときには、一般的に使われる Japan Color 2001 Coated が無難でしょう。

_images/colorpre_m.pngプリフライトでの色の変更

なお、Acrobat Pro で DC よりも古いバージョンの場合は色変換に不具合があり、特定の PDF の変換において「点線が実線になる」「線が太くなる」といった現象が発生します。筆者の経験では、callas pdfToolbox での色変換については、現時点で問題は生じていません。

Ghostscript でも RGB→CMYK 変換はできますが、壊れた箇所などがないか、十分に注意が必要です。以下で使用しているカラープロファイルの JapanColor2001Coated.icc は、Japan Color で配布されています。

$ gs -q -r600 -dNOPAUSE -sDEVICE=pdfwrite -o 出力PDF -dPDFSETTINGS=/prepress -dOverrideICC -sOutputCCProfile=JapanColor2001Coated.icc -sProcessColorMdel=DeviceCMYK -sColorConversionStrategy=CMYK -sColorConversionStrategyForImage=CMYK -dGrayImageResolution=600 -dMonoImageResolution=600 -dColorImageResolution=600 入力PDF
検査方法

Acrobat Pro であれば、「印刷工程」→「プレビュー」で色分解をして表示できます。たとえば白黒印刷用であれば、プロセスブラックのチェックを外し K を非表示にして、全体を見ていきます。もしトンボ以外で何か表示されたなら、それはあるべきでない色が存在する疑いがあります。

_images/kplate_m.pngK版を外して確認

  • Vivliostyle.js を使ってブラウザから生成した場合、黒の箇所は K で正しく表されているようです。

Ghostscript を使って生のデータを調査することもできます。

$ gs -dNOPAUSE -dBATCH -q -sDEVICE=inkcov -sOutputFile=- book.pdf 
 0.50724  0.50873  0.50954  0.00088 CMYK OK
 0.00000  0.00000  0.00000  0.00884 CMYK OK
 0.00000  0.00000  0.00000  0.05060 CMYK OK
 0.00000  0.00003  0.00003  0.00200 CMYK OK
 0.00000  0.00000  0.00000  0.00394 CMYK OK
 …

各ページの C、M、Y、K の含有率が示されています。たとえば白黒印刷なら、1〜3 つめの数値は 0.0000 でなければならないことになります。

RGB が使われている PDF の場合は、黒だけのつもりでも以下のような結果になります。

$ gs -dNOPAUSE -dBATCH -q -sDEVICE=inkcov -sOutputFile=- rgb-black.pdf
 0.00387  0.00387  0.00387  0.00286 CMYK OK

標準化

PDF には、印刷用に適するとされる標準仕様があります。国内の印刷所で一般的に採用されている標準は、以下の2つです。

  • PDF/X-1a:2001:PDF 1.3 に基づく。色は CMYK のみ。すべてのフォントは埋め込み。デジタルトンボを必要とする。透明は分割統合で処理される。

  • PDF/X-4:2008 または PDF/X-4:2010:PDF 1.6 に基づく。色は CMYK または RGB。すべてのフォントは埋め込み。デジタルトンボを必要とする。透明情報をサポート。

入稿仕様で、これらの標準に沿った PDF を入稿することを求められることがあります。PDF/X-4 が RGB をサポートしているからといって、必ずしも印刷所が RGB を受け付けるわけではないことには注意してください。PDF/X-4 を指定されている、あるいは PDF/X-4 でなければ表現できない、というのでなければ、PDF/X-1a でもなんら問題ありません。

現時点で、LaTeX やブラウザから出力した PDF を PDF/X-1a、PDF/X-4 準拠とするには、有償の Acrobat Procallas pdfToolbox を使う必要があります。

_images/x1a_m.pngAcrobat プリフライトでの標準化変換および検証

実際には PDF をそのまま入稿しても印刷所で問題なく印刷できるでしょうが、標準準拠は一定のデータ水準に達していることを保証し、印刷事故を未然に防ぐ重要な役割を担っています。

検査方法

Acrobat Pro では、プリフライトで PDF/X-1a または PDF/X-4 に準拠しているかどうかを確認できます。

完全に準拠しているかどうかはともかく、Acrobat Pro などを使って標準化対応済みかどうかは、pdfinfo コマンドでメタ情報を表示してみることでも判別できます。

$ pdfinfo -meta book-x1a.pdf
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
 …
         <pdfx:GTS_PDFXConformance>PDF/X-1a:2001</pdfx:GTS_PDFXConformance>
         <pdfx:GTS_PDFXVersion>PDF/X-1:2001</pdfx:GTS_PDFXVersion>
 …

Acrobat でのチェック

入稿した PDF は、Adobe の PDF エンジンを使った印刷機によって処理されます。そのため、実際の印刷物との齟齬を極力なくすには、Acrobat Pro、最低でも Acrobat Reader で表示して確認することが重要です。

macOS のプレビューアやブラウザのビューアは、一部の PDF の表現を正常に表現できないことがあり、入稿のための確認には不向きです。

また、Acrobat Pro DC 向けには、以下の「印刷トラブルを防ぐためのプリフライトDC」をプリフライトとして実行することで、入稿に危険がありそうな箇所を教えてくれます。

_images/trouble_m.png「印刷トラブルを防ぐためのプリフライトDC」によるチェック

なるべくコストをかけずに制作したいというのも人情ですが、不適切な PDF を入稿して発生した事故対応の損害や、ここまで挙げてきたリスクとその対策を念頭に置くと、Acrobat Pro の導入はそう高いものではないでしょう。

2021/2/1 by @kmuto

pandoc2review による Markdown ファイルの併用

pandoc2review ツールを使って、Markdown ファイルを原稿形式としたまま Re:VIEW の作業プロジェクトに取り込む手法を紹介します。


pandoc2review とは

Markdown や docx などの文書形式から HTML や TeX などに変換する汎用文書変換ツールとして著名なのが Pandoc というオープンソースソフトウェアです。この変換出力形式を Re:VIEW に対応させた pandoc2review というツールを作ってみました。

Ruby と Pandoc をセットアップした状態で、gem install pandoc2review を実行すれば pandoc2review がインストールされます。

単純な変換

Markdown や docx などのファイルを、次のように変換できます。

pandoc2review 入力ファイル名 > 出力ファイル名

たとえば、次のように使います。

pandoc2review article.md > article.re
pandoc2review document.docx > document.re

Markdown ファイル形式から Re:VIEW ファイル形式に変換するツールとしては md2review がすでに存在しますが、pandoc2review は docx なども含めて汎用的に利用できるほか、Markdown ファイル側の解析を強化しています。md2review では構造が誤認識されていた Markdown ファイルも、かなり良い精度で Re:VIEW ファイル化できるでしょう。

Re:VIEW プロジェクトとの組み合わせ

さて、本題に入ると、Re:VIEW プロジェクト内で Markdown ファイルをそのまま Re:VIEW の章ファイルとして扱うことができます。章ファイル単位であれば Markdown ファイルと Re:VIEW ファイルを混在させることも可能です。

準備作業は次のとおりです。

  1. 既存の Re:VIEW 作業プロジェクト、または review-init で新規プロジェクトを用意します。

  2. Rakefile ルールファイル z01_pandoc2review.rake をダウンロードし、プロジェクトの lib/tasks フォルダに配置します。

  3. プロジェクトの config.yml ファイルに contentdir: _refiles 行を追加します。

次に、Markdown ファイルを用意します。ch01.md を示します。

# こんにちは、Markdown

これは **Markdown** ファイルです。

プロジェクトの catalog.yml には、拡張子の .md.re に変えたファイル名で登録します。

PREDEF:

CHAPS:
  - ch01.re

APPENDIX:

POSTDEF:

Re:VIEW 形式で記述した ch02.re は以下です。

= こんにちは、Re:VIEW

これは@<b>{Re:VIEW}ファイルです。

当然これは catalog.yml に登録できます。

PREDEF:

CHAPS:
  - ch01.re
  - ch02.re

APPENDIX:

POSTDEF:

これで rake の各コマンドを実行すると、最初に pandoc2review の呼び出しと Re:VIEW 形式への変換が行われます。rake pdf で変換した例を以下に掲載します。

_images/page-md.pngMarkdown 部分のページ

_images/page-review.pngRe:VIEW 部分のページ

このように、Markdown ファイルをそのまま利用し続けられる仕組みが、簡単に実現できました。

内部的には、rake の実行時に lib/tasks/z01_pandoc2review.rake ルールが解釈され、Re:VIEW ファイルがあればそのまま _refiles フォルダにコピーします。Re:VIEW ファイルがなかったときには、もし Markdown ファイル(.md 拡張子)のほうがあれば、pandoc2review を使って Re:VIEW 形式に変換し、_refiles フォルダに書き出します。

pandoc2review は、Markdown ファイルの記法(pandoc が提供している Makrown 拡張記法)を逸脱しない範囲で、Re:VIEW の各命令にできるだけ対応させています。

div や span のタグを使って Re:VIEW のブロック命令・インライン命令に展開できるので、相互参照や索引なども無理なく表現できます。各対応および表現サンプルについては、pandoc2review における Markdown 形式処理の注意事項 を参照してみてください。

FAQ(よくある質問と回答)

FAQ - Re:VIEW そのものについて

FAQ(よくある質問と回答)のこのセクションは、直接に Re:VIEW の利用には関わらない内容を記しています。


Re:VIEW はなんと発音するのですか?

「りびゅー」といいます。

Re:VIEW とは何ですか?

Re:VIEW は、主に書籍制作向けのテキストマークアップ言語仕様、およびその変換システムです。指定の記法で記述した原稿ファイルを、HTML、LaTeX、InDesign 用 XML、プレインテキストなどに変換することができます。さらに、HTML を使った EPUB、LaTeX 環境を経由した PDF をそれぞれコマンド1つで作成可能です。

Re:VIEW の Web サイトはどこですか?

Re:VIEW は誰のためのソフトウェアですか?

主なターゲットは、書籍の編集者や著者・訳者です。

より狭義には、Re:VIEW を開発しているチームのメンバーたちがそれぞれ自身のドキュメント制作・管理・業務の効率を上げるためのソフトウェアです。

実際、誰が使っていますか?

技術書分野を中心に、商業刊行物の制作会社および出版社、あるいは同人誌の制作者など、幅広く使われています。

自己申告をもとに GitHub の wiki にて、利用実績 をまとめています。

Re:VIEW は誰が作っていますか?

Re:VIEW は、青木峰郎(@mineroaoki)によって設計・開発されました。その後、武藤健志(@kmuto)が開発を引き継ぎ、高橋征義(@takahashim)、角征典(@kdmsnr)が加わったチームで開発を続けています。

Re:VIEW はいつ作られましたか?

記録によると 2002 年に作成されました。

Re:VIEW のソースコードは公開されていますか?

GitHub のパブリックリポジトリ上で開発しており、ソースコードおよび開発プロセスはすべて公開されています。

https://github.com/kmuto/review

個々の改良は issue と PR が中心ですが、年に数回、開発チームや関心の深いユーザーが face-to-face で集まって大きな方針の策定や次期バージョンの機能目標の設定などを行います。

Re:VIEW のリリーススケジュールはどうなっていますか?

大まかには毎年「2月」「6月」「10月」の月末にリリースすることにしています(開発状況によって前後することがあります)。

具体的には、ニュースリリースに修正内容をまとめ、バージョン番号を更新し、新たな gem パッケージを RubyGems に公開してダウンロードできるようにします。

開発の先端は常に GitHub の master ブランチです。

Re:VIEW のバージョンルールはどうなっていますか?

「メジャーバージョン.マイナーバージョン.フィクスバージョン」となります。

  • メジャーバージョン:後方互換性を大きく損ねることも覚悟した大きな更新です。Re:VIEW ソフトウェアは書籍制作向けという性質上、新たなバージョンでも後方互換性はできるだけ保持しようとしていますが、それが改良の大きな足枷となる場合には互換性を破棄することもあります。

  • マイナーバージョン:基本的に後方互換性を保持した更新です。新機能の導入と、既存の不具合の修正を中心とします。

  • フィクスバージョン:リリース後に発見された重大な不具合のみを修正します。

2022年6月時点で、安定版は「5.5.0」です。

Re:VIEW のサポートルールはどうなっていますか?

Re:VIEW 自体は一切の保証はなく、また開発リソースを鑑みて古いバージョンを維持することに労力を割けません。

過去にリリースしたバージョンへの修正対応は行いません。発覚した問題についての対応は、その時点で最新のバージョンに修正を加えた「次のバージョン」においてのみ行われます。

バージョンごとの機能差異はどこかにまとまっていますか?

Re:VIEW は何の言語で書かれていますか?

Ruby 言語で書かれています。2021年12月時点では、Ruby 2.4 以上を想定しています。なお、2022年6月のリリースにおいて Ruby 2.7 未満のサポートを停止する予定でしたが、大きな変更をしなかったこともあり、まだ 2.7 未満への互換性を保持しています(ただし、Ruby 2.7 未満のバージョンにおける固有の不具合はもう対応しない可能性が高いです)。

Ruby 実装との完全な互換性はありませんが、JavaScript による実装も存在します。https://github.com/vvakame/review.js

Re:VIEW の開発に参加したいですがどうしたらよいですか?

まずは、https://github.com/kmuto/review への issue 登録や PR から始めてみるとよいでしょう。

issue での説明は日本語または英語で書いてください。

「Re:VIEW」という名前は検索しづらいです。変えるべきではないですか?

過去に一度「ReVIEW」から「Re:VIEW」としましたが、むしろ検索精度は悪化しました。

名前を変えることには「絶対に固有で国際的にネガティブなイメージもない妥当な名前を選ぶ」「プロジェクト名を変更する」「新しい名前を周知する」などいろいろなエネルギーが必要ですが、変更で得られる利益に見合わないと考えます。

Re:VIEW は TeX ですか? あるいは TeX に置き換わるものなのですか?

いいえ。

TeX(LaTeX)は Re:VIEW 形式ファイルからの変換先の1つです。ただし LaTeX 変換・LaTeX コンパイル・PDF 生成までを一括で実行する review-pdfmaker というコマンドは用意しています。

Re:VIEW は TeX (または InDesign など) を知らなくても使えますか?

これは「はい」でもあり、「いいえ」でもあります。

Re:VIEW の目的は、TeX や InDesign などのタイプセット環境の記法を気にせず一貫した Re:VIEW マークアップで記述した原稿から、タイプセット環境に適した変換物を生成することにあります。ですので、この段階の範囲では TeX や InDesign などのタイプセット側の知識がなくても利用できます。

これに対し、タイプセット環境でどのように表現するかは紙面デザインによってアプローチが異なり、万能の形状はありません。あるデザインに特化してしまった変換物では、ほかのデザインでまったく不都合になることがままあるため、Re:VIEW が出力する変換物は極力シンプルで、後で加工することを想定したものです。Re:VIEW が生成した変換物をどのようにタイプセット環境での表現と合致させ、加工するかは、タイプセット環境についての知識が必須です。

言い換えるならば、たとえば PDFMaker (TeX タイプセット) において、Re:VIEW 公式・あるいはサードパーティのテンプレートの範囲で実現している範囲であれば TeX の知識がなくても利用できますが、テンプレートの想定範囲を超えたカスタマイズ (書体や装飾を変更するなど) をする場合には TeX/LaTeX についての十分な知識が求められます。

Re:VIEW の「主要なビルダ」とは何ですか?

ビルダは Re:VIEW 形式の原稿ファイルを「HTML」や「LaTeX」などに変換する変換器のことです。現在いくつものビルダが Re:VIEW プログラムに収録されていますが、そのうち、以下のビルダを「主要なビルダ」としています。

  • HTML

  • LaTeX

  • TOP(テキスト)

  • IDGXML(InDesign XML)

Re:VIEW ソフトウェアに新たな命令を追加したり既存の挙動を変更したりする場合は、これらの主要なビルダすべてでエラーとならずに動作することが求められます。

また、主要なビルダはテストケースを豊富に用意しているため、コードロジックの変更による意図せぬ挙動の破壊は起きにくくなっています。

なぜ便利な「○○.gem」を使わないのですか?

Re:VIEW の開発スタンスとして、外部のツールやライブラリへの依存はできるだけ避けています。中核はあくまでも Ruby の基本ライブラリの範囲で実現します。

その代わり、コードハイライトのように「必須ではないが、より便利になる」オプショナルな機能については gem などの外部ライブラリの使用を許容しています。

Re:VIEW は日本語でしか使えませんか?

現時点で実績がさほどあるわけではありませんが、国際化対応しやすくなるような試みはしています。

たとえば //image を変換したときの「図X.X」の「図」の部分は、ロケールファイルとして切り出しており、config.yml の language パラメータ値に en を指定すれば「Figure 」に変わります。既存の設定ファイルは Re:VIEW プログラムの lib/review/i18n.yml にあり、カスタマイズを行うには、プロジェクトフォルダに locale.yml という名前のファイルで定義します。

ただし、TeX を使った PDF 生成については、提供しているスタイルファイルが日本語 LaTeX 環境を前提としています。他言語で使用するには、スタイルファイルなど広範囲での改変が必要になるでしょう。

なお、Re:VIEW に関するドキュメントについてはできる限り英語でも記述するようにしています。

なぜこの「Re:VIEW ナレッジベース」は Re:VIEW ではなく Markdown + Sphinx で書かれているのですか?

Re:VIEW は書籍向けのソフトウェアであり、Sphinx のような Web リファレンスを得意とするソフトウェアではないからです。rst で書いていないのは単にそこまで高機能な記述は本ナレッジベースの範囲では必要としていないからです。

FAQ - Re:VIEW とその成果物のライセンスについて

FAQ(よくある質問と回答)のこのセクションは、Re:VIEW のソフトウェアおよび Re:VIEW が生成する成果物ファイルのライセンスについて記しています。


Re:VIEW のライセンスは何ですか?

Re:VIEW のプログラムには、「GNU Lesser General Public License Version 2.1」(以下LGPL)が適用されます。

EPUB / TeX 用のレイアウトテンプレート、TeX 用のスタイルファイルについては「MIT License」(以下MIT)が適用されます。

TeX (pdfmaker)向けに内包している jumoline.sty スタイルファイルには「The LaTeX Project Public License」(以下LPPL)が適用されます。

Re:VIEW の LGPL、MIT、LPPL は具体的にどのようなライセンスですか?

  • ただありのままに「使用」することは、いずれのライセンスも目的・組織・国籍等一切問わず自由です。

  • ソフトウェアを使用した結果生成されるファイルには、Re:VIEW プログラムの権利保持者の権利は及びません。一般的に、たとえば PDF や EPUB などの成果物は原稿の権利者が著作権を持つことになるでしょう。

  • 「複製し、再配布」することについては、いずれのライセンスも、Copyright を含めて内容を変更せず、元のライセンスも保持する限りにおいて自由です。

  • LGPL が適用される Re:VIEW のプログラム(Re:VIEW コードの templates および vendor 内以外のファイル)は、自由に改変できます。ただし、その改変物を別の人や組織に複製する場合、求められれば改変箇所を提供先に公開する義務があります。改変物を再配布する行為を制限することもできません。

  • MIT が適用される Re:VIEW のテンプレート(Re:VIEW コードの templates 内のファイル、review-init コマンドによって sty フォルダに展開されるファイル)は、自由に改変できます。改変再配布においての制約もありません。

  • LPPL が適用される jumoline.sty ファイルは、改変時は名前を変更する必要があります。

Re:VIEW の利用に料金は必要ですか?

いいえ、Re:VIEW 自体の利用に料金は不要です。しかし当然ながら、実行にかかるコンピュータの運用費用やダウンロードの通信費用などはユーザーが負担するものと捉えます。

なお、Re:VIEW を組み込んだサービスや製品の利用、コンサルティング、Re:VIEW 原稿に対する編集や組版などの使役等ではそれぞれの提供者からの料金がかかる可能性があります。

Re:VIEW を使ったドキュメントや、生成される PDF、EPUB などにはどのようなライセンスが適用されますか?

Re:VIEW を使ったドキュメントや生成されるファイルには Re:VIEW ソフトウェアのライセンスは及びません。ドキュメント製作者あるいは使用者が任意のライセンスを適用できます。

つまり、Re:VIEW を使って作られた同人誌や商業書籍、論文、メモ、EPUB、Web ページなどを作成、あるいは販売・配布しようとするときに、Re:VIEW ソフトウェアのライセンスは無関係です。

他所から入手した図版などで別途ライセンスが存在する可能性がありますが、それはドキュメント製作者の責任において確認する必要があります。

review-init コマンド実行によって生成されるファイルの適用ライセンスは以下のとおりです。

  • sty フォルダにあるデフォルトの TeX スタイルファイル自体には Re:VIEW ソフトウェアの MIT ライセンスが適用されます。ただし、Re:VIEW 3 以降の review-custom.sty は空なので Re:VIEW ソフトウェアのライセンスは及びません。

  • Gemfile、Rakefile、doc、lib/tasks/review.rake、style.css には Re:VIEW ソフトウェアの MIT ライセンスが適用されます。

  • catalog.yml、config.yml、images、layouts、初期 re ファイル には Re:VIEW ソフトウェアのライセンスは及びません。

Re:VIEW ソフトウェアの権利者表記はどのように記すべきですか?

以下のとおりです(2020年10月時点)。

「Copyright (c) 2006-2020 Minero Aoki, Kenshi Muto, Masayoshi Takahashi, Masanori Kado.」

review-ext.rb のライセンスはどうなりますか?

まったく新規、あるいは誰が書いてもほぼそうなる(たとえば「Re:VIEW のモンキーパッチによる拡張の基本」にある基本構造のコード)ものには Re:VIEW ソフトウェアのライセンスは及ばないので、任意のライセンスを適用できます。

Re:VIEW ソフトウェアのコードの一部をコピーして改変する場合は、LGPL が適用されます。

Re:VIEW をフォークして新たなソフトウェアを開発してもよいですか?

ライセンスを遵守する限り、問題ありません。

Re:VIEW という名前をソフトウェアやサービス、製品に使ってもよいですか?

「Re:VIEW」の商標は保有していないので、私たちにそれを判断したり止めたりする権利はありません。しかし、「Re:VIEW ○○」のような名称を使う際には、それが Re:VIEW の開発チームの公式の提供物でないことを明記いただくようお願いいたします。

Re:VIEW を Web サービスや製品に組み込みたいのですが?

ライセンスを遵守する限り、問題ありません。

Re:VIEW を使って損害が生じました。賠償請求はできますか?

Re:VIEW は無保証のソフトウェアです。使用に際して生じたいかなる事故・損害も、開発者・配布者等の関係者は一切の責務を負いません。

Re:VIEW を組み込んだ Web サービス・製品で発生した事故・損害については、各提供者にお尋ねください。

Re:VIEW プログラムを友人に配りたいのですが?

公式な Re:VIEW ソフトウェアとして提供している GitHub 上のコード、および RubyGems で配布している gem ファイルは、改変しない限り自由に再配布できます。

改変して再配布する場合は、適用される各ライセンス条項に従ってください。

Re:VIEW を ○○ OS 用のパッケージにしてもよいですか?

はい、かまいません。ただ、Re:VIEW は活発に開発されている、つまりまだ安定して堅実という状態にはないため、OS のリリースや保守のスケジュールとは合わない可能性があります。

FAQ - Re:VIEW の使い方について

FAQ(よくある質問と回答)のこのセクションは、Re:VIEW の使用方法のポインタや、使う上での注意点などをまとめています。


Re:VIEW を動かすにはどのような環境が必要ですか?

Ruby インタプリタ 2.4 以上がインストールされた OS 環境であれば、基本的に動作します。TeX を使った PDF 生成を行う場合は、別途日本語 TeX 環境のセットアップが必要です。

推奨環境は Linux(特に Debian GNU/Linux 安定版 または Ubuntu 安定版)、および macOS です。

Windows でも、ネイティブ環境でのセットアップ、WSL(Windows Subsystem for Linux)でのセットアップの報告があります。

  • 現時点では、Ruby 2.4〜3.0のテストのみをしています。もし2.1〜2.3で奇妙な挙動を示すときにはご報告ください。(ただし、やむを得ず古いバージョンには非対応になる可能性はあります)

  • 2022年6月のリリースにおいて Ruby 2.7 未満のサポートを停止する予定です。

Re:VIEW はどうやってインストールしたらよいですか?

Ruby をセットアップ済みであれば、ターミナル(またはコマンドプロンプト)から以下のコマンドでインストールできます。

gem install review

プレビュー版をインストールするには以下のようにします。

gem install review --pre

OS の所定の手続きに従って、gem の bin フォルダにパスを通してください。

Gemfile を使っている場合は、以下の行を Gemfile に追加して bundle コマンドを実行します。

gem 'review'

Ruby はどうやってインストールしたらよいですか?

手順は OS によって異なります。

Debian GNU/Linux、Ubuntu の場合は以下のようにしてインストールできます。

apt-get install ruby

TeX 環境など完全な環境構築としては、以下のようにするのもよいでしょう。

apt-get install --no-install-recommends texlive-lang-japanese texlive-fonts-recommended texlive-latex-extra texlive-generic-extra lmodern fonts-lmodern tex-gyre fonts-texgyre texlive-pictures ghostscript gsfonts zip ruby-zip ruby-nokogiri mecab ruby-mecab mecab-ipadic-utf8 poppler-data cm-super graphviz gnuplot python-blockdiag python-aafigure

TeX 環境の構築はどうしたらよいですか?

Docker のイメージはありますか?

以下でセットアップできます。

docker pull vvakame/review

利用方法などは以下を参照してください。

docker pull で mac M1 (arm64) 用のイメージがありません

2022年1月時点で動作可能な Docker イメージ設定は用意しているのですが、Docker Hub に置く前提としての CI ビルドがうまく動いていません。

vvakame/docker-review 直下にある Dockerfile をダウンロードし、docker build コマンドで手元でビルドすれば動作する環境を構築できます。

CI をうまく動作させる方法がわかりましたら下記 PR にご提案お願いします。

基礎的なガイダンスを記した公式のドキュメントはありますか?

Re:VIEW の入門書はありませんか?

バグを見つけました。どうしたらよいですか?

GitHub の issue ページ https://github.com/kmuto/review/issues までお寄せください(日本語または英語)。

使い方の質問はどこに投稿するとよいですか?

GitHub の Discussions ページ https://github.com/kmuto/review/discussions があります。

Twitter で @kmuto に適切な表現でメンションいただければ、可能な範囲でお答えもできます。

プロジェクト(作業フォルダ)を作るにはどうしたらよいですか?

review-init コマンドを使います。

review-init プロジェクト名

Re:VIEW 4 以降では、review-init の実行時に TeX のレイアウトを Web ブラウザ上で設定する機能が備わっています。-w オプション付きで作成します。

review-init -w プロジェクト名

すると、デフォルトではポート 18000 を使った小さな Web サーバが起動します。Web ブラウザで http://localhost:18000 につなげてみると、紙面のレイアウトを GUI のように操作できる画面になります。

プロジェクト作成のデフォルトでは doc サブフォルダが作成され、Re:VIEW のドキュメントがコピーされますが、不要なときには --without-doc オプションを付けます。

review-init --without-doc プロジェクト名

Re:VIEW 4.1 以降では、config.yml のコメントを除去する --without-config-comment オプションがあります。

review-init --without-config-comment プロジェクト名

Re:VIEW 3 以降では、任意の Web サーバーからプロジェクトに適用する各種ファイルをダウンロードすることもできます。Web サーバー側では、zip 形式で初期プロジェクトのうち上書きあるいは新規作成したいフォルダおよびファイルをまとめておきます(アーカイブURLにはローカルファイルを指定することもできます)。

review-init -p アーカイブURL プロジェクト名

プロジェクトにどのようにコンテンツを置いたらよいですか?

review-init コマンド実行後、プロジェクトには次のようなフォルダおよびファイルが置かれます。

  • プロジェクト名と同名の「.re」拡張子付きファイル:空の初期ファイル。ここに内容を入れていく(catalog.yml を変更すれば、このファイルでなくてもよい)

  • config.yml:書名など各種メタ情報の設定ファイル

  • catalog.yml:目次構成ファイル。re ファイルを列挙して順序を決定する

  • doc:ドキュメント

  • Rakefile:rake コマンド用のルールファイル

  • libs:Rakefile ルールの実体など

  • images:画像を置くフォルダ

  • layouts:LaTeX や HTML のテンプレートレイアウト(Re:VIEW 4 以降では作成されない。必要なときには手動で作成)

  • style.css:EPUB/HTML のスタイルシート

  • sty:LaTeX のスタイルファイル

基本的なコンテンツの置き方は次のようになります。

Re:VIEW がバージョンアップしたときに設定を追従するにはどうしたらよいですか?

Re:VIEW 3 から review-update というコマンドが導入されました。このコマンドをプロジェクトフォルダ内で実行すると、config.yml や sty フォルダなどを最新バージョンに適したものに更新できます。

re ファイルを書くのに専用のエディタは必要ですか?

re ファイルは命令を含めてすべてテキストで表現されるので、UTF-8 文字エンコーディングをサポートし、プレインテキスト形式での読み込み・書き出しが可能なテキストエディタであれば OS・ソフトウェアを問わず何でも利用できます。

ただ、Re:VIEW 固有の命令を記入したり色分け表示したりといった支援モードが提供されているエディタを使ったほうが、執筆および編集には便利でしょう。

re ファイルでの執筆・編集を支援するエディタにはどのようなものがありますか?

Visual Studio Code を使ったところ、^H などのおかしな文字が入り、PDF の生成に失敗します!

Re:VIEW 側の問題ではないのですが、Visual Studio Code(VS Code)でバックスペースの文字が入ってしまうことがあるようです。設定と拡張機能によって対処する手段が示されています。

図版はどこに置くのですか? また、どのような形式に対応していますか?

図版の画像ファイルは、images フォルダに配置します。さらにサブフォルダで分けることもできます。このときの探索順序は次のようになっています。

1. images/<builder>/<chapid>/<id>.<ext>
2. images/<builder>/<chapid>-<id>.<ext>
3. images/<builder>/<id>.<ext>
4. images/<chapid>/<id>.<ext>
5. images/<chapid>-<id>.<ext>
6. images/<id>.<ext>

どの画像形式に対応するかは、使用するビルダに依存します。

  • HTMLBuilder (EPUBMaker、WEBMaker)、MARKDOWNBuilder: .png、.jpg、.jpeg、.gif、.svg

  • LATEXBuilder (PDFMaker): .ai、.eps、.pdf、.tif、.tiff、.png、.bmp、.jpg、.jpeg、.gif

  • それ以外のビルダ: .ai、.psd、.eps、.pdf、.tif、.tiff、.png、.bmp、.jpg、.jpeg、.gif、.svg

Re:VIEW 3 以降では、大文字の混ざった拡張子にも対応します。Re:VIEW 2 では「PNG」など大文字のファイル拡張子の場合はヒットしないので注意してください。

config.yml ファイルはどのような役目を持っていますか?

config.yml は、コンテンツの内容を除く、ほとんどの設定および Re:VIEW の制御を司るメタ情報ファイルです。

このプロジェクトが準拠するRe:VIEW バージョン、書名、著者名、刊行日付、見出しへの採番レベル、目次や奥付の有無、デバッグ状態遷移の有無、カバー画像、スタイルシート、LaTeX の使用スタイルなど、多くの設定があります。詳細については、展開された config.yml ファイルのコメントの説明を参照してください。代表的な設定のみを抽出した、config.yml.sample-simple もあります。

catalog.yml ファイルはどのような役目を持っていますか?

PDF(review-pdfmaker)と EPUB(review-epubmaker)、あるいは印刷版 PDF と 電子版 PDF のように出力方法によって若干異なる設定にしたいと思います。重複する内容の yml ファイルを作らずに済みませんか?

inherit を使うと、ベースの yml ファイルを読み込みつつ、設定の追加や変更ができます。

たとえば config.yml で次のようにしていたとします。

 
date: 2018-7-21
 

ここから電子 PDF 版用だけ別の日付にしたいとして、config-epdf.yml などの適当なファイル名で、inherit を使って config.yml を取り込み、設定値を上書きします。

inherit: ["config.yml"]
date: 2018-9-27

この config-epdf.yml を使うには、review-pdfmaker config-epdf.yml のように指定して実行するか、REVIEW_CONFIG_FILE 環境変数に config-epdf.yml を設定した上で rake コマンドを実行します。

REVIEW_CONFIG_FILE=config-epdf.yml rake pdf

ある設定を消したいときには、値として null を指定します。

「図」「リスト」などの一部の固定文字列は locale.yml ファイルで変えられるようですが、どのように書いたらよいですか?

日本語用にはまず locale: ja という行を入れた後、Re:VIEW の lib/erview/i18n.yml の定義を元に置き換えるものを定義します。たとえば図は image、リストは list が文字列定義名です。

locale: ja
image: 
list: リスト

EPUB に変換するにはどうしたらよいですか?

以下のようにして変換します。

rake epub
REIVIEW_CONFIG_FILE=config-epub.yml rake epub (config-ebpub.ymlから作成したいとき)

以下でも可能です(rake epub は中でこのコマンドを実行しています)。

review-epubmaker config.yml

LaTeX を使った PDF に変換するにはどうしたらよいですか?

以下のようにして変換します。

rake pdf
REIVIEW_CONFIG_FILE=config-ebook.yml rake pdf (config-ebook.ymlから作成したいとき)

以下でも可能です(rake pdf は中でこのコマンドを実行しています)。

review-pdfmaker config.yml

Web ページに変換するにはどうしたらよいですか?

以下のようにして変換します。

rake web

以下でも可能です(rake web は中でこのコマンドを実行しています)。

review-webmaker config.yml

プレインテキストに変換するにはどうしたらよいですか?

以下のようにして変換します。

rake text

以下でも可能です(rake text は中でこのコマンドを実行しています)。

review-textmaker config.yml

校正ツールにかけるなどの理由で一切装飾のないプレインテキストが必要なときには、以下のようにします。

rake plaintext

または

review-textmaker -n config.yml

Re:VIEW の命令や記法に馴染めそうもありません。Markdown で記述できませんか?

md2reviewがあります。gem としても配布されているので、以下のようにインストールできます。

gem install md2review

変換は以下のようにします。

md2review mdファイル > reファイル

命令体系が異なるため、変換結果の re ファイルの手直しは必要です。

ほかの方法として、pandoc2review があります。汎用ドキュメント変換ソフトウェアである pandoc を利用し、Markdown を含め docx などの多様なドキュメント形式から re ファイルに変換できます。

pandoc2review mdファイル > reファイル

pandoc2review のサンプルには、Re:VIEW 環境と統合することで、Markdown ファイルを原稿データとしたまま Re:VIEW 原稿と混在して利用する例も収録されています。

Markdown に変換することはできますか?

Markdown については実験的な対応をしたビルダを収録しています。rake ルールや1コマンドで全部を変換するような仕組みはないのですが、以下のようにして変換できます。

review-compile --target=markdown reファイル > mdファイル

@<code> などの頻出するインライン命令だけ Markdown 的に記述することはできませんか?

Re:VIEW では、インラインの命令は一貫した @<命令>{〜}とし、見出しや箇条書き以外の例外はこれ以上増やさないことに決めています。インライン命令の入力の煩雑さについては、エディタ支援環境に頼ったほうがよいでしょう。

それでも Markdown 的なリテラル文字でのインライン記法を使いたいときには、Compiler#text の挙動を置き換えることで一応実現できます。

以下の review-ext.rb をプロジェクトフォルダに設置すると、テキスト内のバッククォートで囲まれた範囲を @<code> 命令に内部で置換します。

module ReVIEW
  module CompilerOverride
    def text(str)
      super(str.gsub(/\`(.+?)\`/, '@<code>$\1$'))
    end
  end

  class Compiler
    prepend CompilerOverride
  end
end

これは推奨するものではなく、あくまでも実装事例です。利用および改良にあたってのヒントを提示しておきます。

  • {} ではなく $$ で囲んでいるのは、{} の文字をリテラルに使う可能性を考えたためです。リテラルな $ を含んでしまう場合は、a. || にする、b. そう使いたいものだけ @<code> を普通に使う、c. 内容を読んで {}$$|| かのどれを使うかまじめに判断するよう実装する のいずれかの対策が必要です。

  • バッククォートのエスケープは考慮していません。まじめに実装するか、途中で改行して開始終了の対応関係が存在しないように見せるかといった対策になります。

  • より Markdown っぽく複数の置換をしたくなるかもしれませんが、素朴に置換を追加すると、置換済みのものにさらに別の置換を重ねてしまうことになります。まじめに実装するには、済んだものはいったん退避しておくなどの複雑な処理が必要です。

pandoc で Re:VIEW の書式はサポートされますか?

現時点では実装の報告はありません。pandoc2review で「ほかの形式のドキュメントから Re:VIEW に変換」はできます。

Sphinx で Re:VIEW の書式はサポートされますか?

LaTeX を使いたくないのですが、ほかの PDF 作成方法はありませんか?

たとえば InDesign を使う方法と、CSS 組版を使う方法があります。

  • InDesign:IDGXML 形式に変換し、レイアウトデザイン向けに調整した上で、Adobe InDesign で半自動 DTP を行う。

  • CSS組版:EPUB に変換し、EPUB をそのまま PDF 変換する(VersaType ConverterEPUB to PDF変換ツール など)か、EPUB の HTML を結合し(Re:VIEW 3 から review-epub2html というコマンドを用意しています)、Web ブラウザ上で整形したものを PDF として保存する(Vivliostyle.js など)。後者については @at_grandpa 氏による、ひとそろいセットの Re:VIEW+CSS組版 執筆環境構築 が公開されています。

これらのいずれも困難であったり、あるいは手作業工程の DTP オペレータに引き渡すということであれば、Re:VIEW 原稿をプレインテキストに変換(rake text)して手作業でページを制作していくほうが妥当かもしれません。

表のセル区切りは、なぜ空白文字ではなく「タブ1つ」なのですか?

コード断片など、セル内で空白を文字として扱いたい場合があるからです。

Re:VIEW 4.1 以降では、table_row_separator パラメータの値で区切り文字を変更できます。

  • tabs (1文字以上のタブ文字区切り。デフォルト)

  • singletab (1文字のタブ文字区切り)

  • spaces (1文字以上のスペースまたはタブ文字の区切り)

  • verticalbar ("0個以上の空白 | 0個以上の空白"の区切り)

Re:VIEW 4.0 以前では、lib/review/builder.rb の次のメソッドで実装しているので、review-ext.rb などを使ってビルダの挙動を上書き(たとえば /\s{2,}/ など)すれば、空白文字による区切りも可能です。

    def table(lines, id = nil, caption = nil)
        …
        rows.push(line.strip.split(/\t+/).map { |s| s.sub(/\A\./, '') })

別フォルダにあるソースコードファイルの一部を原稿内に取り込みたいと思います。動的に取り込む方法はありますか?

catalog.yml での最小単位は章単位ですが、節や項に分けることはできませんか?

現時点の Re:VIEW の実装では、章よりも小さく分割した単位でファイルを扱うことはできません。

ただし、#@mapfile(ファイル名) 命令と review-preproc コマンドを使って、分割ファイルを結合することはできます。

たとえば章ファイルでは次のようにしておき、

= 章見出し
#@mapfile(section1.re)
#@end

#@mapfile(section2.re)
#@end

節の内容となる section1.re と section2.re ファイルを別に用意します。

section1.re の内容

== 節1
ABC

section2.re の内容

== 節2
DEF

この状態で rake preproc あるいは review-preproc --replace 章ファイル を実行すると、章ファイルが次のように更新されます。

= 章見出し
#@mapfile(section1.re)
== 節1
ABC
#@end

#@mapfile(section2.re)
== 節2
DEF
#@end

実行するたびに #@mapfile#@end の中身が書き換えられます。

見出しの一覧を出力することはできますか?

review-index コマンドで表示できます。

Re:VIEW に対応した日本語校正ツールはありますか?

変換途中で独自の処理を挟むことはできますか?

Re:VIEW の標準の命令処理を変えたり、新たな命令を追加したりすることはできますか?

review-ext.rb というファイルを使い、Re:VIEW のロジックを上書きできます。

索引を入れるにはどうしたらよいですか?

@<idx>@<hidx> インライン命令を使って索引を埋め込むことができます。ただし、埋め込んだ索引の抽出・整列・表示は、現時点では、LaTeX のみでの対応です。EPUB/Web ではやや無理矢理ですが対処方法を示しています(以下のリンクを参照)。

プロジェクト直下がたくさんの re ファイルだらけでごちゃごちゃしてしまいました。サブフォルダにまとめて置くことはできますか?

Re:VIEW 3.0 から、config.yml の contentdir パラメータを使って re ファイルを保持するサブフォルダを指定することができます。指定のサブフォルダに格納できるのは re ファイルのみで、画像はプロジェクトフォルダ直下にある images フォルダに入れることに変わりはありません。

UML やグラフの生成ツールから動的に生成して配置することはできますか?

//graph ブロック命令を使い、Graphviz、Gnuplot、Blockdiag、aafigure、PlantUML のソースを記述して画像を生成できます。

インライン命令内で入れ子ができません!

Re:VIEW の言語解析ロジック上、および記法の複雑化を避けるため、インライン命令は入れ子にすることはできません。

複合した結果になる新たな命令を review-ext.rb で定義する必要があるかもしれません。

インライン命令内で「}」を文字として表現したいときにはどうしたらよいですか?

\} と記述します。なお、{ のほうはインライン命令内でそのまま利用できます。

よって、たとえば {} という内容を入れたいときには、@<tt>{{\}} のようになります。

インライン命令内の最後で「\」を文字として表現したいときにはどうしたらよいですか?

インライン命令内の \ は通常そのまま文字として扱われますが、唯一、命令の末尾に入るときだけ \} という表現と区別が付けられなくなります。

  • インライン命令内の文字列が単一の \ だけであれば、\\ と表現し、@<tt>{\\} と記述できます。

  • 複数の文字からなる文字列(たとえば C:\Users\)の場合は \\ ではうまくいきません。フェンス記法を使い、@<tt>|C:\Users\| または @<tt>$C:\Users\$ とします。

@<m>命令を使って TeX 式を記述したところ、「}」がたくさん登場して都度「}」とするのが大変です。何か対策はありますか?

|| または $$ で囲む、フェンス記法があります。フェンス記法内では \} のエスケープは不要です(逆に、|| の場合は |$$ の場合は $ の文字は文字列内で使用できなくなります)。

@<m>|\frac{1}{2}| または @<m>$\frac{1}{2}$ のようになります。

ブロック命令内で「//}」を文字として表現したいときにはどうしたらよいですか?

いくぶん不格好ですが、@<embed> 命令を使って「/」を囲み、ブロックの閉じ側と判定されるのを避けるように記述するとよいでしょう。

//emlist{
この行から//emlist内の内容です
//emlist{
リスト。次の行はブロック閉じと見なされない
@<embed>{/}/}
この行まで//emlist内の内容です
//}

箇条書きを入れ子にするにはどうしたらよいですか?

ビュレット箇条書き * は、** のように深さに応じて数を増やすことで入れ子ができます。

 * 第1の項目
 ** 第1の項目のネスト
 * 第2の項目
 ** 第2の項目のネスト
 * 第3の項目

Re:VIEW 5.0 では、その他の箇条書きの入れ子や、ビュレット箇条書きの下に番号箇条書きを入れる、箇条書きの中に図表や段落を含める、といったことが //beginchild//endchild を使って表現可能です。あまり re ファイルの見た目はよくありませんが…。

 * UL1

//beginchild
#@# ここからUL1の子

UL1の続きの段落

 1. UL1-OL1

//beginchild
#@# ここからUL1-OL1の子

UL1-OL1-PARAGRAPH

 * UL1-OL1-UL1
 * UL1-OL1-UL2

//endchild
#@# ここまでUL1-OL1の子

 2. UL1-OL2

 : UL1-DL1
        UL1-DD1
 : UL1-DL2
        UL1-DD2

//endchild
#@# ここまでUL1の子

 * UL2

Re:VIEW 4 以下では、review-ext.rb での書き換えによる対策として、複雑な箇条書きの入れ子に対応する を参照してください。

Re:VIEW は夏時間に対応していますか?

Ruby ライブラリおよび OS の対応範囲での対応となります。実際のところ、Re:VIEW の実装で「現在時刻」に基づく処理が発生するのは、以下の2箇所のみです。

  • review-init 実行時に config.yml ファイルに書き出す、date: および history: のパラメータの日付の生成

  • review-epubmaker 実行時に OPF メタファイルに書き出される modified タイムスタンプの生成(バージョン 2.5 まではローカルタイム(ただし不適切な時差表記)、バージョン 3 以降は UTC)

前者は日付だけなので、OS の時刻が正しく設定されていれば夏時間は影響しません。後者は「Re:VIEW バージョン 2.5 までを使用し」「夏時間からの時刻の巻き戻しの前後で2回の EPUB ビルドをして」「その2つの EPUB をリーダー上で更新する」ときに「リーダーが modified タイムスタンプを見て更新の有無を判断する」場合に、更新がうまくいかないかもしれません。要するに、まず発生することはない、ということです。

段落を空行区切りではなく、改行をもって区切りにすることはできませんか?

Re:VIEW は空行を何らかの意味区切りとするという暗黙の想定をしており、この挙動を変更することは推奨しません。ただ、段落を判定しているのは各ビルダの paragraph メソッドなので、これを書き換えれば改行で区切りとすることは可能です。以下に LATEXBuilder の場合の挙動変更例を提示します。

module ReVIEW
  module LATEXBuilderOverride
    def paragraph(lines)
      # blank→結合→blankではなく、行ごとに前後blankを入れて段落化する
      lines.each {|line| blank; puts line; blank}
    end
  end
  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

英語の段落を記述したところ、改行のところで単語間がつながってしまいます

たとえば次のような段落を記述すると、

Hello, I
write an
article.

TeX 以外の変換出力では「Hello, Iwrite anarticle.」とつながってしまいます(TeX でできているように見えても、それは Re:VIEW ではなく TeX 側に段落判定を委ねているからに過ぎません)。

基本的に、英語段落を入れたいときには、スペースのところで改行せず、1行にまとめるようにしてください。

Hello, I write an article.

実験的な言語判定実装として、Re:VIEW 4.0 では unicode-eaw ライブラリを使った行結合を用意しました。gem install unicode-eaw で gem をインストールした上で、config.yml に join_lines_by_lang: true のパラメータを追加してみてください。

ファイル名やラベルに避けたほうがよい文字はありますか?

Re:VIEW のシステム自体は OS が許容する範囲での文字をおおむね利用できますが、特に TeX に変換した場合には空白文字や一部の記号文字の利用で奇妙な症状あるいはエラーになることがあります。

トラブルを避けるため、ファイル名やラベル名は半角英字アルファベット(a〜z、A〜Z)、数字(0〜9)、あとは_.-+という程度に留めておくことを推奨します。

Re:VIEW 5.0 以降では、TeX または EPUB で問題になる可能性がある ID 文字列に警告が表示されます。

後注を作ることはできますか

Re:VIEW 5.3 以降では、通常の脚注のほかに章の末尾に注釈を配置する後注の機能が追加されています。

//endnote 命令で後注内容を記述し、@<endnote> 命令で後注を参照します。実際に後注一覧を配置する箇所には、//printendnotes 命令を使います。

 …
ビルダはRe:VIEW形式の原稿ファイルを「HTML」や「LaTeX」などに変換する変換器のことです@<endnote>{builder}。

//endnote[builder][HTML, LaTeX, TOP, IDGXMLを主要なビルダとしています。]

==== 注
//printendnotes

//printendnotes は同一 re ファイル内に記述する必要があります。つまり、章単位で後注を出力することはできますが、書籍全体で最後に1つの後注を出力する、ということはできません。

また、後注は一覧を出力するのみで見出しは付けないので、上記の例のように必要に応じて見出し、あるいは //blankline などで空行を入れる、といった表現をとることになります。

Ruby 3.1 でエラーが発生するようになりました

Ruby 3.1 で YAML ライブラリ (Psych) が変更されたことにより、Re:VIEW 5.3.0 以前ではエラーが発生するようになりました。

Re:VIEW 5.4.0 以降では修正済みです。

Ruby 3.1 以上でかつ Re:VIEW 5.3.0 以下でどうしても利用する必要があるときには、下記の差分を参考に Re:VIEW のプログラムを変更してください。

Re:VIEW は Log4j のセキュリティ侵害の影響を受けますか?

Re:VIEW 自体は Apache Log4j を利用していません。

Re:VIEW のセキュリティは堅牢ですか?

Re:VIEW はユーザー自身がシェル権限を保有して操作・実行することを想定しており、ユーザーの権限で可能なことはすべて実行可能です。LaTeX などの外部ツールとの連携のほか、preproc、フック、レイアウト erb、//graph など、利便性のためにコンパイル実行時に任意のシェルコマンドを注入できるものが多くあり、これらを塞ぐのは実用性を損ねるだけで非現実的です。

信頼できない第三者に Re:VIEW のコンパイル環境を提供する(CI など)場合は、重要なシステム上に直接構築せず、Docker などを使ってコンテナ化・揮発化する環境で提供し、CPU やメモリ・ネットワークなどのリソースも制限するようにしたほうがよいでしょう。第三者にシェル権限やリポジトリを提供している状況下においては、Re:VIEW のセキュリティは脆弱と言えます(そのような状況ではすでに Re:VIEW に限りませんが)。

ただ Re:VIEW 自体がネットワークを利用するのは、review-init --wizard で初期設定ウィザードモードを起動しているときのみなので、Re:VIEW をローカルで使用している範囲において外部からの攻撃に使われる可能性は極めて低いでしょう。

コラム内で見出しを入れたところ、地の文の続きで採番されてしまいます

コラム内で採番レベル範囲(config.yml の secnolevel)の見出しを使うと、地の文からの継続で採番されてしまいます。コラム内で見出しを使いたいときには、採番レベルよりも大きなレベルの見出し(たとえば secnolevel が 3 であれば、=========)を使うことを推奨します。

書籍の都合上どうしても採番レベルが大きくなければならず、かつコラム内見出しも必要となる場合は、場当たり的ではありますが、対処としては採番を付けない nonum 見出しを利用し、かつすぐにその nonum 見出しを閉じることで、採番のない見出しをコラム内に含めることができます。

===[column] コラム見出し

〜

====[nonum] コラム小見出し
====[/nonum]

〜

===[/column]

FAQ - Re:VIEW の使い方について(TeX PDF)

FAQ(よくある質問と回答)のこのセクションは、Re:VIEW の使用方法のうち、TeX を使った PDF 生成に関係する事柄をまとめています。


TeX 環境の構築はどうしたらよいですか?

LaTeX を使った PDF に変換するにはどうしたらよいですか?

プロジェクトフォルダで rake pdf を実行するか、review-pdfmaker config.yml を実行します。

LaTeX 実行時でのエラーが出ましたが、どのように調べたらよいですか?

LaTeX のコンパイル実行でエラーが生じると、エラーが発生した箇所と行番号が表示されます(エラー時の出力はかなり長くなることがあり、結果をシェルのリダイレクトなどで保存したほうがよいかもしれません)。

デフォルトでは Re:VIEW の re ファイルから LaTeX テキストしたファイルは一時フォルダに置かれており、いちいちこれを参照するのは不便です。

config.yml で

debug: true

とすると、デバッグモードとなり、一時フォルダの代わりにプロジェクトフォルダ内に「book-pdf」(book の部分は bookname の値に依存)のようなフォルダが作られます。このフォルダは実行後も消去されないので、ここから LaTeX テキストファイルを開き、エラーの行を参照して解析できます。

また、review-pdfmaker --debug config.yml のように --debug オプションを付けるとconfig.yml の設定に関わらず一時的にデバッグモードになります。

LaTeX のエラーの意味がわかりません。

LaTeX でエラーが発生したときには、「!」から始まるエラーメッセージが表示されています(デバッグモードにして実行し、__REVIEW_BOOK__.log または book.log を参照するのもよいでしょう)。 TeX Wikiの「エラーに遭遇したときは」には、代表的な TeX および LaTeX のエラーについて列挙されています。

エラーによっては、示された行でなく、その前の行に問題があることがあります。

コラムなどの囲み要素では、フロートの図表(//image//table)に制約があります。Re:VIEW 3 以上のレイアウトでは対策していますが、古いレイアウトおよびサードパーティレイアウトでは対応していないことがあります。

Re:VIEW に起因する問題と思われる場合は issue で報告してください。サードパーティのレイアウトテンプレートを使用している場合にはそのサードパーティに連絡してください。

LaTeX の紙面サイズを変更するにはどうしたらよいですか?

Re:VIEW 3 からは、ドキュメントクラスオプションの paper で紙面サイズを指定可能です。

texdocumentclass: ["review-jsbook", "media=print,paper=a5"]

a5 の部分を b5 などに書き換えれば変更されます。

Re:VIEW 2 以前で jsbook ベースのレイアウトを使っている場合は、config.yml の texdocumentclass パラメータに対するオプションで指定できます(正確には、これがドキュメントクラスに直接渡されます)。

デフォルトは以下のようになっています。

texdocumentclass: ["jsbook", "uplatex,twoside"]

これを A5 にするには次のようにします。

texdocumentclass: ["jsbook", "uplatex,twoside,a5j"]

jsbook において文字列で指定可能な紙サイズを以下に示します。

  • a3paper:A3(297mm x 420mm)

  • a4paper または a4j:A4(210mm x 297mm)、デフォルト

  • a5paper または a5j:A5(148mm x 210mm)

  • a6paper:A6(105mm x 148mm)

  • b4paper または b4j:B4(257mm x 364mm)

  • b5paper:B5(182mm x 257mm)

  • b6paper:B6(128mm x 182mm)

  • a4var:A4変の一例(210mm x 283mm)

  • b5var:B5変の一例(182mm x 230mm)

  • letterpaper:レター(8.5in x 11in)

  • legalpaper:リーガル(8.5in x 14in)

  • executivepaper:エグゼクティブ(7.25in x 10.5in)

sty/reviewmacro.sty に mm などの単位で数値を明示することもできます。

\setlength\paperwidth{幅truemm}
\setlength\paperheight{高さtruemm}

LaTeX の紙面レイアウトに満足がいきません。どうやったら置き換えられますか?

標準で提供されているものを変えるには LaTeX および TeX の知識が必要となります。また、場当たりな修正は後々問題になる可能性があります。本当にそのレイアウト調整がすべきことなのかどうかをまず検討したほうがよいでしょう。レイアウトに細かなこだわりを入れたいときには、わざわざ Re:VIEW を経由するよりも、コンテンツを LaTeX 記法で記述し、レイアウト指示もそれに含めるほうが妥当です。

LaTeX はマクロの集合体です。Re:VIEW から読み込まれるカスタムスタイルファイル sty/review-custom.sty(Re:VIEW 3 系以上)または sty/reviewmacro.sty(Re:VIEW 2 以前)にマクロを記述することで、それまでに定義されたマクロを上書きできます。

LaTeX の紙面レイアウトとして他のテンプレートはありますか?

デフォルトのもの以外に広く使われているものとして、TechBooster 提供のテンプレートがあります (Re:VIEW 5 に対応しています)。

紙面の余白の調整をするにはどうしたらよいですか?

紙面の内容部(版面)の四方の余白は、版面の横幅・縦幅と、紙面の上からの版面の位置・綴じ側からの位置によって決まります。

そのため、余白をうまく合わせるには、「本文の文字サイズ・行送り・行あたりの文字数・行数」で版面の縦幅・横幅を決めた上で、上(天)・綴じ側(ノド)を調整する、というステップになります(パラメータについては上記のリンク先を参照)。

この調整は少々試行錯誤が必要ですが、Re:VIEW 4 から Web ブラウザ上で設定する機能を review-init に追加しています。プロジェクトを新規に作成する際に、以下のように -w オプションを付けて review-init を実行します。

review-init -w プロジェクト名

すると、デフォルトではポート 18000 を使った小さな Web サーバが起動します。Web ブラウザで http://localhost:18000 につなげてみると、紙面のレイアウトを GUI のように操作できる画面になります。

_images/wizard.pngウィザードモード

残念ながら現時点では既存のプロジェクトを再設定する機能は用意していません。何か新しいプロジェクトを作成して、その texdocumentclass パラメータをコピーする、という方法で対処してください。

LuaTeX-ja を使うにはどうしたらよいですか?

Re:VIEW 3 以上で LuaTeX への対応を進めています。ただし、現状では LuaTeX を使うユーザーが LaTeX についての十分な知識を持っており、問題を自己解決できるだけの能力があることを前提としています。

  1. テンプレートに review-jlreq など LuaTeX に対応しているものを選ぶ。

  2. texcommand パラメータを変更する。texcommand: "lualatex"

  3. dvicommand パラメータを null にする(dvicommand: null)。これは特に重要です。単にコメントアウトするだけでは、デフォルトの upLaTeX 用の dvicommand パラメータ値が有効になってしまいます。

トンボを付けるにはどうしたらよいですか?

Re:VIEW 3 以降ではデフォルト(media=print のとき)でトンボが付きます。Re:VIEW 2 以前の場合は下記を参照してください。

入稿先に PDF/X-1a 形式か PDF/X-4 形式にするよう求められました。どうしたらよいですか?

PDF/X-1a、PDF/X-4 は印刷用 PDF として準拠の求められることの多い標準規格です。安全に印刷するための基準なので、遵守することが望まれます。十分に実績のある、以下のような有償ソフトウェアを利用して変換することを推奨します。

このほかに、Vibrant というプラットフォームの press-ready というツールで、フリーソフトウェア (Ghostscript) を通した PDF/X-1a の変換が実装されており、Acrobat での検証も通過する PDF/X-1a ファイルができています。

全体をグレースケールにするにはどうしたらよいですか?

LaTeX 自体(および upLaTeX からの PDF 生成に使われる dvipdfmx)にはグレースケール化の機能はありません。

一般には Acrobat または pdfToolbox を使ってグレースケール化します。ただし、Acrobat はグレースケール化によって線の太さが変わったり点線が実践になることがある問題があります。

LaTeX セットにも関連付けてインストールされるフリーソフトウェア Ghostscript を使って PDF をグレースケール化することは可能です。

gs -q -r600 -dNOPAUSE -sDEVICE=pdfwrite -o 出力PDF名 -dPDFSETTINGS=/prepress -dOverrideICC -sProcessColorModel=DeviceGray -sColorConversionStrategy=Gray -sColorConversionStrategyForImage=Gray -dGrayImageResolution=600 -dMonoImageResolution=600 -dColorImageResolution=600 入力PDF名

ただし、Ghostscript も PDF によっては内容を壊す(文字の欠落や順序の変化)ことがあります。変換後は必ず全体を照合するようにしましょう。

コンパイルや PDF 生成処理の途中に割り込むにはどうしたらよいですか?

等幅の長い文字を入れると文字の間がスカスカになってしまいます。途中で折り返させるにはどうしたらよいですか?

ページの途中で強制的に改ページするにはどうしたらよいですか?

あるページの版面を少しだけ伸ばすにはどうしたらよいですか?

@<tt>@<code> の等幅の箇所が段落からはみ出てしまいます。途中で折り返させるにはどうしたらよいですか?

Re:VIEW 4.0 から以下の自動折り返しの機能を標準で採用しています。

見栄えが悪い箇所を「少しだけ」調整する で提示しているように、\allowbreak または \linebreak マクロを @<embed> 命令を使って埋め込むことを推奨します。

どうしても「自動で折り返し」をしたいときには、次のようなマクロを sty/review-custom.sty に追加することで、\reviewtt 等の挙動を変えて分割可能です。

\makeatletter
\newif\ifreview@ba@break
\def\review@ba@end{\review@ba@end@}
\DeclareRobustCommand{\reviewbreakall}[1]{%
  \begingroup
    \review@ba@breakfalse
    \review@break@all@a#1\review@ba@end
  \endgroup
}
\def\review@break@all@a{%
  \futurelet\review@ba@tok\review@break@all@b
}
\def\review@break@all@b{%
  \ifx\review@ba@tok\review@ba@end
    \let\next\@gobble
  \else\ifx\review@ba@tok\@sptoken
    \let\next\review@break@all@c
  \else\ifx\review@ba@tok~%
    \let\next\review@break@all@d
  \else\ifx\review@ba@tok\bgroup
    \let\next\review@break@all@e
  \else
    \let\next\review@break@all@f
  \fi\fi\fi\fi
  \next
}
\expandafter\def\expandafter\review@break@all@c\space{%
  \space
  \review@ba@breakfalse
  \review@break@all@a
}
\def\review@break@all@d#1{%
  \review@break@all@f{\mbox{\space}}%
}
\def\review@break@all@e#1{%
  \review@break@all@f{{#1}}%
}
\def\review@break@all@f#1{%
  \ifreview@ba@break
    \hskip0pt plus 0.02em\relax
  \fi
  #1%
  \review@ba@breaktrue
  \review@break@all@a
}

\DeclareRobustCommand{\reviewtt}[1]{{\ttfamily\reviewbreakall{#1}}}
\DeclareRobustCommand{\reviewcode}[1]{{\ttfamily\reviewbreakall{#1}}}
\DeclareRobustCommand{\reviewtti}[1]{{\ttfamily\itshape\reviewbreakall{#1}}}
\DeclareRobustCommand{\reviewttb}[1]{{\ttfamily\bfseries\reviewbreakall{#1}}}
\makeatother

表のセルなどで、スペースや-を含まない長い英数字の箇所が折り返されません

基本的には上記のFAQと同様で、見栄えが悪い箇所を「少しだけ」調整する で提示しているように、\allowbreak または \linebreak マクロを @<embed> 命令を使って埋め込むことを推奨します。

また、Re:VIEW で定義済みの \reviewbreakall 命令を流用し、たとえば @<code> の箇所を等幅タイプライタ書体にせず、地の書体のまま任意折り返し許容にするという方法があります(このときはタイプライタ書体にしたいところは @<tt> を使うようにしましょう)。sty/review-custom.sty には以下のように定義します。

\DeclareRobustCommand{\reviewcode}[1]{\reviewbreakall{#1}}

複数のスペース文字を入れても、1つになってしまいます。どうしたらよいですか?

どうしてもリテラルなスペースを入れたいときには、以下のようにして埋め込みます。

3つのスペースを@<embed>{|latex|~~~}@<embed>{|html|&nbsp;&nbsp;&nbsp;}と入れる

PREDEF、POSTDEF で割り当てたファイルで図表を使うと、おかしな番号の振り方になります。

jsbook ベースのテンプレートで、ページを頭からの通し番号にするにはどうしたらよいですか?

Re:VIEW 3 以降では、serial_pagination=true ドキュメントクラスオプションで通し番号になります。

Re:VIEW 2 以前の場合、jsbook.cls では以下の2箇所で暗黙にページ番号を変えているため、マクロを上書きする必要があります。

  • titlepage(大扉などで利用)でページ番号を0にリセット

  • 前付(frontmatter)でローマ数字、本文(mainmatter)でアラビア数字化。それぞれ pagenumbering マクロを使用しており、このマクロで番号は0にリセットされる

単純に頭からの通し番号にするには、sty/reviewmacro.styに次のように書いて jsbook.cls のマクロを上書きします。

\renewenvironment{titlepage}{%
    \cleardoublepage
    \if@twocolumn
      \@restonecoltrue\onecolumn
    \else
      \@restonecolfalse\newpage
    \fi
    \thispagestyle{empty}%
%    \setcounter{page}\@ne% リセットを無効化
  }%
  {\if@restonecol\twocolumn \else \newpage \fi
    \if@twoside\else
%      \setcounter{page}\@ne% リセットを無効化
    \fi}
\renewcommand\pagenumbering[1]{% デフォルトのアラビア文字のみとして何もしない
}

開始ページ番号を変えるにはどうしたらよいですか?

Re:VIEW 3 以降では、ドキュメントクラスオプション startpage=開始ページ番号 で大扉の開始ページ番号を指定できます。

目次を付けるにはどうしたらよいですか?

config.yml の toc パラメータを true にします。

toc: true

または

pdfmaker:
  toc: true

目次が奇数ページ始まりになってしまいます

jsbook ベースのクラスの場合、目次は「章」のデザインの流用になっています。そのため、章が奇数ページから始まるのと同様の挙動になります。

よって、章が奇数ページ始まりになっていますが偶数ページからも始まるようにしたいです と同様、ドキュメントクラスオプションに openany を付けることでどちらのページからでも目次を始められます。

texdocumentclass: ["review-jsbook", "media=print,paper=a5,openany"]

目次などでリンクに色や囲みが付きます。装飾なしの黒にできませんか?

Re:VIEW 2 系のデフォルトのスタイルなどでは、この状況になります(Re:VIEW 3 以降ではデフォルトでリンクに色や囲みを使わないようにしています)。

sty/reviewmacro.sty に以下のように追加することで、リンクを表す表現を取り下げます。

\hypersetup{hidelinks}

//image 等で貼り付けた図版が版面幅いっぱいになってしまいます

デフォルトでは //image//indepimage//imgtable で指定した図版は縦横比を保った上で版面いっぱいにサイズが拡縮されます(TeX 変換結果は \reviewincludegraphics[width=\maxwidth])。

各ブロック命令のメトリックスの値により、版面に対する比率を指定できるようになっています。

//image[ID][キャプション][メトリックス]
//indepimage[ID][キャプション][メトリックス]
//imgtable[ID][キャプション][メトリックス]

たとえばこのメトリックスに scale=0.5 を指定すると、版面幅に対して 50% になります(TeX 変換結果は \reviewincludegraphics[width=0.5\maxwidth])。

この scale 値を版面に対してではなく図版の実寸からの拡縮にしたいときには、cofnig.yml の image_scale2width オプションを true にします(TeX 変換結果は \reviewincludegraphics[scale=0.5])。

各図版を正確な原寸で作成している場合には、拡縮自体が余計な処理と言えます。この場合、フックあるいは review-ext.rb を利用して width=\maxwidth を変換結果から削除する必要があるでしょう。

Re:VIEW 4.1 以降では、pdfmaker セクション下に use_original_image_size というパラメータが追加されました。 このパラメータの値を true にすると、拡縮なしで原寸のまま配置するようになります。また、Re:VIEW 4.1 以降では image_scale2width オプションは pdfmaker セクション下に移動しています。

表紙を全面に貼り付けるにはどうしたらよいですか?

Re:VIEW 3 以降ではデフォルトで全面貼り付けになっています。

Re:VIEW 2 系では全面に貼り付ける命令をまだ用意していないため、命令の追加および表紙部分の LaTeX ソースを置き換えることで対処します。

表紙の画像ファイルを用意しておきます(実寸・PDF 形式を推奨します)。ここでは images/cover.pdf に入れておくとします。

全面貼り付けを提供する LaTeX マクロを sty/reviewmacro.sty に追加します。

\newcommand*\includecover[2][]{%
 \clearpage
 \thispagestyle{empty}%
\vbox to \textheight{%
  \vskip-\dimexpr\headheight + 1in\relax%
  \vbox to \paperheight{\vss%
    \hbox to \textwidth{%
      \hskip-\dimexpr\oddsidemargin + 1in\relax%
      \hbox to \paperwidth{\hss
        \includegraphics[#1]{#2}%
        \hss}%
    \hss}%
  \vss}%
\vss}%
}

表紙部分を差し替える LaTeX 断片ファイルを作成します。ここでは cover.tex という名前でプロジェクトフォルダに置いておくことにします。

\includecover[width=\paperwidth,height=\paperheight]{images/cover.pdf}

この cover.tex を使うよう、config.yml を設定します。

pdfmaker:
  cover: cover.tex

これで、表紙が全面貼り付けになります。定義したマクロ自体は、re ファイル内でも embed 命令を使って普通の紙面内に使うことができます。

//embed[latex]{
\includecover{images/sashie.pdf}
//}

挿絵を全面に入れるにはどうしたらよいですか?

Re:VIEW 3 以降の場合、\includefullpagegraphics 命令を利用できます。

//embed[latex]{
\includefullpagegraphics{images/sashie.pdf}
//}

画像ファイルは実寸で、中央合わせで配置されます。塗り足し領域がある場合にはそれを含めたサイズで用意します。

Re:VIEW 2 の場合は上記の \includecover を使ってみるとよいでしょう。

Illustrator AI ファイルを配置したところ、何かおかしいです

厳密には、TeX(というよりは dvi ウェア)は Illustrator のネイティブ形式である AI ファイルをサポートしているというわけではなく、「PDF 互換ファイル」オプション付きで保存された AI ファイルの PDF 部分を使用しています。このオプションなしで保存されている AI ファイルは表示できないので、Illustrator でオプションを有効にして再保存する必要があります。

また、Illustrator 上でレイヤーをオフにして非表示にしていても、TeX に貼り付けた場合には表示されてしまうため、事前に表示不要なレイヤーを削除しておく必要があります。

Re:VIEW 3 で表紙が表示されません

texdocumentclass パラメータで review-jsbook (デフォルト) または review-jlreq を使っており、media=print が指定されている(または media= パラメータ自体指定されていない)場合には、表紙は PDF には入りません。

これは、紙書籍を印刷する場合、表紙は一般に本文 PDF とはまったく別の納品をするからです(通常、表紙+背+裏表紙を1枚にした PDF がそれに相当します)。

  • 電子版書籍 PDF に適した形にする media=ebook にすると、表紙が PDF の先頭に差し込まれます。

  • media=print でも、さらに cover=true パラメータを追加すると、表紙を差し込むことができます。

電子版用の表紙の画像を指定しましたが、はみ出してしまいます(あるいは小さすぎてフチができてしまいます)

デフォルトで、表紙画像は「実寸」で中央合わせで貼り付けられます。正確に指定どおりの大きさで貼り付けることが印刷では重要なので Re:VIEW のデフォルトはこのような仕様にしていますが、「用意した画像ファイルを紙面サイズに拡縮して貼り込みたい」というカジュアルな用途には不向きです。

Re:VIEW 5.0 では texdocumentclass のパラメータとして、cover_fit_page=true オプションを導入しています。このオプションを付けると、サイズに関わらず仕上がりサイズに拡縮します。なお、塗り足し領域までは拡大しないので、印刷用にするには必ず実寸で正しく作成するようにしてください。

類似のことを Re:VIEW 4 以下で行うには、sty/review-custom.sty に以下のように指定します。

% 拡縮し、紙サイズに合わせて貼り付け
\def\review@coverimageoption{width=\paperwidth,height=\paperheight}
% 縦横比を変えたくない(ずれた部分は白くなる)場合は以下を利用
%\def\review@coverimageoption{width=\paperwidth,height=\paperheight,keepaspectratio}

media=print で塗り足し領域まで拡大したい場合には、以下のように塗り足し幅×2のサイズ=通常は6mmを追加します(とはいえ、上記のように紙の書籍印刷用で表紙を PDF に含めることは通常ないはずです)。

% 拡縮し、紙サイズに合わせて貼り付け。塗り足しぶんも含める
\def\review@coverimageoption{width=\dimexpr\paperwidth+6mm,height=\dimexpr\paperheight+6mm}

裏表紙を入れるにはどうしたらよいですか?

裏表紙を含めたいときには、backcover パラメータに TeX 断片ファイルのファイル名を指定します。たとえば以下のような backcover.tex ファイルを作成し、プロジェクトフォルダに配置します。

% imagesフォルダのcover-hyo4.pdfファイルを裏表紙とする
\includefullpagegraphics{images/cover-hyo4.pdf}

これを PDF に含めるように config.yml で設定します。

 …
pdfmaker:
  backcover: backcover.tex
  …

Photoshop psd ファイルを配置できません

2020年10月時点では、Photoshop のネイティブ形式である psd ファイルは TeX の dvipdfmx ではサポートされていません。

ただし、graphicxpsd パッケージを使うと、sips(macOS のツール)または covert(ImageMagick)を使用して、コンパイル時に psd ファイルを PDF に変換して利用できます。graphicxpsd パッケージは TeXLive 2017 以降に収録されているほか、tlmgr install graphicxpsd でインストールすることもできます。

sty/review-custom.sty でスタイルファイルを読み込むよう設定します。

\usepackage{graphicxpsd}

外部コマンド実行を許容するため、config.yml の texoptions に --shell-escape を追加します。

texoptions: "-interaction=nonstopmode -file-line-error --shell-escape"

隠しノンブルを入れるにはどうしたらよいですか?

同人誌印刷では、全ページにページ番号を入れることを求められ、ノドに小さくページ番号を入れる「隠しノンブル」という手法が推奨されることがあるようです。

Re:VIEW 3 以降では、ドキュメントクラスオプション hiddenfolio=プリセット名 を使い、隠しノンブルを指定できます。

詳細については Re:VIEW 3からのLaTeX処理 の「ページ番号に関する調整」を参照してください。

コラム内に image や table を置くとエラーになります

コラムのような囲み内で「フロート」の図表を使うと、TeX のコンパイルエラーになります。Re:VIEW 3 では次のように「必ず指定箇所に置く(H)」を図表に指定することで、エラーを回避できます。Re:VIEW 4 以降ではこれがデフォルトです。

\floatplacement{figure}{H}
\floatplacement{table}{H}

表内で @<br> を使ったときの見た目がよくありません

Re:VIEW 3.0 以降で解消しているはずです(#1207)。

奥付を必ず偶数ページにするにはどうしたらよいですか?

Re:VIEW 3 以降では、\reviewcolophon マクロを変更します。デフォルトは単なる \clearpage(改ページ)なので、偶数になるように改ページする \clearoddpage に置き換えます。これには、sty/review-custom.sty に次のように追加します。

\renewcommand{\reviewcolophon}[0]{\clearoddpage}

この設定で POSTDEF が空の場合、CHAPS または APPENDIX の章の最後が白ページだと、白ページが連続します。これは \backmatter マクロ内で改ページが行われていることが原因なので、\backmatter の呼び出し元の \reviewbackmatterhook を空にするよう sty/review-custom.sty に次のように追加します。

\def\reviewbackmatterhook{}

章が奇数ページ始まりになっていますが偶数ページからも始まるようにしたいです

ドキュメントクラスオプションに openany を付けます。

texdocumentclass: ["review-jsbook", "media=print,paper=a5,openany"]

日本語フォントが埋め込まれません

TeXLive の場合、kanji-config-updmap-sys コマンドで妥当なフォントのマップファイルを指定すれば、埋め込まれます。W32TeX の場合は下記を参照してください。

Windowsでcould not locate a virtual/phisical font for TFM "uphgothr-h" のようなエラーになります

Windows で TeXLive ではなく、W32TeX を使っている場合、デフォルトの日本語フォント設定がヒラギノフォントを参照するようになっています(厳密には W32TeX では otf パッケージ利用時の設定にヒラギノフォントが参照されています)。W32TeX には TeXLive の kanji-config-updmap-sys コマンド相当がないため、config.yml に以下のようにマップファイルを直接設定します(ここでは MS 明朝・ゴシックを割り当てています)。

dvioptions: "-d 5 -z 9 -f msmingoth.map"

行頭の#を外すのを忘れないようにしてください。

  • システムのデフォルトにする方法としては、W32TeX の dvipdfmx.cfg の末尾に「f msmingoth.map」という行を加えます。

  • W32TeX で提供されるマップファイル:hiragino.map, hiraginopron.map, hiraginopron04.map, ipa.map, ipaex.map, kozuka.map, kozukapr6n.map, kozukapr6n04.map, morisawa.map, morisawapr6n.map, morisawapr6n04.map, msmingoth.map, noembed.map, noembed04.map, yu-win10.map, yu.map

システムにインストールされているのにフォントがないと言われます

利用するフォントは「TeX のファイル管理システム」から見えている必要があります。OS やほかのアプリケーションでは見えている、だけではダメなことに注意してください。

kpsewhich フォントファイル名(たとえば kpsewhich HiraMinPro-W3.otf)で返ってこなかったら、そのフォントは TeX からまだ使えません。kpsewhich -show-path="opentype fonts" で表示されるパスのいずれかにフォントを移動・あるいはリンクした後、mktexlsr コマンドでファイルデータベースを更新します。

各書体を変えるにはどうしたらよいですか?

PDF の作成に時間がかかります

よほど遅いプロセッサや少ないメモリでない限り、Re:VIEW 原稿から TeX 形式への変換、TeX コンパイルおよび PDF の生成には時間はあまりかからないはずです。サンプルドキュメントやプロジェクトの初期での PDF 作成時間に比して明らかに遅くなっているという場合、原因としては次のようなことが考えられます。

  • eps ファイルの画像が使われている。eps ファイルは内部で Ghostscript により都度 PDF に変換されるので、時間がかかる要因になります。速度および管理の観点で PDF で統一しておくことを推奨します。

  • 画像が多い。TeX が生成する dvi ファイルを PDF に変換する dvipdfmx の圧縮で時間がかかっている可能性があります。config.yml の dvioptions パラメータの -z に付ける数を小さくしていくと、圧縮の計算作業が減り、より速く結果を得られるようになります(そのぶんファイルサイズは大きくなります)。執筆中で画像の確認は後回しでよいなら、config.yml の texdocumentclass パラメータのドキュメントクラスオプションに draft を付けて試してみるとよいかもしれません。このオプションを付けると、画像の領域は仮のボックスで代替されます。

  • re ファイル上での相互参照が多い。現状の Re:VIEW の実装では、相互参照が指定されていたときにやや力まかせな方法で都度探索しています。re ファイルから TeX ファイルへの変換に時間がかかる可能性はありますが、TeX のコンパイル時間には関係ありません。

  • review-ext.rb で時間のかかる処理を加えている。

  • LuaLaTeX を使っている (これは速度面は理解の上で使われていると思いますが)。upLaTeX に比べると、だいぶ高速化してきたとはいえ LuaLaTeX は時間がかなりかかります。

review-jsbook において、ページ番号を下部中央に配置するには、どうしたらよいですか?

review-jsbook では fancyhdr パッケージの機能を利用してヘッダおよびページ番号を設定しています。sty/review-style.sty で設定されているデフォルトでは、左側のページ(横書きにおいて偶数)の場合は左下、右側のページ(横書きにおいて奇数)の場合は右下に配置されます。

下部中央に変更するには、sty/review-custom.sty にたとえば以下のように記述します。

% ページ番号配置を下部中央にする
\fancyfoot{}% 既存の設定をキャンセル
\cfoot{\thepage}% 下部中央に配置

\fancypagestyle{plainhead}{% 章扉も変更
  \fancyfoot{}% 既存の設定をキャンセル
  \cfoot{\thepage}% 下部中央に配置
  \fancyhead{}% 以下はオリジナルのreview-styleと同じ
  \renewcommand{\headrulewidth}{0pt}%
  \renewcommand{\footrulewidth}{0pt}}

review-jlreq では fancyhdr ではなく jlreq クラス自体の機能を利用しているので、設定は異なります。review-style.sty の「ヘッダスタイル」の記述および jlreq クラスのドキュメントを参照してください。

review-jsbook において、章名を左ページ、節名を右ページに配置するには、どうしたらよいですか?

review-jsbook では fancyhdr パッケージの機能を利用してヘッダおよびページ番号を設定しています。sty/review-style.sty で設定されているデフォルトでは、ヘッダ行に章名と節名の両方が配置されます。

希望の形に変更するには、sty/review-custom.sty にたとえば以下のように記述します。

% ヘッダをページによって切り替える
\fancyhead{}% 既存の設定をキャンセル
\fancyhead[LE]{\gtfamily\sffamily\bfseries\upshape \leftmark}% 左ページなら左側の見出し情報(一般に章名)
\fancyhead[RO]{\gtfamily\sffamily\bfseries\upshape \rightmark}% 右ページなら右側の見出し情報(一般に節名)

review-jlreq では fancyhdr ではなく jlreq クラス自体の機能を利用しているので、設定は異なります。review-style.sty の「ヘッダスタイル」の記述および jlreq クラスのドキュメントを参照してください。

行番号付きリストが長いときの折り返しはどう表現したらよいですか?

コラムの脚注をどこに置いたらよいですか?

簡単に言えば、コラムを閉じたあと(====[/column])に置くのが適切です。

====[column] …
…@<fn>{column-footnote}…

====[/column]

//footnote[column-footnote][…]

LaTeX のモデルにおいて、脚注はやや特殊な扱いを受け、単純には利用できない箇所があります。そのため、Re:VIEW 3 以降では、キャプション・表・コラム の中に脚注参照があったときには、LaTeX の通常の \footnote マクロではなく、\footnotemark+\footnotetext マクロとなるようにしています。

\footnotemark は脚注の採番をして参照記号を打つマクロ、\footnotetext は脚注テキストをその位置のページに配置するマクロです。

LaTeX 上でのコラム環境の中に脚注テキストを置いてしまうと、結局コラム環境の制約を受けてしまい、脚注をうまく処理できません。そのため、コラムを閉じたあとに //footnote 命令を置くことで回避する必要があります。

@<fn> の行よりも前に //footnote を置くと、評価順の都合で脚注が消失するので注意してください。

「コラムがページをまたぐときに、前側のページに脚注を配置する」ためには、たとえばフックを使って該当の \footnotetext 行をコラムの前に移動し、カウンタを調整する、といったように生成 TeX ソースファイルを加工する必要があります。

…
\stepcounter{footnote}% 脚注カウンタを+1
\footnotetext{…コラム内脚注…}

\begin{reviewcolumn}
…

% コラム前側の脚注参照。カウンタを-1し、参照配置
…\addtocounter{footnote}{-1}\footnotemark{}…
…

見出しに脚注を入れると、目次や柱にも番号が入り、カウントもされてしまいます

LaTeX では基本的に見出しに脚注を置くことが望ましくないため、Re:VIEW では見出しについても上記のとおり \footnotemark による対応をしています。副作用として、そのままだと目次や柱にもこの内容が使われてしまうために、脚注記号が入る上にどんどんカウントが増えてしまうということになります。

回避策は、フックスクリプトを使って LaTeX ソースの該当箇所の見出し部分を書き換え、見出しマクロに目次・柱用の別の「安全な」テキストをオプションとして指定することです。

\chapter{見出し}
\section{見出し}
\subsection{見出し}
\subsubsection{見出し}

 ↓

\chapter[目次や柱用で使われるもの]{該当ページで実際に出力するもの}
\section[目次や柱用で使われるもの]{該当ページで実際に出力するもの}
\subsection[目次や柱用で使われるもの]{該当ページで実際に出力するもの}
\subsubsection[目次や柱用で使われるもの]{該当ページで実際に出力するもの}

たとえば変換された ch01.tex において

\chapter{こんにちは世界\protect\\footnotemark{}}
\label{chap:ch01}
\footnotetext[1]{Hello, World.}
 …

となっていたとします。上記URLの手順で、フックスクリプトでこの箇所だけ書き換えます。

#!/usr/bin/env ruby
File.open("#{ARGV[0]}/ch1.tex", 'r+') do |f|
  s = f.read.sub('\chapter{こんにちは世界',
                 '\chapter[こんにちは世界]{こんにちは世界')
  f.rewind
  f.print s
end

結果は以下のようになり、目次や柱で安全になります。

\chapter[こんにちは世界]{こんにちは世界\protect\\footnotemark{}}
\label{chap:ch01}
\footnotetext[1]{Hello, World.}

長い脚注がページで分かれてしまいます

review-custom.sty に次のように記述することで、分かれることを実質的に禁止します (ただし、見た目が悪くなる可能性があります)。

\interfootnotelinepenalty\@M

Re:VIEW 5.1 以降ではこれがデフォルトです。長い脚注がたくさんあり、以前と同様にページで分かれたほうがよいということであれば、ペナルティ値を別のものに設定します。TeX のもともとのデフォルト値は 100 です。

\interfootnotelinepenalty100

数式への番号付けをRe:VIEWのものではなく、LaTeXの番号付けにするにはどうしたらよいですか?

デフォルトでは Re:VIEW での //texequation ブロック命令で記述した数式は、LaTeX の equation* 環境、つまり「番号なし」になります。その代わりに //texequation ブロックに ID およびキャプションを付けた場合には、式<章>.<数式番号> <キャプション> のキャプションが入ります。

Re:VIEW の番号付けを使わず LaTeX 流に式の各行に番号付けをしたいというときには、equation* から equation 環境に一律に書き換えてしまうという手段があります。次のような review-ext.rb を作ります。

module ReVIEW
  module LATEXBuilderOverride
    def result
      super.gsub('{equation*}', '{equation}')
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end
  • EPUB 等のほかの形式は諦めることになるでしょう。

  • 番号への参照はできなくなります。リテラルに書くか、式側に \label{ラベル名} を入れておいて、参照側では 式@<embed>$|latex|\ref{ラベル名}$ のようにする、といった手段はありますが、もう TeX で最初から書いたほうがよいのでは……という気にもなりそうです。

  • equation*equation を混ぜたい (この場合には \notag を使うという手もありますが)、eqnarray 環境などを使いたい、といったときには、もう少しまじめに //texequation の挙動のほうをオーバライドして判定する必要があるでしょう。

参考文献の表現を LaTeX で一般的な形(bibliography)にしたいです

記入した絵文字が消えてしまいます!

review-jsbook の章見出しの上の空きを取るにはどうしたらよいですか?

jsbook 側の設定により、章見出しの前には2行ぶんの空きが入っています。

これを変更するには、章見出しを設定しているマクロごと書き換える必要があります。

具体的には、sty/jsbook.cls に以下の定義があります。

 …
\def\@makechapterhead#1{%
  \vspace*{2\Cvs}% 欧文は50pt
  {\parindent \z@ \raggedright \normalfont
    \ifnum \c@secnumdepth >\m@ne
      \if@mainmatter
        \huge\headfont \@chapapp\thechapter\@chappos
        \par\nobreak
        \vskip \Cvs % 欧文は20pt
      \fi
    \fi
    \interlinepenalty\@M
    \Huge \headfont #1\par\nobreak
    \vskip 3\Cvs}} % 欧文は40pt
 …

この2行目にある \vspace*{2\Cvs} が見出し前2行空きの設定です。このマクロを丸ごと sty/review-custom.sty にコピーし、さらに2行目を % でコメントアウトします。

% for user-defined macro
\def\@makechapterhead#1{%
%  \vspace*{2\Cvs}% 欧文は50pt →上空きを無効化
  {\parindent \z@ \raggedright \normalfont
    \ifnum \c@secnumdepth >\m@ne
      \if@mainmatter
        \huge\headfont \@chapapp\thechapter\@chappos
        \par\nobreak
        \vskip \Cvs % 欧文は20pt
      \fi
    \fi
    \interlinepenalty\@M
    \Huge \headfont #1\par\nobreak
    \vskip 3\Cvs}} % 欧文は40pt

なお、jsbook.cls は各種の調整がやや大きなマクロの中に含まれていることがあり、カスタマイズをしようとするとこのように大掛かりになりがちです。review-jsbook.cls もその制約を受けるので、jsbook.cls / review-jsbook.cls で表現の細かなカスタマイズに手を出そうとすると必然的に TeX 言語および LaTeX マクロの知識が必要になります。

最初から紙面の各要素や見出しの表現などを細かに調整したいという前提があるのであれば、jlreq.cls ベースの review-jlreq.cls を使うほうがよいでしょう。jlreq.clsのドキュメント も参照してください。

書き進めたところ、ある時点から画像が消えるようになりました!

記法ミスでなければ、TeX のコンパイル結果に実際にフォントや画像ファイルなどを埋め込んで PDF を生成する dvipdfmx ツールの内部計算に何らかの問題が発生し、処理に失敗した可能性があります。config.yml の dvioptions パラメータの行頭コメント # を取った上で、-z オプションの値を 9 の代わりに 0(圧縮しない)にして試してみましょう。

# dvioptions: "-d 5 -z 9"
  ↓
dvioptions: "-d 5 -z 0"

これで正常に入るようであれば、dvipdfmx 内部の問題です。ファイルサイズが大きいということを除けば、これで印刷所への入稿は可能です。

電子版配布などのためサイズ圧縮が必要なときには、画像ファイルを PDF 形式にすることを検討しましょう。PDF 形式のファイルは dvipdfmx にとってネイティブファイルであり、変換等の処理がないので比較的安全です。

ビットマップファイルを一度に PDF ファイル化するには、たとえば ImageMagick の mogrify ツールを使って次のように実行します。

mogrify -format pdf *.png
mogrify -format pdf *.jpg

Re:VIEW 4 以下においては、拡張子以外が同じファイルがあると TeX のコンパイル時に図版サイズの計算がおかしくなるため、古いビットマップファイルは別の場所に移動するようにしてください。Re:VIEW 5.0 以降ではこの問題は修正済みです。

印刷版と電子版の設定をうまく管理するにはどうしたらよいですか?

上記のリンク先でヒントを提示しているとおり、config.yml で印刷版ほかひととおりの設定を行い、config-ebook.yml のような名前で inherit を使って config.yml を継承しつつ、差異のある箇所だけ上書きします。

inherit: ["config.yml"]
bookname: book-ebook
texdocumentclass: ["review-jsbook", "media=ebook,paper=a5"]

電子版のみスタイルファイルを変更したいときには、スタイルファイルを統括する sty/reviewmacro.sty を別名でコピーし、それに電子版用の設定を加えるとよいでしょう。

inherit: ["config.yml"]
bookname: book-ebook
texdocumentclass: ["review-jsbook", "media=ebook,paper=a5"]
texstyle: ["reviewmacro-ebook"]

一部の文字が康煕部首の文字になります!

dvipdfmx で Adobe CMap ではなく Unicode マップを使ったフォントを設定している場合、dvipdfmx のバージョンによって一部の文字が本来の文字ではなく、康煕部首の範囲の文字(U+2F00〜U+2FDF)に変わってしまうことがあります。

たとえば源の明朝/ゴシック、Noto Serif/Noto Sans で TeXLive 2018 の dvipdfmx を使っている場合は、U+9577 で入れたはずの「長」が U+2FA7 の康煕文字に変わります。表示上はほとんど区別できませんが、検索したときなどに変わっていることがわかります。より古いバージョンでは「見」「入」なども同様の症状が現れます。

現時点での対処方法は以下のとおりです。

  • より新しい TeXLive / dvipdfmx バージョンを使う。TeXLive 2018 への本件のパッチは dvipdfm-x: tounicode for double encoded glyphs (jp-forum:2575) で公開されています。

  • Unicode マップではない Adobe CMap のフォントを使う (たとえば IPA 明朝/ゴシック)。なお、源の明朝/ゴシックの字形を使った Aodbe CMap 準拠のフォントとして、原の味フォント があります。Docker イメージ vvakame/review の最近のバージョンでは、原の味フォントを採用しています。

各ページの固定位置に画像を配置するにはどうしたらよいですか?

「すべてのページ」に何かを配置するには、everypage パッケージを使用できます。review-custom.sty に以下のように記述します。

\usepackage{everypage}
\AddEverypageHook{
  \myoverlayimage
}

実際に各ページで呼び出すことになる \myoverlayimage ですが、「固定位置」に置く手法はいろいろあるものの、LaTeX のパッケージの中にはトンボの有無によってうまく動作しないものもあります。トンボによらず利用可能な手法として以下に2種類示します。用途に合いやすいものを選びましょう。

手法1は、TikZ パッケージと bxpgfcurpage.sty を組み合わせたものです。bxpgfcurpage.sty は TeXLive にまだ含まれていないので、作者の @zr-tex8r さんの Gist から bxpgfcurpage.sty をダウンロードし、sty フォルダに配置します。

ここでは紙面の左下隅から2mmずつ離したところに images/icon.png を幅20mmで配置するものとします。review-custom.sty にさらに次のように記述します。

 …
\usepackage{tikz}
\usepackage{pxpgfmark}
\usepackage{bxpgfcurpage}
\newcommand{\myoverlayimage}{
\begin{tikzpicture}[remember picture,overlay]
  \node[anchor=south west,% 原点は左下
        xshift=\dimexpr2truemm, % X方向2mmシフト
        yshift=\dimexpr2truemm] % Y方向2mmシフト
        % inner sep=0pt, draw, rectangle] 囲みとかしたいときはこれらも
     at (current page.south west) {% ページの左下位置に貼り付け
       \includegraphics[width=20mm]{images/icon.png}% 幅20mmの画像貼り付け
     };%
\end{tikzpicture}%
}

\node で原点の移動と方向、current page.でページ上の原点位置を表しています。中身は \includegraphics で画像ファイルとしていますが、文字列など任意な指定が可能です。

手法2は、textpos パッケージを利用します。ただ textpos パッケージはトンボ付きのときにずれてしまうので、この修正をする pxtextpos.sty をダウンロードし、sty フォルダに配置します。

この手法での review-custom.sty は次のようになります。

 …
\usepackage[absolute,overlay]{textpos}
\usepackage{pxtextpos}
\newcommand{\myoverlayimage}{
  \begin{textblock*}{20mm}(2mm,\dimexpr\paperheight-20mm-2mm)
    \includegraphics[height=20mm]{images/icon.png}% 高さ20mmの画像貼り付け
  \end{textblock*}
}

\textblock* 環境の引数「{20mm}」は、幅 20mm のボックスを作るという意味です。その後の()内は紙面左上を基準としたX, Y座標です。ここではX座標は左から2mmとし、Y座標は「ページの高さから20mm(画像の高さ)を引いて、さらに2mm上」としています。これで、高さ20mmの画像はページ左下から2mm離れたところに置かれます。

「すべてのページ」ではなく、内容のあるページだけに置きたいときには、review-jsbook を利用している場合 fancyhdr パッケージでヘッダやフッタを作っているので、これを流用するのが手軽です。review-custom.sty は次のようになります。ここでは紙面デザインでは使っていない\chead(中央のヘッダ)を流用しています。

\chead{\myoverlayimage}
\fancypagestyle{plainhead}{% 既存の\fancypagestyle{plainhead}のコピー
\chead{\myoverlayimage}% ここを追加
\fancyfoot{} % clear all header and footer fields
\fancyfoot[LE,RO]{\thepage}
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}}

コードリストの箇所をコピーペーストすると、半角の`'が全角の‘’になってしまいます

review-custom.sty に以下のようなトリックを入れることで、コードリスト部の‘’の文字を変更できます(コードリストを verbatim または alltt の環境で表現している場合。Re:VIEW のデフォルトでは alltt を利用しています)。

%%[ad-hoc] a trick to put upstyle single quotes literally in PDF
\begingroup
\catcode`'=\active
\catcode``=\active
\g@addto@macro\@noligs{%
  \def\review@tt@textquotesingle{{\fontfamily{\ttdefault}\textquotesingle}}%
  \def\review@tt@textasciigrave{{\fontfamily{\ttdefault}\textasciigrave}}%
  \let'\review@tt@textquotesingle
  \let`\review@tt@textasciigrave}%
\endgroup

別解として、本文を含めて、文字の形状をヒゲありのものではない形にし、コピーペースト時も半角になるようにするには、次のような review-ext.rb を使ってすべて置換できます(コードリストを alltt の環境で表現している場合)。いささか乱暴なので、inline_tt, inline_code, common_code_block などに限定したほうが安全かもしれません。

module ReVIEW
  module LATEXBuilderOverride
    def result
      super.gsub("'", '\textquotesingle{}').gsub('`', '\textasciigrave{}')
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

囲み記号として全角の「“」「”」を使うと、PDFからのコピーペーストがうまくいかなくなります

re ファイル側で全角の「“」「”」にしておいた箇所を TeX 上ではシングルクォート2つ・バッククォート2つにするという方法があります。こうすることで EPUB などとも共存しやすくなります。review-ext.rb で出力を書き換える例を示します。

# -*- coding: utf-8 -*-
# 出力前に “ ” のクォートをバックエンド向きの形に置換する
# Copyright 2020 Kenshi Muto
module ReVIEW
  module LATEXBuilderOverride
    def result
      super.gsub('“', '``').gsub('”', "''")
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

奥付に連絡先を入れるにはどうしたらよいですか?

だいぶ昔から標準で提供していたのですが、ドキュメント化していませんでした。config.yml の contact パラメータで連絡先を記載できます。

contact: "Re:VIEW Project (https://reviewml.org/)"

奥付の著者・出版社等の順序を変更するにはどうしたらよいですか?

config.yml の colophon_order パラメータで順序を指定できます。デフォルトは ["aut", "csl", "trl", "dsr", "ill", "cov", "edt", "pbl", "contact", "prt"] です。

奥付の「著 者」などを変更するにはどうしたらよいですか?

locale.yml を使ってデフォルトの文字列から変えることができます。デフォルトの指定を継承すると次のようになります。

locale: ja
aut: "著 者"
csl: "監 修"
dsr: "デザイン"
ill: "イラスト"
cov: "表 紙"
edt: "編 集"
pht: "撮 影"
trl: "翻 訳"
prt: "印刷所"
pbl: "発行所"
contact: "連絡先"

奥付のデザインが気に入らないので、根本的に違うものにしたいです

LaTeX ソースのファイルを用意してプロジェクトフォルダに置き、config.yml の pdfmaker: の下にある colophon パラメータに指定します。

 …
pdfmaker:
  colophon: mycolphon.tex

ここでは mycolphon.tex を読み込むようになります。このファイル内で LaTeX の表現を駆使して奥付を作成することもできますが、別のソフトを使って PDF を作成しておき、それを貼り付けるのがおそらく課題の解決には妥当でしょう。images フォルダに mycolophon.pdf を用意したとして、次のような内容を mycolophon.tex に記述します。

\includefullpagegraphics{images/mycolophon.pdf}

大扉のデザインが気に入らないので、根本的に違うものにしたいです

config.yml の titlefile パラメータに LaTeX ソースのファイルを指定します。PDF を配置したいときには、該当のソースファイル内でたとえば次のようにしておきます。

\includefullpagegraphics{images/mytitlepage.pdf}

大扉ページの後に権利表記のページを入れたいです

config.yml の creditfile パラメータに LaTeX ソースのファイルを指定します。PDF を配置したいときには、該当のソースファイル内でたとえば次のようにしておきます。

\includefullpagegraphics{images/mycredit.pdf}

プロフィールページを入れたいです

config.yml の profile パラメータに LaTeX ソースのファイルを指定します。PDF を配置したいときには、該当のソースファイル内でたとえば次のようにしておきます。

\includefullpagegraphics{images/myprofile.pdf}

プロフィールページはデフォルトの layout.tex.erb においては索引の後、広告・奥付の前に入ります。

広告ページを入れたいです

config.yml の advfile パラメータに LaTeX ソースのファイルを指定します。PDF を配置したいときには、該当のソースファイル内でたとえば次のようにしておきます。

\includefullpagegraphics{images/myadvertisement.pdf}

広告ページはデフォルトの layout.tex.erb においては奥付の前に入ります。

Re:VIEW 4.0 で media=ebook を使うと、「! TeX capacity exceeded, sorry [input stack size=5000]」なるエラーになります

見出し内に @<code>@<tt> を使っており、かつハイパーリンクを有効にするとマクロの解決に失敗します。

次の内容を sty/review-custom.sty に記述することでエラーを回避できます。Re:VIEW 4.1 では修正済みです。

\g@addto@macro\pdfstringdefPreHook{%
  \def\reviewbreakall#1{#1}}

段落の間に少し空きを入れるには?

review-jsbook、review-jlreq ともに段落と段落の間に空きが加わることはありません。洋書の一部などであるように段落間に空きを入れたいときには、sty/review-custom.sty に以下のような定義を入れることで空きが入るようになります。

\setlength\parskip{1ex plus 0.5ex minus 0.2ex}

これは文字「x」の高さぶんの空きを基本とし、状況によって-0.2〜+0.5の変動を許容するという意味です。\parskip は目次などほかの箇所にも影響する可能性があるので、指定したことで何か副作用が出ていないか確認しましょう。

なお、単に「1行の空行」を入れたいときには Re:VIEW の //blankline 命令があります。

アクセント記号の前後に変な空きが入ってしまいます

upLaTeX の利用時において、「ǒ」や「é」などの一部の文字が和文文字として解釈され、おかしな出力になることがあります。pxcjkcat パッケージを使って、特定範囲を欧文扱いに設定する(prefernoncjk オプション)ことでこれを回避できます。

そのままだと「○」や「■」なども欧文扱いになってビルドに失敗することがあるので、以下の review-custom.sty の定義ではさらにいくつかの Unicode ブロックについては和文文字扱いとしています。

\usepackage[prefernoncjk]{pxcjkcat}
\cjkcategory{sym18,sym19,grek}{cjk}

コードハイライトを使うにはどうしたらよいですか?

highlight 設定を有効にします。現時点で有効な値は listings のみです。

highlight:
  latex: "listings"

ハイライト解析に使う言語をリストの言語設定(emlist 系では第2、list 系では第3オプション)で指定する必要があります。

//emlist[][ruby]{
def hello
  puts 'Hello.'
end
//}

なお、LaTeX のコードハイライトは listings および plistings パッケージによって解析されますが、HTML で使っている rouge や pygments に比べるとあまり十分とは言えません。

上級者向けのヒントとしては、minted パッケージを使い(これは内部で pygments を呼び出します)、emlistlst マクロ等にそれを割り当てるという方法があります。

ちょっとした書き物やレポート用に利用するにはどうしたらよいですか?

たとえば A4 でなるべくいっぱいに使い、章番号などは不要、表紙・目次・奥付も不要といった条件として、review-jlreq を使った例を示します(review-jsbook でも可能ですが見出しの空白などで調整すべき内容が多くなってしまうので、シンプルな review-jlreq を使っています)。

まず、review-init -t review-jlreq プロジェクト名 で作成します。

次に、config.ymltexdocumentclass および pdfmaker セクション以下を次のように設定します。texdocumentclass パラメータの値については、sty/README.md ファイルを参照してください。

  …
texdocumentclass: ["review-jlreq", "media=ebook,paper=a4,cover=false,gutter=20mm,fore_edge=20mm,head_space=10mm,foot_space=20mm"]

pdfmaker:
  secnolevel: 0
  toc: null
  titlepage: null
  colophon: null

さらに sty/review-custom.sty でノンブル(ページ番号)の位置を中央下に変えておきます。

\ModifyPageStyle{headings}{nombre_position={bottom-center}}

これで1ファイルのみでの利用を想定し、とてもシンプルなレポートスタイルの紙面になります。

ノンブルも不要なら、以下のようにします。

\ModifyPageStyle{headings}{nombre={}}

@<href>命令でHTMLのように「#アンカー」でハイパーリンクを付けるにはどうしたらよいですか?

TeX(label/ref 関係および hyperref パッケージ)のリンク構造と、HTML のリンク構造とはだいぶ異なります。http://〜 および https://〜 で始まる完全URLであればそれほど挙動に違いはないのですが、相対URLパスであるとか、#を使ったページ内アンカーリンクは HTML 固有のものであり、完全な再現は困難です。図表およびリストの参照は @<img>@<table>@<list>、章や節の参照は @<chap>@<sec> の命令を使うことを推奨します。

これ以上の任意の位置に対するハイパーリンクを実現したいという例として、いくらか制約はありますが、@<href> の挙動を変更して同一書籍内のハイパーリンクを実現する review-ext.rb を示します。

module ReVIEW
  module LATEXBuilderOverride
    def compile_href(url, label)
      # @<href>{url, label} および @<href>{url} の実装メソッドを上書きする
      if /\A\#/ =~ url # 先頭が#で始まっているならアンカーへのハイパーリンクと解釈
        # XXX:この判定手法だとURLに「ch01.xhtml#foo」と別ファイルを指定しているときにはうまくいかないので、
        # より柔軟性を持たせたいならさらに条件を連ねる必要がある
        if label
          # ラベルがあるならそれを表示に利用
          macro('hyperlink', url.sub('#', ''), escape(label))
        else
          # ラベルがないなら、代替でページ参照(p.XX)に
          'p.' + macro('pageref', url.sub('#', ''))
        end
      else
        super(url, label) # ほかはデフォルト挙動を呼び出し
      end
    end

    def label(id)
      super(id)
      puts macro('hypertarget', id, '') # アンカー。文字列なしでポイントのみ作成
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

//label でアンカーラベルを指定しておき、@<href>{#アンカーラベル, 紙面表現文字列} あるいは @<href>{#アンカーラベル} で参照します。後者はリンク文字列に相当するものがなくなってしまうので、代替として「p.XX」のようにアンカーラベルのある箇所のページ番号を示すようにしています。なお、単にページ番号を示す目的には、このような拡張を使う必要はなく、@<pageref> 命令を利用できます。

長いURLを折り返させるのはどうしたらよいですか?

@<href> で入るリンクは、ときに版面を越えてはみ出すことがあります。いくぶん強硬なやり方として、sty/review-custom.sty に以下のように記述し、ほとんどの文字で折り返しを許容することができます。

\renewcommand{\UrlBreaks}{\do\/\do\a\do\b\do\c\do\d\do\e\do\f\do\g\do\h\do\i\do\j\do\k\do\l\do\m\do\n\do\o\do\p\do\q\do\r\do\s\do\t\do\u\do\v\do\w\do\x\do\y\do\z\do\A\do\B\do\C\do\D\do\E\do\F\do\G\do\H\do\I\do\J\do\K\do\L\do\M\do\N\do\O\do\P\do\Q\do\R\do\S\do\T\do\U\do\V\do\W\do\X\do\Y\do\Z}

折り返しの不満な箇所がごく一部で、明示的に指示したいときには、URLの折り返しを参照してください。

複雑な表表現をしたいです

Re:VIEW の表表現はシンプルな縦横表の記述を前提にしています。セル結合や任意の罫線、箇条書きを含めるなどの複雑な表を表現するには不向きなので、画像として作成し、//imgtable 命令を使って貼り込むことを検討してください。

索引に範囲や参照を入れたいです

Re:VIEW の索引命令 @<hidx> はシンプルなもので、単語あるいは階層を指定する程度の機能を提供しているのみです。ただ、実際には TeX の makeidx パッケージと mendex コマンドを内部で使っているので、それらがサポートしている範囲であればいろいろと実現できます。

索引において特に使われそうな機能は以下のとおりです。

  • 範囲。\index{単語|(} を単語の範囲の開始、\index{単語|)} を範囲の終了とする。

  • 参照。\index{単語|see{別単語}} とすることで、ページの代わりに「→別単語」という形になる。

このように展開されるよう、索引内では擬似タグを使います。たとえば範囲の開始は@<hidx>{単語◆→BEGIN←◆}、終了は@<hidx>{単語◆→END←◆}、参照は@<hidx>{単語◆→SEE(別単語)←◆}という表現にしたとすると、これを後処理する review-ext.rb は次のようになります。

# -*- coding: utf-8 -*-
# mendexのBEGIN,END,SEEを索引内に擬似タグを入れて実現する
# Copyright 2020 Kenshi Muto
module ReVIEW
  module LATEXBuilderOverride
    def index(str)
      post = nil

      if str =~ /◆→BEGIN←◆/
        post = '|('
        str.sub!('◆→BEGIN←◆', '')
      elsif str =~ /◆→END←◆/
        post = '|)'
        str.sub!('◆→END←◆', '')
      elsif str =~ /◆→SEE\((.+?)\)←◆/
        post = "|see{#{escape($1)}}"
        str.sub!(/◆→SEE\((.+?)\)←◆/, '')
      end

      "#{super(str).chop}#{post}}"
    end
  end

  class LATEXBuilder
    prepend LATEXBuilderOverride
  end
end

なお、参照のデフォルトは「→ 別単語」ですが、review-custom.sty 等で \see マクロを定義し直すことで変更できます。

\renewcommand\see[2]{#1も参照}

コード内で @<u> を使った下線を引こうとするとエラーになります

review-jsbook で利用している下線スタイルの jumoline.sty だと、コード環境と競合するようです。次のように review-custom.sty で \reviewunderline マクロをデフォルトの \underline に割り当てればひとまずコード内下線については回避できます(review-jlreq ではこれがデフォルトになっています)。

\DeclareRobustCommand{\reviewunderline}[1]{\underline{#1}}

ただし、こうすると段落途中での改行はされないので、必要に応じて手動で @<u> を付け直すといった作業が必要になります。

部や章の番号の表記方法が locale.yml で変更しても変わりません

デフォルトでは部番号はローマ数字大文字(Ⅰ、Ⅱ、……)、章番号はアラビア数字となっています。EPUB などではこれを locale.yml の partpart_shortchapterchapter_short の値を変えることで調整できるようになっています。

しかし、review-jsbook・review-jlreq ではどちらもクラスファイルレベルで部や章の番号表記スタイルが定義されており、locale.yml に対応する柔軟な変更は困難です。@<chapref> などで参照している箇所は Re:VIEW でリテラルな文字展開をしているので locale.yml での指定どおりになりますが、見出しや目次においてはクラスファイル側の既定値のままとなります。

review-jsbook・review-jlreq において部番号をアラビア数字にしたいとき(locale.yml で part: "第%d部"part_short: "%d" としたことに対応)には、review-custom.sty で次のように指定します。

\renewcommand{\thepart}{\arabic{part}}

同様に、章番号をローマ数字大文字にしたいとき(locale.yml で chapter: "第%pRW部"part_short: "%pRW" としたことに対応)には、review-custom.sty で次のように指定します。

\renewcommand{\thechapter}{\Roman{chapter}}

対応付けると、%d\arabic(アラビア数字)、%pRW\Roman(ローマ数字大文字)、%pr\roman(ローマ数字小文字)、%pA\Alph(アルファベット大文字)、%pa\Alph(アルファベット小文字)です。%pAW(アルファベット大文字全角)・%paW(アルファベット小文字全角)・%pJ(漢数字)・%pdW(アラビア数字2桁全角)・%pDW(アラビア数字すべて全角)に相当させるためにはrenewcommand 内で内容を見て適宜処理する必要があるでしょう。

章に[nonum]を付けたときに柱の表示がおかしくなります

章に[nonum]を付けた場合、デフォルトでは柱部分の出力は以下のような挙動になります。

  • review-jsbook クラスの場合: 最初の章だった場合は「第0章 タイトル」のように0章扱いになり、途中の章の場合は3つめの章だったとして「第2章 タイトル」のように1つ前の番号が有効だった章番号が柱に入ります。

  • review-jlreq クラス利用の場合: 最初の章だった場合は「目次」のようになり、途中の章の場合には「第2章 2章のタイトル」のように1つ前の番号が有効だった章番号および章見出しが柱に入ります。

いずれにせよ、意図とは異なる状態ですが、Re:VIEW 側での対処はかなり厄介(対処したことで別の問題を引き起こしかねない)なため、現時点では場当たり的な回避策をとる必要があります。

もし、すべてにおいて章番号を使わない場合は以下のように sty/review-custom.sty に追加します。

review-jsbookクラスの場合: \chaptermark 定義で章番号を柱に含めないようにする。

\def\reviewmainmatterhook{%
  \renewcommand{\chaptermark}[1]{\markboth{##1}{}}
  \mainmatter
}

review-jlreqクラスの場合: chaptersection での採番をやめ、さらに章や節の番号を柱に含めないようにする。

\ModifyHeading{chapter}{number=false}
\ModifyHeading{section}{number=false}
\ModifyPageStyle{headings}{mark_format={_section={#1}, _chapter={#1}}}

すべてではなく特定の章だけ [nonum] を使いたいというときには、その章の章見出しの後に \markboth マクロで直接、柱の文字列を入れます。このマクロは左右の柱を示す2つの引数をとります。以下では左右とも同じ「はじめに」という柱にしています。

=[nonum] はじめに

//embed[latex]{
\markboth{はじめに}{はじめに}
//}

…

FAQ - Re:VIEW の使い方について(EPUB・WebMaker)

FAQ(よくある質問と回答)のこのセクションは、Re:VIEW の使用方法のうち、EPUB および Web ページの生成に関係する事柄をまとめています。


EPUB とは何ですか?

電子書籍フォーマットの世界標準です。多くのリーダーソフトがあり、PC やスマートフォンで本を開くことができます。

中身としては、HTML と CSS を使っていますが、通常は JavaScript は禁止され、CSS の一部も使えないような制約された表現に抑制されています。

ページ表現としては、リフロー型とフィクス型の2種類があります。

  • リフロー型:Web ブラウザと同様に表示サイズや基本フォントサイズによって1ページあたりに表現する範囲が変化します。

  • フィクス型:ページを1つの画像として、紙の本と同じ表現で固定します。

Re:VIEW が生成する EPUB はリフロー型です。

EPUB に変換するにはどうしたらよいですか?

rake epub

または

review-epubmaker config.yml

Web ページに変換するにはどうしたらよいですか?

rake web

または

review-webmaker config.yml

これで、プロジェクトの webroot フォルダに公開用の HTML ファイルが作成されます。

生成される EPUB のバージョンはいくつですか?

デフォルトでは EPUB バージョン 3 のファイルが生成されます。config.yml の epubversion(デフォルトは3)および htmlversion(デフォルトは5)のパラメータで調整できますが、古いバージョンについては今後サポートを終了する可能性があります。

生成された EPUB が標準に合致しているかどうかの確認はどうしたらよいですか?

Kindle 用の mobi ファイルは作れますか?

Re:VIEW 自体にその機能はありませんが、Amazon が無料で配布している Kindle Previewer(https://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765261)というソフトウェアで EPUB から変換できます。

なお、論理目次だけではエラーが報告されるようです。物理目次ページを付けるためには、次のように config.yml に設定します。

epubmaker:
  toc: true

かつては Linux にも対応した CUI の KindleGen というコマンドがありましたが、すでに配布が停止し、Windows または macOS で動作する GUI ベースの Kindle Previewer のみが Amazon 公式の変換ツールです。

「電書協ガイドライン」に従った EPUB は作れますか?

電書協ガイドライン は、紙の本を電子書籍化する過程で EPUB の仕様を知らない制作会社でも迷わないように策定されたローカル規約です。EPUB の標準よりもファイル名やフォルダ構成、タグの付け方などに縛りがあります。

完全に準拠しているかという観点で言えば、Re:VIEW の EPUB は準拠していません。メタファイルに電書協ガイドラインの必須属性を追加するだけならば、config.yml に以下のように加えます。

opf_prefix: {ebpaj: "http://www.ebpaj.jp/"}
opf_meta: {"ebpaj:guide-version": "1.1.3"}

iBooks で EPUB を開いたときに左右ページの間に影ができます

config.yml に以下のように加えると、影を消せます。

opf_prefix: {ibooks: "http://vocabulary.itunes.apple.com/rdf/ibooks/vocabulary-extensions-1.0/"}
opf_meta: {"ibooks:binding": "false"}

上記の電書協ガイドラインの設定もある場合は以下のようにします。

opf_prefix: {ebpaj: "http://www.ebpaj.jp/", ibooks: "http://vocabulary.itunes.apple.com/rdf/ibooks/vocabulary-extensions-1.0/"}
opf_meta: {"ebpaj:guide-version": "1.1.3", "ibooks:binding": "false"}

EPUB から PDF を作ることはできませんか?

Re:VIEW 5.1.0 から、CSS 組版ソフトウェア Vivliostyle-CLI を呼び出す Rake ルールを追加しています。Vivliostyle-CLI をインストールした環境において、rake vivliostyle:build または rake vivliostyle で PDF を作成、rake vivliostyle:preview でブラウザのプレビューが開きます。

関連して以下のような手法・ドキュメントがあります。

CSS を変更するにはどうしたらよいですか?

デフォルトでプロジェクトに展開される style.css ファイルを編集できます。

config.yml の stylesheet パラメータで別ファイルを指定したり、複数指定したりすることも可能です。

Web フォントは利用できますか?

WebMaker で生成した Web ページでは、CSS で設定していれば利用可能です。

EPUB については、EPUB リーダーが対応していれば可能ですが、そのようなリーダーが存在するかは不明です。

縦書き右綴じにするにはどうしたらよいですか?

縦書きにするには、CSS で文字方向を縦にする必要があります。

body {
  ...
  -webkit-writing-mode: vertical-rl;
  -epub-writing-mode:   vertical-rl;
  writing-mode: tb-rl;
}

さらに、config.yml で EPUB のページ送りを右から左に遷移するよう指定します。

direction: "rtl"

実際に縦書きが正常に表示されるかは、EPUB リーダーの能力に依存します。

数式を入れたいのですが良い方法はありませんか?

Re:VIEW フォーマットガイド の「TeX 式」を参照してください。imgmath という機能で TeX 式を画像化できます。

Re:VIEW 5.1 以降では、math_format パラメータの値に基づいて @<m> および //texequation に記載した TeX 数式を HTML 内で実際どう表現するかを指定できます。

  • null: 何もせず、単に文字列として配置します。

  • mathml: MathML で表現します。

  • mathjax: MathJax で表現します。

  • imgmath: 画像で表現します。

コードハイライトを使うにはどうしたらよいですか?

highlight 設定を有効にします。現時点で有効な値は rouge または pygments です。前者の場合は rouge gem パッケージ、後者の場合は pygments.rb gem パッケージおよび Python の pygments コマンドが必要です。

highlight:
  html: "rouge"

ハイライト解析に使う言語をリストの言語設定(emlist 系では第2、list 系では第3オプション)で指定する必要があります。

//emlist[][ruby]{
def hello
  puts 'Hello.'
end
//}

ハイライトを有効にすると、コード内のインライン命令がそのまま出てしまいます

ハイライトとインライン命令は極めて相性が悪く、現状ではまだ妥当な解決方法がありません。ハイライトを使う箇所ではコード内のインライン命令は使わないようにしてください。

どうしてもという場合、いったんインライン命令を隠し、ハイライトをかけてからインライン命令を戻す、という処理が必要です。(#1256)

複数のスペース文字を入れても、1つになってしまいます。どうしたらよいですか?

どうしてもリテラルなスペースを入れたいときには、以下のようにして埋め込みます。

3つのスペースを@<embed>{|latex|~~~}@<embed>{|html|&nbsp;&nbsp;&nbsp;}と入れる

見出しのない re ファイルが EPUB に収録されません

EPUBMaker は論理的な目次を作って管理しているため、見出しのない re ファイルから生成されるコンテンツは欠落してしまいます。

見出しの nodisp オプションを使うと、「目次に含めるけれどもコンテンツ側には表示しない」見出しを定義できます。たとえば以下の例では、「謝辞」という見出しは目次のみに登場し、コンテンツでは「ありがとうございます。」のみが表示されます。

=[nodisp] 謝辞

ありがとうございます。

どうしても目次にも表示したくない場合は、フックで目次の HTML ファイルを書き換えてください。

複雑な表表現をしたいです

Re:VIEW の表表現はシンプルな縦横表の記述を前提にしています。セル結合や任意の罫線、箇条書きを含めるなどの複雑な表を表現するには不向きなので、画像として作成し、//imgtable 命令を使って貼り込むことを検討してください。

EPUB/Web で索引を使うにはどうしたらよいですか

索引を作ると一概に言っても、「読み順のソートをどう実現するか」「相互参照関係をどう表すか」という2つの大きな問題があります。

EPUB/Web 向けの実装例を以下で掲載しています。

上記2つの問題への対応として、次のアプローチをとっています。

  • 索引は TeX 環境、読みは MeCab を流用する(つまり、基本的に TeX と同じやり方を使う)

  • 被参照側(hidx を埋め込んだ側)には中身が空のリンクアンカー(<span id="〜" class="rv_index_target"></span>)、参照側(索引一覧側)は 記号でリンクにする(記号は hook_afterbackmatter_common.rb で変更可)

CSS 組版の場合には参照記号の代わりにたとえば counter(page) などの CSS 命令を使ってページ番号を入れることはできますが、そのページ番号は「組んでみるまでわからない」ので、重複したページ番号を除くといった処理はできません。組んだ結果を見て手動で埋め込み索引を除く、あるいは HTML を加工するといった作業が必要になるでしょう。

<section> 囲みにすることはできませんか

Re:VIEW 5.2 以降では、use_section パラメータを true にすると、HTML の見出しの登場とそのレベルに応じて <section> 要素で囲むようになります。

epubmaker:
  use_section: true

FAQ - Re:VIEW の使い方について(InDesign)

FAQ(よくある質問と回答)のこのセクションは、Re:VIEW の使用方法のうち、InDesign での制作に関係する事柄をまとめています。


InDesign とは何ですか?

Adobe 社が開発している、プロユースの DTP ソフトウェアです。月々または年間のサブスクリプション契約制です。

手作業を念頭に置いているので自由度の高い紙面が作れます。TeX PDF のような完全自動の紙面作成はできませんが、XML のインポート機能と JavaScript による「半自動」の紙面作成は可能です。

InDesign ファイルに変換する maker コマンドがないようです。どうやって変換するのですか?

Re:VIEW 4 以降では、review-idgxmlmaker コマンドが導入されました。

rake idgxml
review-idgxmlmaker config.yml
review-idgxmlmaker -f フィルタプログラム config.yml
REVIEW_CONFIG_FILE=config-idgxml.yml REVIEW_IDGXML_OPTIONS="-f フィルタプログラム" rake idgxml

フィルタプログラムは、標準入力で XML を受け取り、標準出力に加工した XML を書き出すという挙動が期待されます。フィルタプログラムで処理対象の re ファイル名を知るには、REVIEW_FNAME 環境変数を参照してください。

Re:VIEW 3 以下では、Re:VIEW のコンパイルコマンドを直に使用する必要があります。IDGXML ビルダを使うよう、--target=idgxml を指定します。

review-compile --yaml=config.yml --target=idgxml reファイル名 > xmlファイル名

表がある場合、版面の幅を --table= オプションに数値で指定します(mm 単位)。

review-compile --yaml=config.yml --table=版面幅 --target=idgxml reファイル名 > xmlファイル名

IDGXML ビルダが生成される XML ファイルはいったい何ですか?

re ファイルの内容をシンプルな XML 形式で表現したものです。ただし、表の表現などの一部は InDesign 固有の XML 表現形式になっています。

この XML ファイルはあくまでも中間形式であり、紙面レイアウトに合わせて適切に加工することを想定しています。

中間形式の紙面に合わせてどのような作業をしたらよいのですか?

大きく次の3つの作業が必要です。

  • 紙面デザインの InDesign ファイルを、「できるだけ流し込みで、インラインフレームを使わずに済む」よう調整する。

  • IDGXML ビルダの生成した XML ファイルを、紙面デザインに合うようにスタイル名を設定したり加工したりする。

  • 手作業では頻繁・煩雑な調整を、JavaScript のプログラムで代替する。

なぜ IDGXML の XML ファイルには改行が入っていないのですか?

要素中に改行を入れる・入れないは紙面レイアウトによって変化するため、迂闊に人間が見やすいようにと改行を入れてしまうと、「後工程で不要な改行を消す」という手間が増えます。これは「後工程で改行を入れる」に比べて必要だった改行まで消してしまう恐れがあります。

そのため、Re:VIEW の XML ファイルはコードリスト途中の改行や @<br> 命令で入れた強制改行以外には改行を入れていません。

なぜ IDGXML の XML ファイルは浅い構造なのですか?

XML ドキュメントは、各行ごとに InDesign の段落に割り当てられます。改行文字がそのまま段落表現になるため、改行の入れ方には注意が必要ですが、XML ドキュメントによく見られるような深い階層構造にしてしまうと、その行に改行が入るかどうかを追跡するのはとても困難な作業になります。

また、InDesign 自体の XML の処理能力は貧弱で、階層を追跡するような実行操作は非常に遅く、頻繁にクラッシュします。

Re:VIEW 自体もその言語の性質上、複雑な XML 階層構造に向いているわけでもありません。

よくわかりません……Re:VIEW と InDesign の組み合わせについての参考書はありますか?

現時点で以下の書籍があります。

InDesign での実績はあるのでしょうか?

開発チームの武藤健志(@kmuto)が業務で請負制作した書籍のほとんどは、InDesign を使用しています。

InDesign の IDML 形式に変換することはできますか?

いいえ。

InDesign のバージョン間のデータ互換性保持によく使われる IDML は XML 形式のアーカイブファイルですが、紙面レイアウトと強く結び付いているため、仮にそのようなデータを生成したとしても紙面レイアウトを柔軟に変えることができません。

もし固有のレイアウトが決まっていて一切のスタイルの変更などもないのであれば、専用の IDML ビルダ・メーカーを作ること自体は可能でしょうが、公式に対応することはありません。

InDesign の ICML 形式に変換することはできますか?

いいえ。

InDesign のサブツール InCopy で使われるコンテンツファイル形式の ICML も、XML 形式のファイルではあります。現状では開発チームにとって必要性が感じられないのでサポートしていませんが、スタイル名の決め打ちを前提とすれば実装は比較的容易だとは思われます。

ほかの変換器で IDGXML 形式を作ることはできますか?

IDGXML 形式自体、仕様としては実装しかないので、互換性というほどの規則はありません。ただ、Re:VIEW と類似のドキュメント処理システム Sphinx から IDGXML に変換するビルダは存在し、InDesign での制作実績があります。

IDGXML になってしまえば、あとは既存の IDGXML 向けのフィルタおよび InDesign 上の JavaScript を利用できます。