GitHub ActionsでAsciiDocをPDF出力しよう(2)
2020-05-11
azblob://2022/11/11/eyecatch/2020-04-22-github-actions-asciidoc-pdf1-0.png

はじめに

前回はAsciiDocをPDFで出力するための基礎知識としてHTMLとPDFのフォーマットの違いとAsciidoctorに関する違いにフォーカスして説明しました。

今回から「出力編」と「解説編」に分けてPDF出力を行う方法について説明します。今回の「出力編」の内容はサンプルリポジトリをクローンすることですべて完了します。また今回の「出力編」作業をご自身で一つ一つ行わなくても「解説編」を読めばPDF出力の仕組みは理解できると思います。
今回の「出力編」は、これまで手作業で環境を構築してきた方やリポジトリ内のファイルがどのように準備されるか知りたい方に読んでいただき、より理解を深めていただければと思います。

前回までの記事について

これまでの記事はこちらにあります。こちらも合わせてお読みいただけると嬉しいです。

本ページで利用するサンプルについて

出力サンプル用のリポジトリは僕の個人的なプロジェクトの一環で公開しています。
このサンプルではPDF出力でつまづきやすい部分の多くを解決しているので、このサンプルを元にしてご自身の環境を構築すると簡単にPDF出力を行うことができます。

今回の記事では本サンプルから本当に必要な部分のみを抜粋してご紹介します。
解説通り進めるより、以下のサンプルをご自身の環境にコピーしていただきどの部分がどう重要か?確認していただくのがやりやすいかと思います。

今回利用するファイルとディレクトリについて

今回利用するファイルやディレクトリの簡単な図は以下の通りです。
全てのファイルをGitHubにPushします。

文字化けしないPDFを出力するための準備をしよう

ここからはまずAsciiDocに書いた日本語をを出力できる準備を行います。

必要なフォントをかき集めよう

『fonts』ディレクトリを作成し以下で取得したフォントを配置しましょう。日本語のファイルはフォントファイルがないと綺麗にPDF出力できないため、カスタムフォントとしてご自身でフォントを準備する必要があります。
また、カスタムフォントを利用する際は出力に利用する全てのフォントをご自身で用意する必要があります。
以下に今回利用するフォントを紹介します。

※利用可能なフォントはTrueType形式(拡張子 .ttf )のフォントのみとなります。

源真ゴシック

自家製フォント工房で配布されているフォントでフリーのOpenTypeフォントである「源ノ角ゴシック」を TrueType 形式に変換したフォントです。『fonts/GenShinGothic』ディレクトリに配置してください。

源様明朝

GitHubのButTaiwan/genyo-fontで配布されているフォントでフリーのOpenTypeフォントである「源ノ明朝」を TrueType 形式に変換したフォントです。
ttcで配布された 最新のフォントは句読点の制御が上手く行かないので、少し古いバージョンの.ttf形式の物を利用しています。
『fonts/GenYoMinJP』ディレクトリに配置してください。

Noto Emojiフォント

Google Noto Fontsで提供されているオープンソースの絵文字フォントです。なお同じ配布元に携帯電話で使えるカラー絵文字もありますがエラーになるため使えません。
『fonts/NotoEmoji』ディレクトリに配置してください。

テーマファイルでフォントを指定しよう

集めたフォントでPDFを出力できるように、テーマファイルを作ってフォントを指定します。
新たに『themes』ディレクトリ作成しを以下の例を元にテーマファイル「sample-theme.yml」作成し『themes』ディレクトリ配下に配置します。

extends: default

font:
  catalog:
    Noto Serif:
      normal: GenYoMinJP/GenYoMinJP-Regular.ttf
      bold: GenYoMinJP/GenYoMinJP-Bold.ttf
      italic: GenYoMinJP/GenYoMinJP-Light.ttf
      bold_italic: GenYoMinJP/GenYoMinJP-SemiBold.ttf
    M+ 1mn:
      normal: GenShinGothic/GenShinGothic-P-Regular.ttf
      bold: GenShinGothic/GenShinGothic-P-Bold.ttf
      italic: GenShinGothic/GenShinGothic-P-ExtraLight.ttf
      bold_italic: GenShinGothic/GenShinGothic-P-Medium.ttf
    GenYoMin:
      normal: GenYoMinJP/GenYoMinJP-Regular.ttf
      bold: GenYoMinJP/GenYoMinJP-Bold.ttf
      italic: GenYoMinJP/GenYoMinJP-Light.ttf
      bold_italic: GenYoMinJP/GenYoMinJP-SemiBold.ttf
    GenShinGothic:
      normal: GenShinGothic/GenShinGothic-P-Regular.ttf
      bold: GenShinGothic/GenShinGothic-P-Bold.ttf
      italic: GenShinGothic/GenShinGothic-P-ExtraLight.ttf
      bold_italic: GenShinGothic/GenShinGothic-P-Medium.ttf
    Serif:
      normal: GenYoMinJP/GenYoMinJP-Regular.ttf
      bold: GenYoMinJP/GenYoMinJP-Bold.ttf
      italic: GenYoMinJP/GenYoMinJP-Light.ttf
      bold_italic: GenYoMinJP/GenYoMinJP-SemiBold.ttf
    Sans Serif:
      normal: GenShinGothic/GenShinGothic-P-Regular.ttf
      bold: GenShinGothic/GenShinGothic-P-Bold.ttf
      italic: GenShinGothic/GenShinGothic-P-ExtraLight.ttf
      bold_italic: GenShinGothic/GenShinGothic-P-Medium.ttf
    Noto Emoji:
      normal: NotoEmoji/NotoEmoji-Regular.ttf
      bold: NotoEmoji/NotoEmoji-Regular.ttf
      italic: NotoEmoji/NotoEmoji-Regular.ttf
      bold_italic: NotoEmoji/NotoEmoji-Regular.ttf
  fallbacks: [GenShinGothic, Noto Emoji]

