Tech系サービスやガジェットの使い心地、自分の作業環境、資産運用について気が向いたときに記録を残しています。

記事内のAmazonアソシエイト適格販売及び、Google Adsenseでお小遣いを得ています。

Notion + Markdown + VivlioStyle で共著の同人誌を作成する

ここ数年、自分の同人サークルである幻想サイクルの同人誌作成では、vivliostyleを使って原稿を作っている。

vivliostyle.org

組版アプリケーションを使っていて「このオプション、もう少し細かく設定できたらなぁ……」と思ったことはありませんか? Vivliostyle を使った CSS 組版では、比較的柔軟かつプログラマブルに原稿のスタイルを設定できます。

最大でも年に2回しか同人誌を作成しない身としては、InDesignIllustratorのような高価かつ、同人誌作成でしか利用しないスキルを身につけるのは様々な意味でコストが高い。(サークルカットなどを作るにもInkscapeを使ってAdobe税を回避しているほどだ)

VivlioStyleは、普段から仕事で使っているフロントエンドのスキルセット(主にCSS)を使いPDFレイアウトができるツール。さらに、入稿の元データも馴染みのあるMarkdown構文で記述できる。

テーマに原稿データを流し込み、テンプレートエンジンのような感覚で入稿可能なPDF※を生成できる。画像の配置・改ページ・ノンブルや目次の自動生成など、手作業でやると抜けの出やすい部分をおまかせでき、執筆者陣はコンテンツ作成に集中できるという寸法。

※印刷用の入稿PDFにはフォントのアウトライン化やグレースケール化をはじめとするPDF/X-1aという規格に準拠する必要がある

この夏の新刊はこちら。

www.gensobunya.net

後述するが、印刷物としての制限がないKindleでは写真を全てカラー版に置き換えている。

こういった複数フォーマットに対しても、ビルド時の設定を変更することで、単一の原稿ファイルからPDF/X-1a規格とKindle用のPDFを出し分けられる点が非常に強力だ。

組版ツールでも、リンク先のファイルを置き換えるだけで対応できるといえばできるだろうが、こうした機械的な作業は作業漏れ対策も兼ねて自動化するに限る。

VivlioStyleの強みと、自転車同人誌のミスマッチ

VivlioStyleのプロジェクトはMarkdown + CSS + 設定ファイルという構成になり、テキストベースのファイルだけで構成できるので、Gitを使って管理できる。

ここまでくれば、ITエンジニア諸氏にはGitHubなどのGit WEBサービス上にリモートリポジトリを設定し、Pull Requestベースでお互いの原稿ファイルをレビューしたり、ローカルでは好みのエディタを使ってLinterやフォーマッターを使って原稿の質を確保する…といったメリットがすぐに思い浮かぶだろう。(コードではなく文章を書く場合にもTextlintというものがあり、これが素晴らしい仕事をしてくれる)

github.com

事実、技術書の執筆ではこうしたコラボレーションツールと、Textlintを用いたMarkdown原稿での運用事例が山のように転がっている。(MarkdownでなければRe:viewが多いか)

ただ、幻想サイクルの共著者すくみずさんはどちらかというとハードウェア寄りのスキルの持ち主なので、Gitを設定してVSCode上でFormat on SaveしながらLinterの吐いたWarningを読んで修正…ということを1から身に着けてもらうのは難しい。繰り返しだが、年に2回のイベントでしか使わないスキルを身に着けるというのは無理がある。大抵は次回までに体が忘れている。

そこで、ITエンジニアでなくとも使いやすいツールで共同作業しながら、こうしたソースと成果物を分割できるワークフローを回せないかと試行錯誤している。

GoogleDriveでファイルを共有しながら、.mdファイルをいじる…ということもやってみたのだが、テキストエディタMarkdownをいじるという行為をPrettier無しでやると、画像リンクや改行など"流儀"の差が出てしまう他、校正や見直した部分がわからなくなったり、最終編集時刻を見ずにいじって原稿データのデグレが頻発するなど、気分のいいものではなかった。

