diff --git a/_extensions/webr/_extension.yml b/_extensions/webr/_extension.yml index 3fc7909a..eea113bf 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.7 +version: 0.4.0-dev.8 quarto-required: ">=1.2.198" contributes: filters: diff --git a/_extensions/webr/qwebr-cell-initialization.js b/_extensions/webr/qwebr-cell-initialization.js index 9d774f1e..b470b99d 100644 --- a/_extensions/webr/qwebr-cell-initialization.js +++ b/_extensions/webr/qwebr-cell-initialization.js @@ -63,7 +63,7 @@ qwebrInstance.then( switch (evalType) { case 'output': // Run the code in a non-interactive state that is geared to displaying output - await qwebrExecuteCode(`${cellCode}`, qwebrCounter, EvalTypes.Output); + await qwebrExecuteCode(`${cellCode}`, qwebrCounter, entry.options); break; case 'setup': const activeDiv = document.getElementById(`qwebr-noninteractive-setup-area-${qwebrCounter}`); diff --git a/_extensions/webr/qwebr-compute-engine.js b/_extensions/webr/qwebr-compute-engine.js index 1e04c06a..6ed88e78 100644 --- a/_extensions/webr/qwebr-compute-engine.js +++ b/_extensions/webr/qwebr-compute-engine.js @@ -14,6 +14,11 @@ globalThis.qwebrEscapeHTMLCharacters = function(unsafe) { .replace(/'/g, "'"); }; +// Passthrough results +globalThis.qwebrIdentity = function(x) { + return x; +}; + // Function to parse the pager results globalThis.qwebrParseTypePager = async function (msg) { @@ -62,13 +67,26 @@ globalThis.qwebrComputeEngine = async function( // Create a pager variable for help/file contents let pager = []; + // Handle how output is processed + let processOutput; + + if (options.results == "markup") { + processOutput = qwebrEscapeHTMLCharacters; + } else { + processOutput = qwebrIdentity; + } + // ---- + // Convert from Inches to Pixels by using DPI (dots per inch) + // for bitmap devices (dpi * inches = pixels) + let fig_width = options["fig-width"] * options["dpi"] + let fig_height = options["fig-height"] * options["dpi"] // Initialize webR await mainWebR.init(); // Setup a webR canvas by making a namespace call into the {webr} package - await mainWebR.evalRVoid(`webr::canvas(width=${options["fig-width"]}, height=${options["fig-height"]})`); + await mainWebR.evalRVoid(`webr::canvas(width=${fig_width}, height=${fig_height})`); const result = await mainWebRCodeShelter.captureR(codeToRun, { withAutoprint: true, @@ -80,17 +98,26 @@ globalThis.qwebrComputeEngine = async function( // ----- // Start attempting to parse the result data - try { + processResultOutput:try { // Stop creating images await mainWebR.evalRVoid("dev.off()"); + + // Avoid running through output processing + if (options.results === "hide") { + break processResultOutput; + } // Merge output streams of STDOUT and STDErr (messages and errors are combined.) + // Require both `warning` and `message` to be true to display `STDErr`. const out = result.output - .filter(evt => evt.type === "stdout" || evt.type === "stderr") + .filter( + evt => evt.type === "stdout" || + ( evt.type === "stderr" && (options.warning === "true" && options.message === "true")) + ) .map((evt, index) => { const className = `qwebr-output-code-${evt.type}`; - return `${qwebrEscapeHTMLCharacters(evt.data)}`; + return `${processOutput(evt.data)}`; }) .join("\n"); @@ -109,11 +136,15 @@ globalThis.qwebrComputeEngine = async function( if (msg.data.event === 'canvasImage') { canvas.getContext('2d').drawImage(msg.data.image, 0, 0); } else if (msg.data.event === 'canvasNewPage') { + // Generate a new canvas element canvas = document.createElement("canvas"); - canvas.setAttribute("width", 2 * options["fig-width"]); - canvas.setAttribute("height", 2 * options["fig-height"]); - canvas.style.width = "700px"; + canvas.setAttribute("width", 2 * fig_width); + canvas.setAttribute("height", 2 * fig_height); + canvas.style.width = options["out-width"] ? options["out-width"] : `${fig_width}px`; + if (options["out-height"]) { + canvas.style.height = options["out-height"]; + } canvas.style.display = "block"; canvas.style.margin = "auto"; } @@ -173,12 +204,18 @@ globalThis.qwebrComputeEngine = async function( globalThis.qwebrExecuteCode = async function ( codeToRun, id, - evalType = EvalTypes.Interactive, options = {}) { // If options are not passed, we fall back on the bare minimum to handle the computation if (qwebrIsObjectEmpty(options)) { - options = { "fig-width": 504, "fig-height": 360 }; + options = { + "context": "interactive", + "fig-width": 7, "fig-height": 5, + "out-width": "700px", "out-height": "", + "dpi": 72, + "results": "markup", + "warning": "true", "message": "true", + }; } // Next, we access the compute areas values @@ -194,7 +231,7 @@ globalThis.qwebrExecuteCode = async function ( btn.disabled = true; }); - if (evalType == EvalTypes.Interactive) { + if (options.context == EvalTypes.Interactive) { // Emphasize the active code cell elements.runButton.innerHTML = ' Run Code'; } @@ -207,7 +244,7 @@ globalThis.qwebrExecuteCode = async function ( btn.disabled = false; }); - if (evalType == EvalTypes.Interactive) { + if (options.context == EvalTypes.Interactive) { // Revert to the initial code cell state elements.runButton.innerHTML = ' Run Code'; } diff --git a/_extensions/webr/qwebr-monaco-editor-element.js b/_extensions/webr/qwebr-monaco-editor-element.js index ba95433d..980a73c4 100644 --- a/_extensions/webr/qwebr-monaco-editor-element.js +++ b/_extensions/webr/qwebr-monaco-editor-element.js @@ -6,6 +6,7 @@ globalThis.qwebrCreateMonacoEditorInstance = function (cellData) { const initialCode = cellData.code; const qwebrCounter = cellData.id; + const qwebrOptions = cellData.options; // Retrieve the previously created document elements let runButton = document.getElementById(`qwebr-button-run-${qwebrCounter}`); @@ -36,8 +37,9 @@ globalThis.qwebrCreateMonacoEditorInstance = function (cellData) { // Store the official div container ID editor.__qwebrEditorId = `qwebr-editor-${qwebrCounter}`; - // Store the initial code value + // Store the initial code value and options editor.__qwebrinitialCode = initialCode; + editor.__qwebrOptions = qwebrOptions; // Set at the model level the preferred end of line (EOL) character to LF. // This prevent `\r\n` from being given to the webR engine if the user is on Windows. @@ -79,7 +81,7 @@ globalThis.qwebrCreateMonacoEditorInstance = function (cellData) { editor.addCommand(monaco.KeyMod.Shift | monaco.KeyCode.Enter, () => { // Retrieve all text inside the editor - qwebrExecuteCode(editor.getValue(), editor.__qwebrCounter); + qwebrExecuteCode(editor.getValue(), editor.__qwebrCounter, editor.__qwebrOptions); }); // Add a keydown event listener for CMD/Ctrl+Enter to run selected code @@ -108,14 +110,13 @@ globalThis.qwebrCreateMonacoEditorInstance = function (cellData) { } // Run the entire line of code. - qwebrExecuteCode(currentLine, editor.__qwebrCounter, - EvalTypes.Interactive); + qwebrExecuteCode(currentLine, editor.__qwebrCounter, editor.__qwebrOptions); // Move cursor to new position editor.setPosition(newPosition); } else { // Code to run when Ctrl+Enter is pressed with selected code - qwebrExecuteCode(selectedText, editor.__qwebrCounter, EvalTypes.Interactive); + qwebrExecuteCode(selectedText, editor.__qwebrCounter, editor.__qwebrOptions); } }); } @@ -140,7 +141,7 @@ globalThis.qwebrCreateMonacoEditorInstance = function (cellData) { // Add a click event listener to the run button runButton.onclick = function () { - qwebrExecuteCode(editor.getValue(), editor.__qwebrCounter, EvalTypes.Interactive); + qwebrExecuteCode(editor.getValue(), editor.__qwebrCounter, editor.__qwebrOptions); }; // Add a click event listener to the reset button diff --git a/_extensions/webr/webr.lua b/_extensions/webr/webr.lua index 812d4223..a0ac5b7c 100644 --- a/_extensions/webr/webr.lua +++ b/_extensions/webr/webr.lua @@ -57,7 +57,15 @@ local qwebrCapturedCodeBlocks = {} -- Initialize a table that contains the default cell-level options local qwebRDefaultCellOptions = { - ["context"] = "interactive" + ["context"] = "interactive", + ["warning"] = "true", + ["message"] = "true", + ["results"] = "markup", + ["dpi"] = 72, + ["fig-width"] = 7, + ["fig-height"] = 5, + ["out-width"] = "700px", + ["out-height"] = "" } ---- @@ -102,6 +110,9 @@ local function mergeCellOptions(localOptions) -- Override default options with local options for key, value in pairs(localOptions) do + if type(value) == "string" then + value = value:gsub("[\"']", "") + end mergedOptions[key] = value end diff --git a/docs/_quarto.yml b/docs/_quarto.yml index ac39a3df..99cffde2 100644 --- a/docs/_quarto.yml +++ b/docs/_quarto.yml @@ -22,7 +22,9 @@ website: - href: qwebr-first-steps.qmd text: Your first webR-powered Quarto document - href: qwebr-meta-options.qmd - text: Customization Options + text: Document Options + - href: qwebr-cell-options.qmd + text: Code Cell Options - href: qwebr-using-r-packages.qmd text: Using R Packages - href: qwebr-internal-cell.qmd diff --git a/docs/demos/qwebr-code-cell-options.qmd b/docs/demos/qwebr-code-cell-options.qmd new file mode 100644 index 00000000..8304078b --- /dev/null +++ b/docs/demos/qwebr-code-cell-options.qmd @@ -0,0 +1,243 @@ +--- +title: "Demo: Initial Code Cell Option Support" +engine: knitr +webr: + packages: ['knitr', 'plot2'] + repos: + - https://grantmcdermott.r-universe.dev +filters: + - webr +--- + +# Overview + +In this document, we will explore and demonstrate the various cell options available in `{webr-r}` code blocks. These options allow you to customize the behavior and appearance of your code outputs. These options can only be set during the authoring stage of the document. + +## `context` Option + +The `context` option specifies how the cell should operate on the page. Let's use it to create an interactive code editor: + +::: {.panel-tabset group="language"} +#### `{quarto-webr}` Output +```{webr-r} +#| context: interactive +# Write your name here by replace ___ +name <- "_____" +print(paste0("Hello, ", name, "!")) +``` +#### Cell Code +````md +```{webr-r} +#| context: interactive + +# Write your name here by replace ___ +name <- "_____" +print(paste0("Hello, ", name, "!")) +``` +```` +::: + +In this code block, the `context: interactive` option is applied, allowing users to interactively input their name. + +Next, let's use the `context: setup` option to create a data set that can be used by later cells. + +::: {.panel-tabset group="language"} +#### `{quarto-webr}` Output +```{webr-r} +#| context: setup + +# Generating a simple table +data <- data.frame( + Name = c("Alice", "Bob", "Charlie"), + Age = c(25, 30, 22) +) +``` +#### Cell Code +````md +```{webr-r} +#| context: setup + +# Generating a simple table +data <- data.frame( + Name = c("Alice", "Bob", "Charlie"), + Age = c(25, 30, 22) +) +``` +```` +::: + +:::{.callout-note} +Once a `context:setup` is done running, the visual indicator will be removed from the document. +::: + +In a later block, we'll see a `context: output` that will only display the results. + +## `results` Option + +The `results` option controls how text results are displayed. Let's use it to display raw text output: + +::: {.panel-tabset group="language"} +#### `{quarto-webr}` Output +```{webr-r} +#| context: interactive +#| results: asis +knitr::kable(data, "html") +``` + +#### Cell Code +````md +```{webr-r} +#| context: interactive +#| results: asis +knitr::kable(data, "html") +``` +```` +::: + +In the above code block, the `results: asis` option is used to display the raw text output of the `data` dataframe. + +If we use `results: markup`, then we'll end up seeing the HTML output: + + +::: {.panel-tabset group="language"} +#### `{quarto-webr}` Output + +```{webr-r} +#| context: interactive +#| results: markup +knitr::kable(data, "html") +``` +#### Cell Code +````md +```{webr-r} +#| context: interactive +#| results: markup + +knitr::kable(data, "html") +``` +```` +::: + +## `fig-width` and `fig-height` Option + +The `fig-width` and `fig-height` options control the width and height of the plot generated in the code block. Let's use it to create a plot with a specific width: + +::: {.panel-tabset group="language"} +#### `{quarto-webr}` Output +```{webr-r} +#| context: output +#| fig-width: 6 +#| fig-height: 6 + +plot2::plot2( + ~ Petal.Length | Species, + data = iris, + type = "density", + palette = "dark", fill = "by", + grid = TRUE, + main = "Distribution of petal lengths by species" +) +``` +#### Cell Code +````md +```{webr-r} +#| context: output +#| fig-width: 6 +#| fig-height: 6 + +# Generating a bar plot with a specific width +plot2::plot2( + ~ Petal.Length | Species, + data = iris, + type = "density", + palette = "dark", fill = "by", + grid = TRUE, + main = "Distribution of petal lengths by species" +) +``` +```` +::: + +Here, the `fig-width: 6` and `fig-height: 6` option is utilized to set the width of the bar plot. + +In comparison, we have the default option of `7`: + +::: {.panel-tabset group="language"} +#### `{quarto-webr}` Output +```{webr-r} +#| context: output + +plot2::plot2( + ~ Petal.Length | Species, + data = iris, + type = "density", + palette = "dark", fill = "by", + grid = TRUE, + main = "Distribution of petal lengths by species" +) +``` +#### Cell Code +````md +```{webr-r} +#| context: output + +plot2::plot2( + ~ Petal.Length | Species, + data = iris, + type = "density", + palette = "dark", fill = "by", + grid = TRUE, + main = "Distribution of petal lengths by species" +) +``` +```` +::: + +## `out-width` and `out-height` Option + +The `out-width` and `out-height` options control physical space the plot will reside in. Let's revisit our previous example and constrain the output area by specifying `out-width: 500px` and `out-height: 500px`. + + +::: {.panel-tabset group="language"} +#### `{quarto-webr}` Output +```{webr-r} +#| context: output +#| fig-width: 6 +#| fig-height: 6 +#| out-width: 500px +#| out-height: 500px +plot2::plot2( + ~ Petal.Length | Species, + data = iris, + type = "density", + palette = "dark", fill = "by", + grid = TRUE, + main = "Distribution of petal lengths by species" +) +``` +#### Cell Code +````md +```{webr-r} +#| context: output +#| fig-width: 5 +#| fig-height: 5 +#| out-width: 500px +#| out-height: 400px +plot2::plot2( + ~ Petal.Length | Species, + data = iris, + type = "density", + palette = "dark", fill = "by", + grid = TRUE, + main = "Distribution of petal lengths by species" +) +``` +```` +::: + + +## Conclusion + +These examples demonstrate the versatility of `{webr-r}` cell options in customizing code block behavior and output. By incorporating these options into your documents, you can enhance the interactivity and visual presentation of your R code. + +Feel free to experiment with different combinations of these options to suit your specific needs! diff --git a/docs/demos/qwebr-feature-demos.qmd b/docs/demos/qwebr-feature-demos.qmd index 527081c3..ff54932b 100644 --- a/docs/demos/qwebr-feature-demos.qmd +++ b/docs/demos/qwebr-feature-demos.qmd @@ -4,6 +4,7 @@ title: "Feature Demonstrations" Below is a list of different demonstrations of the extensions features. These demos were created to showcase different feature releases. +- [Initial Code Cell Option Support](qwebr-code-cell-options.qmd) - [Using Custom Repositories for R WASM Package binaries](qwebr-custom-repository.qmd) - [Revamped Noninteractive Areas](qwebr-non-interactive-areas.qmd) - [webR in RevealJS](https://quarto-webr.thecoatlessprofessor.com/examples/revealjs) diff --git a/docs/qwebr-cell-options.qmd b/docs/qwebr-cell-options.qmd new file mode 100644 index 00000000..431b7ccd --- /dev/null +++ b/docs/qwebr-cell-options.qmd @@ -0,0 +1,66 @@ +--- +title: "Code Cell Options" +subtitle: "Supported Cell Options in `{webr-r}` Blocks" +date: "01-30-2024" +date-modified: last-modified +format: + html: + toc: true +engine: knitr +--- + +This article provides an in-depth overview of cell options supported in `{webr-r}` code blocks. These options play a crucial role in influencing the execution and output of executable code blocks. It's important to note that these cell options are specified within comments at the top of a code block by using a hashpipe `#| option: value`. + +Here's an example of how you can use these options: + +````md +```{webr-r} +#| results: 'asis' +#| fig-width: 5 + +# R code here +``` +```` + +In this example, the cell options `results` is set to `'asis'`, and `fig-width` is set to `5` inches. + +These options can be customized to tailor the behavior of the code block based on your specific requirements. Understanding and using these options effectively can enhance the overall control and presentation of your code outputs. + + +:::{.callout-important} +The `{quarto-webr}` extension does not support all of the cell options from [Quarto](https://quarto.org/docs/reference/cells/cells-knitr.html) or [Knitr](https://yihui.org/knitr/options/). Please consult below for details on what is available. +::: + +## webR + +| Option | Default Value | Description | +|-----------|-----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `context` | `"interactive"` | Describe how the cell should operate on the page through either `"interactive"` (Runnable code editor), `"output"` (Output only of executed at runtime), or `"setup"` (execute code without seeing output at runtime). | + + +:::{.callout-note} +The `context` option is unique to the `{quarto-webr}` extension. For more details, please see [Hiding and Executing Code](qwebr-internal-cell.qmd). +::: + +## Cell Output + +| Option | Default Value | Description | +|-----------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `results` | `'markup'` | Controls how to display the text results through either: `'markup'` (Mark up text output with appropriate environments), `'asis'` (Write text output as-is, raw text results directly into the output document), or `'hide'` (Hide text output). | +| `warning` | `true` | Preserve standard error output (`warning()`, `message()`, or `stop()`) in the output. | +| `message` | `true` | See prior entry. | + + +:::{.callout-important} +At the present time, we cannot differentiate between the type of condition being sent to standard error. Thus, if either `warning` or `message` is set to `false`, the output for both will be surpressed. +::: + +## Figures + +| Option | Default Value | Description | +|--------------|---------------|-------------------------------------------------------------------------------------------------------------------------------| +| `dpi` | 72 | Dots per inch to use in calculating pixel values for `fig-height` and `fig-width`, e.g. `dpi * inches = pixels`. | +| `fig-width` | 7 | Width of the plot (in inches) | +| `fig-height` | 5 | Height of the plot (in inches) | +| `out-width` | `"700px"` | Width of the plot in the output document, which can be different from its physical `fig-width` such as `"100%"` or `"250px"`. | +| `out-height` | `""` | Height of the plot in the output document, similar to `out-width`. | diff --git a/docs/qwebr-release-notes.qmd b/docs/qwebr-release-notes.qmd index d02f12b0..9f4e943b 100644 --- a/docs/qwebr-release-notes.qmd +++ b/docs/qwebr-release-notes.qmd @@ -20,12 +20,14 @@ format: - Implemented a custom JSON format for code cell data and option sharing between Quarto and webR. ([#120](https://github.com/coatless/quarto-webr/pull/120)) - Redesigned non-interactive cells to provide improved reliability and visual cues. ([#120](https://github.com/coatless/quarto-webr/pull/120)) - Interactive cells now have a toolbar above them that provides three actions: Run Code, Start Over, and Copy. ([#91](https://github.com/coatless/quarto-webr/issues/91)) +- Initial code cell option support for changing figure width and height (`dpi`, `fig-width`, `fig-height`, `out-width`, & `out-height`), suppressing standard error messages generated by `warning()`, `message()`, and `stop()` (`warning: false` or `message: false`), and allowing content to appear as-is (`results: 'asis'`). ([#104](https://github.com/coatless/quarto-webr/issues/104), [#125](https://github.com/coatless/quarto-webr/issues/125)) - Added `repos` document meta option key to specify custom package repositories containing compiled R WASM Packages not found in the main [webR repository](https://repo.r-wasm.org/) ([#124](https://github.com/coatless/quarto-webr/issues/124), [#132](https://github.com/coatless/quarto-webr/pull/132)). ## Changes - Added new CSS IDs governing the webR initialization state. ([#110](https://github.com/coatless/quarto-webr/issues/110)) - Added shim that overrides `install.packages()` with `webr::install()` through `webr::shim_install()` this requires webR v0.2.2 to be in use. ([#122](https://github.com/coatless/quarto-webr/issues/122)) +- Added the keyboard shortcut for Run Code -- `Shift + Enter` -- to mouseover text for the Run Code button. ([#91](https://github.com/coatless/quarto-webr/pulls/138)) - Updated the version of the MonacoEditor from 0.43.0 to 0.45.0. ([#130](https://github.com/coatless/quarto-webr/pull/130)) - Updated the version of the FontAwesome from 6.4.2 to 6.5.1. ([#131](https://github.com/coatless/quarto-webr/pull/131)) diff --git a/tests/qwebr-test-escape-html-output-characters.qmd b/tests/qwebr-test-escape-html-output-characters.qmd index d76717f1..2fee9237 100644 --- a/tests/qwebr-test-escape-html-output-characters.qmd +++ b/tests/qwebr-test-escape-html-output-characters.qmd @@ -22,8 +22,24 @@ Ensure HTML output is escaped. ## Non-interactive +### Escape HTML Characters + +```{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, ''))) +})() +``` + +### Leave characters asis + ```{webr-r} #| context: output +#| results: asis # This function converts a markdown link into HTML "[Posit](https://posit.co)" |> (\(.) { text <- sub("\\].*", "", sub(".*\\[", "", .)) @@ -32,3 +48,4 @@ Ensure HTML output is escaped. writeLines(noquote(paste0('', text, ''))) })() ``` + diff --git a/tests/qwebr-test-output-graph.qmd b/tests/qwebr-test-output-graph.qmd index 81025e2e..ede33849 100644 --- a/tests/qwebr-test-output-graph.qmd +++ b/tests/qwebr-test-output-graph.qmd @@ -9,13 +9,48 @@ filters: This webpage tests the interactive and output contexts for showing a graph ## Interactive + +### Default options +```{webr-r} +#| context: interactive +plot(pressure) +``` + +### Reduced fig height & width + ```{webr-r} #| context: interactive +#| fig-height: 6 +#| fig-width: 4 +#| out-width: 600px plot(pressure) ``` + ## Non-interactive + +### Default options +```{webr-r} +#| context: output +plot(pressure) +``` + +### Reduced fig height & width +```{webr-r} +#| context: output +#| fig-height: 5 +#| fig-width: 6 +#| out-width: 500px +plot(pressure) +``` + + +### Reduced fig height & width ```{webr-r} #| context: output +#| fig-height: 5 +#| fig-width: 6 +#| out-width: 500px +#| out-height: 500px plot(pressure) ``` \ No newline at end of file diff --git a/tests/qwebr-test-output-stderr-result-suppression.qmd b/tests/qwebr-test-output-stderr-result-suppression.qmd new file mode 100644 index 00000000..c3396730 --- /dev/null +++ b/tests/qwebr-test-output-stderr-result-suppression.qmd @@ -0,0 +1,96 @@ +--- +title: "Test: STDErr & Result Output Suppression" +format: html +engine: knitr +filters: + - webr +--- + +Test options for disabling standard error (`warning: false` or `message: false`) and `results = 'hide'` + +## Interactive + +### Suppresion with hide + +```{webr-r} +#| context: interactive +#| results: hide +cat("Display letters: ") +print(letters[1:5]) + +warning("This is a warning message!") + +stop("This is a hard error message!") +``` + + +### Suppression with warning + +```{webr-r} +#| context: interactive +#| warning: false +cat("Display letters: ") +print(letters[1:5]) + +warning("This is a warning message!") + +stop("This is a hard error message!") +``` + + +### Suppression with message + +```{webr-r} +#| context: interactive +#| message: false +cat("Display letters: ") +print(letters[1:5]) + +warning("This is a warning message!") + +stop("This is a hard error message!") +``` + + +## Non-interactive + +### Suppresion with hide + +```{webr-r} +#| context: output +#| results: hide +cat("Display letters: ") +print(letters[1:5]) + +warning("This is a warning message!") + +stop("This is a hard error message!") +``` + + +### Suppression with warning + +```{webr-r} +#| context: output +#| warning: false +cat("Display letters: ") +print(letters[1:5]) + +warning("This is a warning message!") + +stop("This is a hard error message!") +``` + + +### Suppression with message + +```{webr-r} +#| context: output +#| message: false +cat("Display letters: ") +print(letters[1:5]) + +warning("This is a warning message!") + +stop("This is a hard error message!") +```