マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

Pandocで節見出しの“番号の書式”を変えたい話

元ネタはこの辺。

要するに「節見出しの中の番号の書式を変えるにはどうすればよいか」という話。

やりたいこと

Markdown文書をPandocでLaTeXやHTMLに変換する場合に、「節見出しの中の番号の書式」を以下のようにしたい。

  • 章(レベル1)については「第1章」とする。
  • 節(レベル2)については「第1節」とする(章番号はつけない)。

例えばこんなMarkdown文書があったとする。

# まえがき {-}
# ゆきだるま
## ゆきだるまは素敵
## ゆきだるまは本質的
## TeXとの関係 {-}

{-}は節見出しにunnumberedクラスを指定する記法({.unnumbered}と等価)で、番号のない節見出しであることを表す。

この文書の変換結果は以下のようになってほしい。

まえがき
第1章  ゆきだるま
第1節  ゆきだるまは素敵
第2節  ゆきだるまは本質的
TeXとの関係

LaTeXする場合

LaTeX脳で考える

LaTeXの思想に依って考えると、「節見出しの中の番号の書式」は文書クラスの専管事項ということになる。従って、書式を自分好みに変えたいのであれば、そういう文書クラスをつくればよい、という単純な話になる。

ただ、「単純な話」といっても「簡単な話」では決してない。文書クラスを作製(改変)するにはTeX言語の知識が多少とも必要となるからである。そこで、文書クラスによっては多少のカスタマイズを可能としていることがある。例えば、章(\chapter)については、多くの和文文書クラスにおいて、「章の数字(カウンタ表示)の前後に付く文字列」はマクロ(\prechaptername\postchaptername)になっていて変更できる。なので、要件によっては既存のクラスのカスタマイズで済む場合もあるだろう。

この辺りの話は、「PandocでLaTeX文書を生成する」場合であっても基本的には変わらない。Pandocの思想では原則的に「文書の構造を含めた内容だけを変換対象対象とし、文書のレイアウトについては変換先のソフトウェアに委ねる」ことになっているからである。ただしここでも例外があり、(主に複数の文書形式の間で統一的に扱う目的で)一部のレイアウト設定はPandoc側で制御できる。今回の件に関しては、LaTeX出力で標準のテンプレートを適用する場合は以下の機能が存在する。

  • --number-sectionsオプション(短縮名-N)が指定されない場合、節番号の表示を抑止するためにsecnumdepthカウンタの値に負数を設定する。

従って、要件を実現するには、「--number-sectionsを指定した上で、LaTeXの側で節番号表示に対してカスタマイズを行う」という方針をとることになる。

やってみる

いつも通り、BXJSクラスのPandocモードを利用する。今回は章がある文書なのでbxjsbookを使うことになる。

章番号の設定については、bxjsbookクラスも他の和文クラスと同様に\prechaptername\postchapternameマクロで行う。

\renewcommand{\prechaptername}{}
\renewcommand{\postchaptername}{}

ただし、(これも多くの和文クラスと同様で)上に示した値は既定値になっているので実際には何も設定しなくてよい。

節(\section)の番号については、BXJSクラスの独自機能(詳細は過去の記事を参照されたい)を利用する。すなわち、クラスオプションにlabel-section=modernを指定すた上で、以下のようにマクロを再定義する。

% 節のカウンタの表示に章の番号を入れない
\renewcommand{\thesection}{\arabic{section}}
% 節番号の出力を"第1節"とする
\renewcommand{\labelsection}{\thesection}

その他諸々の設定と合わせて、Pandocのデフォルトファイルの形にまとめたものを以下に示す。

to: latex-smart
standalone: true
pdf-engine: lualatex

top-level-division: chapter
number-sections: true

variables:
  papersize: b5
  secnumdepth: 2
  documentclass: bxjsbook
  classoption:
    - pandoc
    - label-section=modern
  header-includes: |
    \renewcommand{\thesection}{\arabic{section}}
    \renewcommand{\labelsection}{第\thesection 節}

f:id:zrbabbler:20200814181729p:plain
LaTeXに変換したやつ(第1章の部分)

HTMLする場合

Pandocで節番号するとアレ

Pandocで--number-sections付きでHTMLに変換した場合、以下のような出力が得られる。

<h1 class="unnumbered" id="まえがき">まえがき</h1>
<h1 data-number="1" id="ゆきだるま"><span class="header-section-number">1</span> ゆきだるま</h1>
<h2 data-number="1.1" id="ゆきだるまは素敵"><span class="header-section-number">1.1</span> ゆきだるまは素敵</h2>
<h2 data-number="1.2" id="ゆきだるまは本質的"><span class="header-section-number">1.2</span> ゆきだるまは本質的</h2>
<h2 class="unnumbered" id="texとの関係">TeXとの関係</h2>
<h2 data-number="1.3" id="マフラー"><span class="header-section-number">1.3</span> マフラー</h2>
<h2 data-number="1.4" id="ホウキ"><span class="header-section-number">1.4</span> ホウキ</h2>

ここで注意すべきなのは、「出力のHTMLの中に節番号が記述されている」ということである。つまり、LaTeX変換の場合と異なり、Pandoc側が番号を生成しているわけであり、先述の「Pandocの思想」にも反している。

※もちろん、--number-sectionsを付けない場合は節番号は入らない。

“思想に合わない”ということもあってか、Pandocの「節番号の自動生成」の機能は中途半端で、番号の書式を変えるためのインタフェースは用意されていないようである。つまり、HTML出力の場合は、Pandoc本体の機能だけでは要件は実現できないのである。

HTMLをLaTeX脳で考える

「Pandocの思想」に沿って考えるならば、「節番号の書式」については“HTMLの側”で対処すべきであろう。HTMLの世界で“文書クラス”に相当するものはCSSである。実際、CSSには「節番号を自動生成して節見出しに表示する」ための機能が存在する。

  • 節番号の生成はCSSカウンタを利用するとできる。
  • 節番号の表示は擬似要素を利用する。この際に、番号の書式を自由に設定できる。

従って、Pandocの側では節番号を生成せず(--number-sectionsを指定しない)、代わりに、CSSを利用して所望の書式の節番号を出力する、というのが“Pandoc的に真っ当な”方法といえるだろう。

今の場合、節番号の生成のためのスタイル指定は以下のようになる。

[sample.css]
/** 章のカウンタ"chapter"と節のカウンタ"section"を用意する **/
body {
  counter-reset: chapter, section;
}
/** 章見出しではchapterを増やしてsectionをリセット **/
h1 {
  counter-increment: chapter;
  counter-reset: section;
}
/** 節見出しではsectionを増やす **/
h2 {
  counter-increment: section;
}
/** "unnumbered"クラスの見出しでは何もしない **/
.unnumbered {
  counter-increment: none;
}