base:
  align: left
  font_family: GenYoMin
  line_height_length: 15
heading:
  font_family: GenShinGothic

※テーマファイルはCSSのようにベースとなるテーマを利用することで全てのスタイルの記述をする必要がありません。このためベースとなるテーマに指定されているフォントファミリーについても上書きする形で指定いるため、フォントの指定が冗長になっています。

画像の埋め込みは特にすることはないけれど

ここからはAsciiDocで使った画像を埋め込む準備と見せかけて、ただのディレクトリの整理をします。

※画像の埋め込みで実際に注意する点は次回に細かく解説します。

わかりやすくするためだけにフォルダを作ろう

『images』ディレクトリを作成し利用している画像を配置しましょう。特に埋め込みには関係ない処理ですが、今回のサンプルと同じフォルダ構成にする作業です。

ワークフローで呼び出すコマンドをシェルスクリプトにしよう

PDFを出力したりより高度な出力オプションを利用するには、外部アクションに対してワークフローからコマンドを直に渡すよりも、シェルスクリプトにコマンドを記述して実行したほうがより便利に利用できます。
このため、以下のシェルスクリプトを「asciidoc.sh」として作成し『.github/workflows』配下に配置します。
作成したらローカル環境で構いませんので実行権限を必ず付与しましょう。実行権限が付与できていないとワークフローの実行時に失敗してしまいます。

#!/bin/bash
set -e

# make directory for Output Types
mkdir -p ./outputs/pdf

# Get file path
CURRENT_PATH=`pwd`
ASCIIDOCTOR_PDF_DIR=`gem contents asciidoctor-pdf --show-install-dir`

set -x

# Output PDF
asciidoctor-pdf -B ${CURRENT_PATH}/ -D ${CURRENT_PATH}/outputs/pdf/ -o sample.pdf -a pdf-styledir=${ASCIIDOCTOR_PDF_DIR}/data/themes -a pdf-style=${CURRENT_PATH}/themes/sample-theme.yml -a pdf-fontsdir=${CURRENT_PATH}/fonts -a scripts=cjk -a allow-uri-read index.adoc

※今までと異なり、今回からはより複雑なファイル出力のサンプルを含めているため、出力対象のファイルをREADME.adocからindex.adocに変更しています。

以前のサンプルから発展させてる人はindex.adocを作成しよう

以下のファイルはindex.adocの簡単な例です。以前のサンプルから発展させてる人は以下のファイルをルートディレクトリ配下に配置します。

= Asciidoctor action sample
// ドキュメント仕様
:asciidoctor:
:doctype: book
:lang: ja
:icons: font
:encoding: utf-8
:backend: html5
:docinfo:
// 画像を埋め込み
:data-uri:
// 目次
:toclevels: 3
:toc: left
// セクションにアンカーを作成
:sectanchors:
// セクションにリンクを作成
:sectlinks:
// 章番号を付けるか。属性を定義しておくだけで章番号が付けられる。
:sectnums:
// ソースコードをハイライトする。
:source-highlighter: coderay
// 画像やビデオリソース(videoは個別に出力先にコピーが必要)
:imagesdir: ./images


toc::[]

[[README]]
== AsciidocサンプルのREADME
include::README.adoc[]

※上記の例で出力される内容は目次とREADMEの内容ですが、公開しているサンプルではその他の記載も確認できると思います。

シェルスクリプトを実行できるようにワークフローを修正しよう

以下のファイルは以前から利用しているasciidoc.ymlを一部修正したものです。
今回の修正は3つです。以下の修正を行ってワークフローを完成させましょう。

  1. 『Analog-inc/asciidoctor-action』の指定を「v1」に変更して、バージョンを固定
  2. 『Analog-inc/asciidoctor-action』の引数を「./.github/workflows/asciidoc.sh」に変更して、シェルスクリプトの実行を指定
  3. 出力ファイルの取得元を「./outputs/」に変更して様々な出力形式のファイルを一回で取得できるよう修正
# This is a AsciiDoctor workflow to help you get started with Actions
name: CI

# Controls when the action will run. Triggers the workflow on push
# events but only for the master branch
on:
  push:
    branches: [ master ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "asciidoctor_job"
  asciidoctor_job:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    name: Build AsciiDoctor
    steps:
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    - name: Check out code
      uses: actions/checkout@v2
    # Output command using asciidoctor-action
    - name: Build AsciiDoc step
      id: documents
      uses: Analog-inc/asciidoctor-action@v1
      with:
        shellcommand: "./.github/workflows/asciidoc.sh"
    # Use the output from the documents step
    - name: Save AsciiDoc step
      uses: actions/upload-artifact@v1
      with:
        name: Output-document
        path: ./outputs/

Pushして出力を確認しよう

ではPushしてPDFを出力してみましょう。正しく出力できましたか?

もし、出力に失敗して以下のメッセージが「CI / Build AsciiDoc」内の「Build AsciiDoc step」に表示されているようであれば、シェルスクリプト「asciidoc.sh」に実行権限がついていません。ローカル環境で構いませんのでで実行権限を付与して再度Pushしてください。

bash: ./.github/workflows/asciidoc.sh: Permission denied
##[error]Docker run failed with exit code 126

※僕は.で始まる不可視ファイルをMacで閲覧するためにファイル転送系のアプリを利用していますが、そのようなアプリのほとんどでも実行権限をファイルに付与することができます。

まとめ

今回はPDF出力の一番の注意点となるフォントの埋め込み作業を中心にPDF出力ができる変更を「出力編」として一気にご紹介しました。
次回は「解説編」として実際に必要な設定について詳細な解説をしたいと思います。