├── .devcontainer
└── devcontainer.json
├── .github
└── workflows
│ └── publish-website.yml
├── .gitignore
├── .quartoignore
├── README.md
├── _extensions
└── panelize
│ ├── _extension.yml
│ └── panelize.lua
├── docs
├── .gitignore
├── _quarto.yml
├── index.qmd
├── qpanelize-cell.qmd
├── qpanelize-install.qmd
├── qpanelize-pyodide.qmd
├── qpanelize-release-notes.qmd
├── qpanelize-webr.qmd
└── requirements.txt
├── logo-panelize.png
└── panelize.code-workspace
/.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.4",
5 | // Add software
6 | "features": {
7 | // Required to test with knitr
8 | // R package config: https://github.com/rocker-org/devcontainer-features/blob/main/src/r-rig/README.md
9 | "ghcr.io/rocker-org/devcontainer-features/r-rig:1": {
10 | "version": "none",
11 | "installRMarkdown": true,
12 | "installJupyterlab": true,
13 | "installRadian": true
14 | },
15 | // You may wish to switch prerelease to latest for stable development
16 | // Quarto configuration : https://github.com/rocker-org/devcontainer-features/blob/main/src/quarto-cli/README.md
17 | "ghcr.io/rocker-org/devcontainer-features/quarto-cli:1": {
18 | "installTinyTex": true,
19 | "version": "prerelease"
20 | }
21 | },
22 | "customizations": {
23 | "vscode": {
24 | "settings": {
25 | "r.rterm.linux": "/usr/local/bin/radian",
26 | "r.bracketedPaste": true,
27 | "r.plot.useHttpgd": true,
28 | "[r]": {
29 | "editor.wordSeparators": "`~!@#%$^&*()-=+[{]}\\|;:'\",<>/?"
30 | }
31 | },
32 | // Enable a development set of extensions for Lua and Quarto
33 | "extensions": ["quarto.quarto", "sumneko.lua", "GitHub.copilot"]
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/.github/workflows/publish-website.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches: [main, master]
4 | release:
5 | types: [published]
6 | workflow_dispatch: {}
7 |
8 | name: demo-website
9 |
10 | jobs:
11 | demo-website:
12 | runs-on: ubuntu-latest
13 | # Only restrict concurrency for non-PR jobs
14 | concurrency:
15 | group: quarto-publish-${{ 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 R"
26 | uses: r-lib/actions/setup-r@v2
27 |
28 | - name: "Setup R dependencies for Quarto's knitr engine"
29 | uses: r-lib/actions/setup-r-dependencies@v2
30 | with:
31 | packages:
32 | any::knitr
33 | any::rmarkdown
34 | any::downlit
35 | any::xml2
36 | any::reticulate
37 |
38 | # Setup Python for reticulate
39 | - uses: actions/setup-python@v5
40 | with:
41 | python-version: "3.x"
42 |
43 | # Install python dependencies for reticulate
44 | - name: Setup r-reticulate venv
45 | shell: Rscript {0}
46 | run: |
47 | path_to_python <- reticulate::virtualenv_create(
48 | envname = "r-reticulate",
49 | python = Sys.which("python"),
50 | requirements = "docs/requirements.txt"
51 | )
52 | writeLines(sprintf("RETICULATE_PYTHON=%s", path_to_python),
53 | Sys.getenv("GITHUB_ENV"))
54 |
55 |
56 | # Back to our regularly scheduled Quarto output
57 | - name: "Set up Quarto"
58 | uses: quarto-dev/quarto-actions/setup@v2
59 | with:
60 | version: "pre-release"
61 |
62 | # Install quarto extensions
63 | - name: "Install quarto extension for quarto-webr and quarto-pyodide"
64 | shell: bash
65 | run: |
66 | cd docs/
67 | quarto add --no-prompt coatless/quarto-webr
68 | quarto add --no-prompt coatless-quarto/pyodide
69 | cp -r ../_extensions/ _extensions
70 |
71 | - name: Publish to GitHub Pages (and render)
72 | uses: quarto-dev/quarto-actions/publish@v2
73 | with:
74 | target: gh-pages
75 | path: docs
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.luarc.json
2 | docs/_site/*
--------------------------------------------------------------------------------
/.quartoignore:
--------------------------------------------------------------------------------
1 | logo-panelize.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # panelize: Tabset Code Cells in Quarto
2 |
3 | The `quarto-panelize` extension allows you to tabbify existing code cells to show their source or add interactivity.
4 |
5 | ## Installation
6 |
7 | To install the `quarto-panelize` extension, follow these steps:
8 |
9 | 1. Enter a Quarto project.
10 |
11 | 2. Open your terminal inside the Quarto project.
12 |
13 | 3. Run the following command:
14 |
15 | ```bash
16 | quarto add coatless-quarto/panelize
17 | ```
18 |
19 | If you wish to make your code interactive, please install the following Quarto extensions:
20 |
21 | ```sh
22 | # For Python
23 | quarto add coatless-quarto/pyodide
24 |
25 | # For R
26 | quarto add coatless/quarto-webr
27 | ```
28 |
29 | These commands will download and install the extension as well as any dependencies under the `_extensions` subdirectory of your Quarto project. If you are using version control, ensure that you include this directory in your repository.
30 |
31 | ## Usage
32 |
33 | For each document, place the `panelize` filter in the document's header:
34 |
35 | ```yml
36 | filters:
37 | - panelize
38 | ```
39 |
40 | Then, wrap existing R or Python code cells using a `Div` and specify the a panelize class.
41 | Supported options include:
42 |
43 | | Class | Description |
44 | |---------------|-------------------------------------------------------------------------------------|
45 | | `.to-source` | Convert a code cell to show rendered output and its source. |
46 | | `.to-pyodide` | Convert code cell from static Python code to interactive Python code using Pyodide. |
47 | | `.to-webr` | Convert code cell from static R code to interactive R code using webR. |
48 |
49 |
50 | ### Display Source
51 |
52 | For example, if we have a code cell with R that we want to show its options, then we use:
53 |
54 | ```` md
55 | :::{.to-source}
56 | ```{r}
57 | #| echo: fenced
58 | #| eval: true
59 | 1 + 1
60 | ```
61 | :::
62 | ````
63 |
64 | This will generate output equivalent to:
65 |
66 | ```` md
67 | :::{.panel-tabset}
68 | ### Results
69 | ```{r}
70 | #| eval: true
71 | 1 + 1
72 | ```
73 | ### Source
74 | ```{{r}}
75 | #| eval: true
76 | 1 + 1
77 | ```
78 | :::
79 | ````
80 |
81 | ### Interactivity
82 |
83 | For creating a tabset that contains both rendered results and interactive option, modify the document header and place the desired extension filter **after** `panelize`, e.g.
84 |
85 | ```yml
86 | filters:
87 | - panelize
88 | - pyodide
89 | - webr
90 | ```
91 |
92 | > [!IMPORTANT]
93 | >
94 | > Order matters! Please make sure to place the filters after `panelize`.
95 | > Otherwise, the interactivity filter will *not* detect the code cell!
96 | >
97 |
98 | Next, wrap the existing code cell using a `Div` with a class of either `.to-pyodide` or `.to-webr`.
99 |
100 | For Python, that looks like:
101 |
102 | ````md
103 | :::{.to-pyodide}
104 | ```{python}
105 | 4 + 5
106 | ```
107 | :::
108 | ````
109 |
110 | For R, that looks like:
111 |
112 | ````md
113 | :::{.to-webr}
114 | ```{r}
115 | 1 + 1
116 | ```
117 | :::
118 | ````
119 |
120 | ## Acknowledgements
121 |
122 | Thanks to [@mcanouil](https://github.com/mcanouil) and [@cscheid](https://github.com/cscheid) who provided great insight into approaching this problem by re-orienting it in a way that is more managable. Please see the [full discussion](https://github.com/quarto-dev/quarto-cli/discussions/9646).
--------------------------------------------------------------------------------
/_extensions/panelize/_extension.yml:
--------------------------------------------------------------------------------
1 | name: panelize
2 | title: Panelize code cells
3 | author: James Joseph Balamuta
4 | version: 0.0.2-dev.1
5 | quarto-required: ">=1.4.554"
6 | contributes:
7 | filters:
8 | - panelize.lua
--------------------------------------------------------------------------------
/_extensions/panelize/panelize.lua:
--------------------------------------------------------------------------------
1 | -- Define helper types for clarity
2 | ---@class Block
3 | ---@field t string The type of the block
4 | ---@field attr table Block attributes
5 | ---@field content? table Block content
6 | ---@field classes table List of classes
7 | ---@field text? string Block text if CodeBlock
8 |
9 | ---@class Cell
10 | ---@field code_blocks Block[] List of code blocks
11 | ---@field outputs Block[] List of output blocks
12 | ---@field language string Programming language
13 |
14 | ---@class DocumentMetadata
15 | ---@field panelize table Configuration options
16 | ---@field handler_added boolean Flag for handler addition
17 |
18 | -- Store metadata at module level
19 | ---@type DocumentMetadata
20 | local document_metadata = {
21 | panelize = {},
22 | handler_added = false
23 | }
24 |
25 | -- Helper function to detect language from a code block
26 | ---@param block Block The code block to analyze
27 | ---@return string|nil language The detected language
28 | local function detect_language(block)
29 | if block.attr.classes:includes("r") then
30 | return "r"
31 | elseif block.attr.classes:includes("python") then
32 | return "python"
33 | elseif block.text:match("^```{{r") then
34 | return "r"
35 | elseif block.text:match("^```{{python") then
36 | return "python"
37 | end
38 | return nil
39 | end
40 |
41 | -- Helper function to clean code block text
42 | ---@param block Block The code block to clean
43 | ---@param language string The programming language
44 | ---@param remove_fences boolean Whether to remove code fences and options
45 | ---@return string cleaned_text The processed text
46 | local function clean_code_text(block, language, remove_fences)
47 | local text = block.text
48 | if remove_fences then
49 | if text:match("^```{{" .. language .. "}") then
50 | text = text:gsub("```{{" .. language .. "}}\n", ""):gsub("\n```", "")
51 | end
52 | text = text:gsub("#|.-\n", "")
53 | end
54 | return text
55 | end
56 |
57 | -- Helper function to extract cell content
58 | ---@param cell_div Block The cell div block
59 | ---@return Cell cell The processed cell content
60 | local function extract_cell_content(cell_div)
61 | local cell = {
62 | blocks = {}, -- Will store alternating code blocks and their outputs
63 | language = nil
64 | }
65 |
66 | -- Process blocks in sequence
67 | for _, block in ipairs(cell_div.content) do
68 | if block.t == "CodeBlock" and block.classes:includes("cell-code") then
69 | table.insert(cell.blocks, {type = "code", content = block})
70 | -- Detect language from first code block if not already set
71 | if not cell.language then
72 | cell.language = detect_language(block)
73 | end
74 | elseif block.t == "Div" and (
75 | block.classes:includes("cell-output") or
76 | block.classes:includes("cell-output-stdout") or
77 | block.classes:includes("cell-output-display")
78 | ) then
79 | table.insert(cell.blocks, {type = "output", content = block})
80 | end
81 | end
82 |
83 | return cell
84 | end
85 |
86 | -- Helper function to create tab content
87 | ---@param cell Cell The cell content
88 | ---@param tab_type string The type of tab ("result", "source", or "interactive")
89 | ---@return pandoc.List content The tab content
90 | local function create_tab_content(cell, tab_type)
91 | local content = pandoc.List()
92 |
93 | if tab_type == "interactive" then
94 | -- For interactive tab, combine all code blocks into one
95 | local combined_code = table.concat(
96 | pandoc.List(cell.blocks)
97 | :filter(function(block) return block.type == "code" end)
98 | :map(function(block) return clean_code_text(block.content, cell.language, true) end),
99 | "\n"
100 | )
101 |
102 | -- Create single code block with appropriate classes
103 | local classes = cell.language == "r" and {"{webr-r}", "cell-code"} or {"{pyodide-python}", "cell-code"}
104 | local attr = pandoc.Attr("", classes, {})
105 | content:insert(pandoc.CodeBlock(combined_code, attr))
106 | else
107 | -- For result and source tabs, process blocks in sequence
108 | for _, block in ipairs(cell.blocks) do
109 | if block.type == "code" then
110 | if tab_type == "result" then
111 | -- For result tab, clean code but keep language class
112 | local new_attr = block.content.attr:clone()
113 | new_attr.classes = pandoc.List({cell.language})
114 | local cleaned_text = clean_code_text(block.content, cell.language, true)
115 | content:insert(pandoc.CodeBlock(cleaned_text, new_attr))
116 | else
117 | -- For source tab, use original code block
118 | content:insert(block.content)
119 | end
120 | else -- output block
121 | content:insert(block.content)
122 | end
123 | end
124 | end
125 |
126 | return content
127 | end
128 |
129 | -- Process metadata
130 | function Meta(meta)
131 | if meta and meta.panelize then
132 | for key, value in pairs(meta.panelize) do
133 | document_metadata.panelize[key] = pandoc.utils.stringify(value)
134 | end
135 | end
136 | return meta
137 | end
138 |
139 | -- Main processing function for divs
140 | function Div(div)
141 | -- Check for required classes
142 | local to_webr = div.classes:includes("to-webr")
143 | local to_pyodide = div.classes:includes("to-pyodide")
144 | local to_source = div.classes:includes("to-source")
145 |
146 | if not (to_source or to_webr or to_pyodide) then
147 | return div
148 | end
149 |
150 | -- Find cell div
151 | local cell_div = nil
152 | for _, block in ipairs(div.content) do
153 | if block.t == "Div" and block.classes:includes("cell") then
154 | cell_div = block
155 | break
156 | end
157 | end
158 |
159 | if not cell_div then
160 | return div
161 | end
162 |
163 | -- Extract cell content
164 | local cell = extract_cell_content(cell_div)
165 |
166 | if not cell.language then
167 | quarto.log.error("Please specify either R or Python code cells inside of the .to-* div.")
168 | return div
169 | end
170 |
171 | -- Create tabs
172 | local tabs = pandoc.List()
173 |
174 | if to_webr or to_pyodide then
175 | -- Interactive environment tabs
176 | tabs:insert(quarto.Tab({
177 | title = "Result",
178 | content = pandoc.Blocks(create_tab_content(cell, "result"))
179 | }))
180 | tabs:insert(quarto.Tab({
181 | title = "Interactive",
182 | content = pandoc.Blocks(create_tab_content(cell, "interactive"))
183 | }))
184 | else
185 | -- Source code tabs
186 | tabs:insert(quarto.Tab({
187 | title = "Result",
188 | content = pandoc.Blocks(create_tab_content(cell, "result"))
189 | }))
190 | tabs:insert(quarto.Tab({
191 | title = "Source",
192 | content = pandoc.Blocks(create_tab_content(cell, "source"))
193 | }))
194 | end
195 |
196 | -- Return just the tabset, replacing the original div
197 | return quarto.Tabset({
198 | level = 3,
199 | tabs = tabs,
200 | attr = pandoc.Attr("", {"panel-tabset"}, {})
201 | })
202 | end
203 |
204 | -- Return the list of functions to register
205 | return {
206 | {Meta = Meta},
207 | {Div = Div}
208 | }
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | /.quarto/
2 |
--------------------------------------------------------------------------------
/docs/_quarto.yml:
--------------------------------------------------------------------------------
1 | project:
2 | type: website
3 |
4 | website:
5 | title: "panelize"
6 | reader-mode: true
7 | repo-url: https://github.com/coatless-quarto/panelize/
8 | repo-actions: [edit, issue]
9 | sidebar:
10 | style: "floating"
11 | search: true
12 | tools:
13 | - icon: github
14 | href: https://github.com/coatless-quarto/panelize/
15 | contents:
16 | - text: "Home"
17 | file: index.qmd
18 | - text: "Install"
19 | file: qpanelize-install.qmd
20 | - section: "Panelize Demos"
21 | contents:
22 | - text: "Code Cells"
23 | href: qpanelize-cell.qmd
24 | - text: "Python to Pyodide"
25 | href: qpanelize-pyodide.qmd
26 | - text: "R to webR"
27 | href: qpanelize-webr.qmd
28 | - section: "Support"
29 | contents:
30 | - text: "Submit an issue"
31 | href: https://github.com/coatless-quarto/panelize/issues/new/choose
32 | - section: "Extra"
33 | contents:
34 | - qpanelize-release-notes.qmd
35 |
36 | format:
37 | html:
38 | toc: true
39 |
40 | engine: knitr
--------------------------------------------------------------------------------
/docs/index.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Home"
3 | format:
4 | html:
5 | toc: false
6 | engine: knitr
7 | filters:
8 | - panelize
9 | ---
10 |
11 | The `panelize` extension allows you to tabbify existing code cells. The supported options include:
12 |
13 | | Class | Description |
14 | |---------------|-------------------------------------------------------------------------------------|
15 | | `.to-source` | Convert a code cell to show rendered output and its source. |
16 | | `.to-pyodide` | Convert code cell from static Python code to interactive Python code using Pyodide. |
17 | | `.to-webr` | Convert code cell from static R code to interactive R code using webR. |
18 |
19 | You can wrap existing code cells using a `Div` and specify the class. For example, with Python we would have:
20 |
21 | ```` md
22 | :::{.to-source}
23 | ```{{python}}
24 | #| echo: fenced
25 | #| eval: true
26 | x = [1, 2]
27 | print(x)
28 | ```
29 | :::
30 | ````
31 |
32 | This will generate output equivalent to:
33 |
34 | ````md
35 | :::{.panel-tabset}
36 | ### Results
37 | ```{{python}}
38 | #| echo: fenced
39 | #| eval: true
40 | x = [1, 2]
41 | print(x)
42 | ```
43 | ### Source
44 | ```{{{python}}}
45 | #| eval: true
46 | x = [1, 2]
47 | print(x)
48 | ```
49 | :::
50 | ````
51 |
--------------------------------------------------------------------------------
/docs/qpanelize-cell.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Display Code Cell Source Separately"
3 | format: html
4 | filters:
5 | - panelize
6 | ---
7 |
8 | For example, let's take the following code cell using the [fenced](https://quarto.org/docs/computations/execution-options.html#fenced-echo) output to ensure options are passed forward.
9 |
10 | ````md
11 | ```{{r}}
12 | #| echo: fenced
13 | #| eval: true
14 | 1 + 1
15 |
16 | plot(1:10)
17 | ```
18 | ````
19 |
20 | Using the **{quarto-panelize}** extension, you can show the code cell and its output together in one tab, and separately display the source of the code cell with nearly all options (minus `echo`) in another tab tab. Here's how it can be done:
21 |
22 | ````md
23 | :::{.to-source}
24 | ```{{r}}
25 | #| echo: fenced
26 | #| eval: true
27 | 1 + 1
28 |
29 | plot(1:10)
30 | ```
31 | :::
32 | ````
33 |
34 | This will create two tabs: Result and Source.
35 |
36 | :::{.to-source}
37 |
38 | ```{r}
39 | #| echo: fenced
40 | #| eval: true
41 | 1 + 1
42 |
43 | plot(1:10)
44 | ```
45 |
46 | :::
47 |
48 | Without setting `echo: fenced`, the Source tab will only display the code without results.
49 |
50 | :::{.to-source}
51 |
52 |
53 | ```{r}
54 | #| eval: true
55 | 1 + 1
56 |
57 | plot(1:10)
58 | ```
59 |
60 | :::
61 |
62 |
--------------------------------------------------------------------------------
/docs/qpanelize-install.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Install the Extension"
3 | format: html
4 | filters:
5 | - panelize
6 | ---
7 |
8 | To install the `quarto-panelize` extension, follow these steps:
9 |
10 | 1. Enter a Quarto project.
11 |
12 | 2. Open your terminal inside the Quarto project.
13 |
14 | 3. Run the following command:
15 |
16 | ```bash
17 | quarto add coatless-quarto/panelize
18 | ```
19 |
20 | This command will download and install the extension under the `_extensions` subdirectory of your Quarto project. If you are using version control, ensure that you include this directory in your repository.
21 |
22 | ## Interactivity
23 |
24 | If you wish to use the interactive feature, please make sure to install the following Quarto extensions:
25 |
26 | ### Python
27 |
28 | For interactivity with Python, please type into Terminal:
29 |
30 | ```sh
31 | quarto add coatless-quarto/pyodide
32 | ```
33 |
34 | Please make sure that `panelize` is placed before `pyodide` in the document header `filters` statement, e.g.
35 |
36 | ```yml
37 | ---
38 | filters:
39 | - panelize
40 | - pyodide
41 | ---
42 | ```
43 |
44 | ### R
45 |
46 | For interactivity with R, please type into Terminal:
47 |
48 | ```sh
49 | quarto add coatless/quarto-webr
50 | ```
51 |
52 | Please make sure that `panelize` is placed before `webr` in the document header `filters` statement, e.g.
53 |
54 | ```yml
55 | ---
56 | filters:
57 | - panelize
58 | - webr
59 | ---
60 | ```
61 |
62 |
--------------------------------------------------------------------------------
/docs/qpanelize-pyodide.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Python to Interactive Python"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - panelize
7 | - pyodide
8 | ---
9 |
10 | # Overview
11 |
12 | We can use **{quarto-panelize}** to take a usual Python code cell and convert it into an interactive cell powered by [Pyodide](https://pyodide.org/en/stable/). In this guide, we'll walk through the steps!
13 |
14 | ## Code Cell
15 |
16 | For example, let's take the following Python cell:
17 |
18 | ````md
19 | ```{{python}}
20 | x = [1, 2]
21 | print(x)
22 | ```
23 | ````
24 |
25 | ## Document Header modification
26 |
27 | Next, in our document header, we need to specify both the `panelize` and `pyodide` filters under the `filters` key, e.g.
28 |
29 |
30 | ````md
31 | ---
32 | title: "My title"
33 | format: html
34 | filters:
35 | - panelize
36 | - pyodide
37 | ---
38 | ````
39 |
40 | :::{.callout-important}
41 | The order matters! Please make sure `panelize` comes before `pyodide`. Otherwise, the `pyodide` filter will _not_ see the code cell.
42 | :::
43 |
44 | You will also need to have the `{quarto-pyodide}` extension installed by typing in Terminal:
45 |
46 | ````sh
47 | quarto add coatless-quarto/pyodide
48 | ````
49 |
50 | ## Wraping the code cell
51 |
52 | Next, we use a special class called `.to-pyodide` inside of a Div denoted by `:::` around a usual R code cell, e.g.
53 |
54 | ````md
55 | :::{.to-pyodide}
56 | ```{{python}}
57 | x = [1, 2]
58 | print(x)
59 | ```
60 | :::
61 | ````
62 |
63 | This allows us to ensure the computational order is maintained when translating from R to a `{quarto-webr}` code cell.
64 |
65 | ## Result
66 |
67 | As a result, we now have access to two tabs: Result and Interactive.
68 |
69 | :::{.to-pyodide}
70 | ```{python}
71 | x = [1, 2]
72 | print(x)
73 | ```
74 | :::
75 |
76 | ### Graphs
77 |
78 | We can also use the same approach for plotting graphs, e.g.
79 |
80 | :::{.to-pyodide}
81 | ```{python}
82 | import matplotlib.pyplot as plt
83 |
84 | x = [1, 2, 3, 4, 5]
85 | y = [1, 4, 9, 16, 25]
86 |
87 | plt.plot(x, y)
88 | plt.show()
89 | ```
90 | :::
91 |
92 | ### Multiline
93 |
94 | We can also use the same approach for multiline code cells, e.g.
95 |
96 | :::{.to-pyodide}
97 | ```{python}
98 | x = list(range(1, 11))
99 | x
100 |
101 | y = [i**2 for i in x]
102 | y
103 |
104 | import matplotlib.pyplot as plt
105 |
106 | x = [1, 2, 3, 4, 5]
107 | y = [1, 4, 9, 16, 25]
108 |
109 | plt.plot(x, y)
110 | plt.show()
111 | ```
112 | :::
113 |
--------------------------------------------------------------------------------
/docs/qpanelize-release-notes.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Release Notes"
3 | date: "05-16-2024"
4 | date-modified: last-modified
5 | engine: markdown
6 | format:
7 | html:
8 | toc: true
9 | ---
10 |
11 | # 0.0.2-dev.1: ???? (??-??-????)
12 |
13 | ## Features
14 |
15 | ## Bug fixes
16 |
17 |
18 | # 0.0.2: Playful Graphs (02-04-2024)
19 |
20 | ## Features
21 |
22 | - Graphs can now be displayed in the `panelize` extension.
23 |
24 | ## Bug fixes
25 |
26 | - Fixed a bug where the `panelize` extension was not allow for multiple outputs to be shown in rendered results and interactive code chunks.
27 |
28 | ## Documentation
29 |
30 | - Added examples for displaying graphs and multiline code cells in the `panelize` extension.
31 |
32 | # 0.0.1: Interactive Polyglot (06-11-2024)
33 |
34 | ## Features
35 |
36 | - `panelize` allows for Quarto code cells to be tabbified.
37 | - `.to-source`: converts an existing code cell also show its source with options.
38 | - `.to-pyodide`: converts a Python cell to Python
39 | - `.to-webr`: converts an R code cell to webR
40 |
--------------------------------------------------------------------------------
/docs/qpanelize-webr.qmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "R to Interactive R"
3 | format: html
4 | engine: knitr
5 | filters:
6 | - panelize
7 | - webr
8 | ---
9 |
10 | # Overview
11 |
12 | We can use **{quarto-panelize}** to take a usual R code cell and convert it into an interactive cell powered by [webR](https://docs.r-wasm.org/). In this guide, we'll walk through the steps!
13 |
14 | ## Code Cell
15 |
16 | For example, let's take the following R cell:
17 |
18 | ````md
19 | ```{{r}}
20 | 1 + 1
21 | ```
22 | ````
23 |
24 | ## Document Header modification
25 |
26 | Next, in our document header, we need to specify both the `panelize` and `webr` filters under the `filters` key, e.g.
27 |
28 |
29 | ````md
30 | ---
31 | title: "My title"
32 | format: html
33 | filters:
34 | - panelize
35 | - webr
36 | ---
37 | ````
38 |
39 | :::{.callout-important}
40 | The order matters! Please make sure `panelize` comes before `webr`. Otherwise, the `webr` filter will _not_ see the code cell.
41 | :::
42 |
43 | You will also need to have the `{quarto-webr}` extension installed by typing in Terminal:
44 |
45 | ````sh
46 | quarto add coatless/quarto-webr
47 | ````
48 |
49 | ## Wraping the code cell
50 |
51 | Next, we use a special class called `.to-webr` inside of a Div denoted by `:::` around a usual R code cell, e.g.
52 |
53 | ````md
54 | :::{.to-webr}
55 | ```{{r}}
56 | 1 + 1
57 | ```
58 | :::
59 | ````
60 |
61 | This allows us to ensure the computational order is maintained when translating from R to a `{quarto-webr}` code cell.
62 |
63 | ## Result
64 |
65 | As a result, we now have access to two tabs: Result and Interactive.
66 |
67 | :::{.to-webr}
68 | ```{r}
69 | 1 + 1
70 | ```
71 | :::
72 |
73 | The `Result` tab shows the output of the code cell, while the `Interactive` tab allows us to interact with the code cell.
74 |
75 | ### Graphs
76 |
77 | We can also use the same approach for plotting graphs, e.g.
78 |
79 | :::{.to-webr}
80 | ```{r}
81 | plot(1:10)
82 | ```
83 | :::
84 |
85 | ### Multiline
86 |
87 | We can also use the same approach for multiline code cells, e.g.
88 |
89 | :::{.to-webr}
90 | ```{r}
91 | x <- 1:10
92 | x
93 |
94 | y <- x^2
95 | y
96 |
97 | plot(x, y)
98 | ```
99 | :::
100 |
101 |
102 | ## Autorun Code
103 |
104 | You may wish to allow the interactive cells to be automatically run when the document opens by specifying in the document header:
105 |
106 | ```yml
107 | ---
108 | title: "My title"
109 | format: html
110 | webr:
111 | cell-options:
112 | autorun: true
113 | filters:
114 | - panelize
115 | - webr
116 | ---
117 | ```
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | matplotlib
2 |
--------------------------------------------------------------------------------
/logo-panelize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/coatless-quarto/panelize/788385fc7bc9cb754f2965792190e03d22d1c46b/logo-panelize.png
--------------------------------------------------------------------------------
/panelize.code-workspace:
--------------------------------------------------------------------------------
1 | {
2 | "folders": [
3 | {
4 | "path": "."
5 | }
6 | ],
7 | "settings": {}
8 | }
--------------------------------------------------------------------------------