R Markdown での Lua フィルタ

この vignette は,rmarkdown パッケージに含まれるLuaフィルタに関する詳細な情報を提供します。 Luaフィルターの詳細については、最後のセクション に直接ジャンプすることができます。

##改ページ

ドキュメントに改ページを加えることは、rmarkdownファイルの中でカスタム出力特有の構文を使って常に可能でしたが、一つの欠点はいくつかの出力フォーマットとの互換性でした。

rmarkdown >= 1.15 および RStudio >= 1.2 (または pandoc >= 2.0) 以降では、newpage` またはpagebreakコマンドを新しい行に追加することで、以下のいずれかの形式で改ページを行うことができます。pdf_document()html_document()word_document()odt_document()` のいずれかのフォーマットで改ページを含めることができます。

# Header 1

Some text

\newpage

# Header 2 on a new page

Some other text

\pagebreak

# Header 3 on a third page

rmarkdownは、pandoc変換時に Luaフィルター を使用して、それらのコマンドを正しい出力形式の構文に変換します。

PDF/latexドキュメントでの使用 {#pdf}。

コマンドはすでに latex の構文で使用されているものなので、tex の出力文書では期待通りに動作し、pdf では期待通りに動作します。 ページブレークの追加は、rmarkdown で出力が pdf_document() または latex_document() の場合に、pandoc のバージョンに関係なくすでに可能でした。

HTMLドキュメントでの使用 {#html}。

HTML として出力される rmarkdown ドキュメントの中で \newpage\pagebreak コマンドを実行すると、デフォルトではCSSルール page-break-after を用いてインラインスタイルの html コードに変換されます 。

<div style="page-break-after: always;"></div>

これにより、常にこのdivの後にページブレークが挿入されます。

より柔軟性を高めるために、インラインスタイルの代わりに、HTMLクラスとカスタムCSSを使用することができます。 クラスを設定するには、yaml ヘッダーにメタデータフィールド newpage_html_class を追加する必要があります。

そして、次の例のように、カスタムCSSを使って動作をコントロールすることができます。

---
output: 
  html_document: default
newpage_html_class: page-break
---

```{css, echo = FALSE}
// display the pagebreak only when printing the html page
@media all {
    .page-break { display: none; }
}
@media print {
    .page-break { display: block; break-after: page; }
}
```

# Header 1

Some text

\newpage

# Header 2 on a new page

Some other text

\newpage will be converted here to

<div class="page-break"></div>

そして、チャンクに含まれるCSSからこのクラスにスタイルが適用されます。

このカスタマイズは、環境変数 PANDOC_NEWPAGE_HTML_CLASS を、ドキュメントをレンダリングする R セッション (または、.Renviron ファイルなど) で設定することでも実現できます。

この例では、page-break-after の代わりに break-after プロパティを使用していることに注意してください。 これは、現在では、代替となる前者を使用することが推奨されているためです。 後者は ブラウザとの互換性の理由 で残されています。

Word文書での使用

Word文書として出力される rmarkdown 文書の中で、\newpage\pagebreak コマンドを実行すると、Word文書用の改ページに変換されます。 手動では、rmarkdown の中に次のように追加します。

```{=openxml}
<w:p><w:r><w:br w:type="page"/></w:r></w:p>
```

例えば、ページブレイク機能を使って、作業用ドキュメントの2ページ目に最初のヘッダーを追加します。

---
title: My main title
output: word_document
---

\newpage

# First Header

ODT文書での使用

ページブレーク機能を odt_document() で使用するには、デフォルトで Pagebreak という名前の段落スタイルを含む参照ドキュメントを用意する必要があります。 この名前のついた段落スタイルは、前後に余分なスペースを入れず、そのあとにページブレークを入れる必要があります。(スタイルを作成する方法については、 libre office documentation を参照してください)。

名前付きパラグラフスタイルの名前は、yamlヘッダのnewpage_odt_styleメタデータや、PANDOC_NEWPAGE_ODT_STYLE環境変数(htmlドキュメントのように)を使ってカスタマイズできます。

先ほどの例と同様に、この例では2ページのドキュメントになり、最初のヘッダは2ページ目になります。

---
title: My main title
output: 
  odt_document:
    reference_odt: reference.odt
---

\newpage

# First Header

セクションの番号付け

セクションに番号を付ける機能は、Pandoc では限られたフォーマット(html や pdf など)でサポートされています。 rmarkdown パッケージでは、他のフォーマット(例:docx、odt など)でこの機能をサポートするために、number_sections.luaを追加しています。 ユーザーはどのフォーマットが Pandoc の機能や Lua のフィルターを使っているかを知る必要はありません。

---
title: My main title
output: 
  md_document:
    number_sections: true # implemented by Lua filter
  html_document
    number_sections: true # implemented by Pandoc
---

# First Header

## A Header Belonging the First Header

# Second Header

一般的に、セクションの番号とタイトルはスペースで区切られます。 例外として、word_document 関数では、Pandoc >= 2.10.1の docx フォーマットにおける Pandoc のセクション番号との整合性をとるために、タブで区切っています。 セクション番号のフォーマットを細かく制御したい場合は、カスタマイズした docx ファイルを用意して、それを word_document 関数の reference_docx 引数に指定します。

Luaフィルターについて

pandoc 2.0以降、Lua フィルターを使って、pandoc のドキュメント変換にいくつかの機能を追加することができます。複数の出力文書と互換性を持たせるために markdown に pagebreak コマンドを追加するのもその一つです。 Lua フィルターについては、 pandoc’s documentation に詳しい情報がありますし、a collection of Lua filters for pandoc にはいくつかの例があります。 これらの例や他の Luaフィルタは、yaml ヘッダに a pandoc argument を追加することで、Rmarkdown ドキュメントで直接使用することができます。

---
output:
  html_document:
    pandoc_args: ["--lua-filter=filter.lua"]
---

ヘッダーで yaml の !expr 構文を使った特別なヘルパーを使うこともできます。

パッケージ rmdfiltr は、Lua フィルターとそれを使うためのヘルパー関数のコレクションを提供しています。

pandoc 2.0以前は、ASTを修正するプログラムを通じて、pandoc で use filter を利用することができました。 pandoc-citeproc は引用を処理するために使われる例です。 Rを使ってフィルタを作成するには、pandocfilter というパッケージが便利です。

出力形式でフィルタを使う

特別なフィルターを使用するフォーマットを作成したい場合は、出力フォーマットに pandoc のオプションとして追加できます。

既存のフォーマットを修正する方法もあります。

custom_format <- function(...) {
  base_format <- rmarkdown::html_document(...)
  # prepending a new Lua filter to html_document() ones
  base_format$pandoc$lua_filters <- c(
    rmarkdown::pandoc_path_arg("new.lua"), 
    base_format$pandoc$lua_filters)
  base_format
}

basename(custom_format()$pandoc$lua_filters)
#> [1] "new.lua"       "pagebreak.lua" "latex-div.lua"

または、新しいフォーマットを作成することによって:

custom_format <- function(toc = TRUE, ...) {
  rmarkdown::output_format(
    knitr = rmarkdown::knitr_options(),
    # a new filter will be appended to base_format ones
    pandoc = rmarkdown::pandoc_options(to = "html", lua_filters = "new.lua"),
    base_format = rmarkdown::html_document(toc = toc, ...)
  )
}

basename(custom_format()$pandoc$lua_filters)
#> [1] "pagebreak.lua" "latex-div.lua" "new.lua"

これは上級者向けの機能なので、さらに詳しく知りたい場合は、rmarkdownbookdownpagedown などのパッケージにあるフォーマットの例を参考にすることをお勧めします。