2015-07-27 41 views
13

बिना datatable मैं आरबुनना डीटी :: pandoc

में एक ठीक से स्वरूपित, इंटरैक्टिव टेबल उत्पादन के लिए DT::datatable उपयोग करने के लिए कोशिश कर रहा हूँ ... केवल समस्या यह है कि मैं एक Heroku काम मेरे लिए दस्तावेज़ बुनी करना चाहते हैं, और मैंने सीखा है कि रुस्टूडियो और rmarkdown::render() हुड के नीचे पैंडोक का उपयोग करें - लेकिन पैंडोक उसके पोकोक के लिए R Buildpack को छीनने में नहीं भेजता है।

क्या datatable शक्तियों को पार करने वाले जावास्क्रिप्ट को पास करने के लिए पुराने मार्कडाउन इंजन (knitr:knit2html या markdown:markdownToHTML) प्राप्त करने का कोई तरीका है? या अधिक सटीक होने के लिए, के नीचे नमूना तालिका उत्पन्न करने के लिए पैंडोक का उपयोग कर?

यहाँ एक न्यूनतम उदाहरण है:

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') 

उत्पन्न करता है:

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 

वांछित व्यवहार: मेरे datatable के माध्यम से आ (नहीं <!–html_preserve–>)

मैं क्या कोशिश की है मैं htmltools को देखा और htmlPreserve सामान लेकिन समझ नहीं सकता कैसे यहाँ है कि लागू करने के लिए। saveWidget के साथ कुछ पागल सामान किया जो सफल नहीं था और दोहराने वाला नहीं है।

धन्यवाद!

+1

वहाँ भी [Docverter] (http://www.docverter.com/), आ सेवा के रूप में pandoc की तरह ... – mb21

उत्तर

4

saveWidget साथ एक वर्ग कुछ पागल सामान से थोड़ा सा लेकिन अगर आप XML package उपयोग कर सकते हैं (आप देवदार-14 के लिए की आवश्यकता होगी) कुछ नीचे की तरह चाल करना चाहिए:

#' http://stackoverflow.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) 
} 
+0

यह नहीं किया है मेरे लिए काम। लिपियों को लोड नहीं किया जाता है क्योंकि कम से कम विंडोज़ पर फ़ायरफ़ॉक्स पर, पूर्ण फ़ाइल नाम 'src' विशेषता के रूप में काम नहीं करते हैं। विगेट्स के लिए JSON भी उलझन में हो जाता है। –

+0

इसे पूर्ण पथ नहीं होना चाहिए, लेकिन सर्वर वातावरण में यह संभव है कि आप जो चाहते हैं वह सबसे अधिक संभावना है। निर्भरता स्थिर हैं और प्रत्येक जेनरेट किए गए दस्तावेज़ के लिए अलग-अलग रखने और सेवा करने का कोई कारण नहीं है। मुझे यकीन नहीं है कि उलझन में जेएसओएन का क्या मतलब है। – zero323

+0

'मार्कडाउन :: मार्कडाउन टूम HTML 'एचटीएमएल इकाइयों के साथ कुछ पात्रों को प्रतिस्थापित करता है और इसलिए JSON अब मान्य नहीं है। यदि आप मेरा जवाब देखते हैं, तो मैंने मौजूदा HTML को पहले खींचने के लिए 'htmltools: extractPreserveChunks' का उपयोग किया है और फिर इसे बाद में पुनर्स्थापित करें; यह 'rmarkdown' द्वारा उपयोग की जाने वाली विधि है। मैं सैद्धांतिक रूप से सहमत हूं कि अंतरिक्ष बचाने के लिए स्क्रिप्ट और स्टाइलशीट को रेखांकित नहीं किया गया है, हालांकि यह 'rmarkdown' में डिफ़ॉल्ट रूप से किया जाता है, और यह अधिक पोर्टेबल अंतिम परिणाम बनाता है। इसे फिर से देखकर, आपके कोड को सापेक्ष पथों के साथ काम करना चाहिए, इसलिए पूर्ण पथ का उपयोग मेरा मुद्दा था। –

8

यहाँ एक समाधान जो पैकेज knitr, markdown, base64enc और htmltools का उपयोग करता है। यह rmarkdown::render में आंतरिक रूप से क्या होता है, इसका मॉडल किया गया है, लेकिन pandoc पर इसकी कोई निर्भरता नहीं है। यह डिफ़ॉल्ट रूप से एक स्वयं निहित HTML फ़ाइल उत्पन्न करता है, या वैकल्पिक रूप से सभी निर्भरताओं को एक फ़ोल्डर में कॉपी करता है। उत्तरार्द्ध के साथ, यह मानता है कि सभी सीएसएस और जेएस फाइलों पर यह निर्भर करता है कि विशिष्ट रूप से नामित हैं (यानी यह दोनों आयात नहीं करेगा यदि दो htmlwidgets दोनों अपनी सीएसएस फ़ाइल 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) 
} 

यह इस तरह कहा जा सकता है:

render_with_widgets("testing.Rmd") 

यह भी संयोजन में, किसी भी htmlwidgets के लिए काम करना चाहिए। उदाहरण:

टेस्टविड्जेट्स।आरएमडी

--- 
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") 
``` 

और फिर आर से

render_with_widgets("TestWidgets.Rmd") 
संबंधित मुद्दे