├── README.md ├── webr-quarto-html-demo.html ├── webr-quarto-html-demo.qmd ├── webr-serviceworker.js └── webr-worker.js /README.md: -------------------------------------------------------------------------------- 1 | # webR-quarto-demos 2 | 3 | This repository houses experiments with generating a standalone [Quarto Document](https://quarto.org/) using [WebR](https://docs.r-wasm.org/webr/latest/). 4 | 5 | - [Proof of Concept: Quarto HTML Document with WebR](https://rd.thecoatlessprofessor.com/webR-quarto-demos/webr-quarto-html-demo.html) ([Source](webr-quarto-html-demo.qmd)) 6 | 7 | You can create WebR-powered Quarto code cells using the [`quarto-webr`](https://github.com/coatless/quarto-webr) extension: 8 | 9 | 10 | 11 | ## Background 12 | 13 | [WebR v0.1.0](https://twitter.com/gwstagg/status/1633821049329537025) was launched on March 9th 14 | by George Stagg ([georgestagg](https://github.com/georgestagg)) and Lionel Henry ([lionel-](https://github.com/lionel-)). The goal of webR is to: 15 | 16 | > run R code in the browser without the need for an R server to execute the code 17 | 18 | This is an _amazing_ advancement of _R_ and has major implications with teaching R to the masses in an active learning context! 19 | 20 | ## Acknowledgements 21 | 22 | This repository leans _heavily_ on the webR developers public-facing examples: 23 | 24 | - [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) 25 | - [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/)) 26 | -------------------------------------------------------------------------------- /webr-quarto-html-demo.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "webR with Quarto HTML Standalone Document Proof of Concept" 3 | subtitle: "Experiments with an Interactive Quarto Document using webR v0.1.0" 4 | author: "JJB leaning heavily on webR authors" 5 | engine: knitr 6 | execute: 7 | echo: true 8 | error: true 9 | embed-resources: true 10 | format: 11 | html: 12 | toc: true 13 | editor: source 14 | --- 15 | 16 | # Demo 17 | 18 | ## Background 19 | 20 | The purpose of this document is to explore how WebR can be embedded in a 21 | Quarto Document for the purposes of teaching _R_. 22 | 23 | - WebR Website: 24 | - WebR GitHub: 25 | 26 | ## Setup 27 | 28 | See the for source. 29 | 30 | ```{=html} 31 | 32 | 42 | 43 | 44 | 56 | ``` 57 | 58 | ```{r} 59 | #| results: asis 60 | #| echo: false 61 | webr_counter = 0 62 | 63 | cat("importScripts('https://webr.r-wasm.org/v0.1.0/webr-worker.js');", file = "webr-worker.js") 64 | cat("importScripts('https://webr.r-wasm.org/v0.1.0/webr-serviceworker.js');", file = "webr-serviceworker.js") 65 | 66 | webr_editor = function(code = I(encodeString(code, quote = '`')), width, height) { 67 | webr_counter <<- webr_counter + 1 68 | 69 | output = glue::glue(' 70 | 71 |
72 |
73 | 148 | ', .open = "{{", .close = "}}") 149 | } 150 | ``` 151 | 152 | ```{r} 153 | #| echo: false 154 | knitr::knit_engines$set(webr = function(options) { 155 | code = paste(options$code, collapse = "\n") 156 | w = knitr::opts_current$get('fig.width') * 72 157 | h = knitr::opts_current$get('fig.height') * 72 158 | options$results = 'asis' 159 | 160 | form = webr_editor(code = I(encodeString(code, quote = '`')), width = w, height = h) 161 | 162 | form 163 | } 164 | ) 165 | ``` 166 | 167 | ## Exploration 168 | 169 | Next, let's look at a few features of the language 170 | 171 | ### Linear Regression 172 | 173 | We'll first start with the WebR team's demo example or the statistician way of 174 | saying, "Hello world!"... Aka linear regression: 175 | 176 | ```{webr} 177 | fit = lm(mpg ~ am, data=mtcars) 178 | summary(fit) 179 | ``` 180 | 181 | ### Retrieving prior objects 182 | 183 | Each WebR cell appears to be connected to each other. Thus, we can access the 184 | `fit` outcome: 185 | 186 | ```{webr} 187 | coef(fit) 188 | ``` 189 | 190 | ```{webr} 191 | anova(fit) 192 | ``` 193 | 194 | ### Mixing active and non-active _R_ code 195 | 196 | For _if-else_ statements, we have: 197 | 198 | ```r 199 | if (...) { 200 | # Statements for TRUE 201 | } else { 202 | # Statements for FALSE 203 | } 204 | ``` 205 | 206 | - `...` denotes a condition (either `TRUE` or `FALSE`) 207 | - If `TRUE`, then run the statements inside `{}` 208 | - Else, `FALSE`, carry on with your day. 209 | 210 | How could we modify `temperature` to have the `if` statement print `"Hot!"`? 211 | 212 | ```{webr} 213 | # Let's classify 214 | temperature = 60 215 | 216 | if (temperature > 76) { 217 | print("Hot!") 218 | } else { 219 | print("Cold!") 220 | } 221 | ``` 222 | 223 | 224 | ### Summarize Data 225 | 226 | Glancing at data frames yields: 227 | 228 | ```{webr} 229 | summary(mtcars) 230 | ``` 231 | 232 | ### Errors and Warnings 233 | 234 | 235 | ```{webr} 236 | stop("What happens if an error is present?") 237 | ``` 238 | 239 | ```{webr} 240 | warning("You shouldn't be here...") 241 | ``` 242 | 243 | 244 | ### Base graphics 245 | 246 | Graphing with base R 247 | 248 | ```{webr} 249 | plot(pressure) 250 | ``` 251 | 252 | More advanced base R graphing... 253 | 254 | ```{webr} 255 | x1 = seq(0, 1, length = 20) 256 | y1 = rep(0, 20) 257 | x2 = rep(0, 20) 258 | y2 = seq(0.75, 0, length = 20) 259 | 260 | plot(0, type = "n", 261 | axes = FALSE, ylab = "", xlab = "", 262 | xlim = c(0, 1), ylim = c(0, 0.75), asp = 1, 263 | main = "Straight Lines as a Curve") 264 | 265 | segments(x1, y1, x2, y2) 266 | box(col = "grey") 267 | ``` 268 | 269 | ### ggplot2 Graphics 270 | 271 | Next, we look at using `ggplot2` graphics. By default, the `ggplot2` package 272 | is not available as it is _dependency_ heavy. 273 | 274 | ```{=html} 275 |
276 | 277 | Package installation for `ggplot2` given by `webr::install("ggplot2")` 278 | 279 | Downloading webR package: cli 280 | Downloading webR package: glue 281 | Downloading webR package: gtable 282 | Downloading webR package: isoband 283 | Downloading webR package: rlang 284 | Downloading webR package: lifecycle 285 | Downloading webR package: MASS 286 | Downloading webR package: lattice 287 | Downloading webR package: nlme 288 | Downloading webR package: Matrix 289 | Downloading webR package: mgcv 290 | Downloading webR package: farver 291 | Downloading webR package: labeling 292 | Downloading webR package: colorspace 293 | Downloading webR package: munsell 294 | Downloading webR package: R6 295 | Downloading webR package: RColorBrewer 296 | Downloading webR package: viridisLite 297 | Downloading webR package: scales 298 | Downloading webR package: fansi 299 | Downloading webR package: magrittr 300 | Downloading webR package: utf8 301 | Downloading webR package: vctrs 302 | Downloading webR package: pillar 303 | Downloading webR package: pkgconfig 304 | Downloading webR package: tibble 305 | Downloading webR package: withr 306 | Downloading webR package: ggplot2 307 |
308 | ``` 309 | 310 | ```{webr} 311 | # Install non-base R packages 312 | webr::install("ggplot2") 313 | # Load non-base packages like normal 314 | library("ggplot2") 315 | p = ggplot(mpg, aes(class, hwy)) 316 | p + geom_boxplot() 317 | ``` 318 | 319 | 320 | 321 | -------------------------------------------------------------------------------- /webr-serviceworker.js: -------------------------------------------------------------------------------- 1 | importScripts('https://webr.r-wasm.org/v0.1.0/webr-serviceworker.js'); 2 | -------------------------------------------------------------------------------- /webr-worker.js: -------------------------------------------------------------------------------- 1 | importScripts('https://webr.r-wasm.org/v0.1.0/webr-worker.js'); 2 | --------------------------------------------------------------------------------