📝

技術書典13に向けて執筆環境を整える(Markdown + Re:VIEW)

2022/05/30に公開約5,600字

(2022年8月3日追記)執筆完了したので本の宣伝をします。

https://zenn.dev/sikkim/books/how_to_create_api_sales_service

(2022年6月22日追記)prhと機能がかぶるため、textlintの設定からWEB+DB PRESS用語統一ルールを除外しました。

技術書典に参加したい

先日、技術書典13の開催日が発表されました。9月10日なので、約3か月後ですね。

https://twitter.com/techbookfest/status/1527997016261169152

筆者は今回初参加する予定です。本の内容は現在作成中のReactアプリについてです。今まで本を書いたことがないので、執筆環境を模索するところからはじめる必要がありました。

Markdownで書いて組版はRe:VIEWに任せたい

本をつくるには組版という工程が必要です。技術同人誌ではRe:VIEWという組版ツールが広く使われています。

https://reviewml.org/ja/

TechBoosterさん[1]ReVIEW-Templateやカウプラン機関極東⽀部さんのRe:VIEW Starterといったテンプレートがとくに人気です。両方とも試してみましたが、どちらも完成度が非常に高いツールです。

ただし、Re:Viewを利用するには文章を「Re:VIEW記法」というフォーマットで書く必要があります。Re:VIEW記法はさほど難しくありませんが、筆者はふだんMarkdownで文章を書いているため、切り替えると混乱します。ただでさえ遅い執筆速度がおそろしく低下してしまいます。

また、書いた本を公開するプラットフォームの問題もあります。筆者は今回3つのプラットフォームを利用しようと考えています。

  • 技術書典(紙の本、PDFダウンロード)
  • Booth(PDFダウンロード)
  • Zenn Books(HTML)

Zenn BooksではMarkdownで書く必要があります。Re:VIEW記法で書いたらわざわざMarkdownに修正する手間がかかります。したがって、Markdownで書いて本にするのが理想的です。

Markdownから直接組版が可能なCSS組版という方法もあります。CSS組版ではVivliostyleというツールが有名です。

https://vivliostyle.org/ja/

Vivliostyleには技術書用のテンプレートもデフォルトで用意されています。試してみたところ十分に実用的でした。ただ、生成されるPDFを比べると、Re:VIEWの方がより洗練されていて読みやすいです。

MarkdownをRe:VIEW記法に変換するツールもあります。md2reviewpandoc2reviewを試してみました。pandoc2reviewの方が変換精度は高いようです。md2reviewは脚注を正常に変換できず、手動で修正する必要がありました。

前置きが長くなりました。以上を踏まえて、筆者の執筆方針は次の通りとします。

  • オリジナルの文章はMarkdownで書く
  • pandoc2reviewでMarkdownをRe:VIEW記法に変換する
  • 組版はReVIEW-Templateで行う

執筆環境の構築手順

前提として、ハードウェアはIntel MacでエディターはVSCodeです。

リポジトリの準備

ReVIEW-Templateのリポジトリでuse this templateをクリックし、自分用のリポジトリを作ります。

ReVIEW-Templateのリポジトリ

基本的な使い方はドキュメントが充実しているので省略します。筆者はDockerを使ってコンパイルしています。デフォルトのsetup.shは毎回node_modulesを削除して時間がかかるので一部コメントアウトしました。

pandocのインストール

pandoc2reviewを利用するには事前にpandocをインストールする必要があります。

brew install pandoc

pandoc2reviewを利用する設定

ReVIEW-Templateにはpandoc2reviewを利用する設定が最初から用意されています。設定は次の箇所を有効にするだけです。これだけでコンパイル時にはMarkdownファイルが自動的にRe:VIEW形式に変換され、PDFが生成されます。素晴らしい。

config.ymlの一部
# reファイルを格納するディレクトリ。省略した場合は以下 (. はカレントディレクトリを示す)
# contentdir: .
# pandoc2reviewを利用してMarkdownコンテンツを取り込むには、以下を有効にする
contentdir: _refiles

コードブロック内の自動折り返し

ReVIEW-Templateのデフォルト設定ではコードブロック内の行は自動で折り返されず、次のようにはみ出してしまいます。

デフォルト設定のコードブロック

Re:VIEWナレッジベースに回避方法がいくつか紹介されています。

https://review-knowledge-ja.readthedocs.io/ja/latest/latex/linebreak-verbatim.html

筆者は次のようにしました。

まずreview-ext.rbarticleの下に配置します。

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 = 76
      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

次にGemfileを修正します。

Gemfile
# A sample Gemfile
source "https://rubygems.org"

gem 'review', '5.4.0'
gem 'pandoc2review'
gem 'rake'
# gem 'review-peg', '0.2.2'
+ gem 'unicode-display_width'

これで折り返されるようになりました。B5判のPDFではnの値を76にするとちょうどよい位置で折り返されます。

修正後のコードブロック

表の自動折り返し

表も自動では折り返されません。

修正前の表

この問題はエレガントな解決方法が見つからず、仕方なくMarkdown側で表の直前に次の記述を追加しました。

//tsize[|latex|50,70]

これは表の幅を50mmと70mmに設定するRe:VIEW記法です。幅は列ごとに設定する必要があります。PDFは次のように修正されますが、Markdown側ではこの記述はそのまま表示されてしまいます。Zennに移植する場合は事前にスクリプトで削除する必要がありそうです。

修正後の表

文章校正ツールの導入

筆者はtextlintを使っています。また、今回からprhも使い始めました。

textlintとルールをインストールします。

npm i -D textlint textlint-rule-preset-ja-technical-writing

テクニカルライティング用のルールセットをインストールしています。

.textlintrcファイルをプロジェクトルートに配置します。

.textlintrc
{
  "rules": {
    "preset-ja-technical-writing": true
  }
}

次はprhを導入します。うまくパスが通らなかったので筆者はグローバルインストールしました。

npm i -g prh prh-languageserver

VSCodeの機能拡張を導入します。

prh機能拡張のインストール

vscode-textlintprh - ProofReadingHelperをインストールしましょう。VSCodeを再起動すれば校正指摘箇所がエラーやワーニングになるはずです。

prhのルールや設定はReVIEW-Templateに最初から入っています。ちらっと中を見ましたがすごい労作ですね。TechBoosterさんの豊富な経験に裏付けされた校正ノウハウを享受できるのはとてもありがたいです。

レビューしてくださる方を募集中です

Webアプリは6月中に完成する予定ですが、執筆の方はいつ書き終わるかわかりません。とりあえず前書きと1章は書きました。Zennに書いた記事をベースにしているので、書き下ろし部分は少ないのですが、手を入れはじめると無限に修正したくなってしまってなかなか進みません。

筆者の周りにはReactの本をレビューできる人がひとりもいません。[2]どなたかレビューしてくださる方がいらっしゃいましたら、この記事のコメント欄に書き込んでいただけると幸いです。

脚注
  1. 技術書典の主催者グループ。 ↩︎

  2. 同僚には読んでもらう予定ですが、フロントエンドが苦手な人々なので、内容が間違っていても指摘してもらえないのがつらいです。 ↩︎

Discussion

ログインするとコメントできます