節番号の表示は以下のようになる。

[sample.css(続き)]
/** 章見出しの内容の前に"第1章"の形式で章番号を挿入 **/
h1::before {
  content: "第" counter(chapter) "章 ";
}
/** 節見出しの内容の前に"第1節"の形式で節番号を挿入 **/
h2::before {
  content: "第" counter(section) "節 ";
}
/** "unnumbered"クラスの見出しでは出力しない **/
.unnumbered::before {
  content: ""
}

Pandoc側の設定をデフォルトファイルで表すと以下の通り。

standalone: true
css: sample.css
number-sections: false

f:id:zrbabbler:20200814194512p:plain
HTMLに変換したやつ(第1章の部分)

実際には、「既定のテンプレートを指定した場合、文書のタイトルが“titleクラス付きのh1要素”で出力されるので、そのための対処が必要」といった問題がある。(まあ、実用で既定テンプレートを指定することはあまりないのかも知れないが。)その辺りの対処も加えたサンプル一式をGistに置いた。

厳しい現実の話

自分としては、これで満足なのであるが、しかし現実問題としては、CSSの素敵な機能を使おうとする場合には常に「その機能は世の中で十分にサポートされているのか」ということに留意しておく必要がある。

CSSの素敵な機能がサポートされていない環境のことも考慮する必要があるのなら、残念ながら結局、「Pandoc側で節番号を生成してHTMLのソースに入れておく」しかないことになる。

どうにかしてどうにかする

結局、Pandocが生成する節番号の書式を設定する機能はないのであるが、だとしても、節見出しがもつ「節番号表示のデータ」をフィルタを使って上書きすることはできないか。いろいろ調べてみた結果、次のことがわかった。

  • 節見出しのオブジェクト(Header型)の属性(attributes)のnumberに文字列を設定しておくと、writerの処理において、Pandocが生成した文字列の代わりにnumberの文字列が「節番号表示の文字列」として使用される1

ということは、「自分で好きな節番号文字列を生成してそれをnumber属性に格納する」ようなフィルタを作れば解決することになる。

[numbering.lua]
local numbers = {}
-- 節番号のスタイル
local number_styles = {
  -- この配列のn番目の要素に"レベルnの節番号表示"を返す関数を置く.
  -- 関数の実行時に, 配列numbersには現在の節番号の値が入っている.
  -- 例えば3.5節であればnumbersの値は {3,5} である.
  function() return ("第%s章"):format(numbers[1]) end;
  function() return ("第%s節"):format(numbers[2]) end;
}

function Header(el)
  -- 子カウンタをリセット
  if numbers[el.level+1] then
    numbers[el.level+1] = 0
  end
  -- .unnumbered なら変更しない
  if el.classes:includes("unnumbered") then
    return -- 変更しない
  end
  -- カウンタをインクリメント
  numbers[el.level] = (numbers[el.level] or 0) + 1
  -- 番号を生成し'number'属性に設定する
  el.attributes['number'] = number_styles[el.level]()
  return el
end

このフィルタを用いる場合のPandoc側の設定は以下の通り。

filters:
  - numbering.lua
standalone: true
number-sections: true

※今度は--number-sectionsを有効にする必要があることに注意。

この設定を適用してHTMLに変換した結果(のbody内)を示す。所望の節番号表示が入っていることがわかる。

<h1 class="unnumbered" id="まえがき">まえがき</h1>
<h1 data-number="第1章" id="ゆきだるま"><span class="header-section-number">第1章</span> ゆきだるま</h1>
<h2 data-number="第1節" id="ゆきだるまは素敵"><span class="header-section-number">第1節</span> ゆきだるまは素敵</h2>
<h2 data-number="第2節" id="ゆきだるまは本質的"><span class="header-section-number">第2節</span> ゆきだるまは本質的</h2>
<h2 class="unnumbered" id="texとの関係">TeXとの関係</h2>
<h2 data-number="第3節" id="マフラー"><span class="header-section-number">第3節</span> マフラー</h2>
<h2 data-number="第4節" id="ホウキ"><span class="header-section-number">第4節</span> ホウキ</h2>

実際にブラウザで表示したときの結果は前のもの(CSSを利用したもの)と全く同じになるので省略する。

まとめ


  1. Pandoc要素に属性を設定すると、HTMLに出力した際に、対応するHTML要素のデータ属性として値が現れる。先に挙げた「PandocのHTML出力」のコードをよくみると、h1・h2要素のdata-number属性に節番号文字列が入っていることがわかる。これは「writerの処理時にPandocのHeader要素のnumber属性に節番号文字列が入っていた」ことを意味している。ただし、節番号の生成はまさにwriterの処理の中で行われるため、フィルタ処理の中でnumber属性を読みだしても何も入っていない。

イマドキのWindowsでcomicsansパッケージする方法

前回の記事の続きで、LaTeXのcomicsansパッケージ(あるいは「Comic Sans MS」フォント)をイマドキのWindowsで使うための話。

イマドキのComic Sans MSだとcomicsansできない話

周知のとおり、Comic Sans MSはWindows(95から)に標準で搭載されているフォントである。comicsansパッケージのマニュアルの説明に従うと、comicsansは「Windowsに搭載されているComic Sans MS」もサポートしているはずである。

ところが、実際に現役のWindows(8.1以降)でマニュアル通りの手順(前回説明した手順からフォントファイルのダウンロードを省いたもの)に従ってインストールした上でcomicsansを利用しようとすると、コンパイルは通ってPDFが生成されるが、肝心のComic Sans MSの文字が全て化けてしまうという無残な結果になる。

f:id:zrbabbler:20200812005848p:plain

この原因は、要するに、「comicsansは古いパッケージ(最終更新は2013年)であり、Windows 8以降の新しいComic Sans MSフォントに対応できていない」からである。

イマドキのComic Sans MSでcomicsansする話

そこで、「comicsansを新しいフォントファイルに対応させるためのパッケージ」を作ってみた

comicsansの内容に変更を加えるのは避けたいので、「comicsansを内部で読み込む新たなパッケージ」という形で提供する。

tccomicsansのインストール方法

Windows 8以降が必要である1

  • comicsansパッケージをパッケージのファイルだけインストールする。すなわち、CTANからcomicsans.tds.zipをダウンロードして、$TEXMFLOCALの下でそのZIPファイルを展開する。
    ※既にcomicsansが完全にインストールされているならそれでもOK。
  • tccomissansのReleaseページから最新の“tccomicsans.tds.zip”(この名前のリンクがある)をダウンロードして$TEXMFLOCALの下でそのZIPファイルを展開する。
  • mktexlsrを実行する。(必要なら管理者権限で)

tccomicsansのキホン的な使い方

comicsansと同じ用法で使いたいのであれば、tccomicsansをmainオプションを付けて読み込む。

