├── .devcontainer
└── devcontainer.json
├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug-report.yml
│ ├── community-example.yml
│ ├── config.yml
│ ├── feature-request.yml
│ └── question.yml
└── workflows
│ └── publish-demo.yml
├── .gitignore
├── README.md
├── _extensions
└── webr
│ ├── _extension.yml
│ ├── qwebr-cell-elements.js
│ ├── qwebr-cell-initialization.js
│ ├── qwebr-compute-engine.js
│ ├── qwebr-document-engine-initialization.js
│ ├── qwebr-document-history.js
│ ├── qwebr-document-settings.js
│ ├── qwebr-document-status.js
│ ├── qwebr-monaco-editor-element.js
│ ├── qwebr-monaco-editor-init.html
│ ├── qwebr-styling.css
│ ├── qwebr-theme-switch.js
│ ├── template.qmd
│ └── webr.lua
├── _publish.yml
├── docs
├── .gitignore
├── CNAME
├── _extensions
├── _quarto.yml
├── demos
│ ├── qwebr-auto-run.qmd
│ ├── qwebr-code-cell-options.qmd
│ ├── qwebr-custom-repository.qmd
│ ├── qwebr-editor-options.qmd
│ ├── qwebr-feature-demos.qmd
│ ├── qwebr-global-cell-defaults.qmd
│ ├── qwebr-long-running-execution-interactive-locking.qmd
│ ├── qwebr-non-interactive-areas.qmd
│ ├── qwebr-read-only.qmd
│ └── qwebr-setting-options-in-document-yaml.qmd
├── images
│ └── rstudio-render-button.png
├── index.qmd
├── qwebr-acknowledgements.md
├── qwebr-cell-options.qmd
├── qwebr-code-cell-demos.qmd
├── qwebr-communication-channels.qmd
├── qwebr-community-examples.qmd
├── qwebr-deployment-templates.qmd
├── qwebr-developer-resources.qmd
├── qwebr-extension-website.qmd
├── qwebr-faq.qmd
├── qwebr-first-steps.qmd
├── qwebr-internal-cell.qmd
├── qwebr-loading-data.qmd
├── qwebr-meta-options.qmd
├── qwebr-release-notes.qmd
├── qwebr-theming.qmd
├── qwebr-troubleshooting.qmd
└── qwebr-using-r-packages.qmd
├── examples
├── blog
│ ├── .gitignore
│ ├── _extensions
│ ├── _quarto.yml
│ ├── about.qmd
│ ├── index.qmd
│ ├── posts
│ │ ├── _metadata.yml
│ │ ├── embed-slides
│ │ │ ├── image.jpg
│ │ │ └── index.qmd
│ │ └── post-with-code
│ │ │ ├── image.jpg
│ │ │ └── index.qmd
│ ├── profile.jpg
│ └── styles.css
├── book
│ ├── .gitignore
│ ├── _extensions
│ ├── _quarto.yml
│ ├── example-page.qmd
│ ├── index.qmd
│ └── slide-embed.qmd
├── html-document
│ ├── .gitignore
│ ├── _extensions
│ ├── _quarto.yml
│ └── index.qmd
├── readme
│ ├── _extensions
│ ├── _quarto.yml
│ └── index.qmd
├── revealjs
│ ├── .gitignore
│ ├── _extensions
│ ├── _quarto.yml
│ └── index.qmd
└── website
│ ├── .gitignore
│ ├── _extensions
│ ├── _quarto.yml
│ ├── example-page.qmd
│ ├── index.qmd
│ └── slide-embed.qmd
├── quarto-webr.code-workspace
├── tests
├── .gitignore
├── _extensions
├── _quarto.yml
├── index.qmd
├── qwebr-test-editor-options.qmd
├── qwebr-test-escape-html-output-characters.qmd
├── qwebr-test-global-cell-options.qmd
├── qwebr-test-help-documentation.qmd
├── qwebr-test-interactive-with-keyboard-shortcut.qmd
├── qwebr-test-internal-cell.qmd
├── qwebr-test-multiple-cells.qmd
├── qwebr-test-non-interactive-chained-cells.qmd
├── qwebr-test-non-interactive-context-with-packages.qmd
├── qwebr-test-non-interactive-setup-with-packages-and-interactive.qmd
├── qwebr-test-non-interactive-setup-with-packages.qmd
├── qwebr-test-option-space-removal.qmd
├── qwebr-test-output-classes.qmd
├── qwebr-test-output-graph.qmd
├── qwebr-test-output-stderr-result-suppression.qmd
├── qwebr-test-packages-autoload.qmd
├── qwebr-test-packages-multi.qmd
├── qwebr-test-repo-key.qmd
├── qwebr-test-revealjs.qmd
├── qwebr-test-run-built-in.qmd
├── qwebr-test-run-latest.qmd
├── qwebr-test-self-contained.qmd
├── qwebr-test-service-worker-version.qmd
├── qwebr-test-service-worker.qmd
├── qwebr-test-shim-install.qmd
├── qwebr-test-status-header-no-title.qmd
├── qwebr-test-status-header-suppressed-html copy.qmd
├── qwebr-test-status-header-suppressed-revealjs.qmd
└── qwebr-test-theme-switch.qmd
└── update-quarto-dev.sh
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | // Config options: https://github.com/rocker-org/devcontainer-templates/tree/main/src/r-ver
2 | {
3 | "name": "R (rocker/r-ver base)",
4 | "image": "ghcr.io/rocker-org/devcontainer/r-ver:4.3",
5 | // Add software
6 | "features": {
7 | // R package config: https://github.com/rocker-org/devcontainer-features/blob/main/src/r-packages/README.md
8 | "ghcr.io/rocker-org/devcontainer-features/r-packages:1": {
9 | "packages": "cli,rlang,knitr",
10 | "installSystemRequirements": true
11 | },
12 | // Quarto configuration : https://github.com/rocker-org/devcontainer-features/blob/main/src/quarto-cli/README.md
13 | "ghcr.io/rocker-org/devcontainer-features/quarto-cli:1": {
14 | "installTinyTex": true,
15 | "version": "prerelease"
16 | }
17 | },
18 | "customizations": {
19 | "vscode": {
20 | "extensions": [
21 | "quarto.quarto",
22 | "sumneko.lua",
23 | "peakchen90.open-html-in-browser"
24 | ]
25 | },
26 | "codespaces": {
27 | "openFiles": [
28 | "examples/readme/index.qmd"
29 | ]
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [coatless] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.yml:
--------------------------------------------------------------------------------
1 | name: Bug report
2 | description: Report an error or unexpected behavior
3 | labels: ['t: bug', 's: triage-needed']
4 | title: "[Bug]: "
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | Welcome to the quarto-webr Extension GitHub repository!
10 |
11 | We're sorry to hear that you might have encounter a bug; we're happy that you want to let us know so that we can make the extension even better.
12 |
13 | Thank you in advance for your feedback.
14 |
15 | - type: textarea
16 | attributes:
17 | label: Bug description
18 | description: Description of the bug and why you think its a bug.
19 | placeholder: Please describe the bug here.
20 |
21 | - type: textarea
22 | attributes:
23 | label: Steps to reproduce
24 | description: |
25 | Tell us how to reproduce this bug.
26 |
27 | Please include a minimal, fully reproducible example as a self-contained Quarto document or a link to a Git repository.
28 | placeholder: |
29 | You can share a Quarto document using the following syntax, _i.e._, using more backticks than you have in your document (usually four ` ```` `).
30 |
31 | ````qmd
32 | ---
33 | title: "Reproducible webR powered Quarto Document"
34 | format: html
35 | filter:
36 | - webr
37 | ---
38 |
39 | This is a reproducible Quarto document using `format: html` with
40 | the `webr` filter active. It contains a webr code cell that
41 | should create a plot using the cars data.
42 |
43 | ```{webr-r}
44 | plot(cars)
45 | ```
46 |
47 | The end.
48 | ````
49 |
50 | - type: textarea
51 | attributes:
52 | label: Your environment
53 | description: |
54 | Please document the IDE (_e.g._ RStudio, VSCode, NVim), its version, and the operating system you're running (_e.g., MacOS Ventura 13.4, Windows 11, Linux Debian 11, _etc._).
55 | placeholder: |
56 | - IDE: RStudio 2023.06.2+561
57 | - OS: MacOS Ventura 13.4
58 |
59 | - type: textarea
60 | attributes:
61 | label: Quarto check output
62 | description: |
63 | Please provide the output of `quarto check` so we know which version of quarto and its dependencies you're running.
64 | placeholder: |
65 | ```bash
66 | quarto check
67 | ```
68 |
69 | - type: markdown
70 | attributes:
71 | value: "_Thanks for submitting this bug report!_"
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/community-example.yml:
--------------------------------------------------------------------------------
1 | name: Example
2 | description: Contribute an Example
3 | labels: ['t: documentation', 't: community-example']
4 | title: "[Example]: "
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | We appreciate you taking the time out of your day to let us know about the example!
10 | We love to include links to videos, talks, notebooks, course websites, workshops, blog posts, and so on!
11 |
12 | **Thank you for letting us know!**
13 | - type: textarea
14 | attributes:
15 | label: What's your question?
16 | description: |
17 | Feel free to just start writing about the example!
18 | validations:
19 | required: true
20 | - type: markdown
21 | attributes:
22 | value: |
23 | _Thank you for opening this issue to let us know about the example!_
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: true
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.yml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Ask for a feature to be added
3 | labels: ['t: feature-request']
4 | title: "[Feature]: "
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | First, please check [`quarto-webr` Issue Tracker](https://github.com/coatless/quarto-webr/issues?q=is%3Aissue+) to see if your feature request has already been discussed.
10 | If it has, please consider adding a comment to the existing issue instead of creating a new one.
11 |
12 | After checking, if you are not sure if your feature request has already been discussed, please create a new issue.
13 | We look forward to hearing from you.
14 |
15 | Finally, try to describe the best you can what you want to achieve and why you think it is important.
16 | This will help us to understand your request and prioritise it.
17 |
18 | _Thank you for opening this feature request!_
19 | - type: textarea
20 | attributes:
21 | label: Feature Description
22 | description: Please discuss your feature request here!
23 | validations:
24 | required: true
25 | - type: markdown
26 | attributes:
27 | value: |
28 | _Thank you for opening this feature request!_
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.yml:
--------------------------------------------------------------------------------
1 | name: Question
2 | description: Ask a question
3 | labels: ['t: question', 's: question-needs-answer']
4 | title: "[Q&A]: "
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | **Before You Begin:**
10 | 1. Check the [**quarto-webr Issue Tracker**](https://github.com/coatless/quarto-webr/issues?q=is%3Aissue+) to ensure your question hasn't already been addressed.
11 |
12 | 2. If you're uncertain, feel free to create a new issue; we appreciate your engagement.
13 |
14 | **Creating a New Issue:**
15 |
16 | If you're creating a new issue, please provide the following information:
17 |
18 | 1. **Description**: Clearly state your question or problem.
19 |
20 | 2. **Goal**: Explain what you're trying to achieve or the challenge you're facing.
21 |
22 | 3. **Significance**: Share why this issue matters to you or the project.
23 |
24 | 4. **Additional Information**: Include any relevant context, such as your system setup, actions taken so far, and any potential solutions you've considered.
25 |
26 | **Thank you for reaching out!**
27 | - type: textarea
28 | attributes:
29 | label: What's your question?
30 | description: |
31 | You can include webR-powered Quarto document code with your question by using:
32 |
33 | ````qmd
34 | ---
35 | title: "Hello quarto-webr!"
36 | format: html
37 | filters:
38 | - webr
39 | ---
40 |
41 | ```{webr-r}
42 | 1 + 1
43 | ```
44 | ````
45 |
46 | validations:
47 | required: true
48 | - type: markdown
49 | attributes:
50 | value: |
51 | _Thank you for opening this issue to ask a question!_
--------------------------------------------------------------------------------
/.github/workflows/publish-demo.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches: [main, master]
4 | release:
5 | types: [published]
6 | workflow_dispatch: {}
7 |
8 | name: doc-website
9 |
10 | jobs:
11 | demo-website:
12 | runs-on: ubuntu-latest
13 | # Only restrict concurrency for non-PR jobs
14 | concurrency:
15 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
16 | permissions:
17 | contents: write
18 | steps:
19 | - name: "Check out repository"
20 | uses: actions/checkout@v4
21 |
22 | # To render using knitr, we need a few more setup steps...
23 | # If we didn't want the examples to use `engine: knitr`, we could
24 | # skip a few of the setup steps.
25 | - name: "Setup pandoc"
26 | uses: r-lib/actions/setup-pandoc@v2
27 |
28 | - name: "Setup R"
29 | uses: r-lib/actions/setup-r@v2
30 |
31 | - name: "Setup R dependencies for Quarto's knitr engine"
32 | uses: r-lib/actions/setup-r-dependencies@v2
33 | with:
34 | packages:
35 | any::knitr
36 | any::rmarkdown
37 | any::downlit
38 | any::xml2
39 |
40 | # Back to our regularly scheduled Quarto output
41 | - name: "Set up Quarto"
42 | uses: quarto-dev/quarto-actions/setup@v2
43 | with:
44 | version: "pre-release"
45 |
46 | # Generate the documentation website
47 | - name: Render Documentation website
48 | uses: quarto-dev/quarto-actions/render@v2
49 | with:
50 | path: "docs"
51 |
52 | # Attempt to render the nested deployment template Quarto projects
53 | - name: Render README demo
54 | uses: quarto-dev/quarto-actions/render@v2
55 | with:
56 | path: "examples/readme/index.qmd"
57 |
58 | - name: Render sample deployment RevealJS presentation template
59 | uses: quarto-dev/quarto-actions/render@v2
60 | with:
61 | path: "examples/revealjs/index.qmd"
62 |
63 | - name: Render sample deployment HTML document template
64 | uses: quarto-dev/quarto-actions/render@v2
65 | with:
66 | path: "examples/html-document/index.qmd"
67 |
68 | - name: Render sample deployment website template
69 | uses: quarto-dev/quarto-actions/render@v2
70 | with:
71 | path: "examples/website"
72 |
73 | - name: Render sample deployment blog template
74 | uses: quarto-dev/quarto-actions/render@v2
75 | with:
76 | path: "examples/blog"
77 |
78 | - name: Render sample deployment book template
79 | uses: quarto-dev/quarto-actions/render@v2
80 | with:
81 | path: "examples/book"
82 |
83 | - name: Render test suite
84 | uses: quarto-dev/quarto-actions/render@v2
85 | with:
86 | path: "tests"
87 |
88 | # Collect the output into the staging/ directory
89 | - name: Copy documentation portal & examples into the staging directory
90 | run: |
91 | mkdir -p staging/{examples,tests} && \
92 | cp -rp docs/_site/* staging/ && \
93 | cp -rp tests/_site/* staging/tests/ && \
94 | cp -rp examples/book/_book staging/examples/book && \
95 | cp -rp examples/website/_site staging/examples/website && \
96 | cp -rp examples/blog/_site staging/examples/blog && \
97 | cp -rp examples/html-document/ staging/examples/html-document && \
98 | cp -rp examples/revealjs/ staging/examples/revealjs && \
99 | cp -rp examples/readme/ staging/examples/readme
100 |
101 | # Remove symlinks
102 | - name: Delete symlinks
103 | run: |
104 | rm -rf staging/examples/*/_extensions && \
105 | rm -rf staging/tests/_extensions
106 |
107 | # Publish the docs directory onto gh-pages
108 | - name: Deploy 🚀
109 | uses: JamesIves/github-pages-deploy-action@v4
110 | with:
111 | folder: staging # The folder the action should deploy.
112 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.luarc.json
2 | *.luarc.json
3 | *.DS_Store
4 | webr-worker.js
5 | webr-serviceworker.js
6 | *.csv
7 | *_files
8 | docs/_site/*
9 | tests/_site/*
10 | *.html
11 | !_extensions/*/*
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # webR Extension for Quarto
2 |
3 | > [!IMPORTANT]
4 | >
5 | > Looking for the official Quarto WebAssembly backend? Check out [`quarto-live`](https://github.com/r-wasm/quarto-live)!
6 |
7 | This community developed Quarto extension enables the [webR](https://docs.r-wasm.org/webr/latest/) code cell within various [Quarto](https://quarto.org/) formats, including [HTML](https://quarto.org/docs/output-formats/html-basics.html), [RevealJS](https://quarto.org/docs/presentations/revealjs/), [Websites](https://quarto.org/docs/websites/), [Blogs](https://quarto.org/docs/websites/website-blog.html), and [Books](https://quarto.org/docs/books).
8 |
9 | 
10 |
11 | Take a look at a live example of the extension in action [here](https://quarto-webr.thecoatlessprofessor.com/examples/readme)! To delve deeper into the extension's capabilities, see our comprehensive [documentation website](https://quarto-webr.thecoatlessprofessor.com/).
12 |
13 | Looking for a Python version? Check out [`quarto-pyodide`](https://github.com/coatless-quarto/pyodide)!
14 |
15 | > [!NOTE]
16 | > Please note that the `{quarto-webr}` Quarto extension is a community-driven initiative and is **not** affiliated with Posit, Quarto, or the main [webR](https://docs.r-wasm.org/webr/latest/) project. Its evolution and maintenance stem solely from the collective efforts of community members.
17 |
18 | ## Background
19 |
20 | If you're new to [webR](https://docs.r-wasm.org/webr/latest/), this cutting-edge technology empowers you to:
21 |
22 | > "run R code in the browser without the need for an R server to execute the code."
23 |
24 | For a deeper understanding of [webR](https://docs.r-wasm.org/webr/latest/), explore the following resources:
25 |
26 | - [webR Documentation](https://docs.r-wasm.org/webr/latest/)
27 | - [webR Source Code](https://github.com/r-wasm/webr/)
28 |
29 | ## Quick Start Video Guide
30 |
31 | For those new to Quarto and Quarto Extensions, we highly recommend checking out this informative [YouTube video](https://youtu.be/DoRR2S5lLvk?t=5) to get started quickly:
32 |
33 | [](https://youtu.be/DoRR2S5lLvk?t=5)
34 |
35 | ## Installation
36 |
37 | To use this extension in a [Quarto project](https://quarto.org/docs/projects/quarto-projects.html), install it from within the project's working directory by typing into **Terminal**:
38 |
39 | ``` bash
40 | quarto add coatless/quarto-webr
41 | ```
42 |
43 | 
44 |
45 | After the installation process is finished, the extension will be readily available for Quarto documents within the designated working directory. Please note that if you are working on projects located in different directories, you will need to repeat this installation step for each of those directories.
46 |
47 | ## Usage
48 |
49 | For each document, place the `webr` filter in the document's header:
50 |
51 | ```yaml
52 | filters:
53 | - webr
54 | ```
55 |
56 | Then, place the R code for `webR` in a code block marked with `{webr-r}`
57 |
58 | ````markdown
59 | ---
60 | title: webR in Quarto HTML Documents
61 | format: html
62 | engine: knitr
63 | filters:
64 | - webr
65 | ---
66 |
67 | This is a webR-enabled code cell in a Quarto HTML document.
68 |
69 | ```{webr-r}
70 | fit = lm(mpg ~ am, data = mtcars)
71 |
72 | summary(fit)
73 | ```
74 | ````
75 |
76 | The rendered document can be viewed online [here](https://quarto-webr.thecoatlessprofessor.com/examples/readme).
77 |
78 | **Note:** If you don't specify the `engine: knitr`, the default compute engine used will be `jupyter`. This could trigger prompts to install Python. However, if you specify `engine: knitr`, there's no need to install Python.
79 |
80 | There are many more customization options that are available. Please see the [customization documentation](https://quarto-webr.thecoatlessprofessor.com/qwebr-meta-options.html) for more examples.
81 |
82 | For specific deployment usage cases, please see [Templates](https://quarto-webr.thecoatlessprofessor.com/qwebr-deployment-templates.html).
83 |
84 | ## Help
85 |
86 | For troubleshooting help, please see our [troubleshooting page](https://quarto-webr.thecoatlessprofessor.com/qwebr-troubleshooting.html).
87 |
88 | To report a bug, please [add an issue](https://github.com/coatless/quarto-webr/issues/new) to the repository's [bug tracker](https://github.com/coatless/quarto-webr/issues).
89 |
90 | Want to contribute a feature? Please open an issue ticket to discuss the feature before sending a pull request.
91 |
92 | ## Acknowledgements
93 |
94 | Please see our [acknowledgements page](https://quarto-webr.thecoatlessprofessor.com/qwebr-acknowledgements.html).
95 |
--------------------------------------------------------------------------------
/_extensions/webr/_extension.yml:
--------------------------------------------------------------------------------
1 | name: webr
2 | title: Embedded webr code cells
3 | author: James Joseph Balamuta
4 | version: 0.4.3-dev.2
5 | quarto-required: ">=1.4.554"
6 | contributes:
7 | filters:
8 | - webr.lua
9 |
--------------------------------------------------------------------------------
/_extensions/webr/qwebr-cell-initialization.js:
--------------------------------------------------------------------------------
1 | // Handle cell initialization initialization
2 | qwebrCellDetails.map(
3 | (entry) => {
4 | // Handle the creation of the element
5 | qwebrCreateHTMLElement(entry);
6 | // In the event of interactive, initialize the monaco editor
7 | if (entry.options.context == EvalTypes.Interactive) {
8 | qwebrCreateMonacoEditorInstance(entry);
9 | }
10 | }
11 | );
12 |
13 | // Identify non-interactive cells (in order)
14 | const filteredEntries = qwebrCellDetails.filter(entry => {
15 | const contextOption = entry.options && entry.options.context;
16 | return ['output', 'setup'].includes(contextOption) || (contextOption == "interactive" && entry.options && entry.options.autorun === 'true');
17 | });
18 |
19 | // Condition non-interactive cells to only be run after webR finishes its initialization.
20 | qwebrInstance.then(
21 | async () => {
22 | const nHiddenCells = filteredEntries.length;
23 | var currentHiddenCell = 0;
24 |
25 |
26 | // Modify button state
27 | qwebrSetInteractiveButtonState(`🟡 Running hidden code cells ...`, false);
28 |
29 | // Begin processing non-interactive sections
30 | // Due to the iteration policy, we must use a for() loop.
31 | // Otherwise, we would need to switch to using reduce with an empty
32 | // starting promise
33 | for (const entry of filteredEntries) {
34 |
35 | // Determine cell being examined
36 | currentHiddenCell = currentHiddenCell + 1;
37 | const formattedMessage = `Evaluating hidden cell ${currentHiddenCell} out of ${nHiddenCells}`;
38 |
39 | // Update the document status header
40 | if (qwebrShowStartupMessage) {
41 | qwebrUpdateStatusHeader(formattedMessage);
42 | }
43 |
44 | // Display the update in non-active areas
45 | qwebrUpdateStatusMessage(formattedMessage);
46 |
47 | // Extract details on the active cell
48 | const evalType = entry.options.context;
49 | const cellCode = entry.code;
50 | const qwebrCounter = entry.id;
51 |
52 | if (['output', 'setup'].includes(evalType)) {
53 | // Disable further global status updates
54 | const activeContainer = document.getElementById(`qwebr-non-interactive-loading-container-${qwebrCounter}`);
55 | activeContainer.classList.remove('qwebr-cell-needs-evaluation');
56 | activeContainer.classList.add('qwebr-cell-evaluated');
57 |
58 | // Update status on the code cell
59 | const activeStatus = document.getElementById(`qwebr-status-text-${qwebrCounter}`);
60 | activeStatus.innerText = " Evaluating hidden code cell...";
61 | activeStatus.classList.remove('qwebr-cell-needs-evaluation');
62 | activeStatus.classList.add('qwebr-cell-evaluated');
63 | }
64 |
65 | switch (evalType) {
66 | case 'interactive':
67 | // TODO: Make this more standardized.
68 | // At the moment, we're overriding the interactive status update by pretending its
69 | // output-like.
70 | const tempOptions = entry.options;
71 | tempOptions["context"] = "output"
72 | // Run the code in a non-interactive state that is geared to displaying output
73 | await qwebrExecuteCode(`${cellCode}`, qwebrCounter, tempOptions);
74 | break;
75 | case 'output':
76 | // Run the code in a non-interactive state that is geared to displaying output
77 | await qwebrExecuteCode(`${cellCode}`, qwebrCounter, entry.options);
78 | break;
79 | case 'setup':
80 | const activeDiv = document.getElementById(`qwebr-noninteractive-setup-area-${qwebrCounter}`);
81 |
82 | // Store code in history
83 | qwebrLogCodeToHistory(cellCode, entry.options);
84 |
85 | // Run the code in a non-interactive state with all output thrown away
86 | await mainWebR.evalRVoid(`${cellCode}`);
87 | break;
88 | default:
89 | break;
90 | }
91 |
92 | if (['output', 'setup'].includes(evalType)) {
93 | // Disable further global status updates
94 | const activeContainer = document.getElementById(`qwebr-non-interactive-loading-container-${qwebrCounter}`);
95 | // Disable visibility
96 | activeContainer.style.visibility = 'hidden';
97 | activeContainer.style.display = 'none';
98 | }
99 | }
100 | }
101 | ).then(
102 | () => {
103 | // Release document status as ready
104 |
105 | if (qwebrShowStartupMessage) {
106 | qwebrStartupMessage.innerText = "🟢 Ready!"
107 | }
108 |
109 | qwebrSetInteractiveButtonState(
110 | ` Run Code`,
111 | true
112 | );
113 | }
114 | );
--------------------------------------------------------------------------------
/_extensions/webr/qwebr-document-engine-initialization.js:
--------------------------------------------------------------------------------
1 | // Function to install a single package
2 | async function qwebrInstallRPackage(packageName) {
3 | await mainWebR.evalRVoid(`webr::install('${packageName}');`);
4 | }
5 |
6 | // Function to load a single package
7 | async function qwebrLoadRPackage(packageName) {
8 | await mainWebR.evalRVoid(`require('${packageName}', quietly = TRUE)`);
9 | }
10 |
11 | // Generic function to process R packages
12 | async function qwebrProcessRPackagesWithStatus(packages, processType, displayStatusMessageUpdate = true) {
13 | // Switch between contexts
14 | const messagePrefix = processType === 'install' ? 'Installing' : 'Loading';
15 |
16 | // Modify button state
17 | qwebrSetInteractiveButtonState(`🟡 ${messagePrefix} package ...`, false);
18 |
19 | // Iterate over packages
20 | for (let i = 0; i < packages.length; i++) {
21 | const activePackage = packages[i];
22 | const formattedMessage = `${messagePrefix} package ${i + 1} out of ${packages.length}: ${activePackage}`;
23 |
24 | // Display the update in header
25 | if (displayStatusMessageUpdate) {
26 | qwebrUpdateStatusHeader(formattedMessage);
27 | }
28 |
29 | // Display the update in non-active areas
30 | qwebrUpdateStatusMessage(formattedMessage);
31 |
32 | // Run package installation
33 | if (processType === 'install') {
34 | await qwebrInstallRPackage(activePackage);
35 | } else {
36 | await qwebrLoadRPackage(activePackage);
37 | }
38 | }
39 |
40 | // Clean slate
41 | if (processType === 'load') {
42 | await mainWebR.flush();
43 | }
44 | }
45 |
46 | // Start a timer
47 | const initializeWebRTimerStart = performance.now();
48 |
49 | // Encase with a dynamic import statement
50 | globalThis.qwebrInstance = import(qwebrCustomizedWebROptions.baseURL + "webr.mjs").then(
51 | async ({ WebR, ChannelType }) => {
52 | // Populate WebR options with defaults or new values based on `webr` meta
53 | globalThis.mainWebR = new WebR(qwebrCustomizedWebROptions);
54 |
55 | // Initialization WebR
56 | await mainWebR.init();
57 |
58 | // Setup a shelter
59 | globalThis.mainWebRCodeShelter = await new mainWebR.Shelter();
60 |
61 | // Setup a pager to allow processing help documentation
62 | await mainWebR.evalRVoid('webr::pager_install()');
63 |
64 | // Setup a viewer to allow processing htmlwidgets.
65 | // This might not be available in old webr version
66 | await mainWebR.evalRVoid('try({ webr::viewer_install() })');
67 |
68 | // Override the existing install.packages() to use webr::install()
69 | await mainWebR.evalRVoid('webr::shim_install()');
70 |
71 | // Specify the repositories to pull from
72 | // Note: webR does not use the `repos` option, but instead uses `webr_pkg_repos`
73 | // inside of `install()`. However, other R functions still pull from `repos`.
74 | await mainWebR.evalRVoid(`
75 | options(
76 | webr_pkg_repos = c(${qwebrPackageRepoURLS.map(repoURL => `'${repoURL}'`).join(',')}),
77 | repos = c(${qwebrPackageRepoURLS.map(repoURL => `'${repoURL}'`).join(',')})
78 | )
79 | `);
80 |
81 | // Check to see if any packages need to be installed
82 | if (qwebrSetupRPackages) {
83 | // Obtain only a unique list of packages
84 | const uniqueRPackageList = Array.from(new Set(qwebrInstallRPackagesList));
85 |
86 | // Install R packages one at a time (either silently or with a status update)
87 | await qwebrProcessRPackagesWithStatus(uniqueRPackageList, 'install', qwebrShowStartupMessage);
88 |
89 | if (qwebrAutoloadRPackages) {
90 | // Load R packages one at a time (either silently or with a status update)
91 | await qwebrProcessRPackagesWithStatus(uniqueRPackageList, 'load', qwebrShowStartupMessage);
92 | }
93 | }
94 | }
95 | );
96 |
97 | // Stop timer
98 | const initializeWebRTimerEnd = performance.now();
99 |
--------------------------------------------------------------------------------
/_extensions/webr/qwebr-document-history.js:
--------------------------------------------------------------------------------
1 | // Define a global storage and retrieval solution ----
2 |
3 | // Store commands executed in R
4 | globalThis.qwebrRCommandHistory = [];
5 |
6 | // Function to retrieve the command history
7 | globalThis.qwebrFormatRHistory = function() {
8 | return qwebrRCommandHistory.join("\n\n");
9 | }
10 |
11 | // Retrieve HTML Elements ----
12 |
13 | // Get the command modal
14 | const command_history_modal = document.getElementById("qwebr-history-modal");
15 |
16 | // Get the button that opens the command modal
17 | const command_history_btn = document.getElementById("qwebrRHistoryButton");
18 |
19 | // Get the element that closes the command modal
20 | const command_history_close_span = document.getElementById("qwebr-command-history-close-btn");
21 |
22 | // Get the download button for r history information
23 | const command_history_download_btn = document.getElementById("qwebr-download-history-btn");
24 |
25 | // Plug in command history into modal/download button ----
26 |
27 | // Function to populate the modal with command history
28 | function populateCommandHistoryModal() {
29 | document.getElementById("qwebr-command-history-contents").innerHTML = qwebrFormatRHistory() || "No commands have been executed yet.";
30 | }
31 |
32 | // Function to format the current date and time to
33 | // a string with the format YYYY-MM-DD-HH-MM-SS
34 | function formatDateTime() {
35 | const now = new Date();
36 |
37 | const year = now.getFullYear();
38 | const day = String(now.getDate()).padStart(2, '0');
39 | const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are zero-based
40 | const hours = String(now.getHours()).padStart(2, '0');
41 | const minutes = String(now.getMinutes()).padStart(2, '0');
42 | const seconds = String(now.getSeconds()).padStart(2, '0');
43 |
44 | return `${year}-${month}-${day}-${hours}-${minutes}-${seconds}`;
45 | }
46 |
47 |
48 | // Function to convert document title with datetime to a safe filename
49 | function safeFileName() {
50 | // Get the current page title
51 | let pageTitle = document.title;
52 |
53 | // Combine the current page title with the current date and time
54 | let pageNameWithDateTime = `Rhistory-${pageTitle}-${formatDateTime()}`;
55 |
56 | // Replace unsafe characters with safe alternatives
57 | let safeFilename = pageNameWithDateTime.replace(/[\\/:\*\?! "<>\|]/g, '-');
58 |
59 | return safeFilename;
60 | }
61 |
62 |
63 | // Function to download list contents as text file
64 | function downloadRHistory() {
65 | // Get the current page title + datetime and use it as the filename
66 | const filename = `${safeFileName()}.R`;
67 |
68 | // Get the text contents of the R History list
69 | const text = qwebrFormatRHistory();
70 |
71 | // Create a new Blob object with the text contents
72 | const blob = new Blob([text], { type: 'text/plain' });
73 |
74 | // Create a new anchor element for the download
75 | const a = document.createElement('a');
76 | a.style.display = 'none';
77 | a.href = URL.createObjectURL(blob);
78 | a.download = filename;
79 |
80 | // Append the anchor to the body, click it, and remove it
81 | document.body.appendChild(a);
82 | a.click();
83 | document.body.removeChild(a);
84 | }
85 |
86 | // Register event handlers ----
87 |
88 | // When the user clicks the View R History button, open the command modal
89 | command_history_btn.onclick = function() {
90 | populateCommandHistoryModal();
91 | command_history_modal.style.display = "block";
92 | }
93 |
94 | // When the user clicks on (x), close the command modal
95 | command_history_close_span.onclick = function() {
96 | command_history_modal.style.display = "none";
97 | }
98 |
99 | // When the user clicks anywhere outside of the command modal, close it
100 | window.onclick = function(event) {
101 | if (event.target == command_history_modal) {
102 | command_history_modal.style.display = "none";
103 | }
104 | }
105 |
106 | // Add an onclick event listener to the download button so that
107 | // the user can download the R history as a text file
108 | command_history_download_btn.onclick = function() {
109 | downloadRHistory();
110 | };
--------------------------------------------------------------------------------
/_extensions/webr/qwebr-document-settings.js:
--------------------------------------------------------------------------------
1 | // Document level settings ----
2 |
3 | // Determine if we need to install R packages
4 | globalThis.qwebrInstallRPackagesList = [{{INSTALLRPACKAGESLIST}}];
5 |
6 | // Specify possible locations to search for the repository
7 | globalThis.qwebrPackageRepoURLS = [{{RPACKAGEREPOURLS}}];
8 |
9 | // Check to see if we have an empty array, if we do set to skip the installation.
10 | globalThis.qwebrSetupRPackages = !(qwebrInstallRPackagesList.indexOf("") !== -1);
11 | globalThis.qwebrAutoloadRPackages = {{AUTOLOADRPACKAGES}};
12 |
13 | // Display a startup message?
14 | globalThis.qwebrShowStartupMessage = {{SHOWSTARTUPMESSAGE}};
15 | globalThis.qwebrShowHeaderMessage = {{SHOWHEADERMESSAGE}};
16 |
17 | // Describe the webR settings that should be used
18 | globalThis.qwebrCustomizedWebROptions = {
19 | "baseURL": "{{BASEURL}}",
20 | "serviceWorkerUrl": "{{SERVICEWORKERURL}}",
21 | "homedir": "{{HOMEDIR}}",
22 | "channelType": "{{CHANNELTYPE}}"
23 | };
24 |
25 | // Store cell data
26 | globalThis.qwebrCellDetails = {{QWEBRCELLDETAILS}};
27 |
--------------------------------------------------------------------------------
/_extensions/webr/qwebr-monaco-editor-element.js:
--------------------------------------------------------------------------------
1 | // Global array to store Monaco Editor instances
2 | globalThis.qwebrEditorInstances = [];
3 |
4 | function isValidCodeLineNumbers(stringCodeLineNumbers) {
5 | // Regular expression to match valid input strings
6 | const regex = /^(\d+(-\d+)?)(,\d+(-\d+)?)*$/;
7 | return regex.test(stringCodeLineNumbers);
8 | }
9 |
10 | // Function that builds and registers a Monaco Editor instance
11 | globalThis.qwebrCreateMonacoEditorInstance = function (cellData) {
12 |
13 | const initialCode = cellData.code;
14 | const qwebrCounter = cellData.id;
15 | const qwebrOptions = cellData.options;
16 |
17 | // Retrieve the previously created document elements
18 | let runButton = document.getElementById(`qwebr-button-run-${qwebrCounter}`);
19 | let resetButton = document.getElementById(`qwebr-button-reset-${qwebrCounter}`);
20 | let copyButton = document.getElementById(`qwebr-button-copy-${qwebrCounter}`);
21 | let editorDiv = document.getElementById(`qwebr-editor-${qwebrCounter}`);
22 |
23 | // Load the Monaco Editor and create an instance
24 | let editor;
25 | require(['vs/editor/editor.main'], function () {
26 | editor = monaco.editor.create(editorDiv, {
27 | value: initialCode,
28 | language: 'r',
29 | theme: 'vs-light',
30 | automaticLayout: true, // Works wonderfully with RevealJS
31 | scrollBeyondLastLine: false,
32 | minimap: {
33 | enabled: false
34 | },
35 | fontSize: qwebrScaledFontSize(editorDiv, qwebrOptions),
36 | renderLineHighlight: "none", // Disable current line highlighting
37 | hideCursorInOverviewRuler: true, // Remove cursor indictor in right hand side scroll bar
38 | readOnly: qwebrOptions['read-only'] ?? false,
39 | quickSuggestions: qwebrOptions['editor-quick-suggestions'] ?? false,
40 | wordWrap: (qwebrOptions['editor-word-wrap'] == 'true' ? "on" : "off")
41 | });
42 |
43 | // Store the official counter ID to be used in keyboard shortcuts
44 | editor.__qwebrCounter = qwebrCounter;
45 |
46 | // Store the official div container ID
47 | editor.__qwebrEditorId = `qwebr-editor-${qwebrCounter}`;
48 |
49 | // Store the initial code value and options
50 | editor.__qwebrinitialCode = initialCode;
51 | editor.__qwebrOptions = qwebrOptions;
52 |
53 | // Set at the model level the preferred end of line (EOL) character to LF.
54 | // This prevent `\r\n` from being given to the webR engine if the user is on Windows.
55 | // See details in: https://github.com/coatless/quarto-webr/issues/94
56 | // Associated error text:
57 | // Error: :1:7 unexpected input
58 |
59 | // Retrieve the underlying model
60 | const model = editor.getModel();
61 | // Set EOL for the model
62 | model.setEOL(monaco.editor.EndOfLineSequence.LF);
63 |
64 | // Dynamically modify the height of the editor window if new lines are added.
65 | let ignoreEvent = false;
66 | const updateHeight = () => {
67 | // Increment editor height by 2 to prevent vertical scroll bar from appearing
68 | const contentHeight = editor.getContentHeight() + 2;
69 |
70 | // Retrieve editor-max-height option
71 | const maxEditorHeight = qwebrOptions['editor-max-height'];
72 |
73 | // If editor-max-height is missing, allow infinite growth. Otherwise, threshold.
74 | const editorHeight = !maxEditorHeight ? contentHeight : Math.min(contentHeight, maxEditorHeight);
75 |
76 | // We're avoiding a width change
77 | //editorDiv.style.width = `${width}px`;
78 | editorDiv.style.height = `${editorHeight}px`;
79 | try {
80 | ignoreEvent = true;
81 |
82 | // The key to resizing is this call
83 | editor.layout();
84 | } finally {
85 | ignoreEvent = false;
86 | }
87 | };
88 |
89 | // Function to generate decorations to highlight lines
90 | // in the editor based on input string.
91 | function decoratorHighlightLines(codeLineNumbers) {
92 | // Store the lines to be lighlight
93 | let linesToHighlight = [];
94 |
95 | // Parse the codeLineNumbers string to get the line numbers to highlight
96 | // First, split the string by commas
97 | codeLineNumbers.split(',').forEach(part => {
98 | // Check if we have a range of lines
99 | if (part.includes('-')) {
100 | // Handle range of lines (e.g., "6-8")
101 | const [start, end] = part.split('-').map(Number);
102 | for (let i = start; i <= end; i++) {
103 | linesToHighlight.push(i);
104 | }
105 | } else {
106 | // Handle single line (e.g., "7")
107 | linesToHighlight.push(Number(part));
108 | }
109 | });
110 |
111 | // Create monaco decorations for the lines to highlight
112 | const decorations = linesToHighlight.map(lineNumber => ({
113 | range: new monaco.Range(lineNumber, 1, lineNumber, 1),
114 | options: {
115 | isWholeLine: true,
116 | className: 'qwebr-editor-highlight-line'
117 | }
118 | }));
119 |
120 | // Return decorations to be applied to the editor
121 | return decorations;
122 | }
123 |
124 | // Ensure that the editor-code-line-numbers option is set and valid
125 | // then apply styling
126 | if (qwebrOptions['editor-code-line-numbers']) {
127 | // Remove all whitespace from the string
128 | const codeLineNumbers = qwebrOptions['editor-code-line-numbers'].replace(/\s/g,'');
129 | // Check if the string is valid for line numbers, e.g., "1,3-5,7"
130 | if (isValidCodeLineNumbers(codeLineNumbers)) {
131 | // Apply the decorations to the editor
132 | editor.createDecorationsCollection(decoratorHighlightLines(codeLineNumbers));
133 | } else {
134 | // Warn the user that the input is invalid
135 | console.warn(`Invalid "editor-code-line-numbers" value in code cell ${qwebrOptions['label']}: ${codeLineNumbers}`);
136 | }
137 | }
138 |
139 | // Helper function to check if selected text is empty
140 | function isEmptyCodeText(selectedCodeText) {
141 | return (selectedCodeText === null || selectedCodeText === undefined || selectedCodeText === "");
142 | }
143 |
144 | // Registry of keyboard shortcuts that should be re-added to each editor window
145 | // when focus changes.
146 | const addWebRKeyboardShortCutCommands = () => {
147 | // Add a keydown event listener for Shift+Enter to run all code in cell
148 | editor.addCommand(monaco.KeyMod.Shift | monaco.KeyCode.Enter, () => {
149 |
150 | // Retrieve all text inside the editor
151 | qwebrExecuteCode(editor.getValue(), editor.__qwebrCounter, editor.__qwebrOptions);
152 | });
153 |
154 | // Add a keydown event listener for CMD/Ctrl+Enter to run selected code
155 | editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {
156 |
157 | // Get the selected text from the editor
158 | const selectedText = editor.getModel().getValueInRange(editor.getSelection());
159 | // Check if no code is selected
160 | if (isEmptyCodeText(selectedText)) {
161 | // Obtain the current cursor position
162 | let currentPosition = editor.getPosition();
163 | // Retrieve the current line content
164 | let currentLine = editor.getModel().getLineContent(currentPosition.lineNumber);
165 |
166 | // Propose a new position to move the cursor to
167 | let newPosition = new monaco.Position(currentPosition.lineNumber + 1, 1);
168 |
169 | // Check if the new position is beyond the last line of the editor
170 | if (newPosition.lineNumber > editor.getModel().getLineCount()) {
171 | // Add a new line at the end of the editor
172 | editor.executeEdits("addNewLine", [{
173 | range: new monaco.Range(newPosition.lineNumber, 1, newPosition.lineNumber, 1),
174 | text: "\n",
175 | forceMoveMarkers: true,
176 | }]);
177 | }
178 |
179 | // Run the entire line of code.
180 | qwebrExecuteCode(currentLine, editor.__qwebrCounter, editor.__qwebrOptions);
181 |
182 | // Move cursor to new position
183 | editor.setPosition(newPosition);
184 | } else {
185 | // Code to run when Ctrl+Enter is pressed with selected code
186 | qwebrExecuteCode(selectedText, editor.__qwebrCounter, editor.__qwebrOptions);
187 | }
188 | });
189 | }
190 |
191 | // Register an on focus event handler for when a code cell is selected to update
192 | // what keyboard shortcut commands should work.
193 | // This is a workaround to fix a regression that happened with multiple
194 | // editor windows since Monaco 0.32.0
195 | // https://github.com/microsoft/monaco-editor/issues/2947
196 | editor.onDidFocusEditorText(addWebRKeyboardShortCutCommands);
197 |
198 | // Register an on change event for when new code is added to the editor window
199 | editor.onDidContentSizeChange(updateHeight);
200 |
201 | // Manually re-update height to account for the content we inserted into the call
202 | updateHeight();
203 |
204 | // Store the editor instance in the global dictionary
205 | qwebrEditorInstances[editor.__qwebrCounter] = editor;
206 |
207 | });
208 |
209 | // Add a click event listener to the run button
210 | runButton.onclick = function () {
211 | qwebrExecuteCode(editor.getValue(), editor.__qwebrCounter, editor.__qwebrOptions);
212 | };
213 |
214 | // Add a click event listener to the reset button
215 | copyButton.onclick = function () {
216 | // Retrieve current code data
217 | const data = editor.getValue();
218 |
219 | // Write code data onto the clipboard.
220 | navigator.clipboard.writeText(data || "");
221 | };
222 |
223 | // Add a click event listener to the copy button
224 | resetButton.onclick = function () {
225 | editor.setValue(editor.__qwebrinitialCode);
226 | };
227 |
228 | }
--------------------------------------------------------------------------------
/_extensions/webr/qwebr-monaco-editor-init.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/_extensions/webr/qwebr-styling.css:
--------------------------------------------------------------------------------
1 | .monaco-editor pre {
2 | background-color: unset !important;
3 | }
4 |
5 | .qwebr-editor-toolbar {
6 | width: 100%;
7 | display: flex;
8 | justify-content: space-between;
9 | box-sizing: border-box;
10 | }
11 |
12 | .qwebr-editor-toolbar-left-buttons, .qwebr-editor-toolbar-right-buttons {
13 | display: flex;
14 | }
15 |
16 | .qwebr-non-interactive-loading-container.qwebr-cell-needs-evaluation, .qwebr-non-interactive-loading-container.qwebr-cell-evaluated {
17 | justify-content: center;
18 | display: flex;
19 | background-color: rgba(250, 250, 250, 0.65);
20 | border: 1px solid rgba(233, 236, 239, 0.65);
21 | border-radius: 0.5rem;
22 | margin-top: 15px;
23 | margin-bottom: 15px;
24 | }
25 |
26 | .qwebr-r-project-logo {
27 | color: #2767B0; /* R Project's blue color */
28 | }
29 |
30 | .qwebr-icon-status-spinner {
31 | color: #7894c4;
32 | }
33 |
34 | .qwebr-icon-run-code {
35 | color: #0d9c29
36 | }
37 |
38 | body.quarto-light .qwebr-output-code-stdout {
39 | color: #111;
40 | }
41 |
42 | body.quarto-dark .qwebr-output-code-stdout {
43 | color: #EEE;
44 | }
45 |
46 | .qwebr-output-code-stderr {
47 | color: #db4133;
48 | }
49 |
50 | body.quarto-light .qwebr-editor {
51 | border: 1px solid #EEEEEE;
52 | }
53 |
54 | body.quarto-light .qwebr-editor-toolbar {
55 | background-color: #EEEEEE;
56 | padding: 0.2rem 0.5rem;
57 | }
58 |
59 | body.quarto-dark .qwebr-editor {
60 | border: 1px solid #111;
61 | }
62 |
63 | body.quarto-dark .qwebr-editor-toolbar {
64 | background-color: #111;
65 | padding: 0.2rem 0.5rem;
66 | }
67 |
68 | .qwebr-button {
69 | display: inline-block;
70 | font-weight: 400;
71 | line-height: 1;
72 | text-decoration: none;
73 | text-align: center;
74 | padding: 0.375rem 0.75rem;
75 | font-size: .9rem;
76 | border-radius: 0.25rem;
77 | transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
78 | }
79 |
80 | body.quarto-light .qwebr-button {
81 | background-color: #EEEEEE;
82 | color: #000;
83 | border-color: #dee2e6;
84 | border: 1px solid rgba(0,0,0,0);
85 | }
86 |
87 | body.quarto-dark .qwebr-button {
88 | background-color: #111;
89 | color: #EEE;
90 | border-color: #dee2e6;
91 | border: 1px solid rgba(0,0,0,0);
92 | }
93 |
94 | body.quarto-light .qwebr-button:hover {
95 | color: #000;
96 | background-color: #d9dce0;
97 | border-color: #c8ccd0;
98 | }
99 |
100 | body.quarto-dark .qwebr-button:hover {
101 | color: #d9dce0;
102 | background-color: #323232;
103 | border-color: #d9dce0;
104 | }
105 |
106 | .qwebr-button:disabled,.qwebr-button.disabled,fieldset:disabled .qwebr-button {
107 | pointer-events: none;
108 | opacity: .65
109 | }
110 |
111 | .qwebr-button-reset {
112 | color: #696969; /*#4682b4;*/
113 | }
114 |
115 | .qwebr-button-copy {
116 | color: #696969;
117 | }
118 |
119 | /* Style the code highlight lines */
120 | body.quarto-light .qwebr-editor-highlight-line {
121 | background-color: lightblue;
122 | }
123 |
124 | body.quarto-dark .qwebr-editor-highlight-line {
125 | background-color: darkblue;
126 | }
127 |
128 | /* Style the modal pop-up */
129 |
130 | /* The Modal (background) */
131 | .qwebr-modal {
132 | display: none; /* Hidden by default */
133 | position: fixed; /* Stay in place */
134 | z-index: 1; /* Sit on top */
135 | left: 0;
136 | top: 0;
137 | width: 100%; /* Full width */
138 | height: 100%; /* Full height */
139 | overflow: auto; /* Enable scroll if needed */
140 | background-color: rgb(0,0,0); /* Fallback color */
141 | background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
142 | padding-top: 60px;
143 | }
144 |
145 | /* Modal Content */
146 | .qwebr-modal-content {
147 | background-color: #fefefe;
148 | margin: 5% auto; /* 15% from the top and centered */
149 | padding: 20px;
150 | border: 1px solid #888;
151 | width: 80%; /* Could be more or less, depending on screen size */
152 | }
153 |
154 | .qwebr-modal-content-code {
155 | max-height: 50vh;
156 | min-height: 5vh;
157 | overflow: scroll;
158 | border: 1px solid #888;
159 | }
160 |
161 | /* The Close Button */
162 | .qwebr-modal-close {
163 | color: #aaa;
164 | float: right;
165 | font-size: 28px;
166 | font-weight: bold;
167 | }
168 |
169 | .qwebr-modal-close:hover,
170 | .qwebr-modal-close:focus {
171 | color: black;
172 | text-decoration: none;
173 | cursor: pointer;
174 | }
175 |
176 | .qwebr-download-btn {
177 | margin-top: 10px;
178 | text-decoration: none !important;
179 | }
180 |
181 | /* Styling to download image that is created */
182 |
183 | .qwebr-canvas-image {
184 | position: relative;
185 | display: inline-block;
186 | margin: 10px;
187 | }
188 |
189 | .qwebr-canvas-image-download-btn {
190 | position: absolute;
191 | top: 10px;
192 | right: 10px;
193 | padding: 5px 10px;
194 | background-color: #007BFF;
195 | color: white;
196 | border: none;
197 | cursor: pointer;
198 | display: none;
199 | }
200 |
201 | figure:hover .qwebr-canvas-image-download-btn {
202 | display: block;
203 | }
204 |
205 | /* Custom styling for RevealJS Presentations*/
206 |
207 | /* Reset the style of the interactive area */
208 | .reveal div.qwebr-interactive-area {
209 | display: block;
210 | box-shadow: none;
211 | max-width: 100%;
212 | max-height: 100%;
213 | margin: 0;
214 | padding: 0;
215 | }
216 |
217 | /* Provide space to entries */
218 | .reveal div.qwebr-output-code-area pre div {
219 | margin: 1px 2px 1px 10px;
220 | }
221 |
222 | /* Collapse the inside code tags to avoid extra space between line outputs */
223 | .reveal pre div code.qwebr-output-code-stdout, .reveal pre div code.qwebr-output-code-stderr {
224 | padding: 0;
225 | display: contents;
226 | }
227 |
228 | body.reveal.quarto-light pre div code.qwebr-output-code-stdout {
229 | color: #111;
230 | }
231 |
232 | body.reveal.quarto-dark pre div code.qwebr-output-code-stdout {
233 | color: #EEEEEE;
234 | }
235 |
236 | .reveal pre div code.qwebr-output-code-stderr {
237 | color: #db4133;
238 | }
239 |
240 |
241 | /* Create a border around console and output (does not effect graphs) */
242 | body.reveal.quarto-light div.qwebr-console-area {
243 | border: 1px solid #EEEEEE;
244 | box-shadow: 2px 2px 10px #EEEEEE;
245 | }
246 |
247 | body.reveal.quarto-dark div.qwebr-console-area {
248 | border: 1px solid #111;
249 | box-shadow: 2px 2px 10px #111;
250 | }
251 |
252 |
253 | /* Cap output height and allow text to scroll */
254 | /* TODO: Is there a better way to fit contents/max it parallel to the monaco editor size? */
255 | .reveal div.qwebr-output-code-area pre {
256 | max-height: 400px;
257 | overflow: scroll;
258 | }
259 |
260 | iframe.qwebr-output-code-browse {
261 | width: 100%;
262 |
263 | /*
264 | TODO: How to make the height automatic according to the widget size,
265 | or respect the quarto code block options?
266 | */
267 | min-height: 500px;
268 | }
269 |
--------------------------------------------------------------------------------
/_extensions/webr/qwebr-theme-switch.js:
--------------------------------------------------------------------------------
1 | // Function to update Monaco Editors when body class changes
2 | function updateMonacoEditorsOnBodyClassChange() {
3 | // Select the body element
4 | const body = document.querySelector('body');
5 |
6 | // Options for the observer (which mutations to observe)
7 | const observerOptions = {
8 | attributes: true, // Observe changes to attributes
9 | attributeFilter: ['class'] // Only observe changes to the 'class' attribute
10 | };
11 |
12 | // Callback function to execute when mutations are observed
13 | const bodyClassChangeCallback = function(mutationsList, observer) {
14 | for(let mutation of mutationsList) {
15 | if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
16 | // Class attribute has changed
17 | // Update all Monaco Editors on the page
18 | updateMonacoEditorTheme();
19 | }
20 | }
21 | };
22 |
23 | // Create an observer instance linked to the callback function
24 | const observer = new MutationObserver(bodyClassChangeCallback);
25 |
26 | // Start observing the target node for configured mutations
27 | observer.observe(body, observerOptions);
28 | }
29 |
30 | // Function to update all instances of Monaco Editors on the page
31 | function updateMonacoEditorTheme() {
32 | // Determine what VS Theme to use
33 | const vsThemeToUse = document.body.classList.contains("quarto-dark") ? 'vs-dark' : 'vs' ;
34 |
35 | // Iterate through all initialized Monaco Editors
36 | qwebrEditorInstances.forEach( function(editorInstance) {
37 | editorInstance.updateOptions({ theme: vsThemeToUse });
38 | });
39 | }
40 |
41 | // Call the function to start observing changes to body class
42 | updateMonacoEditorsOnBodyClassChange();
--------------------------------------------------------------------------------
/_extensions/webr/template.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "WebR-enabled code cell"
3 | format: html
4 | engine: knitr
5 | #webr:
6 | # show-startup-message: false # Disable display of webR initialization state
7 | # show-header-message: true # Display whether COOP&COEP headers are set for speed.
8 | # packages: ['ggplot2', 'dplyr'] # Pre-install dependencies
9 | # autoload-packages: false # Disable automatic library calls on R packages specified in packages.
10 | # repos: # Specify repositories to check for custom packages
11 | # - https://github-username.github.io/reponame
12 | # - https://username.r-universe.dev
13 | # channel-type: 'post-message' # Specify a specific communication channel type.
14 | # home-dir: "/home/rstudio" # Customize where the working directory is
15 | # base-url: '' # Base URL used for downloading R WebAssembly binaries
16 | # service-worker-url: '' # URL from where to load JavaScript worker scripts when loading webR with the ServiceWorker communication channel.
17 | filters:
18 | - webr
19 | ---
20 |
21 | ## Demo
22 |
23 | This is a webr-enabled code cell in a Quarto HTML document.
24 |
25 | ```{webr-r}
26 | 1 + 1
27 | ```
28 |
29 | ```{webr-r}
30 | fit = lm(mpg ~ am, data = mtcars)
31 | summary(fit)
32 | ```
33 |
34 | ```{webr-r}
35 | plot(pressure)
36 | ```
37 |
--------------------------------------------------------------------------------
/_publish.yml:
--------------------------------------------------------------------------------
1 | - source: webr-demo.qmd
2 | quarto-pub:
3 | - id: 2ae0a31d-b315-4617-a8a4-cda96a9abd3c
4 | url: 'https://coatless.quarto.pub/webr-enabled-code-cells'
5 | - source: webr-channel-type.qmd
6 | quarto-pub:
7 | - id: 9a6782cc-7f9a-4773-a43b-ddeae9944dfb
8 | url: 'https://coatless.quarto.pub/webr-communication-channel-options'
9 | - source: webr-internal-cell.qmd
10 | quarto-pub:
11 | - id: 9a086f67-3a62-4ac6-bd63-a5987751855a
12 | url: 'https://coatless.quarto.pub/hidden-webr-code-cells'
13 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | /.quarto/
2 |
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | quarto-webr.thecoatlessprofessor.com
--------------------------------------------------------------------------------
/docs/_extensions:
--------------------------------------------------------------------------------
1 | ../_extensions
--------------------------------------------------------------------------------
/docs/_quarto.yml:
--------------------------------------------------------------------------------
1 | project:
2 | type: website
3 | resources:
4 | - CNAME
5 |
6 | website:
7 | title: "quarto-webr"
8 | reader-mode: true
9 | repo-url: https://github.com/coatless/quarto-webr
10 | repo-actions: [edit, issue]
11 | repo-subdir: "docs"
12 | google-analytics: "G-S8CXP9TZG0"
13 | sidebar:
14 | style: "floating"
15 | search: true
16 | tools:
17 | - icon: github
18 | href: https://github.com/coatless/quarto-webr/
19 | contents:
20 | - section: "Getting Started"
21 | contents:
22 | - href: qwebr-first-steps.qmd
23 | text: Your first webR-powered Quarto document
24 | - href: qwebr-code-cell-demos.qmd
25 | text: Exploring Interactive Code Cells
26 | - href: qwebr-using-r-packages.qmd
27 | text: Using R Packages
28 | - href: qwebr-internal-cell.qmd
29 | text: Hiding and Executing Code
30 | - href: qwebr-loading-data.qmd
31 | text: Loading Data
32 | - section: "Options Reference"
33 | contents:
34 | - href: qwebr-meta-options.qmd
35 | text: Document Options
36 | - href: qwebr-cell-options.qmd
37 | text: Code Cell Options
38 | - section: "Demos"
39 | contents:
40 | - href: demos/qwebr-feature-demos.qmd
41 | text: Feature Demos
42 | - href: qwebr-community-examples.qmd
43 | text: Community Examples
44 | - section: "Deployment"
45 | contents:
46 | - href: qwebr-deployment-templates.qmd
47 | text: Templates
48 | - href: qwebr-theming.qmd
49 | text: Theming Elements
50 | - href: qwebr-communication-channels.qmd
51 | text: Communication Channels
52 | - section: "Support"
53 | contents:
54 | - href: qwebr-troubleshooting.qmd
55 | text: Troubleshooting
56 | - href: qwebr-faq.qmd
57 | text: FAQ
58 | - href: https://github.com/coatless/quarto-webr/issues/new
59 | text: Submit an issue
60 | - section: "Extra Information"
61 | contents:
62 | - href: qwebr-release-notes.qmd
63 | text: Release Notes
64 | - href: qwebr-acknowledgements.md
65 | text: Acknowledgements
66 | - href: qwebr-developer-resources.qmd
67 | text: Developer Resources
68 | - href: qwebr-extension-website.qmd
69 | text: Extension Website Notes
70 | - href: https://quarto-webr.thecoatlessprofessor.com/tests/
71 | text: Test Suite
72 | announcement:
73 | icon: info-circle
74 | dismissable: true
75 | content: "Looking for the official Quarto WebAssembly backend? Check out [`quarto-live`](https://github.com/r-wasm/quarto-live)!"
76 | type: primary
77 | body-footer: |
78 | :::{.callout-important}
79 | This Quarto extension is open source software and is **not affiliated with** Posit, Quarto, or webR. The extension is at best a community effort to simplify the integration of webR inside of Quarto generated documents.
80 | :::
81 |
82 | format:
83 | html:
84 | toc: true
85 |
86 | # Allow quarto to switch between light and dark themes.
87 | theme:
88 | light: cosmo
89 | dark: darkly
--------------------------------------------------------------------------------
/docs/demos/qwebr-auto-run.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Demo: Autorun Interactive Code Cells"
3 | engine: knitr
4 | webr:
5 | packages: ['ggplot2', 'gapminder']
6 | filters:
7 | - webr
8 | ---
9 |
10 | # Overview
11 |
12 | This demo showcases the functionality of automatically executing code within an interactive area, revealing output before any modifications can be made to the document.
13 |
14 | ## `autorun` Option
15 |
16 | The `autorun` option works in tandem with the `interactive` context, enabling a non-interactive execution of code within the editable code area before any changes can be made to the area.
17 |
18 | To illustrate, let's imagine a situation where you are prompted to modify the statement "Hello ___!" In the default view of an interactive cell, the results are not initially displayed.
19 |
20 | ::: {.panel-tabset group="autoRunExmple"}
21 | #### `{quarto-webr}` Output
22 | ```{webr-r}
23 | #| context: interactive
24 | # Write your name here by replace ___
25 | name <- "_____"
26 | print(paste0("Hello, ", name, "!"))
27 | ```
28 | #### Cell Code
29 | ````md
30 | ```{webr-r}
31 | #| context: interactive
32 | # Write your name here by replace ___
33 | name <- "_____"
34 | print(paste0("Hello, ", name, "!"))
35 | ```
36 | ````
37 | :::
38 |
39 | By including `#| autorun: true`, we enable the display of results when the document first loads. Revisiting the previous example, the editable code area now presents a distinct output, prompting the user to "Fill in the blanks":
40 |
41 | ::: {.panel-tabset group="autoRunExmple"}
42 | #### `{quarto-webr}` Output
43 | ```{webr-r}
44 | #| context: interactive
45 | #| autorun: true
46 | # Write your name here by replace ___
47 | name <- "_____"
48 | print(paste0("Hello, ", name, "!"))
49 | ```
50 | #### Cell Code
51 | ````md
52 | ```{webr-r}
53 | #| context: interactive
54 | #| autorun: true
55 | # Write your name here by replace ___
56 | name <- "_____"
57 | print(paste0("Hello, ", name, "!"))
58 | ```
59 | ````
60 | :::
61 |
62 |
63 | ## Target Practice
64 |
65 | One key use of the non-interactive areas is to generate a targeted outcome and have iterative attempts to reach the desired output.
66 |
67 | For example, consider the `gapminder` data set.
68 |
69 | ::: {.panel-tabset group="gapminderRecreate"}
70 | #### `{quarto-webr}` Output
71 | ```{webr-r}
72 | #| context: output
73 | data("gapminder", package = "gapminder")
74 | head(gapminder)
75 | ```
76 | #### Cell Code
77 | ```{{webr-r}}
78 | #| context: output
79 | data("gapminder", package = "gapminder")
80 | head(gapminder)
81 | ```
82 | :::
83 |
84 | How can we use `gapminder` data to re-create the following `ggplot2` graph?
85 |
86 |
87 | ::: {.panel-tabset}
88 | #### `{quarto-webr}` Output
89 | ```{webr-r}
90 | #| context: output
91 | #| fig-width: 5
92 | #| fig-height: 3
93 | #| out-width: 500px
94 | ggplot(gapminder, aes(lifeExp)) +
95 | geom_density(aes(fill=continent), alpha=1/4) + theme_bw()
96 | ```
97 | #### Cell Code
98 | ```{{webr-r}}
99 | #| context: output
100 | #| fig-width: 5
101 | #| fig-height: 3
102 | #| out-width: 500px
103 | ggplot(gapminder, aes(lifeExp)) +
104 | geom_density(aes(fill=continent), alpha=1/4) + theme_bw()
105 | ```
106 | :::
107 |
108 | We've provided a code area for you to explore creating different kinds of graphs and have already run its contents!
109 |
110 | ::: {.panel-tabset}
111 | #### `{quarto-webr}` Output
112 | ```{webr-r}
113 | #| context: interactive
114 | #| autorun: true
115 | #| fig-width: 5
116 | #| fig-height: 3
117 | #| out-width: 500px
118 | ggplot(gapminder, aes(lifeExp)) +
119 | theme_bw()
120 | ```
121 | #### Cell Code
122 | ```{{webr-r}}
123 | #| context: interactive
124 | #| autorun: true
125 | #| fig-width: 5
126 | #| fig-height: 3
127 | #| out-width: 500px
128 | ggplot(gapminder, aes(lifeExp)) +
129 | theme_bw()
130 | ```
131 | :::
132 |
133 | # Fin
134 |
135 | This demo illustrated the ease with which an interactive editable code area can seamlessly transition into a non-interactive mode, allow its results to be shown when the page loads.
136 |
137 |
--------------------------------------------------------------------------------
/docs/demos/qwebr-code-cell-options.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Demo: Initial Code Cell Option Support"
3 | engine: knitr
4 | webr:
5 | packages: ['knitr', 'tinyplot']
6 | repos:
7 | - https://grantmcdermott.r-universe.dev
8 | filters:
9 | - webr
10 | ---
11 |
12 | # Overview
13 |
14 | 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.
15 |
16 | ## `context` Option
17 |
18 | The `context` option specifies how the cell should operate on the page. Let's use it to create an interactive code editor:
19 |
20 | ::: {.panel-tabset group="language"}
21 | #### `{quarto-webr}` Output
22 | ```{webr-r}
23 | #| context: interactive
24 | # Write your name here by replace ___
25 | name <- "_____"
26 | print(paste0("Hello, ", name, "!"))
27 | ```
28 | #### Cell Code
29 | ````md
30 | ```{webr-r}
31 | #| context: interactive
32 |
33 | # Write your name here by replace ___
34 | name <- "_____"
35 | print(paste0("Hello, ", name, "!"))
36 | ```
37 | ````
38 | :::
39 |
40 | In this code block, the `context: interactive` option is applied, allowing users to interactively input their name.
41 |
42 | Next, let's use the `context: setup` option to create a data set that can be used by later cells.
43 |
44 | ::: {.panel-tabset group="language"}
45 | #### `{quarto-webr}` Output
46 | ```{webr-r}
47 | #| context: setup
48 |
49 | # Generating a simple table
50 | data <- data.frame(
51 | Name = c("Alice", "Bob", "Charlie"),
52 | Age = c(25, 30, 22)
53 | )
54 | ```
55 | #### Cell Code
56 | ````md
57 | ```{webr-r}
58 | #| context: setup
59 |
60 | # Generating a simple table
61 | data <- data.frame(
62 | Name = c("Alice", "Bob", "Charlie"),
63 | Age = c(25, 30, 22)
64 | )
65 | ```
66 | ````
67 | :::
68 |
69 | :::{.callout-note}
70 | Once a `context:setup` is done running, the visual indicator will be removed from the document.
71 | :::
72 |
73 | In a later block, we'll see a `context: output` that will only display the results.
74 |
75 | ## `results` Option
76 |
77 | The `results` option controls how text results are displayed. Let's use it to display raw text output:
78 |
79 | ::: {.panel-tabset group="language"}
80 | #### `{quarto-webr}` Output
81 | ```{webr-r}
82 | #| context: interactive
83 | #| results: asis
84 | knitr::kable(data, "html")
85 | ```
86 |
87 | #### Cell Code
88 | ````md
89 | ```{webr-r}
90 | #| context: interactive
91 | #| results: asis
92 | knitr::kable(data, "html")
93 | ```
94 | ````
95 | :::
96 |
97 | In the above code block, the `results: asis` option is used to display the raw text output of the `data` dataframe.
98 |
99 | If we use `results: markup`, then we'll end up seeing the HTML output:
100 |
101 |
102 | ::: {.panel-tabset group="language"}
103 | #### `{quarto-webr}` Output
104 |
105 | ```{webr-r}
106 | #| context: interactive
107 | #| results: markup
108 | knitr::kable(data, "html")
109 | ```
110 | #### Cell Code
111 | ````md
112 | ```{webr-r}
113 | #| context: interactive
114 | #| results: markup
115 |
116 | knitr::kable(data, "html")
117 | ```
118 | ````
119 | :::
120 |
121 | ## `fig-width` and `fig-height` Option
122 |
123 | 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:
124 |
125 | ::: {.panel-tabset group="language"}
126 | #### `{quarto-webr}` Output
127 | ```{webr-r}
128 | #| context: output
129 | #| fig-width: 6
130 | #| fig-height: 6
131 |
132 | tinyplot::tinyplot(
133 | ~ Petal.Length | Species,
134 | data = iris,
135 | type = "density",
136 | palette = "dark", fill = "by",
137 | grid = TRUE,
138 | main = "Distribution of petal lengths by species"
139 | )
140 | ```
141 | #### Cell Code
142 | ````md
143 | ```{webr-r}
144 | #| context: output
145 | #| fig-width: 6
146 | #| fig-height: 6
147 |
148 | # Generating a bar plot with a specific width
149 | tinyplot::tinyplot(
150 | ~ Petal.Length | Species,
151 | data = iris,
152 | type = "density",
153 | palette = "dark", fill = "by",
154 | grid = TRUE,
155 | main = "Distribution of petal lengths by species"
156 | )
157 | ```
158 | ````
159 | :::
160 |
161 | Here, the `fig-width: 6` and `fig-height: 6` option is utilized to set the width of the bar plot.
162 |
163 | In comparison, we have the default option of `7`:
164 |
165 | ::: {.panel-tabset group="language"}
166 | #### `{quarto-webr}` Output
167 | ```{webr-r}
168 | #| context: output
169 |
170 | tinyplot::tinyplot(
171 | ~ Petal.Length | Species,
172 | data = iris,
173 | type = "density",
174 | palette = "dark", fill = "by",
175 | grid = TRUE,
176 | main = "Distribution of petal lengths by species"
177 | )
178 | ```
179 | #### Cell Code
180 | ````md
181 | ```{webr-r}
182 | #| context: output
183 |
184 | tinyplot::tinyplot(
185 | ~ Petal.Length | Species,
186 | data = iris,
187 | type = "density",
188 | palette = "dark", fill = "by",
189 | grid = TRUE,
190 | main = "Distribution of petal lengths by species"
191 | )
192 | ```
193 | ````
194 | :::
195 |
196 | ## `out-width` and `out-height` Option
197 |
198 | 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`.
199 |
200 |
201 | ::: {.panel-tabset group="language"}
202 | #### `{quarto-webr}` Output
203 | ```{webr-r}
204 | #| context: output
205 | #| fig-width: 6
206 | #| fig-height: 6
207 | #| out-width: 500px
208 | #| out-height: 500px
209 | tinyplot::tinyplot(
210 | ~ Petal.Length | Species,
211 | data = iris,
212 | type = "density",
213 | palette = "dark", fill = "by",
214 | grid = TRUE,
215 | main = "Distribution of petal lengths by species"
216 | )
217 | ```
218 | #### Cell Code
219 | ````md
220 | ```{webr-r}
221 | #| context: output
222 | #| fig-width: 5
223 | #| fig-height: 5
224 | #| out-width: 500px
225 | #| out-height: 400px
226 | tinyplot::tinyplot(
227 | ~ Petal.Length | Species,
228 | data = iris,
229 | type = "density",
230 | palette = "dark", fill = "by",
231 | grid = TRUE,
232 | main = "Distribution of petal lengths by species"
233 | )
234 | ```
235 | ````
236 | :::
237 |
238 |
239 | ## Conclusion
240 |
241 | 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.
242 |
243 | Feel free to experiment with different combinations of these options to suit your specific needs!
244 |
--------------------------------------------------------------------------------
/docs/demos/qwebr-custom-repository.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Demo: Custom R WASM Package Repository"
3 | engine: knitr
4 | webr:
5 | packages: ['demorwasmbinary']
6 | repos:
7 | - https://tutorials.thecoatlessprofessor.com/webr-unified-gh-workflow/
8 | filters:
9 | - webr
10 | ---
11 |
12 | # Overview
13 |
14 | In this example, we add a custom R WASM Package repository that contains `demorwasmbinary` R WASM package. The package is not available from the [main webR repository](https://repo.r-wasm.org/).
15 |
16 | The source of the custom repository can be viewed [here](https://github.com/coatless-tutorials/webr-unified-gh-workflow) and the rendered website using {pkgdown} can be viewed [here](https://tutorials.thecoatlessprofessor.com/webr-unified-gh-workflow/). Another approach would be to use [r-universe.dev](https://ropensci.org/blog/2023/11/17/runiverse-wasm/)
17 | to automatically build and supply R WASM package binaries.
18 |
19 | ## Specify `repos` key
20 |
21 | To automatically have the package installed and loaded like normal, please specify the name of the package in `packages` and where the custom repository is in `repos`.
22 |
23 | For this example, we would specify:
24 |
25 | ```yaml
26 | ---
27 | webr:
28 | packages: ['demorwasmbinary']
29 | repos:
30 | - https://tutorials.thecoatlessprofessor.com/webr-unified-gh-workflow/
31 | ---
32 | ```
33 |
34 | :::{.callout-note}
35 | This version will ensure that any `webr-r` code cells inside of the document are not run prior to the package being present.
36 | :::
37 |
38 | ## Specify `repos` in `webr::install()`
39 |
40 | Alternatively, we can avoid registering a repository and directly install
41 | from a custom repository by using `webr::install(pkg, repos = "...")`.
42 |
43 | For example, we can re-create the above statement using:
44 |
45 | ````md
46 | ```{webr-r}
47 | # context: setup
48 | # Install the binary from a custom repository
49 | webr::install(
50 | "demorwasmbinary",
51 | repos = "https://tutorials.thecoatlessprofessor.com/webr-unified-gh-workflow/"
52 | )
53 |
54 | library("demorwasmbinary")
55 | ```
56 | ````
57 |
58 | # Explore the package
59 |
60 | Finally, let's use the package within a regular webR code cell, e.g.
61 |
62 | ```{webr-r}
63 | #| context: interactive
64 | # Check to see if the function works
65 | demorwasmbinary::in_webr()
66 |
67 | # View help documentation
68 | ?demorwasmbinary::in_webr
69 | ```
70 |
--------------------------------------------------------------------------------
/docs/demos/qwebr-feature-demos.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Feature Demonstrations"
3 | ---
4 |
5 | Below is a list of different demonstrations of the extensions features. These demos were created to showcase different feature releases.
6 |
7 | - [Editor Options](qwebr-editor-options.qmd)
8 | - [Set Global Cell Options](qwebr-global-cell-defaults.qmd)
9 | - [Read-only Interactive Code Cells](qwebr-read-only.qmd)
10 | - [Autorun Interactive Code Cells](qwebr-auto-run.qmd)
11 | - [Initial Code Cell Option Support](qwebr-code-cell-options.qmd)
12 | - [Using Custom Repositories for R WASM Package binaries](qwebr-custom-repository.qmd)
13 | - [Revamped Noninteractive Areas](qwebr-non-interactive-areas.qmd)
14 | - [webR in RevealJS](https://quarto-webr.thecoatlessprofessor.com/examples/revealjs)
15 | - [Locking interactive areas when long runtime is present](qwebr-long-running-execution-interactive-locking.qmd)
16 | - [Setting Options in Document Header](qwebr-setting-options-in-document-yaml.qmd)
17 | - [webR in Quarto HTML Documents](https://quarto-webr.thecoatlessprofessor.com/examples/readme/)
--------------------------------------------------------------------------------
/docs/demos/qwebr-global-cell-defaults.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Demo: Set Global Cell Options"
3 | engine: knitr
4 | webr:
5 | cell-options:
6 | out-width: "100%"
7 | autorun: true
8 | read-only: true
9 | filters:
10 | - webr
11 | ---
12 |
13 | :::{.callout-important}
14 | This feature is currently experimental and is included in 0.4.2-dev.1 build of `{quarto-webr}`.
15 | :::
16 |
17 | # Overview
18 |
19 | This demo illustrates how to set cell-level options for the entire document by specifying them in the document header. Once established, these options govern the behavior and appearance of `{webr-r}` code cells. However, they can be overridden locally by specifying cell options within individual `{webr-r}` cells.
20 |
21 | ## `cell-options` Document Key
22 |
23 | To establish default cell behavior, you can utilize the `cell-options` subkey in `webr`. For instance, consider the following structure:
24 |
25 | ```yaml
26 | webr:
27 | cell-options:
28 | :
29 | ```
30 |
31 | Here, `` and `` represent one of the [supported cell options](../qwebr-cell-options.qmd).
32 |
33 | ## Restricting Access
34 |
35 | An example use case is to prevent modifications to interactive code cells while ensuring their content is executed. In this document, we've defined the global behavior with:
36 |
37 | ```md
38 | ---
39 | title: "Demo: Set Global Cell Options"
40 | engine: knitr
41 | webr:
42 | cell-options:
43 | out-width: "100%"
44 | autorun: true
45 | read-only: true
46 | filters:
47 | - webr
48 | ---
49 | ```
50 |
51 | Let's observe the outcome with a cell like this:
52 |
53 | ::: {.panel-tabset group="language"}
54 | #### `{quarto-webr}` Output
55 | ```{webr-r}
56 | fit = lm(mpg ~ am, data = mtcars)
57 | summary(fit)
58 | ```
59 | #### Cell Code
60 | ````md
61 | ```{webr-r}
62 | fit = lm(mpg ~ am, data = mtcars)
63 | summary(fit)
64 | ```
65 | ````
66 | :::
67 |
68 | Attempting to modify the cell will be ineffective. However, in the subsequent cell, we've specified a local option that overrides the document's default, allowing modification. Feel free to try modifying the cell below.
69 |
70 | ::: {.panel-tabset group="language"}
71 | #### `{quarto-webr}` Output
72 | ```{webr-r}
73 | #| read-only: false
74 | plot(fit)
75 | ```
76 | #### Cell Code
77 | ````md
78 | ```{webr-r}
79 | #| read-only: false
80 | plot(fit)
81 | ```
82 | ````
83 | :::
84 |
85 | # Conclusion
86 |
87 | This approach eliminates the need to repeatedly specify options across multiple cells within the document, consolidating them in a single location. Should the need arise, you can always override the behavior by specifying a local value for the cell.
--------------------------------------------------------------------------------
/docs/demos/qwebr-long-running-execution-interactive-locking.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Demo: Locking interactive code"
3 | engine: knitr
4 | filters:
5 | - webr
6 | ---
7 |
8 | :::{.callout-important}
9 | We've slowed down each cell's execution time by 5 seconds by adding `Sys.sleep()` to emphasize code cell locking.
10 | :::
11 |
12 | # Say Hi
13 |
14 | ```{webr-r}
15 | #| context: interactive
16 | print("Hello {quarto-webr} world!")
17 | Sys.sleep(5) # Sleep for 5 seconds
18 | ```
19 |
20 | # Calculate
21 |
22 | ```{webr-r}
23 | #| context: interactive
24 | -3 + 5
25 | Sys.sleep(5) # Sleep for 5 seconds
26 | ```
27 |
28 | # Help!
29 |
30 | ```{webr-r}
31 | #| context: interactive
32 | ?mean
33 | Sys.sleep(5) # Sleep for 5 seconds
34 | ```
35 |
36 |
--------------------------------------------------------------------------------
/docs/demos/qwebr-non-interactive-areas.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Demo: Revamped Noninteractive Areas"
3 | engine: knitr
4 | webr:
5 | packages: ['ggplot2', 'dplyr']
6 | filters:
7 | - webr
8 | ---
9 |
10 | :::{.callout-important}
11 | We've slowed down each cell's execution time by about 1/2 of a second to show how the document is responding.
12 | :::
13 |
14 | # Package dependencies
15 |
16 | The `quarto-webr` extension is set to automatically install and load the `ggplot2` and `dplyr` packages by specifying a `packages` key in the document's header.
17 |
18 | # Setup a hidden ggplot2 object
19 |
20 | From there, we're going to use the `context: setup` hidden cell to create a `ggplot2` object that uses the `mtcars` data set with the aesthetic mappings of `x = wt` and `y = mpg` called `g`.
21 |
22 | ```{webr-r}
23 | #| context: setup
24 | g <- ggplot(mtcars, aes(x = wt, y = mpg))
25 |
26 | Sys.sleep(0.5)
27 | ```
28 |
29 | # Generate a graph
30 |
31 | Let's move from setup to generating and displaying results by using `g` object created in `setup` within an `output` context:
32 |
33 | ```{webr-r}
34 | #| context: output
35 | g + geom_point()
36 |
37 | Sys.sleep(0.5)
38 | ```
39 |
40 | # Re-use prior graph object
41 |
42 | Let's also re-use the base `g` but change the aesthetics so that colour is now present.
43 |
44 | ```{webr-r}
45 | #| context: output
46 | g + geom_point(aes(colour = factor(cyl)))
47 | Sys.sleep(0.5)
48 | ```
49 |
50 | # Work with a hidden setup object
51 |
52 | Finally, let's make sure we can do some interesting things with the interactive session.
53 |
54 | :::{.callout-note}
55 | Changes inside of interactive cells do not propagate backwards in the document.
56 | :::
57 |
58 | ```{webr-r}
59 | g
60 | ```
61 |
--------------------------------------------------------------------------------
/docs/demos/qwebr-read-only.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Demo: Read-Only Code Cells"
3 | engine: knitr
4 | filters:
5 | - webr
6 | ---
7 |
8 | # Overview
9 |
10 | This demo shows how a code cell can be placed into a read-only mode.
11 |
12 | ## `read-only` Option
13 |
14 | The `read-only` option modifies the `interactive` context such that changes to the cell's code is not possible.
15 |
16 | For example, try modifying the value associated with `age` in the following cell.
17 |
18 | ::: {.panel-tabset group="readOnlyExmple"}
19 | #### `{quarto-webr}` Output
20 | ```{webr-r}
21 | #| context: interactive
22 | #| read-only: true
23 | # Try modifying the age variable
24 | age <- 42
25 | cat("Your age is: ", age, fill = TRUE)
26 | ```
27 | #### Cell Code
28 | ````md
29 | ```{webr-r}
30 | #| context: interactive
31 | #| read-only: true
32 | # Try modifying age
33 | age <- 42
34 | cat("Your age is: ", age, fill = TRUE)
35 | ```
36 | ````
37 | :::
38 |
39 | ## Constraining Modifications
40 |
41 | We can pair `read-only` with `autorun` to create a constrained example allowing us to focus on a single piece of the code.
42 |
43 | For example, let's say we want to understand what happens when we increase the number of observations randomly sampled from a normal distribution. We could define two interactive cells:
44 |
45 | 1. one cell exposing changes to the number of samples, e.g. `n`; and,
46 | 2. a second cell containing graphing code that is restricted from being modified.
47 |
48 |
49 | ::: {.panel-tabset group="readOnlyExmple"}
50 | #### `{quarto-webr}` Output
51 |
52 | Try different values for `n` by modifying the assignment statement.
53 | ```{webr-r}
54 | #| context: interactive
55 | #| autorun: true
56 | # Experiment with different sample sizes by
57 | # changing the n value and re-running the code
58 | # cell.
59 | n <- 100
60 | ```
61 |
62 | Then, press "Run Code" to recreate the graph and see how the distribution changed:
63 |
64 | ```{webr-r}
65 | #| context: interactive
66 | #| autorun: true
67 | #| read-only: true
68 | samples = rnorm(n)
69 | hist(samples,
70 | main = "Randomly Sampled Normal Distribution",
71 | sub = paste("Based on", n, "samples"),
72 | xlab = "Sample Value"
73 | )
74 | ```
75 |
76 | #### Cell Code
77 | ````md
78 | ```{webr-r}
79 | #| context: interactive
80 | #| autorun: true
81 | # Experiment with different sample sizes by
82 | # changing the n value and re-running the code
83 | # cell.
84 | n <- 100
85 | ```
86 | ```{webr-r}
87 | #| context: interactive
88 | #| autorun: true
89 | #| read-only: true
90 | samples = rnorm(n)
91 | hist(samples,
92 | main = "Randomly Sampled Normal Distribution",
93 | sub = paste("Based on", n, "samples"),
94 | xlab = "Sample Value"
95 | )
96 | ```
97 | ````
98 | :::
99 |
100 | # Fin
101 |
102 | In this demo, we saw the possibility of preventing modifications to a code cell area.
103 |
--------------------------------------------------------------------------------
/docs/demos/qwebr-setting-options-in-document-yaml.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Demo: Setting Options in Document Header"
3 | format: html
4 | engine: knitr
5 | webr:
6 | packages: ['ggplot2', 'dplyr']
7 | show-startup-message: true
8 | show-header-message: true
9 | autoload-packages: false
10 | filters:
11 | - webr
12 | ---
13 |
14 | # Demo
15 |
16 | webR-enabled code cells are established by using `{webr-r}` in a Quarto HTML document.
17 |
18 | ```{webr-r}
19 | library("ggplot2")
20 |
21 | ggplot()
22 | ```
--------------------------------------------------------------------------------
/docs/images/rstudio-render-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coatless/quarto-webr/8ad65f045e718ecfd45c0e5b2ec04998dd508c0f/docs/images/rstudio-render-button.png
--------------------------------------------------------------------------------
/docs/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: Greetings from quarto-webr Wonderland!
3 | subtitle: Empowering Your Quarto Documents with R through webR
4 | format: html
5 | engine: knitr
6 | filters:
7 | - webr
8 | ---
9 |
10 | Welcome to the documentation portal for the community [`quarto-webr`](https://github.com/coatless/quarto-webr) extension – your key to unlocking the endless possibilities of [webR](https://docs.r-wasm.org/webr/latest/) within various [Quarto](https://quarto.org/) formats, including [HTML](https://quarto.org/docs/output-formats/html-basics.html), [RevealJS](https://quarto.org/docs/presentations/revealjs/), [Websites](https://quarto.org/docs/websites/), [Blogs](https://quarto.org/docs/websites/website-blog.html), and [Books](https://quarto.org/docs/books).
11 |
12 | Ready for an exciting journey into the world of webR's interactive code cells? Click the "Run Code" button below to experience it firsthand:
13 |
14 | ```{webr-r}
15 | # Fit a linear model
16 | model = lm(mpg ~ wt, data = mtcars)
17 |
18 | # Obtain a summary
19 | summary(model)
20 | ```
21 |
22 | At its core, the community [`quarto-webr` extension](https://github.com/coatless/quarto-webr) is designed to empower you to run R code directly in your web browser using familiar reporting tools, all without the need for an external R server. Moreover, the extension abstracts away the need to know HTML or JavaScript to use webR. However, it's worth noting that you can also choose to unlock the full potential of webR and create more complex applications independently by directly using **[webR's JavaScript API](https://docs.r-wasm.org/webr/latest/evaluating.html)**, granting you unparalleled freedom to harness the power of R in innovative ways.
23 |
24 | With this in mind, let's dive in and kickstart your journey with interactive code cells by [creating our very first webR-powered Quarto document](qwebr-first-steps.qmd) or [exploring some examples](qwebr-code-cell-demos.qmd)!
25 |
--------------------------------------------------------------------------------
/docs/qwebr-acknowledgements.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Acknowledgments and Collaborations"
3 | subtitle: "Bringing webR to Quarto"
4 | date: "03-11-2023"
5 | date-modified: last-modified
6 | aliases:
7 | - webr-acknowledgements.html
8 | ---
9 |
10 | We would like to express our heartfelt gratitude to several individuals and teams who played a pivotal role in bringing [`quarto-webr`](https://github.com/coatless/quarto-webr) to life as an extension for Quarto. Without their dedication and contributions, this project would not have been possible.
11 |
12 | ## quarto-webr Extension Core Developers
13 |
14 | - [James Joseph Balamuta](https://github.com/coatless)
15 | - [JooYoung Seo](https://github.com/jooyoungseo) for accessibility improvements.
16 |
17 | They played a pivotal role in shaping the development of this Quarto extension.
18 |
19 | ## webR Core Developers
20 |
21 | - [George Stagg](https://github.com/georgestagg)
22 | - [Lionel Henry](https://github.com/lionel-)
23 |
24 | Their tireless efforts and expertise in developing [webR](https://docs.r-wasm.org/webr/latest/) were instrumental in being able to even develop this extension for Quarto. We are immensely grateful for their contribution of the webR project. Further, we greatly appreciate them answering our questions and providing guidance throughout the development process.
25 |
26 | ## Early Testing Feedback
27 |
28 | We extend our sincere appreciation to the following individuals for providing early testing feedback on the extension:
29 |
30 | - [Eli E. Holmes](https://eeholmes.github.io/)
31 | - [Bob Rudis](https://rud.is/)
32 |
33 | Their insightful feedback and suggestions have been invaluable in refining and enhancing the functionality of the extension.
34 |
35 | ## Quarto Team Assistance
36 |
37 | We would like to acknowledge the Quarto team for their assistance in setting up a new code cell type, which greatly improved the overall functionality of the extension. You can view the discussion [here](https://github.com/quarto-dev/quarto-cli/discussions/4761#discussioncomment-5336636).
38 |
39 | ## Inspirations
40 |
41 | Our project built upon the initial proof of concept for a standalone Quarto HTML document, made possible by the work of the [coatless-r-n-d/webR-quarto-demos](https://github.com/coatless-r-n-d/webR-quarto-demos) repository.
42 |
43 | Additionally, we were inspired by the following public-facing examples from the webR Core developers that contributed to the initial standalone experiment:
44 |
45 | - [Source of Tidyverse Blog Post](https://github.com/tidyverse/tidyverse.org/pull/617/files) and [Minor fix](https://github.com/tidyverse/tidyverse.org/commit/72bb2dd7ca0b2f211498a891aa54f55ddcad5014)
46 | - [webR documentation landing page](https://github.com/r-wasm/webr/blob/53acd8861c44f1f167941d0a40f62b0cc23852da/src/docs/index.qmd#L23-L68) ([Live page](https://docs.r-wasm.org/webr/latest/))
47 |
48 | # Fin
49 |
50 | Once again, thank you to everyone who contributed, collaborated, and provided support throughout this project. Your dedication and expertise have made this achievement possible.
--------------------------------------------------------------------------------
/docs/qwebr-cell-options.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Code Cell Options"
3 | subtitle: "Supported Cell Options in `{webr-r}` Blocks"
4 | date: "01-30-2024"
5 | date-modified: last-modified
6 | format:
7 | html:
8 | toc: true
9 | engine: knitr
10 | ---
11 |
12 | 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`.
13 |
14 | Here's an example of how you can use these options:
15 |
16 | ````md
17 | ```{webr-r}
18 | #| results: 'asis'
19 | #| fig-width: 5
20 |
21 | # R code here
22 | ```
23 | ````
24 |
25 | In this example, the cell options `results` is set to `'asis'`, and `fig-width` is set to `5` inches.
26 |
27 | 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.
28 |
29 |
30 | :::{.callout-important}
31 | 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 the tables below for details on what is available.
32 | :::
33 |
34 | ## quarto-webr
35 |
36 | :::{.callout-note}
37 | Options listed here are unique to the `{quarto-webr}` extension and do not have a Quarto equivalent.
38 | :::
39 |
40 | ### Run Options
41 |
42 | | Option | Default Value | Description |
43 | |----------------------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
44 | | `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). |
45 | | `autorun` | `false` | Allow `interactive` cells to be run during document initialization without a user pressing run code. |
46 |
47 |
48 | :::{.callout-note}
49 | For details regarding run options, please see [Hiding and Executing Code](qwebr-internal-cell.qmd).
50 | :::
51 |
52 |
53 | ### Monaco Editor Options
54 |
55 | | Option | Default Value | Description |
56 | |----------------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
57 | | `read-only` | `false` | Prevent code in `interactive` cells from being modified by disallowing code input. |
58 | | `editor-max-height` | `0` | Set a threshold to prevent infinite growth of the editor window. |
59 | | `editor-quick-suggestions` | `false` | Show a list of autocomplete variables and/or functions based on what was typed. |
60 | | `editor-font-scale` | `1` | Modify the size of code cell and output relative to the page font size. Values less than 1 shrink the text size and values greater than 1 increase the text size. |
61 | | `editor-word-wrap` | `true` | Allow long lines to be wrapped to avoid code going off the screen causing a scroll bar to appear. |
62 |
63 |
64 |
65 | ## Attributes
66 |
67 | | Option | Default Value | Description |
68 | |-----------|---------------|---------------------------------------------------|
69 | | `label` | `''` | Unique label for code cell. Useful for debugging. |
70 | | `classes` | `''` | Classes to apply to cell container |
71 |
72 | ## Cell Output
73 |
74 | | Option | Default Value | Description |
75 | |-----------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
76 | | `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). |
77 | | `output` | `true` | Controls inclusion of results: `true` (all results), `false` (no results), or `'asis'` (output as-is, raw text results directly into the output document). |
78 | | `warning` | `true` | Preserve standard error output (`warning()`, `message()`, or `stop()`) in the output. |
79 | | `message` | `true` | See prior entry. |
80 |
81 |
82 | :::{.callout-important}
83 | 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.
84 | :::
85 |
86 | ## Figures
87 |
88 | | Option | Default Value | Description |
89 | |--------------|---------------|-------------------------------------------------------------------------------------------------------------------------------|
90 | | `fig-cap` | `""` | Figure caption that should appear under the canvas |
91 | | `dpi` | `72` | Dots per inch to use in calculating pixel values for `fig-height` and `fig-width`, e.g. `dpi * inches = pixels`. |
92 | | `fig-width` | `7` | Width of the plot (in inches) |
93 | | `fig-height` | `5` | Height of the plot (in inches) |
94 | | `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"`. |
95 | | `out-height` | `""` | Height of the plot in the output document, similar to `out-width`. |
96 |
--------------------------------------------------------------------------------
/docs/qwebr-code-cell-demos.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Exploring Interactive Code Cells"
3 | subtitle: "Unleash the Power of Interactive R Code in Your Quarto Documents"
4 | author: "James Joseph Balamuta"
5 | date: "03-14-2023"
6 | date-modified: last-modified
7 | format:
8 | html:
9 | toc: true
10 | engine: knitr
11 | filters:
12 | - webr
13 | aliases:
14 | - webr-code-cell-demos.html
15 | ---
16 |
17 | Welcome to the world of interactive code cells, unlocked by the community `quarto-webr` extension. These cells allow you to run R code directly within your Quarto HTML documents, enabling real-time computations, dynamic visualizations, and more. Let's explore the impressive capabilities webR offers.
18 |
19 | # Creating webR-Enabled Code Cells
20 |
21 | To create a webR-enabled code cell, simply use the `{webr-r}` tag in your Quarto HTML document, like this:
22 |
23 | ```{webr-r}
24 | 1 + 1
25 | ```
26 |
27 | For example, the code cell above, powered by `webr`, was generated by entering the following into the Quarto document:
28 |
29 | ```{{webr-r}}
30 | 1 + 1
31 | ```
32 |
33 | # Sample Use Cases
34 |
35 | Now, let's delve into some practical scenarios where interactive code cells shine.
36 |
37 | ## Fit a Linear Regression Model
38 |
39 | We begin by using the "Hello World" example of statistics: fitting and analyzing a linear regression.
40 |
41 | ```{webr-r}
42 | fit <- lm(mpg ~ vs, data = mtcars)
43 |
44 | summary(fit)
45 | ```
46 |
47 | ## Line-by-line Execution
48 |
49 | In this section, we'll explore the built-in keyboard shortcuts for executing code within the interactive code cell. You can run either the selected code or specific lines or the entire cell with the following keyboard shortcuts:
50 |
51 | - Run selected code:
52 | - macOS: ⌘ + ↩/Return
53 | - Windows/Linux: Ctrl + ↩/Enter
54 |
55 | - To run the entire code cell, you can simply click the "Run code" button, or use the keyboard shortcut:
56 | - Shift + ↩
57 |
58 | Feel free to try it out in the following code cell:
59 |
60 | ```{webr-r}
61 | # Try running selected code at the start of the line
62 | print("Hello quarto-webr World!")
63 |
64 | # Try highlight only -3 or 5 and pressing the keys required
65 | # for the "selected code" approach
66 | -3 + 5
67 |
68 | # Finally, try running the entire code cell by using Shift + ↩
69 | ```
70 |
71 | By using these shortcuts, you can run code conveniently and efficiently. This practice can also help you become familiar with keyboard shortcuts when transitioning to integrated development environments (IDEs) like [RStudio](https://posit.co/products/open-source/rstudio/) or [Visual Studio Code with R](https://code.visualstudio.com/docs/languages/r).
72 |
73 |
74 | ## Preventing Modifications to Code
75 |
76 | Code cells can be locked to their initial state by specifying `#| read-only: true`. The next code cell has such a feature implemented. Try modifying the expression `1 + 1` to any other value.
77 |
78 | ::: {.panel-tabset}
79 | ## `{quarto-webr}` Output
80 |
81 | ```{webr-r}
82 | #| read-only: true
83 | 1 + 1
84 | ```
85 |
86 | ## Cell code
87 |
88 | ```{{webr-r}}
89 | #| read-only: true
90 | 1 + 1
91 | ```
92 | :::
93 |
94 | :::{.callout-note}
95 | This option can be paired with `autorun: true` to avoid having the user press the "Run code" button to see the output.
96 | :::
97 |
98 |
99 | ## Drawing Attention to Code
100 |
101 | Lines of code can be highlighted using `editor-code-line-numbers` to draw attention to specific parts of the code. For example:
102 |
103 | - `editor-code-line-numbers: 1-3` will highlight lines 1 to 3.
104 | - `editor-code-line-numbers: 1,3,6` will highlight lines 1, 3, and 6.
105 | - `editor-code-line-numbers: 1,3-5,7` will highlight lines 1, 3 to 5, and 7.
106 |
107 | We can see the `1,3-5,7` example in the following code cell:
108 |
109 | ::: {.panel-tabset}
110 | ## `{quarto-webr}` Output
111 |
112 | ```{webr-r}
113 | #| read-only: true
114 | #| editor-code-line-numbers: 1,3-5,7
115 |
116 | # This is a comment
117 |
118 | 1 + 1
119 | 2 + 2
120 | 3 + 3
121 |
122 | # This is another comment
123 | ```
124 |
125 | ## Cell code
126 |
127 | ```{{webr-r}}
128 | #| read-only: true
129 | #| editor-code-line-numbers: 1,3-5,7
130 |
131 | # This is a comment
132 |
133 | 1 + 1
134 | 2 + 2
135 | 3 + 3
136 |
137 | # This is another comment
138 | ```
139 | :::
140 |
141 |
142 | ## Create a Graph with Base R
143 |
144 | For this example, webR empowers us to create and visualize data plots interactively. We can tweak labels, colors, or even the variables being used on an as-needed basis to explore "What if ..." scenarios. For instance, what if we try changing the value `blue` to `orange` and run the code again.
145 |
146 | ```{webr-r}
147 | plot(
148 | mpg ~ wt,
149 | data = mtcars,
150 | col = "blue",
151 | xlab = "Miles/(US) gallon",
152 | ylab = "Weight (1000 lbs)",
153 | main = "Miles per Gallon and Weight of Cars",
154 | sub = "Source: 1974 Motor Trend US magazine."
155 | )
156 | ```
157 |
158 |
159 |
160 | ## Fill in the Blanks
161 |
162 | Another approach is to purposely leave out part of a command during an exercise to afford students structure in solving it. For example, we could have the question of:
163 |
164 | > Fill in the blank to have the following expression add up to **42**.
165 |
166 | ```{webr-r}
167 | 35 + ________
168 | ```
169 |
170 | ## Data Wrangle in Real Time
171 |
172 | Data manipulation is a crucial part of data analysis. In this example, we'll modify a data set in real-time and view the results. It's like changing ingredients while cooking to get the perfect dish!
173 |
174 | ```{webr-r}
175 | # Create a copy of the data
176 | mtcars2 <- mtcars
177 |
178 | # Change variable to a factor
179 | mtcars2$vs <- factor(mtcars2$vs, labels = c("V", "S"))
180 |
181 | modified_vs_data = data.frame(
182 | "original_vs" = mtcars$vs,
183 | "modified_vs" = mtcars2$vs
184 | )
185 |
186 | head(modified_vs_data)
187 | ```
188 |
189 |
190 | ## Working with R Packages
191 |
192 | You can incorporate R packages available in webR by installing them interactively using `webr::install()` within a `{webr-r}` code cell or by specifying them in the document's YAML. Once you've installed a package, you can harness its power just as you would in a traditional R environment. For more details, please refer to [Using R Packages](qwebr-using-r-packages.qmd).
193 |
194 | :::callout-note
195 | Please note that installing certain packages, such as `ggplot2`, may take some time depending on the [communication channel](qwebr-communication-channels.qmd) being used.
196 | :::
197 |
198 | Let's take `ggplot2` as an example:
199 |
200 | ```{webr-r}
201 | webr::install("ggplot2")
202 | ```
203 |
204 | With `ggplot2` now installed, let's create a graph with it!
205 |
206 | ```{webr-r}
207 | library(ggplot2)
208 |
209 | p <- ggplot(mpg, aes(class, hwy))
210 | p + geom_boxplot()
211 | ```
212 |
213 | ## Variable Definitions and Reuse
214 |
215 | Define variables in one code cell and reuse them in subsequent cells:
216 |
217 | ```{webr-r}
218 | name <- "James"
219 | age <- 42
220 | ```
221 |
222 | ```{webr-r}
223 | message(name, " is ", age, " years old!")
224 | ```
225 |
226 | ## Functions
227 |
228 | Functions can similarly be defined and used in one code cell or multiple code cells.
229 |
230 | ```{webr-r}
231 | say_hello = function(name) {
232 | msg = paste0("Hello ", name, "! Welcome to webR :)")
233 | return(msg)
234 | }
235 |
236 | say_hello("James")
237 | ```
238 |
239 | ```{webr-r}
240 | say_hello("Hulya")
241 | ```
242 |
243 | :::callout-note
244 |
245 | The function definition must be run before calling the function. Otherwise, there will be an error that is generated.
246 | :::
247 |
248 | ## Handling Errors and Warnings
249 |
250 | When webR encounters an error while running R code, the error and warning messages are displayed to the user.
251 |
252 | For example, if the routine has a hard stop, the execution immediately ends, and the message is shared.
253 |
254 | ```{webr-r}
255 | stop("This is a hard error")
256 | ```
257 |
258 | Similarly, if a variable is not found, then the code stops being evaluated and returns an error.
259 | ```{webr-r}
260 | variable_not_defined
261 | ```
262 |
263 | Unlike errors, warning messages are allowed to propagate into the output without stopping the computation.
264 |
265 | ```{webr-r}
266 | warning("Uh-oh, there's a warning!")
267 |
268 | # Compute a value
269 | 1 + 1
270 | ```
271 |
272 | This is even the case inside of complex functions.
273 |
274 | ```{webr-r}
275 | quadratic_roots <- function(a, b, c) {
276 |
277 | cat(paste0("Analyzing the quadratic equation: ", a, "x^2 + ", b, "x + ", c, "."))
278 |
279 | discriminant <- (b^2) - (4*a*c)
280 |
281 | # Check if there are 2 solutions
282 | if(discriminant != 0) {
283 |
284 | # Are the solutions imaginary?
285 | if(discriminant < 0) {
286 | warning("There are no real-numbered roots for this quadratic equation.")
287 | discriminant <- as.complex(discriminant)
288 | }
289 |
290 | # Compute the solutions
291 | x_intercepts <- (-b + c(-1, 1) * sqrt(discriminant)) / (2*a)
292 |
293 | return(x_intercepts)
294 | }
295 |
296 | # When the discriminant is 0, compute a single solution.
297 | x_intercept <- (-b) / (2*a)
298 |
299 | return(x_intercept)
300 | }
301 |
302 | quadratic_roots(1, 3, 7)
303 | ```
304 |
305 | ## Escaping Characters in a String
306 |
307 | Handle special characters in strings with ease:
308 |
309 | ```{webr-r}
310 | seven_seas <- "Ahoy, matey!\nLet's set sail for adventure!\n"
311 | seven_seas
312 | ```
313 |
314 | ## Anonymous Function Definition
315 |
316 | Define and use anonymous functions seamlessly:
317 |
318 | ```{webr-r}
319 | add_one <- \(x) x + 1
320 | add_one(2)
321 | ```
322 |
323 | ## Empty Code Cell
324 |
325 | Define an empty code cell by simply leaving it blank.
326 |
327 | ```{webr-r}
328 |
329 | ```
330 |
331 | ## Pre-rendered Code Cell
332 |
333 | Any code using the usual `{r}` tag will be executed, and its output saved, just as if you were rendering a Quarto document without the webR extension:
334 |
335 | ```{r}
336 | message("Hello!")
337 | ```
338 |
339 | # Fin
340 |
341 | These are just some of the powerful features and capabilities that webR brings to your Quarto HTML documents, making your data analysis and presentation more dynamic and engaging. Have an interesting example to share? Let us know [at our issue tracker](https://github.com/coatless/quarto-webr/issues)!
342 |
--------------------------------------------------------------------------------
/docs/qwebr-deployment-templates.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Deployment Templates"
3 | date: "10-01-2023"
4 | date-modified: last-modified
5 | ---
6 |
7 | Discover a range of sample deployment templates for the community `quarto-webr` extension at our [GitHub repository](https://github.com/coatless/quarto-webr/tree/main/examples). These templates serve as convenient starting points for various web-based projects that harness the power of the `quarto-webr` extension, enabling interactive data analysis inside of a web browser. Whether you're embarking on an individual report, creating an interactive website, or compiling a digital book, these templates simplify the process, making it effortless to kickstart your own projects.
8 |
9 | # HTML Document Template
10 |
11 | This template is designed for creating standalone HTML documents with interactive webR functionality. It's suitable for individual reports or interactive documents.
12 |
13 | - **Example**: You can find an example of an HTML document template [here](https://quarto-webr.thecoatlessprofessor.com/examples/html-document/).
14 | - **Source Code**: Access the source code for this template [here](https://github.com/coatless/quarto-webr/tree/main/examples/html-document).
15 |
16 | # RevealJS Presentation Template
17 |
18 | This template is designed for creating standalone RevealJS presentations with interactive webR functionality. It's suitable for creating lecture slides.
19 |
20 | :::{.callout-important}
21 | This template requires a [**pre-release** version of Quarto that is 1.4.502 or greater](https://quarto.org/docs/download/prerelease) that contains an updated copy of `pandoc`. For more details, please see [Issue #14](https://github.com/coatless/quarto-webr/issues/14).
22 | :::
23 |
24 | - **Example**: You can find an example of a RevealJS presentation template [here](https://quarto-webr.thecoatlessprofessor.com/examples/revealjs/).
25 | - **Source Code**: Access the source code for this template [here](https://github.com/coatless/quarto-webr/tree/main/examples/revealjs).
26 |
27 | # Website Template
28 |
29 | This template is meant for building interactive websites with multiple webR-powered pages. It's ideal for websites that have multiple piece of web content that requires interactive data analysis at the "top-level".
30 |
31 | - **Example**: Explore an example of a website template [here](https://quarto-webr.thecoatlessprofessor.com/examples/website/).
32 | - **Source Code**: Access the source code for this template [here](https://github.com/coatless/quarto-webr/tree/main/examples/website).
33 |
34 | # Blog Template
35 |
36 | For users who want to periodically use webR on their Quarto blog, please use the following template.
37 |
38 | - **Example**: Explore an example of a blog website template [here](https://quarto-webr.thecoatlessprofessor.com/examples/blog/).
39 | - **Source Code**: Access the source code for this template [here](https://github.com/coatless/quarto-webr/tree/main/examples/blog).
40 |
41 | # Book Template
42 |
43 | The book template is designed for creating interactive web-based books or documentation. It allows you to compile a collection of chapters, sections, and interactive content into a cohesive digital book.
44 |
45 | - **Example**: You can view an example of a book template [here](https://quarto-webr.thecoatlessprofessor.com/examples/book).
46 | - **Source Code**: Access the source code for this template [here](https://github.com/coatless/quarto-webr/tree/main/examples/book).
47 |
--------------------------------------------------------------------------------
/docs/qwebr-developer-resources.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Developer Resources"
3 | author: "James Joseph Balamuta"
4 | date: "03-14-2023"
5 | date-modified: last-modified
6 | format:
7 | html:
8 | toc: true
9 | ---
10 |
11 | Want to contribute to the `quarto-webr` extension or customize it? This resource page guides you with essential tools and references.
12 |
13 | ## Mastering webR
14 |
15 | Understanding [webR](https://docs.r-wasm.org/webr/latest/), which powers the interactivity, is crucial for developing `quarto-webr`. Review these resources:
16 |
17 | - **[webR Documentation](https://docs.r-wasm.org/webr/latest/)**: Comprehensive guides and examples to deepen your webR knowledge.
18 | - **[webR Source Code](https://github.com/r-wasm/webr/)**: For the technically curious, explore the official webR project's development on GitHub.
19 | - **[Bob Rudis' Experiments with webR](https://rud.is/webr-experiments/)**: Discover diverse projects using the webR JavaScript API.
20 |
21 | These resources will help you master webR and, subsequently, your ability to create interactive code cells in HTML documents. Remember, webR is a versatile tool that can be used independently or alongside the community Quarto extension to unlock the magic of interactive code cells in HTML documents.
22 |
23 | Want to contribute to the `quarto-webr` extension or customize it? This resource page guides you with essential tools and references.
24 |
25 | ## Quarto Development Ecosystem
26 |
27 | For those interested in extending the `quarto-webr` extension or exploring broader extension development within the Quarto ecosystem, we recommend exploring the following supplementary resources.
28 |
29 | ### Quarto Documentation
30 |
31 | Get acquainted with Quarto's official extension documentation to deepen your understanding.
32 |
33 | - **[Filters Documentation](https://quarto.org/docs/extensions/filters.html)**: Learn the art of creating filters for Quarto documents, enabling you to customize content generation.
34 |
35 | - **[Lua Development Tips](https://quarto.org/docs/extensions/lua.html)**: Access development tips specific to Lua scripting within Quarto extensions.
36 |
37 | - **[Lua API](https://quarto.org/docs/extensions/lua-api.html)**: Explore the Lua API documentation to understand how to interact with Quarto's core functionality programmatically.
38 |
39 | ### Related Extensions
40 |
41 | For those intrigued by the broader world of extension development, we suggest the following Quarto extensions that can inspire your journey into extension development and functionality:
42 |
43 | - **[`quarto-ext/shinylive`](https://github.com/quarto-ext/shinylive)**: Explore the `shinylive` extension's codebase to understand how interactive content is implemented within Quarto documents.
44 |
45 | - **[`mcanouil/quarto-elevator`](https://github.com/mcanouil/quarto-elevator)**: Delve into the `quarto-elevator` extension to gain insights into adding new features to Quarto documents.
46 |
47 | - **[`shafayetShafee/downloadthis`](https://github.com/shafayetShafee/downloadthis/tree/main)**: Investigate the `downloadthis` extension to see how it facilitates downloads within Quarto documents.
48 |
49 | There are many more Quarto extensions to explore and learn from. For an up-to-date list, visit:
50 |
51 |
52 | ### Pandoc Essentials
53 |
54 | Pandoc plays a pivotal role in Quarto's document conversion process. To deepen your knowledge of Quarto, consider these Pandoc resources:
55 |
56 | - **[Example Filters](https://pandoc.org/lua-filters.html#examples)**: Draw inspiration from Pandoc's example filters to see how custom filters can be applied to your Quarto documents.
57 |
58 | - **[CodeBlock](https://pandoc.org/lua-filters.html#type-codeblock)**: Understand the significance of the `CodeBlock` element in Pandoc, often used for implementing extensions and custom functionality.
59 |
60 | # Fin
61 |
62 | With this wealth of resources at your disposal, you're well-equipped to embark on your development journey, whether you're diving into webR or contributing to the `quarto-webr` extension. Happy coding!
63 |
--------------------------------------------------------------------------------
/docs/qwebr-extension-website.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Extension Website"
3 | subtitle: "Development notes for the quarto-webr website"
4 | author: "James Joseph Balamuta"
5 | date: "09-17-2023"
6 | date-modified: last-modified
7 | format:
8 | html:
9 | toc: true
10 | ---
11 |
12 | # Initializing the Project
13 |
14 | To get started, follow these steps to set up the Quarto extension website project:
15 |
16 | 1. Create a new directory named `docs/` within your repository using the following command:
17 |
18 | ```sh
19 | mkdir docs && cd $_
20 | ```
21 |
22 | 2. Initialize a Quarto website project by running the following command:
23 |
24 | ```sh
25 | quarto create project website .
26 | ```
27 |
28 | # Incorporating the Extension
29 |
30 | To seamlessly integrate the extension into your project, you'll need to create a symbolic link to the `_extensions` folder containing the development version of the extension. This approach helps you avoid maintaining a duplicate copy of the extension in your Git repository history.
31 |
32 | Follow these steps:
33 |
34 | 1. Navigate to the `docs/` directory in your project.
35 |
36 | 2. Create a symbolic link to the `_extensions` folder using the following command:
37 |
38 | ```sh
39 | ln -s ../_extensions _extensions
40 | ```
41 |
42 |
--------------------------------------------------------------------------------
/docs/qwebr-faq.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Frequently Asked Questions"
3 | subtitle: "Find Answers to Common Queries About the community `quarto-webr` Extension"
4 | date: "10-01-2023"
5 | date-modified: last-modified
6 | engine: markdown
7 | format:
8 | html:
9 | toc: true
10 | aliases:
11 | - webr-faq.html
12 | ---
13 |
14 | Welcome to our Frequently Asked Questions (FAQ) page, your go-to resource for finding answers to common queries about the community `quarto-webr` extension. If you can't find the answer you're looking for, don't hesitate to reach out to our community for additional support by opening a [question](https://github.com/coatless/quarto-webr/issues/new?assignees=&labels=q%26a&projects=&template=question.yml&title=%5BQ%26A%5D%3A+) or a [bug report](https://github.com/coatless/quarto-webr/issues/new?assignees=&labels=bug%2Ctriage-needed&projects=&template=bug-report.yml&title=%5BBug%5D%3A+) on the [issue tracker](https://github.com/coatless/quarto-webr/issues).
15 |
16 | # Stability and Long Term Support
17 |
18 | > Q. Would you say the quarto-webr extension API is stable? Thinking about starting to convert course notes and wondering where the project is in terms of stability.
19 |
20 | Yes, the `quarto-webr` extension API can be considered stable for most practical purposes. It has undergone significant development and testing to ensure that it functions reliably and consistently within the Quarto framework. You can confidently start converting your course notes and materials using this extension.
21 |
22 | However, it's important to keep in mind a few considerations:
23 |
24 | 1. **Dependency on Quarto and webR projects:** The `quarto-webr` extension relies on the main `webR` project for its core functionality. While we actively maintain the `quarto-webr` extension and aim to keep it compatible with the latest versions of Quarto and `webR`, we cannot control what happens upstream at either project. Changes or updates to either project may occasionally require adjustments in the extension. For the most part, these adjustments will be largely hidden.
25 |
26 | 1. **Version compatibility:** It's important to note that the version of the R client and R packages that is downloaded for `webR` execution may affect your materials. It's advisable to periodically review and update your teaching materials, especially when major changes occur in R version or R package contents, just as before.
27 |
28 | 1. **Start with a small set:** When converting your course materials, it's a good practice to start with a small set of materials as a pilot. This allows you to familiarize yourself with the extension's functionality and raise/address any specific issues that may arise during the conversion process. Once you are comfortable with the workflow and have tested your materials, you should proceed with converting the rest of your course content.
29 |
30 | # Improving Performance
31 |
32 | > Q. What are your plans, if any, for scaling webR to handle complex content faster?
33 |
34 | For handling complex content, we recommend setting the `channel-type` option to the [`'shared-array-buffer'`](qwebr-communication-channels.qmd#sec-shared-array-buffer), which can significantly speed up its execution. This environment requires the proper configuration of HTTP headers for [Cross-Origin Embedder Policy (COEP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) and [Cross-Origin Opener Policy (COOP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy). By setting these headers correctly, you can already achieve notable speed improvements when working with webR.
35 |
36 | However, for further enhancements and speed optimizations beyond what the COEP and COOP headers provide, we recommend keeping an eye on the [main webR project's documentation](https://docs.r-wasm.org/webr/latest/). The core webR project continuously works on improving performance and scalability, so any future advancements in handling complex content faster will likely originate from their developments.
37 |
38 | # webR Limitations
39 |
40 | > Q. I noticed that built in docs with ? don't work in webR. Are there any other known issues? How long to feature parity?
41 |
42 | Regarding feature parity with the main `webR` project, it's important to understand that `quarto-webr` inherits the same limitations and capabilities as the core `webR` technology. Efforts to address these limitations and bring feature parity will depend on the ongoing development of `webR` itself and the evolution of WebAssembly and web browser capabilities. While there may be progress in mitigating some of these limitations over time, achieving complete feature parity may be a complex and ongoing process. In the case of help documentation, we added support in `quarto-webr` v0.3.7.
43 |
44 | The known limitations at this time are:
45 |
46 | 1. **Package Installation**: Installing packages from source within `webR` is not currently supported. This limitation is unlikely to change in the near future as it would require a complete C and Fortran compiler toolchain to run within the browser. As a result, the only supported way to install R packages in `webR` is by providing pre-compiled WebAssembly binaries.
47 |
48 | 2. **Graphics Device**: The `webr::canvas()` graphics device relies on OffscreenCanvas support in the web browser or JavaScript engine running `webR`. This means that a modern and up-to-date browser is required for plotting with this device. Older browsers without OffscreenCanvas support can still create plots using the Cairo-based graphics devices, such as `png()`.
49 |
50 | 3. **Communication Channels**: `webR` relies on communication channels for interaction. Without cross-origin isolation, it falls back to the ServiceWorker communication channel, which may result in reduced performance or require additional setup.
51 |
52 | 4. **Interruption of Running Code**: Interruption of running R code and the use of nested R REPLs (such as `readline()`, `menu()`, `browser()`, etc.) are unsupported when using the PostMessage communication channel.
53 |
54 | 5. **System Command**: The `system()` command is not implemented in webR, which means that executing system-level commands from within R code or packages is not possible.
55 |
56 | # State of Accessibility
57 |
58 | > Q. You mentioned there has been some work on accessibility. I'm curious what the current state of accessibility is? What are the known issues?
59 |
60 | Accessibility is an important aspect of webR, and we are committed to ensuring that the tool is usable by individuals with disabilities. To address accessibility concerns, we have engaged the expertise of [JooYoung Seo](https://github.com/jooyoungseo), an Assistant Professor in the School of Information Sciences (iSchool) at the University of Illinois Urbana-Champaign. JooYoung specializes in accessibility within Data Science and has been instrumental in conducting periodic accessibility reviews of webR.
61 |
62 | One of the primary areas of focus has been making sure that screen readers can easily identify and interact with code cells on the page. This ensures that individuals with visual impairments can effectively use webR. While we've made significant strides in improving accessibility, we continue to work on addressing any known issues and enhancing the overall accessibility of the tool. We are committed to providing an inclusive and user-friendly experience for all users, and JooYoung's expertise has been invaluable in this regard.
63 |
64 | # Package Usage
65 |
66 | > Q. Does the use of R packages cause any issues for you when teaching content with webR and Quarto?
67 |
68 | When teaching content with `webR` and Quarto, the use of R packages is certainly supported. However, it's important to be aware of a few considerations that can help ensure a smooth teaching experience.
69 |
70 | In a typical R environment, packages are installed once and are available for subsequent sessions using `library()` or `require()`. In `webR`, packages are installed on each session. This means that each `webR` session starts with a clean slate, and packages need to be installed again for that specific session.
71 |
72 | To optimize this process and avoid unnecessary downloads, it's recommended to use the `webr::install()` function instead of the standard `install.packages()` function. `webr::install()` checks if a package is already installed and does not re-download it if it's already available. This can significantly speed up the package installation process when working with `webR` and Quarto.
73 |
74 | One way to simplify the teaching process and prevent students from working while packages are being installed is to use the built-in [`packages` option](qwebr-using-r-packages.qmd#install-r-packages-on-document-open) in the document's header. This option hides the installation process from students and ensures that the required packages are pre-installed when they access the document.
75 |
76 | Finally, it's worth noting that the R packages available to `webR` may not always be the latest versions that you can get from CRAN (the Comprehensive R Archive Network). Therefore, it's a good practice to check the package versions and ensure compatibility with your teaching materials.
77 |
78 |
79 | # Debugging
80 |
81 | > Q. How are error messages, etc. communicated in webr's interface? Would it be easy for a student to debug without the tools that are available in the RStudio?
82 |
83 | Error messages, warnings, and other diagnostic information are presented in the output of a `quarto-webr` interface, just like in a standard R environment. These messages appear directly below the code cell that generated them. While `quarto-webr` provides a user-friendly interface for working with R in a web browser, it does not offer advanced debugging tools like `debug()`, `debugonce()`, `debuggingState()`, or `setBreakpoint()`. Therefore, debugging in `quarto-webr` is primarily reliant on interpreting the error messages and warnings displayed in the output. For students familiar with RStudio's debugging tools, transitioning to `quarto-webr` may require an adjustment to debugging practices. However, the clear presentation of error messages in the output makes it relatively straightforward for students to identify and address issues in their code.
84 |
85 |
86 | # Styling
87 |
88 | > Q. Is it possible to style the UI elements the quarto-webr extension add to your document? Do they get affected by styling/theme changes so things look coherent?
89 |
90 | Certainly! You have the flexibility to style the UI elements added by the `quarto-webr` extension to your document. For more details, please see [Theming Elements](qwebr-theming.qmd).
91 |
--------------------------------------------------------------------------------
/docs/qwebr-first-steps.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Making your first webR-powered Quarto document"
3 | author: "James Joseph Balamuta"
4 | date: "03-20-2023"
5 | date-modified: last-modified
6 | format:
7 | html:
8 | toc: true
9 | filters:
10 | - webr
11 | aliases:
12 | - webr-first-steps.html
13 | ---
14 |
15 | To get started, we highly recommend watching our walkthrough video. This video provides an in-depth breakdown of how to use a Quarto extension like `quarto-webr` within a Quarto document. Following that, delve into the subsequent sections that highlight crucial workflow changes for incorporating webR functionality into your Quarto HTML documents. We strongly encourage you to bookmark this page, as it serves as an invaluable reference for users of all expertise levels.
16 |
17 | ## Workflow Video
18 |
19 | {{< video https://youtu.be/DoRR2S5lLvk
20 | title="Creating your first webR-powered Quarto Document inside of RStudio"
21 | start="5"
22 | >}}
23 |
24 | ## Installation
25 |
26 | To use this extension in a Quarto project, install it from within the project's working directory by typing into **Terminal**:
27 |
28 | ```bash
29 | quarto add coatless/quarto-webr
30 | ```
31 |
32 | 
33 |
34 | :::callout-note
35 | Quarto extensions are project-specific installations and are not stored in a global library, unlike R packages. This means that for every new Quarto project or directory where you create a Quarto Document, you'll need to install the extension again.
36 | :::
37 |
38 | ## Usage
39 |
40 | Once the extension is successfully installed, you can begin utilizing it in your Quarto documents located within the same working directory as the `_extensions` folder. To activate the `webR` functionality in those documents, follow these steps:
41 |
42 | 1. **Add `webr` Filter**: In the header of your Quarto document, add the `webr` filter to the list of filters:
43 |
44 | ```yaml
45 | filters:
46 | - webr
47 | ```
48 |
49 | 2. **Use `{webr-r}` Code Blocks**: Write your R code within code blocks marked with `{webr-r}`. Here's an example:
50 |
51 | ````markdown
52 | ---
53 | title: webR in Quarto HTML Documents
54 | format: html
55 | engine: knitr
56 | filters:
57 | - webr
58 | ---
59 |
60 | This is a webr-enabled code cell in a Quarto HTML document.
61 |
62 | ```{webr-r}
63 | fit = lm(mpg ~ am, data = mtcars)
64 | summary(fit)
65 | ```
66 | ````
67 |
68 | 3. **Render Your Document**: You can now render your Quarto document by clicking on {width="25" height="20"} **Render** (or use the keyboard shortcut ⇧⌘K on macOS or Ctrl+Shift+K on Windows/Linux). The document will execute under `engine: knitr` by default, but you can specify a different engine if needed.
69 |
70 | :::callout-note
71 | If an engine is not specified, Quarto will attempt to use the `jupyter` compute engine by default. This may cause an error if `jupyter` is not installed on your computer.
72 | :::
73 |
74 | # Fin
75 |
76 | In summary, this guide has provided an overview of how to incorporate the community `quarto-webr` extension into your Quarto HTML documents using RStudio. We began with a walkthrough video that offered an in-depth understanding of how this Quarto extension operates within the Quarto framework. Subsequently, we explored key workflow changes necessary for incorporating webR into your Quarto HTML documents, from installation to document rendering.
77 |
78 | For your next steps consider looking at different use cases for [interactive options](qwebr-code-cell-demos.qmd).
79 |
80 | If you're eager to delve even deeper, explore topics like [setting document-level customizations inside the document header](qwebr-meta-options.qmd), [using R packages inside webR](qwebr-using-r-packages.qmd), or [hiding and executing code](qwebr-internal-cell.qmd). These resources will further empower you to make the most of `quarto-webr` and `webR` to elevate your Quarto documents to new heights.
--------------------------------------------------------------------------------
/docs/qwebr-loading-data.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Accessing and Using Data"
3 | subtitle: "Working with webR's Virtual File System and Data"
4 | author: "James Joseph Balamuta"
5 | date: "01-14-2024"
6 | date-modified: last-modified
7 | format:
8 | html:
9 | toc: true
10 | engine: knitr
11 | filters:
12 | - webr
13 | ---
14 |
15 | # Overview
16 |
17 | When working with webR in a web environment, there are some modifications and considerations required for using data. This documentation entry guides you through a few changes related to accessing data for the community Quarto extension.
18 |
19 | ## Background: Virtual File System
20 |
21 | Given the browser-based nature of webR, accessing local files is restricted. To overcome this limitation, webR establishes a [**virtual** file system](https://docs.r-wasm.org/webr/latest/communication.html#emscripten-virtual-filesystem) inside of your browser that is separate from your local file system. Consequently, webR does **not** have awareness of local file system and its paths. Thus, to use data we need to download it into the virtual file system either through: an R package, a URL using HTTPS, or a Web API.
22 |
23 | By default, the webR virtual file system's home directory and initial working directory is `/home/web_user`. This can be changed using a built-in extension [document-level option `home-dir`](https://quarto-webr.thecoatlessprofessor.com/qwebr-meta-options.html#home-dir).
24 |
25 | ### Aside
26 |
27 | While there are methods for mounting pre-built images using the webR's [Mounting Filesystem](https://docs.r-wasm.org/webr/latest/mounting.html#the-virtual-filesystem) mechanic, the community `quarto-webr` Extension does not support this option at the moment.
28 |
29 | ## Accessing Data through R Data Packages
30 |
31 | The quickest approach for accessing data is to store it inside of an [R data package](https://thecoatlessprofessor.com/programming/r/creating-an-r-data-package/). This kind of R package consists solely of data in an R ready format with the added benefit of help documentation. If the data package is available on CRAN, there's a good chance a version exists for webR on the [main webR package repository (warning not a mobile data friendly link)](https://repo.r-wasm.org/) and, thus, can be accessed using `install.packages("pkg")` or added to the documents `packages` key.
32 |
33 | If the R package is not available on CRAN, then it will need to be compiled for webR, deployed, and accessed through GitHub Pages or [r-universe.dev](https://ropensci.org/blog/2023/11/17/runiverse-wasm/) by following the advice on [creating a custom webR/R WASM package repository](qwebr-using-r-packages.qmd#custom-repositories).
34 |
35 | ## Retrieving Data from the Web
36 |
37 | ::: {.callout-important}
38 | Before proceeding, take note of the following considerations when working with remote data:
39 |
40 | 1. **Security Protocol:** webR necessitates data retrieval via the [HyperText Transfer Protocol Secure (HTTPS)](https://developer.mozilla.org/en-US/docs/Glossary/HTTPS) protocol to ensure secure connections and the [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) being enabled on the server where the data is being served.
41 | 2. **Package Compatibility:** In the absence of websockets within webR, packages reliant on `{curl}` methods may require adaptation or alternative solutions.
42 | :::
43 |
44 | ### Hosting Data
45 |
46 | #### Standalone Repository
47 |
48 | We suggest creating a GitHub repository that uses GitHub Pages to host the data. By default, GitHub Pages serves data files using the CORS protocol and can quickly be setup to enforce HTTPS URLs [by checking a box](https://docs.github.com/en/pages/getting-started-with-github-pages/securing-your-github-pages-site-with-https#enforcing-https-for-your-github-pages-site).
49 |
50 | You can see an example raw data repository here:
51 |
52 |
53 |
54 | The corresponding site deployment of the `main` branch can be seen here:
55 |
56 |
57 |
58 | #### Alongside the document
59 |
60 | There may be times when it is not feasible to create a standalone repository to host the data. In cases like this, you may wish to host the data alongside of the document through Quarto's publishing system. In this case, please add the `resources` key to the top of the [HTML document](https://quarto.org/docs/reference/formats/html.html#includes) or inside the [project's `_quarto.yml`](https://quarto.org/docs/reference/projects/websites.html#project).
61 |
62 | For `my-document.qmd`, this would be:
63 |
64 | ```yaml
65 | ---
66 | title: "quarto-webr document with data"
67 | format:
68 | html:
69 | resources:
70 | - my-data.csv # Include just the CSV
71 | - my-data-directory/* # Include all files
72 | engine: knitr
73 | filters:
74 | - webr
75 | ---
76 | ```
77 |
78 | For `_quarto.yml`, this would be:
79 |
80 | ```yaml
81 | ---
82 | project:
83 | type: website
84 | resources:
85 | - my-data.csv # Include just the CSV
86 | - my-data-directory/* # Include all files
87 | ---
88 | ```
89 |
90 | Subsequently, reference the data using the URL to where the document is located. For example, if the document is at:
91 |
92 | ```default
93 | https://example.com/folder/my-document.html
94 | ```
95 |
96 | Then, the data should be accessed using:
97 |
98 | ```default
99 | https://example.com/folder/my-data.csv
100 | ```
101 |
102 | :::{.callout-note}
103 | You may need to publish the document before using the URL. Also, be mindful of data version mismatches, as the data will be fetched from the HTTPS URL instead of being available locally.
104 | :::
105 |
106 | ### Obtain Data
107 |
108 | We can retrieve data at a URL with HTTPS through using the `download.file()` function and, subsequently, reading it into R using a relative path. The later can be done using either Base R or Tidyverse functions.
109 |
110 | For example, if we wanted to work with [flights.csv](https://coatless.github.io/raw-data/flights.csv) from the [`nycflights13`](https://cran.r-project.org/package=nycflights13) _R_ package ([Details](https://nycflights13.tidyverse.org/reference/flights.html)), we would specify:
111 |
112 | ```r
113 | url <- "https://coatless.github.io/raw-data/flights.csv"
114 | download.file(url, "flights.csv")
115 | ```
116 |
117 | This action saves the file into webR's virtual file system to be read into R's analysis environment. Replace `"https://coatless.github.io/raw-data/flights.csv"` and `"flights.csv"` with the actual URL of your desired data source and desired local file name.
118 |
119 | ### Base R
120 |
121 | For optimized performance, leverage base R's `read.*()` functions, as they do not necessitate additional package dependencies.
122 |
123 | ```r
124 | data <- read.csv("flights.csv")
125 | ```
126 |
127 | ### Tidyverse
128 |
129 | Alternatively, you can use `tidyverse`-based functions like `readr::read_*()`.
130 |
131 | :::{.callout-note}
132 | Note that employing `tidyverse` or `readr` functions entails additional package downloads at the session's outset or immediately preceeding the function usage.
133 | :::
134 |
135 | ```r
136 | install.packages("readr")
137 | data <- readr::read_csv("data.csv")
138 | ```
139 |
140 | ### Try it!
141 |
142 | We've setup the above example inside of an interactive cell for your to explore below.
143 |
144 | :::{.panel-tabset}
145 |
146 | ### {quarto-webr}
147 |
148 | ```{webr-r}
149 | #| autorun: true
150 | # See where we are in the file system:
151 | cat("We're currently at:\n")
152 | getwd()
153 |
154 | # View a list of files for the working directory.
155 | cat("We have the following files present:\n")
156 | list.files()
157 |
158 | # Specify the data URL using HTTPS
159 | url <- "https://coatless.github.io/raw-data/flights.csv"
160 |
161 | # Download the data file from the HTTPS URL and save it as
162 | # flights.csv
163 | cat("Download the data ...\n")
164 | download.file(url, "flights.csv")
165 |
166 | # Check for the data.
167 | cat("After downloading the data, we now have:\n")
168 | list.files()
169 |
170 | # Read the flights data into R
171 | flights_from_csv <- read.csv("flights.csv")
172 |
173 | # See the first few rows of the flights_from_csv data frame.
174 | cat("Let's view the first 6 observations of data:\n")
175 | head(flights_from_csv)
176 | ```
177 |
178 | ### Code cell
179 |
180 | ```{{webr-r}}
181 | #| autorun: true
182 | # See where we are in the file system:
183 | cat("We're currently at:\n")
184 | getwd()
185 |
186 | # View a list of files for the working directory.
187 | cat("We have the following files present:\n")
188 | list.files()
189 |
190 | # Specify the data URL using HTTPS
191 | url <- "https://coatless.github.io/raw-data/flights.csv"
192 |
193 | # Download the data file from the HTTPS URL and save it as
194 | # flights.csv
195 | cat("Download the data ...\n")
196 | download.file(url, "flights.csv")
197 |
198 | # Check for the data.
199 | cat("After downloading the data, we now have:\n")
200 | list.files()
201 |
202 | # Read the flights data into R
203 | flights_from_csv <- read.csv("flights.csv")
204 |
205 | # See the first few rows of the flights_from_csv data frame.
206 | cat("Let's view the first 6 observations of data:\n")
207 | head(flights_from_csv)
208 | ```
209 |
210 | :::
211 |
--------------------------------------------------------------------------------
/docs/qwebr-meta-options.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Customization Options"
3 | subtitle: "Fine-Tuning `quarto-webr` with Powerful Configuration Options"
4 | author: "James Joseph Balamuta"
5 | date: "09-14-2023"
6 | date-modified: last-modified
7 | format:
8 | html:
9 | toc: true
10 | engine: knitr
11 | aliases:
12 | - webr-meta-options.html
13 | ---
14 |
15 | The `quarto-webr` extension empowers you to tailor your webR environment to meet your unique requirements. By configuring various options in your document's YAML header or `_quarto.yml` file, you can structure the webR experience on a per-page or per-project basis. Below, we explore these customization options and how to implement them.
16 |
17 | # Customization Options
18 |
19 | Enhance your webR experience by customizing its behavior through the `webr` key. This key should be added before listing the `filter` statement.
20 |
21 | ## Document YAML
22 |
23 | To fine-tune webR to the specific needs of a document, place inside your document's YAML header the `webr` key. Specifying options this way allows webR to be setup with unique options confined to only that document.
24 |
25 | ```yaml
26 | ---
27 | title: webR in Quarto HTML Documents
28 | format: html
29 | engine: knitr
30 | webr:
31 | show-startup-message: false # Disable displaying status of webR initialization
32 | packages: ['ggplot2', 'dplyr'] # Install R packages on document open
33 | filters:
34 | - webr
35 | ---
36 | ```
37 |
38 | ## Global Configuration
39 |
40 | If you have multiple pages that use webR, we suggest setting global options inside of the `_quarto.yml` file. This option is appropriate for Websites, Blogs, or Books. For instance, if you have a book project, the `_quarto.yml` should look like:
41 |
42 | ```yaml
43 | project:
44 | type: book
45 |
46 | book:
47 | title: "Sample quarto-webr Book Project"
48 | # ... more options
49 |
50 | # Set default options for every bookpage that may or may not include webR.
51 | webr:
52 | show-startup-message: false # Disable displaying status of webR initialization
53 | packages: ['ggplot2', 'dplyr'] # Install R packages on document open
54 |
55 | # Attach webR extension for the project
56 | filters:
57 | - webr
58 | ```
59 |
60 | :::{.callout-note}
61 | If a webR code cell is not present on a website, blog, or book page, then the `quarto-webr` extension will not setup webR on the page.
62 | :::
63 |
64 | You can see full examples of setting a global option under the [Deployment Templates](qwebr-deployment-templates.qmd) page.
65 |
66 | ## webR options
67 |
68 | By specifying various `WebROptions` options in the document YAML, you can create a personalized webR experience
69 |
70 | ### `home-dir`
71 |
72 | - **Description**: Set the WebAssembly user's home directory and initial working directory.
73 | - **Default Value**: `'/home/web_user'`
74 | - **Documentation**: [homeDir](https://docs.r-wasm.org/webr/latest/api/js/interfaces/WebR.WebROptions.html#homedir)
75 |
76 | ### `version`
77 |
78 | - **Description**: Define the version that should be used for the R WebAssembly binaries.
79 | - **Default Value**: `0.3.3` (version keyed by the extension)
80 |
81 | ### `base-url`
82 |
83 | - **Description**: Define the base URL for downloading R WebAssembly binaries.
84 | - **Default Value**: `'https://webr.r-wasm.org/v[version]/'`
85 | - **Documentation**: [baseUrl](https://docs.r-wasm.org/webr/latest/api/js/interfaces/WebR.WebROptions.html#baseurl)
86 |
87 | ### `channel-type`
88 |
89 | - **Description**: Specify the communication channel type to interact with webR.
90 | - **Default Value**: `"automatic"` (0)
91 | - **Possible Values**: `"automatic"` (0), `"shared-array-buffer"` (1), `"service-worker"` (2), `"post-message"` (3).
92 | - **Documentation**: [channelType](https://docs.r-wasm.org/webr/latest/api/js/interfaces/WebR.WebROptions.html#channeltype)
93 |
94 | :::callout-note
95 | We recommend using the `"post-message"` channel when [GitHub Pages](https://pages.github.com/) or [Quarto Pub](https://quartopub.com/) serve the webR-enabled document. Note that this option prevents the interruption of running R code and the use of nested R REPLs (`readline()`, `menu()`, `browser()`, etc.).
96 | For more details, please see [Communication Channels](qwebr-communication-channels.qmd#sec-post-message)
97 | :::
98 |
99 | ### `service-worker-url`
100 |
101 | - **Description**: Set the base URL for loading JavaScript worker scripts when using the ServiceWorker communication channel mode.
102 | - **Default Value**: `''`
103 | - **Documentation**: [serviceWorkerUrl](https://docs.r-wasm.org/webr/latest/api/js/interfaces/WebR.WebROptions.html#serviceworkerurl)
104 |
105 |
106 | ## Native Extension Options
107 |
108 | The extension also provides native options that affect its behavior:
109 |
110 | ### `show-startup-message`
111 |
112 | - **Description**: Controls the display of the WebR initialization state in the document header.
113 | - **Default Value**: `true`
114 | - **Demo Document**: [Setting Options in Document Header](demos/qwebr-setting-options-in-document-yaml.qmd)
115 |
116 | ### `show-header-message`
117 |
118 | - **Description**: Determines whether COOP and COEP headers are in use for faster page loads.
119 | - **Default Value**: `false`
120 | - **Demo Document**: [Setting Options in Document Header](demos/qwebr-setting-options-in-document-yaml.qmd)
121 |
122 | ### `cell-options`
123 |
124 | - **Description**: Modifies default cell options for `{webr-r}` cells.
125 | - **Default Value**: Please see [Code Cell Options](qwebr-cell-options.qmd) for individual cell option defaults.
126 | - **Demo Document**: [Set Global Cell Options](demos/qwebr-global-cell-defaults.qmd)
127 | - **Example:**
128 |
129 | ```yaml
130 | webr:
131 | cell-options:
132 | autorun: true
133 | fig-height: 400
134 | fig-width: 300
135 | ```
136 |
137 | This modifies the default cell options for `autorun`, `fig-width`, and `fig-height` for all cells in the document.
138 |
139 | ### `repos`
140 |
141 | - **Description**: Specify the repository locations to search for R packages when trying to install them in array form. Regardless of values specified, we will always conclude by checking to see if the package is present in the main webR repository: .
142 | - **Default Value**: `['https://repo.r-wasm.org/']`
143 | - **Demo Document**: [Custom R WASM Package Repository](demos/qwebr-custom-repository.qmd)
144 | - **Example**: `['https://username.r-universe.dev', 'https://username.github.io/reponame']` will cause webR to first look for the package on `r-universe.dev`, then move to looking at the package on GitHub Pages, before finally landing on the official repository.
145 |
146 | ### `packages`
147 |
148 | - **Description**: Specifies R packages to install automatically when the document opens.
149 | - **Default Value**: `[]`
150 | - **Demo Document**: [Setting Options in Document Header](demos/qwebr-setting-options-in-document-yaml.qmd)
151 | - **Example:** `['ggplot2', 'dplyr']` will cause `ggplot2` and `dplyr` to be installed.
152 |
153 | ### `autoload-packages`
154 |
155 | - **Description**: The `autoload-packages` option allows you to control whether R packages specified in the `packages` document option will be automatically loaded using `library()` calls when the document opens. By default, this option is set to `true`, meaning that packages listed in the `packages` option will be automatically loaded. If you set it to `false`, you will need to include a code cell with `library(package)` function calls for each package in `packages`.
156 | - **Default Value**: `true`
157 | - **Demo Document**: [Setting Options in Document Header](demos/qwebr-setting-options-in-document-yaml.qmd)
158 |
159 |
--------------------------------------------------------------------------------
/docs/qwebr-theming.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Theming Elements"
3 | subtitle: "Customizing the Look and Feel of `quarto-webr` Elements"
4 | date: "11-01-2023"
5 | date-modified: last-modified
6 | author: James Balamuta
7 | engine: markdown
8 | format:
9 | html:
10 | toc: true
11 | filters:
12 | - webr
13 | ---
14 |
15 | :::{.callout-note}
16 | This section of the documentation is tailored to those with a deeper understanding of web design. If you're new to these concepts, don't worry; you can still create fantastic documents using the `quarto-webr` extension. This part is for those who want to take their styling to the next level and have knowledge of HTML and CSS.
17 | :::
18 |
19 | On this page, we delve into the world of web design to enhance the visual aesthetics and styling of web-based documents created with the Quarto-WebR extension. While prior knowledge of these topics is not mandatory for using the extension, a good understanding can empower you to create documents that effectively convey valuable insights and captivate your audience with a visually appealing design tailored to your preferences. Whether you want to seamlessly integrate your document with your personal brand or align it with your organization's style guidelines, this page serves as your expert guide, leading you through the process of crafting a visually captivating and cohesive user experience. The focus here is on explaining the HTML structure and predefined CSS classes that will help you achieve the visual results you desire.
20 |
21 | ## CSS Class and ID Identifiers
22 |
23 | To effectively style web-based documents created with the extension, you'll need to understand the unique `id` and `class` attributes associated with different content areas. There are two key areas to every Quarto document that uses the `quarto-webr` extension: header and code cells. The header is where status and debug information can be found whereas the code cell portion is where R code is actively run using webR.
24 |
25 | Let's turn our attention to the document's header. By default, the webR initialization state is displayed in the header. This can be turned off by setting the [`show-startup-message: false` meta option.](qwebr-meta-options.qmd).
26 |
27 | - **Status Area**: This represents the area we dynamic add to the document using JavaScript and stores the **Status Title** and **Status Message**
28 | - `id`: `#qwebr-status-message-area`
29 | - **Status Title**: This element contains the header of the status text.
30 | - `id`: `#qwebr-status-message-title`
31 | - **Status Message**: This element is updated with the document status updates.
32 | - `id`: `#qwebr-status-message-body`
33 |
34 | With this in mind, we next focus on improving how content is being displayed through **code cells**. There are two primary context types where code content is displayed to users:
35 |
36 | - **Interactive Area**: This area encompasses the **Code Editor**, **Code Output**, and the **Graph Output Area** under the `interactive` context.
37 | - `id`: `#qwebr-interactive-area-{{ID}}`
38 | - `class`: `.qwebr-interactive-area`
39 |
40 | - **Non-Interactive Area**: This includes the **Code Output** and the **Graph Output Area** under the `output` context.
41 | - `id`: `#qwebr-noninteractive-area-{{ID}}`
42 | - `class`: `.qwebr-noninteractive-area`
43 |
44 | Within the interactive section, you'll find elements that are displayed when users request results:
45 |
46 | - **Run Button**: This button triggers the execution of your R code.
47 | - `id`: `#qwebr-button-run-{{ID}}`
48 | - `class`: `.qwebr-button-run`
49 |
50 | - **Console Area**: This area contains the **Code Editor** and **Code Output**.
51 | - `id`: `#qwebr-console-area-{{ID}}`
52 | - `class`: `.qwebr-console-area`
53 |
54 | - **Code Editor**: You use this area to input and edit your R code.
55 | - `id`: `#qwebr-editor-{{ID}}`
56 | - `class`: `.qwebr-editor`
57 |
58 | Across both contexts, you'll find shared output element classes and names:
59 |
60 | - **Code Output Area**: This is where the results and output of your R code are displayed.
61 | - `id`: `#qwebr-output-code-area-{{ID}}`
62 | - `class`: `.qwebr-output-code-area`
63 |
64 | - **Code Output Standard Output**: Results from standard output (`STDOUT`) are stored here.
65 | - `id`: `#qwebr-output-code-stdout-{{ID}}`
66 | - `class`: `.qwebr-output-code-stdout`
67 |
68 | - **Code Output Standard Error**: Each line of results from standard error (`STDERR`) when running your code is stored here.
69 | - `id`: `#qwebr-output-code-stderr-{{ID}}`
70 | - `class`: `.qwebr-output-code-stderr`
71 |
72 | - **Graph Output Area**: Any graphical output of your R code is displayed in this area.
73 | - `id`: `#qwebr-output-graph-area-{{ID}}`
74 | - `class`: `.qwebr-output-graph-area`
75 |
76 | - **Browse Output Area**: Any HTML widgets generated by your R code is displayed in this area.
77 | - `id`: `#qwebr-output-code-browse-{{ID}}`
78 | - `class`: `.qwebr-output-code-browse`
79 |
80 |
81 | The `{{ID}}` in these identifiers represents the instance of the element on the page, whether it's the first, second, or nth occurrence. You can customize their appearance by targeting the specific `id` or `class` attributes in your document's CSS, or you can include a separate CSS file to align with your design preferences.
82 |
83 | ## CSS & HTML Structure
84 |
85 | ### Interactive Area Structure
86 |
87 | ```{.html}
88 |
113 | ```
114 |
115 | ## Custom Embedded Styles
116 |
117 | For instance, you can insert new CSS elements by using the following method:
118 |
119 | ````markdown
120 | ```{=html}
121 |
125 | ```
126 | ````
127 |
128 | ## External Theme Support
129 |
130 | Furthermore, if you are using a Quarto theme, you can make use of [theme-specific styling options](https://quarto.org/docs/output-formats/html-themes.html#basic-options) to ensure that these UI elements align with the overall theme of your document.
131 |
132 | ```markdown
133 | ---
134 | title: My post
135 | format:
136 | html:
137 | theme:
138 | - cosmo
139 | - custom.scss
140 | ---
141 | ```
142 |
143 | ## Light and Dark Mode
144 |
145 | The Monaco editor used by `{quarto-webr}` to power interactive code cells respects [Quarto's light and dark theme modes](https://quarto.org/docs/output-formats/html-themes.html#dark-mode). To apply light and dark themes on a Quarto website, specify the following settings in the `_quarto.yml` configuration file:
146 |
147 | ```yaml
148 | theme:
149 | light: cosmo
150 | dark: darkly
151 | ```
152 |
153 | Once set, a clickable toggle will appear on the page that can switch between these modes. This toggle modifies CSS classes on the `body` HTML element, adding `.quarto-light` for light mode and `.quarto-dark` for dark mode.
154 |
155 | :::{.callout-note}
156 | The Monaco editor's theme automatically adjusts based on the document's theme. It uses a light theme (`vs`) in light mode and a dark theme (`vs-dark`) in dark mode.
157 | :::
158 |
159 | ### RevealJS
160 |
161 | For RevealJS, please note you may only specify [a single RevealJS theme](https://quarto.org/docs/presentations/revealjs/themes.html#using-themes) at a time. We recommend specifying either `default` (for light mode) or `dark` (for dark mode).
162 |
163 | ```yaml
164 | format:
165 | revealjs:
166 | theme: default
167 | ```
168 |
--------------------------------------------------------------------------------
/docs/qwebr-troubleshooting.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Troubleshooting"
3 | subtitle: "Common Problems and Fixes in quarto-webR"
4 | date: "03-20-2023"
5 | date-modified: last-modified
6 | engine: knitr
7 | aliases:
8 | - webr-troubleshooting.html
9 | ---
10 |
11 | As this is an exciting new frontier, we're learning as we go. Or as my friend [Lawrence](https://cs.illinois.edu/about/people/faculty/angrave) says, ["I like to build airplanes in the air-"](https://www.youtube.com/watch?v=L2zqTYgcpfg). In the spirit of learning, let's address some common issues you may come across...
12 |
13 | # Unable to Render the Quarto File
14 |
15 | **Problem**: When I add the `webr` value to the `filter` section, my Quarto document fails to render and displays a lengthy error message.
16 |
17 | **Solution**: Quarto extensions are project-specific, which means you must install the extension for each new project you create. To resolve this issue, ensure that your project directory structure includes an `_extensions` directory with the appropriate extension files, as shown below:
18 |
19 | ```sh
20 | .
21 | ├── _extensions
22 | │ └── coatless
23 | │ └── webr
24 | │ ├── _extension.yml
25 | │ ├── ...
26 | │ └── webr.lua
27 | └── test-document.qmd
28 | ```
29 |
30 | If your directory is missing the `_extensions/` folder, please install the `webr` extension by following the instructions in [Install the quarto-webr extension](qwebr-first-steps.qmd) video.
31 |
32 | Starting from Quarto v1.4, you will receive an improved error message that emphasizes the extension's absence from your current working directory.
33 |
34 | ```{sh}
35 | #| eval: false
36 | #| code-fold: true
37 | #| code-summary: "Missing extension error for Quarto v1.4 and later"
38 |
39 | FATAL (/Applications/quarto/share/filters/main.lua:129) An error occurred:
40 | Could not run /Users/jjb/github/demo-webr/webr as a JSON filter.
41 | Please make sure the file exists and is executable.
42 |
43 | Did you intend 'webr' as a Lua filter in an extension?
44 | If so, make sure you've spelled the name of the extension correctly.
45 |
46 | The original Pandoc error follows below.
47 | Error running filter /Users/jjb/github/demo-webr/webr:
48 | Could not find executable /Users/jjb/github/demo-webr/webr
49 | ```
50 |
51 | In versions prior to Quarto v1.4, including v1.3 and earlier, the error message may differ, but it typically signals that the extension is either missing or not executable.
52 |
53 | ```{sh}
54 | #| eval: false
55 | #| code-fold: true
56 | #| code-summary: "Missing extension error for Quarto v1.3 and earlier"
57 |
58 | Error running filter /Applications/quarto/share/filters/main.lua:
59 | Error running filter /Users/jjb/github/demo-webr/webr:
60 | Could not find executable /Users/jjb/github/demo-webr/webr
61 | stack traceback:
62 | /Applications/quarto/share/filters/main.lua:4030: in function
63 | [C]: in ?
64 | [C]: in method 'walk'
65 | /Applications/quarto/share/filters/main.lua:171: in function 'run_emulated_filter'
66 | /Applications/quarto/share/filters/main.lua:449: in local 'callback'
67 | /Applications/quarto/share/filters/main.lua:454: in upvalue 'run_emulated_filter_chain'
68 | /Applications/quarto/share/filters/main.lua:495: in function
69 | stack traceback:
70 | /Applications/quarto/share/filters/main.lua:171: in function 'run_emulated_filter'
71 | /Applications/quarto/share/filters/main.lua:449: in local 'callback'
72 | /Applications/quarto/share/filters/main.lua:454: in upvalue 'run_emulated_filter_chain'
73 | /Applications/quarto/share/filters/main.lua:495: in function
74 | ```
75 |
76 |
77 | # Directly Accessing Rendered HTML
78 |
79 | **Problem**: When I directly open the rendered HTML document in a web browser, webR components are not loaded due to security reasons.
80 |
81 | **Solution**: When you use `quarto preview` or `quarto render`, the rendered HTML document is served by mimicking a server running under `https://localhost/`. In this context, everything usually works fine if you follow the directory structure mentioned above.
82 |
83 | However, if you directly open the rendered HTML document (e.g., `demo-quarto-web.html`) in a web browser, you may encounter issues with WebR components not loading due to security restrictions. This behavior is explained further in this [StackOverflow answer](https://stackoverflow.com/questions/6811398/html5-web-workers-work-in-firefox-4-but-not-in-chrome-12-0-742-122/6823683#6823683).
84 |
85 | To address this problem and avoid the need for a local Quarto installation to open the rendered file directly, you have a few options:
86 |
87 | 1. **Use Chrome's `--allow-file-access-from-files` access**: You can modify your Chrome shortcut to include the [`--allow-file-access-from-files` flag](https://stackoverflow.com/questions/18586921/how-to-launch-html-using-chrome-at-allow-file-access-from-files-mode). This allows local files to access other local files, potentially resolving the issue.
88 |
89 | 2. **Use the WebServer for Chrome Extension**: Install the [WebServer for Chrome extension](https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en) to serve your HTML files. This extension sets up a local web server that doesn't have the same security restrictions as directly opening files.
90 |
91 | 3. **Use NPM to Obtain `local-web-server`**: Install the [`local-web-server` package from npm](https://github.com/lwsjs/local-web-server), which is a lightweight, no-configuration-required HTTP server. You can use it to serve your HTML files without encountering security restrictions.
92 |
93 | # Speed Up webR
94 |
95 | **Problem**: WebR documents are not performing as efficiently as expected.
96 |
97 | **Solution**: To optimize the performance of webR documents, it's essential to set appropriate HTTP headers for [COOP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) and [COEP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy). These headers help speed up the process and ensure a smoother user experience.
98 |
99 | Here are the recommended COOP and COEP headers to use:
100 |
101 | ```http
102 | Cross-Origin-Opener-Policy: same-origin
103 | Cross-Origin-Embedder-Policy: require-corp
104 | ```
105 |
106 | By configuring these headers, you enforce a same-origin policy for cross-origin windows and ensure that cross-origin iframes are required to have a COEP policy that allows cross-origin embedding. For more detailed instructions on setting up these headers, please refer to the [`"shared-array-buffer"`](qwebr-communication-channels.qmd#sec-shared-array-buffer) channel type documentation.
107 |
108 | # Engine Registration
109 |
110 | **Problem**: When using the `knitr` engine instead of the `jupyter` engine and the original tag `{webr}` instead of `{webr-r}`, a warning message may appear in the render processing output:
111 |
112 | ```r
113 | Warning message:
114 | In get_engine(options$engine) :
115 | Unknown language engine 'webr' (must be registered via knit_engines$set()).
116 | ```
117 |
118 | **Solution**: The warning message about the unknown language engine 'webr' is purely cosmetic and does not affect the functionality of the `webr` filter. It is merely an aesthetic issue and does not impact the execution of code cells.
119 |
120 | This warning occurs because the `knitr` engine is not initially aware of the `webr` engine. However, this lack of awareness does not cause any functional problems. The `webr` filter will operate as expected despite this warning.
121 |
122 | While the warning is not critical, it may be addressed in future updates for aesthetic reasons. Nevertheless, you can safely disregard this warning message as it does not interfere with the functionality of your webR documents.
123 |
124 | # Stuck at Loading webR...
125 |
126 | **Problem**: If you encounter the message `Loading webR...` above your code cell instead of `Run code`, it's likely due to missing worker files (`webr-worker.js` and `webr-serviceworker.js`) in the document's root or a relative directory.
127 |
128 | **Solution**: To resolve this issue, make sure that these worker files are located in the same directory as your Quarto document. Here's the recommended directory structure:
129 |
130 | ```sh
131 | .
132 | ├── demo-quarto-webr.qmd
133 | ├── webr-serviceworker.js
134 | └── webr-worker.js
135 | ```
136 |
137 | If you still encounter the error after confirming the file placement, check the output of the preview command in either the **Terminal** or RStudio's **Background Jobs** tab. The output might resemble the following:
138 |
139 | ```sh
140 | quarto preview --no-browser --no-watch-inputs
141 |
142 | Watching files for changes
143 | GET: /website/posts/index.html
144 | /website/posts/webr-serviceworker.js (404: Not Found)
145 | /website/posts/webr-worker.js (404: Not Found)
146 | ```
147 |
148 | This indicates that the `webr-serviceworker.js` and `webr-worker.js` files are missing during the rendering stage of your document. To fix this, add the [`resources` key](https://quarto.org/docs/reference/formats/html.html#includes) to your document header, explicitly specifying these two JavaScript files like so:
149 |
150 | ```markdown
151 | ---
152 | title: "My Post"
153 | resources:
154 | - webr-serviceworker.js
155 | - webr-worker.js
156 | filters:
157 | - webr
158 | ---
159 | ```
160 |
161 | :::{.callout-note}
162 | We've informed the Quarto team about this issue regarding [automatic inclusion of extension registered dependencies](https://github.com/quarto-dev/quarto-cli/issues/6828).
163 | :::
164 |
165 | If the problem persists, you can specify the location of the worker files using the [`service-worker-url` option](qwebr-meta-options.qmd) in the document's YAML header or set the [`channel-type` option to `"post-message"`](qwebr-communication-channels.qmd#sec-post-message). You can see an example of the later [here](qwebr-communication-channels.qmd#specifying-how-webr-communicates).
166 |
--------------------------------------------------------------------------------
/docs/qwebr-using-r-packages.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Using R Packages"
3 | subtitle: "Seamlessly integrate R packages into your interactive Quarto HTML documents"
4 | author: "James Joseph Balamuta"
5 | date: "09-14-2023"
6 | date-modified: last-modified
7 | format:
8 | html:
9 | toc: true
10 | engine: knitr
11 | filters:
12 | - webr
13 | aliases:
14 | - webr-using-r-packages.html
15 | ---
16 |
17 | Whether you need specialized statistical analysis, advanced visualization, or any other R-based functionality, you can harness the rich ecosystem of R packages directly within your documents. By default, the community `quarto-webr` extension avoids loading additional packages. However, you have two ways to incorporate packages into your document: one where packages are installed when the document opens, and the other where packages are installed interactively within specific code cells.
18 |
19 | # Available R Packages
20 |
21 | Before you use any R package with webR, it's essential to check if it's available. You can explore the available packages by navigating to the [webR binary R repository](https://repo.r-wasm.org/) (link is not mobile friendly) for package listings.
22 |
23 | ::: {.callout-note}
24 | webR reports the number of packages available in two ways:
25 |
26 | - **Built R packages**: This indicates the number of R packages with WebAssembly binaries that can be used within webR, although they may have a decreased number of features available.
27 |
28 | - **Available R packages**: This number represents feature-complete R packages that have all their dependencies compiled and are fully functional within webR.
29 |
30 | To achieve parity with base R, the **Available R packages** metric serves as an indicator of whether R scripts may require further modification to function properly within webR.
31 | :::
32 |
33 | Alternatively, you can run the following R code, either with webR or just R:
34 |
35 | ```{webr-r}
36 | # Determine the version of R being used
37 | major_minor_version <- paste(
38 | R.version$major,
39 | strsplit(R.version$minor, ".", fixed = TRUE)[[1L]][1L],
40 | sep = "."
41 | )
42 |
43 | # Obtain a list of packages
44 | webr_info <- as.data.frame(
45 | available.packages(
46 | contriburl = paste0(
47 | "https://repo.r-wasm.org/bin/emscripten/contrib/",
48 | major_minor_version
49 | )
50 | )
51 | )
52 |
53 | # Obtain the number of R packages built
54 | n_webr_pkgs <- nrow(webr_info)
55 |
56 | # Number of R packages available to webR
57 | cat("There are current", n_webr_pkgs,
58 | "available to use with webR!\n")
59 |
60 | # Only view the first 6, there's a lot available!
61 | head(webr_info[, c("Version", "License")])
62 | ```
63 |
64 |
65 |
66 | ## Custom Repositories
67 |
68 | If an R package is not available on the [main webR repository](https://repo.r-wasm.org) (link is not mobile friendly), fear not! You can compile your own R package to an R WASM Package binary and setup a custom repository to share it.
69 |
70 | The quickest way is to opt into using the **[r-universe.dev](https://ropensci.org/blog/2023/11/17/runiverse-wasm/) service**. This is a free service that allows you to host R packages and binaries not just for webR, but also macOS, Linux, and Windows variants of R.
71 |
72 |
73 | If you want tighter integration with your development repository, we have the following guides:
74 |
75 | - [Org-focused webR/WASM Package Repository without a `{pkgdown}` website](https://github.com/coatless-tutorials/webr-org-gh-action)
76 | - [Unified GitHub Action Deployment using artifacts of R WASM Package binaries and {pkgdown} website](https://github.com/coatless-tutorials/webr-unified-gh-workflow)
77 | - [Separate GitHub Action Deployment onto `gh-pages` branch of R WASM Package binaries and {pkgdown} website](https://github.com/coatless-tutorials/webr-github-action-wasm-binaries)
78 |
79 |
80 | Once done, please make sure to specify where the custom repository is by using the `repos` key under the `webr` option in the document header. For example, we can add two custom repositories -- one to a GitHub pages hosted repository and another to the [r-universe](https://r-universe.dev/search/), by using:
81 |
82 | ```yaml
83 | ---
84 | webr:
85 | repos:
86 | - https://username.github.io/reponame
87 | - https://username.r-universe.dev
88 | ---
89 | ```
90 |
91 | :::{.callout-note}
92 | The community `{quarto-webr}` extension is setup to always check whether an R package is available at the main repository even without it being specified in the `repos` key.
93 | :::
94 |
95 | # Install R Packages on Document Open
96 |
97 | To automatically install packages when the document opens, add the `packages` key under `webr` in the YAML header, listing the packages in an array:
98 |
99 | ```yaml
100 | ---
101 | webr:
102 | packages: ['ggplot2', 'dplyr']
103 | ---
104 | ```
105 |
106 | By using this approach, you ensure that necessary packages are available right from the start when readers access your document. Moreover, the webR code cells will not become active until the packages are installed and loaded. This can be especially helpful when working with packages in multiple cells.
107 |
108 | If you do not want the packages to be loaded by default, add the `autoload-packages: false` under `webr` in the YAML header. This will disable the calls to load each R package in the `packages` key, e.g. `library(package)`.
109 |
110 | ```yaml
111 | ---
112 | webr:
113 | packages: ['ggplot2', 'dplyr']
114 | autoload-packages: false
115 | ---
116 | ```
117 |
118 | # Installing an R Package Interactively
119 |
120 | If you need to install a package interactively within specific code cells, you can do so using either the `webr::install()` or `install.packages()` function. This method allows you to install packages on-the-fly when needed.
121 |
122 | :::callout-note
123 | Please note that not all R packages are immediately available for use with webR due to the presence of compiled code routines. The installation process might also take some time depending on the [communication channel](qwebr-communication-channels.qmd#sec-service-worker) being used.
124 | :::
125 |
126 | Let's take ggplot2 as an example:
127 |
128 | ```{webr-r}
129 | webr::install("ggplot2")
130 | ```
131 |
132 | Using this approach, you can install packages on a per-code cell basis, which can be more efficient when you only need specific packages for certain parts of your document.
133 |
134 |
135 | # Load R Packages Interactively
136 |
137 | Once an R package is installed, you can use it just like normal by calling either `library()` or `require()` to load the package.
138 |
139 | For instance, if you have installed `ggplot2` in the prior code cell, then the following will load the `ggplot2` and create a scatterplot.
140 |
141 | ```{webr-r}
142 | library("ggplot2")
143 |
144 | ggplot(mpg, aes(displ, hwy, colour = class)) +
145 | geom_point()
146 | ```
147 |
148 |
149 | Not a fan of having a code cell dedicated to load packages? You can use the `packages` key option above to let the `quarto-webr` extension take care of loading the packages after installing.
150 |
--------------------------------------------------------------------------------
/examples/blog/.gitignore:
--------------------------------------------------------------------------------
1 | /.quarto/
2 | /_site/*
3 |
--------------------------------------------------------------------------------
/examples/blog/_extensions:
--------------------------------------------------------------------------------
1 | ../../_extensions
--------------------------------------------------------------------------------
/examples/blog/_quarto.yml:
--------------------------------------------------------------------------------
1 | project:
2 | type: website
3 |
4 | website:
5 | title: "blog"
6 | navbar:
7 | right:
8 | - about.qmd
9 | - icon: github
10 | href: https://github.com/
11 | - icon: twitter
12 | href: https://twitter.com
13 | format:
14 | html:
15 | theme: cosmo
16 | css: styles.css
17 |
18 | # Enable webR on all post pages
19 | webr:
20 | channel-type: 'automatic'
21 | filters:
22 | - webr
23 |
--------------------------------------------------------------------------------
/examples/blog/about.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "About"
3 | image: profile.jpg
4 | about:
5 | template: jolla
6 | links:
7 | - icon: github
8 | text: GitHub
9 | href: https://github.com/coatless/quarto-webr
10 | ---
11 |
12 | This blog is a demo showing how to use the `quarto-webr` extension.
13 |
--------------------------------------------------------------------------------
/examples/blog/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "blog"
3 | listing:
4 | contents: posts
5 | sort: "date desc"
6 | type: default
7 | categories: true
8 | sort-ui: false
9 | filter-ui: false
10 | page-layout: full
11 | title-block-banner: true
12 | ---
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/blog/posts/_metadata.yml:
--------------------------------------------------------------------------------
1 | # options specified here will apply to all posts in this folder
2 |
3 | # freeze computational output
4 | # (see https://quarto.org/docs/projects/code-execution.html#freeze)
5 | freeze: true
6 |
7 | # Enable banner style title blocks
8 | title-block-banner: true
9 |
--------------------------------------------------------------------------------
/examples/blog/posts/embed-slides/image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coatless/quarto-webr/8ad65f045e718ecfd45c0e5b2ec04998dd508c0f/examples/blog/posts/embed-slides/image.jpg
--------------------------------------------------------------------------------
/examples/blog/posts/embed-slides/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Post Containing Slides with Interactive Code"
3 | author: "James Balamuta"
4 | date: "2023-11-13"
5 | categories: [news, code, analysis]
6 | image: "image.jpg"
7 | ---
8 |
9 | This is a post that contains slides with interactive code on a [Quarto Blog](https://quarto.org/docs/websites/website-blog.html) through the [`quarto-webr`](https://github.com/coatless/quarto-webr) extension. The configuration setup for the `quarto-webr` extension is taken care of in the `_quarto.yml` file to avoid needing to re-specify options multiple times.
10 |
11 | ## Presentation
12 |
13 | :::{.callout-important}
14 | For `quarto-webr` to work within RevealJS, you must use a [**pre-release** version of Quarto that is 1.4.502 or greater](https://quarto.org/docs/download/prerelease) that contains an updated copy of `pandoc`. For more details, please see [Issue #14](https://github.com/coatless/quarto-webr/issues/14).
15 | :::
16 |
17 |
24 |
25 |
26 | ```{=html}
27 |
28 | ```
29 |
30 |
31 | ## Embed Code
32 |
33 | Place the following code inside of the Quarto Document:
34 |
35 | ````html
36 |
43 |
44 |
45 | ```{=html}
46 |
47 | ```
48 |
49 | ````
50 |
--------------------------------------------------------------------------------
/examples/blog/posts/post-with-code/image.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coatless/quarto-webr/8ad65f045e718ecfd45c0e5b2ec04998dd508c0f/examples/blog/posts/post-with-code/image.jpg
--------------------------------------------------------------------------------
/examples/blog/posts/post-with-code/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Post With Interactive Code"
3 | author: "James Balamuta"
4 | date: "2023-11-12"
5 | categories: [news, code, analysis]
6 | image: "image.jpg"
7 | ---
8 |
9 | This is a post with interactive code on a [Quarto Blog](https://quarto.org/docs/websites/website-blog.html) through the [`quarto-webr`](https://github.com/coatless/quarto-webr) extension. The configuration setup for the `quarto-webr` extension is taken care of in the `_quarto.yml` file to avoid needing to re-specify options multiple times.
10 |
11 | ```{webr-r}
12 | print("Hello blog Quarto world!")
13 | ```
14 |
--------------------------------------------------------------------------------
/examples/blog/profile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coatless/quarto-webr/8ad65f045e718ecfd45c0e5b2ec04998dd508c0f/examples/blog/profile.jpg
--------------------------------------------------------------------------------
/examples/blog/styles.css:
--------------------------------------------------------------------------------
1 | /* css styles */
2 |
--------------------------------------------------------------------------------
/examples/book/.gitignore:
--------------------------------------------------------------------------------
1 | /.quarto/
2 |
--------------------------------------------------------------------------------
/examples/book/_extensions:
--------------------------------------------------------------------------------
1 | ../../_extensions/
--------------------------------------------------------------------------------
/examples/book/_quarto.yml:
--------------------------------------------------------------------------------
1 | project:
2 | type: book
3 |
4 | book:
5 | title: "Sample quarto-webr Book Project"
6 | author: "JJB"
7 | date: today
8 | url: https://quarto-webr.thecoatlessprofessor.com/examples/book
9 | repo-url: https://github.com/coatless/quarto-webr/tree/main/examples/book
10 | repo-actions: edit
11 | search: true
12 | reader-mode: true
13 | sidebar:
14 | style: "docked"
15 | chapters:
16 | - index.qmd
17 | - part: "Exploring R"
18 | chapters:
19 | - example-page.qmd
20 | - slide-embed.qmd
21 | - href: ../../
22 | text: Documentation Portal
23 | page-footer:
24 | left: "An example book with quarto-webr."
25 | right:
26 | - icon: github
27 | href: https://github.com/coatless/quarto-webr
28 |
29 | # Set the language that should be used for Quarto book
30 | # https://github.com/quarto-dev/quarto-cli/tree/main/src/resources/language
31 | # lang: en
32 |
33 | # Set default options for every webpage that may or may not include webR.
34 | webr:
35 | show-startup-message: false # Display status of webR initialization
36 | # show-header-message: false # Check to see if COOP&COEP headers are set for speed.
37 | # packages: ['ggplot2', 'dplyr'] # Pre-install dependencies
38 | # base-url: '' # Base URL used for specifying where R WebAssembly binaries should be located
39 | # home-dir: '/home/rstudio' # Customize where the working directory is
40 | # channel-type: 'post-message' # Specify communication channel
41 | # service-worker-url: '' # URL from where to load JavaScript worker scripts when loading webR with the ServiceWorker communication channel.
42 |
43 | # Attach webR to every page
44 | filters:
45 | - webr
46 |
--------------------------------------------------------------------------------
/examples/book/example-page.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Example page"
3 | webr:
4 | show-startup-message: true # Display status of webR initialization
5 | packages: ['ggplot2', 'dplyr'] # Pre-install dependency
6 | ---
7 |
8 | On this page, we set two options directly in the Quarto document. The rest of the options are coming from the `_quarto.yml` project file. These options are considered "global".
9 |
10 | The local options that we enabled are to show the webR status bar and to pre-install the `ggplot2` and `dplyr` packages. We create a hypothetical document that compares and constrasts Base R code with Tidyverse code.
11 |
12 |
13 | # Sorting
14 |
15 | Consider the need to find the highest or lowest values. In this case, we're seeking to sort or modify the order of the data.
16 |
17 | ::: {.panel-tabset group="language"}
18 |
19 | ## Base R
20 |
21 | ```{webr-r}
22 | within(mtcars, {
23 | mtcars[order(cyl, disp), , drop = FALSE]
24 | })
25 | ```
26 |
27 | ## tidyverse
28 |
29 | ```{webr-r}
30 | library(dplyr)
31 | mtcars |>
32 | arrange(cyl, disp)
33 | ```
34 |
35 |
36 | :::
37 |
38 | # Summarize
39 |
40 | Next, let's take a look at how summarization differs between Base R and the Tidyverse
41 |
42 | ::: {.panel-tabset group="language"}
43 |
44 | ## Base R
45 |
46 | ```{webr-r}
47 | mtcars_by <- by(mtcars, mtcars$cyl, function(df) {
48 | with(df, data.frame(cyl = cyl[[1]], mean = mean(disp), n = nrow(df)))
49 | })
50 | do.call(rbind, mtcars_by)
51 | ```
52 |
53 | ## tidyverse
54 |
55 | ```{webr-r}
56 | library(dplyr)
57 |
58 | mtcars |>
59 | group_by(cyl) |>
60 | summarise(mean = mean(disp), n = n())
61 | ```
62 |
63 |
64 | :::
65 |
66 | # Graphing
67 |
68 | Next, let's take a look at how summarization differs between Base R and the Tidyverse
69 |
70 | ::: {.panel-tabset group="language"}
71 |
72 | ## Base R
73 |
74 | ```{webr-r}
75 | plot(mtcars$wt, mtcars$mpg,
76 | main = "Scatterplot in Base R",
77 | xlab = "Car Weight", ylab = "MPG",
78 | col = "blue", lwd = 1)
79 | abline(lm(mtcars$mpg ~ mtcars$wt), col = "red")
80 | ```
81 |
82 | ## tidyverse
83 |
84 | ```{webr-r}
85 | library(ggplot2)
86 |
87 | ggplot(mtcars, aes(x = wt, y = mpg)) +
88 | geom_point(size=2, color="blue", stroke=1) +
89 | geom_smooth(method=lm, color="red") +
90 | ggtitle("Scatterplot in ggplot2") +
91 | xlab("Car Weight")
92 | ```
93 |
94 |
95 | :::
96 |
--------------------------------------------------------------------------------
/examples/book/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Quarto Webr Demo Book"
3 | ---
4 |
5 | # Welcome
6 |
7 | Welcome to a demo Book that uses the [`quarto-webr`](https://github.com/coatless/quarto-webr) extension to generate interactive code cells with [Quarto](https://quarto.org) and [webR](https://docs.r-wasm.org/webr/latest/).
8 |
9 | ```{webr-r}
10 | print("Hello there! Welcome to a quarto-webR powered book!")
11 | ```
12 |
13 |
--------------------------------------------------------------------------------
/examples/book/slide-embed.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Embed Slides"
3 | ---
4 |
5 | On this page, we show how we can embed a RevealJS Presentation inside of a Quarto Book.
6 |
7 | ## Presentation
8 |
9 | :::{.callout-important}
10 | For `quarto-webr` to work within RevealJS, you must use a [**pre-release** version of Quarto that is 1.4.502 or greater](https://quarto.org/docs/download/prerelease) that contains an updated copy of `pandoc`. For more details, please see [Issue #14](https://github.com/coatless/quarto-webr/issues/14).
11 | :::
12 |
13 |
20 |
21 |
22 | ```{=html}
23 |
24 |
25 | ```
26 |
27 |
28 | ```{=html}
29 |
30 | ```
31 |
32 |
33 | ## Embed Code
34 |
35 | Place the following code inside of the Quarto Document:
36 |
37 | ````html
38 |
45 |
46 |
47 | ```{=html}
48 |
49 | ```
50 |
51 | ````
--------------------------------------------------------------------------------
/examples/html-document/.gitignore:
--------------------------------------------------------------------------------
1 | /.quarto/
2 |
--------------------------------------------------------------------------------
/examples/html-document/_extensions:
--------------------------------------------------------------------------------
1 | ../../_extensions/
--------------------------------------------------------------------------------
/examples/html-document/_quarto.yml:
--------------------------------------------------------------------------------
1 | project:
2 | title: "index"
3 |
--------------------------------------------------------------------------------
/examples/html-document/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "quarto-webr Demo HTML Document"
3 | format: html
4 | webr:
5 | channel-type: "automatic"
6 | filters:
7 | - webr
8 | ---
9 |
10 | # Welcome
11 |
12 | Welcome to a demo HTML Document that uses the [`quarto-webr`](https://github.com/coatless/quarto-webr) extension to generate interactive code cells with [Quarto](https://quarto.org) and [webR](https://docs.r-wasm.org/webr/latest/).
13 |
14 | ```{webr-r}
15 | print("Hello there! Welcome to a quarto-webR powered HTML Document!")
16 | ```
17 |
18 | Let's go back to the [documentation portal](../../)
19 |
--------------------------------------------------------------------------------
/examples/readme/_extensions:
--------------------------------------------------------------------------------
1 | ../../_extensions
--------------------------------------------------------------------------------
/examples/readme/_quarto.yml:
--------------------------------------------------------------------------------
1 | project:
2 | title: "index"
3 |
--------------------------------------------------------------------------------
/examples/readme/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: webR in Quarto HTML Documents
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | This is a webr-enabled code cell in a Quarto HTML document.
10 |
11 | ```{webr-r}
12 | fit = lm(mpg ~ am, data = mtcars)
13 |
14 | summary(fit)
15 | ```
16 |
17 |
18 | Return to the [documentation website](https://quarto-webr.thecoatlessprofessor.com/) or [GitHub Repository](https://github.com/coatless/quarto-webr).
--------------------------------------------------------------------------------
/examples/revealjs/.gitignore:
--------------------------------------------------------------------------------
1 | /.quarto/
2 |
--------------------------------------------------------------------------------
/examples/revealjs/_extensions:
--------------------------------------------------------------------------------
1 | ../../_extensions/
--------------------------------------------------------------------------------
/examples/revealjs/_quarto.yml:
--------------------------------------------------------------------------------
1 | project:
2 | title: "index"
3 |
--------------------------------------------------------------------------------
/examples/revealjs/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "quarto-webr Demo RevealJS Document"
3 | format: revealjs
4 | webr:
5 | packages: ['ggplot2', 'dplyr'] # Install R packages on document open
6 | # autoload-packages: false # Disable automatic loading of packages
7 | # show-startup-message: false # Disable displaying status of webR initialization
8 | filters:
9 | - webr
10 | ---
11 |
12 | ## Welcome
13 |
14 | Welcome to a demo RevealJS presentation that uses the [`quarto-webr`](https://github.com/coatless/quarto-webr) extension to generate interactive code cells with [Quarto](https://quarto.org) and [webR](https://docs.r-wasm.org/webr/latest/).
15 |
16 | :::{.callout-important}
17 | This template requires a [**pre-release** version of Quarto that is 1.4.502 or greater](https://quarto.org/docs/download/prerelease) that contains an updated copy of `pandoc`. For more details, please see [Issue #14](https://github.com/coatless/quarto-webr/issues/14).
18 | :::
19 |
20 | Not the right template? Let's go back to the [documentation portal](../../)
21 |
22 | ## webR in RevealJS
23 |
24 | This is a webR-enabled code cell in a Quarto RevealJS document.
25 |
26 | ```{webr-r}
27 | fit = lm(mpg ~ wt, data = mtcars)
28 |
29 | summary(fit)
30 | ```
31 |
32 | ## Base R Graphing with webR
33 |
34 | ```{webr-r}
35 | plot(pressure)
36 | ```
37 |
38 | ## ggplot2 in webR
39 |
40 | ```{webr-r}
41 | ggplot(mpg, aes(displ, hwy, colour = class)) +
42 | geom_point()
43 | ```
44 |
45 | ## Help Documentation
46 |
47 | ```{webr-r}
48 | ?mean
49 | ```
50 |
51 |
52 | ## Prints, Warnings, and Errors
53 |
54 | ```{webr-r}
55 | cat("Hello there!\n")
56 |
57 | x = c(1, 2, 3)
58 | print(x)
59 |
60 | warning("Uh-oh, something is amiss")
61 |
62 | stop("I'm sorry Dave, I'm afraid I can't do that")
63 | ```
64 |
65 |
66 | ## Keyboard Shortcuts
67 |
68 | - Run selected code using either:
69 | - macOS: ⌘ + ↩/Return
70 | - Windows/Linux: Ctrl + ↩/Enter
71 | - Run the entire code by clicking the "Run code" button or pressing Shift+↩.
72 |
73 | ```{webr-r}
74 | print("Hello quarto-webr RevealJS world!")
75 |
76 | 3 + 5
77 | ```
78 |
79 | ## Embedded Slides
80 |
81 | You can embed the slide deck inside of a Quarto Website or Book by using:
82 |
83 | ````html
84 |
91 |
92 |
93 | ```{=html}
94 |
95 | ```
96 |
97 | ````
98 |
99 | :::{.callout-note}
100 | Avoid using _within_ a RevealJS presentation. Only 1 instance of webR should be running.
101 | :::
102 |
103 | ## Fin
104 |
105 | Thanks for checking out the demo! Let's head back to
106 | the [documentation portal](../../).
--------------------------------------------------------------------------------
/examples/website/.gitignore:
--------------------------------------------------------------------------------
1 | /.quarto/
2 | /_site/*
3 |
--------------------------------------------------------------------------------
/examples/website/_extensions:
--------------------------------------------------------------------------------
1 | ../../_extensions/
--------------------------------------------------------------------------------
/examples/website/_quarto.yml:
--------------------------------------------------------------------------------
1 | project:
2 | type: website
3 |
4 | website:
5 | title: "Demo Quarto Webr Website"
6 | search: true
7 | reader-mode: true
8 | navbar:
9 | left:
10 | - href: index.qmd
11 | text: Home
12 | - href: example-page.qmd
13 | text: Example page
14 | - href: slide-embed.qmd
15 | text: Embed Slides
16 | - href: ../../
17 | text: Documentation Portal
18 | sidebar:
19 | style: "floating"
20 | contents:
21 | - section: "Content"
22 | contents:
23 | - index.qmd
24 | - example-page.qmd
25 | - slide-embed.qmd
26 | - href: ../../
27 | text: Documentation Portal
28 |
29 | page-footer:
30 | left: "An example website with quarto-webr."
31 | right:
32 | - icon: github
33 | href: https://github.com/coatless/quarto-webr
34 |
35 | # Set the language that should be used for Quarto websites
36 | # https://github.com/quarto-dev/quarto-cli/tree/main/src/resources/language
37 | # lang: en
38 |
39 | # Set default options for every webpage that may or may not include webR.
40 | webr:
41 | show-startup-message: false # Display status of webR initialization
42 | # show-header-message: false # Check to see if COOP&COEP headers are set for speed.
43 | # packages: ['ggplot2', 'dplyr'] # Pre-install dependencies
44 | # base-url: '' # Base URL used for specifying where R WebAssembly binaries should be located
45 | # home-dir: '/home/rstudio' # Customize where the working directory is
46 | # channel-type: 'post-message' # Specify communication channel
47 | # service-worker-url: '' # URL from where to load JavaScript worker scripts when loading webR with the ServiceWorker communication channel.
48 |
49 | # Attach webR to every page
50 | filters:
51 | - webr
52 |
--------------------------------------------------------------------------------
/examples/website/example-page.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Example page"
3 | webr:
4 | show-startup-message: true # Display status of webR initialization
5 | packages: ['ggplot2'] # Pre-install dependency
6 | ---
7 |
8 | On this page, we set two options directly in the Quarto document. The rest of the options are coming from the `_quarto.yml` project file. These options are considered "global".
9 |
10 | The local options that we enabled are to show the webR status bar and to pre-install the ggplot2 package.
11 |
12 | ```{webr-r}
13 | library(ggplot2)
14 |
15 | p <- ggplot(mpg, aes(cyl, hwy))
16 | p + geom_jitter(aes(colour = class))
17 | ```
18 |
19 | :::callout-note
20 | If we did not specify the package dependency in the document header, then we would need to add to the code cell the installation command of `webr::install('ggplot2')` prior to using `library(ggplot2)`.
21 | :::
--------------------------------------------------------------------------------
/examples/website/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Quarto Webr Demo Website"
3 | ---
4 |
5 | # Welcome
6 |
7 | Welcome to a demo website that uses the [`quarto-webr`](https://github.com/coatless/quarto-webr) extension to generate interactive code cells with [Quarto](https://quarto.org) and [webR](https://docs.r-wasm.org/webr/latest/).
8 |
9 | ```{webr-r}
10 | print("Hello there! Welcome to a quarto-webR powered website!")
11 | ```
12 |
13 |
--------------------------------------------------------------------------------
/examples/website/slide-embed.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Embed Slides"
3 | ---
4 |
5 | On this page, we show how we can embed a RevealJS Presentation inside of a Quarto Website.
6 |
7 | ## Presentation
8 |
9 | :::{.callout-important}
10 | For `quarto-webr` to work within RevealJS, you must use a [**pre-release** version of Quarto that is 1.4.502 or greater](https://quarto.org/docs/download/prerelease) that contains an updated copy of `pandoc`. For more details, please see [Issue #14](https://github.com/coatless/quarto-webr/issues/14).
11 | :::
12 |
13 |
20 |
21 |
22 | ```{=html}
23 |
24 | ```
25 |
26 |
27 | ## Embed Code
28 |
29 | Place the following code inside of the Quarto Document:
30 |
31 | ````html
32 |
39 |
40 |
41 | ```{=html}
42 |
43 | ```
44 |
45 | ````
46 |
--------------------------------------------------------------------------------
/quarto-webr.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "."
5 | }
6 | ],
7 | "settings": {}
8 | }
--------------------------------------------------------------------------------
/tests/.gitignore:
--------------------------------------------------------------------------------
1 | /.quarto/
2 |
--------------------------------------------------------------------------------
/tests/_extensions:
--------------------------------------------------------------------------------
1 | ../_extensions
--------------------------------------------------------------------------------
/tests/_quarto.yml:
--------------------------------------------------------------------------------
1 | project:
2 | type: website
3 |
4 | website:
5 | title: "Test Suite for quarto-webr"
6 | search: true
7 | reader-mode: true
8 | sidebar:
9 | style: "floating"
10 | contents:
11 | - href: index.qmd
12 | text: Home
13 | - href: ../../
14 | text: Main Website
15 | - section: "Tests"
16 | contents:
17 | - auto: "*test*.qmd"
18 |
19 |
20 | page-footer:
21 | left: "Test suite for quarto-webr."
22 | right:
23 | - icon: github
24 | href: https://github.com/coatless/quarto-webr
25 |
26 | # Allow quarto to switch between light and dark themes.
27 | theme:
28 | light: cosmo
29 | dark: darkly
30 |
31 | # Set the language that should be used for Quarto websites
32 | # https://github.com/quarto-dev/quarto-cli/tree/main/src/resources/language
33 | # lang: en
34 |
35 | # Set default options for every webpage that may or may not include webR.
36 | # webr:
37 | # show-startup-message: false # Display status of webR initialization
38 | # show-header-message: false # Check to see if COOP&COEP headers are set for speed.
39 | # packages: ['ggplot2', 'dplyr'] # Pre-install dependencies
40 | # base-url: '' # Base URL used for specifying where R WebAssembly binaries should be located
41 | # home-dir: '/home/rstudio' # Customize where the working directory is
42 | # channel-type: 'post-message' # Specify communication channel
43 | # service-worker-url: '' # URL from where to load JavaScript worker scripts when loading webR with the ServiceWorker communication channel.
44 |
45 | # Attach webR to every page
46 | filters:
47 | - webr
48 |
--------------------------------------------------------------------------------
/tests/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "quarto-webr Test Website"
3 | subtitle: "Extension Test Suite"
4 | ---
5 |
6 | # Welcome
7 |
8 | Welcome to the test suite website for the [`quarto-webr`](https://github.com/coatless/quarto-webr). This website is meant to examine how different features of the extension are working or not working across different browsers.
9 |
10 | ```{webr-r}
11 | print("Welcome to behind the scenes of quarto-webr!")
12 | ```
13 |
14 |
--------------------------------------------------------------------------------
/tests/qwebr-test-editor-options.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Editor Options"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | Check that the editor responses correctly to options being set.
10 |
11 | ## Adaptive Container Constraints
12 |
13 | ### Single line
14 |
15 | ```{webr-r}
16 | print("test")
17 | ```
18 |
19 | ### Uncapped height
20 |
21 | ```{webr-r}
22 | print("test")
23 | 59120
24 | 1 + 1
25 | c(1, 3, 4)
26 | print("line 5")
27 | ```
28 |
29 | ### Height cap
30 |
31 | ```{webr-r}
32 | #| editor-max-height: 80
33 | print("test")
34 | 59120
35 | 1 + 1
36 | c(1, 3, 4)
37 | print("line 5")
38 | ```
39 |
40 | ## Autosuggetions
41 |
42 | Opt-in to auto suggestions.
43 |
44 | ```{webr-r}
45 | #| editor-quick-suggestions: true
46 | my_long_variable = 1
47 |
48 | prin
49 | ```
50 |
51 |
52 | ## Highlight
53 |
54 | Opt-in to auto suggestions.
55 |
56 | ### Only 1 line
57 | ```{webr-r}
58 | #| editor-code-line-numbers:1
59 | my_long_variable = 1
60 |
61 | 1 + 1
62 |
63 | print("hello!")
64 | ```
65 |
66 | ### Line 1 and 5
67 | ```{webr-r}
68 | #| editor-code-line-numbers:1,5
69 | my_long_variable = 1
70 |
71 | 1 + 1
72 |
73 | print("hello!")
74 | ```
75 |
76 | ### Line 1-3 and 5
77 |
78 | ```{webr-r}
79 | #| editor-code-line-numbers:1-3,5
80 | my_long_variable = 1
81 |
82 | 1 + 1
83 |
84 | print("hello!")
85 | ```
86 |
87 |
88 | ## Word wrap
89 |
90 | ### Enabled Wrap
91 | ```{webr-r}
92 | #| editor-word-wrap: true
93 |
94 | my_extra_extra_extra_extra_extra_long_variable = 1
95 | ```
96 |
97 | ### Disabled Wrap
98 | ```{webr-r}
99 | #| editor-word-wrap: false
100 |
101 | my_extra_extra_extra_extra_extra_long_variable = 1
102 | ```
103 |
--------------------------------------------------------------------------------
/tests/qwebr-test-escape-html-output-characters.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Escape Output with HTML Entities"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | Ensure HTML output is escaped or passed t hrough
10 |
11 | ## Interactive
12 |
13 | ### results: markup
14 | ```{webr-r}
15 | # This function converts a markdown link into HTML
16 | "[Posit](https://posit.co)" |> (\(.) {
17 | text <- sub("\\].*", "", sub(".*\\[", "", .))
18 | url <- sub("\\).*", "", sub(".*\\(", "", .))
19 |
20 | writeLines(noquote(paste0('', text, '')))
21 | })()
22 | ```
23 |
24 | ## Non-interactive
25 |
26 | ### results: markup
27 |
28 | ```{webr-r}
29 | #| context: output
30 | # This function converts a markdown link into HTML
31 | "[Posit](https://posit.co)" |> (\(.) {
32 | text <- sub("\\].*", "", sub(".*\\[", "", .))
33 | url <- sub("\\).*", "", sub(".*\\(", "", .))
34 |
35 | writeLines(noquote(paste0('', text, '')))
36 | })()
37 | ```
38 |
39 | ### results: asis
40 |
41 | ```{webr-r}
42 | #| context: output
43 | #| results: asis
44 | # This function converts a markdown link into HTML
45 | "[Posit](https://posit.co)" |> (\(.) {
46 | text <- sub("\\].*", "", sub(".*\\[", "", .))
47 | url <- sub("\\).*", "", sub(".*\\(", "", .))
48 |
49 | writeLines(noquote(paste0('', text, '')))
50 | })()
51 | ```
52 |
53 |
54 | ### output: asis
55 |
56 | ```{webr-r}
57 | #| context: output
58 | #| output: asis
59 | # This function converts a markdown link into HTML
60 | "[Posit](https://posit.co)" |> (\(.) {
61 | text <- sub("\\].*", "", sub(".*\\[", "", .))
62 | url <- sub("\\).*", "", sub(".*\\(", "", .))
63 |
64 | writeLines(noquote(paste0('', text, '')))
65 | })()
66 | ```
67 |
68 |
--------------------------------------------------------------------------------
/tests/qwebr-test-global-cell-options.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Setting Global Cell Options"
3 | format: html
4 | engine: knitr
5 | webr:
6 | cell-options:
7 | comment: "## "
8 | autorun: true
9 | filters:
10 | - webr
11 | ---
12 |
13 | Check that the global options array is correctly parsed and that local values of the cell can still override a global option.
14 |
15 | ## Interactive
16 |
17 | ### Global
18 | ```{webr-r}
19 | print("test")
20 | ```
21 |
22 | ### Local
23 |
24 | ```{webr-r}
25 | #| comment: ""
26 | print("test")
27 | ```
28 |
29 |
30 | ## Non-interactive
31 |
32 | ### Global
33 | ```{webr-r}
34 | #| context: output
35 | print("test")
36 | ```
37 |
38 | ### Local
39 |
40 | ```{webr-r}
41 | #| context: output
42 | #| comment: ""
43 | print("test")
44 | ```
45 |
--------------------------------------------------------------------------------
/tests/qwebr-test-help-documentation.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Help Documentation"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | Test pager event support by verifying help documentation works in the interactive and non-interactive contexts.
10 |
11 | ## Interactive
12 |
13 | ```{webr-r}
14 | ?mean
15 | ```
16 |
17 | ## Non-interactive
18 |
19 | ```{webr-r}
20 | #| context: output
21 | ?sd
22 | ```
23 |
--------------------------------------------------------------------------------
/tests/qwebr-test-interactive-with-keyboard-shortcut.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Keyboard Shortcuts in Code cell"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | This is a webr-enabled code cell in a Quarto HTML document.
10 |
11 |
12 | ```{webr-r}
13 | -3 + 5
14 |
15 | print("Hello quarto-webr World!")
16 | ```
17 |
18 |
19 | - Run selected code using either:
20 | - macOS: ⌘ + ↩/Return
21 | - Windows/Linux: Ctrl + ↩/Enter
22 | - Run the entire code by clicking the "Run code" button or pressing Shift+↩.
23 |
24 |
25 |
--------------------------------------------------------------------------------
/tests/qwebr-test-internal-cell.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Cell Context Options"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | Test page for verifying cell context options set explicitly with `context`.
10 |
11 | ## Interactive
12 |
13 | ### Static
14 | ```{webr-r}
15 | #| context: interactive
16 | 1 + 1
17 | ```
18 |
19 | ### Autorun
20 |
21 | ```{webr-r}
22 | #| context: interactive
23 | #| autorun: true
24 | 1 + 1
25 | ```
26 |
27 | ### Read-only
28 |
29 | ```{webr-r}
30 | #| context: interactive
31 | #| read-only: true
32 | #| autorun: true
33 | 1 + 1
34 | ```
35 |
36 |
37 | ## Setup
38 |
39 | Hidden cell that sets `x` and `y` vector values.
40 |
41 | ```{webr-r}
42 | #| context: setup
43 | x = c(1, 5, 3, -2)
44 | y = c(-5, 8, 9, 4)
45 | ```
46 |
47 | ## Output
48 |
49 | Hidden cell that retrieves previously set `x` and `y` vector values and displays the data.
50 |
51 | ```{webr-r}
52 | #| context: output
53 | cat("x: ")
54 | print(x)
55 |
56 | cat("y: ")
57 | print(y)
58 |
59 | plot(x, y)
60 | ```
61 |
--------------------------------------------------------------------------------
/tests/qwebr-test-multiple-cells.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Multiple webR cells"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | Ensure each webR cell outputs in its own area.
10 |
11 | ## Interactive
12 |
13 | ```{webr-r}
14 | 1 + 1
15 | ```
16 |
17 | Graph in separate code cell
18 |
19 | ```{webr-r}
20 | plot(pressure)
21 | ```
22 |
23 | ## Non-interactive
24 |
25 | ```{webr-r}
26 | #| context: output
27 | 1 + 1
28 | ```
29 |
30 | Graph in separate code cell
31 |
32 | ```{webr-r}
33 | #| context: output
34 | plot(pressure)
35 | ```
--------------------------------------------------------------------------------
/tests/qwebr-test-non-interactive-chained-cells.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Chained Non-interactive Areas"
3 | engine: knitr
4 | webr:
5 | packages: ['ggplot2', 'dplyr']
6 | filters:
7 | - webr
8 | ---
9 |
10 | :::{.callout-important}
11 | We've slowed down each cell's execution time by about 1/4 of a second to show how the document is responding.
12 | :::
13 |
14 | # Package dependencies
15 |
16 | The `quarto-webr` extension is set to automatically install and load the `ggplot2` and `dplyr` packages by specifying a `packages` key in the document's header.
17 |
18 | # Setup a hidden ggplot2 object
19 |
20 | From there, we're going to use the `context: setup` hidden cell to create a `ggplot2` object that uses the `mtcars` data set with the aesthetic mappings of `x = wt` and `y = mpg` called `g`.
21 |
22 | ```{webr-r}
23 | #| context: setup
24 | g <- ggplot(mtcars, aes(x = wt, y = mpg))
25 |
26 | Sys.sleep(0.25)
27 | ```
28 |
29 | # Generate a graph
30 |
31 | Let's move from setup to generating and displaying results by using `g` object created in `setup` within an `output` context:
32 |
33 | ```{webr-r}
34 | #| context: output
35 | g + geom_point()
36 |
37 | Sys.sleep(0.25)
38 | ```
39 |
40 | # Re-use prior graph object
41 |
42 | Let's also re-use the base `g` but change the aesthetics so that colour is now present.
43 |
44 | ```{webr-r}
45 | #| context: output
46 | g + geom_point(aes(colour = factor(cyl)))
47 | Sys.sleep(0.25)
48 | ```
49 |
50 | # Expose the setup object
51 |
52 | Finally, let's make sure we can do some interesting things with the interactive session.
53 |
54 | :::{.callout-note}
55 | Changes inside of interactive cells do not propagate backwards in the document.
56 | :::
57 |
58 | ```{webr-r}
59 | g
60 | ```
61 |
--------------------------------------------------------------------------------
/tests/qwebr-test-non-interactive-context-with-packages.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Load and Use Packages used in Context"
3 | engine: knitr
4 | webr:
5 | packages: ['ggplot2']
6 | show-startup-message: false
7 | autoload-packages: false
8 | filters:
9 | - webr
10 | ---
11 |
12 | This document disables autoloading of the packages and manually loads the package inside of the context output.
13 |
14 | ```{webr-r}
15 | #| context: output
16 | library("ggplot2")
17 | g <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()
18 | g
19 | ```
20 |
21 | Next, we should be able to retrieve the prior cells value
22 | ```{webr-r}
23 | #| context: interactive
24 | g + aes(color = factor(cyl))
25 | ```
26 |
--------------------------------------------------------------------------------
/tests/qwebr-test-non-interactive-setup-with-packages-and-interactive.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Setup Cell with Packages for Interactive"
3 | engine: knitr
4 | webr:
5 | show-startup-message: true
6 | packages: ['tibble', 'dplyr', 'ggplot2']
7 | autoload-packages: true
8 | filters:
9 | - webr
10 | ---
11 |
12 | The following hidden cell should setup a ggplot2 theme and set variables:
13 |
14 | ```{webr-r}
15 | #| context: setup
16 | s <- 1000
17 | theme_set(theme_minimal())
18 | blue <- "#327291"
19 | ```
20 |
21 | The next cell should handle graphing values with a theme being set:
22 |
23 | ```{webr-r}
24 | mean <- 5
25 | sd <- 2
26 | n <- 100
27 |
28 | data <- tibble(x = rnorm(n = n, mean = mean, sd = sd))
29 |
30 | ggplot(data, aes(x = x)) +
31 | geom_histogram(
32 | color = "gray20",
33 | linewidth = 0.25,
34 | fill = blue,
35 | alpha = .85
36 | )
37 | ```
--------------------------------------------------------------------------------
/tests/qwebr-test-non-interactive-setup-with-packages.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Packages used in Hidden Setup"
3 | engine: knitr
4 | webr:
5 | packages: ["dplyr", "tibble"]
6 | filters:
7 | - webr
8 | ---
9 |
10 | Perform data manipulations on `mtcars` in a non-interactive cell...
11 |
12 | ```{webr-r}
13 | #| label: spike-data
14 | #| context: setup
15 |
16 | new_mtcars <- mtcars |>
17 | tibble::rownames_to_column(var = "car") |>
18 | tibble::as_tibble() |>
19 | dplyr::select(car, cyl, disp, wt) |>
20 | dplyr::mutate(wt = dplyr::case_when(
21 | wt < 2 ~ -wt,
22 | TRUE ~ wt))
23 | ```
24 |
25 | Then we print it to see how it looks:
26 |
27 | ```{webr-r}
28 | #| label: spike-data
29 | new_mtcars
30 | ```
--------------------------------------------------------------------------------
/tests/qwebr-test-option-space-removal.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Space Removal after Options"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | Check that the editor contents avoids retaining spaces after the options.
10 |
11 |
12 | ## Option with a Single Space
13 |
14 | ```{webr-r}
15 | #| autorun: true
16 |
17 | print("test")
18 | 1 + 1
19 | ```
20 |
21 | ## Multiple Options with a Single Space
22 |
23 | ```{webr-r}
24 | #| read-only: true
25 | #| editor-code-line-numbers: 1,3-5,7
26 |
27 | # This is a comment
28 |
29 | 1 + 1
30 | 2 + 2
31 | 3 + 3
32 |
33 | # This is another comment
34 | ```
35 |
36 | ## Multiple Spaces
37 |
38 | ```{webr-r}
39 | #| autorun: true
40 |
41 |
42 |
43 |
44 | print("test")
45 |
46 | 1 + 1
47 |
48 | ```
49 |
50 |
51 | ## No Space
52 |
53 | ```{webr-r}
54 | #| autorun: true
55 | print("test")
56 |
57 | 1 + 1
58 | ```
59 |
60 |
61 | ## No Options
62 |
63 | ```{webr-r}
64 | fit <- lm(mpg ~ vs, data = mtcars)
65 |
66 | summary(fit)
67 | ```
68 |
--------------------------------------------------------------------------------
/tests/qwebr-test-output-classes.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: CSS Output Classes"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | Test output classes for standard output, standard error, and custom `classes` attributes.
10 |
11 | ## Interactive
12 |
13 | ```{webr-r}
14 | cat("Display letters: ")
15 | print(letters[1:5])
16 |
17 | warning("This is a warning message!")
18 |
19 | stop("This is a hard error message!")
20 | ```
21 |
22 | ## Non-interactive
23 |
24 | ### No Comment
25 | ```{webr-r}
26 | #| context: output
27 | cat("Display letters: ")
28 | print(letters[1:5])
29 |
30 | warning("This is a warning message!")
31 |
32 | stop("This is a hard error message!")
33 | ```
34 |
35 | ### With comment
36 |
37 | ```{webr-r}
38 | #| context: output
39 | #| comment: "## "
40 | cat("Display letters: ")
41 | print(letters[1:5])
42 |
43 | warning("This is a warning message!")
44 |
45 | stop("This is a hard error message!")
46 | ```
47 |
48 | ### With output class custom
49 |
50 | ```{=html}
51 |
60 | ```
61 |
62 | ```{webr-r}
63 | #| context: output
64 | #| classes: toad green
65 | cat("Display letters: ")
66 | print(letters[1:5])
67 |
68 | warning("This is a warning message!")
69 |
70 | stop("This is a hard error message!")
71 | ```
72 |
--------------------------------------------------------------------------------
/tests/qwebr-test-output-graph.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Graphics Output"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | This webpage tests the interactive and output contexts for showing a graph
10 |
11 | ## Interactive
12 |
13 | ### Default options
14 | ```{webr-r}
15 | #| context: interactive
16 | plot(pressure)
17 | ```
18 |
19 | ### Reduced fig height & width
20 |
21 | ```{webr-r}
22 | #| context: interactive
23 | #| fig-height: 6
24 | #| fig-width: 4
25 | #| out-width: 600px
26 | plot(pressure)
27 | ```
28 |
29 |
30 | ## Non-interactive
31 |
32 | ### Default options
33 | ```{webr-r}
34 | #| context: output
35 | #| fig-cap: Testing out figure captions
36 | plot(pressure)
37 | ```
38 |
39 | ### Reduced fig height & width
40 | ```{webr-r}
41 | #| context: output
42 | #| fig-height: 5
43 | #| fig-width: 6
44 | #| out-width: 500px
45 | plot(pressure)
46 | ```
47 |
48 |
49 | ### Reduced fig height & width
50 | ```{webr-r}
51 | #| context: output
52 | #| fig-height: 5
53 | #| fig-width: 6
54 | #| out-width: 500px
55 | #| out-height: 500px
56 | plot(pressure)
57 | ```
--------------------------------------------------------------------------------
/tests/qwebr-test-output-stderr-result-suppression.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: STDErr & Result Output Suppression"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | Test options for disabling standard error (`warning: false` or `message: false`), `results: hide`, and `output: false`.
10 |
11 | ## Interactive
12 |
13 | ### Suppresion with hide
14 |
15 | ```{webr-r}
16 | #| context: interactive
17 | #| results: hide
18 | cat("Display letters: ")
19 | print(letters[1:5])
20 |
21 | warning("This is a warning message!")
22 |
23 | stop("This is a hard error message!")
24 | ```
25 |
26 |
27 | ### Suppression with warning
28 |
29 | ```{webr-r}
30 | #| context: interactive
31 | #| warning: false
32 | cat("Display letters: ")
33 | print(letters[1:5])
34 |
35 | warning("This is a warning message!")
36 |
37 | stop("This is a hard error message!")
38 | ```
39 |
40 |
41 | ### Suppression with message
42 |
43 | ```{webr-r}
44 | #| context: interactive
45 | #| message: false
46 | cat("Display letters: ")
47 | print(letters[1:5])
48 |
49 | warning("This is a warning message!")
50 |
51 | stop("This is a hard error message!")
52 | ```
53 |
54 |
55 | ## Non-interactive
56 |
57 | ### Suppresion with hide
58 |
59 | ```{webr-r}
60 | #| context: output
61 | #| results: hide
62 | cat("Display letters: ")
63 | print(letters[1:5])
64 |
65 | warning("This is a warning message!")
66 |
67 | stop("This is a hard error message!")
68 | ```
69 |
70 | ### Suppresion with output
71 |
72 | ```{webr-r}
73 | #| context: output
74 | #| output: false
75 | cat("Display letters: ")
76 | print(letters[1:5])
77 |
78 | warning("This is a warning message!")
79 |
80 | stop("This is a hard error message!")
81 | ```
82 |
83 |
84 |
85 | ### Suppression with warning
86 |
87 | ```{webr-r}
88 | #| context: output
89 | #| warning: false
90 | cat("Display letters: ")
91 | print(letters[1:5])
92 |
93 | warning("This is a warning message!")
94 |
95 | stop("This is a hard error message!")
96 | ```
97 |
98 |
99 | ### Suppression with message
100 |
101 | ```{webr-r}
102 | #| context: output
103 | #| message: false
104 | cat("Display letters: ")
105 | print(letters[1:5])
106 |
107 | warning("This is a warning message!")
108 |
109 | stop("This is a hard error message!")
110 | ```
111 |
--------------------------------------------------------------------------------
/tests/qwebr-test-packages-autoload.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Autoload Package"
3 | format: html
4 | engine: knitr
5 | webr:
6 | packages: ['ggplot2']
7 | autoload-packages: 'false'
8 | filters:
9 | - webr
10 | ---
11 |
12 | This webpage tests the `autoload-packages` key meta option by not loading the requested packages.
13 |
14 | ```{webr-r}
15 | # Must call the library statement
16 | library('ggplot2')
17 | ```
--------------------------------------------------------------------------------
/tests/qwebr-test-packages-multi.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Packages Key with Autoloading"
3 | format: html
4 | engine: knitr
5 | webr:
6 | packages: ['ggplot2', 'dplyr']
7 | autoload-packages: true
8 | filters:
9 | - webr
10 | ---
11 |
12 | This webpage tests the `packages` key meta option with the default of `autoload-packages` removing the need for a `library()` call.
13 |
14 | ```{webr-r}
15 | ggplot()
16 | ```
--------------------------------------------------------------------------------
/tests/qwebr-test-repo-key.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Repos package key"
3 | format: html
4 | engine: knitr
5 | webr:
6 | packages: ['demorwasmbinary', 'visualize', 'fakepkg']
7 | repos:
8 | - 'https://tutorials.thecoatlessprofessor.com/webr-unified-gh-workflow/'
9 | filters:
10 | - webr
11 | ---
12 |
13 | This document tests the `repos` key meta option by attempting to download a package `demorwasmbinary` from a custom repository at:
14 |
15 |
16 |
17 | And, then, falls back on the main webR repository for a second package `visualize`.
18 |
19 | ```{webr-r}
20 | #| context: output
21 |
22 | print(paste0("Check if we are in webR with non-CRAN package demorwasmbinary: ", demorwasmbinary::in_webr()))
23 |
24 | print("Creating a graph with a package on CRAN")
25 | visualize::visualize.norm()
26 | ```
--------------------------------------------------------------------------------
/tests/qwebr-test-revealjs.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: webR in RevealJS"
3 | subtitle: "Examining State"
4 | authors: "Presentation Lead"
5 | format:
6 | revealjs:
7 | theme: dark
8 | engine: knitr
9 | filters:
10 | - webr
11 | ---
12 |
13 | ## webR in RevealJS
14 |
15 | This is a webR-enabled code cell in a Quarto RevealJS document.
16 |
17 | ```{webr-r}
18 | fit = lm(mpg ~ wt, data = mtcars)
19 |
20 | summary(fit)
21 | ```
22 |
23 |
24 | ## Keyboard Shortcuts
25 |
26 | - Run selected code using either:
27 | - macOS: ⌘ + ↩/Return
28 | - Windows/Linux: Ctrl + ↩/Enter
29 | - Run the entire code by clicking the "Run code" button or pressing Shift+↩.
30 |
31 | ```{webr-r}
32 | print("Hello quarto-webr RevealJS world!")
33 |
34 | 3 + 5
35 | ```
36 |
37 | ## Text Before and After Code Cell
38 |
39 | Sample text before
40 |
41 | ```{webr-r}
42 | message("Hello World!")
43 | ```
44 |
45 | Sample text after
46 |
47 | ## Scrollable Class Enabled
48 |
49 | ```{webr-r}
50 | 2 + 3
51 | ```
52 |
53 | The default webR block should not make the slide too wide
54 | (no scrollbar at the bottom).
55 |
--------------------------------------------------------------------------------
/tests/qwebr-test-run-built-in.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Run built-in webR version"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | Test to see if the `version` is respected under the built-in value:
10 |
11 | ```{webr-r}
12 | #| context: output
13 | utils::packageVersion("webr")
14 | ```
15 |
--------------------------------------------------------------------------------
/tests/qwebr-test-run-latest.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Run latest version"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | webr:
8 | version: 'latest'
9 | ---
10 |
11 | Test to see if the version key works under the latest version:
12 |
13 | ```{webr-r}
14 | #| context: output
15 | utils::packageVersion("webr")
16 | ```
17 |
--------------------------------------------------------------------------------
/tests/qwebr-test-self-contained.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: embed-resources"
3 | format:
4 | html:
5 | embed-resources: true
6 | engine: knitr
7 | filters:
8 | - webr
9 | ---
10 |
11 | Ensure `embed-resources` option correctly puts a copy of FontAwesome in the document.
12 |
13 | ## Interactive
14 | ```{webr-r}
15 | 1 + 1
16 | ```
17 |
18 | ## Non-interactive
19 |
20 | ```{webr-r}
21 | #| context: output
22 | Sys.sleep(3)
23 |
24 | print("Sleep successful! Did you see the R logo?")
25 | ```
26 |
--------------------------------------------------------------------------------
/tests/qwebr-test-service-worker-version.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Service Worker with Version"
3 | format:
4 | html:
5 | resources:
6 | - webr-serviceworker.js
7 | - webr-worker.js
8 | engine: knitr
9 | webr:
10 | channel-type: "service-worker"
11 | version: "latest"
12 | filters:
13 | - webr
14 | ---
15 |
16 | This is a webr-enabled code cell in a Quarto HTML document that is set to use the service-worker option under the `latest` version of webR.
17 |
18 | ```{webr-r}
19 | #| autorun: true
20 | -3 + 5
21 |
22 | utils::packageVersion("webr")
23 |
24 | print("Hello service worker model!")
25 | ```
26 |
--------------------------------------------------------------------------------
/tests/qwebr-test-service-worker.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Service Worker"
3 | format:
4 | html:
5 | resources:
6 | - webr-serviceworker.js
7 | - webr-worker.js
8 | engine: knitr
9 | webr:
10 | channel-type: "service-worker"
11 | filters:
12 | - webr
13 | ---
14 |
15 | This is a webr-enabled code cell in a Quarto HTML document that is set to use the service-worker option.
16 |
17 | ```{webr-r}
18 | -3 + 5
19 |
20 | print("Hello service worker model!")
21 | ```
22 |
--------------------------------------------------------------------------------
/tests/qwebr-test-shim-install.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Install Packages Shim"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | ## Non-interactive
10 |
11 | ```{webr-r}
12 | #| context: output
13 |
14 | check_pkg_installed <- function(x) {
15 | x %in% installed.packages()[,"Package"]
16 | }
17 |
18 | print(paste0("(Pre-install) Is the package visualize installed? ", check_pkg_installed("visualize")))
19 |
20 | install.packages("visualize")
21 |
22 | print(paste0("(Post-install) Is the package visualize installed? ", check_pkg_installed("visualize")))
23 | ```
24 |
--------------------------------------------------------------------------------
/tests/qwebr-test-status-header-no-title.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | format: html
3 | engine: knitr
4 | filters:
5 | - webr
6 | ---
7 |
8 | Ensure that the webR code cell initializes a status even if a title is omitted.
9 |
10 | ```{webr-r}
11 | print("Hello hidden title world!")
12 | ```
13 |
--------------------------------------------------------------------------------
/tests/qwebr-test-status-header-suppressed-html copy.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: No Startup Status Present in HTML Documents"
3 | format: html
4 | engine: knitr
5 | webr:
6 | show-startup-message: false
7 | filters:
8 | - webr
9 | ---
10 |
11 | Ensure that the webR code cell initializes even if the webR status bar is disabled.
12 |
13 | ```{webr-r}
14 | print("Hello hidden title world!")
15 | ```
16 |
--------------------------------------------------------------------------------
/tests/qwebr-test-status-header-suppressed-revealjs.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: No Startup Status Present in RevealJS Presentations"
3 | subtitle: "Examining State"
4 | authors: "Presentation Lead"
5 | format:
6 | revealjs:
7 | theme: default
8 | engine: knitr
9 | webr:
10 | show-startup-message: false
11 | filters:
12 | - webr
13 | ---
14 |
15 | ## webR in RevealJS
16 |
17 | Ensure that the webR code cell initializes even if the webR status bar is disabled.
18 |
19 | ```{webr-r}
20 | print("Hello hidden title world!")
21 | ```
22 |
--------------------------------------------------------------------------------
/tests/qwebr-test-theme-switch.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test: Light and Dark Mode"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - webr
7 | ---
8 |
9 | Test classes for Quarto's light and dark mode.
10 |
11 | Toggle the switch to see: editor change from `vs` to `vs-dark` and standard output.
12 |
13 | ## Interactive
14 |
15 | ```{webr-r}
16 | #| autorun: true
17 | cat("Display letters: ")
18 | print(letters[1:5])
19 |
20 | plot(1:5)
21 |
22 | warning("This is a warning message!")
23 |
24 | stop("This is a hard error message!")
25 | ```
26 |
--------------------------------------------------------------------------------
/update-quarto-dev.sh:
--------------------------------------------------------------------------------
1 | QUARTO_VERSION="1.4.358"
2 |
3 | wget -O quarto-latest.deb https://github.com/quarto-dev/quarto-cli/releases/download/v${QUARTO_VERSION}/quarto-${QUARTO_VERSION}-linux-amd64.deb
4 |
5 | sudo dpkg -i ./quarto-latest.deb
6 |
7 | rm quarto-latest.deb
8 |
9 |
--------------------------------------------------------------------------------