R Markdownを利用していると,htmlタグをRのコードで生成できればと思うことがあるかと思います。ShinyのUIを作るときや,RmdでWebサイトを作成しているとこれが頻出します。そんな時はhtmltoolsパッケージが便利です。
htmltoolsにはRでhtmlなどのタグを生成するのに便利な関数がたくさん収められています。非常にたくさんの関数があるのですが,ドキュメントが整備されていなかったり内容が複雑だったりして,正直手探りな感じです。なので今回はあまり深追いせずに簡単なところだけ紹介します。
今回使うパッケージを読みこんどきます:
library(htmltools)
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
tags
リスト
tags
はhtmltoolsパッケージに格納されているリストで,以下のような要素が入っています:
names(tags)
## [1] "a" "abbr" "address" "area" "article"
## [6] "aside" "audio" "b" "base" "bdi"
## [11] "bdo" "blockquote" "body" "br" "button"
## [16] "canvas" "caption" "cite" "code" "col"
## [21] "colgroup" "command" "data" "datalist" "dd"
## [26] "del" "details" "dfn" "div" "dl"
## [31] "dt" "em" "embed" "eventsource" "fieldset"
## [36] "figcaption" "figure" "footer" "form" "h1"
## [41] "h2" "h3" "h4" "h5" "h6"
## [46] "head" "header" "hgroup" "hr" "html"
## [51] "i" "iframe" "img" "input" "ins"
## [56] "kbd" "keygen" "label" "legend" "li"
## [61] "link" "mark" "map" "menu" "meta"
## [66] "meter" "nav" "noscript" "object" "ol"
## [71] "optgroup" "option" "output" "p" "param"
## [76] "pre" "progress" "q" "ruby" "rp"
## [81] "rt" "s" "samp" "script" "section"
## [86] "select" "small" "source" "span" "strong"
## [91] "style" "sub" "summary" "sup" "table"
## [96] "tbody" "td" "textarea" "tfoot" "th"
## [101] "thead" "time" "title" "tr" "track"
## [106] "u" "ul" "var" "video" "wbr"
htmlに触れたことがある方は,この出力で察しがつくと思います。ひとつ出してみます:
tags$div
## function (...)
## tag("div", list(...))
## <environment: namespace:htmltools>
ここに格納されているのは**tag
関数**で,今回後ろに括弧をつけてなかったので関数のコードが出てきています。では引数を与えてみます:
kosaki <- tags$div(class = "section")
これで生成されたものをチェックします:
as.character(kosaki)
## [1] "<div class=\"section\"></div>"
引数に指定した属性が組み込まれたdivタグ生成されています。でもこれはただのcharacter型オブジェクトではなく,タグ用のオブジェクトになっています:
class(kosaki)
## [1] "shiny.tag"
なお,これのベースはlist型です:
is.list(kosaki)
## [1] TRUE
細かいところは省略します。
タグで挟みこむ要素を与える
p
タグなどでは文字列を挟み込めないと意味がありません。もちろん可能です:
paragraph <- "終末何してますか?忙しいですか?救ってくれますか?"
tags$p(paragraph) %>% as.character()
## [1] "<p>終末何してますか?忙しいですか?救ってくれますか?</p>"
要するに,属性を指定せずにそのまま渡せばこんな感じで挟みこむようになります。
入れ子構造のhtmlを生成
tag関数を入れ子構造にするとうまくいきます:
kutori <- tags$div(id = "hoge",
tags$h2("サブタイトル"),
tags$p(paragraph),
tags$ul(
tags$li("箇条書き1"),
tags$li("箇条書き2")
)
)
as.character(kutori) %>% cat()
## <div id="hoge">
## <h2>サブタイトル</h2>
## <p>終末何してますか?忙しいですか?救ってくれますか?</p>
## <ul>
## <li>箇条書き1</li>
## <li>箇条書き2</li>
## </ul>
## </div>
なお,この場合ですとkutori
をR Markdown内のRチャンクでそのまま出力させると,ちゃんとhtmlタグとして出力されてブラウザでhtmlとして読み込まれます。普通の文字列を生成するRコードで作ってしまうと,<code>
タグで挟まれてしまうため,ブラウザでhtmlとして読み込まれません。これを解消するものだと考えてください。
応用例
htmlタグ生成をプログラミング
lapply
やmapply
を利用して,一気に生成することも可能です。なおtagList()
はこれらtag
によって生成されたオブジェクトをリストとしてまとめてくれるものです:
f_kutori <- function(title, list_c) {
tagList(tags$h2(title),
tags$ul(
lapply(list_c, tags$li)
)
)
}
f_kutori("タイトル", c("終末何してますか?", "忙しいですか?", "救ってくれますか?")) %>%
as.character() %>%
cat()
## <h2>タイトル</h2>
## <ul>
## <li>終末何してますか?</li>
## <li>忙しいですか?</li>
## <li>救ってくれますか?</li>
## </ul>
このように,今まで慣れ親しんできたRの関数を絡めていくこともできます。また,htmlwidgets系は生成されたオブジェクトをそのままhtmlオブジェクトとして使えますので,うまく活用することもできます。
これらを駆使すれば,shinyやRmdによる表現力,および苦労が大きく変化します。ぜひ試してみてください。
Enjoy!