Examples

---
title: Area of a circle
---

Define the radius as `x`:

```{r}
x = 1 + 1
```

When the radius is `{r} x`, the area will be `{r} pi * x^2`.
---
title: The `attr.*` chunk options
---

1. Add an ID `#example-a` to the whole chunk.

2. Add line numbers to source blocks via the `.line-numbers` class.

3. Add the class `.round` to the first plot and set its width to 400px.

4. Add two classes `.dark` and `.img-center` to the second plot.

```{r}
#| example-a,
#| attr.chunk = '#example-a',
#| attr.source = '.line-numbers',
#| attr.plot = c('.round width="400"', '.dark .img-center'),
#| fig.alt = c('A scatterplot of rnorm(100) numbers.',
#|   'A sunflower plot of iris.')

plot(rnorm(100), rnorm(100))
i34 = iris[, 3:4]
smoothScatter(i34)
sunflowerplot(i34, add = TRUE)
```

Define CSS rules for the classes in the `#example-a` chunk:

```{css}
#example-a {
  .round { border: solid 1px; border-radius: 50%; }
  .dark  { filter: invert(1); }
  .img-center { display: block; margin: auto; }
}
```
---
title: Create a callout via the option `attr.chunk`
output:
  html:
    meta:
      css: ["@default", "@callout"]
      js: ["@callout"]
---

If you use the class name `.callout-*` on a chunk, you can turn it into a callout, e.g.,

```{r}
#| attr.chunk = '.callout-example'

1 + 1
```

Remember to load the `callout` CSS/JS assets in YAML.
---
title: Caption position
---

## Default caption positions

```{r, fig-bottom, fig.cap = 'Bottom figure caption.'}
plot(cars)
```

```{r, tab-top, tab.cap = 'Top table caption.'}
cars
```

## Change the positions

```{r, fig-top, fig.cap = 'Top figure caption.', cap.pos = 'top'}
plot(cars)
```

```{r, tab-bottom, tab.cap = 'Bottom table caption.', cap.pos = 'bottom'}
cars
```
---
title: The `code` option
---

Define a code template `tpl`:

```{r}
tpl    = 'lm(mpg ~ %s, data = mtcars) |> summary() |> coef()'
x_vars = names(mtcars)[2:4]
```

We run regressions on three variables one by one:

<!-- ... -->

```{r, code = sprintf(tpl, x_vars)}
```
---
title: Collapse source code and text output
---

By default, the source and output are in separate blocks:

```{r}
x = 1 + 1
x
x + 2
```

Set `collapse = TRUE` to collapse them:

```{r, collapse = TRUE}
x = 1 + 1
x
x + 100
```
---
title: The `comment` option
---

Use `#-> ` to comment out text output:

```{r, comment = '#-> ', print = NA}
matrix(1:12, 3)
```

Do not comment out text output:

```{r, comment = '', print = NA}
matrix(1:12, 3)
```
---
title: The graphics device
---

The default (png) device with a higher resolution:

```{r}
#| chunk-a, dev.args = list(res = 96),
#| fig.alt = 'png with a resolution of 96 ppi'

plot(cars)
```

The `svg` device with a background color:

```{r}
#| chunk-b, dev = 'svg', dev.args = list(bg = 'lightyellow'),
#| fig.alt = 'svg with a lightyellow background'

plot(cars)
```
---
title: Decorating figures
output:
  html:
    meta:
      css: ["@default", "@article"]
      js: ["@sidenotes"]
---

Place two plots side by side via the `width` attribute:

```{r}
#| chunk-a, attr.plot = 'width="45%"',
#| fig.alt = c('a histogram', 'a sunflower plot'),
#| fig.cap = 'Exploring the faithful dataset.',

hist(faithful$eruptions, main = '', border = 'white')
sunflowerplot(faithful)
```

A full-width figure (requires the `@article` CSS):

```{r}
#| chunk-b, fig.dim = c(14, 4), fig.env = '.figure .fullwidth',
#| fig.cap = 'Monthly mean relative sunspot numbers from 1749 to 1983.'
par(mar = c(4, 4, .1, .1), bg = 'lightyellow', fg = 'red', las = 1)
plot(sunspots, col = 'red')
grid()
```

Feel free to experiment with other class names provided by the `@article` CSS, such as `.side .side-right` or `.embed-right` in addition to `.fullwidth`.
---
title: Plot files
---

The default extension for the `jpeg()` device is `jpeg`, and you can change it to `.jpg` if desired:

