Pandocで出力形式に依存せず見出し番号をつけたり、第1章とか第1.1節とか装飾したい

カテゴリ: pandoc

昨日はHTML出力の場合に限って、見出し番号の装飾方法を紹介しました。

PandocでHTML出力時に見出し番号を第1章とか第1.1節とかしたい

ただ、昨日の段階ではどの方法も一長一短だったので、 今日は任意の出力に対応するLuaフィルタを用意しました。

Luaフィルタが何ものかは↓でも読んでください。

Luaフィルタがアツイ2020

やり方

Luaフィルタをダウンロード

↓からダウンロードできます

https://raw.githubusercontent.com/atusy/lua-filters/master/lua/number-sections.lua

コマンドを使うなら

wget -qO number-sections.lua https://raw.githubusercontent.com/atusy/lua-filters/master/lua/number-sections.lua

変換したい文章を用意

Markdownの場合、章番号を装飾したり、章番号をずらしたりするのも簡単です。 ↓のようにYAMLを指定しましょう。

---
number_sections_with_decorations:
    - '第%s章'
    - '第%s節'
number_offset: 3
---

# A

## A-1

# B

## B-1

number_sections_with_decorationsには 見出しレベル順にフォーマットを記述します。 %sとした部分が見出し番号で置換される点に注意してください。 省略したレベルに関してはそのままの値が出力されます。

number_sections_with_decorationsって長いので将来的には名前変わるかも?

Pandocを実行

先程の文書がexample.mdに保存されているとし、gfmに出力してみましょう。

pandoc example.md \
       -t gfm \
       --lua-filter number-sections.lua

結果

ちゃんとmarkdown出力であっても章番号がついてますね。

# 第3章 A

## 第3.1節 A-1

# 第4章 B

## 第4.1節 B-1

おまけ

HTML出力で目次をつけてみる
pandoc example.md \
       -t html \
       --standalone \
       --toc \
       --metadata="title: example" \
       --lua-filter number-sections.lua
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="pandoc" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title> example</title>
  <style>
    html {
      line-height: 1.5;
      font-family: Georgia, serif;
      font-size: 20px;
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      word-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 1em;
      }
    }
    @media print {
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
      font-size: 85%;
      margin: 0;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      background-color: #1a1a1a;
      border: none;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    span.underline{text-decoration: underline;}
    div.column{display: inline-block; vertical-align: top; width: 50%;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    ul.task-list{list-style: none;}
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
  </style>
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title"> example</h1>
</header>
<nav id="TOC" role="doc-toc">
<ul>
<li><a href="#a"><span class="header-section-number">第3章</span> A</a>
<ul>
<li><a href="#a-1"><span class="header-section-number">第3.1節</span> A-1</a></li>
</ul></li>
<li><a href="#b"><span class="header-section-number">第4章</span> B</a>
<ul>
<li><a href="#b-1"><span class="header-section-number">第4.1節</span> B-1</a></li>
</ul></li>
</ul>
</nav>
<h1 data-number="第3章" id="a"><span class="header-section-number">第3章</span> A</h1>
<h2 data-number="第3.1節" id="a-1"><span class="header-section-number">第3.1節</span> A-1</h2>
<h1 data-number="第4章" id="b"><span class="header-section-number">第4章</span> B</h1>
<h2 data-number="第4.1節" id="b-1"><span class="header-section-number">第4.1節</span> B-1</h2>
</body>
</html>

Enjoy!