---
title: "Lua filters in R Markdown"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{lua-filters}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

## Pagebreaks

Adding a pagebreak in document was always possible using custom output specific syntax in a rmarkdown file but one drawback was the compatibility with several output format.

Since rmarkdown >= 1.15 and with RStudio >= 1.2 (or with pandoc >= 2.0), it is possible to add a `\newpage` or `\pagebreak` command in a new line to include a pagebreak in any of these formats: `pdf_document()`, `html_document()`, `word_document()` and `odt_document()`. 

```md
# Header 1

Some text

\newpage

# Header 2 on a new page

Some other text

\pagebreak

# Header 3 on a third page

```

rmarkdown will convert those commands in the correct output format syntax using a [lua filter](#lua-filter) during pandoc conversion. 

### Using with PDF/ latex documents {#pdf}

As the commands are the ones already used in latex syntax, this works as expected in a tex output document, and thus with pdf. Adding a pagebreak was already possible with rmarkdown when output is `pdf_document()` or `latex_document()`, without any restriction about the version of pandoc.

### Using with HTML documents {#html}

A `\newpage` or `\pagebreak` command in a rmarkdown document with output as HTML will be converted by default in this html code with inline style using CSS rule [`page-break-after`](https://developer.mozilla.org/en-US/docs/Web/CSS/page-break-after)

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

This will always insert a pagebreak after this div. 

To get more flexibility, you can use a HTML class and some custom CSS instead of an inline style. You need to add a metadata field `newpage_html_class` in your yaml header to set the class.

Then you can control the behavior using custom CSS as in this example

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

```{css, echo = FALSE}`r ''`
// 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 

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

and the style will be applied to this class from the CSS included in the chunk. 

This customisation can also be achieved by setting the environnement variable `PANDOC_NEWPAGE_HTML_CLASS` in the R session that will render the document (or in `.Renviron` file for example)

Let's note that in this example we use [`break-after`](https://developer.mozilla.org/en-US/docs/Web/CSS/break-after) property instead of `page-break-after` as it is recommended now to use the former which is the replacement. The latter is kept around for [compatibility reason with browsers](https://caniuse.com/#search=page-break).

### Using with Word documents {#word}

A `\newpage` or `\pagebreak` command in a rmarkdown document with output as Word document will be converted in a pagebreak for word document. Manually, this would mean adding this in your rmarkdown

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

For example, using the pagebreak feature, this will add the first header in the second page of the work document

````md
---
title: My main title
output: word_document
---

\newpage

# First Header
````

### Using with ODT documents {#odt}

To use the pagebreak feature with `odt_document()`, you need to provide a reference document that includes a paragraph style with, by default, the name _Pagebreak_. This named paragraph style should have no extra space before or after and have a pagebreak after it. (see [libre office documentation](https://help.libreoffice.org/Writer/Text_Flow) on how to create a style). 

The name of the named paragrah style could be customized using `newpage_odt_style` metadata in yaml header or `PANDOC_NEWPAGE_ODT_STYLE` environment variable (as in [html document](#html)).

As the previous one, this example will lead to a two pages document, with first header on the second page.

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

\newpage

# First Header
````


## About lua filters {#lua-filter}

Since pandoc 2.0, it is possible to use lua filters to add some extra functionality to pandoc document conversion. Adding a pagebreak command in markdown to be compatible with several output documents is one of them. You can find some more informations about lua filters in [pandoc's documentation](https://pandoc.org/lua-filters.html) and also some examples in [a collection of lua filters for pandoc](https://github.com/pandoc/lua-filters). These examples, and any other lua filters, can be use in your Rmarkdown document directly by adding [a pandoc argument](https://bookdown.org/yihui/rmarkdown/html-document.html#pandoc-arguments) in yaml header

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

The package [rmdfiltr](https://github.com/crsh/rmdfiltr) provides a collection of lua filters and helpers functions to use them.

Before pandoc 2.0, [using filter](https://pandoc.org/filters.html) with pandoc was already available through programs that modifies the AST. `pandoc-citeproc` is an example used to deal with citations. The package [pandocfilter](https://cran.r-project.org/package=pandocfilters) is useful to create filters using R.
