r datatables knitr pandoc

tejer DT:: datatable sin pandoc



datatables knitr (2)

Aquí hay una solución que usa los paquetes knitr , markdown , base64enc y htmltools . Se basa en lo que sucede internamente en rmarkdown::render , pero no tiene dependencias en pandoc . Genera un archivo HTML autónomo de forma predeterminada u opcionalmente copia todas las dependencias en una carpeta. Con este último, se supone que todos los archivos CSS y JS de los que depende tienen un nombre único (es decir, no se importarán ambos si dos htmlwidgets deciden llamar a su archivo css style.css).

library("knitr") library("htmltools") library("base64enc") library("markdown") render_with_widgets <- function(input_file, output_file = sub("//.Rmd$", ".html", input_file, ignore.case = TRUE), self_contained = TRUE, deps_path = file.path(dirname(output_file), "deps")) { # Read input and convert to Markdown input <- readLines(input_file) md <- knit(text = input) # Get dependencies from knitr deps <- knit_meta() # Convert script dependencies into data URIs, and stylesheet # dependencies into inline stylesheets dep_scripts <- lapply(deps, function(x) { lapply(x$script, function(script) file.path(x$src$file, script))}) dep_stylesheets <- lapply(deps, function(x) { lapply(x$stylesheet, function(stylesheet) file.path(x$src$file, stylesheet))}) dep_scripts <- unique(unlist(dep_scripts)) dep_stylesheets <- unique(unlist(dep_stylesheets)) if (self_contained) { dep_html <- c( sapply(dep_scripts, function(script) { sprintf(''<script type="text/javascript" src="%s"></script>'', dataURI(file = script)) }), sapply(dep_stylesheets, function(sheet) { sprintf(''<style>%s</style>'', paste(readLines(sheet), collapse = "/n")) }) ) } else { if (!dir.exists(deps_path)) { dir.create(deps_path) } for (fil in c(dep_scripts, dep_stylesheets)) { file.copy(fil, file.path(deps_path, basename(fil))) } dep_html <- c( sprintf(''<script type="text/javascript" src="%s"></script>'', file.path(deps_path, basename(dep_scripts))), sprintf(''<link href="%s" type="text/css" rel="stylesheet">'', file.path(deps_path, basename(dep_stylesheets))) ) } # Extract the <!--html_preserve--> bits preserved <- extractPreserveChunks(md) # Render the HTML, and then restore the preserved chunks html <- markdownToHTML(text = preserved$value, header = dep_html) html <- restorePreserveChunks(html, preserved$chunks) # Write the output writeLines(html, output_file) }

Esto se puede llamar así:

render_with_widgets("testing.Rmd")

Esto debería funcionar para cualquier htmlwidgets, incluso en combinación. Ejemplo:

TestWidgets.Rmd

--- title: "TestWidgets" author: "Nick Kennedy" date: "5 August 2015" output: html_document --- First test a dygraph ```{r} library(dygraphs) dygraph(nhtemp, main = "New Haven Temperatures") %>% dyRangeSelector(dateWindow = c("1920-01-01", "1960-01-01")) ``` Now a datatable ```{r} library(DT) datatable(iris, options = list(pageLength = 5)) ``` ```{r} library(d3heatmap) d3heatmap(mtcars, scale="column", colors="Blues") ```

Y luego desde R

render_with_widgets("TestWidgets.Rmd")

Estoy tratando de usar DT::datatable para generar una tabla interactiva con buen formato en R.

... el único problema es que quiero un trabajo heroku para tejer el documento para mí, y he aprendido que RStudio y rmarkdown::render() usan pandoc debajo del capó, pero Pandoc no se envía en el desmantelado R Buildpack para heroku.

¿Hay alguna manera de obtener el motor de knitr:knit2html ( knitr:knit2html o markdown:markdownToHTML ) para pasar el javascript que datatable través de datatable ? ¿O para ser más precisos, generar la siguiente tabla de muestra sin usar pandoc?

Aquí hay un ejemplo mínimo:

testing.Rmd

--- title: "testing" output: html_document --- this is a datatable table ```{r test2, echo=FALSE} library(DT) DT::datatable( iris, rownames = FALSE, options = list(pageLength = 12, dom = ''tip'') ) ``` this is regular R output ```{r} head(iris) ```

knit_test.R

require(knitr) knitr::knit2html(''testing.Rmd'')

genera:

this is a datatable table <!–html_preserve–> <!–/html_preserve–> this is regular R output head(iris) ## Sepal.Length Sepal.Width Petal.Length Petal.Width Species ## 1 5.1 3.5 1.4 0.2 setosa ## 2 4.9 3.0 1.4 0.2 setosa ## 3 4.7 3.2 1.3 0.2 setosa ## 4 4.6 3.1 1.5 0.2 setosa ## 5 5.0 3.6 1.4 0.2 setosa ## 6 5.4 3.9 1.7 0.4 setosa

Comportamiento deseado: hacer que mi datatable llegue (no <!–html_preserve–> )

lo que probé , miré htmltools y htmlPreserve pero no pude encontrar la forma de aplicarlo aquí. Hizo algunas cosas locas con saveWidget que no fue exitoso y no se repite.

¡Gracias!


Un poco de una categoría algunas cosas locas con saveWidget pero si puedes usar el paquete XML (necesitarás cedro-14 para eso) algo como lo siguiente debería hacer el truco:

#'' http://.com/q/31645528/1560062 #'' #'' @param dt datatables object as returned from DT::datatable #'' @param rmd_path character path to the rmd template #'' @param libdir path to the directory with datatable static files #'' @param output_path where to write output file #'' process <- function(dt, rmd_path, libdir, output_path) { widget_path <- tempfile() template_path <- tempfile() # Save widget and process Rmd template DT::saveWidget(dt, widget_path, selfcontained=FALSE) knitr::knit2html(input=rmd_path, output=template_path) # Parse html files widget <- XML::htmlParse(widget_path) template <- XML::htmlParse(paste0(template_path, ".html")) # Extract elements from the body of widget file widget_container <- XML::getNodeSet( widget, "/html/body/div[@id = ''htmlwidget_container'']") body_scripts <- XML::getNodeSet(widget, "/html/body/script") # Make sure we point to the correct static dir # Using lapply purely for side effect is kind of # wrong but it is cheaper than a for loop if we use :: correct_libdir <- function(nodeset, attr_name) { lapply(nodeset, function(el) { src <- XML::xmlAttrs(el)[[attr_name]] XML::xmlAttrs(el)[[attr_name]] <- file.path( libdir, sub("^.*?/", "", src)) }) nodeset } # Extract script and link tags, correct paths head_scripts <- correct_libdir( XML::getNodeSet(widget, "/html/head/script"), "src") head_links <- correct_libdir( XML::getNodeSet(widget, "/html/head/link"), "href") # Get template root root <- XML::xmlRoot(template) # Append above in the right place root[[2]] <- XML::addChildren(root[[2]], widget_container) root[[2]] <- XML::addChildren(root[[2]], body_scripts) root[[1]] <- XML::addChildren(root[[1]], head_scripts) root[[1]] <- XML::addChildren(root[[1]], head_links) # Write output XML::saveXML(template, output_path) }