diff --git a/.Rbuildignore b/.Rbuildignore new file mode 100644 index 0000000..91114bf --- /dev/null +++ b/.Rbuildignore @@ -0,0 +1,2 @@ +^.*\.Rproj$ +^\.Rproj\.user$ diff --git a/.gitignore b/.gitignore index b1fd20c..9dbbbef 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ venv/ *.log .DS_Store .idea +.Rproj.user diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..c52012b --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,16 @@ +Package: dashDangerouslySetInnerHtml +Title: Dash component to dangerously set inner raw HTML +Version: 0.0.1 +Authors@R: c( + person(family = "plotly", role = c("aut", "cre"), email = "chris@plot.ly"), + person("Carson", "Sievert", role = "aut")) +Description: Dash component to dangerously set inner raw HTML +Suggests: + testthat, + roxygen2 +License: MIT + file LICENSE +URL: https://github.com/plotly/dash-dangerously-set-inner-html +BugReports: https://github.com/plotly/dash-dangerously-set-inner-html/issues +Encoding: UTF-8 +LazyData: true +RoxygenNote: 6.0.1.9000 \ No newline at end of file diff --git a/NAMESPACE b/NAMESPACE new file mode 100644 index 0000000..caf1f72 --- /dev/null +++ b/NAMESPACE @@ -0,0 +1,3 @@ +# Generated by roxygen2: do not edit by hand + +export(DangerouslySetInnerHTML) diff --git a/R/components.R b/R/components.R new file mode 100644 index 0000000..2aac240 --- /dev/null +++ b/R/components.R @@ -0,0 +1,70 @@ +# Auto-generated by dashTranspileR -- do not edit by hand + +#' DangerouslySetInnerHTML component +#' @description Render a string of raw, unescaped HTML. This uses React.js's `dangerouslySetInnerHTML` method. From React.js's documentation, note that: > Setting HTML from code is risky because it's easy to > inadvertently expose your users to a cross-site scripting (XSS) > (https://en.wikipedia.org/wiki/Cross-site_scripting) > attack. So, you can set HTML directly in Dash through React.js, but you have to type out dangerouslySetInnerHTML to remind yourself that it's dangerous. In most cases, you are safer using the Dash HTML component classes, dash-html-components (https://github.com/plotly/dash-html-components). You can also provide HTML in a sandboxed iframe using the `dash_html_components.IFrame(srcDoc='raw html here')` component, see , see https://community.plot.ly/t/rendering-html-similar-to-markdown/6232/2?u=chriddyp Note that the elements in the HTML block that is generated will can not be targeted with Dash callbacks. +#' @export +#' @param ... An string of raw, unescaped HTML that will be rendered directly +#' @param children An string of raw, unescaped HTML that will be rendered directly + +DangerouslySetInnerHTML <- function(..., children = NULL) { + +component <- list( + props = list( + children=c(children, assert_valid_children(..., wildcards = NULL)) + ), + type = 'DangerouslySetInnerHTML', + namespace = 'dash_dangerously_set_inner_html', + propNames = c('children'), + package = 'dashDangerouslySetInnerHtml' +) + +component$props <- filter_null(component$props) + + +structure(component, class = c('dash_component', 'list')) +} + + +filter_null <- function(x) { + if (length(x) == 0 || !is.list(x)) return(x) + x[!vapply(x, is.null, logical(1))] +} + +assert_valid_children <- function(..., wildcards = NULL) { + kids <- list(...) + if (length(wildcards)) { + pattern <- paste(paste0('^', wildcards), collapse = '|') + kids <- kids[!grepl(pattern, names2(kids))] + } + if (!length(kids)) return(NULL) + assert_no_names(kids) +} + +append_wildcard_props <- function(component, wildcards = NULL, ...) { + attrs <- list(...) + if (!length(attrs) || !length(wildcards)) return(component) + pattern <- paste(paste0('^', wildcards), collapse = '|') + attrs_wild <- attrs[grepl(pattern, names2(attrs))] + if (!length(attrs_wild)) return(component) + component[['props']] <- c(component[['props']] %||% list(), attrs_wild) + component[['propNames']] <- c(component[['propNames']], names(attrs_wild)) + component +} + +names2 <- function(x) names(x) %||% rep('', length(x)) + +`%||%` <- function(x, y) if (length(x)) x else y + +assert_no_names <- function(x) { + nms <- names(x) + if (!is.null(nms)) { + stop( + sprintf( + "Didn't recognize the following named arguments: '%s'", + paste(nms, collapse = "', '") + ), call. = FALSE + ) + } + names(x) <- NULL + x +} diff --git a/dashDangerouslySetInnerHtml.Rproj b/dashDangerouslySetInnerHtml.Rproj new file mode 100644 index 0000000..21a4da0 --- /dev/null +++ b/dashDangerouslySetInnerHtml.Rproj @@ -0,0 +1,17 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source diff --git a/inst/dashR_deps.rds b/inst/dashR_deps.rds new file mode 100644 index 0000000..fb0293c Binary files /dev/null and b/inst/dashR_deps.rds differ diff --git a/inst/dash_dangerously_set_inner_html/bundle.js b/inst/dash_dangerously_set_inner_html/bundle.js new file mode 120000 index 0000000..73e963b --- /dev/null +++ b/inst/dash_dangerously_set_inner_html/bundle.js @@ -0,0 +1 @@ +../../dash_dangerously_set_inner_html/bundle.js \ No newline at end of file diff --git a/man/DangerouslySetInnerHTML.Rd b/man/DangerouslySetInnerHTML.Rd new file mode 100644 index 0000000..9d836c7 --- /dev/null +++ b/man/DangerouslySetInnerHTML.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/components.R +\name{DangerouslySetInnerHTML} +\alias{DangerouslySetInnerHTML} +\title{DangerouslySetInnerHTML component} +\usage{ +DangerouslySetInnerHTML(..., children = NULL) +} +\arguments{ +\item{...}{An string of raw, unescaped HTML that will be rendered directly} + +\item{children}{An string of raw, unescaped HTML that will be rendered directly} +} +\description{ +Render a string of raw, unescaped HTML. This uses React.js's `dangerouslySetInnerHTML` method. From React.js's documentation, note that: > Setting HTML from code is risky because it's easy to > inadvertently expose your users to a cross-site scripting (XSS) > (https://en.wikipedia.org/wiki/Cross-site_scripting) > attack. So, you can set HTML directly in Dash through React.js, but you have to type out dangerouslySetInnerHTML to remind yourself that it's dangerous. In most cases, you are safer using the Dash HTML component classes, dash-html-components (https://github.com/plotly/dash-html-components). You can also provide HTML in a sandboxed iframe using the `dash_html_components.IFrame(srcDoc='raw html here')` component, see , see https://community.plot.ly/t/rendering-html-similar-to-markdown/6232/2?u=chriddyp Note that the elements in the HTML block that is generated will can not be targeted with Dash callbacks. +} diff --git a/package.json b/package.json index 55c6c44..371cb19 100644 --- a/package.json +++ b/package.json @@ -16,14 +16,17 @@ "copy-lib": "copyfiles -u 1 lib/* dash_dangerously_set_inner_html", "demo": "builder run demo", "install-local": "npm run copy-lib && python setup.py install", + "install-local-r": "npm run copy-lib && Rscript tools/transpile.R && Rscript -e 'roxygen2::roxygenise()' && R CMD install .", "prepublish": "npm test && builder run build-dist && npm run copy-lib", "publish-all": "npm publish && python setup.py sdist upload", "publish-pypi": "npm run prepublish && python setup.py sdist upload", + "publish-cran": "npm run prepublish && Rscript -e 'devtools::release()'", "start": "builder run build-dev", "test": "", "test-watch": "builder run test-frontend-watch", "test-debug": "builder run test-frontend-debug", - "uninstall-local": "pip uninstall dash-dangerously-set-inner-html -y" + "uninstall-local": "pip uninstall dash-dangerously-set-inner-html -y", + "uninstall-local-r": "Rscript -e \"utils::remove.packages(read.dcf('DESCRIPTION')[, 'Package'])\"" }, "dependencies": { "builder": "3.2.2", diff --git a/tools/transpile.R b/tools/transpile.R new file mode 100644 index 0000000..93a3146 --- /dev/null +++ b/tools/transpile.R @@ -0,0 +1,4 @@ +if (!require(dashTranspileR)) remotes::install_github("plotly/dashTranspileR") + +library(dashTranspileR) +transpile_write(transpile()) \ No newline at end of file