9.6 カスタムブロック (*)

bookdown 本の 2.7節 では, どうすれば R Markdown でブロックの見た目をカスタマイズできるかを話しました. これはレポートや本の中でコンテンツを目立たせる便利な方法で, 読者があなたの著作の中の要点を確実に取りせるようにできます. これらのブロックの使い方の例として, 次のようなものがあります.

  • あなたの分析コードを実行する前に, ユーザが最新のパッケージを使用しているか確認するための警告メッセージを表示する.
  • ソースコードのある GitHub リポジトリへのリンクを文書の冒頭に追加する.
  • あなたの分析から得られた要点や知見を強調する.

この節では PDF と HTML の両方でカスタムブロックを作成する方法を説明します. どちらのフォーマットでも R Markdown 上で同じ整形の構文を使用できますが, 要求される設定は異なります.

9.6.1 構文

カスタムブロックの構文は Pandoc の fenced Div blocks に基づいています. Div ブロックはとても強力ですが1つだけ問題があります. これはおもに HTML 出力に対して動作しますが, LaTeX 出力に対しては動作しないことです.

バージョン 1.16 以降の rmarkdown パッケージは Div ブロックを HTML と LaTeX どちらに対しても変換するようになりました. HTML 出力に対してはブロックの全ての属性が <div> タグの属性になります. 例えば Div は ID (# の後のに続くもの), 1つまたは複数のクラス (クラス名は . の後に書かれるものです), そしてそれ以外の属性を持ちます. 以下の Div ブロック,

::: {#hello .greeting .message style="color: red;"}
Hello **world**!
:::

は以下の HTML コードに変換されます.

<div id="hello" class="greeting message" style="color: red;">
  Hello <strong>world</strong>!
</div>

LaTeX 出力に対しては, 最初のクラス名が LaTeX 環境名として使われます. また, Div ブロックに data-latex と名付けた属性を与え, 環境の引数としましょう. 環境が引数を必要としないなら, この属性は空白にすることができます. 2つの単純な例を以下にお見せします. 1つ目の例は LaTeX で verbatim 環境を使用します. これは引数を必要としません.

::: {.verbatim data-latex=""}
ここに _verbatim_ テキストを表示.
:::

LaTeX 出力はこうなります.

\begin{verbatim}
ここに \emph{verbatim} テキストを表示.
\end{verbatim}

ブロックが HTML へと変換される場合は, HTML コードはこのようになります.

<div class="verbatim">
ここに <em>verbatim</em> テキストを表示.
</div>

2つ目の例では centerminipage 環境を使い, ページ幅の半分の大きさに中央揃えしたボックス内にテキストを表示しています.

:::: {.center data-latex=""}

::: {.minipage data-latex="{.5\linewidth}"}
この段落は中央揃えされ, 親要素の半分の幅で表示されます.
:::

::::

center ブロックの中に minipage ブロックをネストしていることに注意してください. 親ブロックに子ブロックを入れるには, さらにコロンが必要です. 上記の例では center ブロックに4つのコロンを使用していますが, 5個以上書くことも可能です. 2つのブロックは以下の LaTeX コードに変換されます.

\begin{center}
\begin{minipage}{.5\linewidth}
この段落は中央揃えされ, 親要素の半分の幅で表示されます.
\end{minipage}
\end{center}

HTML 出力では, ユーザーの好みで CSS によって <div> ブロックの外見を定義することもできます. LaTeX 出力の場合は, 環境が未定義ならば \newenvironment を, 既存の環境を再定義するならば \renewenvironment コマンドを LaTeX 上で使うこともできます. LaTeX 上での定義で PDF 上でのブロックの見た目を決定できます. これらのカスタマイズは通常は style.csspreamble.tex といったファイルを内に記述して, YAML オプションで読み込みます.

---
output:
  html_document:
    css: style.css
  pdf_document:
    includes:
      in_header: preamble.tex
---

次に, CSS ルールや LaTeX 環境を使用したいくつか発展的なカスタムブロックの実例をお見せします. さらなる使用例としては, 5.8節に, 多段組みレイアウト内で複数ブロックを並べるものがあります.

9.6.2 影付きブロックを追加する

まず, 影付きボックスの内部にコンテンツを入れる方法を紹介します. ボックスは黒の背景色とオレンジ色の枠があり, 角は丸めます. ボックス内のテキストは白色です.

HTML 出力に対しては, CSS ファイル内でそのルールを定義します. CSSにあまり詳しくなくても, 無料で見られるオンラインチュートリアルが豊富にあります. 例えば https://www.w3schools.com/css/ とか33.

.blackbox {
  padding: 1em;
  background: black;
  color: white;
  border: 2px solid orange;
  border-radius: 10px;
}
.center {
  text-align: center;
}

LaTeX 出力に対しては, LaTeX パッケージの framed を基にして blackbox という名前で新しい環境を作成し, 黒い背景色と白い文字色にします.

\usepackage{color}
\usepackage{framed}
\setlength{\fboxsep}{.8em}

\newenvironment{blackbox}{
  \definecolor{shadecolor}{rgb}{0, 0, 0}  % black
  \color{white}
  \begin{shaded}}
 {\end{shaded}}

本書で framed パッケージを使うのはこれがかなり軽量だからですが, このパッケージは色付きで角の丸い枠を描画することができません. それを実現するには, より洗練された LaTeX パッケージである tcolorblox (https://ctan.org/pkg/tcolorbox)が必要です. このパッケージには影付きボックスを作るためのとても柔軟な一連のオプションがあります. パッケージのドキュメントからは多くの使用例を見ることができます. 以下の LaTeX 環境は上記の CSS の例と似た影付きボックスを作成できます.

\usepackage{tcolorbox}

\newtcolorbox{blackbox}{
  colback=black,
  colframe=orange,
  coltext=white,
  boxsep=5pt,
  arc=4pt}

これで PDF と HTML 出力の両方のフォーマットでカスタムボックスを使用できるようになりました. ボックスのソースコードはこのようになります.

:::: {.blackbox data-latex=""}
::: {.center data-latex=""}
**注意!**
:::

この**新しい注意書き**を見てくれてありがとう! あなたがこれを見ていることは監視されており, 当局に報告される!
::::

出力はこうなります.

注意!

この新しい注意書きを見てくれてありがとう! あなたがこれを見ていることは監視されており, 当局に報告される!

9.6.3 アイコンを加える

カスタムボックス内に画像を含めることで, より見た目で注意を引く作りにできます. 画像はブロックの内容をより効果的に伝える方法にもなりえます. 以下に続く例では, 次のようなディレクトリ構造で動作させるという前提にしています. これは本書を作成するために使ったものを簡略化したものです.

  • directory/
    • your-report.Rmd
    • style.css
    • preamble.tex
    • images/
      • important.png
      • note.png
      • caution.png
      • ...

全体がどのように動作するかを説明する前に, この例のソースコードと出力をお見せしましょう.

::: {.infobox .caution data-latex="{caution}"}
**注意!**

この**新しい注意書き**を見てくれてありがとう! あなたがこれを見ていることは監視されており, 当局に報告される!
:::

出力はこうなります.

注意!

この新しい注意書きを見てくれてありがとう! あなたがこれを見ていることは監視されており, 当局に報告される!

HTML 出力では, CSS の background-image プロパティ内にボックスの画像を追加することができます. 背景に画像を挿入し, 左側に十分な幅のパディングを追加することでテキストと画像の重なりを避けます. ローカルの画像ファイルを使用するなら, ファイルパスは CSS との相対パスで与えます. これが例です.

.infobox {
  padding: 1em 1em 1em 4em;
  margin-bottom: 10px;
  border: 2px solid orange;
  border-radius: 10px;
  background: #f5f5f5 5px center/3em no-repeat;
}

.caution {
  background-image: url("images/caution.png");
}

ブロックに .infobox.caution という2つのクラス名を使用していることに注意してください. infobox クラスは色付きの外枠のある影付きボックスを定義するのに使用し, caution クラスは画像を入れるために使用されています. 2つのクラスを使用する利点は影付きボックスの設定を繰り返すことなく, いろいろなアイコンの付いたブロックを定義できるということです. 例えば, warning のボックスが必要ならば, .infobox のルールを繰り返し書くことなく, 以下のように定義するだけで十分です.

.warning {
  background-image: url("images/warning.png");
}

すると以下の Markdown ソースコードで warning ボックスを作成できます.

:::: {.infobox .warning data-latex="warning"}

実際のコンテンツをここに表示

::::

PDF 出力に対しては, 以前の例で定義した blackbox 環境を基に infobox 環境を作成し, ボックスの左側に画像を追加できます. LaTeX 環境に画像を追加する方法はいくつもあります. これはそのうちの1つにすぎません. なお, これは上記の CSS で定義したスタイルを正確に再現するものではありません.

\newenvironment{infobox}[1]
  {
  \begin{itemize}
  \renewcommand{\labelitemi}{
    \raisebox{-.7\height}[0pt][0pt]{
      {\setkeys{Gin}{width=3em,keepaspectratio}
        \includegraphics{images/#1}}
    }
  }
  \setlength{\fboxsep}{1em}
  \begin{blackbox}
  \item
  }
  {
  \end{blackbox}
  \end{itemize}
  }

以下に, 様々なアイコンを付けたブロックを掲載します.

注意!

この新しい注意書きを見てくれてありがとう! あなたがこれを見ていることは監視されており, 当局に報告される!

注意!

この新しい注意書きを見てくれてありがとう! あなたがこれを見ていることは監視されており, 当局に報告される!

注意!

この新しい注意書きを見てくれてありがとう! あなたがこれを見ていることは監視されており, 当局に報告される!

注意!

この新しい注意書きを見てくれてありがとう! あなたがこれを見ていることは監視されており, 当局に報告される!

代替案として, LaTeX パッケージの awesomebox を使って PDF にアイコン付きのボックスを生成することもできます. このパッケージがあれば非常に多くのアイコンを選ぶことができます. 以下に簡単な例をお見せします. 使用可能な LaTeX 環境と引数についてはパッケージのドキュメントを参照してください.

---
title: Awesome Boxes
output:
  pdf_document:
    latex_engine: lualatex
    extra_dependencies: awesomebox
documentlass: ltjsarticle
mainfont: Noto Serif CJK JP
sansfont: Noto Sans CJK JP
---

"note" 型のボックス:

::: {.noteblock data-latex=""}
この**新しい注意書き**を見てくれてありがとう! あなたがこれを見ていることは監視されており, あなたがこれを見ていることは監視されており, _当局に報告される_!
:::

このボックスの引数を生成するための R 関数 `box_args()` を定義しました.

```{r}
box_args <- function(
  vrulecolor = 'white',
  hrule = c('\\abLongLine', '\\abShortLine', ''),
  title = '', vrulewidth = '0pt',
  icon = 'Bomb', iconcolor = 'black'
) {
  hrule <- match.arg(hrule)
  sprintf(
    '[%s][%s][\\textbf{%s}]{%s}{\\fa%s}{%s}',
    vrulecolor, hrule, title, vrulewidth, icon, iconcolor
  )
}
```

インライン R コード内で `awesomeblock` 環境に引数を与えます.

::: {.awesomeblock data-latex="`r box_args(title = '注意!')`"}
この**新しい注意書き**を見てくれてありがとう!

あなたがこれを見ていることは監視されており, _当局に報告される_!
:::

訳注: 翻訳者の開発した rmdja パッケージでは, デフォルトでこの節で紹介されているようなカスタムブロックが定義されており, より簡単にアイコン付きブロックを記述できます. 詳細はこのパッケージのドキュメントをご覧ください.


  1. 訳注: このサイト相当の日本語のサイトを翻訳者は知らないので Moziila のサイトなどを参考にしてください https://developer.mozilla.org/ja/docs/Learn/Getting_started_with_the_web/CSS_basics (一部未翻訳のページもあるかもしれません)↩︎