\usepackage[main]{tccomicsans}

注意として、tccomicsansはドライバ依存をもつ。従って、dvipdfmxと併用する場合はクラスオプション2dvipdfmxを指定する必要がある。

例えば、前回の記事のテスト用の文書と同等のものは、以下のソースファイルから得られる。

\documentclass{article} % pdfLaTeXの場合
%\documentclass[dvipdfmx]{article} % dvipdfmxの場合
\usepackage[main]{tccomicsans}
\begin{document}
\section{A Simple Test}
Hello, comic {\TeX} world!
\[ \lim_{x\to0}\frac{\sin x}{x} = 1 \]
\end{document}

f:id:zrbabbler:20200810094421p:plain

なお、新しいComic Sans MSフォントは以前のものとは異なり「イタリック」「太字イタリック」のフォントファイルが含まれている。tccomicsansパッケージのフォントマップはイタリックシェープに対して(合成斜体ではなく)これらのフォントファイルを割り当てているため、pdfLaTeXでもイタリックシェープが使用可能である。もちろん、キリル文字にも対応している。

% 文字コードはUTF-8
\documentclass{article} % pdfLaTeX
%\documentclass[dvipdfmx]{article} % dvipdfmx
%↓ロシア語したい
\usepackage[utf8]{inputenc}
\usepackage[T2A,T1]{fontenc}
\usepackage[russian,main=english]{babel}
\babeltags{RUS=russian}
%↑
\usepackage[main]{tccomicsans}
\begin{document}
\section{A \emph{Very} Simple Test}
\begin{itemize}
\item In \emph{America}, you run {\TeX}.
\item \textRUS{В \emph{Советской-России}, {\TeX} выполняет вас!}
\end{itemize}
\end{document}

f:id:zrbabbler:20200812025222p:plain

tccomicsansをホンキで使う

comicsansのオプション、例えばulemphlargesymbolsなどはtccomicsansでも有効である。(内部でcomicsansを読み込む際にこれらのオプションをそのまま渡している。)

\documentclass{article} % pdfLaTeX
%\documentclass[dvipdfmx]{article} % dvipdfmx
% 大型演算子をアレにする
\usepackage[main,largesymbols]{tccomicsans}
\begin{document}
\[ e = \lim_{t\to\infty} \left(
       1 + \frac{1}{t} \right)^t
     = \sum_{n=0}^{\infty} \frac{1}{n!}
\]
\end{document}

f:id:zrbabbler:20200812025203p:plain

tccomicsansパッケージのmainオプションは「comicsansパッケージを内部で読み込んで本文のメインのフォントをComic Sans MSに変更する」という設定を行うためのものである。従って、tccomicsansをmainを付けずに読み込んだ場合はメインのフォントの設定は変更されない。この場合に「comicというフォントファミリを利用すれば文書の一部だけComic Sans MSを適用できる」ということは前回の記事で述べたが、さらにtccomicsansパッケージでは次のユーザ命令が利用できる。

  • \comic: 以降のテキストをComic Sans MSで出力する。(普通はグルーピング内で使う。)
  • \textcomic{テキスト}: 引数のテキストをComic Sans MSで出力する。

mainが有効な場合もこれらの命令は提供される。
mainが無効な場合はcomicsansパッケージは読み込まれない。従って、comicsans用のオプション指定は無効になる。
※tccomicsansパッケージの仕様では、Comic Sans MSで実際に出力する場合には必ずパッケージを読み込む必要がある。(フォントマップを有効にするため。)

\documentclass{article} % pdfLaTeX
%\documentclass[dvipdfmx]{article} % dvipdfmx
\usepackage[nomain]{tccomicsans}
\begin{document}
% 一部だけComic Sans MSにする.
Hello, \textcomic{comic} {\TeX} world!
\end{document}

f:id:zrbabbler:20200810094451p:plain

LuaLaTeXとかXeLaTeXとか

fontspecパッケージの機能を利用してWindows付属のComic Sans MSを指定する場合は以下のようにする。

Windows上のTeX LiveではOSにインストールされたフォントはfontspecにおいて必ずフォント名で指定できる。ファミリ名だけ書けば済むのでフォント名指定のほうが便利であろう。

% LuaLaTeX/XeLaTeX
\documentclass{article}
\usepackage{fontspec}
% フォント名で指定する場合
\setmainfont{Comic Sans MS}
% ファイル名で指定する場合
%\setmainfont{comic}[Extension=.ttf,ItalicFont=*i,
%    BoldFont=*bd,BoldItalicFont=*z]
\begin{document}
Hello, comic {\TeX} world!
\end{document}

f:id:zrbabbler:20200810124233p:plain

前回の記事の最後に挙げた「Comic Sans MSの指定を、テキストはfontspec、数式はcomicsansで行う」例をtccomicsansを使って書き直すと以下のようになる。

% LuaLaTeX/XeLaTeX; UTF-8
\documentclass{article}
\usepackage[main]{tccomicsans}
\usepackage[no-math]{fontspec}
\setmainfont{Comic Sans MS}
\begin{document}
\section{\emph{Comic} Lua{\LaTeX}}
\begin{itemize}
\item \TeX-lingvo estas \emph{danĝera!}
\item \TeX-язык — \emph{опасен!}
\item Η γλώσσα \TeX\ είναι \emph{επικίνδυνη!}
\item $\displaystyle
  \frac{1}{1^2} + \frac{1}{2^2} + \frac{1}{3^2} + \cdots
  = \frac{\pi^2}{6}$.
\end{itemize}
\end{document}

f:id:zrbabbler:20200812035350p:plain

まとめ

