From c9f8640ab61d7212705b52ecc8dcaa1ff5d803fa Mon Sep 17 00:00:00 2001 From: James J Balamuta Date: Thu, 7 Dec 2023 03:51:16 -0700 Subject: [PATCH] Escape HTML output characters generated by R code output (#116) --- _extensions/webr/_extension.yml | 2 +- .../webr/webr-context-interactive.html | 2 +- _extensions/webr/webr-context-output.html | 2 +- _extensions/webr/webr-init.html | 10 ++++++ docs/qwebr-release-notes.qmd | 1 + ...ebr-test-escape-html-output-characters.qmd | 34 +++++++++++++++++++ 6 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 tests/qwebr-test-escape-html-output-characters.qmd diff --git a/_extensions/webr/_extension.yml b/_extensions/webr/_extension.yml index 34e97a8f..51da7f46 100644 --- a/_extensions/webr/_extension.yml +++ b/_extensions/webr/_extension.yml @@ -1,7 +1,7 @@ name: webr title: Embedded webr code cells author: James Joseph Balamuta -version: 0.4.0-dev.2 +version: 0.4.0-dev.3 quarto-required: ">=1.2.198" contributes: filters: diff --git a/_extensions/webr/webr-context-interactive.html b/_extensions/webr/webr-context-interactive.html index 80bf7ee8..55f91b3a 100644 --- a/_extensions/webr/webr-context-interactive.html +++ b/_extensions/webr/webr-context-interactive.html @@ -188,7 +188,7 @@ .filter(evt => evt.type === "stdout" || evt.type === "stderr") .map((evt, index) => { const className = `qwebr-output-code-${evt.type}`; - return `${evt.data}`; + return `${qwebrEscapeHTMLCharacters(evt.data)}`; }) .join("\n"); diff --git a/_extensions/webr/webr-context-output.html b/_extensions/webr/webr-context-output.html index ca9f96b4..b086cf20 100644 --- a/_extensions/webr/webr-context-output.html +++ b/_extensions/webr/webr-context-output.html @@ -72,7 +72,7 @@ .filter(evt => evt.type === "stdout" || evt.type === "stderr") .map((evt, index) => { const className = `qwebr-output-code-${evt.type}`; - return `${evt.data}`; + return `${qwebrEscapeHTMLCharacters(evt.data)}`; }) .join("\n"); diff --git a/_extensions/webr/webr-init.html b/_extensions/webr/webr-init.html index 72c2351c..1defaec0 100644 --- a/_extensions/webr/webr-init.html +++ b/_extensions/webr/webr-init.html @@ -292,4 +292,14 @@ true ); + // Global version of the Escape HTML function that converts HTML + // characters to their HTML entities. + globalThis.qwebrEscapeHTMLCharacters = function(unsafe) { + return unsafe + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + }; \ No newline at end of file diff --git a/docs/qwebr-release-notes.qmd b/docs/qwebr-release-notes.qmd index e86e076b..811c0938 100644 --- a/docs/qwebr-release-notes.qmd +++ b/docs/qwebr-release-notes.qmd @@ -19,6 +19,7 @@ format: ## Bugfixes +- Prevented HTML output being shown as HTML by replacing HTML characters like `<`, `>`, `&`, etc., with their corresponding HTML entities. ([#115](https://github.com/coatless/quarto-webr/issues/115), h/t [@gvelasq](https://github.com/gvelasq)) - Fixed display of text found after a code cell in RevealJS appearing off the page ([#102](https://github.com/coatless/quarto-webr/issues/102), [#106](https://github.com/coatless/quarto-webr/issues/106)) ## Documentation diff --git a/tests/qwebr-test-escape-html-output-characters.qmd b/tests/qwebr-test-escape-html-output-characters.qmd new file mode 100644 index 00000000..d76717f1 --- /dev/null +++ b/tests/qwebr-test-escape-html-output-characters.qmd @@ -0,0 +1,34 @@ +--- +title: "Test: Escape Output with HTML Entities" +format: html +engine: knitr +filters: + - webr +--- + +Ensure HTML output is escaped. + +## Interactive + +```{webr-r} +# This function converts a markdown link into HTML +"[Posit](https://posit.co)" |> (\(.) { + text <- sub("\\].*", "", sub(".*\\[", "", .)) + url <- sub("\\).*", "", sub(".*\\(", "", .)) + + writeLines(noquote(paste0('', text, ''))) +})() +``` + +## Non-interactive + +```{webr-r} +#| context: output +# This function converts a markdown link into HTML +"[Posit](https://posit.co)" |> (\(.) { + text <- sub("\\].*", "", sub(".*\\[", "", .)) + url <- sub("\\).*", "", sub(".*\\(", "", .)) + + writeLines(noquote(paste0('', text, ''))) +})() +```