R Markdown と reveal.js でスライドを作る際につまづいたこと

R の [revealjs](https://github.com/rstudio/revealjs) ライブラリ（R Markdown で [reveal.js](https://revealjs.com/) を用いた HTML スライドを作成するライブラリ）の使い方を勉強したので、そのときにつまづいたことをメモ。細かいところにこだわろうとすると結構難しい……

# スライドのループを防ぐ

[@kazutan](https://qiita.com/kazutan) さんの [R Markdown 入門](https://kazutan.github.io/kazutanR/Rmd_intro.html#faq7) に詳しく書かれていますが、スライドのヘッダが被るとループします。特に注意が必要なのがヘッダに日本語と ASCII 文字を混ぜて書いている場合で、ASCII 文字だけを取り出してできる文字列が被らないように設定しないとスライドがループします。

以下の例だと、一見 `ほげX` と `ぴよX` は別の文字列なので被っていないように見えますが、内部的には ASCII 文字だけが取り出されてどちらも `X` になるためループが発生します。

```md:スライドがループする例
## ほげX

* aaa
* bbb

## ぴよX

* xxx
* yyy
```

参考：[RStudioの"knit HTML"でPandocに送っている内容 - 5行目: 入力するファイル形式の指定](https://qiita.com/kazutan/items/eb15a42607f87f57b525#5%E8%A1%8C%E7%9B%AE-%E5%85%A5%E5%8A%9B%E3%81%99%E3%82%8B%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%BD%A2%E5%BC%8F%E3%81%AE%E6%8C%87%E5%AE%9A)

現象としては、以下のようなことが起こっています。

1. knit すると Pandoc がヘッダに基づいてスライドに ID を割り当てようとする（`auto_identifiers`）が、
2. 割り当ての際に ASCII 文字以外を削除する処理（`ascii_identifiers`）が走り、
3. 削除された結果スライドの ID が重複し、
4. 重複した ID に基づいて reveal.js がスライドを遷移させるため、
5. スライドがループする。

参考：[Pandoc ユーザーズガイド 日本語版 - HTML, LaTeX, そしてConTeXtにおけるヘッダ識別子](http://sky-y.github.io/site-pandoc-jp/users-guide/#header-identifiers-in-html-latex-and-context) の `auto_identifiers`
参考：[Pandoc ユーザーズガイド 日本語版 - Pandoc標準以外の拡張](http://sky-y.github.io/site-pandoc-jp/users-guide/#non-pandoc-extensions) の `ascii_identifiers`

解決策として、[@kazutan](https://qiita.com/kazutan) さんの [R Markdown 入門](https://kazutan.github.io/kazutanR/Rmd_intro.html#faq7) では `ascii_identifiers` を無効化しています。私はこの方法では上手く行かなかったので、別の方法として `auto_identifiers` 自体を無効化しました。`auto_identifiers` を無効化すると ID が割り振られなくなりますが、別に ID がなくてもスライドの遷移自体は問題なくできます。

```yaml:rmd冒頭のYAML
---
output:
  revealjs::revealjs_presentation:
    pandoc_args: [
      '--from', 'markdown-auto_identifiers'
    ]
---
```

# 特定のスライドだけ上下中央揃えにする

YAML で `center` オプションを `true` にすれば全スライドの上下中央揃えを有効にすることはできますが、特定のスライドだけ上下中央揃えにすることはできません。

```yaml:rmd冒頭のYAML
---
output:
  revealjs::revealjs_presentation:
    center: true
---
```

特定のスライドだけ上下中央揃えにするためには、上下中央揃えにしたいスライドの `<section>` タグに `center` クラスを追加します。rmarkdown 上で追加するには以下のように書きます。

```md
# header {class="center"}
```

参考：[Pandoc ユーザーズガイド 日本語版 - HTML, LaTeX, そしてConTeXtにおけるヘッダ識別子](http://sky-y.github.io/site-pandoc-jp/users-guide/#header-identifiers-in-html-latex-and-context)

ただし、この方法だとスライドの表紙（YAML の `title` や `author` で指定した値が出力されるスライド）を上下中央揃えにすることができません。上手い解決方法が見つからなかったので、取り急ぎ動的に `center` クラスを追加する JavaScript を書いて `<head>` 内に挿入することにしました……かなり苦肉の策ですが。

```yaml:rmd冒頭のYAML
---
output:
  revealjs::revealjs_presentation:
    includes:
      in_header: header.html
---
```

```html:header.html
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
    var sections = document.querySelectorAll("div.reveal section:first-of-type, div.reveal section.titleslide");
    for (var i = 0; i < sections.length; i++) {
        sections[i].setAttribute("class", "center " + sections[i].getAttribute("class"));
    }
});

window.onload = function() {
    document.querySelector("body").setAttribute("style", "display: block;")
}
</script>

<style type="text/css">
body {
    display: none;
}
</style>
```

動的に `center` クラスを追加すると上下中央揃えになるまで若干の遅延があり画面がチラつくので、チラつき防止のために `<body>` タグをいったん非表示にして後から表示に切り替えるよう工夫しています。

参考：[Presentations with reveal.js - Advanced Customization](https://rmarkdown.rstudio.com/revealjs_presentation_format.html#advanced_customization)

# テーマをいじる

YAML の `theme` オプションで指定したテーマに対応する CSS をダウンロード（[reveal.js/css/theme/](https://github.com/hakimel/reveal.js/tree/master/css/theme)）し、それを見ながらいじりたい部分を上書きする CSS ファイルを作ります。あとは YAML の `css` オプションにそのファイルを指定するだけ。

```yaml:rmd冒頭のYAML
---
output:
  revealjs::revealjs_presentation:
    theme: simple
    css: style.css
---
```

参考：[R Presentationの書式設定について](https://qiita.com/kazutan/items/017bcdf5f9beedc170f1)

# 共有フォルダ上に置いても正しく開けるようにする

3連休に R Markdown でスライドを作れるようになったので休み明けに早速打合せ資料を作って社内のイントラネット上の共有フォルダに置いたのですが、残念なことに Internet Explorer 11（社内標準）では正しく開けないと怒られてしまいました……

これは HTML ファイル全般で起こりうる現象なのですが、原因は IE が共有フォルダ上の HTML ファイルを互換表示で表示することです。互換表示は IE 7 相当なので、reveal.js が正しく動作せず表示が崩れます。

デフォルト設定では、イントラネット内にある Web サイトは互換表示で表示することになっています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/51798/afc95019-0867-06f1-a466-2674a1e3409d.png)

解決するためには、IE を開いて [ツール] > [互換表示設定] > [イントラネットサイトを互換表示にする] のチェックを外してください。その代わり社内システムは動かなくなるかもしれませんが……

久々に IE にムカついてしまった……(´・ω・｀)

# 参考情報

* [R Markdown入門](https://kazutan.github.io/kazutanR/Rmd_intro.html)
* [Presentations with reveal.js](https://rmarkdown.rstudio.com/revealjs_presentation_format.html)
* [Pandoc ユーザーズガイド 日本語版](http://sky-y.github.io/site-pandoc-jp/users-guide/)