イマドキのWindowsのComic Sans MSは用法・用量を守って(ry


  1. 実際には「Windows 8以降に搭載のものと同等なComic Sans MS」があればtccomicsansは使えるはずである。この場合、そのフォントファイルを「TeXから見える場所」に配置すればよい。

  2. ドライバオプションをtccomicsansのオプションとして指定することも可能であるが、イマドキのLaTeXを使っているのであれば、ドライバオプションはクラスオプション(グローバルオプション)に指定すべきである。

TeX Liveでcomicsansパッケージする方法

TeX Live(およびそれに準ずるTeX配布)で「comicsansパッケージ」をインストールする手順を説明してみる。

最初に注意してみる

  • Windowsでは当然Comic Sans MSが付属しているはずであるが、Windows 8以降に付属する新しい版のComic Sans MSについてはcomicsansパッケージはサポートしていないので使えない。ここで説明する手順に従って古い版のComic Sans MSを導入する方法はWindowsでも有効であるが、OSのフォントを古い版で上書きしてしまわないように十分に注意すること。
  • ★印を付けた操作は管理者権限(例えば“sudo”を付けるなど)が必要である。

手順を説明してみる

①comicsansのパッケージをダウンロードする

  • CTANのページを開く。
    CTAN: Package comicsans
  • “comicsans.tds.zip”のリンクから、その名前のファイルをダウンロードする。
    ※“Download”から得られる「comicsans.zip」ではないので注意。
  • “Package Documentation”のリンクをたどって、マニュアルを開く。
    ※あるいは、何らかの方法で、zip内にあるcomicsans.pdfを開く。

②マニュアルの手順に従う

2.1 Acquire and install the TrueType files
  • フォントファイル(comic.ttf、comicbd.ttf)の取得は書いてある通り。
  • ★フォントファイルを次の場所に配置する: $TEXMFLOCAL/fonts/truetype/microsoft/comicsans/
2.2 Generate the italic and/or Cyrillic variants (optional)
  • これは、TeX外のシステム依存の話なので、がんばる。あるいは、optionalなのでがんばらなくてもよい。

※マニュアルの説明の中に「cyrfinst package」なるものが登場するが、要するに、t2a.encがあればよく、TeX Liveのフルインストールなら入っているはずである。(kpsewhich t2a.encで確認できる。)ない場合は、TeX Liveのインストールにcollection-langcyrillicを追加する。(もちろん、キリル文字を使う予定がないなら不要。)

2.3 Install font files and refresh TeX’s database

この節に相当する手順は以下のようになる:

  • ★先ほどダウンロードしたcomicsans.tds.zipを$TEXMFLOCALの下で展開する。
  • ★2.2の手順を行った場合は、生成されたフォントファイル(*.pfb)を以下の場所に配置する:
    $TEXMFLOCAL/fonts/type1/microsoft/comicsans/
  • ★「mktexlsr」を実行する。

※Texdocが利用可能な場合、これ以降は「texdoc comicsans」でインストールしたcomicsans.pdfが開くようになるはず。

2.4 Point the TeX backends to the comicsans files

この節に相当する手順は以下のようになる:

  • ★「updmap-sys --enable Map comicsans.map」を実行する。

③動作確認する

以下のような簡単なテストファイルを用意する。

\documentclass{article}
\usepackage{comicsans}
\begin{document}
\section{A Simple Test}
Hello, comic {\TeX} world!
\[ \lim_{x\to0}\frac{\sin x}{x} = 1 \]
\end{document}

このソースファイルを、以下の各々のワークフローで普通にビルドして、正常にPDFが生成されるかを調べる。

  • pdflatex
  • (p)latex → dvipdfmx

成功の場合、以下の出力が得られるはずである。

f:id:zrbabbler:20200810094421p:plain

さらに蛇足してみる

Type1フォントを作らない方法

dvipdfmxの場合は、わざわざType1フォントに変換しなくても、元のTrueTypeフォントのままでイタリック(擬似斜体)を使うことができる。(pdfTeXでは不可。)その設定に変更する手順を示す。

※管理者権限が必要。

①まず、$TEXMFLOCAL/fonts/map/dvips/comicsans/comicsans.mapを開いて、31~32行目を以下のように書き換える。

(修正前)
rcomico8r ComicSansMS "0.167 SlantFont" <rcomic8r.pfb
rcomicbdo8r ComicSansMS-Bold "0.167 SlantFont" <rcomicbd8r.pfb
rcomiccyro ComicSansMS "0.167 SlantFont" <rcomiccyr.pfb
rcomiccyrbdo ComicSansMS-Bold "0.167 SlantFont" <rcomiccyrbd.pfb
(修正後)
rcomico8r ComicSansMS "0.167 SlantFont TeXBase1Encoding ReEncodeFont" <8r.enc <comic.ttf
rcomicbdo8r ComicSansMS-Bold "0.167 SlantFont TeXBase1Encoding ReEncodeFont" <8r.enc <comicbd.ttf
rcomiccyro ComicSansMS "0.167 SlantFont T2AAdobeEncoding ReEncodeFont" <t2a.enc <comic.ttf
rcomiccyrbdo ComicSansMS-Bold "0.167 SlantFont T2AAdobeEncoding ReEncodeFont" <t2a.enc <comicbd.ttf

②その上で、updmap-sysを(オプションなしで)実行する。

以下にサンプルを示す。

\documentclass{article}
\usepackage{comicsans}
\begin{document}
% \emph が斜体になる.
\section{A \emph{Very} Simple Test}
Hello, \emph{comic} {\TeX} world!
\end{document}

f:id:zrbabbler:20200810095855p:plain

文書の一部だけComic Sans MSにする

comicsansパッケージを読み込む(\usepackage{comicsans})と、文書のメインのフォントがComic Sans MSに変更されてしまうため、「メインのフォントは変えずに、文書の一部だけComic Sans MSを使いたい」という場合には対応できない。実は、comicsansをインストールした時点で、Comic Sans MSが「comic」という(NFSSの)ファミリ名で使えるようになっているので、一部だけ使いたい場合はパッケージを使用せずに直接ファミリを切り替えればよい。

\documentclass{article}
%% \textcomic{テキスト}: Comic Sans MSで出力する.
\newcommand{\textcomic}[1]{%
  {\fontfamily{comic}\selectfont #1}}
\begin{document}
% 一部だけComic Sans MSにする.
Hello, \textcomic{comic} {\TeX} world!
\end{document}

f:id:zrbabbler:20200810094451p:plain

まとめ

Comic Sans MSは用法・用量を守って正しく使いましょう(多分)。


追記:さらにさらに蛇足してみる

LuaLaTeXとかXeLaTeXとかの場合

もちろん、LuaLaTeX・XeLaTeXを使っているのなら、fontspecパッケージの機能を利用してComic Sans MSを利用できる。なので普通はそもそもcomicsansパッケージは不要である。

% LuaLaTeX/XeLaTeX
\documentclass{article}
\usepackage{fontspec}
% ファイル名で指定する場合
\setmainfont{comic.ttf}[BoldFont=comicbd.ttf]
% フォント名で指定する場合(環境依存)
%\setmainfont{Comic Sans MS}
\begin{document}
Hello, comic {\TeX} world!
\end{document}

f:id:zrbabbler:20200810124233p:plain

しかし、数式でComic Sans MSを使いたいのであれば、comicsansパッケージを使うのが妥当であろう1。この場合は、一般的な「fontspecと数式フォントパッケージと組み合わせる」場合のノウハウに従えばよい。つまり:

  • まず数式フォントパッケージ(つまりcomicsans)を読み込む。
  • 次にfontspecをno-mathオプションを付けて読み込む。これでテキスト用フォントはfontspecの初期設定に戻る(数式フォントパッケージの設定は消える)。
  • 改めてテキスト用フォントをfontspecの機能で設定する。
% LuaLaTeX/XeLaTeX
\documentclass{article}
\usepackage{comicsans}
\usepackage[no-math]{fontspec}
\setmainfont{comic.ttf}[BoldFont=comicbd.ttf]
\begin{document}
Hello, comic {\TeX} world and $e^{\pi i} = -1$.
\end{document}

f:id:zrbabbler:20200810124259p:plain

ただし注意がある。この設定では、テキスト用フォントについてはfontspecの機能を使って「TrueTypeフォントを直接指定している」ので、マップファイル(comicsans.map)の設定は使われていない2。なので、イタリックの指定は無効になる。合成斜体によるイタリックを有効にするには、fontspecのFakeSlant指定を利用すればよい3

% ファイル名で指定する場合
\setmainfont{comic}[Extension=.ttf,
    BoldFont=*bd,
    ItalicFont=*,ItalicFeatures={FakeSlant=0.167},
    BoldItalicFont=*bd,BoldItalicFeatures={FakeSlant=0.167}]
% フォント名で指定する場合(環境依存)
%\setmainfont{Comic Sans MS}[
%    ItalicFont=*,ItalicFeatures={FakeSlant=0.167},
%    BoldItalicFont={* Bold},BoldItalicFeatures={FakeSlant=0.167}]

イタリックと数式を含む完全な形のサンプルを挙げておく。

% LuaLaTeX/XeLaTeX; UTF-8
\documentclass{article}
\usepackage{comicsans}
\usepackage[no-math]{fontspec}
\setmainfont{comic}[Extension=.ttf,
    BoldFont=*bd,
    ItalicFont=*,ItalicFeatures={FakeSlant=0.167},
    BoldItalicFont=*bd,BoldItalicFeatures={FakeSlant=0.167}]
\begin{document}
\section{\emph{Comic} Lua{\LaTeX}}
\begin{itemize}
\item \TeX-lingvo estas \emph{danĝera!}
\item \TeX-язык — \emph{опасен!}
\item Η γλώσσα \TeX\ είναι \emph{επικίνδυνη!}
\item $\displaystyle
  \frac{1}{1^2} + \frac{1}{2^2} + \frac{1}{3^2} + \cdots
  = \frac{\pi^2}{6}$.
\end{itemize}
\end{document}

f:id:zrbabbler:20200810125805p:plain


  1. Comic Sans MSは数式用のフォントではないため、unicode-mathパッケージを適用したのでは恐らくロクな結果にならない。comicsansの数式もアレであるが、多分そっちの方がマシだろう。

  2. マップファイルで指定したのは非Unicodeのエンジンのためのフォントの設定であり、それは8ビットのエンコーディングを前提にしているため、Unicodeエンジンでそれを用いることは(可能ではあるが)推奨されない。

  3. (Bold)ItalicFeaturesを効かせるためには(Bold)ItalicFontを明示指定する必要があるようだ。なんか面倒だ……。

LaTeXでつくる「回転ゆきだるまGIF画像」

今年は世界を襲った未曾有の疫病のため日常が……(中略)…………ゆきだるま☃!

LaTeXでつくる「ツイッタァーの進捗」

毎年恒例の「ゆきだるま☃の日」ですが、その日が近づくとツイッタァーに現れる「進捗を促す某ZR氏のツイート」もすっかりお馴染みのものとなりました(多分)。

くるくる回るゆきだるま☃をツイッタァーに上げるべき、というのは至極当然の提案ですね(多分)。

しかし、この提案に沿って、ツイッタァーに素敵な回転ゆきだるま☃のGIFアニメ画像を投稿しようとすると、すぐにある問題に気づくことでしょう。

回転ゆきだるま☃のGIFアニメ画像をどうやって作るか。

もちろん、回転ゆきだるま☃の画像をつくるツールや手法について何か指定があるわけではないので、GIFアニメ画像をつくるツールであれば何でも事足りるのは確かです。しかし、当ブログの読者の多くがLaTeXユーザであると思しきことを考えると、scsnowmanパッケージのカワイイゆきだるま☃を使ったLaTeXソースから回転ゆきだるま☃のGIFアニメ画像をつくることができたら最高に幸せであることは間違いないでしょう。

というわけで、今年の「ゆきだるま☃の日」の記事では、回転ゆきだるま☃画像をつくるスクリプトであるtcspingifを紹介します。

復習:LaTeXでつくる「回転☃文書」

LaTeXでゆきだるま☃を出力する方法は皆さんご存じでしょう。scsnowmanパッケージを利用すると、好きな色のマフラーや帽子を付けたゆきだるま☃を出力できます。

[sample-1.tex]
% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{scsnowman}% ゆきだるま☃!
\begin{document}
% 赤マフラーの素敵なゆきだるま☺
\scsnowman[scale=40,
  muffler=Red,hat=Green,buttons=RoyalBlue,
  arms=Brown,snow=SkyBlue]%
\end{document}

f:id:zrbabbler:20200808205518p:plain
sample-1の出力(非回転)
あるいは、「自分は『原ノ味フォント』の☃が好きだ」という人なら、XeLaTeX(やLuaLaTeX)1でfontspecパッケージを利用した上で、大きなフォントサイズで「☃」の文字を書けばよいでしょう。

[sample-2.tex]
% XeLaTeX文書; UTF-8
\documentclass[margin=10pt]{standalone}
\usepackage{xcolor,fontspec}
\setmainfont{Harano Aji Mincho}% 原ノ味明朝
\begin{document}
\fontsize{240}{0}\selectfont % サイズは240pt
\color{blue!60!black}%% ←素敵☺
\end{document}

f:id:zrbabbler:20200808205616p:plain
sample-2の出力(非回転)
これらの文書の出力は素敵ですが、しかし、回っていません。ゆきだるま☃を回転させるにはどうすればよいでしょうか。「LaTeXで何かを回転させる」ということなので、tcfaspinパッケージが使えそうです。

早速、ゆきだるま☃に\faSpin命令を適用してみましょう。

\faSpinを使用する場合、コンパイルを2回以上行う必要があります。

[sample-3.tex]
% pdfLaTeX文書; UTF-8
\documentclass[margin=25pt]{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{scsnowman}% ゆきだるま☃!
\usepackage{tcfaspin}% 回転!
\begin{document}
% \scsnowman を回転させる
\faSpin{\scsnowman[scale=40,
  muffler=Red,hat=Green,buttons=RoyalBlue,
  arms=Brown,snow=SkyBlue]}%
\end{document}
[sample-4.tex]
% XeLaTeX文書; UTF-8
\documentclass[margin=25pt]{standalone}
\usepackage{xcolor,fontspec}
\setmainfont{Harano Aji Mincho}% 原ノ味明朝
\usepackage{tcfaspin}
\begin{document}
\fontsize{240}{0}\selectfont
\color{blue!60!black}%
\faSpin{}% ←回転!
\end{document}

これをAdobe Readerで開くと……。

f:id:zrbabbler:20200808205648g:plain
sample-3の出力(回転!)
f:id:zrbabbler:20200808205725g:plain
sample-4の出力(回転!)

ゆきだるま☃が回りました! 素敵ですね! というわけで、あとはツイッタァーに投稿するだけ……アッ、チョット待って。この回転ゆきだるま☃は確かに回っていますが、GIF画像ではなくてPDF文書なので、残念ながらこのままではツイッタァーに投稿できません。どうにかして、このPDF文書を画像ファイルに変換しないといけません。

LaTeXでつくる「回転☃画像」

回転☃をImageMagickできない話

PDF文書を画像ファイルに変換する方法としては、(特にTeX界隈では)ImageMagickがよく使われます。例えば、最初の例のsample-1.pdfをPNG画像に変換するには、magickコマンド2を使って次のようにします。

ImageMagickでPDFファイルを扱うにはGhostscriptを併せてインストールする必要があります。

# sample-1.pdf を sample-1.png に変換する(-density はDPI値指定)
> magick -density 72 sample-1.pdf sample-1.png

ImageMagick自体はアニメGIF画像にも対応していますが、残念ながら、tcfaspinを利用した「回るPDF文書」を直接「回るGIF画像」に変換することはできません。これはtcfaspinがかなり特殊な処理を行っているからです3。従って、tcfaspinを使ったLaTeXソースから「ツイッタァーに上げるための回転ゆきだるま☃画像」を生成することは困難です。

回転☃をImageMagickする話

このままでは「ツイッタァー上の回転ゆきだるま☃画像がいつまで経っても増えない」という由々しき事態になりかねません。この困難を打破するため、スクリプトつくりました

このPerlスクリプト tcspingif.pl の実行には以下のインストールが必要です。

tcspingif.pl を使うとコマンド1つで「tcfaspinを使ったLaTeX文書をアニメGIF画像に変換する」ことができます。例えば、先の例にあるsample-3.texとsample-4.texの場合、次のコマンドを実行することで、「PDF文書と同じ出力(同じ動き)」のGIF画像が得られます。

# pdfLaTeX文書 sample-3.tex をGIF画像 sample-3.gif に変換する
> perl tcspingif.pl -e pdflatex sample-3.tex
# XeLaTeX文書 sample-4.tex をGIF画像 sample-4.gif に変換する
> perl tcspingif.pl -e xelatex sample-4.tex

オプションは次の通りです(詳しくは--help付実行で出るヘルプを参照)。

  • -e <名前>: 使用するLaTeXのエンジン(コマンド名、例えばxelatex)。(既定値=pdflatex
    ※DVI出力のエンジン(platexなど)を指定した場合、PDFに変換するのにdvipdfmxが使われます。
  • -d <実数>: 出力解像度のDPI値。(既定値=72
  • -t <整数>: 1回転中のフレーム数。既定値はtcfaspinのオプションで指定された値で、さらにその既定値は32。
  • -b <実数>: 回転速度の標準に対する倍率。(既定値=1
    ※標準は「2秒で1回転」です4。ただし、アニメGIFのフレーム時間設定が10ミリ秒単位であるため実際には誤差が出ます。

チョット補足

生成される画像の大きさは元のPDF文書のものを引き継ぐので、大きさを調整したい場合は、standaloneクラスを利用した上で

  • standaloneのmarginオプションで適宜調節する
  • 文書本体を1つのpicture環境(の類、例えばTikZのtikzpicture環境)にしてその外形を所望のサイズに設定する

などの工夫をすればいいでしょう。

※以下、解像度指定(-dオプション)は72dpiとします。この場合、LaTeX内の1bpが1ピクセルに対応することになります。

例えば、sample-3.texではmarginの値は25ptとなっていますが、これを0ptに変えると出力の大きさは縦横309ピクセルとなります(そして回転の途中で一部が外にはみ出す)。これを縦横360ピクセルで出力するには、marginを25.5bpに指定すればよいことになります((360-309)÷2=25.5)。

[sample-5.tex]
% pdfLaTeX文書; UTF-8
\documentclass[margin=25.5bp]{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{scsnowman}% ゆきだるま☃!
\usepackage{tcfaspin}% 回転!
\begin{document}
\faSpin{\scsnowman[scale=40,
  muffler=Red,hat=Green,buttons=RoyalBlue,
  arms=Brown,snow=SkyBlue]}%
\end{document}
# sample-5.tex をGIF画像 sample-5.gif に変換する
> perl tcspingif.pl -e pdflatex sample-5.tex

f:id:zrbabbler:20200808205648g:plain
sample-5の出力(回転GIF!)

同様に、sample-4.texを縦横280ピクセルで出力する場合は、以下のように調整することになります5

[sample-6.tex]
% XeLaTeX文書; UTF-8
\documentclass{standalone}
\standaloneconfig{margin={20.5bp 26bp}}
\usepackage{xcolor,fontspec}
\setmainfont{Harano Aji Mincho}% 原ノ味明朝
\usepackage{tcfaspin}
\begin{document}
\fontsize{240}{0}\selectfont
\color{blue!60!black}%
\faSpin{}% 回転!
\end{document}
# sample-6.tex をGIF画像 sample-6.gif に変換する
> perl tcspingif.pl -e xelatex sample-6.tex

f:id:zrbabbler:20200808205725g:plain
sample-6の出力(回転GIF!)

tcspingif.plを使うことで、素敵な「回転ゆきだるま☃」の画像をつくることができました!

おまけ:「点滅☃画像」する話

実は、tcspingif.plはtcfaspinパッケージの他にbxblinkパッケージにも対応しています6。つまり、tcspingif.plを利用すると、「回転ゆきだるま☃」だけでなく「点滅ゆきだるま☃」の画像も生成できます(素敵)。

[sample-7.tex]
% pdfLaTeX文書; UTF-8
\documentclass[margin=25.5bp]{standalone}
\usepackage{xcolor,scsnowman}% ゆきだるま☃!
\usepackage{bxblink}% 点滅!
\begin{document}
\textblink{\scsnowman[scale=40,
  muffler=red,hat=red!75!black,buttons,arms,snow]}%
\end{document}
# sample-7.tex をGIF画像 sample-7.gif に変換する
> perl tcspingif.pl -e pdflatex sample-7.tex

f:id:zrbabbler:20200808222213g:plain
sample-7の出力(点滅GIF!)

イロイロやってみる

某ZR氏のツイッタァーでよく見かけるやつ

「赤マフラーと青マフラーと緑マフラーのやつが並んで回っている」画像をつくってみましょう。基本的なデザインを次のように決めます:

  • 画像のサイズを600×240ピクセルとする。
  • 横に三等分した領域の真ん中にゆきだるま☃を配置する。つまり、(100,120)に赤マフラー、(300,120)に青マフラー、(500,120)に緑マフラーを置く。

描画にはTikZを利用しますが、ここで座標の単位をピクセル(既に述べた通り、これは1bpと同じです)に合わせるために、tikzpicture環境の設定にx=1bp,y=1bpを入れておきます。また、最初のうちはtcfaspinを読み込まずに、「PDFファイルの更新に表示を追随する」機能をもつPDFビューアを用いてゆきだるま☃の位置や大きさを調整するのがよいでしょう。

% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage{xcolor,scsnowman}% ゆきだるま☃!
\colorlet{mygreen}{green!50!black}
%\usepackage{tcfaspin}% まだ読み込まない
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]% 座標を"ピクセル"単位にする
% 画像全体のサイズを600×240ピクセルに設定する
\useasboundingbox (0,0) rectangle (600,240);
% ↓満足するまで試行錯誤して調整する
\node at (100,120) {% 赤マフラー
  \scsnowman[muffler=red,scale=XXX,...]};
\node at (300,120) {% 青マフラー
  \scsnowman[muffler=blue,scale=XXX,...]};
\node at (500,120) {% 緑マフラー
  \scsnowman[muffler=mygreen,scale=XXX,...]};
\end{tikzpicture}
\end{document}

満足する構成が得られたら、tcfaspinを読み込んだ上で、\scsnowmanの出力に\faSpinを適用します。

[sample-8.tex]
% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage{xcolor,scsnowman}
\colorlet{mygreen}{green!50!black}
\colorlet{mylbrown}{rgb,10:red,7;green,5}
\pagecolor{mygreen!5}
\usepackage{tcfaspin}% 回転!
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (600,240);
\node at (100,120) {% 赤マフラー(ほうき)
  \faSpin{\scsnowman[scale=15,
    hat=red!75!black,muffler=red,
    broom=mylbrown,snow,arms,buttons]}};
\node at (300,120) {% 青マフラー(冷や汗)
  \faSpin{\scsnowman[scale=15,
    hat=blue!75!black,muffler=blue,
    arms,buttons,sweat,mouthshape=tight]}};
\node at (500,120) {% 緑マフラー(♪)
  \faSpin{\scsnowman[scale=15,
    hat=mygreen!75!black,muffler=mygreen,
    note=green!30!black,snow,arms,buttons]}};
\end{tikzpicture}
\end{document}

まずは普通にpdflatexでPDFに変換してAdobe Readerで回転している様子を確かめます。イイカンジだったら、いよいよtcspingifを実行して画像に変換しましょう。

# sample-8.tex をGIF画像 sample-8.gif に変換する
> perl tcspingif.pl -e pdflatex sample-8.tex

f:id:zrbabbler:20200809004753g:plain
sample-8の出力(0.5Hzくらい)

これでもイイカンジですが、某ZR氏によると、ゆきだるま☃の回転速度は「1Hzあたり(1秒で1回転)」がよいらしいです。なので、速度を2倍に上げましょう。

# 回転速度を2倍にする
> perl tcspingif.pl -e pdflatex -b 2 sample-8.tex

f:id:zrbabbler:20200809004831g:plain
sample-8の出力(1Hzくらい)

トッテモ素敵!

どっかのSlackでよく見かけるやつ

「雪だけ点滅しているやつ」の画像をつくってみましょう。次のようにします:

  • 雪つきの\scsnowmanを描いて、それを点滅させる。
  • その後に、全く同じ位置に、雪なしの\scsnowmanを描く。結果的に雪の部分だけ点滅しているように見える。
[sample-9.tex]
% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage{xcolor,scsnowman}% ゆきだるま☃!
\usepackage{bxblink}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (360,360);
\node at (180,180) {% 雪つき, 点滅
  \textblink{\strut\scsnowman[scale=40,snow]}};
\node at (180,180) {% 雪なし
  \strut\scsnowman[scale=40,
    muffler=red,hat=red!75!black,buttons,arms]};
\end{tikzpicture}
\end{document}
# sample-9.tex をGIF画像 sample-9.gif に変換する
> perl tcspingif.pl -e pdflatex sample-9.tex

f:id:zrbabbler:20200809004908g:plain
sample-9の出力(素敵!)

やっぱり素敵!

まとめ

というわけで、「せっかくのお盆休みなのに外出自粛のせいで何もやることがない」という人は、自作の「回転ゆきだるま☃画像」を一日中眺めて本質的な「おうち時間」を楽しみましょう! 時には「点滅ゆきだるま☃」もよいかもしれません!


  1. このように「文字を画像として使う」あるいは「画像に文字を入れる」という場合は「和文組版用の調整」は不要(あるいは却って邪魔)であることが多く、その場合、LaTeXエンジンの選択として(u)pLaTeXは避けるのが無難です。日本語処理パッケージを併用せずにpdfLaTeX・XeLaTeX・LuaLaTeXを使用しましょう。OpenTypeフォントを使う場合は、処理時間の点でLuaLaTeXよりもXeLaTeXの方がオススメです。

  2. ImageMagickの古い版では変換用のコマンドはconvertという名前でした。

  3. tcfaspinは内部でanimateパッケージを利用しています。そして、animateパッケージはPDFのスクリプティング機能を利用してページ上のオブジェクトを動的に変化させています。

  4. tcfaspinの\faSpin命令は元来はWebのfontawesomeのfa-spinクラス指定の動作を模倣するものなので、その回転速度に合わせています。

  5. marginの値を縦と横で変えるにはmargin={<横> <縦>}という形で設定しますが、このように{ }を含む指定はクラスオプションでは受け付けられないので、代わりに\standaloneconfigという命令で設定する必要があります。

  6. bxblinkを使用した文書の場合、tcspingifの-tオプションの既定値は8になります。

TeX言語をおすすめできる場合とそうでない場合(私見)

f:id:zrbabbler:20200710213626p:plain

TeX言語をおすすめできる場合

  • TeX言語をやりたい場合

TeX言語をおすすめできない場合

  • それ以外全部

補足

  • もし、不幸にして、TeX言語をやる以外の手段が一切存在しない事態に陥ってしまった場合は、諦めてTeX言語しましょう。

元ネタ

☃~~~~♪(☃☃)

☃、☃☃☃☃☃!

f:id:zrbabbler:20200704161257p:plain
☃~~♪

☃☃~☃☃☃~、☃☃☃☃。

☃☃☃☃~☃、☃☃~~~~~☃、☃☃☃☃☃、☃☃☃☃☃。☃☃~☃、☃~~~☃~~~☃~~~☃☃☃~、☃☃~~☃☃~~☃☃~~☃☃☃~。☃~~~~~~~~~~~~!!

☃☃☃。

f:id:zrbabbler:20200704161535p:plain
☃~~☃~~♪(☃☃)

☃☃☃☃☃!

(☃☃☃)

メモ:Pandocでのメタデータ指定の挙動

Luaフィルタでの利用に主眼をおく1

メタデータの値の型

Luaフィルタ特有のLuaメタテーブルをもつテーブル値のことを(マニュアルに倣って)「オブジェクト(object)」と呼ぶことにする。特に、tag値がFooであるオブジェクトを「Fooオブジェクト」と呼ぶ。

  • MetaBool: 真偽値。
    • Lua真偽値で表される。
  • MetaString: 文字列。
    • Lua文字列値で表される。
  • MetaInlines: インライン要素のリスト。
    • MetaInlinesオブジェクトで表される。
    • 「インライン要素オブジェクト」のListオブジェクトとして機能する。
  • MetaBlocks: ブロック要素のリスト。
    • MetaBlocksオブジェクトで表される。
    • 「ブロック要素オブジェクト」のListオブジェクトとして機能する。
  • MetaList: メタデータ値のリスト。
    • MetaListオブジェクトで表される。
    • メタデータ値のListオブジェクトとして機能する。
    • Luaシーケンスとしても扱える。例えば、ipairs関数で列挙できる。
  • MetaMap: 文字列からメタデータ値への写像
    • MetaMapオブジェクトで表される。
    • 連想配列としてのテーブル”として扱える。例えば、pairs関数でキー値ペアを列挙できる。

※MetaInlinesやMetaBlocksも実質的にListオブジェクトなので、Luaシーケンスとして扱える。

仕様(documentedな話)

コマンド行のオプション(--metadata/-M)で指定するメタデータは必ず真偽値か文字列として扱われる。

Values will be parsed as YAML boolean or string values. If no value is specified, the value will be treated as Boolean true.

メタデータファイル(--metadata-file)んそ指定は、Pandoc’s Markdownメタデータブロックと同様に扱われる。(ただし入力形式がMarkdown以外でも使える。)

Generally, the input will be handled the same as in YAML metadata blocks.

既定値ファイル(--defaults/-d)のフィールドはコマンド行オプションに対応する。

FILE is a YAML file whose fields correspond to command-line option settings.

既定値ファイルでの設定は、コマンド行オプションによって上書きまたは拡張される。

Settings from the defaults file may be overridden or extended by subsequent options on the command line.

複数指定できるオプション(--metadataも含む)の場合は上書きではなく拡張になる。

Note that, where command-line arguments may be repeated (…), the values specified on the command line will combine with values specified in the defaults file, rather than replacing them.

メタデータブロック(またはメタデータファイル)で設定されるメタデータ値はリストやオブジェクトでもよい。文字列のスカラー値はMarkdownのソースとして解釈される。

Metadata will be taken from the fields of the YAML object and added to any existing document metadata. Metadata can contain lists and objects (nested arbitrarily), but all string scalars will be interpreted as Markdown.

実際の動作(undocumentedな話)

コマンド行オプション(--metadata/-M)

オプションで指定した値の文字列が、そのままMetaString型のメタデータ値となる2。ただし例外として、true/True/TRUE/false/False/FALSEは真偽値として解釈されて3MetaBool型のメタデータ値となる。また、値を省略した場合(-M フィールド)はMetaBool型のtrueとなる。

  • -M foo=Bar → fooの値はMetaString["Bar"]
  • -M foo=42 → fooの値はMetaString["42"](文字列)。
  • -M foo=yes → fooの値はMetaString["yes"]
  • -M foo=[42.00] → fooの値はMetaString["[42.00]"]
  • -M foo=true → fooの値はMetaBool[true]
  • -M foo=False → fooの値はMetaBool[false]
  • -M foo=truE → fooの値はMetaString["truE"](文字列!)。
  • -M foo=false,0 → fooの値はMetaString["false,0"]
  • -M foo → fooの値はMetaBool[true](値を省略)。
  • -M foo= → fooの値はMetaString[""](値が空文字列)。

同じフィールドを複数回指定した場合は、各々のメタデータ値を順に並べたMetaList値として扱われる。オプションで指定したメタデータ値がMetaMapになることは恐らくない。

  • -M foo=Baz -M foo=Bar
    → fooの値はMetaList[MetaString["Baz"],MetaString["Bar"]]
  • -M foo=0 -M foo=TRUE
    → fooの値はMetaList[MetaString["0"],MetaBool[true]]
  • -M foo.bar=54
    → foo.barというフィールドがMetaString["54"]に設定される。fooがMetaMapになるのではない。

既定値ファイル(--defaults/-d)

既定値ファイルの内容はYAMLマッピング値として解釈され、そのmetadataキーに対する値(これもマッピング値でないといけない)がメタデータとして解釈される。

  • YAMLスカラー値は全て(真偽値も含めて)MetaString型の値に変換される。
    • 文字列値(!!str型)はそのまま。
    • 真偽値(!!bool型)は、真(true/True/TRUE)はtrue、偽(false/False/FALSE)は空文字列になる。MetaBool値になるのではない
    • 数値(!!int型・!!float型)は、その典型的な文字列表現になる。intの42は42、floatの42は42.0、無限大(.inf)はInfinity、等。
    • Null値(!!null型、表記は~/null等)は空文字列になる4
  • YAMLのシーケンス値はそのままMetaList型の値になる。
  • YAMLマッピング値はそのままMetaMap型の値になる。

例えば次のような内容の既定値ファイルを指定したとする。

metadata:
  foo1: blah
  foo2: "false"
  bar1: 0x42
  bar2: 042.000
  gee1: True
  gee2: FALSE
  whiz1: [true,false]
  whie2:
  - false
  - true
  whiz3:
    boo: ! 0x42
  • foo1の値はMetaString["blah"]
  • foo2の値はMetaString["false"]。(" "囲いなのでYAMLで文字列型と見なされる。)
  • bar1の値はMetaString["66"]。(YAMLで整数の66と見なされるので)
  • bar2の値はMetaString["42.0"]
  • gee1の値はMetaString["true"]。(MetaBoolではない。)
  • gee2の値はMetaString[""]。(なぜかfalseは空になる。)
  • whiz1の値は
    MetaList[MetaString["true"],MetaString[""]]
  • whiz2の値はMetaList[MetaString[""],MetaString["true"]]
  • whiz3の値はMetaMap[("boo",MetaString["0x42"])]。(!が文字列型を強制するのでYAMLで文字列の0x42と解釈されている。)

(つづけ)


  1. はすけーる はなにもわからないので。

  2. オプションの文字列にはYAMLのルールは適用されない。例えば、42.042.00はどちらもそのままMetaStringと解釈される。

  3. これはYAMLの(真偽値と解釈されるplain scalar値の)ルールと同じ。

  4. 恐らく想定外であろうが、その他の型(!!timestampとか)のスカラー値を指定した場合も空文字列に変換される。