```{r, chunk-a, dev = 'jpeg', fig.ext = '.jpg'}
plot(cars)
```

Set the plot size via `fig.dim`:

```{r, chunk-b, fig.dim = c(5, 4)}
plot(cars)
```

Write plot files to a different folder:

```{r, chunk-c, fig.path = 'figures/'}
plot(cars)
```
---
title: Shared chunk labels
---

```{r, chunk-a}
message("This chunk's label is chunk-a")
```

Repeat `chunk-a` but suppress the message:

```{r, chunk-a, message=FALSE}
```
---
title: Custom execution order
abstract: "We analyzed `{r, order = N + 1} nrow(x)` `{r} n_cyl`-cylinder cars, with an average MPG of `{r} m`."
---

Subset the data:

```{r}
n_cyl = 8
x = subset(mtcars, cyl == n_cyl)
```

The average MPG `{r} m` is calculated from:

```{r, order = i - 1.5}
m = mean(x$mpg)
```
---
title: Print objects
---

Print objects with `base::print()`, and use different arguments for different objects.

```{r}
#| print = NA,
#| print.args = list(table = list(zero.print = '.'),
#|   factor = list(quote = TRUE, max.levels = 3))

X = c('a', 'b', 'c', 'c', 'c', 'a')
Y = factor(c('A', 'B', 'C', 'C', 'D', 'E'))
Y  # factor

table(X, Y)  # table
```
This code chunk is not important for the `fiss()` output.

```{r, setup, purl = FALSE}
litedown::reactor(fig.height = 5)
```

This code chunk will be included in the script.

```{r}
if (TRUE) {
  x = 1 + 1
}
```
---
title: "Fill out references in code chunks"
---

Define `chunk-a` that includes a reference to `chunk-b`:

```{r, chunk-a, eval = FALSE, echo = FALSE}
x = runif(1); y = runif(1)
`<chunk-b>`
```

```{r, chunk-b, eval = FALSE, echo = FALSE}
if (x^2 + y^2 <= 1) {
  n = n + 1
}
```

```{r, echo = FALSE}
N = 10000
```

<!-- ... -->

Embed `chunk-a` in a function body:

```{r}
f = function() {
  n = 0
  for (i in 1:`{N}`) {
    `<chunk-a>`
  }
  n/`{N}` * 4
}
abs(f() - pi) <= 0.1  # is it close to pi?
```

We can generate code dynamically in any code chunk, not limited to R chunks, e.g.,

```{js, eval = FALSE, fill = xfun::tojson}
const data = `{ iris[1:5, 1:2] }`;
Object.keys(data);  // column names
```
---
title: Text output
---

Default verbatim output:

```{r, test-out}
cat('Hello _world_!\n')
```

Hide output:

```{r, test-out, results = FALSE}
```

Output as is:

```{r, test-out, results = 'asis'}
```
---
title: Blank lines in source code
---

Keep blank lines at the beginning/end:

<!-- ... -->

```{r, strip.white = FALSE}

# a blank line above
1 + 1
# and a blank line below

```
---
title: A simple table
---

See @tab:simple.

<!-- ... -->

```{r}
#| simple, tab.cap = 'First 3 rows of the `cars` data.',
head(cars, 3)
```
---
title: Printing verbosity
---

Default `verbose = 0`:

```{r, test}
1:5  # a visible value
x = 1 + 1  # invisible
for (i in 1:10) i^2  # for loop returns invisible NULL
y = x^2  # invisible
```

`verbose = 1` always prints the last value:

```{r, test, verbose = 1}
```

`verbose = 2` prints all invisible values (except for `NULL`):

```{r, test, verbose = 2}
```
---
title: Inline output
---

We know that $\pi = `{r} pi`$, and the first 3 letters are `{r} LETTERS[1:3]`. The first 3 variables of `mtcars` are `{r} xfun::join_words(names(mtcars)[1:3])`. You will not see this value `{r, eval = FALSE} 2 * pi`.

Some numbers:

```{r}
x = 1.23456789 * 10^c(0, 5, 6, 9, -6) * c(1, 1, -1, 1, 1)
sprintf('%f', x)
```

| n = signif/p = power | n = 3, p = 6 | n = 5/2/4/1/7 | p = 0/4/Inf/9/5 |
|-----------|-----------:|---------------------:|----------------------:|
| x_1       | `{r} x[1]` | `{r, signif=5} x[1]` | `{r, power=0}   x[1]` | 
| x_2 10^5  | `{r} x[2]` | `{r, signif=2} x[2]` | `{r, power=4}   x[2]` |
| x_3 10^6  | `{r} x[3]` | `{r, signif=4} x[3]` | `{r, power=Inf} x[3]` |
| x_4 10^9  | `{r} x[4]` | `{r, signif=1} x[4]` | `{r, power=9}   x[4]` |
| x_5 10^-6 | `{r} x[5]` | `{r, signif=7} x[5]` | `{r, power=5}   x[5]` |

