GithubHelp home page GithubHelp logo

htmltools's Introduction

R build status CRAN status Lifecycle: experimental

htmltools

Tools for creating, manipulating, and writing HTML from R.

Installation

Install the stable release of htmltools on CRAN:

install.packages("htmltools")

Install the development version with:

remotes::install_github("rstudio/htmltools")

Quick overview

{htmltools} makes it easy to customize the user interface (UI) of any Shiny or R Markdown project by using R code to generate custom HTML (including JavaScript and CSS).

This Shiny article provides a great introduction to {htmltools} (even if you're not interested in Shiny). As you'll learn in that article, the general foundation that {htmltools} provides allows other R packages (e.g., {htmlwidgets}, {crosstalk}, etc.) to provide "HTML components" in R that users can manipulate and combine in ways the component authors didn't foresee.

For example, as described in depth here, {htmltools} makes it fairly easy to arrange numerous {htmlwidgets} (e.g., {plotly} graphs) into a single static HTML webpage:

library(htmltools)
library(plotly)
browsable(tagList(
  plot_ly(diamonds, x = ~carat, height = 200),
  plot_ly(diamonds, x = ~price, height = 200)
))

Also, thanks to tagQuery(), it is fairly easy to query and manipulate the underlying HTML structure of components. See the tagQuery() article to learn more.

Learn more

If you're looking to learn how to build more custom user interfaces by writing custom HTML/JavaScript/CSS, we recommend the following resource:

htmltools's People

Contributors

atusy avatar cderv avatar colinfay avatar cpsievert avatar daattali avatar dmpe avatar dmurdoch avatar flrd avatar gadenbuie avatar gtritchie avatar hadley avatar haozhu233 avatar indrajeetpatil avatar jcheng5 avatar jimhester avatar jjallaire avatar jmcphers avatar maelle avatar mkuhn avatar nistara avatar olivroy avatar ramnathv avatar romainfrancois avatar schloerke avatar shrektan avatar slodge avatar strazto avatar trestletech avatar wch avatar yihui avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

htmltools's Issues

support boolean attributes (support for unnamed attributes)

Currently, boolean attributes (see this link) may be passed to a tag using the empty string syntax.

library(htmltools)

tags$button(type = "button", disable = "")

Per https://html.spec.whatwg.org/#boolean-attributes, this works.

However, boolean attributes cannot be used without use of the empty string.

library(htmltools)

tagAppendAttributes(
  tags$button(type = "button"),
  "disable"
)

(currently throws an error because the attribute is not named)

This is not a bug, the empty string syntax works for now, simply an enhancement.

head tag broken?

I am having trouble getting the html head tag to be emitted. Other tags seem to work. Example:

> htmltools::tags$body()
<body></body>
> htmltools::tags$head()

> htmltools::tags$title('Test')
<title>Test</title>
> htmltools::tags$head(htmltools::tags$title('Test'))

> 

i.e. htmltools::tags$head() emits nothing. Am I doing something wrong? Or is this broken?

I am using the current version of the htmltools package from CRAN, i.e. 0.3.5

Allow imports as dependencies

For example,

htmlDependency( name="foo", version="1.0", src=c(href="https://foo.io"), import="foo.html" )

would give: <link rel="import" href="https://foo.io/foo.html></link> in <head>...</head>. Is there a way to do this already?

Add selfcontained option to save_html()

I could have easily missed an easier solution, but saving a tagList especially as selfcontained = TRUE seems difficult. Here is the function I wrote to accomplish this using bits and pieces of htmltools. Would this be deemed as something worth of htmltools?

save_tags <- function (tags, file, selfcontained = F, libdir = "./lib") 
{
    if (is.null(libdir)) {
        libdir <- paste(tools::file_path_sans_ext(basename(file)), 
            "_files", sep = "")
    }
    htmltools::save_html(tags, file = file, libdir = libdir)
    if (selfcontained) {
        if (!htmlwidgets:::pandoc_available()) {
            stop("Saving a widget with selfcontained = TRUE requires pandoc. For details see:\n", 
                "https://github.com/rstudio/rmarkdown/blob/master/PANDOC.md")
        }
        htmlwidgets:::pandoc_self_contained_html(file, file)
        unlink(libdir, recursive = TRUE)
    }
    return(file)
}

Finer granularity than all_files = TRUE / FALSE

When exposing a webfont as an html dependency, you need to include a css file, and a handful of web font files. There's currently no way to select only specified files out of the src/ that aren't scripts, stylesheets, or attachments.

copyDependenciesToDir() throws confusing error message when dependency file doesn't exist

library(htmltools)

dep <- htmlDependency(
  name = "foo",
  version = "0.0.1",
  script = "foo.js",
  src = list(file = ""),
  package = "htmltools",
  all_files = FALSE
)

copyDependencyToDir(dep, "bar")
Error in dirname(to) : a character vector argument expected

It'd be useful if the error message said something to the effect of: Can't copy 'foo.js' since it doesn't exist

tags renderer line feeds can result in unwanted white space

As described in my StackOverflow question, if in a Shiny app you write something like

p('This is my ', a(href = 'https://stackoverflow.com/', 'favorite link ever'), '!')

because of the way line feeds and spaces are rendered between each of the child elements the resulting HTML is

<p>
  This is my 
  <a href="https://stackoverflow.com/">favorite link ever</a>
  !
</p>

Which looks like this (note the space before the exclamation mark)

This is my favorite link ever !

I think I've correctly tracked this down to this section of code:

if (length(children) > 0) {

Maybe the "special case" block could be expanded to deal with this? It feels like the renderer is too eager to add line feeds and indents, and there are more cases where this is not necessary/wanted.

I know this can be worked around by building explicit HTML (say with HTML(paste0(...))), but since my year-old SO question still gets an occasional upvote I figured I should write something up here.

Related issue: #80

Need some way of not printing whitespace

For example:

> div("foo", "bar")
<div>
  foo
  bar
</div> 

It would be good to be able to do something like one of the following:

div(.nospace = TRUE, "foo", "bar")
div("foo", nospace(), "bar")
nospace(div("foo", "bar"))

Issue with dplyr

I am trying to add HTML buttons to a DT using dplyr, but I seem to have run into an edgecase.

library(dplyr)
library(htmltools)
# obviously works
data.frame(x = c("A","B","C")) %>% 
  mutate(row = row_number())
# doesn't work
data.frame(x = c("A","B","C")) %>% 
  mutate(button = HTML(as.character(tags$button(id = paste0("btn",row_number())))))
# also doesn't work
data.frame(x = c("A","B","C")) %>% 
  mutate(row = row_number()) %>%
  mutate(button = HTML(as.character(tags$button(id = paste0("btn", row)))))

Weirdly it seems a whole vector of row numbers is getting passed to paste0 so each button has a vector of ids so it spits out a warning and subsets to the first yielding a table with buttons all having the same id.

Kind Regards

Having trouble including multiple scripts and stylesheets.

I am trying to make rCharts plots easier to use with rmarkdown. I wrote a simple function that makes use of the configuration file in rCharts to import dependencies

importChart <- function(chart){
  lib = chart$LIB$url
  config = yaml::yaml.load_file(file.path(lib, 'config.yml'))[[1]]
  htmlDependency(chart$lib, "1.0.1", src = lib, 
    script = config$jshead, style = config$css
  )
}

However, if I try to use attachDependencies to add this to a test page, only the first script and stylesheet is included. I tried to trace the source of this bug, but the chain of functions went really deep and I wasn't sure where to look.

page = attachDependencies(tags$html('page'), importChart(r2))
html_print(page)

Is this a bug, or am I doing something wrong with how I amusing htmlDependency?

HTML dependencies with query parameters

The problem

This issue is relevant for anyone hoping to use htmlDependency() with (query) parameters (e.g. MathJax). There doesn't seem to be a good way to create this class of dependency so that it gets rendered correctly in various contexts, for example:

library(htmltools)

dep <- htmlDependency(
  name = "mathjax",
  version = "2.7.4",
  src = c(
    href = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4"
  ),
  script = "MathJax.js?config=TeX-AMS-MML_HTMLorMML"
)

renderDependencies(list(dep), "href")
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js%3Fconfig%3DTeX-AMS-MML_HTMLorMML"></script>

You can set encodeFunc = identity to render this properly...

renderDependencies(list(dep), "href", encodeFunc = identity)
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>

...but the problem is that several "higher-level" functions (e.g. htmltools::save_html(), htmltools::renderDocument(), and htmlwidgets:::pandoc_save_markdown()) call renderDependencies() without a way to set the encodeFunc argument.

A proposed solution

More flexible

Make it possible to "escape" urlEncodePath by using a special class, like "AsIs"

urlEncodePath <- function(x) {
  if (inherits(x, "AsIs")) return(x)
  vURLEncode <- Vectorize(URLencode, USE.NAMES = FALSE)
  gsub("%2[Ff]", "/", vURLEncode(x, TRUE))
}

Then you could do:

htmlDependency(
  ...,
  script = I("MathJax.js?config=TeX-AMS-MML_HTMLorMML")
)

Less flexible

Add a query argument to htmlDependency() which takes a named list so that

dep <- htmlDependency(
  name = "mathjax",
  version = "2.7.4",
  src = c(
    href = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4"
  ),
  script = "MathJax.js",
  config = list(config = "TeX-AMS-MML_HTMLorMML")
)

renderDependencies(list(dep), "href")

would generate

<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>

Insert CSS/JS dependencies at the end of the body

It would be nice, if there is a way to insert JS&CSS dependencies towards the end of the body tag.

Reasoning:

Putting your script tags at the end of the body tag, after all of the page's contents, means your entire page will begin displaying as soon as possible to give the user something to look at - and then your scripts will download and make everything work.

Source

High priority for me.

Thanks.

Notes in R CMD check

checking DESCRIPTION meta-information ... NOTE
Malformed Description field: should contain one or more complete sentences.
checking dependencies in R code ... NOTE
'library' or 'require' call to ‘markdown’ in package code.
  Please use :: or requireNamespace() instead.
  See section 'Suggested packages' in the 'Writing R Extensions' manual.

be able to delete tags from code

Having code like this :

<li class="nav-item">
  <a href="#tab-3402-1" class="nav-link active" data-toggle="tab" data-value="Table" role="tab">Table</a>
</li>

I would like to have a method something like this:
deleteTags(tagObject, tag = "li", class= "nav-item")

which would delete
<li class="nav-item"> </li> code from the above. Resulting into standalone:

  <a href="#tab-3402-1" class="nav-link active" data-toggle="tab" data-value="Table" role="tab">Table</a>

htmlTemplate not respecting indentation

Consider the following example.

library(htmltools)
template <- "
<div>
  <span>Hello</span>
  <span>{{ user }}</span>
</div>
"
htmlTemplate(text_ = template, user = 'Jane Doe')

It renders as shown below

<div>
  <span>Hello</span>
  <span>
Jane Doe
</span>
</div>

I would have expected htmlTemplate to respect the indentation and instead render

<div>
  <span>Hello</span>
  <span>Jane Doe</span>
</div>

Bad behavior when passing `as.tags` output to `shiny::renderUI`

When I render this file, an extra "div form-group shiny-input-container" appears in front of the label of the second slider. This seems to be a side effect of as.tags not passing on the class shiny.tag

The included as.tags.shiny.tag functions seems to fix it, but the function is a bit of a hack.

This comes up in real life when I eval and parse code from a shinyAce editor then feed it into as.tags

    ---
    runtime: shiny
    ---

    ```{r}
    # Works fine
    renderUI({
      sliderInput("s1", "Slide Me", min = 0, max = 10, val = 5)
    })

    # Odd label
    renderUI({
      htmltools::as.tags(sliderInput("s1", "Slide Me", min = 0, max = 10, val = 5))
    })
    ```


    ```{r eval = FALSE}
    # eval = FALSE
    # But works again
    as.tags.shiny.tag <- function(...) {
      structure(htmltools:::as.tags.default(...), class = "shiny.tag")
    }

    renderUI({
      htmltools::as.tags(sliderInput("s1", "Slide Me", min = 0, max = 10, val = 5))
    })
    ```

HTML "escaping" for \n

Joe,

I tried to pass "A\nB" to p() and found that \n does not have the desired effect in the rendered HTML page even though the generated HTML file had

A B

Wouldn't it be necessary to "escape" \n by
? I certainly can do p(HTML("A
B")), but p("A\nB") looks more intuitive. What do you think?

Sincerely,
Junghoon Lee

Support for carrying along external CSV/JSON files

The idea would be to allow external CSV/JSON files to be copied to the temp directory in which the html file is generated so that the page can make use of it. This behavior is very beneficial especially when you are reading large geojson files and want to keep the file external to your html.

Critical Error: includeMarkdown() fails if the file is empty

htmltools_error

I've been developing a module, and I've just noticed that the includeMarkdown() function will fail if the file is empty. Although this may seem fairly harmless, I have a project in which we develop modules that may include a help file, and the example help.md file is sometimes empty. If I add just a small amount of text to it, the function works again, and if I remove all text, the function fails.

It'd be nice just to include an empty pair of tags just to make sure that the function stays in tact in this very mundane fail case.

normalizePath() issue on Windows machine

This piece of code

library(mapview)
library(htmlwidgets)

m <- mapview(breweries91)@map
# > class(m)
# [1] "leaflet"    "htmlwidget"

saveWidget(m, file = "img/mapshot.html")

throws the following error:

Error in normalizePath(path.expand(path), winslash, mustWork) :
path[1]="img": The system cannot find the file specified

Such an undesirable behavior has been reported previously (e.g., https://bugs.r-project.org/bugzilla3/show_bug.cgi?id=16369). However, after examining the source code, I found that this issue could simply be solved (at least on my machine) by replacing line 83 in html_print.R with

dep <- makeDependencyRelative(dep, getwd(), FALSE)

I.e., specifying the working directory as absolute rather than relative path prevents normalizePath from failing. Here is the output of sessionInfo().

R version 3.3.0 Patched (2016-05-03 r70575)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

locale:
[1] LC_COLLATE=German_Germany.1252 LC_CTYPE=German_Germany.1252 LC_MONETARY=German_Germany.1252
[4] LC_NUMERIC=C LC_TIME=German_Germany.1252

attached base packages:
[1] stats graphics grDevices utils datasets methods base

other attached packages:
[1] webshot_0.3.0.9000 gimms_0.5.1 raster_2.5-2 rgdal_1.1-8 sp_1.2-3
[6] mapview_1.0.22 leaflet_1.0.1

loaded via a namespace (and not attached):
[1] Rcpp_0.12.4 RColorBrewer_1.1-2 plyr_1.8.3 base64enc_0.1-3 R.methodsS3_1.7.1
[6] R.utils_2.3.0 viridis_0.3.4 iterators_1.0.8 tools_3.3.0 gdalUtils_2.0.1.7
[11] boot_1.3-18 digest_0.6.9 jsonlite_0.9.19 gtable_0.2.0 satellite_0.2.0
[16] memoise_1.0.0 lattice_0.20-33 png_0.1-7 foreach_1.4.3 yaml_2.1.13
[21] parallel_3.3.0 Kendall_2.2 zyp_0.10-1 gridExtra_2.2.1 withr_1.0.1
[26] knitr_1.12.3 htmlwidgets_0.6 rgeos_0.3-19 devtools_1.11.1 stats4_3.3.0
[31] grid_3.3.0 latticeExtra_0.6-28 ggplot2_2.1.0 magrittr_1.5 scales_0.4.0
[36] codetools_0.2-14 Orcs_1.0.3 htmltools_0.3.5 colorspace_1.2-6 munsell_0.4.3
[41] doParallel_1.0.10 R.oo_1.20.0

HTML content still escaped in tag() attribues

 tag("a", list(HTML("&"), href=HTML("mailto:&")))

gives

<a href="mailto:&amp;">&</a> 

when I would expect

<a href="mailto:&">&</a> 

NB: this is a problem to obfuscate email addresses using markdown for example.

Encoding lost when replacing content with gsub in htmlEscape

Here is my problem:
I have data loaded from a file encoded in UTF-8 that contains quotes and accents.
I then try to use it as content in an attribute of an HTML tag. But during the rendering of the tag, htmlEscape calls gsub and then when gsub replaces my quotes, the encoding is lost from my string. Not modified, just lost...

Before gsub I have:

text
[1] "Nombre d'observations. Devrait être numérique"
Encoding(text)
[1] "UTF-8"

And after the gsub:

text
[1] "Nombre d&#39;observations. Devrait être numérique"
Encoding(text)
[1] "unknown"

And if I do:

Encoding(text) <- "UTF-8"
text
[1] "Nombre d'observations. Devrait être numérique"

Everything works fine again!

My workaround for the moment is quite easy. I just save the encoding before the gsub loop and then reapply it at the end and everything seems ok!
The only problem is I seem to have to do it in htmlEscape because the final encoding of the tag rendering is UTF-8 and yet the error subsists. But htmlEscape is buried so deep in the call stack that the only way I found to fix it quickly is by replacing htmlEscape with my modified version with assignInNamespace, which is not really nice it seems.

I don't know if there are there other ways around this problem, but I will gladly take any other solution that doesn't involve ugly hacking!

Thanks a lot!

Build failing in MacOS

I'm trying to build htmltools on MacOS, but the build fails with these messages:

** testing if installed package can be loaded
Error: package or namespace load failed for ‘htmltools’ in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/Library/Frameworks/R.framework/Versions/3.4/Resources/library/htmltools/libs/htmltools.so':
  dlopen(/Library/Frameworks/R.framework/Versions/3.4/Resources/library/htmltools/libs/htmltools.so, 6): Symbol not found: _htmltools_template_dfa
  Referenced from: /Library/Frameworks/R.framework/Versions/3.4/Resources/library/htmltools/libs/htmltools.so
  Expected in: flat namespace in /Library/Frameworks/R.framework/Versions/3.4/Resources/library/htmltools/libs/htmltools.so
Error: loading failed
Execution halted
ERROR: loading failed
* removing ‘/Library/Frameworks/R.framework/Versions/3.4/Resources/library/htmltools’

The missing symbol is one produced automatically by Rcpp, so I've tried updating Rcpp, deleting the automatically generated files and regenerating them, etc., all with no improvement. Is this a problem in htmltools, or on my system (which I've recently updated)?

Should print.htmlwidget return the HTML path instead of the widget

Should print.htmlwidget return the output of htmltools::html_print instead of the passed in x.

so simply.

html_print(htmltools::as.tags(x, standalone=TRUE), viewer = if (view) viewerFunc))

instead of

html_print(htmltools::as.tags(x, standalone=TRUE), viewer = if (view) viewerFunc)

  # return value
  invisible(x)

htmltools::html_print return the saved HTML path invisibly.

Getting back the same widget is not really helpful, but getting back the HTML file path where the widget is stored can be very helpful. e.g.

saved_widget_html <- print(widget, view=NULL)
# Now use the save_widget_html path to do something else.

Same for print.suppress_viewer.

NA properties are sometimes rendered as "NA" in HTML

If an argument to a tag function is NA, then it should be turned into an empty HTML attribute:

div(class = "abc", foo=NA)
#> <div class="abc" foo></div>

However, if there are two other arguments with the same name, then the NA will turn into "NA":

div(class = "abc", class = "xyz", foo=NA)
#> <div class="abc xyz" foo="NA"></div>

tags$script() should automatically not escape content

Currently, the content of tags$script() needs to be wrapped with HTML() in order to not be escaped. But there's no reason (that I can think of) that the content should be escaped, and it just causes confusion with users.

I realize that this is a departure from how all other tag functions work, but it's also true that the <script> tag is different from other tags.

Error when an attribute is character(0)

For example:

div(foo=character(0), "text")
# Error in if (!is.na(attribValue)) { : argument is of length zero

I think it should just drop the attribute, the same as if it were NULL.

print.html conflicts with Hmisc:::print.html

Not sure there is really anything to do about this, but I thought I would post an issue just in case someone else runs into this problem.

Hmisc:::print.html conflicts with htmltools:::print.html, and the error I get when doing something like browsable(HTML(...an object of class html...)) is

Error in paste(browser, object, if (.Platform$OS.type == "unix") "&") : 
  cannot coerce type 'closure' to vector of type 'character'

This error traces to Hmisc line.

I'll cross-post and refer back to this issue, and then I'll close.

Error if template block has no leading or trailing spaces

For example:

htmlTemplate(text_= "{{ 1+1 }}")
# Error in htmlTemplate(text_ = "{{ 1+1 }}") : 
#   Mismatched {{ and }} in HTML template.

htmlTemplate(text_= " {{ 1+1 }}")
# Error in FUN(X[[i]], ...) : Mismatched {{ and }} in HTML template. 

htmlTemplate(text_= "{{ 1+1 }} ")
# Error in htmlTemplate(text_ = "{{ 1+1 }} ") : 
#   Mismatched {{ and }} in HTML template.

htmlTemplate(text_= " {{ 1+1 }} ")
# [1] " \n2\n "

Add support for <script> "integrity" and "crossorigin" attributes

In use of htmltools::htmlDependency() for CDNs, it would allow for SRI checking (which ensures resources hosted on third-party servers have not been tampered with), considered a best practice.

Example from jQuery:

<script
  src="https://code.jquery.com/jquery-1.12.4.min.js"
  integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
  crossorigin="anonymous"></script>

References:

Object generated by `htmltools::htmlDependency` fails `rmarkdown::validate_html_dependency`

The list element that is meant to hold the name of the directory to find "the goods" in seems to be in flux and the object that is generated within htmltools is not valid as far as rmarkdown is concerned.

htmltools::htmlDependency puts this in a list element named src and it seems that rmarkdown::validate_html_dependency expects this to be in a list element named path.

Furthermore, src is flagged as an invalid_field at the tail end rmarkdown::validate_html_dependency.

I'm running into this bug because I'm trying to get an rmdexmaples::datatable into an rmarkdown report.

Embedding a plotly html figure in an rmarkdown report

Hi,

I'm generating a plotly figure which I save as an html file:


p <- plot_ly(z = volcano, type = "heatmap")
htmlwidgets::saveWidget(pi,paste0("p.html"))

And then, from an rmarkdown code, I'd like to embed p.html.

I thought knit_print.html can be used for that, e.g. rmarkdown code chunk:

htmltools::knit_print.html("p.html")

But that doesn't work - it only prints the text "p.html" in the report.

I've also used htmltools::includeHTML:

htmltools::includeHTML("p.html")

While this does work, when I have other code chunks that embed other graphics (e.g., png figures embedded using knitr::include_graphics), the result is that p.html takes over the entire report and the pngs cannot be seen.

So, any idea how to embed plotly html pages with non html (e.g. png) graphics?

One more related question:
Suppose I generate several plotly html figures, e.g. using this code:

for(i in 1:3){
  pi <- plot_ly(z = volcano, type = "heatmap")
  htmlwidgets::saveWidget(pi,paste0("p.",i,".html"))
}

And I want to embed them in an rmarkdown code. How do I loop over them and embed them?

I know that if I'd generated them within the rmarkdown code, I'd use tagList like in this code:

plot.list <- vector(mode="list",3)
for(i in 1:3) plot.list[[i]] <- plot_ly(z = volcano, type = "heatmap")
htmltools::tagList(plot.list)

So is there something equivalent for html plots generated and saved externally?

tagList print inline output option

I wrote a function that converts raw html text to a tagList object. i found that when i try to use tagLists with the example below I get a weird result. The final output is wrapped in a <pre> chunk.

htmlIn<-print(xtable::xtable(mtcars),type = 'html',print.results = F)
tagL<-html2tagList(htmlIn)
fileGood='testGood.html'
fileBad='testBad.html'
htmltools::save_html(tagL,file=fileGood)
htmlwidgets:::pandoc_self_contained_html(fileGood, fileBad)

This happens because the htmltools:::print.shiny.tag.list prints by default an indented output and when it gets rendered by markdown it is assumed to be in a pre chunk. is there a way to have it print inline?

<table border="1">
  <tr>
    <th></th>
    <th>mpg</th>
    <th>cyl</th>
    <th>disp</th>
    <th>hp</th>
    <th>drat</th>
    <th>wt</th>
    <th>qsec</th>
    <th>vs</th>
    <th>am</th>
    <th>gear</th>
    <th>carb</th>
    
  </tr>
  <tr>
    <td align="right">Mazda RX4</td>
    <td align="right">21.00</td>
    <td align="right">6.00</td>
    <td align="right">160.00</td>
    <td align="right">110.00</td>
    <td align="right">3.90</td>
    <td align="right">2.62</td>
    <td align="right">16.46</td>
    <td align="right">0.00</td>
    <td align="right">1.00</td>
    <td align="right">4.00</td>
    <td align="right">4.00</td>
    
  </tr>
  <tr>
    <td align="right">Mazda RX4 Wag</td>
    <td align="right">21.00</td>
    <td align="right">6.00</td>
    <td align="right">160.00</td>
    <td align="right">110.00</td>
    <td align="right">3.90</td>
    <td align="right">2.88</td>
    <td align="right">17.02</td>
    <td align="right">0.00</td>
    <td align="right">1.00</td>
    <td align="right">4.00</td>
    <td align="right">4.00</td>
    
  </tr>
  <tr>
    <td align="right">Datsun 710</td>
    <td align="right">22.80</td>
    <td align="right">4.00</td>
    <td align="right">108.00</td>
    <td align="right">93.00</td>
    <td align="right">3.85</td>
    <td align="right">2.32</td>
    <td align="right">18.61</td>
    <td align="right">1.00</td>
    <td align="right">1.00</td>
    <td align="right">4.00</td>
    <td align="right">1.00</td>
    
  </tr>
  <tr>
    <td align="right">Hornet 4 Drive</td>
    <td align="right">21.40</td>
    <td align="right">6.00</td>
    <td align="right">258.00</td>
    <td align="right">110.00</td>
    <td align="right">3.08</td>
    <td align="right">3.21</td>
    <td align="right">19.44</td>
    <td align="right">1.00</td>
    <td align="right">0.00</td>
    <td align="right">3.00</td>
    <td align="right">1.00</td>
    
  </tr>
  <tr>
    <td align="right">Hornet Sportabout</td>
    <td align="right">18.70</td>
    <td align="right">8.00</td>
    <td align="right">360.00</td>
    <td align="right">175.00</td>
    <td align="right">3.15</td>
    <td align="right">3.44</td>
    <td align="right">17.02</td>
    <td align="right">0.00</td>
    <td align="right">0.00</td>
    <td align="right">3.00</td>
    <td align="right">2.00</td>
    
  </tr>
  <tr>
    <td align="right">Valiant</td>
    <td align="right">18.10</td>
    <td align="right">6.00</td>
    <td align="right">225.00</td>
    <td align="right">105.00</td>
    <td align="right">2.76</td>
    <td align="right">3.46</td>
    <td align="right">20.22</td>
    <td align="right">1.00</td>
    <td align="right">0.00</td>
    <td align="right">3.00</td>
    <td align="right">1.00</td>
    
  </tr>
   
</table>

consider annotating dependency information

It would be useful if renderDependencies() annotated the injected <script> / <link> tags with data attributes describing the source of each dependency, e.g.

 <script
        data-name="htmlwidgets"
        data-version="0.6"
        data-script="htmlwidgets.js"
        data-stylesheet=""
        src="/path/to/R/library/htmlwidgets/www/htmlwidgets.js"></script>

This would make it possible to recover the source of a dependency after e.g. rmarkdown::render() is done with the document.

add md() convenience function to write fragments in markdown

this has been migrated from rstudio/shiny#1936.

I'll do a PR sometime soon, as suggested by @jcheng5.


I'm so used to writing in basic markdown (emph, bold, pre etc.), I can't get myself to write, say shiny::tags$em("foo").
Maybe others are feeling the same.

I build myself a simple wrapper to be able to easily write markdown:

#' @title Convert markdown to html
#'
#' @param text A character vector to be converted to markdown.
#'
#' @param HTML A logical flag, indicating whether the result should additionally be wrapped in shiny::HTML().
#'
#' @noRd
md <- function(text, HTML = TRUE) {
  res <- markdown::renderMarkdown(
    file = NULL,
    output = NULL,
    text = text
  )
  if (HTML) {
    res <- shiny::HTML(text = res)
  }
  return(res)
}

which can be used wherever shiny expects HTML.

Now I can write something like:

fileInput(
  inputId = "rdata",
  label = md("Upload a `*.rdata` file created by *pensieve*."),
)

which makes life a little easier.

Is there any interest in supporting this directly in shiny? I'm guessing an md() function might be an alternative to / modelled on the existing HTML().

If there's interest, I'd be happy to write up a PR.


Just to be sure, what this isn't:

  • this is not about including external files, shiny::includeMarkdown() does that already,
  • this is strictly about Markdown, not RMarkdown.

No releases are tagged

Several releases have been made to CRAN, but none of them have been tagged here. This makes it difficult to find the exact commit from which any release originated.

Error in enc2utf8(text) : argument is not a character vector when rendering DT

When knitting an Rmd with a datatable, was failing with:
Error in enc2utf8(text) argument is not a character vector
I tried include = FALSE and echo = FALSE on the DT::datatable chunk, but still could not knit the document.

Based on the traceback (collapsed, below) it looks like it's failing on htmlEscape(dep$meta).

Possibly related to:

text <- enc2utf8(text)

Traceback 9. htmlEscape(dep$meta)
  1. paste("<meta name="", htmlEscape(names(dep$meta)), "" content="",
    htmlEscape(dep$meta), "" />", sep = "")

  2. renderDependencies(dependencies, "file", encodeFunc = identity,
    hrefFilter = function(path) {
    html_reference_path(path, lib_dir, output_dir)
    })

  3. html_dependencies_as_string(dependencies, NULL, NULL)

  4. as_tmpfile(html_dependencies_as_string(dependencies, NULL, NULL))

  5. pandoc_html_extras_args(extras, self_contained, lib_dir, output_dir)

  6. base(...)

  7. output_format$pre_processor(yaml_front_matter, utf8_input, runtime, knit_meta, files_dir, output_dir)

  8. rmarkdown::render(here::here("inst", "pkgreporting.Rmd"))

I was able to fix this by downgrading to the CRAN version of htmltools.

pandoc version 2.2
rmarkdown at rstudio/markdown@5abbfae

Just let me know if you need more info, or if this is the wrong repo! 😳

Should give a warning if htmlDependency() is called in a package namespace with system.file()

If htmlDependency() is called in a package namespace with a system.file() argument, this can lead to a subtle problem that will be visible only after a the binary package is built and distributed on CRAN.

For example, in shinybootstrap2, there is this code:

dataTableDependency <- list(
  htmlDependency(
    "datatables", "1.10.2",
    c(file = system.file("www/datatables", package = "shinybootstrap2")),
    script = "js/jquery.dataTables.min.js"
  ),
  htmlDependency(
    "datatables-bootstrap", "1.10.2",
    c(file = system.file("www/datatables", package = "shinybootstrap2")),
    stylesheet = c("css/dataTables.bootstrap.css", "css/dataTables.extra.css"),
    script = "js/dataTables.bootstrap.js"
  )
)

This works fine when the package is built and tested on the same machine. However, if the package is built on one machine and then used on another (as is the case with CRAN binary packages), then this will fail -- the dependency will point to the wrong directory on the host.

It fails because system.file() is called at build-time, and the result is stored in the variable dataTableDependency and saved in the binary package. When someone installs the binary package on their machine, the path isn't updated to their path -- it still refers to a path on the machine that built the binaries.

If, on the other hand, htmlDependency() is called from a function at run-time, everything will work fine.

We've also run into this problem with ggvis, and fixed it by converting the variable to a function: rstudio/ggvis@ac65f35

Note: It just so happens that inside of Shiny proper, you can call htmlDependency() and store the results, because Shiny's dependencies use relative paths, without system.file().

This may sound a bit drastic, but I think it would be a good idea have htmlDependency() check if (A) system.file() is called in any of its arguments, and (B) the parent frame is a package namespace. If both of these are true, give a warning or message. I think it would be helpful because otherwise, developers will run into this problem only after their package seems OK and is on CRAN -- and then they'll have a really hard time debugging it, and after they fix it, they'll have to resubmit to CRAN. (This was very confusing for us the first time we saw it, in ggvis, and it was still confusing when we saw it again in shinybootstrap2.)

One more update: I just checked, and shinydashboard also has this problem. :( And as with the other two cases, it would only have been found after sending the package to CRAN.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.