ようやくこの記事の本題だが、C102では下記のステップで原稿を作った。手戻り少なく成果物もわかりやすい状態を維持できて、中々いい具合だったので記録に残しておきたい。

  1. 下書きと構成をNotionでコメント入れながら試行錯誤(Notion内)
  2. Markdownエクスポートしたものをリポジトリに入れてTextlintとPrettierで綺麗にする
  3. VivliostyleでPDF作って校正(チャットでやり取り)

1. Notionでの原稿下書き

Notionでの下書きについては特に何も考慮することはない…わけでもない。

エクスポート時に、Notionにおける「ページ」が1つのMarkdownファイルになるため、これを意識したページ構成にする必要がある。また、後々は原稿と画像ファイルの紐付け管理のために、Markdownファイルと、それに伴うアセットファイルがうまく整理されると嬉しい。

Vivliostyleの設定ファイルから、理想的な下書きの吐き出し方を考慮してページ構成を決める必要がある。

//vivliostyle.config.js

module.exports = {
  title: "限界自転車部屋",
  author: "Gen and skmz",
  language: "ja",
  size: "JIS-B5",
  theme: "theme_print.css",
  tocTitle: "目次",
  entry: [  //原稿用Markdownのパス
    { path: "toc.md", rel: "contents", theme: "theme_toc.css" },
    "chapter0/intro.md",
    "chapter1/chapter1.md", 
    "chapter2/chapter2.md",
    "chapter99/outro.md",
  ],
  entryContext: "./contents",
  workspaceDir: ".vivliostyle",
  output: "./output/bike-room-catalog.pdf", 
  toc: true,
};

(個々人の好みはあるにせよ)チャプターごとにディレクトリを分けておきたいところ。

Vivliostyleは章ごとにファイルを指定するので、Notionページも章ごとに分けておく。(これは粒度が大きすぎるので、もっと細かくファイルを分けたいところだがVivliostyleの設定を見る限りこれ以下の粒度にはできないっぽい)

サブページを出力し、フォルダ分けするオプションをONにすると都合のいい出力となる

それっぽいオプションをONにして出力すると、いい具合にページごとのディレクトリが作成される。

ページ名+ハッシュがアセットのディレクトリ名となり、日本語名は文字化けするので英字必須。この変換・出力は5分ほどかかる点に注意。

後処理の必要性があるファイル名とディレクトリ名だが、後ほど処理する

Google Docsライクな共同作業能力

ページの編集自体は何の変哲もなく、Googleドキュメントのようなオンライン同時編集と、履歴管理・コメント管理ができる。これでレビューや章立ての議論・見直しを行いながら本文を書きあげていく。

Gitでバージョン管理して複数案検討したり、それぞれの案で現物出力したいなどの欲は出るが、この方法でも必要十分な議論はできる。

2. エクスポートした原稿を整形し、改ページなどをいじる

ここからはITエンジニアの作業。

エクスポートしたファイルたちを取り込むvivliostyle.config.jsを書き、フォーマッター・Linterを用いて原稿を綺麗にする。そのうえで、Vivliostyleのプレビュー機能を使いながら改ページや段落の分割などを行っていく。

NotionエクスポートしたMarkdownの下処理

Lintの表記を修正したくなるところだが、キャプション付き画像のキャプションがMarkdown Image記法と本文で2重に出力されたり、キャプションnullの画像はファイル名が挿入されるなどの都合があるため、これらを一括修正する必要がある。

ファイル名はともかく、段落にもキャプションが入ってしまうのは仕様としてイケていないので何とかしてほしい…

キャプション未設定だとキャプションにファイル名が入る

なぜかキャプションが二重に…

これらを正規表現で修正。

また、ページ名とハッシュの間にもスペースがありLinuxでは困るという点については、ディレクトリとファイル名のスペースを削除してMarkdown内は置換でなんとかする。