An equation: $Y = 300 `{r, dollar = FALSE, signif = 1} x[3]`x$.
---
title: "Simple DataTables"
---

Add the CSS/JS assets from the [simple-datatables](https://github.com/fiduswriter/simple-datatables/) library:

```{r}
litedown::vest(css = '@npm/simple-datatables/dist/style', js = '@npm/simple-datatables')
```

There are two ways to render a table using the library. You can either pass the data as a JSON object:

```{js, type = 'module', fill = xfun::tojson}
new simpleDatatables.DataTable('#table-iris', {
  data: {
    headings: `{ names(iris) }`,
    data: `{ unname(iris)[1:20, ] }`
  },
  perPage: 5
});
```

<table id="table-iris"></table>

or generate the data to an HTML table first:

::: {#mtcars}
```{r, echo = FALSE}
I(mtcars[1:10, 1:5])
```
:::

and then initialize a simple data table.

```{js, type = 'module'}
new simpleDatatables.DataTable('#mtcars > table', {
  perPage: 1,
  perPageSelect: [1, 2, 4, 8, ['All', 0]]
});
```

022. Dygraphs (source: 022-dygraphs.Rmd)

---
title: "Dygraphs"
---

Add the CSS/JS assets from the [dygraphs](https://github.com/danvk/dygraphs) library:

```{r}
litedown::vest(css = '@npm/dygraphs/dist/dygraph', js = '@npm/dygraphs/dist/dygraph')
```

Show the yearly sunspots data (with a range selector):

```{r}
sunspot = cbind(Year = time(sunspot.year), Sunspots = sunspot.year)
```

```{js, type = 'module', fill = xfun::tojson}
const g = new Dygraph(
  document.getElementById('graph-sunspot'),
  `{ unname(sunspot) }`,
  {
    labels: `{ colnames(sunspot) }`,
    showRangeSelector: true
  }
);
// annotate the maximum
g.ready(() => g.setAnnotations([
  {
    series: `{ colnames(sunspot)[2] }`,
    x: `{ sunspot[which.max(sunspot[, 2]), 1] }`,
    shortText: "M",
    text: "Maximum number"
  }
]));
```

::: {#graph-sunspot style="width: 100%;"}
:::

Show two time series:

```{r}
deaths = cbind(Time = round(time(mdeaths), 2), Male = mdeaths, Female = fdeaths)
```

```{js, type = 'module', fill = xfun::tojson}
new Dygraph(
  document.getElementById('graph-deaths'),
  `{ unname(deaths) }`,
  {
    labels: `{ colnames(deaths) }`
  }
);
```

::: {#graph-deaths style="width: 100%;"}
:::

023. Leaflet (source: 023-leaflet.Rmd)

---
title: "Leaflet"
---

Add the CSS/JS assets from the [leaflet](https://leafletjs.com) library:

```{r}
litedown::vest(css = '@npm/leaflet/dist/leaflet', js = '@npm/leaflet')
```

```{r}
loc = c(41.2542491, -95.9728748)
theta = (1:12)/6 * pi
circles = data.frame(Lat = loc[1] + sin(theta)/1000, Lng = loc[2] + cos(theta)/1000)
```

Provide a fenced Div with the ID `unmc` as the map container, and create the map:

::: {#unmc style="height: 500px;"}
:::

```{js, type = 'module', fill = xfun::tojson}
const map = L.map('unmc').setView(`{ loc }`, 17);

// add a tile layer
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 21,
    attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);

// add a marker and bind a popup to it
const marker = L.marker(`{ loc }`).addTo(map);
marker.bindPopup("<b>UNMC</b><p>You can play badminton here.</p>");

// draw a circle of circles (lat/long from the data frame `circles`)
`{ unname(circles) }`.forEach(row => L.circle(row, {
  color: 'orangered', radius: 30,
  fillColor: 'lightskyblue', fillOpacity: 0.5
}).addTo(map));
```

024. Chart.js (source: 024-chart-js.Rmd)

---
title: "Chart.js"
---

Import the [chart.js](https://www.chartjs.org) library:

```{r}
litedown::vest(js = '@npm/chart.js')
```

Draw the chart with the `uspop` dataset:

```{js, type = 'module', fill = xfun::tojson}
const ctx = document.getElementById('uspop-polar');
new Chart(ctx, {
  type: 'polarArea',
  data: {
    labels: `{ time(uspop) }`,
    datasets: [{
      data: `{ uspop }`
    }]
  },
  options: {
    responsive: true,
    scales: {
      r: {
        pointLabels: {
          display: true,
          centerPointLabels: true
        }
      }
    },
    plugins: {
      legend: {
        display: false
      }
    }
  }
});
```

<canvas id="uspop-polar"></canvas>
---
title: "Test inline expressions"
---

A normal inline expression: `{r} pi`.

The knitr-style inline expressions are ignored by default: `r pi`.

An expression that spans multiple lines: `{r} pi +
1 -
1`.

When a line has leading spaces that are not meaningful,
 it should still work: `{r} pi`.

<!-- doesn't work when the next line has leading spaces, e.g., `{r} pi +
 1` -->

- An item.

  `{r} pi` (leading spaces are meaningful here)
  
  hi `{r} pi > 1 & FALSE`
   hi `{r} pi`
  
  <!-- doesn't work: hi `{r} pi +
  1` -->

      hi `{r} pi` (four spaces: this is a plain code block)
## Test Markdown options

```{r, test-a}
library(litedown)

# toc example
mkd <- c('# Header 1', 'p1', '## Header 2', 'p2')

mark(mkd, options = '+number_sections')
mark(mkd, options = '+number_sections+toc')

# hard_wrap example
mark('foo\nbar\n')
mark('foo\nbar\n', options = '+hardbreaks')

# latex math example
mkd <- c(
  '`$x$` is inline math $x$!', '', 'Display style:', '', '$$x + y$$', '',
  '\\begin{align}
a^{2}+b^{2} & = c^{2}\\\\
\\sin^{2}(x)+\\cos^{2}(x) & = 1
\\end{align}'
)

mark(mkd)
mark(mkd, options = '-latex_math')

# table example
mark('
First Header  | Second Header
------------- | -------------
Content Cell  | Content Cell
Content Cell  | Content Cell
')

# caption
mark('
| a | b |
|---|--:|
| A | 9 |

Table: A table _caption_.
')

# no table
mark('
First Header  | Second Header
------------- | -------------
Content Cell  | Content Cell
Content Cell  | Content Cell
', options = '-table')

# autolink example
mark('https://www.r-project.org/')
mark('https://www.r-project.org/', options = '-autolink')

# links and spans
mark('[a b](#){.red}')
mark('[a\nb](){.red}')

# strikethrough example
mark('~~awesome~~')
mark('~~awesome~~', options = '-strikethrough')

# superscript and subscript examples
mark('2^10^')
mark('2^10^', options = '-superscript')
mark('H~2~O')
mark('H~2~O', options = '-subscript')

# code blocks
mark('```r\n1 + 1;\n```')
mark('```{.r}\n1 + 1;\n```')
mark('```{.r .js}\n1 + 1;\n```')
mark('```{.r .js #foo}\n1 + 1;\n```')
mark('```{.r .js #foo style="background:lime;"}\n1 + 1;\n```')
mark('````\nA _code chunk_:\n\n```{r, echo=TRUE}\n1 + 1;\n```\n````')

# raw blocks
mark('```{=html}\n<p>raw HTML</p>\n```')
mark('```{=latex}\n\\textbf{raw LaTeX}\n```')

# fenced Divs
mark('::: foo\nasdf\n:::')
mark('::: {.foo .bar #baz style="color: red;"}\nasdf\n:::')

# smartypants example
mark('1/2 (c)')
mark('1/2 (c)', options = '+smartypants')

mkd <- paste(names(litedown:::pants), collapse = ' ')
mark(mkd, options = '+smartypants')

# filter out HTML tags
mkd = '<style>a {}</style><script type="text/javascript">console.log("No!");</script>\n[Hello](#)'
mark(mkd)
# tagfiler doesn't work: https://github.com/r-lib/commonmark/issues/15
# mark(mkd, options = 'tagfilter')
```

## The HTML output of above examples

```{r, test-b, results = 'asis'}
`<test-a>`
```
`results = 'hide'` should try to collapse output, e.g., merge the source blocks below:

```{r, results = 'hide'}
nrow(iris)
ncol(iris)
iris
```

Other types of output (such as messages) will interrupt the collapsed block:

```{r, results = 'hide'}
nrow(iris)
message(ncol(iris))
iris
```