まとめると、下記の手順となる。

  1. アセットディレクトリのスペースを削除し、Markdown内の相対リンクも半角スペースを消したディレクトリ名で置換
  2. キャプション被りを正規表現置換で修正する
    1. ^!\[(.*)\]\((.*)\)\n\n\1 to ![$1]($2)
  3. ファイル名キャプションの画像を修正する
    1. ^!\[(.*.[png|jpg|JPG|PNG|webp|WEBP])\] to ![ ]

Markdown文法上は、キャプションの中身を0文字にしても問題ないが、Vivliostyle側でエラーになってしまうので半角スペースを挿入している。

校正

Prettierやmarkdownlintで自動整形が走った後に、textlintのサジェストを一つ一つ確認しながら、ルールを無効にするか、文章を修正するか判断して機械的に判定できる点の構成を行っていく。

プリインのルールや、技術書向けのルールを適用している

利用している校正ルールの一覧

これだけのルールを人力で見つけるのは非現実的なので、機械的に検出することで漏れをなくし、時間も劇的に節約できる。

改ページ処理

実際の出来上がりをプレビューしながら、自動改ページを手直しする

Vivliostyleが画像や段落に応じて自動的に改ページを入れてくれるのだが、そのままにしておくと「写真が1枚載っているだけ」というページや、「改ページ直後にその後の本文と無関係な写真が入る」という現象が起きる

これらを改ページ用の不可視区切り<hr class="page-wrap" />を挿入して改ページを増やしたり、段落分割を行ったりして見た目にダサい本文にならないように修正。

3. PDFプレビュー

一通りの処理が終わったら、PCで読めるPDFファイルに出力して最終校正を行う。

グレイスケール化や、フォントのアウトライン化を行わないことで軽量なPDFを出力して読み合わせし、温かみのある課題表を手作りして対応。

// package.json
  "scripts": {
    "lint": "textlint README.md 'contents/**/**.md'",
    "lint:fix": "textlint --fix 'contents/**/*.md'",
    "build": "run-p build:scss build:vivliostyle",
    "build-ebook": "run-p build:scss build:ebook",
    "build:scss": "sass theme:.",
    "build:vivliostyle": "vivliostyle build --press-ready --preflight-option gray-scale",
    "build:ebook": "vivliostyle build -o ./output/ebook.pdf",
    "dev": "run-p preview watch:scss",
    "preview": "vivliostyle preview",
    "preview-ebook": "vivliostyle preview -c vivliostyle.ebook.config.js",
    "preview-build": "npm run build:scss && vivliostyle build -o ./output/preview.pdf",
    "validate": "vivliostyle-theme-scripts validate",
    "watch:scss": "sass --watch theme:."
  },

必要なコマンドを作っているだけでnpmスクリプトが肥大化するが、必要なので仕方ない。

ここばかりは人力が必要。有料版Acrobatを持っていたりすると、直接赤を書き込めて捗る。

まとめ

GUIで共同作業できるNotionと、IDEのパワーを使うことで、入稿期限数時間前まで変更をかけても原稿ファイルが破綻しない。実際にC102ではデスマーチ対応実績も積むことができ、期せずして信頼性の高いワークフローに仕上がったと思っている。

その他:テーマについて

本のテーマは、公式で配布しているvivliostyle-techbookを自分用に手直ししたものだが、飾り気に欠けるのが改善点と思いながら着手できていない。

ひとえに、CSS力が足りない他、Vivliostyleはmarkdown→HTML→PDFという内部変換を行っている影響も大きい。手になじんでいるNext.jsやGatsbyでHTMLを出力すればMDXと合わせてリッチな原稿を作れる可能性を考えたのだが、クライアントサイドのJavascriptCSS-in-JSライブラリがVivliostyleのPDF化ライフサイクルのどこで評価されるか分かりづらいこともあって手を出せなかった。

最近使いだしたAstroは、ゼロランタイムのCSSライブラリと合わせて完全に静的なHTML+CSSを出力できるため、こうしたフレームワークを使って冬コミ原稿にチャレンジしたいところ。