diff --git a/_freeze/docs/authoring/article-layout/execute-results/html.json b/_freeze/docs/authoring/article-layout/execute-results/html.json index 4fedb0632f..1f33812c83 100644 --- a/_freeze/docs/authoring/article-layout/execute-results/html.json +++ b/_freeze/docs/authoring/article-layout/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "3577d066c9712067f7db52921545541e", + "hash": "2b9eef9bad651370cf2bc31beccf1fa0", "result": { "engine": "knitr", - "markdown": "---\ntitle: \"Article Layout\"\nformat: html\nreference-location: margin\ncitation-location: margin\naliases:\n - page-layout.html\n---\n\n## Overview\n\nQuarto supports a variety of page layout options that enable you to author content that:\n\n- Fills the main content region\n- Overflows the content region\n- Spans the entire page\n- Occupies the document margin\n- Uses landscape mode in paginated formats\n\nQuarto uses the concept of columns to describe page layout (e.g. the \"body\" column, the \"margin\" column, etc.). Below we'll describe how to arrange content into these columns. If you need to adjust the widths of the columns, see [Page Layout - Grid Customization](/docs/output-formats/page-layout.qmd#grid-customization).\n\nAll of the layout capabilities described in this document work for HTML and Typst output. Many also work for PDF and LaTeX output, though with some differences. See [Typst Layout] and [PDF/LaTeX Layout] for format-specific details.\n\n## Body Column\n\nBy default, elements are position in the body of the document and are allowed to span the content of the document, like the below.\n\n::: {.layout-example .column-body}\n.column-body\n:::\n\nBut if you'd like, you can extend content slightly outside the bounds of the body by creating a div with the .`column-body-outset` class. For example:\n\n``` markdown\n:::{.column-body-outset}\nOutset content...\n:::\n```\n\n::: {.layout-example .column-body-outset}\n.column-body-outset\n:::\n\n## Page Column\n\nIf you need even more space for your content, you can use the `.column-page` class to make the content much wider, though stopping short of extending across the whole document.\n\n::: {.layout-example .column-page}\n.column-page\n:::\n\nFor example, to create a wider image, you could use:\n\n``` markdown\n:::{.column-page}\n![](images/elephant.jpg)\n:::\n```\n\n::: column-page\n![](images/elephant.jpg){fig-alt=\"Three walking elephants in silhouette against the backdrop of a sunset.\"}\n:::\n\nFor computational output, you can specify the page column in your code cell options. For example:\n\n\n::: {.cell .column-page}\n\n````{.cell-code}\n```{{r}}\n#| column: page\n\nknitr::kable(\n mtcars[1:6, 1:10]\n)\n```\n````\n\n::: {.cell-output-display}\n\n\n| | mpg| cyl| disp| hp| drat| wt| qsec| vs| am| gear|\n|:-----------------|----:|---:|----:|---:|----:|-----:|-----:|--:|--:|----:|\n|Mazda RX4 | 21.0| 6| 160| 110| 3.90| 2.620| 16.46| 0| 1| 4|\n|Mazda RX4 Wag | 21.0| 6| 160| 110| 3.90| 2.875| 17.02| 0| 1| 4|\n|Datsun 710 | 22.8| 4| 108| 93| 3.85| 2.320| 18.61| 1| 1| 4|\n|Hornet 4 Drive | 21.4| 6| 258| 110| 3.08| 3.215| 19.44| 1| 0| 3|\n|Hornet Sportabout | 18.7| 8| 360| 175| 3.15| 3.440| 17.02| 0| 0| 3|\n|Valiant | 18.1| 6| 225| 105| 2.76| 3.460| 20.22| 1| 0| 3|\n\n\n:::\n:::\n\n\nIn addition, you can use `.column-page-inset` to inset the element from the page slightly, like so:\n\n::: {.layout-example .column-page-inset}\n.column-page-inset\n:::\n\n## Screen Column\n\nYou can have content span the full width of the page with no margin (full bleed). For this, use the `.column-screen` class or specify `column: screen` on a code cell. For example:\n\n``` md\n::: {.column-screen}\n![A full screen image](/image.png)\n:::\n```\n\n::: {.layout-example .column-screen}\n.column-screen\n:::\n\nThe following code displays a Leaflet map across the whole page.\n\n\n::: {.cell .column-screen}\n\n````{.cell-code}\n```{{r}}\n#| column: screen\n\nlibrary(leaflet)\nleaflet() %>%\n addTiles() %>% # Add default OpenStreetMap map tiles\n addMarkers(lng=174.768, lat=-36.852, popup=\"The birthplace of R\")\n```\n````\n\n::: {.cell-output-display}\n\n```{=html}\n
\n\n```\n\n:::\n:::\n\n\n### Screen Inset\n\nIf you'd like a full width appearance, but would like to retain a margin, you can use inset or inset-shaded modifiers on the column. For example:\n\n``` md\n::: {.column-screen-inset}\n![A full screen image](/image.png)\n:::\n```\n\n::: {.layout-example .column-screen-inset}\n.column-screen-inset\n:::\n\nThe inset-shaded modifier results in a block spanning the full width but wrapped with a lightly shaded background. For example:\n\n\n::: {.cell .column-screen-inset-shaded}\n\n````{.cell-code}\n```{{r}}\n#| column: screen-inset-shaded\n\nlibrary(leaflet)\nleaflet() %>%\n addTiles() %>% # Add default OpenStreetMap map tiles\n addMarkers(lng=174.768, lat=-36.852, popup=\"The birthplace of R\")\n```\n````\n\n::: {.cell-output-display}\n\n```{=html}\n
\n\n```\n\n:::\n:::\n\n\nColumn layouts like `screen-inset-shaded` will work with advanced figure layout. For example, it is straightforward to create a multi column presentation of figures that spans the document:\n\n\n::: {.cell .column-screen-inset-shaded layout-nrow=\"1\"}\n\n````{.cell-code}\n```{{r}}\n#| column: screen-inset-shaded\n#| layout-nrow: 1\n\nplot(cars)\nplot(iris)\nplot(pressure)\n```\n````\n\n::: {.cell-output-display}\n![](article-layout_files/figure-html/unnamed-chunk-4-1.png){width=672}\n:::\n\n::: {.cell-output-display}\n![](article-layout_files/figure-html/unnamed-chunk-4-2.png){width=672}\n:::\n\n::: {.cell-output-display}\n![](article-layout_files/figure-html/unnamed-chunk-4-3.png){width=672}\n:::\n:::\n\n\n## Margin Content\n\nYou can place content within the right margin of Quarto document. For example, here we use the `.column-margin` class to place an image in the margin:\n\n``` md\n::: {.column-margin}\n![A margin image](image.png)\n:::\n```\n\n::: {.layout-example .column-margin style=\"margin-top: 18px;\"}\n.column-margin\n:::\n\nThis also works for text content:\n\n``` md\n::: {.column-margin}\nWe know from *the first fundamental theorem of calculus* that for $x$ in $[a, b]$:\n\n$$\\frac{d}{dx}\\left( \\int_{a}^{x} f(u)\\,du\\right)=f(x).$$\n:::\n```\n\n::: column-margin\nWe know from *the first fundamental theorem of calculus* that for $x$ in $[a, b]$:\n\n$$\\frac{d}{dx}\\left( \\int_{a}^{x} f(u)\\,du\\right)=f(x).$$\n:::\n\n### Margin Figures\n\nFigures that you create using code cells can be placed in the margin by using the `column: margin` code cell option. If the code produces more than one figure, each of the figures will be placed in the margin.\n\n\n::: {.cell .column-margin}\n\n````{.cell-code}\n```{{r}}\n#| label: fig-mtcars\n#| fig-cap: \"MPG vs horsepower, colored by transmission.\"\n#| column: margin\n\nlibrary(ggplot2)\nmtcars2 <- mtcars\nmtcars2$am <- factor(\n mtcars$am, labels = c('automatic', 'manual')\n)\nggplot(mtcars2, aes(hp, mpg, color = am)) +\n geom_point() +\n geom_smooth(formula = y ~ x, method = \"loess\") +\n theme(legend.position = 'bottom')\n```\n````\n\n::: {.cell-output-display}\n![MPG vs horsepower, colored by transmission.](article-layout_files/figure-html/fig-mtcars-1.png){#fig-mtcars width=672}\n:::\n:::\n\n\n### Margin Tables\n\nYou can also place tables in the margin of your document by specifying `column: margin`.\n\n\n::: {.cell .column-margin}\n\n````{.cell-code}\n```{{r}}\n#| column: margin\n\nknitr::kable(\n mtcars[1:6, 1:3]\n)\n```\n````\n\n::: {.cell-output-display}\n\n\n| | mpg| cyl| disp|\n|:-----------------|----:|---:|----:|\n|Mazda RX4 | 21.0| 6| 160|\n|Mazda RX4 Wag | 21.0| 6| 160|\n|Datsun 710 | 22.8| 4| 108|\n|Hornet 4 Drive | 21.4| 6| 258|\n|Hornet Sportabout | 18.7| 8| 360|\n|Valiant | 18.1| 6| 225|\n\n\n:::\n:::\n\n\n### Multiple Outputs\n\nYou can also target specific output types (for example, figures) to be placed in the margin. For example, the following code will render a table showing part of the `mtcars` dataset and produce a plot in the margin next to the table.\n\n\n::: {.cell .fig-column-margin}\n\n````{.cell-code}\n```{{r}}\n#| fig-column: margin\n\nmtcars2 <- mtcars\nmtcars2$am <- factor(\n mtcars$am, labels = c('automatic', 'manual')\n)\n\nknitr::kable(\n mtcars[1:6, 1:6]\n)\n\nlibrary(ggplot2)\nggplot(mtcars2, aes(hp, mpg, color = am)) +\n geom_point() +\n geom_smooth(formula = y ~ x, method = \"loess\") +\n theme(legend.position = 'bottom')\n```\n````\n\n::: {.cell-output-display}\n\n\n| | mpg| cyl| disp| hp| drat| wt|\n|:-----------------|----:|---:|----:|---:|----:|-----:|\n|Mazda RX4 | 21.0| 6| 160| 110| 3.90| 2.620|\n|Mazda RX4 Wag | 21.0| 6| 160| 110| 3.90| 2.875|\n|Datsun 710 | 22.8| 4| 108| 93| 3.85| 2.320|\n|Hornet 4 Drive | 21.4| 6| 258| 110| 3.08| 3.215|\n|Hornet Sportabout | 18.7| 8| 360| 175| 3.15| 3.440|\n|Valiant | 18.1| 6| 225| 105| 2.76| 3.460|\n\n\n:::\n\n::: {.cell-output-display}\n![](article-layout_files/figure-html/unnamed-chunk-7-1.png){width=672}\n:::\n:::\n\n\n## Page Breaks\n\nThe `pagebreak` [shortcode](shortcodes.qmd) enables you to insert a native pagebreak into a document (.e.g in LaTeX this would be a `\\newpage`, in MS Word a docx-native pagebreak, in HTML a `page-break-after: always` CSS directive, etc.):\n\n```{.markdown shortcodes=\"false\"}\npage 1\n\n{{< pagebreak >}}\n\npage 2\n```\n\nNative pagebreaks are supported for HTML, LaTeX, Context, MS Word, Open Document, and ePub (for other formats a form-feed character `\\f` is inserted).\n\n\n\n## Margin References\n\nFootnotes and the bibliography typically appear at the end of the document, but you can choose to have them placed in the margin by setting the following option[^1] in the document front matter:\n\n``` yaml\n---\nreference-location: margin\ncitation-location: margin\n---\n```\n\nWith these options set, footnotes and citations will (respectively) be automatically be placed in the margin of the document rather than the bottom of the page. As an example, when I cite @xie2018, the citation bibliography entry itself will now appear in the margin.\n\n### Asides\n\nAsides allow you to place content aside from the content it is placed in. Asides look like footnotes, but do not include the footnote mark (the superscript number). [This is a span that has the class `aside` which places it in the margin without a footnote number.]{.aside}\n\n``` markdown\n[This is a span that has the class `aside` which places it in the margin without a footnote number.]{.aside}\n```\n\n## Margin Captions\n\nFor figures and tables, you may leave the content in the body of the document while placing the caption in the margin of the document. Using `cap-location: margin` in a code cell or document front matter to control this. For example:\n\n\n::: {.cell .caption-margin}\n\n````{.cell-code}\n```{{r}}\n#| label: fig-cap-margin\n#| fig-cap: \"MPG vs horsepower, colored by transmission.\"\n#| cap-location: margin\n\nlibrary(ggplot2)\nmtcars2 <- mtcars\nmtcars2$am <- factor(\n mtcars$am, labels = c('automatic', 'manual')\n)\nggplot(mtcars2, aes(hp, mpg, color = am)) +\n geom_point() +\n geom_smooth(formula = y ~ x, method = \"loess\") +\n theme(legend.position = 'bottom')\n```\n````\n\n::: {.cell-output-display}\n![MPG vs horsepower, colored by transmission.](article-layout_files/figure-html/fig-cap-margin-1.png){#fig-cap-margin width=672}\n:::\n:::\n\n\n## Overflowing Content\n\nYou can also extend content outside the body region on only the left or right side of the document by using the `right` and `left` versions of the `body`, `page`, and `screen` columns to layout your content. The `left` or `right` version of these columns are as follows:\n\n::: {.layout-example .column-body-outset-right .left}\n.column-body-outset-right\n:::\n\n::: {.layout-example .column-page-inset-right .left}\n.column-page-inset-right\n:::\n\n::: {.layout-example .column-page-right .left}\n.column-page-right\n:::\n\n::: {.layout-example .column-screen-inset-right .left}\n.column-screen-inset-right\n:::\n\n::: {.layout-example .column-screen-right .left}\n.column-screen-right\n:::\n\n::: {.layout-example .column-body-outset-left .right}\n.column-body-outset-left\n:::\n\n::: {.layout-example .column-page-inset-left .right}\n.column-page-inset-left\n:::\n\n::: {.layout-example .column-page-left .right}\n.column-page-left\n:::\n\n::: {.layout-example .column-screen-inset-left .right}\n.column-screen-inset-left\n:::\n\n::: {.layout-example .column-screen-left .right}\n.column-screen-left\n:::\n\nUse a div with one of the above classes to align content into one of the overflow regions. This also works using the `column` option of executable code cells:\n\n\n::: {.cell .column-screen-inset-right}\n\n````{.cell-code}\n```{{r}}\n#| column: screen-inset-right\n\nlibrary(leaflet)\nleaflet() %>%\n addTiles() %>% # Add default OpenStreetMap map tiles\n addMarkers(lng=174.768, lat=-36.852, popup=\"The birthplace of R\")\n```\n````\n\n::: {.cell-output-display}\n\n```{=html}\n
\n\n```\n\n:::\n:::\n\n\n## Options Reference\n\n### Global Options\n\nSome layout options can be specified globally in document yaml. For example:\n\n``` yaml\n---\nfig-cap-location: margin\nreference-location: margin\n---\n```\n\nAll of the below options currently only support setting a value of `margin` which tells Quarto to place the corresponding element in the margin.\n\n+----------------------+---------------------------------------------------------------------------------------------------------+\n| Option | Description |\n+======================+=========================================================================================================+\n| `reference-location` | Where to place footnotes. Defaults to `document`.\\ |\n| | \\[`document` \\| `section` \\| `block` \\| `margin` \\] |\n+----------------------+---------------------------------------------------------------------------------------------------------+\n| `citation-location` | Where to place citations. Defaults to `document`.\\ |\n| | \\[`document` \\| `margin` \\] |\n+----------------------+---------------------------------------------------------------------------------------------------------+\n| `cap-location` | Where to place figure and table captions. Defaults to `bottom` for figures and `top` for tables.\\ |\n| | \\[`top` \\| `bottom` \\| `margin`\\] |\n+----------------------+---------------------------------------------------------------------------------------------------------+\n| `fig-cap-location` | Where to place figure captions. Defaults to `bottom`.\\ |\n| | \\[`top` \\| `bottom` \\| `margin`\\] |\n+----------------------+---------------------------------------------------------------------------------------------------------+\n| `tbl-cap-location` | Where to place table captions. Defaults to `top`.\\ |\n| | \\[`top` \\| `bottom` \\| `margin`\\] |\n+----------------------+---------------------------------------------------------------------------------------------------------+\n\n### Code Cell Options\n\nYou can also set layout column on specific code cells. This controls the layout of content that is produced by the code cell.\n\n```{{r}}\n#| column: page\n\nplot(cars)\n```\n\n::: column-page-right\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| Option | Description |\n+====================+==============================================================================================================================+\n| `column` | Layout column to use for code cell outputs. See column options below. |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| `fig-column` | Layout column to use for code cell figure outputs. See column options below. |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| `tbl-column` | Layout column to use for code cell table outputs. See column options below. |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| `cap-location` | Where to place figure and table captions produced by this code cell. Defaults to `bottom` for figures and `top` for tables.\\ |\n| | \\[`top` \\| `bottom` \\| `margin`\\] |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| `fig-cap-location` | Where to place captions for figures produced by this code cell. Defaults to `inline`.\\ |\n| | \\[`inline` \\| `margin`\\] |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| `tbl-cap-location` | Where to place captions for tables produced by this code cell. Defaults to `inline`.\\ |\n| | \\[`inline` \\| `margin`\\] |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n:::\n\n### Using Classes\n\nIn addition to global and code cell specific options, you may use divs with layout classes (prefixed with `.column-`) to arrange content into columns:\n\n``` md\n::: {.column-margin}\nThis content will appear in the margin!\n:::\n```\n\n### Available Columns\n\nHere are all of the available column specifiers:\n\n::: column-page-right\n+--------------+---------------------------------+---------------------------------+\n| Column | Code Cell `column` | Class Name |\n+==============+=================================+=================================+\n| Body | column: body | .column-body |\n| | column: body-outset | .column-body-outset |\n| | column: body-outset-left | .column-body-outset-left |\n| | column: body-outset-right | .column-body-outset-right |\n+--------------+---------------------------------+---------------------------------+\n| Page Inset | column: page-inset | .column-page-inset |\n| | column: page-inset-left | .column-page-inset-left |\n| | column: page-inset-right | .column-page-inset-right |\n+--------------+---------------------------------+---------------------------------+\n| Page | column: page | .column-page |\n| | column: page-left | .column-page-left |\n| | column: page-right | .column-page-right |\n+--------------+---------------------------------+---------------------------------+\n| Screen Inset | column: screen-inset | .column-screen-inset |\n| | column: screen-inset-shaded | .column-screen-inset-shaded |\n| | column: screen-inset-left | .column-screen-inset-left |\n| | column: screen-inset-right | .column-screen-inset-right |\n+--------------+---------------------------------+---------------------------------+\n| Screen | column: screen | .column-screen |\n| | column: screen-left | .column-screen-left |\n| | column: screen-right | .column-screen-right |\n+--------------+---------------------------------+---------------------------------+\n| Margin | column: margin | .column-margin |\n+--------------+---------------------------------+---------------------------------+\n:::\n\n## PDF/LaTeX Layout {data-link=\"PDF/LaTeX Layout\"}\n\nWhile most of the layout capabilities described are supported for both HTML and PDF output, some are available only for HTML output. You can use the full set of columns for HTML. Then, when you render PDF or LaTeX output, content will automatically be placed in the most appropriate related column (typically this will mean using the main column and right margin). Here is how columns are mapped:\n\n- Any column that uses the right margin (e.g. `page`, `screen`, `screen-right`, etc.) will be rendered as `page-right` in LaTeX.\n- Any column that uses the left margin will be rendered as normal body content.\n\n### Page Geometry\n\nWhen you render a PDF using content in the margin or content that spans the page, Quarto will automatically adjust the page geometry for the default Quarto LaTeX document classes (KOMA `scrartcl`, `scrreport`, or `scrbook`) to create a slightly narrower body content region and a slightly wider margin region. This adjustment will incorporate known paper sizes to create a reasonable page geometry for most content.\n\nYou can control the page geometry directly yourself by setting `geometry` options in your document's front matter. For example:\n\n``` yaml\n---\ngeometry:\n - left=.75in\n - textwidth=4.5in\n - marginparsep=.25in\n - marginparwidth=2.25in\n---\n```\n\nYou can use these options to control the page geometry for the built-in document classes or to customize the geometry of other document classes that you may be using.\n\n::: {.callout-tip appearance=\"simple\"}\nIf you'd like to view the page geometry in your rendered PDF, you can pass `showframe` to the `geometry` option as in the below example.\n\n``` {.yaml style=\"background: none;\"}\n---\ngeometry:\n - showframe\n---\n```\n:::\n\n### Code Blocks\n\nWhen rendering a PDF that uses the margins for content, Quarto automatically adjusts the appearance of code blocks. Rather than having a solid background color, a left border treatment is used.\n\nThis enables non-breaking code to overflow into the margin without cosmetic issues created by the code block background (which does not overflow into the margin region).\n\nYou can disable this treatment by setting the following `code-block-border-left: false` in your document front matter.\n\n## Typst Layout {#typst-layout data-link=\"Typst Layout\"}\n\nTypst output supports the layout capabilities described in this document via the [Marginalia](https://typst.app/universe/package/marginalia) package.\n\n### Page Geometry\n\nWhen you use margin content in a Typst document, Quarto automatically calculates appropriate page geometry based on your `papersize` setting. The geometry creates a narrower body column and a margin column for notes and figures.\n\nYou can customize the column widths using the `grid` option:\n\n``` yaml\nformat:\n typst:\n grid:\n margin-width: 2in\n body-width: 4in\n gutter-width: 0.25in\n```\n\nFor fine-grained control over margin placement, Typst also provides the `margin-geometry` option which directly configures the underlying Marginalia package. See [Typst Basics - Article Layout](/docs/output-formats/typst.qmd#article-layout) for details.\n\n## Landscape mode\n\nIn `docx`, `pdf` and `typst` formats, you can set portions of the document to landscape mode by wrapping the content around a fenced div with class `landscape`:\n\n````markdown\n---\nformat:\n docx: default\n typst: default\n pdf: default\n---\n\nThis will appear in portrait mode.\n\n::: {.landscape}\n\nThis will appear in landscape.\n\n:::\n\nThis will appear in portrait mode again.\n````\n\n\n\n[^1]: You can also position references in other location (such as the bottom of the block, section, or document).\n", + "markdown": "---\ntitle: \"Article Layout\"\nformat: html\nreference-location: margin\ncitation-location: margin\naliases:\n - page-layout.html\n---\n\n## Overview\n\nQuarto supports a variety of page layout options that enable you to author content that:\n\n- Fills the main content region\n- Overflows the content region\n- Spans the entire page\n- Occupies the document margin\n- Uses landscape mode in paginated formats\n\nQuarto uses the concept of columns to describe page layout (e.g. the \"body\" column, the \"margin\" column, etc.). Below we'll describe how to arrange content into these columns. If you need to adjust the widths of the columns, see [Page Layout - Grid Customization](/docs/output-formats/page-layout.qmd#grid-customization).\n\nAll of the layout capabilities described in this document work for HTML and Typst output. Many also work for PDF and LaTeX output, though with some differences. See [Typst Layout] and [PDF/LaTeX Layout] for format-specific details.\n\n## Body Column\n\nBy default, elements are positioned in the body of the document and are allowed to span the content of the document, like the below.\n\n::: {.layout-example .column-body}\n.column-body\n:::\n\nBut if you'd like, you can extend content slightly outside the bounds of the body by creating a div with the .`column-body-outset` class. For example:\n\n``` markdown\n:::{.column-body-outset}\nOutset content...\n:::\n```\n\n::: {.layout-example .column-body-outset}\n.column-body-outset\n:::\n\n## Page Column\n\nIf you need even more space for your content, you can use the `.column-page` class to make the content much wider, though stopping short of extending across the whole document.\n\n::: {.layout-example .column-page}\n.column-page\n:::\n\nFor example, to create a wider image, you could use:\n\n``` markdown\n:::{.column-page}\n![](images/elephant.jpg)\n:::\n```\n\n::: column-page\n![](images/elephant.jpg){fig-alt=\"Three walking elephants in silhouette against the backdrop of a sunset.\"}\n:::\n\nFor computational output, you can specify the page column in your code cell options. For example:\n\n\n::: {.cell .column-page}\n\n````{.cell-code}\n```{{r}}\n#| column: page\n\nknitr::kable(\n mtcars[1:6, 1:10]\n)\n```\n````\n\n::: {.cell-output-display}\n\n\n| | mpg| cyl| disp| hp| drat| wt| qsec| vs| am| gear|\n|:-----------------|----:|---:|----:|---:|----:|-----:|-----:|--:|--:|----:|\n|Mazda RX4 | 21.0| 6| 160| 110| 3.90| 2.620| 16.46| 0| 1| 4|\n|Mazda RX4 Wag | 21.0| 6| 160| 110| 3.90| 2.875| 17.02| 0| 1| 4|\n|Datsun 710 | 22.8| 4| 108| 93| 3.85| 2.320| 18.61| 1| 1| 4|\n|Hornet 4 Drive | 21.4| 6| 258| 110| 3.08| 3.215| 19.44| 1| 0| 3|\n|Hornet Sportabout | 18.7| 8| 360| 175| 3.15| 3.440| 17.02| 0| 0| 3|\n|Valiant | 18.1| 6| 225| 105| 2.76| 3.460| 20.22| 1| 0| 3|\n\n\n:::\n:::\n\n\nIn addition, you can use `.column-page-inset` to inset the element from the page slightly, like so:\n\n::: {.layout-example .column-page-inset}\n.column-page-inset\n:::\n\n## Screen Column\n\nYou can have content span the full width of the page with no margin (full bleed). For this, use the `.column-screen` class or specify `column: screen` on a code cell. For example:\n\n``` md\n::: {.column-screen}\n![A full screen image](/image.png)\n:::\n```\n\n::: {.layout-example .column-screen}\n.column-screen\n:::\n\nThe following code displays a Leaflet map across the whole page.\n\n\n::: {.cell .column-screen}\n\n````{.cell-code}\n```{{r}}\n#| column: screen\n\nlibrary(leaflet)\nleaflet() %>%\n addTiles() %>% # Add default OpenStreetMap map tiles\n addMarkers(lng=174.768, lat=-36.852, popup=\"The birthplace of R\")\n```\n````\n\n::: {.cell-output-display}\n\n```{=html}\n
\n\n```\n\n:::\n:::\n\n\n### Screen Inset\n\nIf you'd like a full width appearance, but would like to retain a margin, you can use inset or inset-shaded modifiers on the column. For example:\n\n``` md\n::: {.column-screen-inset}\n![A full screen image](/image.png)\n:::\n```\n\n::: {.layout-example .column-screen-inset}\n.column-screen-inset\n:::\n\nThe inset-shaded modifier results in a block spanning the full width but wrapped with a lightly shaded background. For example:\n\n\n::: {.cell .column-screen-inset-shaded}\n\n````{.cell-code}\n```{{r}}\n#| column: screen-inset-shaded\n\nlibrary(leaflet)\nleaflet() %>%\n addTiles() %>% # Add default OpenStreetMap map tiles\n addMarkers(lng=174.768, lat=-36.852, popup=\"The birthplace of R\")\n```\n````\n\n::: {.cell-output-display}\n\n```{=html}\n
\n\n```\n\n:::\n:::\n\n\nColumn layouts like `screen-inset-shaded` will work with advanced figure layout. For example, it is straightforward to create a multi column presentation of figures that spans the document:\n\n\n::: {.cell .column-screen-inset-shaded layout-nrow=\"1\"}\n\n````{.cell-code}\n```{{r}}\n#| column: screen-inset-shaded\n#| layout-nrow: 1\n#| fig-alt:\n#| - \"Scatterplot of stopping distance against speed for 50 cars. Distance increases with speed.\"\n#| - \"Scatterplot matrix of the five iris variables, showing every pairwise combination of sepal length, sepal width, petal length, petal width, and species.\"\n#| - \"Scatterplot of vapor pressure against temperature for mercury. Pressure stays near zero until about 200 degrees Celsius, then rises steeply.\"\n\nplot(cars)\nplot(iris)\nplot(pressure)\n```\n````\n\n::: {.cell-output-display}\n![](article-layout_files/figure-html/unnamed-chunk-4-1.png){fig-alt='Scatterplot of stopping distance against speed for 50 cars. Distance increases with speed.' width=672}\n:::\n\n::: {.cell-output-display}\n![](article-layout_files/figure-html/unnamed-chunk-4-2.png){fig-alt='Scatterplot matrix of the five iris variables, showing every pairwise combination of sepal length, sepal width, petal length, petal width, and species.' width=672}\n:::\n\n::: {.cell-output-display}\n![](article-layout_files/figure-html/unnamed-chunk-4-3.png){fig-alt='Scatterplot of vapor pressure against temperature for mercury. Pressure stays near zero until about 200 degrees Celsius, then rises steeply.' width=672}\n:::\n:::\n\n\n## Margin Content\n\nYou can place content within the right margin of Quarto document. For example, here we use the `.column-margin` class to place an image in the margin:\n\n``` md\n::: {.column-margin}\n![A margin image](image.png)\n:::\n```\n\n::: {.layout-example .column-margin style=\"margin-top: 18px;\"}\n.column-margin\n:::\n\nThis also works for text content:\n\n``` md\n::: {.column-margin}\nWe know from *the first fundamental theorem of calculus* that for $x$ in $[a, b]$:\n\n$$\\frac{d}{dx}\\left( \\int_{a}^{x} f(u)\\,du\\right)=f(x).$$\n:::\n```\n\n::: column-margin\nWe know from *the first fundamental theorem of calculus* that for $x$ in $[a, b]$:\n\n$$\\frac{d}{dx}\\left( \\int_{a}^{x} f(u)\\,du\\right)=f(x).$$\n:::\n\n### Margin Figures\n\nFigures that you create using code cells can be placed in the margin by using the `column: margin` code cell option. If the code produces more than one figure, each of the figures will be placed in the margin.\n\n\n::: {.cell .column-margin}\n\n````{.cell-code}\n```{{r}}\n#| label: fig-mtcars\n#| fig-cap: \"MPG vs horsepower, colored by transmission.\"\n#| fig-alt: \"Scatterplot of miles per gallon against horsepower for 32 cars, with a smoothed trend line for each transmission type. Mileage falls as horsepower rises, and manual cars cluster at lower horsepower and higher mileage than automatic cars.\"\n#| column: margin\n\nlibrary(ggplot2)\nmtcars2 <- mtcars\nmtcars2$am <- factor(\n mtcars$am, labels = c('automatic', 'manual')\n)\nggplot(mtcars2, aes(hp, mpg, color = am)) +\n geom_point() +\n geom_smooth(formula = y ~ x, method = \"loess\") +\n theme(legend.position = 'bottom')\n```\n````\n\n::: {.cell-output-display}\n![MPG vs horsepower, colored by transmission.](article-layout_files/figure-html/fig-mtcars-1.png){#fig-mtcars fig-alt='Scatterplot of miles per gallon against horsepower for 32 cars, with a smoothed trend line for each transmission type. Mileage falls as horsepower rises, and manual cars cluster at lower horsepower and higher mileage than automatic cars.' width=672}\n:::\n:::\n\n\n### Margin Tables\n\nYou can also place tables in the margin of your document by specifying `column: margin`.\n\n\n::: {.cell .column-margin}\n\n````{.cell-code}\n```{{r}}\n#| column: margin\n\nknitr::kable(\n mtcars[1:6, 1:3]\n)\n```\n````\n\n::: {.cell-output-display}\n\n\n| | mpg| cyl| disp|\n|:-----------------|----:|---:|----:|\n|Mazda RX4 | 21.0| 6| 160|\n|Mazda RX4 Wag | 21.0| 6| 160|\n|Datsun 710 | 22.8| 4| 108|\n|Hornet 4 Drive | 21.4| 6| 258|\n|Hornet Sportabout | 18.7| 8| 360|\n|Valiant | 18.1| 6| 225|\n\n\n:::\n:::\n\n\n### Multiple Outputs\n\nYou can also target specific output types (for example, figures) to be placed in the margin. For example, the following code will render a table showing part of the `mtcars` dataset and produce a plot in the margin next to the table.\n\n\n::: {.cell .fig-column-margin}\n\n````{.cell-code}\n```{{r}}\n#| fig-column: margin\n#| fig-alt: \"Scatterplot of miles per gallon against horsepower for 32 cars, with a smoothed trend line for each transmission type. Mileage falls as horsepower rises, and manual cars cluster at lower horsepower and higher mileage than automatic cars.\"\n\nmtcars2 <- mtcars\nmtcars2$am <- factor(\n mtcars$am, labels = c('automatic', 'manual')\n)\n\nknitr::kable(\n mtcars[1:6, 1:6]\n)\n\nlibrary(ggplot2)\nggplot(mtcars2, aes(hp, mpg, color = am)) +\n geom_point() +\n geom_smooth(formula = y ~ x, method = \"loess\") +\n theme(legend.position = 'bottom')\n```\n````\n\n::: {.cell-output-display}\n\n\n| | mpg| cyl| disp| hp| drat| wt|\n|:-----------------|----:|---:|----:|---:|----:|-----:|\n|Mazda RX4 | 21.0| 6| 160| 110| 3.90| 2.620|\n|Mazda RX4 Wag | 21.0| 6| 160| 110| 3.90| 2.875|\n|Datsun 710 | 22.8| 4| 108| 93| 3.85| 2.320|\n|Hornet 4 Drive | 21.4| 6| 258| 110| 3.08| 3.215|\n|Hornet Sportabout | 18.7| 8| 360| 175| 3.15| 3.440|\n|Valiant | 18.1| 6| 225| 105| 2.76| 3.460|\n\n\n:::\n\n::: {.cell-output-display}\n![](article-layout_files/figure-html/unnamed-chunk-6-1.png){fig-alt='Scatterplot of miles per gallon against horsepower for 32 cars, with a smoothed trend line for each transmission type. Mileage falls as horsepower rises, and manual cars cluster at lower horsepower and higher mileage than automatic cars.' width=672}\n:::\n:::\n\n\n## Page Breaks\n\nThe `pagebreak` [shortcode](shortcodes.qmd) enables you to insert a native pagebreak into a document (e.g. in LaTeX this would be a `\\newpage`, in MS Word a docx-native pagebreak, in HTML a `page-break-after: always` CSS directive, etc.):\n\n```{.markdown shortcodes=\"false\"}\npage 1\n\n{{< pagebreak >}}\n\npage 2\n```\n\nNative pagebreaks are supported for HTML, LaTeX, Context, MS Word, Open Document, ePub, and Typst (for other formats a form-feed character `\\f` is inserted).\n\n\n\n## Margin References\n\nFootnotes and the bibliography typically appear at the end of the document, but you can choose to have them placed in the margin by setting the following option[^1] in the document front matter:\n\n``` yaml\n---\nreference-location: margin\ncitation-location: margin\n---\n```\n\nWith these options set, footnotes and citations will (respectively) be automatically be placed in the margin of the document rather than the bottom of the page. As an example, when I cite @xie2018, the citation bibliography entry itself will now appear in the margin.\n\n### Asides\n\nAsides allow you to place content aside from the content it is placed in. Asides look like footnotes, but do not include the footnote mark (the superscript number). [This is a span that has the class `aside` which places it in the margin without a footnote number.]{.aside}\n\n``` markdown\n[This is a span that has the class `aside` which places it in the margin without a footnote number.]{.aside}\n```\n\n## Margin Captions\n\nFor figures and tables, you may leave the content in the body of the document while placing the caption in the margin of the document. Using `cap-location: margin` in a code cell or document front matter to control this. For example:\n\n\n::: {.cell .caption-margin}\n\n````{.cell-code}\n```{{r}}\n#| label: fig-cap-margin\n#| fig-cap: \"MPG vs horsepower, colored by transmission.\"\n#| fig-alt: \"Scatterplot of miles per gallon against horsepower for 32 cars, with a smoothed trend line for each transmission type. Mileage falls as horsepower rises, and manual cars cluster at lower horsepower and higher mileage than automatic cars.\"\n#| cap-location: margin\n\nlibrary(ggplot2)\nmtcars2 <- mtcars\nmtcars2$am <- factor(\n mtcars$am, labels = c('automatic', 'manual')\n)\nggplot(mtcars2, aes(hp, mpg, color = am)) +\n geom_point() +\n geom_smooth(formula = y ~ x, method = \"loess\") +\n theme(legend.position = 'bottom')\n```\n````\n\n::: {.cell-output-display}\n![MPG vs horsepower, colored by transmission.](article-layout_files/figure-html/fig-cap-margin-1.png){#fig-cap-margin fig-alt='Scatterplot of miles per gallon against horsepower for 32 cars, with a smoothed trend line for each transmission type. Mileage falls as horsepower rises, and manual cars cluster at lower horsepower and higher mileage than automatic cars.' width=672}\n:::\n:::\n\n\n## Overflowing Content\n\nYou can also extend content outside the body region on only the left or right side of the document by using the `right` and `left` versions of the `body`, `page`, and `screen` columns to layout your content. The `left` or `right` version of these columns are as follows:\n\n::: {.layout-example .column-body-outset-right .left}\n.column-body-outset-right\n:::\n\n::: {.layout-example .column-page-inset-right .left}\n.column-page-inset-right\n:::\n\n::: {.layout-example .column-page-right .left}\n.column-page-right\n:::\n\n::: {.layout-example .column-screen-inset-right .left}\n.column-screen-inset-right\n:::\n\n::: {.layout-example .column-screen-right .left}\n.column-screen-right\n:::\n\n::: {.layout-example .column-body-outset-left .right}\n.column-body-outset-left\n:::\n\n::: {.layout-example .column-page-inset-left .right}\n.column-page-inset-left\n:::\n\n::: {.layout-example .column-page-left .right}\n.column-page-left\n:::\n\n::: {.layout-example .column-screen-inset-left .right}\n.column-screen-inset-left\n:::\n\n::: {.layout-example .column-screen-left .right}\n.column-screen-left\n:::\n\nUse a div with one of the above classes to align content into one of the overflow regions. This also works using the `column` option of executable code cells:\n\n\n::: {.cell .column-screen-inset-right}\n\n````{.cell-code}\n```{{r}}\n#| column: screen-inset-right\n\nlibrary(leaflet)\nleaflet() %>%\n addTiles() %>% # Add default OpenStreetMap map tiles\n addMarkers(lng=174.768, lat=-36.852, popup=\"The birthplace of R\")\n```\n````\n\n::: {.cell-output-display}\n\n```{=html}\n
\n\n```\n\n:::\n:::\n\n\n## Options Reference\n\n### Global Options\n\nSome layout options can be specified globally in document yaml. For example:\n\n``` yaml\n---\nfig-cap-location: margin\nreference-location: margin\n---\n```\n\nAll of the below options currently only support setting a value of `margin` which tells Quarto to place the corresponding element in the margin.\n\n+----------------------+---------------------------------------------------------------------------------------------------------+\n| Option | Description |\n+======================+=========================================================================================================+\n| `reference-location` | Where to place footnotes. Defaults to `document`.[^2]\\ |\n| | \\[`document` \\| `section` \\| `block` \\| `margin` \\] |\n+----------------------+---------------------------------------------------------------------------------------------------------+\n| `citation-location` | Where to place citations. Defaults to `document`.\\ |\n| | \\[`document` \\| `margin` \\] |\n+----------------------+---------------------------------------------------------------------------------------------------------+\n| `cap-location` | Where to place figure and table captions. Defaults to `bottom` for figures and `top` for tables.\\ |\n| | \\[`top` \\| `bottom` \\| `margin`\\] |\n+----------------------+---------------------------------------------------------------------------------------------------------+\n| `fig-cap-location` | Where to place figure captions. Defaults to `bottom`.\\ |\n| | \\[`top` \\| `bottom` \\| `margin`\\] |\n+----------------------+---------------------------------------------------------------------------------------------------------+\n| `tbl-cap-location` | Where to place table captions. Defaults to `top`.\\ |\n| | \\[`top` \\| `bottom` \\| `margin`\\] |\n+----------------------+---------------------------------------------------------------------------------------------------------+\n\n### Code Cell Options\n\nYou can also set layout column on specific code cells. This controls the layout of content that is produced by the code cell.\n\n```{{r}}\n#| column: page\n\nplot(cars)\n```\n\n::: column-page-right\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| Option | Description |\n+====================+==============================================================================================================================+\n| `column` | Layout column to use for code cell outputs. See column options below. |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| `fig-column` | Layout column to use for code cell figure outputs. See column options below. |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| `tbl-column` | Layout column to use for code cell table outputs. See column options below. |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| `cap-location` | Where to place figure and table captions produced by this code cell. Defaults to `bottom` for figures and `top` for tables.\\ |\n| | \\[`top` \\| `bottom` \\| `margin`\\] |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| `fig-cap-location` | Where to place captions for figures produced by this code cell. Defaults to `inline`.\\ |\n| | \\[`inline` \\| `margin`\\] |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n| `tbl-cap-location` | Where to place captions for tables produced by this code cell. Defaults to `inline`.\\ |\n| | \\[`inline` \\| `margin`\\] |\n+--------------------+------------------------------------------------------------------------------------------------------------------------------+\n:::\n\n### Using Classes\n\nIn addition to global and code cell specific options, you may use divs with layout classes (prefixed with `.column-`) to arrange content into columns:\n\n``` md\n::: {.column-margin}\nThis content will appear in the margin!\n:::\n```\n\n### Available Columns\n\nHere are all of the available column specifiers:\n\n::: column-page-right\n+--------------+---------------------------------+---------------------------------+\n| Column | Code Cell `column` | Class Name |\n+==============+=================================+=================================+\n| Body | column: body | .column-body |\n| | column: body-outset | .column-body-outset |\n| | column: body-outset-left | .column-body-outset-left |\n| | column: body-outset-right | .column-body-outset-right |\n+--------------+---------------------------------+---------------------------------+\n| Page Inset | column: page-inset | .column-page-inset |\n| | column: page-inset-left | .column-page-inset-left |\n| | column: page-inset-right | .column-page-inset-right |\n+--------------+---------------------------------+---------------------------------+\n| Page | column: page | .column-page |\n| | column: page-left | .column-page-left |\n| | column: page-right | .column-page-right |\n+--------------+---------------------------------+---------------------------------+\n| Screen Inset | column: screen-inset | .column-screen-inset |\n| | column: screen-inset-shaded | .column-screen-inset-shaded |\n| | column: screen-inset-left | .column-screen-inset-left |\n| | column: screen-inset-right | .column-screen-inset-right |\n+--------------+---------------------------------+---------------------------------+\n| Screen | column: screen | .column-screen |\n| | column: screen-left | .column-screen-left |\n| | column: screen-right | .column-screen-right |\n+--------------+---------------------------------+---------------------------------+\n| Margin | column: margin | .column-margin |\n+--------------+---------------------------------+---------------------------------+\n:::\n\n## PDF/LaTeX Layout {data-link=\"PDF/LaTeX Layout\"}\n\nWhile most of the layout capabilities described are supported for both HTML and PDF output, some are available only for HTML output. You can use the full set of columns for HTML. Then, when you render PDF or LaTeX output, content will automatically be placed in the most appropriate related column (typically this will mean using the main column and right margin). Here is how columns are mapped:\n\n- Any column that uses the right margin (e.g. `page`, `screen`, `screen-right`, etc.) will be rendered as `page-right` in LaTeX.\n- Any column that uses the left margin will be rendered as normal body content.\n\n### Page Geometry\n\nWhen you render a PDF using content in the margin or content that spans the page, Quarto will automatically adjust the page geometry for the default Quarto LaTeX document classes (KOMA `scrartcl`, `scrreport`, or `scrbook`) to create a slightly narrower body content region and a slightly wider margin region. This adjustment will incorporate known paper sizes to create a reasonable page geometry for most content.\n\nYou can control the page geometry directly yourself by setting `geometry` options in your document's front matter. For example:\n\n``` yaml\n---\ngeometry:\n - left=.75in\n - textwidth=4.5in\n - marginparsep=.25in\n - marginparwidth=2.25in\n---\n```\n\nYou can use these options to control the page geometry for the built-in document classes or to customize the geometry of other document classes that you may be using.\n\n::: {.callout-tip appearance=\"simple\"}\nIf you'd like to view the page geometry in your rendered PDF, you can pass `showframe` to the `geometry` option as in the below example.\n\n``` {.yaml style=\"background: none;\"}\n---\ngeometry:\n - showframe\n---\n```\n:::\n\n### Code Blocks\n\nWhen rendering a PDF that uses the margins for content, Quarto automatically adjusts the appearance of code blocks. Rather than having a solid background color, a left border treatment is used.\n\nThis enables non-breaking code to overflow into the margin without cosmetic issues created by the code block background (which does not overflow into the margin region).\n\nYou can disable this treatment by setting the following `code-block-border-left: false` in your document front matter.\n\n## Typst Layout {#typst-layout data-link=\"Typst Layout\"}\n\nTypst output supports the layout capabilities described in this document via the [Marginalia](https://typst.app/universe/package/marginalia) package.\n\n### Page Geometry\n\nWhen you use margin content in a Typst document, Quarto automatically calculates appropriate page geometry based on your `papersize` setting. The geometry creates a narrower body column and a margin column for notes and figures.\n\nYou can customize the column widths using the `grid` option:\n\n``` yaml\nformat:\n typst:\n grid:\n margin-width: 2in\n body-width: 4in\n gutter-width: 0.25in\n```\n\nFor fine-grained control over margin placement, Typst also provides the `margin-geometry` option which directly configures the underlying Marginalia package. See [Typst Basics - Article Layout](/docs/output-formats/typst.qmd#article-layout) for details.\n\n## Landscape mode\n\nIn `docx`, `pdf` and `typst` formats, you can set portions of the document to landscape mode by wrapping the content around a fenced div with class `landscape`:\n\n````markdown\n---\nformat:\n docx: default\n typst: default\n pdf: default\n---\n\nThis will appear in portrait mode.\n\n::: {.landscape}\n\nThis will appear in landscape.\n\n:::\n\nThis will appear in portrait mode again.\n````\n\n\n\n[^1]: You can also position references in other location (such as the bottom of the block, section, or document).\n[^2]: Typst does not support `block` or `section` for `reference-location`.\n", "supporting": [ "article-layout_files" ], @@ -11,7 +11,7 @@ ], "includes": { "include-in-header": [ - "\n\n\n\n\n\n\n\n\n\n" + "\n\n\n\n\n\n\n\n\n\n" ] }, "engineDependencies": {}, diff --git a/_freeze/docs/authoring/article-layout/figure-html/fig-cap-margin-1.png b/_freeze/docs/authoring/article-layout/figure-html/fig-cap-margin-1.png index 4d2089672a..461af45e01 100644 Binary files a/_freeze/docs/authoring/article-layout/figure-html/fig-cap-margin-1.png and b/_freeze/docs/authoring/article-layout/figure-html/fig-cap-margin-1.png differ diff --git a/_freeze/docs/authoring/article-layout/figure-html/fig-mtcars-1.png b/_freeze/docs/authoring/article-layout/figure-html/fig-mtcars-1.png index 4d2089672a..461af45e01 100644 Binary files a/_freeze/docs/authoring/article-layout/figure-html/fig-mtcars-1.png and b/_freeze/docs/authoring/article-layout/figure-html/fig-mtcars-1.png differ diff --git a/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-1.png b/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-1.png index c280fa3135..a7b0de86bf 100644 Binary files a/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-1.png and b/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-1.png differ diff --git a/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-2.png b/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-2.png index f886019a41..b78209d7e4 100644 Binary files a/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-2.png and b/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-2.png differ diff --git a/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-3.png b/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-3.png index 016bbd9b45..7764c1fdb7 100644 Binary files a/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-3.png and b/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-4-3.png differ diff --git a/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-6-1.png b/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-6-1.png new file mode 100644 index 0000000000..461af45e01 Binary files /dev/null and b/_freeze/docs/authoring/article-layout/figure-html/unnamed-chunk-6-1.png differ diff --git a/_freeze/docs/authoring/cross-references/execute-results/html.json b/_freeze/docs/authoring/cross-references/execute-results/html.json index 586febffde..eb7e1f1e15 100644 --- a/_freeze/docs/authoring/cross-references/execute-results/html.json +++ b/_freeze/docs/authoring/cross-references/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "73687d731b0958f2db2cfbc7be4ad153", + "hash": "fda9e39b3ce2f0e6b166c069ffb75a1a", "result": { "engine": "jupyter", - "markdown": "---\ntitle: \"Cross References\"\nformat: html\ntoc-expand: 2\ntoc-depth: 4\naliases: \n - /docs/authoring/cross-references-listings.html\n - /docs/authoring/cross-references-callouts.html\n---\n\n## Overview\n\nCross-references make it easier for readers to navigate your document by providing numbered references and hyperlinks to various entities like figures and tables. Every cross-referenceable entity requires a label---a unique identifier prefixed with a cross-reference type e.g. `#fig-element`. For example, this is a cross-referenceable figure:\n\n``` markdown\n![Elephant](elephant.png){#fig-elephant}\n```\n\nThe presence of the label (`#fig-elephant`) makes this figure referenceable. This enables you to use the following syntax to refer to it elsewhere in the document:\n\n``` markdown\nSee @fig-elephant for an illustration.\n```\n\nHere is what this would look like rendered to HTML:\n\n![](images/crossref-figure.png){.border fig-alt=\"A line drawing of an elephant. The caption 'Figure 1: Elephant' is centered beneath it.\" width=\"100%\"}\n\nNote that cross reference identifiers must start with their type (e.g. `fig-` or `tbl-`). So the identifier `#fig-elephant` is valid for a cross-reference but the identifiers `#elephant` and `#elephant-fig` are not.\n\n::: {#reserved-prefixes}\n::: {.callout-warning}\n\n## Reserved Prefixes \n\nUnless you are creating a cross-reference, avoid using the reserved cross-reference prefixes for code cell labels (e.g. set using the `label` code cell option) and element IDs (set using a `#` in an attribute). \n \nThe reserved prefixes are: `fig`, `tbl`, `lst`, `tip`, `nte`, `wrn`, `imp`, `cau`, `thm`, `lem`, `cor`, `prp`, `cnj`, `def`, `exm`, `exr`, `sol`, `rem`, `alg`, `eq`, `sec`.\n\nAlso avoid using underscores (`_`) in labels and IDs as this can cause problems when rendering to PDF with LaTeX.\n\n:::\n:::\n\nQuarto enables you to create cross-references to figures, tables, equations, sections, code listings, theorems, proofs, and more. Cross references can also be applied to dynamic output from Knitr and Jupyter. \n\nOn this page you'll learn:\n\n* Different ways to use the `@` syntax to create [References](#references).\n* How to add [Lists](#lists) of references in LaTeX / PDF output.\n\nThen, we enumerate the syntax for the different types of elements you might want to reference:\n\n* [Floats](#floats): [Figures](#figures), [Tables](#tables) and [Code Listings](#code-listings)\n* Blocks: [Callouts](#callouts), [Theorems and Proofs](#theorems-and-proofs) and [Equations](#equations) \n* [Sections](#sections)\n\nThere are options available that control the text used for titles and references. For example, you could change \"Figure 1\" to read \"Fig 1\" or \"fig. 1\". See the [options documentation](cross-reference-options.qmd) for details on how to customize the text used for cross-references.\n\n## References\n\nThe examples on this page all use the default syntax for inline references (e.g. `@fig-elephant`), which results in the reference text \"Figure 1\", \"Table 1\", etc.\n\nYou can customize the appearance of inline references by either changing the syntax of the inline reference or by setting options. Here are the various ways to compose a cross-reference and their resulting output:\n\n| Type | Syntax | Output |\n|---------------|-----------------------|----------|\n| Default | `@fig-elephant` | Figure 1 |\n| Capitalized | `@Fig-elephant` | Figure 1 |\n| Custom Prefix | `[Fig @fig-elephant]` | Fig 1 |\n| No Prefix | `[-@fig-elephant]` | 1 |\n\nNote that the capitalized syntax makes no difference for the default output, but would indeed capitalize the first letter if the default prefix had been changed via an [option](cross-reference-options.qmd#references) to use lower case (e.g. \"fig.\").\n\nThese syntax variations work not only for Figures, but for all cross-referenceable elements in Quarto such as Tables, Equations, Theorems, and so on.\n\nYou can also group cross-references using the following syntax:\n\n``` markdown\nAs illustrated in [@fig-elephant; @fig-panther; @fig-rabbit].\n```\n\nThere are a number of options that can be used to further customize the treatment of cross-references. See the guide on [Cross Reference Options](cross-reference-options.qmd#references) for additional details.\n\n## Lists\n\nFor LaTeX / PDF output, you can use the raw LaTeX commands `\\listoffigures`, `\\listoftables` and `\\listoflistings` to produce listings of all figures, tables, etc. within a document. You can use the `lof-title`, `lot-title`, and `lol-title` crossref options to customize the title of the listing.\n\nFor example:\n\n``` markdown\n---\ntitle: \"My Document\"\ncrossref:\n lof-title: \"List of Figures\"\nformat: pdf\n---\n\n\\listoffigures\n```\n\nNote that the default titles for the lists use the form displayed above (i.e. \"List of \\\").\n\n## Floats\n\n[Figures](#figures), [tables](#tables) and [code listings](#code-listings) are known as \"float\" cross-references. Floats can appear in the rendered document at locations other than where they are defined, i.e. they float, and usually have captions. \n\nIn addition to the compact syntax for the most common uses of float cross-references, you can also define float cross-references with a div syntax. Use the div syntax when you need more flexibility in the content of your cross-reference, for example, to have a [video](cross-references-divs.qmd#videos) be referenced as a figure. Basic examples of the div syntax are included in the sections below, but you can find more complicated examples in [Cross-Reference Div Syntax](cross-references-divs.qmd). \n\nYou can also define custom types of float cross-reference to reference elements beyond figures, tables and code listings. Read more at [Custom Float Cross-References](cross-references-custom.qmd).\n\n\n### Figures\n\nAs described on the Overview above, this is the markdown used to create a cross-referenceable figure and then refer to it:\n\n``` markdown\n![Elephant](elephant.png){#fig-elephant}\n\nSee @fig-elephant for an illustration.\n```\n\nNote again that cross-reference identifiers must start with their type (e.g. `#fig-`) and that cross-reference identifiers must be all lower case.\n\nTo create a cross-reference to a figure using div syntax, create a fenced div with an id starting with `fig-`, include the image followed by the caption inside the div:\n\n````markdown\n::: {#fig-elephant}\n\n![](elephant.png)\n\nAn Elephant\n:::\n````\n\n\nYou can read about using div syntax with figures at [Cross-Reference Div Syntax](cross-references-divs.qmd#figures).\n\n#### Subfigures\n\nYou may want to create a figure composed of multiple subfigures. To do this, enclose the figures in a div (with its own label and caption) and give each subfigure its own label and (optionally) caption. You can then refer to either the entire figure in a reference or a single subfigure:\n\n``` markdown\n::: {#fig-elephants layout-ncol=2}\n\n![Surus](surus.png){#fig-surus}\n\n![Hanno](hanno.png){#fig-hanno}\n\nFamous Elephants\n:::\n\nSee @fig-elephants for examples. In particular, @fig-hanno.\n```\n\nHere is what this looks like when rendered as HTML:\n\n![](images/crossref-subfigures.png){.preview-image .border fig-alt=\"An artistic rendition of Surus, Hannibal's last war elephant, is on the left. Underneath this picture is the caption '(a) Surus.' On the right is a line drawing of Hanno, a famous elephant. Underneath this picture is the caption '(b) Hanno.' The words 'Figure 1: Famous elephants' are centered beneath both pictures. The text 'See fig. 1 for examples. In particular, fig. 1(b).' is underneath this text and is aligned to the left.\" width=\"100%\"}\n\nNote that we also used the `layout-ncol` attribute to specify a two-column layout. See the article on [Figures](figures.qmd) for more details on laying out panels of figures.\n\n#### Computations\n\nFigures produced by Jupyter and Knitr can also be cross-referenced. To do this, add a `label` and `fig-cap` option at the top of the code block. For example:\n\n::: panel-tabset\n##### Jupyter\n\n ```{{python}}\n #| label: fig-plot\n #| fig-cap: \"Plot\"\n\n import matplotlib.pyplot as plt\n plt.plot([1,23,2,4])\n plt.show()\n ```\n\n For example, see @fig-plot.\n\n![](images/crossref-figure-jupyter.png){fig-alt=\"A line plot with the label 'Figure 1: Plot' centered underneath it. The text 'For example, see fig. 1' is underneath this label and aligned to the left.\"}\n\n##### Knitr\n\n ```{{r}}\n #| label: fig-plot\n #| fig-cap: \"Plot\"\n\n plot(cars)\n ```\n\n For example, see @fig-plot.\n\n![](images/crossref-figure-r.png){fig-alt=\"A scatter plot of speed versus distance for the `cars` dataset. The label 'Figure 1: Plot' is centered beneath it. The text 'For example, see fig. 1' is aligned to the left underneath that.\"}\n:::\n\n::: {.callout-tip}\n\n## Computed Captions\n\nIf you need to generate a dynamic caption, instead of using the `fig-cap` or `tbl-cap` code cell option, combine inline code with the [Cross-Reference Div Syntax](/docs/authoring/cross-references-divs.qmd#computed-captions).\n\n:::\n\n\nYou can also create multiple figures within a code cell and reference them as subfigures. To do this use `fig-cap` for the main caption, and `fig-subcap` to provide an array of subcaptions. For example:\n\n ```{{python}}\n #| label: fig-plots\n #| fig-cap: \"Plots\" \n #| fig-subcap:\n #| - \"Plot 1\"\n #| - \"Plot 2\" \n #| layout-ncol: 2\n\n import matplotlib.pyplot as plt\n plt.plot([1,23,2,4])\n plt.show()\n\n plt.plot([8,65,23,90])\n plt.show()\n ```\n\n See @fig-plots for examples. In particular, @fig-plots-2.\n\n![](images/crossref-subfigures-jupyter.png){fig-alt=\"Two line plots side-by-side. The plot on the left has the caption '(a) Plot 1' centered underneath it. The plot on the right has the caption '(b) Plot 2' centered underneath it. The text 'Figure 1: Plots' is centered underneath both of these plots. The text 'See fig. 1 for examples. In particular, fig. 1(b)' is aligned to the left underneath that.\"}\n\nNote that subfigure reference labels are created automatically based on the main chunk label (e.g. `@fig-plots-1`, `@fig-plots-2`, etc.).\n\nIf you'd like subfigure captions that include only an identifier, e.g. \"(a)\", and not a text caption, then specify `fig-subcap: true` rather than providing explicit subcaption text:\n\n```{{python}}\n#| label: fig-plots\n#| fig-cap: \"Plots\" \n#| fig-subcap: true\n#| layout-ncol: 2\n```\n\n### Tables\n\n\n\nFor markdown tables, add a caption below the table, then include a `#tbl-` label in braces at the end of the caption. For example:\n\n``` markdown\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: My Caption {#tbl-letters}\n\nSee @tbl-letters.\n```\n\nWhich looks like this when rendered to HTML:\n\n::: light-content\n![](images/crossref-table.png){fig-alt=\"A table with 3 columns and four rows. The text 'Table 1: My Caption' is above the header column. The text 'See tbl. 1' is aligned to the left underneath the last column.\" width=\"500\"}\n:::\n\n::: dark-content\n![](images/crossref-table-dark.png){fig-alt=\"A table with 3 columns and four rows. The text 'Table 1: My Caption' is above the header column. The text 'See tbl. 1' is aligned to the left underneath the last column.\" width=\"500\"}\n:::\n\n\n::: callout-important\n## Label Prefix\n\nIn order for a table to be cross-referenceable, its label must start with the `tbl-` prefix.\n:::\n\nTo create a cross-reference to a table using div syntax, create a fenced div with an id starting with `tbl-`, include the table followed by the caption inside the div:\n\n````markdown\n::: {#tbl-letters}\n\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\nMy Caption\n\n::: \n````\n\n\nYou can read more about using div syntax with tables at [Cross-Reference Div Syntax](cross-references-divs.qmd#tables).\n\n#### Subtables\n\nYou may want to create a composition of several sub-tables. To do this, create a div with a main identifier, then apply sub-identifiers (and optional caption text) to the contained tables. For example:\n\n``` markdown\n::: {#tbl-panel layout-ncol=2}\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: First Table {#tbl-first}\n\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: Second Table {#tbl-second}\n\nMain Caption\n:::\n\nSee @tbl-panel for details, especially @tbl-second.\n```\n\nWhich looks like this when rendered to HTML:\n\n![](/docs/authoring/images/crossref-subtable.png){fig-alt=\"Two tables side-by-side. Both tables have 3 columns and 4 rows. The table on the left is titled '(a) First table'. The table on the right is titled '(b) Second Table'. Centered underneath both tables is the text 'Table 1: Main Caption'. The text 'See tbl. 2 for details, especially tbl. 2 (b)' is aligned to the left underneath that.\"}\n\nNote that the \"Main Caption\" for the table is provided as the last block within the containing div.\n\n\n#### Computations\n\nYou can also cross-reference tables created from code executed via computations. To do this, add the `label` and `tbl-cap` cell options. For example:\n\n```{{r}}\n#| label: tbl-iris\n#| tbl-cap: \"Iris Data\"\n\nlibrary(knitr)\nkable(head(iris))\n```\n\n![](/docs/authoring/images/crossref-table-knitr.png){fig-alt=\"Example table output.\" fig-align=\"center\" width=\"80%\"}\n\n::: {.callout-tip}\n\n## Computed Captions\n\nIf you need to generate a dynamic caption, instead of using the `fig-cap` or `tbl-cap` code cell option, combine inline code with the [Cross-Reference Div Syntax](/docs/authoring/cross-references-divs.qmd#computed-captions).\n\n:::\n\n\nYou can also create multiple tables within a code cell and reference them as subtables. To do this, add a `tbl-subcap` option with an array of subcaptions. For example:\n\n```{{r}}\n#| label: tbl-tables\n#| tbl-cap: \"Tables\"\n#| tbl-subcap:\n#| - \"Cars\"\n#| - \"Pressure\"\n#| layout-ncol: 2\n\nlibrary(knitr)\nkable(head(cars))\nkable(head(pressure))\n```\n\n![](/docs/authoring/images/crossref-subtable-knitr.png){fig-alt=\"Two tables side-by-side. Each table has 2 columns and 8 rows. The table on the left is titled '(a) Cars'. The table on the right is titled '(b) Pressure'. Centered underneath both tables is the text 'Table 1: Tables.'\" fig-align=\"center\" width=\"80%\"}\n\nIf you'd like subtable captions that include only an identifier, e.g. \"(a)\", and not a text caption, then specify `tbl-subcap: true` rather than providing explicit subcaption text:\n\n```{{r}}\n#| label: tbl-tables\n#| tbl-cap: \"Tables\"\n#| tbl-subcap: true\n#| layout-ncol: 2\n\nlibrary(knitr)\nkable(head(cars))\nkable(head(pressure))\n```\n\n![](/docs/authoring/images/crossref-subtable-nocaption-knitr.png){fig-align=\"center\" width=\"80%\"}\n\n\n### Code Listings\n\nTo create a reference-able code block, add a `#lst-` identifier along with a `lst-cap` attribute. For example:\n\n```` markdown\n```{#lst-customers .sql lst-cap=\"Customers Query\"}\nSELECT * FROM Customers\n```\n\nThen we query the customers database (@lst-customers).\n````\n\nTo create a cross-reference to a code listing using div syntax, create a fenced div with an id starting with `lst-`, include the code cell followed by the caption inside the div: \n\n````markdown\n::: {#lst-customers}\n\n```{.sql}\nSELECT * FROM Customers\n```\n\nCustomers Query\n\n:::\n````\n\n\nYou can read more about using div syntax for code listings in [Cross-Reference Div Syntax](cross-references-divs.qmd).\n\nTo cross-reference code from an executable code block, add the code cell options `lst-label` and `lst-cap`. The option `lst-label` provides the cross reference identifier and must begin with the prefix `lst-` to be treated as a code listing. The value of `lst-cap` provides the caption for the code listing. For example:\n\n````{.markdown}\n```{{python}}\n#| lst-label: lst-import\n#| lst-cap: Import pyplot\n\nimport matplotlib.pyplot as plt\n```\n\n@lst-import...\n````\n\nWhen rendered, this results in the following:\n\n::: {.border .p-3}\n\n::: {#30d5a652 .cell execution_count=1}\n``` {#lst-import .python .cell-code lst-cap=\"Import pyplot\"}\nimport matplotlib.pyplot as plt\n```\n:::\n\n\n@lst-import...\n\n:::\n\nIf the code cell produces a figure or table, you can combine the `lst-` options with `label` and `fig-cap`/`tbl-cap` to create cross references to both the code and output:\n\n````{.markdown}\n```{{python}}\n#| label: fig-plot\n#| fig-cap: Figure caption\n#| lst-label: lst-plot\n#| lst-cap: Listing caption\n\nplt.plot([1,23,2,4])\nplt.show()\n```\n\nThe code in @lst-plot produces the figure in @fig-plot.\n````\n\nWhen rendered, this produces the following output:\n\n:::{.border .p-3}\n\n::: {#cell-fig-plot .cell execution_count=2}\n``` {#lst-plot .python .cell-code lst-cap=\"Listing caption\"}\nplt.plot([1,23,2,4])\nplt.show()\n```\n\n::: {.cell-output .cell-output-display}\n![Figure caption](cross-references_files/figure-html/fig-plot-output-1.png){#fig-plot width=566 height=411}\n:::\n:::\n\n\nThe code in @lst-plot produces the plot in @fig-plot.\n:::\n\n\n## Callouts\n\nTo cross-reference a callout, add an ID attribute that starts with the appropriate callout prefix (see @tbl-callout-prefixes). You can then reference the callout using the usual `@` syntax. For example, here we add the ID `#tip-example` to the callout, and then refer back to it:\n\n``` markdown\n::: {#tip-example .callout-tip}\n## Cross-Referencing a Tip\n\nAdd an ID starting with `#tip-` to reference a tip.\n:::\n\nSee @tip-example...\n```\n\nThis renders as follows:\n\n::: {.border .p-3}\n::: {#tip-example .callout-tip}\n## Cross-Referencing a Tip\n\nAdd an ID starting with `#tip-` to reference a tip.\n:::\n\nSee @tip-example...\n:::\n\nThe prefixes for each type of callout are:\n\n| Callout Type | Prefix |\n|--------------|---------|\n| `note` | `#nte-` |\n| `tip` | `#tip-` |\n| `warning` | `#wrn-` |\n| `important` | `#imp-` |\n| `caution` | `#cau-` |\n\n: Prefixes for callout cross-references {#tbl-callout-prefixes}\n\nThe text used for each callout cross-reference (for example, \"Note 1\" in \"See Note 1...\") can be localised by setting `crossref-{nte,tip,wrn,imp,cau}-prefix` under `language:`:\n\n``` yaml\n---\nlang: fr\nlanguage:\n crossref-nte-prefix: \"Note\"\n crossref-tip-prefix: \"Astuce\"\n crossref-wrn-prefix: \"Avertissement\"\n crossref-imp-prefix: \"Important\"\n crossref-cau-prefix: \"Mise en garde\"\n---\n```\n\nSee [Cross-Reference Titles and Prefixes](language.qmd#cross-reference-titles-and-prefixes) for the full localisation pattern, including per-language subkeys.\n\n\n## Theorems and Proofs\n\nTheorems are commonly used in articles and books in mathematics. To include a reference-able theorem, create a div with a `#thm-` label (or one of other theorem-type labels described below). You also need to specify a theorem name either via the first heading in the block. You can include any content you like within the div. For example:\n\n``` markdown\n::: {#thm-line}\n\n## Line\n\nThe equation of any straight line, called a linear equation, can be written as:\n\n$$\ny = mx + b\n$$\n:::\n\nSee @thm-line.\n```\n\n![](images/crossref-theorem.png){fig-alt=\"A snippet of a LaTeX document. The first line reads: 'Thereom 1 (Line) The equation of any straight line, called a linear equation, can be written as:' Cenetered on a separate line is the equation 'y = mx + b'. The text 'See thm. 1' is aligned to the left underneath that.\"}\n\nFor LaTeX output, the [amsthm](https://ctan.org/pkg/amsthm?lang=en) package is used for typesetting theorems. For other formats an appropriate treatment is used (the above is an example of HTML output).\n\nThere are a number of theorem variations supported, each with their own label prefix:\n\n| **Label Prefix** | **Printed Name** | **LaTeX Environment** |\n|------------------|------------------|-----------------------|\n| `#thm-` | Theorem | theorem |\n| `#lem-` | Lemma | lemma |\n| `#cor-` | Corollary | corollary |\n| `#prp-` | Proposition | proposition |\n| `#cnj-` | Conjecture | conjecture |\n| `#def-` | Definition | definition |\n| `#exm-` | Example | example |\n| `#exr-` | Exercise | exercise |\n| `#sol-` | Solution | solution |\n| `#rem-` | Remark | remark |\n| `#alg-` | Algorithm | algorithm |\n\nThe `proof` environment receives similar typesetting as theorems, however it is not numbered (and therefore cannot be cross-referenced). To create a proof add the `.proof` class to a div:\n\n``` markdown\n::: {.proof}\nBy induction.\n:::\n```\n\nAs with theorems you can optionally include a heading as the first element of the div (or a `name` attribute) to give the environment a caption for typesetting (this typically appears in parentheses after the environment title).\n\nFor LaTeX output the [amsthm](https://ctan.org/pkg/amsthm?lang=en) package is used to typeset these environments. For other formats a similar treatment is used, but you can further customizing this using CSS.\n\n## Equations\n\nProvide an `#eq-` label immediately after an equation to make it referenceable. For example:\n\n``` markdown\nBlack-Scholes (@eq-black-scholes) is a mathematical model that seeks to explain the behavior of financial derivatives, most commonly options:\n\n$$\n\\frac{\\partial \\mathrm C}{ \\partial \\mathrm t } + \\frac{1}{2}\\sigma^{2} \\mathrm S^{2}\n\\frac{\\partial^{2} \\mathrm C}{\\partial \\mathrm S^2}\n + \\mathrm r \\mathrm S \\frac{\\partial \\mathrm C}{\\partial \\mathrm S}\\ =\n \\mathrm r \\mathrm C \n$$ {#eq-black-scholes}\n```\n\nBlack-Scholes (@eq-black-scholes) is a mathematical model that seeks to explain the behavior of financial derivatives, most commonly options:\n\n$$\n\\frac{\\partial \\mathrm C}{ \\partial \\mathrm t } + \\frac{1}{2}\\sigma^{2} \\mathrm S^{2}\n\\frac{\\partial^{2} \\mathrm C}{\\partial \\mathrm S^2}\n + \\mathrm r \\mathrm S \\frac{\\partial \\mathrm C}{\\partial \\mathrm S}\\ =\n \\mathrm r \\mathrm C \n$$ {#eq-black-scholes}\n\nNote that the equation number is included (via `\\qquad`) in the right margin of the equation.\n\n## Sections\n\nTo reference a section, add a `#sec-` identifier to any heading. For example:\n\n``` markdown\n## Introduction {#sec-introduction}\n\nSee @sec-introduction for additional context.\n```\n\nNote that when using section cross-references, you will also need to enable the `number-sections` option (so that section numbering is visible to readers). For example:\n\n``` yaml\n---\ntitle: \"My Document\"\nnumber-sections: true\n---\n```\n\n", + "markdown": "---\ntitle: \"Cross References\"\nformat: html\ntoc-expand: 2\ntoc-depth: 4\naliases: \n - /docs/authoring/cross-references-listings.html\n - /docs/authoring/cross-references-callouts.html\n---\n\n## Overview\n\nCross-references make it easier for readers to navigate your document by providing numbered references and hyperlinks to various entities like figures and tables. Every cross-referenceable entity requires a label---a unique identifier prefixed with a cross-reference type e.g. `#fig-element`. For example, this is a cross-referenceable figure:\n\n``` markdown\n![Elephant](elephant.png){#fig-elephant}\n```\n\nThe presence of the label (`#fig-elephant`) makes this figure referenceable. This enables you to use the following syntax to refer to it elsewhere in the document:\n\n``` markdown\nSee @fig-elephant for an illustration.\n```\n\nHere is what this would look like rendered to HTML:\n\n![](images/crossref-figure.png){.border fig-alt=\"A line drawing of an elephant. The caption 'Figure 1: Elephant' is centered beneath it.\" width=\"100%\"}\n\nNote that cross reference identifiers must start with their type (e.g. `fig-` or `tbl-`). So the identifier `#fig-elephant` is valid for a cross-reference but the identifiers `#elephant` and `#elephant-fig` are not.\n\n::: {#reserved-prefixes}\n::: {.callout-warning}\n\n## Reserved Prefixes \n\nUnless you are creating a cross-reference, avoid using the reserved cross-reference prefixes for code cell labels (e.g. set using the `label` code cell option) and element IDs (set using a `#` in an attribute). \n \nThe reserved prefixes are: `fig`, `tbl`, `lst`, `tip`, `nte`, `wrn`, `imp`, `cau`, `thm`, `lem`, `cor`, `prp`, `cnj`, `def`, `exm`, `exr`, `sol`, `rem`, `alg`, `eq`, `sec`.\n\nAlso avoid using underscores (`_`) in labels and IDs as this can cause problems when rendering to PDF with LaTeX.\n\n:::\n:::\n\nQuarto enables you to create cross-references to figures, tables, equations, sections, code listings, theorems, proofs, and more. Cross references can also be applied to dynamic output from Knitr and Jupyter. \n\nOn this page you'll learn:\n\n* Different ways to use the `@` syntax to create [References](#references).\n* How to add [Lists](#lists) of references in LaTeX / PDF output.\n\nThen, we enumerate the syntax for the different types of elements you might want to reference:\n\n* [Floats](#floats): [Figures](#figures), [Tables](#tables) and [Code Listings](#code-listings)\n* Blocks: [Callouts](#callouts), [Theorems and Proofs](#theorems-and-proofs) and [Equations](#equations) \n* [Sections](#sections)\n\nThere are options available that control the text used for titles and references. For example, you could change \"Figure 1\" to read \"Fig 1\" or \"fig. 1\". See the [options documentation](cross-reference-options.qmd) for details on how to customize the text used for cross-references.\n\n## References\n\nThe examples on this page all use the default syntax for inline references (e.g. `@fig-elephant`), which results in the reference text \"Figure 1\", \"Table 1\", etc.\n\nYou can customize the appearance of inline references by either changing the syntax of the inline reference or by setting options. Here are the various ways to compose a cross-reference and their resulting output:\n\n| Type | Syntax | Output |\n|---------------|-----------------------|----------|\n| Default | `@fig-elephant` | Figure 1 |\n| Capitalized | `@Fig-elephant` | Figure 1 |\n| Custom Prefix | `[Fig @fig-elephant]` | Fig 1 |\n| No Prefix | `[-@fig-elephant]` | 1 |\n\nNote that the capitalized syntax makes no difference for the default output, but would indeed capitalize the first letter if the default prefix had been changed via an [option](cross-reference-options.qmd#references) to use lower case (e.g. \"fig.\").\n\nThese syntax variations work not only for Figures, but for all cross-referenceable elements in Quarto such as Tables, Equations, Theorems, and so on.\n\nYou can also group cross-references using the following syntax:\n\n``` markdown\nAs illustrated in [@fig-elephant; @fig-panther; @fig-rabbit].\n```\n\nThere are a number of options that can be used to further customize the treatment of cross-references. See the guide on [Cross Reference Options](cross-reference-options.qmd#references) for additional details.\n\n## Lists\n\nFor LaTeX / PDF output, you can use the raw LaTeX commands `\\listoffigures`, `\\listoftables` and `\\listoflistings` to produce listings of all figures, tables, etc. within a document. You can use the `lof-title`, `lot-title`, and `lol-title` crossref options to customize the title of the listing.\n\nFor example:\n\n``` markdown\n---\ntitle: \"My Document\"\ncrossref:\n lof-title: \"List of Figures\"\nformat: pdf\n---\n\n\\listoffigures\n```\n\nNote that the default titles for the lists use the form displayed above (i.e. \"List of \\\").\n\n## Floats\n\n[Figures](#figures), [tables](#tables) and [code listings](#code-listings) are known as \"float\" cross-references. Floats can appear in the rendered document at locations other than where they are defined, i.e. they float, and usually have captions. \n\nIn addition to the compact syntax for the most common uses of float cross-references, you can also define float cross-references with a div syntax. Use the div syntax when you need more flexibility in the content of your cross-reference, for example, to have a [video](cross-references-divs.qmd#videos) be referenced as a figure. Basic examples of the div syntax are included in the sections below, but you can find more complicated examples in [Cross-Reference Div Syntax](cross-references-divs.qmd). \n\nYou can also define custom types of float cross-reference to reference elements beyond figures, tables and code listings. Read more at [Custom Float Cross-References](cross-references-custom.qmd).\n\n\n### Figures\n\nAs described on the Overview above, this is the markdown used to create a cross-referenceable figure and then refer to it:\n\n``` markdown\n![Elephant](elephant.png){#fig-elephant}\n\nSee @fig-elephant for an illustration.\n```\n\nNote again that cross-reference identifiers must start with their type (e.g. `#fig-`) and that cross-reference identifiers must be all lower case.\n\nTo create a cross-reference to a figure using div syntax, create a fenced div with an id starting with `fig-`, include the image followed by the caption inside the div:\n\n````markdown\n::: {#fig-elephant}\n\n![](elephant.png)\n\nAn Elephant\n:::\n````\n\n\nYou can read about using div syntax with figures at [Cross-Reference Div Syntax](cross-references-divs.qmd#figures).\n\n#### Subfigures\n\nYou may want to create a figure composed of multiple subfigures. To do this, enclose the figures in a div (with its own label and caption) and give each subfigure its own label and (optionally) caption. You can then refer to either the entire figure in a reference or a single subfigure:\n\n``` markdown\n::: {#fig-elephants layout-ncol=2}\n\n![Surus](surus.png){#fig-surus}\n\n![Hanno](hanno.png){#fig-hanno}\n\nFamous Elephants\n:::\n\nSee @fig-elephants for examples. In particular, @fig-hanno.\n```\n\nHere is what this looks like when rendered as HTML:\n\n![](images/crossref-subfigures.png){.preview-image .border fig-alt=\"An artistic rendition of Surus, Hannibal's last war elephant, is on the left. Underneath this picture is the caption '(a) Surus.' On the right is a line drawing of Hanno, a famous elephant. Underneath this picture is the caption '(b) Hanno.' The words 'Figure 1: Famous elephants' are centered beneath both pictures. The text 'See fig. 1 for examples. In particular, fig. 1(b).' is underneath this text and is aligned to the left.\" width=\"100%\"}\n\nNote that we also used the `layout-ncol` attribute to specify a two-column layout. See the article on [Figures](figures.qmd) for more details on laying out panels of figures.\n\n#### Computations\n\nFigures produced by Jupyter and Knitr can also be cross-referenced. To do this, add a `label` and `fig-cap` option at the top of the code block. For example:\n\n::: panel-tabset\n##### Jupyter\n\n ```{{python}}\n #| label: fig-plot\n #| fig-cap: \"Plot\"\n\n import matplotlib.pyplot as plt\n plt.plot([1,23,2,4])\n plt.show()\n ```\n\n For example, see @fig-plot.\n\n![](images/crossref-figure-jupyter.png){fig-alt=\"A line plot with the label 'Figure 1: Plot' centered underneath it. The text 'For example, see fig. 1' is underneath this label and aligned to the left.\"}\n\n##### Knitr\n\n ```{{r}}\n #| label: fig-plot\n #| fig-cap: \"Plot\"\n\n plot(cars)\n ```\n\n For example, see @fig-plot.\n\n![](images/crossref-figure-r.png){fig-alt=\"A scatter plot of speed versus distance for the `cars` dataset. The label 'Figure 1: Plot' is centered beneath it. The text 'For example, see fig. 1' is aligned to the left underneath that.\"}\n:::\n\n::: {.callout-tip}\n\n## Computed Captions\n\nIf you need to generate a dynamic caption, instead of using the `fig-cap` or `tbl-cap` code cell option, combine inline code with the [Cross-Reference Div Syntax](/docs/authoring/cross-references-divs.qmd#computed-captions).\n\n:::\n\n\nYou can also create multiple figures within a code cell and reference them as subfigures. To do this use `fig-cap` for the main caption, and `fig-subcap` to provide an array of subcaptions. For example:\n\n ```{{python}}\n #| label: fig-plots\n #| fig-cap: \"Plots\" \n #| fig-subcap:\n #| - \"Plot 1\"\n #| - \"Plot 2\" \n #| layout-ncol: 2\n\n import matplotlib.pyplot as plt\n plt.plot([1,23,2,4])\n plt.show()\n\n plt.plot([8,65,23,90])\n plt.show()\n ```\n\n See @fig-plots for examples. In particular, @fig-plots-2.\n\n![](images/crossref-subfigures-jupyter.png){fig-alt=\"Two line plots side-by-side. The plot on the left has the caption '(a) Plot 1' centered underneath it. The plot on the right has the caption '(b) Plot 2' centered underneath it. The text 'Figure 1: Plots' is centered underneath both of these plots. The text 'See fig. 1 for examples. In particular, fig. 1(b)' is aligned to the left underneath that.\"}\n\nNote that subfigure reference labels are created automatically based on the main chunk label (e.g. `@fig-plots-1`, `@fig-plots-2`, etc.).\n\nIf you'd like subfigure captions that include only an identifier, e.g. \"(a)\", and not a text caption, then specify `fig-subcap: true` rather than providing explicit subcaption text:\n\n```{{python}}\n#| label: fig-plots\n#| fig-cap: \"Plots\" \n#| fig-subcap: true\n#| layout-ncol: 2\n```\n\n### Tables\n\n\n\nFor markdown tables, add a caption below the table, then include a `#tbl-` label in braces at the end of the caption. For example:\n\n``` markdown\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: My Caption {#tbl-letters}\n\nSee @tbl-letters.\n```\n\nWhich looks like this when rendered to HTML:\n\n::: light-content\n![](images/crossref-table.png){fig-alt=\"A table with 3 columns and four rows. The text 'Table 1: My Caption' is above the header column. The text 'See tbl. 1' is aligned to the left underneath the last column.\" width=\"500\"}\n:::\n\n::: dark-content\n![](images/crossref-table-dark.png){fig-alt=\"A table with 3 columns and four rows. The text 'Table 1: My Caption' is above the header column. The text 'See tbl. 1' is aligned to the left underneath the last column.\" width=\"500\"}\n:::\n\n\n::: callout-important\n## Label Prefix\n\nIn order for a table to be cross-referenceable, its label must start with the `tbl-` prefix.\n:::\n\nTo create a cross-reference to a table using div syntax, create a fenced div with an id starting with `tbl-`, include the table followed by the caption inside the div:\n\n````markdown\n::: {#tbl-letters}\n\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\nMy Caption\n\n::: \n````\n\n\nYou can read more about using div syntax with tables at [Cross-Reference Div Syntax](cross-references-divs.qmd#tables).\n\n#### Subtables\n\nYou may want to create a composition of several sub-tables. To do this, create a div with a main identifier, then apply sub-identifiers (and optional caption text) to the contained tables. For example:\n\n``` markdown\n::: {#tbl-panel layout-ncol=2}\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: First Table {#tbl-first}\n\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: Second Table {#tbl-second}\n\nMain Caption\n:::\n\nSee @tbl-panel for details, especially @tbl-second.\n```\n\nWhich looks like this when rendered to HTML:\n\n![](/docs/authoring/images/crossref-subtable.png){fig-alt=\"Two tables side-by-side. Both tables have 3 columns and 4 rows. The table on the left is titled '(a) First table'. The table on the right is titled '(b) Second Table'. Centered underneath both tables is the text 'Table 1: Main Caption'. The text 'See tbl. 2 for details, especially tbl. 2 (b)' is aligned to the left underneath that.\"}\n\nNote that the \"Main Caption\" for the table is provided as the last block within the containing div.\n\n\n#### Computations\n\nYou can also cross-reference tables created from code executed via computations. To do this, add the `label` and `tbl-cap` cell options. For example:\n\n```{{r}}\n#| label: tbl-iris\n#| tbl-cap: \"Iris Data\"\n\nlibrary(knitr)\nkable(head(iris))\n```\n\n![](/docs/authoring/images/crossref-table-knitr.png){fig-alt=\"Example table output.\" fig-align=\"center\" width=\"80%\"}\n\n::: {.callout-tip}\n\n## Computed Captions\n\nIf you need to generate a dynamic caption, instead of using the `fig-cap` or `tbl-cap` code cell option, combine inline code with the [Cross-Reference Div Syntax](/docs/authoring/cross-references-divs.qmd#computed-captions).\n\n:::\n\n\nYou can also create multiple tables within a code cell and reference them as subtables. To do this, add a `tbl-subcap` option with an array of subcaptions. For example:\n\n```{{r}}\n#| label: tbl-tables\n#| tbl-cap: \"Tables\"\n#| tbl-subcap:\n#| - \"Cars\"\n#| - \"Pressure\"\n#| layout-ncol: 2\n\nlibrary(knitr)\nkable(head(cars))\nkable(head(pressure))\n```\n\n![](/docs/authoring/images/crossref-subtable-knitr.png){fig-alt=\"Two tables side-by-side. Each table has 2 columns and 8 rows. The table on the left is titled '(a) Cars'. The table on the right is titled '(b) Pressure'. Centered underneath both tables is the text 'Table 1: Tables.'\" fig-align=\"center\" width=\"80%\"}\n\nIf you'd like subtable captions that include only an identifier, e.g. \"(a)\", and not a text caption, then specify `tbl-subcap: true` rather than providing explicit subcaption text:\n\n```{{r}}\n#| label: tbl-tables\n#| tbl-cap: \"Tables\"\n#| tbl-subcap: true\n#| layout-ncol: 2\n\nlibrary(knitr)\nkable(head(cars))\nkable(head(pressure))\n```\n\n![](/docs/authoring/images/crossref-subtable-nocaption-knitr.png){fig-alt=\"Two tables side-by-side, with identifier-only subcaptions. The table on the left is titled '(a)' and has columns 'speed' and 'dist'. The table on the right is titled '(b)' and has columns 'temperature' and 'pressure'. Centered above both tables is the text 'Table 1: Tables'.\" fig-align=\"center\" width=\"80%\"}\n\n\n### Code Listings\n\nTo create a reference-able code block, add a `#lst-` identifier along with a `lst-cap` attribute. For example:\n\n```` markdown\n```{#lst-customers .sql lst-cap=\"Customers Query\"}\nSELECT * FROM Customers\n```\n\nThen we query the customers database (@lst-customers).\n````\n\nTo create a cross-reference to a code listing using div syntax, create a fenced div with an id starting with `lst-`, include the code cell followed by the caption inside the div: \n\n````markdown\n::: {#lst-customers}\n\n```{.sql}\nSELECT * FROM Customers\n```\n\nCustomers Query\n\n:::\n````\n\n\nYou can read more about using div syntax for code listings in [Cross-Reference Div Syntax](cross-references-divs.qmd).\n\nTo cross-reference code from an executable code block, add the code cell options `lst-label` and `lst-cap`. The option `lst-label` provides the cross reference identifier and must begin with the prefix `lst-` to be treated as a code listing. The value of `lst-cap` provides the caption for the code listing. For example:\n\n````{.markdown}\n```{{python}}\n#| lst-label: lst-import\n#| lst-cap: Import pyplot\n\nimport matplotlib.pyplot as plt\n```\n\n@lst-import...\n````\n\nWhen rendered, this results in the following:\n\n::: {.border .p-3}\n\n::: {#4fb44c2c .cell execution_count=1}\n``` {#lst-import .python .cell-code lst-cap=\"Import pyplot\"}\nimport matplotlib.pyplot as plt\n```\n:::\n\n\n@lst-import...\n\n:::\n\nIf the code cell produces a figure or table, you can combine the `lst-` options with `label` and `fig-cap`/`tbl-cap` to create cross references to both the code and output:\n\n````{.markdown}\n```{{python}}\n#| label: fig-plot\n#| fig-cap: Figure caption\n#| lst-label: lst-plot\n#| lst-cap: Listing caption\n\nplt.plot([1,23,2,4])\nplt.show()\n```\n\nThe code in @lst-plot produces the figure in @fig-plot.\n````\n\nWhen rendered, this produces the following output:\n\n:::{.border .p-3}\n\n::: {#cell-fig-plot .cell execution_count=2}\n``` {#lst-plot .python .cell-code lst-cap=\"Listing caption\"}\nplt.plot([1,23,2,4])\nplt.show()\n```\n\n::: {.cell-output .cell-output-display}\n![Figure caption](cross-references_files/figure-html/fig-plot-output-1.png){#fig-plot width=566 height=411 fig-alt='Line plot of four values that rises steeply from 1 to 23, drops back to 2, then rises slightly to 4.'}\n:::\n:::\n\n\nThe code in @lst-plot produces the plot in @fig-plot.\n:::\n\n\n## Callouts\n\nTo cross-reference a callout, add an ID attribute that starts with the appropriate callout prefix (see @tbl-callout-prefixes). You can then reference the callout using the usual `@` syntax. For example, here we add the ID `#tip-example` to the callout, and then refer back to it:\n\n``` markdown\n::: {#tip-example .callout-tip}\n## Cross-Referencing a Tip\n\nAdd an ID starting with `#tip-` to reference a tip.\n:::\n\nSee @tip-example...\n```\n\nThis renders as follows:\n\n::: {.border .p-3}\n::: {#tip-example .callout-tip}\n## Cross-Referencing a Tip\n\nAdd an ID starting with `#tip-` to reference a tip.\n:::\n\nSee @tip-example...\n:::\n\nThe prefixes for each type of callout are:\n\n| Callout Type | Prefix |\n|--------------|---------|\n| `note` | `#nte-` |\n| `tip` | `#tip-` |\n| `warning` | `#wrn-` |\n| `important` | `#imp-` |\n| `caution` | `#cau-` |\n\n: Prefixes for callout cross-references {#tbl-callout-prefixes}\n\nThe text used for each callout cross-reference (for example, \"Note 1\" in \"See Note 1...\") can be localised by setting `crossref-{nte,tip,wrn,imp,cau}-prefix` under `language:`:\n\n``` yaml\n---\nlang: fr\nlanguage:\n crossref-nte-prefix: \"Note\"\n crossref-tip-prefix: \"Astuce\"\n crossref-wrn-prefix: \"Avertissement\"\n crossref-imp-prefix: \"Important\"\n crossref-cau-prefix: \"Mise en garde\"\n---\n```\n\nSee [Cross-Reference Titles and Prefixes](language.qmd#cross-reference-titles-and-prefixes) for the full localisation pattern, including per-language subkeys.\n\n\n## Theorems and Proofs\n\nTheorems are commonly used in articles and books in mathematics. To include a reference-able theorem, create a div with a `#thm-` label (or one of other theorem-type labels described below). You also need to specify a theorem name either via the first heading in the block. You can include any content you like within the div. For example:\n\n``` markdown\n::: {#thm-line}\n\n## Line\n\nThe equation of any straight line, called a linear equation, can be written as:\n\n$$\ny = mx + b\n$$\n:::\n\nSee @thm-line.\n```\n\n![](images/crossref-theorem.png){fig-alt=\"A snippet of a LaTeX document. The first line reads: 'Thereom 1 (Line) The equation of any straight line, called a linear equation, can be written as:' Cenetered on a separate line is the equation 'y = mx + b'. The text 'See thm. 1' is aligned to the left underneath that.\"}\n\nFor LaTeX output, the [amsthm](https://ctan.org/pkg/amsthm?lang=en) package is used for typesetting theorems. For other formats an appropriate treatment is used (the above is an example of HTML output).\n\nThere are a number of theorem variations supported, each with their own label prefix:\n\n| **Label Prefix** | **Printed Name** | **LaTeX Environment** |\n|------------------|------------------|-----------------------|\n| `#thm-` | Theorem | theorem |\n| `#lem-` | Lemma | lemma |\n| `#cor-` | Corollary | corollary |\n| `#prp-` | Proposition | proposition |\n| `#cnj-` | Conjecture | conjecture |\n| `#def-` | Definition | definition |\n| `#exm-` | Example | example |\n| `#exr-` | Exercise | exercise |\n| `#sol-` | Solution | solution |\n| `#rem-` | Remark | remark |\n| `#alg-` | Algorithm | algorithm |\n\nThe `proof` environment receives similar typesetting as theorems, however it is not numbered (and therefore cannot be cross-referenced). To create a proof add the `.proof` class to a div:\n\n``` markdown\n::: {.proof}\nBy induction.\n:::\n```\n\nAs with theorems you can optionally include a heading as the first element of the div (or a `name` attribute) to give the environment a caption for typesetting (this typically appears in parentheses after the environment title).\n\nFor LaTeX output the [amsthm](https://ctan.org/pkg/amsthm?lang=en) package is used to typeset these environments. For other formats a similar treatment is used, but you can further customizing this using CSS.\n\n## Equations\n\nProvide an `#eq-` label immediately after an equation to make it referenceable. For example:\n\n``` markdown\nBlack-Scholes (@eq-black-scholes) is a mathematical model that seeks to explain the behavior of financial derivatives, most commonly options:\n\n$$\n\\frac{\\partial \\mathrm C}{ \\partial \\mathrm t } + \\frac{1}{2}\\sigma^{2} \\mathrm S^{2}\n\\frac{\\partial^{2} \\mathrm C}{\\partial \\mathrm S^2}\n + \\mathrm r \\mathrm S \\frac{\\partial \\mathrm C}{\\partial \\mathrm S}\\ =\n \\mathrm r \\mathrm C \n$$ {#eq-black-scholes}\n```\n\nBlack-Scholes (@eq-black-scholes) is a mathematical model that seeks to explain the behavior of financial derivatives, most commonly options:\n\n$$\n\\frac{\\partial \\mathrm C}{ \\partial \\mathrm t } + \\frac{1}{2}\\sigma^{2} \\mathrm S^{2}\n\\frac{\\partial^{2} \\mathrm C}{\\partial \\mathrm S^2}\n + \\mathrm r \\mathrm S \\frac{\\partial \\mathrm C}{\\partial \\mathrm S}\\ =\n \\mathrm r \\mathrm C \n$$ {#eq-black-scholes}\n\nNote that the equation number is included (via `\\qquad`) in the right margin of the equation.\n\n## Sections\n\nTo reference a section, add a `#sec-` identifier to any heading. For example:\n\n``` markdown\n## Introduction {#sec-introduction}\n\nSee @sec-introduction for additional context.\n```\n\nNote that when using section cross-references, you will also need to enable the `number-sections` option (so that section numbering is visible to readers). For example:\n\n``` yaml\n---\ntitle: \"My Document\"\nnumber-sections: true\n---\n```\n\n", "supporting": [ "cross-references_files" ], diff --git a/_freeze/docs/authoring/cross-references/figure-html/fig-plot-output-1.png b/_freeze/docs/authoring/cross-references/figure-html/fig-plot-output-1.png index f7534010ce..a4ca94ac2e 100644 Binary files a/_freeze/docs/authoring/cross-references/figure-html/fig-plot-output-1.png and b/_freeze/docs/authoring/cross-references/figure-html/fig-plot-output-1.png differ diff --git a/_freeze/docs/authoring/penguins-qmd/execute-results/html.json b/_freeze/docs/authoring/penguins-qmd/execute-results/html.json index a38dd52db3..42ac46b734 100644 --- a/_freeze/docs/authoring/penguins-qmd/execute-results/html.json +++ b/_freeze/docs/authoring/penguins-qmd/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "2824ad66844e803d9073ac9a3449a8eb", + "hash": "b22f6b75c97b15fbe219520be08b0e1f", "result": { "engine": "knitr", - "markdown": "---\ntitle: \"Palmer Penguins (`.qmd`)\"\n---\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(tidyverse)\n```\n\n::: {.cell-output .cell-output-stderr}\n\n```\n── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──\n✔ dplyr 1.1.2 ✔ readr 2.1.4\n✔ forcats 1.0.0 ✔ stringr 1.5.0\n✔ ggplot2 3.4.2 ✔ tibble 3.2.1\n✔ lubridate 1.9.2 ✔ tidyr 1.3.0\n✔ purrr 1.0.1 \n── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──\n✖ dplyr::filter() masks stats::filter()\n✖ dplyr::lag() masks stats::lag()\nℹ Use the conflicted package () to force all conflicts to become errors\n```\n\n\n:::\n\n```{.r .cell-code}\nlibrary(palmerpenguins)\n```\n:::\n\n\nData from [Palmer Penguins R package](https://allisonhorst.github.io/palmerpenguins/)\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\npenguins |> count(species)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 3 × 2\n species n\n \n1 Adelie 152\n2 Chinstrap 68\n3 Gentoo 124\n```\n\n\n:::\n:::\n\n::: {.cell}\n\n```{.r .cell-code}\ncolors <- c(\"#FF8C00\", \"#A020F0\", \"#008B8B\")\n```\n:::\n\n::: {.cell}\n\n```{.r .cell-code}\nggplot(penguins, aes(body_mass_g, flipper_length_mm)) +\n geom_point(aes(color = species)) +\n scale_color_manual(values = colors) +\n theme_minimal()\n```\n\n::: {.cell-output .cell-output-stderr}\n\n```\nWarning: Removed 2 rows containing missing values (`geom_point()`).\n```\n\n\n:::\n\n::: {.cell-output-display}\n![](penguins-qmd_files/figure-html/fig-size-scatter-1.png){#fig-size-scatter width=672}\n:::\n:::", + "markdown": "---\ntitle: \"Palmer Penguins (.qmd)\"\n---\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(tidyverse)\n```\n\n::: {.cell-output .cell-output-stderr}\n\n```\n── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──\n✔ dplyr 1.2.0 ✔ readr 2.1.6\n✔ forcats 1.0.1 ✔ stringr 1.6.0\n✔ ggplot2 4.0.2 ✔ tibble 3.3.1\n✔ lubridate 1.9.5 ✔ tidyr 1.3.2\n✔ purrr 1.2.1 \n── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──\n✖ dplyr::filter() masks stats::filter()\n✖ dplyr::lag() masks stats::lag()\nℹ Use the conflicted package () to force all conflicts to become errors\n```\n\n\n:::\n\n```{.r .cell-code}\nlibrary(palmerpenguins)\n```\n\n::: {.cell-output .cell-output-stderr}\n\n```\n\nAttaching package: 'palmerpenguins'\n\nThe following objects are masked from 'package:datasets':\n\n penguins, penguins_raw\n```\n\n\n:::\n:::\n\n\nData from [Palmer Penguins R package](https://allisonhorst.github.io/palmerpenguins/)\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\npenguins |> count(species)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 3 × 2\n species n\n \n1 Adelie 152\n2 Chinstrap 68\n3 Gentoo 124\n```\n\n\n:::\n:::\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncolors <- c(\"#FF8C00\", \"#A020F0\", \"#008B8B\")\n```\n:::\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nggplot(penguins, aes(body_mass_g, flipper_length_mm)) +\n geom_point(aes(color = species)) +\n scale_color_manual(values = colors) +\n theme_minimal()\n```\n\n::: {.cell-output .cell-output-stderr}\n\n```\nWarning: Removed 2 rows containing missing values or values outside the scale range\n(`geom_point()`).\n```\n\n\n:::\n\n::: {.cell-output-display}\n![](penguins-qmd_files/figure-html/fig-size-scatter-1.png){#fig-size-scatter fig-alt='Scatterplot of flipper length against body mass for 344 penguins, colored by species. Flipper length increases with body mass, and Gentoo penguins sit apart from Adelie and Chinstrap at the highest values of both.' width=288}\n:::\n:::\n", "supporting": [ "penguins-qmd_files" ], diff --git a/_freeze/docs/authoring/penguins-qmd/execute-results/ipynb.json b/_freeze/docs/authoring/penguins-qmd/execute-results/ipynb.json index d16e08e4c1..beaaf8d636 100644 --- a/_freeze/docs/authoring/penguins-qmd/execute-results/ipynb.json +++ b/_freeze/docs/authoring/penguins-qmd/execute-results/ipynb.json @@ -1,8 +1,8 @@ { - "hash": "7c58eb46b87208792a5f71c912c1c658", + "hash": "b22f6b75c97b15fbe219520be08b0e1f", "result": { "engine": "knitr", - "markdown": "---\ntitle: \"Palmer Penguins (.qmd)\"\n---\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(tidyverse)\n```\n\n::: {.cell-output .cell-output-stderr}\n\n```\n── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──\n✔ dplyr 1.1.2 ✔ readr 2.1.4\n✔ forcats 1.0.0 ✔ stringr 1.5.0\n✔ ggplot2 3.4.2 ✔ tibble 3.2.1\n✔ lubridate 1.9.2 ✔ tidyr 1.3.0\n✔ purrr 1.0.1 \n── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──\n✖ dplyr::filter() masks stats::filter()\n✖ dplyr::lag() masks stats::lag()\nℹ Use the conflicted package () to force all conflicts to become errors\n```\n\n\n:::\n\n```{.r .cell-code}\nlibrary(palmerpenguins)\n```\n:::\n\n\nData from [Palmer Penguins R package](https://allisonhorst.github.io/palmerpenguins/)\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\npenguins |> count(species)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 3 × 2\n species n\n \n1 Adelie 152\n2 Chinstrap 68\n3 Gentoo 124\n```\n\n\n:::\n:::\n\n::: {.cell}\n\n```{.r .cell-code}\ncolors <- c(\"#FF8C00\", \"#A020F0\", \"#008B8B\")\n```\n:::\n\n::: {#cell-fig-size-scatter .cell}\n\n```{.r .cell-code}\n#| label: fig-size-scatter\nggplot(penguins, aes(body_mass_g, flipper_length_mm)) +\n geom_point(aes(color = species)) +\n scale_color_manual(values = colors) +\n theme_minimal()\n```\n\n::: {.cell-output .cell-output-stderr}\n\n```\nWarning: Removed 2 rows containing missing values (`geom_point()`).\n```\n\n\n:::\n\n::: {.cell-output-display}\n![](penguins-qmd_files/figure-ipynb/fig-size-scatter-1.png){#fig-size-scatter}\n:::\n:::", + "markdown": "---\ntitle: \"Palmer Penguins (.qmd)\"\n---\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(tidyverse)\n```\n\n::: {.cell-output .cell-output-stderr}\n\n```\n── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──\n✔ dplyr 1.2.1 ✔ readr 2.2.0\n✔ forcats 1.0.1 ✔ stringr 1.6.0\n✔ ggplot2 4.0.3 ✔ tibble 3.3.1\n✔ lubridate 1.9.5 ✔ tidyr 1.3.2\n✔ purrr 1.2.2 \n── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──\n✖ dplyr::filter() masks stats::filter()\n✖ dplyr::lag() masks stats::lag()\nℹ Use the conflicted package () to force all conflicts to become errors\n```\n\n\n:::\n\n```{.r .cell-code}\nlibrary(palmerpenguins)\n```\n\n::: {.cell-output .cell-output-stderr}\n\n```\n\nAttaching package: 'palmerpenguins'\n\nThe following objects are masked from 'package:datasets':\n\n penguins, penguins_raw\n```\n\n\n:::\n:::\n\n\nData from [Palmer Penguins R package](https://allisonhorst.github.io/palmerpenguins/)\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\npenguins |> count(species)\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n# A tibble: 3 × 2\n species n\n \n1 Adelie 152\n2 Chinstrap 68\n3 Gentoo 124\n```\n\n\n:::\n:::\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncolors <- c(\"#FF8C00\", \"#A020F0\", \"#008B8B\")\n```\n:::\n\n\n\n::: {#cell-fig-size-scatter .cell}\n\n```{.r .cell-code}\n#| label: fig-size-scatter\n#| fig-width: 3\n#| fig-height: 3\n#| fig-alt: \"Scatterplot of flipper length against body mass for 344 penguins, colored by species. Flipper length increases with body mass, and Gentoo penguins sit apart from Adelie and Chinstrap at the highest values of both.\"\nggplot(penguins, aes(body_mass_g, flipper_length_mm)) +\n geom_point(aes(color = species)) +\n scale_color_manual(values = colors) +\n theme_minimal()\n```\n\n::: {.cell-output .cell-output-stderr}\n\n```\nWarning: Removed 2 rows containing missing values or values outside the scale range\n(`geom_point()`).\n```\n\n\n:::\n\n::: {.cell-output-display}\n![](penguins-qmd_files/figure-ipynb/fig-size-scatter-1.png){#fig-size-scatter fig-alt='Scatterplot of flipper length against body mass for 344 penguins, colored by species. Flipper length increases with body mass, and Gentoo penguins sit apart from Adelie and Chinstrap at the highest values of both.'}\n:::\n:::\n", "supporting": [ "penguins-qmd_files/figure-ipynb" ], diff --git a/_freeze/docs/authoring/penguins-qmd/figure-html/fig-size-scatter-1.png b/_freeze/docs/authoring/penguins-qmd/figure-html/fig-size-scatter-1.png index fef43796bf..41a764b71f 100644 Binary files a/_freeze/docs/authoring/penguins-qmd/figure-html/fig-size-scatter-1.png and b/_freeze/docs/authoring/penguins-qmd/figure-html/fig-size-scatter-1.png differ diff --git a/_freeze/docs/authoring/penguins-qmd/figure-ipynb/fig-size-scatter-1.png b/_freeze/docs/authoring/penguins-qmd/figure-ipynb/fig-size-scatter-1.png index ff249d32ff..3e527a7ad5 100644 Binary files a/_freeze/docs/authoring/penguins-qmd/figure-ipynb/fig-size-scatter-1.png and b/_freeze/docs/authoring/penguins-qmd/figure-ipynb/fig-size-scatter-1.png differ diff --git a/_freeze/docs/authoring/tables/execute-results/html.json b/_freeze/docs/authoring/tables/execute-results/html.json index 3c47aa06c5..4f3cdf1ddd 100644 --- a/_freeze/docs/authoring/tables/execute-results/html.json +++ b/_freeze/docs/authoring/tables/execute-results/html.json @@ -2,7 +2,7 @@ "hash": "58ad76fc21eb84f4fa8452b9ce150226", "result": { "engine": "jupyter", - "markdown": "---\ntitle: Tables\nengine: jupyter\naliases: \n - /docs/prerelease/1.5/lua-table-processing.html\n---\n\n## Overview\n\nQuarto includes a number of features aimed at making it easy to to author and customize markdown table output, including:\n\n- Specifying column alignment and widths.\n- Providing captions, subcaptions, and cross-references.\n- Generating tables dynamically from executable code cells.\n\nThis article covers using these features in-depth.\n\n## Markdown Tables\n\nThe most commonly used markdown table is known as a pipe table. Pipe tables support specifying per column alignment as well as captions. For example:\n\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n| Default | Left | Right | Center |\n|---------|:-----|------:|:------:|\n| 12 | 12 | 12 | 12 |\n| 123 | 123 | 123 | 123 |\n| 1 | 1 | 1 | 1 |\n\n: Demonstration of pipe table syntax\n```\n\n::::\n\n:::: {}\n\n| Default | Left | Right | Center |\n|---------|:-----|------:|:------:|\n| 12 | 12 | 12 | 12 |\n| 123 | 123 | 123 | 123 |\n| 1 | 1 | 1 | 1 |\n\n: Demonstration of pipe table syntax\n\n::::\n\n:::\n\nThe beginning and ending pipe characters are optional, but pipes are required between all columns. The colons indicate column alignment as shown. The header cannot be omitted, however you can simulate a headerless table by including a header with blank cells.\n\nSince the pipes indicate column boundaries, columns need not be vertically aligned, as they are in the above example. So, this is a perfectly legal (though ugly) pipe table:\n\n``` markdown\nfruit| price\n-----|-----:\napple|2.05\npear|1.37\norange|3.09\n```\n\nThe cells of pipe tables cannot contain block elements like paragraphs and lists, and cannot span multiple lines. If a pipe table contains a row whose markdown content is wider than the column width (see `columns` option), then the table will take up the full text width and the cell contents will wrap, with the relative cell widths determined by the number of dashes in the line separating the table header from the table body.\n\nFor example `---|-` would make the first column 3/4 and the second column 1/4 of the full text width. On the other hand, if no lines are wider than column width, then cell contents will not be wrapped, and the cells will be sized to their contents.\n\n### Using Bootstrap classes\n\nBootstrap table classes given as attributes next to a table caption are inserted into the `` element.\nThe classes permitted are those that apply expressly to the entire table, and these are:\n`\"primary\"`, `\"secondary\"`, `\"success\"`, `\"danger\"`, `\"warning\"`, `\"info\"`, `\"light\"`, `\"dark\"`, `\"striped\"`, `\"hover\"`, `\"active\"`, `\"bordered\"`, `\"borderless\"`, `\"sm\"`, `\"responsive\"`, `\"responsive-sm\"`, `\"responsive-md\"`, `\"responsive-lg\"`, `\"responsive-xl\"`, `\"responsive-xxl\"`.\nFor example, the following Markdown table will be rendered with row stripes and the rows will also be highlighted on hover:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n\n``` markdown\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: Fruit prices {.striped .hover}\n```\n\n::::\n\n:::: {}\n\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: Fruit prices {.striped .hover}\n\n::::\n\n:::\n\n### Authoring\n\nFor simple tables with only a few cells it's straightforward to create them directly in markdown. As tables get larger, it makes sense to use an authoring tool. Some table authoring tools to consider include:\n\n+------------------------------------------------------------------------+---------------------------------------------------------------+\n| [TablesGenerator](https://www.tablesgenerator.com/markdown_tables) | Online tool for generating markdown tables |\n+------------------------------------------------------------------------+---------------------------------------------------------------+\n| [Emacs TableMode](https://www.emacswiki.org/emacs/TableMode) | Text based table creation and editing capabilities for Emacs. |\n+------------------------------------------------------------------------+---------------------------------------------------------------+\n| [Quarto Visual Editor](/docs/visual-editor/content.qmd#editing-tables) | Visual editor for `.qmd` files with table editing support. |\n+------------------------------------------------------------------------+---------------------------------------------------------------+\n\n: {tbl-colwidths=\"\\[35,65\\]\"}\n\n## Column Widths\n\nAbove we describe a means of specifying column widths using the relative number of dashes in each column header (_e.g._, `---|-` to get a 75% / 25% split for a two-column table).\n\nYou can also explicitly specify columns widths using the `tbl-colwidths` attribute or document-level option. For an individual markdown table, add the attribute after the caption. For example:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: Fruit prices {tbl-colwidths=\"[75,25]\"}\n```\n\n::::\n\n:::: {}\n\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: Fruit prices {tbl-colwidths=\"[75,25]\"}\n\n::::\n\n:::\n\nIf your table doesn't have a caption, then you can still specify only `tbl-colwidths`:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: {tbl-colwidths=\"[75,25]\"}\n```\n\n::::\n\n:::: {}\n\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: {tbl-colwidths=\"[75,25]\"}\n\n::::\n\n:::\n\nColumn widths can also be specified at the document level (_e.g._, to have uniform widths across a set of tables):\n\n``` yaml\n---\ntitle: \"My Document\"\nformat: html\ntbl-colwidths: [75,25]\n---\n```\n\n## Cross References\n\nFor tables produced by executable code cells, include a label with a `tbl-` prefix to make them cross-referenceable.\nFor example:\n\n::: {#tbl-planets .cell tbl-cap='Astronomical object' execution_count=1}\n```` { .cell-code}\n```{{python}}\n#| label: tbl-planets\n#| tbl-cap: Astronomical object\n\nfrom IPython.display import Markdown\nfrom tabulate import tabulate\ntable = [[\"Sun\",\"696,000\",1.989e30],\n [\"Earth\",\"6,371\",5.972e24],\n [\"Moon\",\"1,737\",7.34e22],\n [\"Mars\",\"3,390\",6.39e23]]\nMarkdown(tabulate(\n table, \n headers=[\"Astronomical object\",\"R (km)\", \"mass (kg)\"]\n))\n```\n\n````\n\n::: {.cell-output .cell-output-display .cell-output-markdown execution_count=1}\nAstronomical object R (km) mass (kg)\n--------------------- -------- -----------\nSun 696,000 1.989e+30\nEarth 6,371 5.972e+24\nMoon 1,737 7.34e+22\nMars 3,390 6.39e+23\n:::\n:::\n\n\n::: callout-important\n## Label Prefix\n\nIn order for a table to be cross-referenceable, its label must start with the `tbl-` prefix.\n:::\n\n\n\nFor markdown tables, add a caption below the table, then include a `#tbl-` label in braces at the end of the caption. For example:\n\n``` markdown\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: My Caption {#tbl-letters}\n\nSee @tbl-letters.\n```\n\nWhich looks like this when rendered to HTML:\n\n::: light-content\n![](images/crossref-table.png){fig-alt=\"A table with 3 columns and four rows. The text 'Table 1: My Caption' is above the header column. The text 'See tbl. 1' is aligned to the left underneath the last column.\" width=\"500\"}\n:::\n\n::: dark-content\n![](images/crossref-table-dark.png){fig-alt=\"A table with 3 columns and four rows. The text 'Table 1: My Caption' is above the header column. The text 'See tbl. 1' is aligned to the left underneath the last column.\" width=\"500\"}\n:::\n\n\nSee the article on [Cross References](cross-references.qmd) for additional details.\n\n### Subtables\n\nYou may want to create a composition of several sub-tables. To do this, create a div with a main identifier, then apply sub-identifiers (and optional caption text) to the contained tables. For example:\n\n``` markdown\n::: {#tbl-panel layout-ncol=2}\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: First Table {#tbl-first}\n\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: Second Table {#tbl-second}\n\nMain Caption\n:::\n\nSee @tbl-panel for details, especially @tbl-second.\n```\n\nWhich looks like this when rendered to HTML:\n\n![](/docs/authoring/images/crossref-subtable.png){fig-alt=\"Two tables side-by-side. Both tables have 3 columns and 4 rows. The table on the left is titled '(a) First table'. The table on the right is titled '(b) Second Table'. Centered underneath both tables is the text 'Table 1: Main Caption'. The text 'See tbl. 2 for details, especially tbl. 2 (b)' is aligned to the left underneath that.\"}\n\nNote that the \"Main Caption\" for the table is provided as the last block within the containing div.\n\n\n## Caption Location\n\nBy default, table captions are positioned above tables. You can modify this behavior using the `tbl-cap-location` option. For example:\n\n``` yaml\n---\ntbl-cap-location: top\n---\n```\n\nNote that this option is specified at the top level so that it can be shared by both PDF and HTML formats. If you are only targeting a single format you can place it alongside other `format` specific options.\n\nValid values for the caption location include:\n\n| Value | Description |\n|----------|---------------------------------------|\n| `top` | Position the caption above the table. |\n| `bottom` | Position the caption below the table. |\n| `margin` | Position the caption in the margin. |\n\nSee the article on [Article Layout](article-layout.qmd#margin-captions) for additional details on placing captions in the margin.\n\n## Computations\n\nAll of the options described above work for tables produced by executable code cells. For example, here we use the Python [tabulate](https://pypi.org/project/tabulate/) package along with the `Markdown()` function from the IPython [display](https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#) module to print a markdown table:\n\n::: {#tbl-planet-measures .cell tbl-cap='Astronomical object' execution_count=2}\n```` { .cell-code}\n```{{python}}\n#| label: tbl-planet-measures\n#| tbl-cap: Astronomical object\n\nfrom IPython.display import Markdown\nfrom tabulate import tabulate\ntable = [[\"Sun\",\"696,000\",1.989e30],\n [\"Earth\",\"6,371\",5.972e24],\n [\"Moon\",\"1,737\",7.34e22],\n [\"Mars\",\"3,390\",6.39e23]]\nMarkdown(tabulate(\n table, \n headers=[\"Astronomical object\",\"R (km)\", \"mass (kg)\"]\n))\n```\n\n````\n\n::: {.cell-output .cell-output-display .cell-output-markdown execution_count=2}\nAstronomical object R (km) mass (kg)\n--------------------- -------- -----------\nSun 696,000 1.989e+30\nEarth 6,371 5.972e+24\nMoon 1,737 7.34e+22\nMars 3,390 6.39e+23\n:::\n:::\n\n\nHere we apply the `tbl-cap` and `tbl-colwidths` options to a code cell that uses the knitr `kable()` function to write a markdown table:\n\n```{{r}}\n#| label: tbl-cars\n#| tbl-cap: \"Cars\"\n#| tbl-colwidths: [60,40]\n\nkable(head(cars))\n```\n\nIf your code cell produces multiple tables, you can also specify subcaptions and layout using cell options:\n\n::: {.panel-tabset group=\"language\"}\n\n## Python\n\n````python\n```{{python}}\n#| label: tbl-example\n#| tbl-cap: \"Example\"\n#| tbl-subcap: \n#| - \"MPG\"\n#| - \"Taxis\"\n#| layout-ncol: 2\n\nimport seaborn as sns\nfrom IPython.display import Markdown, display\nmpg = sns.load_dataset(\"mpg\").head(10)\ntaxis = sns.load_dataset(\"taxis\").head(10)\n\ndisplay(Markdown(mpg.to_markdown(index = False)))\ndisplay(Markdown(taxis.to_markdown(index = False)))\n```\n````\n\nNote that we use the [`display()`](https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.display) function imported from `IPython` so that we can render multiple outputs from a single cell (by default cells only output their last expression).\n\n## R\n\n````python\n```{{r}}\n#| label: tbl-example\n#| tbl-cap: \"Example\"\n#| tbl-subcap: \n#| - \"Cars\"\n#| - \"Pressure\"\n#| layout-ncol: 2\n\nlibrary(knitr)\nkable(head(cars))\nkable(head(pressure))\n```\n````\n\n\n:::\n\n### Computational Table Styling\n\nQuarto adds additional styling to tables generated by computations. By default, such tables are styled to be smaller and have striped rows.\nIf you want to disable this treatment, add `plain` to the classes of the code cell:\n\n````python\n```{{r}}\n#| classes: plain\n\ntibble::tribble(\n ~fruit, ~price,\n \"apple\", 2.05,\n \"pear\", 1.37,\n \"orange\", 3.09\n) |> \n gt::gt()\n```\n````\n\n## List Tables\n\nList tables provide an alternative syntax for creating tables with complex content like multiple paragraphs, code blocks, or lists. Unlike [grid tables](#grid-tables), list tables use familiar bullet list syntax, making them easier to write and maintain.\n\nA list table is a fenced div with the `.list-table` class containing a bullet list. Each top-level bullet represents a row, and nested bullets represent cells:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n\n::::\n\n:::\n\nList tables support block elements within cells, including code blocks and lists:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n```` markdown\n::: {.list-table}\n- - Function\n - Description\n\n- - `sum()`\n - Add values:\n\n ```python\n sum([1, 2, 3])\n ```\n\n- - `len()`\n - Count items:\n\n - Works on lists\n - Works on strings\n:::\n````\n\n::::\n\n:::: {}\n\n::: {.list-table}\n- - Function\n - Description\n\n- - `sum()`\n - Add values:\n\n ```python\n sum([1, 2, 3])\n ```\n\n- - `len()`\n - Count items:\n\n - Works on lists\n - Works on strings\n:::\n\n::::\n\n:::\n\nBe careful to maintain the usual whitespace requirements: indent nested items and include blank lines around code blocks.\n\n### Header Rows \n\nBy default, the first row is treated as a header. To change this, set the `header-rows` attribute to `0`:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table header-rows=0}\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table header-rows=0}\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n\n::::\n\n:::\n\n### Column Alignment\n\nSpecify column alignment with the `aligns` attribute using `d` (default), `l` (left), `r` (right), or `c` (center):\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table aligns=\"l,r\"}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table aligns=\"l,r\"}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n\n::::\n\n:::\n\n### Column Widths\n\nYou can specify relative column widths by adding the `tbl-colwidths` attribute:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table tbl-colwidths=\"[75,25]\"}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table tbl-colwidths=\"[75,25]\"}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n\n::::\n\n:::\n\n### Captions and Cross References\n\nAdd a caption by including a paragraph at the start of the div:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table}\nFruit prices\n\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table}\nFruit prices\n\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n:::\n\n::::\n\n:::\n\nTo make a list table cross-referenceable, add an id with the `tbl-` prefix:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {#tbl-fruits .list-table}\nFruit prices\n\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n:::\n\nSee @tbl-fruits.\n```\n\n::::\n\n:::: {}\n\n::: {#tbl-fruits .list-table}\nFruit prices\n\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n:::\n\nSee @tbl-fruits.\n\n::::\n\n:::\n\n### Cell Attributes\n\nTo add attributes to a cell, start the cell with an empty span containing the attributes. For example, use `rowspan` and `colspan` to span cells across rows or columns:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table}\n- - []{colspan=2} Item\n - Price\n\n- - []{rowspan=2} Citrus\n - Orange\n - 0.90\n\n- - Lemon\n - 0.80\n\n- - []{rowspan=2} Stone Fruit\n - Peach\n - 1.20\n\n- - Plum\n - 1.00\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table}\n- - []{colspan=2} Item\n - Price\n\n- - []{rowspan=2} Citrus\n - Orange\n - 0.90\n\n- - Lemon\n - 0.80\n\n- - []{rowspan=2} Stone Fruit\n - Peach\n - 1.20\n\n- - Plum\n - 1.00\n:::\n\n::::\n\n:::\n\nThe empty span must be the first inline element in the cell. Cells with `rowspan` or `colspan` still count toward the total number of cells in a row—subsequent rows should have fewer cells to account for the span.\n\n## Grid Tables\n\nGrid tables are a more advanced type of markdown tables that allow arbitrary block elements (multiple paragraphs, code blocks, lists, etc.). For example:\n\n\n``` markdown\n+-----------+-----------+--------------------+\n| Fruit | Price | Advantages |\n+===========+===========+====================+\n| Bananas | $1.34 | - built-in wrapper |\n| | | - bright color |\n+-----------+-----------+--------------------+\n| Oranges | $2.10 | - cures scurvy |\n| | | - tasty |\n+-----------+-----------+--------------------+\n\n: Sample grid table.\n```\n\nWhich looks like this when rendered to HTML:\n\n+-----------+-----------+--------------------+\n| Fruit | Price | Advantages |\n+===========+===========+====================+\n| Bananas | $1.34 | - built-in wrapper |\n| | | - bright color |\n+-----------+-----------+--------------------+\n| Oranges | $2.10 | - cures scurvy |\n| | | - tasty |\n+-----------+-----------+--------------------+\n\n: Sample grid table.\n\n\nThe row of `=`s separates the header from the table body, and can be omitted for a headerless table. The cells of grid tables may contain arbitrary block elements (multiple paragraphs, code blocks, lists, etc.)\n\nAlignments can be specified as with pipe tables, by putting colons at the boundaries of the separator line after the header:\n\n\n``` markdown\n+---------+--------+------------------+\n| Right | Left | Centered |\n+========:+:=======+:================:+\n| Bananas | $1.34 | built-in wrapper |\n+---------+--------+------------------+\n```\nWhich looks like this when rendered to HTML:\n\n+---------+--------+------------------+\n| Right | Left | Centered |\n+========:+:=======+:================:+\n| Bananas | $1.34 | built-in wrapper |\n+---------+--------+------------------+\n\n\nFor headerless tables, the colons go on the top line instead:\n\n``` markdown\n+----------:+:----------+:--------:+\n| Right | Left | Centered |\n+-----------+-----------+----------+\n```\n\nWhich looks like this when rendered to HTML:\n\n+----------:+:----------+:--------:+\n| Right | Left | Centered |\n+-----------+-----------+----------+\n\n\nNote that grid tables are quite awkward to write with a plain text editor (because unlike pipe tables, the column indicators must align). Here are some tools that can assist with creating grid tables:\n\n- Emacs' [table-mode](https://www.gnu.org/software/emacs/manual/html_node/emacs/Text-Based-Tables.html) (`M-x table-insert`)\n- Quarto [Visual Editor](/docs/visual-editor/content.qmd#editing-tables)\n- Tables Generator's [Plain Text mode](https://www.tablesgenerator.com/text_tables) with `Use reStructuredText syntax` enabled\n\n::: callout-warning\n\n## Shortcodes are not supported\n\nIn Quarto, shortcodes are processed internally by transforming the Markdown text ahead of Pandoc.\nUnfortunately, it's not possible to do this transformation in a way that preserves the grid table structure.\nAs a result, shortcodes are not supported inside grid tables. Consider using [list tables](#list-tables) instead.\n\n:::\n\n## HTML Tables\n\nQuarto can process HTML tables in `html` `RawBlock` nodes (_i.e._, `{=html}`) and convert them to Markdown tables, regardless of the output format (intentionally including non-HTML formats).\nAs a result, you can use HTML table syntax in your documents and it will be converted to Markdown syntax for all formats.\nAdditionally, libraries that emit computational tables in HTML format can work in other output formats.\n\nFor example, consider the following raw HTML block:\n\n````markdown\n```{=html}\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
As described in the section above, Quarto tables are great.
Header 1Header 2
\"AfricanRegular output
\n```\n````\n\nWhen rendered, this results in the following output for HTML and PDF formats:\n\n::: {layout-ncol=2}\n\n:::: {}\n### HTML Output\n\n```{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n
As described in the section above, Quarto tables are great.
Header 1Header 2
\"AfricanRegular output
\n```\n::::\n\n:::: {}\n### PDF Output\n\n![](images/raw-table-pdf.png){.border fig-alt=\"Screenshot of PDF output showing a table with a caption and two columns. The column headers are Header 1 and Header 2, and the cell contents are an image of an elephant and text that reads Regular Output.\"}\n::::\n\n:::\n\nIn addition, Quarto supports the specification of embedded Markdown content in raw table markup. This allows Quarto features like cross-references, shortcodes, and markdown formatting to be used inside tables produced by libraries that emit raw HTML or LaTeX.\n\n#### HTML Raw Blocks\n\nFor HTML raw blocks, this is done by providing a data attribute `qmd` or `qmd-base64` in an embedded `span` or `div` node. These nodes can appear anywhere that such content is allowed: table headers, footers, cells, captions, _etc._\n\nFor example, the following table includes a cross reference, markdown formatting and a shortcode:\n\n:::: {layout-nrow=\"2\"}\n\n::: {}\n\n```` markdown\n## HTML Tables Example {#sec-html-tables}\n\n```{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n
}}}\">Regular output
\n```\n````\n\n:::\n\n::: {}\n\nWhich renders as follows:\n\n## HTML Tables Example {#sec-html-tables}\n\n```{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n
}}\">Regular output
\n```\n\n:::\n\n::::\n\n#### LaTeX Raw Blocks\n\nFor LaTeX raw blocks (used in PDF output), the equivalent syntax is `\\QuartoMarkdownBase64{<>}`. When Quarto detects this command, it decodes the base64 content, processes it as Quarto markdown (including cross-references, shortcodes, and user filters), and inserts the result back into the LaTeX output.\n\nFor example, the following LaTeX raw block uses cross-references and markdown formatting inside a table:\n\n```` markdown\n## LaTeX Tables Example {#sec-latex-tables}\n\n```{=latex}\n\\begin{tabular}{ll}\n % X0hlYWRlciAxXw== is base64 for \"_Header 1_\"\n \\QuartoMarkdownBase64{X0hlYWRlciAxXw==} &\n % X0hlYWRlciAyXw== is base64 for \"_Header 2_\"\n \\QuartoMarkdownBase64{X0hlYWRlciAyXw==} \\\\\n % U2VlIEBzZWMtbGF0ZXgtdGFibGVzLg== is base64 for\n % \"See @sec-latex-tables.\"\n \\QuartoMarkdownBase64{U2VlIEBzZWMtbGF0ZXgtdGFibGVzLg==} &\n Regular output \\\\\n\\end{tabular}\n```\n````\n\nWhen rendered to PDF, this table would display with italic headers (*Header 1* and *Header 2*), and the cross-reference `@sec-latex-tables` would be resolved to a clickable section link.\n\n::: {.callout-note}\nUnlike the HTML feature, only base64-encoded content is supported for LaTeX raw blocks (there is no plain-text equivalent of `data-qmd`). This feature cannot be disabled, but this should not be necessary since `\\QuartoMarkdownBase64` is unlikely to conflict with existing LaTeX commands.\n:::\n\n::: {.callout-warning}\nCitations do not currently work inside `\\QuartoMarkdownBase64`. See [GitHub issue #9342](https://github.com/quarto-dev/quarto-cli/issues/9342) for details.\n:::\n\n### Colspans and Rowspans\n\nTables containing cells spanning multiple rows or columns are supported across output formats[except in PDF margins]{.aside}.\n\nHowever, using markdown, it is tricky to draw grid tables with spans, and there is no way to express spans in pipe tables. \n\nIf you are comfortable with HTML, or use a package that generates HTML, the table cell HTML attributes `colspan` and `rowspan` are a better option.\n\n```{=html}\n\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n
I span two columnsC1
I span two rowsB2C2
B3C3
\n\n```\n\n````html\n```{=html}\n\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n
I span two columnsC1
I span two rowsB2C2
B3C3
\n\n```\n````\n\n\n### Individual cell alignment\n\nMarkdown supports specification of alignment by column, but does not allow setting the alignment of individual cells. The CSS properties `text-align` and `vertical-align` are only available through Raw HTML. (These are not currently supported by PDF/Latex or Pptx output formats, and Docx only supports `text-align`.)\n\n\n```{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
vertical-align: topvertical-align: middlevertical-align: bottom
text-align: left
text-align: center
text-align: right
\n \n\n```\n\n````html\n```{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
vertical-align: topvertical-align: middlevertical-align: bottom
text-align: left
text-align: center
text-align: right
\n \n\n```\n````\n\n## Disabling Quarto Table Processing\n\nIt's possible that Quarto's processing of HTML tables may interfere with the HTML produced computationally with table packages in R and Python (or other supported languages).\n\n\nWhen you disable Quarto's HTML table processing, tables are not translated to Markdown, will not be rendered to other output formats, and can not use Quarto Markdown features, like cross-references, shortcodes, etc.\nThe tables also won't be visible to Lua filters that act on `Table` nodes.\n\nYou can disable Quarto's HTML table processing at a document level or project level with the option `html-table-processing`:\n\n```{.yaml}\n---\nformat:\n html:\n html-table-processing: none\n---\n```\n\nThis option is also available as a code cell option for Knitr and Jupyter, e.g. \n\n````{markdown}\n```{{r}}\n#| html-table-processing: none\n\n# R Code that generates an HTML table\n```\n````\n\nTo disable Quarto's HTML table processing for parts of a document use a div with the attribute `html-table-processing=\"none\"`:\n\n````{.markdown}\n::: {html-table-processing=\"none\"}\n\nContent with HTML tables you don't want processed.\n\n:::\n````\n\n### Library authors\n\nIf you are the author of a library that emits HTML tables you might like to disable Quarto's processing of HTML tables by adding the attribute `data-quarto-disable-processing=\"true\"` to the `` element. For example:\n\n```html\n
\n ...\n
\n```\n\nAdditionally, you can add the comment `` to the HTML raw block, and Quarto will not attempt to process it.\n\n", + "markdown": "---\ntitle: Tables\nengine: jupyter\naliases: \n - /docs/prerelease/1.5/lua-table-processing.html\n---\n\n## Overview\n\nQuarto includes a number of features aimed at making it easy to to author and customize markdown table output, including:\n\n- Specifying column alignment and widths.\n- Providing captions, subcaptions, and cross-references.\n- Generating tables dynamically from executable code cells.\n\nThis article covers using these features in-depth.\n\n## Markdown Tables\n\nThe most commonly used markdown table is known as a pipe table. Pipe tables support specifying per column alignment as well as captions. For example:\n\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n| Default | Left | Right | Center |\n|---------|:-----|------:|:------:|\n| 12 | 12 | 12 | 12 |\n| 123 | 123 | 123 | 123 |\n| 1 | 1 | 1 | 1 |\n\n: Demonstration of pipe table syntax\n```\n\n::::\n\n:::: {}\n\n| Default | Left | Right | Center |\n|---------|:-----|------:|:------:|\n| 12 | 12 | 12 | 12 |\n| 123 | 123 | 123 | 123 |\n| 1 | 1 | 1 | 1 |\n\n: Demonstration of pipe table syntax\n\n::::\n\n:::\n\nThe beginning and ending pipe characters are optional, but pipes are required between all columns. The colons indicate column alignment as shown. The header cannot be omitted, however you can simulate a headerless table by including a header with blank cells.\n\nSince the pipes indicate column boundaries, columns need not be vertically aligned, as they are in the above example. So, this is a perfectly legal (though ugly) pipe table:\n\n``` markdown\nfruit| price\n-----|-----:\napple|2.05\npear|1.37\norange|3.09\n```\n\nThe cells of pipe tables cannot contain block elements like paragraphs and lists, and cannot span multiple lines. If a pipe table contains a row whose markdown content is wider than the column width (see `columns` option), then the table will take up the full text width and the cell contents will wrap, with the relative cell widths determined by the number of dashes in the line separating the table header from the table body.\n\nFor example `---|-` would make the first column 3/4 and the second column 1/4 of the full text width. On the other hand, if no lines are wider than column width, then cell contents will not be wrapped, and the cells will be sized to their contents.\n\n### Using Bootstrap classes\n\nBootstrap table classes given as attributes next to a table caption are inserted into the `` element.\nThe classes permitted are those that apply expressly to the entire table, and these are:\n`\"primary\"`, `\"secondary\"`, `\"success\"`, `\"danger\"`, `\"warning\"`, `\"info\"`, `\"light\"`, `\"dark\"`, `\"striped\"`, `\"hover\"`, `\"active\"`, `\"bordered\"`, `\"borderless\"`, `\"sm\"`, `\"responsive\"`, `\"responsive-sm\"`, `\"responsive-md\"`, `\"responsive-lg\"`, `\"responsive-xl\"`, `\"responsive-xxl\"`.\nFor example, the following Markdown table will be rendered with row stripes and the rows will also be highlighted on hover:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n\n``` markdown\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: Fruit prices {.striped .hover}\n```\n\n::::\n\n:::: {}\n\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: Fruit prices {.striped .hover}\n\n::::\n\n:::\n\n### Authoring\n\nFor simple tables with only a few cells it's straightforward to create them directly in markdown. As tables get larger, it makes sense to use an authoring tool. Some table authoring tools to consider include:\n\n+------------------------------------------------------------------------+---------------------------------------------------------------+\n| [TablesGenerator](https://www.tablesgenerator.com/markdown_tables) | Online tool for generating markdown tables |\n+------------------------------------------------------------------------+---------------------------------------------------------------+\n| [Emacs TableMode](https://www.emacswiki.org/emacs/TableMode) | Text based table creation and editing capabilities for Emacs. |\n+------------------------------------------------------------------------+---------------------------------------------------------------+\n| [Quarto Visual Editor](/docs/visual-editor/content.qmd#editing-tables) | Visual editor for `.qmd` files with table editing support. |\n+------------------------------------------------------------------------+---------------------------------------------------------------+\n\n: {tbl-colwidths=\"\\[35,65\\]\"}\n\n## Column Widths\n\nAbove we describe a means of specifying column widths using the relative number of dashes in each column header (_e.g._, `---|-` to get a 75% / 25% split for a two-column table).\n\nYou can also explicitly specify columns widths using the `tbl-colwidths` attribute or document-level option. For an individual markdown table, add the attribute after the caption. For example:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: Fruit prices {tbl-colwidths=\"[75,25]\"}\n```\n\n::::\n\n:::: {}\n\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: Fruit prices {tbl-colwidths=\"[75,25]\"}\n\n::::\n\n:::\n\nIf your table doesn't have a caption, then you can still specify only `tbl-colwidths`:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: {tbl-colwidths=\"[75,25]\"}\n```\n\n::::\n\n:::: {}\n\n| fruit | price |\n|--------|--------|\n| apple | 2.05 |\n| pear | 1.37 |\n| orange | 3.09 |\n\n: {tbl-colwidths=\"[75,25]\"}\n\n::::\n\n:::\n\nColumn widths can also be specified at the document level (_e.g._, to have uniform widths across a set of tables):\n\n``` yaml\n---\ntitle: \"My Document\"\nformat: html\ntbl-colwidths: [75,25]\n---\n```\n\n## Cross References\n\nFor tables produced by executable code cells, include a label with a `tbl-` prefix to make them cross-referenceable.\nFor example:\n\n::: {#tbl-planets .cell tbl-cap='Astronomical object' execution_count=1}\n```` { .cell-code}\n```{{python}}\n#| label: tbl-planets\n#| tbl-cap: Astronomical object\n\nfrom IPython.display import Markdown\nfrom tabulate import tabulate\ntable = [[\"Sun\",\"696,000\",1.989e30],\n [\"Earth\",\"6,371\",5.972e24],\n [\"Moon\",\"1,737\",7.34e22],\n [\"Mars\",\"3,390\",6.39e23]]\nMarkdown(tabulate(\n table, \n headers=[\"Astronomical object\",\"R (km)\", \"mass (kg)\"]\n))\n```\n\n````\n\n::: {.cell-output .cell-output-display .cell-output-markdown execution_count=1}\nAstronomical object R (km) mass (kg)\n--------------------- -------- -----------\nSun 696,000 1.989e+30\nEarth 6,371 5.972e+24\nMoon 1,737 7.34e+22\nMars 3,390 6.39e+23\n:::\n:::\n\n\n::: callout-important\n## Label Prefix\n\nIn order for a table to be cross-referenceable, its label must start with the `tbl-` prefix.\n:::\n\n\n\nFor markdown tables, add a caption below the table, then include a `#tbl-` label in braces at the end of the caption. For example:\n\n``` markdown\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: My Caption {#tbl-letters}\n\nSee @tbl-letters.\n```\n\nWhich looks like this when rendered to HTML:\n\n::: light-content\n![](images/crossref-table.png){fig-alt=\"A table with 3 columns and four rows. The text 'Table 1: My Caption' is above the header column. The text 'See tbl. 1' is aligned to the left underneath the last column.\" width=\"500\"}\n:::\n\n::: dark-content\n![](images/crossref-table-dark.png){fig-alt=\"A table with 3 columns and four rows. The text 'Table 1: My Caption' is above the header column. The text 'See tbl. 1' is aligned to the left underneath the last column.\" width=\"500\"}\n:::\n\n\nSee the article on [Cross References](cross-references.qmd) for additional details.\n\n### Subtables\n\nYou may want to create a composition of several sub-tables. To do this, create a div with a main identifier, then apply sub-identifiers (and optional caption text) to the contained tables. For example:\n\n``` markdown\n::: {#tbl-panel layout-ncol=2}\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: First Table {#tbl-first}\n\n| Col1 | Col2 | Col3 |\n|------|------|------|\n| A | B | C |\n| E | F | G |\n| A | G | G |\n\n: Second Table {#tbl-second}\n\nMain Caption\n:::\n\nSee @tbl-panel for details, especially @tbl-second.\n```\n\nWhich looks like this when rendered to HTML:\n\n![](/docs/authoring/images/crossref-subtable.png){fig-alt=\"Two tables side-by-side. Both tables have 3 columns and 4 rows. The table on the left is titled '(a) First table'. The table on the right is titled '(b) Second Table'. Centered underneath both tables is the text 'Table 1: Main Caption'. The text 'See tbl. 2 for details, especially tbl. 2 (b)' is aligned to the left underneath that.\"}\n\nNote that the \"Main Caption\" for the table is provided as the last block within the containing div.\n\n\n## Caption Location\n\nBy default, table captions are positioned above tables. You can modify this behavior using the `tbl-cap-location` option. For example:\n\n``` yaml\n---\ntbl-cap-location: top\n---\n```\n\nNote that this option is specified at the top level so that it can be shared by both PDF and HTML formats. If you are only targeting a single format you can place it alongside other `format` specific options.\n\nValid values for the caption location include:\n\n| Value | Description |\n|----------|---------------------------------------|\n| `top` | Position the caption above the table. |\n| `bottom` | Position the caption below the table. |\n| `margin` | Position the caption in the margin. |\n\nSee the article on [Article Layout](article-layout.qmd#margin-captions) for additional details on placing captions in the margin.\n\n## Computations\n\nAll of the options described above work for tables produced by executable code cells. For example, here we use the Python [tabulate](https://pypi.org/project/tabulate/) package along with the `Markdown()` function from the IPython [display](https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#) module to print a markdown table:\n\n::: {#tbl-planet-measures .cell tbl-cap='Astronomical object' execution_count=2}\n```` { .cell-code}\n```{{python}}\n#| label: tbl-planet-measures\n#| tbl-cap: Astronomical object\n\nfrom IPython.display import Markdown\nfrom tabulate import tabulate\ntable = [[\"Sun\",\"696,000\",1.989e30],\n [\"Earth\",\"6,371\",5.972e24],\n [\"Moon\",\"1,737\",7.34e22],\n [\"Mars\",\"3,390\",6.39e23]]\nMarkdown(tabulate(\n table, \n headers=[\"Astronomical object\",\"R (km)\", \"mass (kg)\"]\n))\n```\n\n````\n\n::: {.cell-output .cell-output-display .cell-output-markdown execution_count=2}\nAstronomical object R (km) mass (kg)\n--------------------- -------- -----------\nSun 696,000 1.989e+30\nEarth 6,371 5.972e+24\nMoon 1,737 7.34e+22\nMars 3,390 6.39e+23\n:::\n:::\n\n\nHere we apply the `tbl-cap` and `tbl-colwidths` options to a code cell that uses the knitr `kable()` function to write a markdown table:\n\n```{{r}}\n#| label: tbl-cars\n#| tbl-cap: \"Cars\"\n#| tbl-colwidths: [60,40]\n\nkable(head(cars))\n```\n\nIf your code cell produces multiple tables, you can also specify subcaptions and layout using cell options:\n\n::: {.panel-tabset group=\"language\"}\n\n## Python\n\n````python\n```{{python}}\n#| label: tbl-example\n#| tbl-cap: \"Example\"\n#| tbl-subcap: \n#| - \"MPG\"\n#| - \"Taxis\"\n#| layout-ncol: 2\n\nimport seaborn as sns\nfrom IPython.display import Markdown, display\nmpg = sns.load_dataset(\"mpg\").head(10)\ntaxis = sns.load_dataset(\"taxis\").head(10)\n\ndisplay(Markdown(mpg.to_markdown(index = False)))\ndisplay(Markdown(taxis.to_markdown(index = False)))\n```\n````\n\nNote that we use the [`display()`](https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.display) function imported from `IPython` so that we can render multiple outputs from a single cell (by default cells only output their last expression).\n\n## R\n\n````python\n```{{r}}\n#| label: tbl-example\n#| tbl-cap: \"Example\"\n#| tbl-subcap: \n#| - \"Cars\"\n#| - \"Pressure\"\n#| layout-ncol: 2\n\nlibrary(knitr)\nkable(head(cars))\nkable(head(pressure))\n```\n````\n\n\n:::\n\n### Computational Table Styling\n\nQuarto adds additional styling to tables generated by computations. By default, such tables are styled to be smaller and have striped rows.\nIf you want to disable this treatment, add `plain` to the classes of the code cell:\n\n````python\n```{{r}}\n#| classes: plain\n\ntibble::tribble(\n ~fruit, ~price,\n \"apple\", 2.05,\n \"pear\", 1.37,\n \"orange\", 3.09\n) |> \n gt::gt()\n```\n````\n\n## List Tables\n\nList tables provide an alternative syntax for creating tables with complex content like multiple paragraphs, code blocks, or lists. Unlike [grid tables](#grid-tables), list tables use familiar bullet list syntax, making them easier to write and maintain.\n\nA list table is a fenced div with the `.list-table` class containing a bullet list. Each top-level bullet represents a row, and nested bullets represent cells:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n\n::::\n\n:::\n\nList tables support block elements within cells, including code blocks and lists:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n```` markdown\n::: {.list-table}\n- - Function\n - Description\n\n- - `sum()`\n - Add values:\n\n ```python\n sum([1, 2, 3])\n ```\n\n- - `len()`\n - Count items:\n\n - Works on lists\n - Works on strings\n:::\n````\n\n::::\n\n:::: {}\n\n::: {.list-table}\n- - Function\n - Description\n\n- - `sum()`\n - Add values:\n\n ```python\n sum([1, 2, 3])\n ```\n\n- - `len()`\n - Count items:\n\n - Works on lists\n - Works on strings\n:::\n\n::::\n\n:::\n\nBe careful to maintain the usual whitespace requirements: indent nested items and include blank lines around code blocks.\n\n### Header Rows \n\nBy default, the first row is treated as a header. To change this, set the `header-rows` attribute to `0`:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table header-rows=0}\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table header-rows=0}\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n\n::::\n\n:::\n\n### Column Alignment\n\nSpecify column alignment with the `aligns` attribute using `d` (default), `l` (left), `r` (right), or `c` (center):\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table aligns=\"l,r\"}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table aligns=\"l,r\"}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n\n::::\n\n:::\n\n### Column Widths\n\nYou can specify relative column widths by adding the `tbl-colwidths` attribute:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table tbl-colwidths=\"[75,25]\"}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table tbl-colwidths=\"[75,25]\"}\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n\n- - Orange\n - 0.90\n:::\n\n::::\n\n:::\n\n### Captions and Cross References\n\nAdd a caption by including a paragraph at the start of the div:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table}\nFruit prices\n\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table}\nFruit prices\n\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n:::\n\n::::\n\n:::\n\nTo make a list table cross-referenceable, add an id with the `tbl-` prefix:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {#tbl-fruits .list-table}\nFruit prices\n\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n:::\n\nSee @tbl-fruits.\n```\n\n::::\n\n:::: {}\n\n::: {#tbl-fruits .list-table}\nFruit prices\n\n- - Fruit\n - Price\n\n- - Apple\n - 1.20\n:::\n\nSee @tbl-fruits.\n\n::::\n\n:::\n\n### Cell Attributes\n\nTo add attributes to a cell, start the cell with an empty span containing the attributes. For example, use `rowspan` and `colspan` to span cells across rows or columns:\n\n::: {layout-ncol=\"2\"}\n\n:::: {}\n\n``` markdown\n::: {.list-table}\n- - []{colspan=2} Item\n - Price\n\n- - []{rowspan=2} Citrus\n - Orange\n - 0.90\n\n- - Lemon\n - 0.80\n\n- - []{rowspan=2} Stone Fruit\n - Peach\n - 1.20\n\n- - Plum\n - 1.00\n:::\n```\n\n::::\n\n:::: {}\n\n::: {.list-table}\n- - []{colspan=2} Item\n - Price\n\n- - []{rowspan=2} Citrus\n - Orange\n - 0.90\n\n- - Lemon\n - 0.80\n\n- - []{rowspan=2} Stone Fruit\n - Peach\n - 1.20\n\n- - Plum\n - 1.00\n:::\n\n::::\n\n:::\n\nThe empty span must be the first inline element in the cell. Cells with `rowspan` or `colspan` still count toward the total number of cells in a row—subsequent rows should have fewer cells to account for the span.\n\n## Grid Tables\n\nGrid tables are a more advanced type of markdown tables that allow arbitrary block elements (multiple paragraphs, code blocks, lists, etc.). For example:\n\n\n``` markdown\n+-----------+-----------+--------------------+\n| Fruit | Price | Advantages |\n+===========+===========+====================+\n| Bananas | $1.34 | - built-in wrapper |\n| | | - bright color |\n+-----------+-----------+--------------------+\n| Oranges | $2.10 | - cures scurvy |\n| | | - tasty |\n+-----------+-----------+--------------------+\n\n: Sample grid table.\n```\n\nWhich looks like this when rendered to HTML:\n\n+-----------+-----------+--------------------+\n| Fruit | Price | Advantages |\n+===========+===========+====================+\n| Bananas | $1.34 | - built-in wrapper |\n| | | - bright color |\n+-----------+-----------+--------------------+\n| Oranges | $2.10 | - cures scurvy |\n| | | - tasty |\n+-----------+-----------+--------------------+\n\n: Sample grid table.\n\n\nThe row of `=`s separates the header from the table body, and can be omitted for a headerless table. The cells of grid tables may contain arbitrary block elements (multiple paragraphs, code blocks, lists, etc.)\n\nAlignments can be specified as with pipe tables, by putting colons at the boundaries of the separator line after the header:\n\n\n``` markdown\n+---------+--------+------------------+\n| Right | Left | Centered |\n+========:+:=======+:================:+\n| Bananas | $1.34 | built-in wrapper |\n+---------+--------+------------------+\n```\nWhich looks like this when rendered to HTML:\n\n+---------+--------+------------------+\n| Right | Left | Centered |\n+========:+:=======+:================:+\n| Bananas | $1.34 | built-in wrapper |\n+---------+--------+------------------+\n\n\nFor headerless tables, the colons go on the top line instead:\n\n``` markdown\n+----------:+:----------+:--------:+\n| Right | Left | Centered |\n+-----------+-----------+----------+\n```\n\nWhich looks like this when rendered to HTML:\n\n+----------:+:----------+:--------:+\n| Right | Left | Centered |\n+-----------+-----------+----------+\n\n\nNote that grid tables are quite awkward to write with a plain text editor (because unlike pipe tables, the column indicators must align). Here are some tools that can assist with creating grid tables:\n\n- Emacs' [table-mode](https://www.gnu.org/software/emacs/manual/html_node/emacs/Text-Based-Tables.html) (`M-x table-insert`)\n- Quarto [Visual Editor](/docs/visual-editor/content.qmd#editing-tables)\n- Tables Generator's [Plain Text mode](https://www.tablesgenerator.com/text_tables) with `Use reStructuredText syntax` enabled\n\n::: callout-warning\n\n## Shortcodes are not supported\n\nIn Quarto, shortcodes are processed internally by transforming the Markdown text ahead of Pandoc.\nUnfortunately, it's not possible to do this transformation in a way that preserves the grid table structure.\nAs a result, shortcodes are not supported inside grid tables. Consider using [list tables](#list-tables) instead.\n\n:::\n\n## HTML Tables\n\nQuarto can process HTML tables in `html` `RawBlock` nodes (_i.e._, `{=html}`) and convert them to Markdown tables, regardless of the output format (intentionally including non-HTML formats).\nAs a result, you can use HTML table syntax in your documents and it will be converted to Markdown syntax for all formats.\nAdditionally, libraries that emit computational tables in HTML format can work in other output formats.\n\nFor example, consider the following raw HTML block:\n\n````markdown\n```{=html}\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
As described in the section above, Quarto tables are great.
Header 1Header 2
\"AfricanRegular output
\n```\n````\n\nWhen rendered, this results in the following output for HTML and PDF formats:\n\n::: {layout-ncol=2}\n\n:::: {}\n### HTML Output\n\n```{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n
As described in the section above, Quarto tables are great.
Header 1Header 2
\"AfricanRegular output
\n```\n::::\n\n:::: {}\n### PDF Output\n\n![](images/raw-table-pdf.png){.border fig-alt=\"Screenshot of PDF output showing a table with a caption and two columns. The column headers are Header 1 and Header 2, and the cell contents are an image of an elephant and text that reads Regular Output.\"}\n::::\n\n:::\n\nIn addition, Quarto supports the specification of embedded Markdown content in raw table markup. This allows Quarto features like cross-references, shortcodes, and markdown formatting to be used inside tables produced by libraries that emit raw HTML or LaTeX.\n\n#### HTML Raw Blocks\n\nFor HTML raw blocks, this is done by providing a data attribute `qmd` or `qmd-base64` in an embedded `span` or `div` node. These nodes can appear anywhere that such content is allowed: table headers, footers, cells, captions, _etc._\n\nFor example, the following table includes a cross reference, markdown formatting and a shortcode:\n\n:::: {layout-nrow=\"2\"}\n\n::: {}\n\n```` markdown\n## HTML Tables Example {#sec-html-tables}\n\n```{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n
}}}\">Regular output
\n```\n````\n\n:::\n\n::: {}\n\nWhich renders as follows:\n\n## HTML Tables Example {#sec-html-tables}\n\n```{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n
}}\">Regular output
\n```\n\n:::\n\n::::\n\n#### LaTeX Raw Blocks\n\nFor LaTeX raw blocks (used in PDF output), the equivalent syntax is `\\QuartoMarkdownBase64{<>}`. When Quarto detects this command, it decodes the base64 content, processes it as Quarto markdown (including cross-references, shortcodes, and user filters), and inserts the result back into the LaTeX output.\n\nFor example, the following LaTeX raw block uses cross-references and markdown formatting inside a table:\n\n```` markdown\n## LaTeX Tables Example {#sec-latex-tables}\n\n```{=latex}\n\\begin{tabular}{ll}\n % X0hlYWRlciAxXw== is base64 for \"_Header 1_\"\n \\QuartoMarkdownBase64{X0hlYWRlciAxXw==} &\n % X0hlYWRlciAyXw== is base64 for \"_Header 2_\"\n \\QuartoMarkdownBase64{X0hlYWRlciAyXw==} \\\\\n % U2VlIEBzZWMtbGF0ZXgtdGFibGVzLg== is base64 for\n % \"See @sec-latex-tables.\"\n \\QuartoMarkdownBase64{U2VlIEBzZWMtbGF0ZXgtdGFibGVzLg==} &\n Regular output \\\\\n\\end{tabular}\n```\n````\n\nWhen rendered to PDF, this table would display with italic headers (*Header 1* and *Header 2*), and the cross-reference `@sec-latex-tables` would be resolved to a clickable section link.\n\n::: {.callout-note}\nUnlike the HTML feature, only base64-encoded content is supported for LaTeX raw blocks (there is no plain-text equivalent of `data-qmd`). This feature cannot be disabled, but this should not be necessary since `\\QuartoMarkdownBase64` is unlikely to conflict with existing LaTeX commands.\n:::\n\n::: {.callout-warning}\nCitations do not currently work inside `\\QuartoMarkdownBase64`. See [GitHub issue #9342](https://github.com/quarto-dev/quarto-cli/issues/9342) for details.\n:::\n\n### Colspans and Rowspans\n\nTables containing cells spanning multiple rows or columns are supported across output formats[except in PDF margins]{.aside}.\n\nHowever, using markdown, it is tricky to draw grid tables with spans, and there is no way to express spans in pipe tables. \n\nIf you are comfortable with HTML, or use a package that generates HTML, the table cell HTML attributes `colspan` and `rowspan` are a better option.\n\n```{=html}\n\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n
I span two columnsC1
I span two rowsB2C2
B3C3
\n\n```\n\n````html\n```{=html}\n\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n
I span two columnsC1
I span two rowsB2C2
B3C3
\n\n```\n````\n\n\n### Individual cell alignment\n\nMarkdown supports specification of alignment by column, but does not allow setting the alignment of individual cells. The CSS properties `text-align` and `vertical-align` are only available through Raw HTML. (These are not currently supported by PDF/Latex or Pptx output formats, and Docx only supports `text-align`.)\n\n\n```{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\"Placeholdervertical-align: topvertical-align: middlevertical-align: bottom
text-align: left
text-align: center
text-align: right
\n \n\n```\n\n````html\n```{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\"Placeholdervertical-align: topvertical-align: middlevertical-align: bottom
text-align: left
text-align: center
text-align: right
\n \n\n```\n````\n\n## Disabling Quarto Table Processing\n\nIt's possible that Quarto's processing of HTML tables may interfere with the HTML produced computationally with table packages in R and Python (or other supported languages).\n\n\nWhen you disable Quarto's HTML table processing, tables are not translated to Markdown, will not be rendered to other output formats, and can not use Quarto Markdown features, like cross-references, shortcodes, etc.\nThe tables also won't be visible to Lua filters that act on `Table` nodes.\n\nYou can disable Quarto's HTML table processing at a document level or project level with the option `html-table-processing`:\n\n```{.yaml}\n---\nformat:\n html:\n html-table-processing: none\n---\n```\n\nThis option is also available as a code cell option for Knitr and Jupyter, e.g. \n\n````{markdown}\n```{{r}}\n#| html-table-processing: none\n\n# R Code that generates an HTML table\n```\n````\n\nTo disable Quarto's HTML table processing for parts of a document use a div with the attribute `html-table-processing=\"none\"`:\n\n````{.markdown}\n::: {html-table-processing=\"none\"}\n\nContent with HTML tables you don't want processed.\n\n:::\n````\n\n### Library authors\n\nIf you are the author of a library that emits HTML tables you might like to disable Quarto's processing of HTML tables by adding the attribute `data-quarto-disable-processing=\"true\"` to the `` element. For example:\n\n```html\n
\n ...\n
\n```\n\nAdditionally, you can add the comment `` to the HTML raw block, and Quarto will not attempt to process it.\n\n", "supporting": [ "tables_files" ], diff --git a/_freeze/site_libs/htmltools-fill-0.5.9/fill.css b/_freeze/site_libs/htmltools-fill-0.5.9/fill.css new file mode 100644 index 0000000000..841ea9d59e --- /dev/null +++ b/_freeze/site_libs/htmltools-fill-0.5.9/fill.css @@ -0,0 +1,21 @@ +@layer htmltools { + .html-fill-container { + display: flex; + flex-direction: column; + /* Prevent the container from expanding vertically or horizontally beyond its + parent's constraints. */ + min-height: 0; + min-width: 0; + } + .html-fill-container > .html-fill-item { + /* Fill items can grow and shrink freely within + available vertical space in fillable container */ + flex: 1 1 auto; + min-height: 0; + min-width: 0; + } + .html-fill-container > :not(.html-fill-item) { + /* Prevent shrinking or growing of non-fill items */ + flex: 0 0 auto; + } +} diff --git a/_freeze/site_libs/leaflet-binding-2.2.3/leaflet.js b/_freeze/site_libs/leaflet-binding-2.2.3/leaflet.js new file mode 100644 index 0000000000..79dbe714a8 --- /dev/null +++ b/_freeze/site_libs/leaflet-binding-2.2.3/leaflet.js @@ -0,0 +1,2787 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i this.effectiveLength) throw new Error("Row argument was out of bounds: " + row + " > " + this.effectiveLength); + var colIndex = -1; + + if (typeof col === "undefined") { + var rowData = {}; + this.colnames.forEach(function (name, i) { + rowData[name] = _this3.columns[i][row % _this3.columns[i].length]; + }); + return rowData; + } else if (typeof col === "string") { + colIndex = this._colIndex(col); + } else if (typeof col === "number") { + colIndex = col; + } + + if (colIndex < 0 || colIndex > this.columns.length) { + if (missingOK) return void 0;else throw new Error("Unknown column index: " + col); + } + + return this.columns[colIndex][row % this.columns[colIndex].length]; + } + }, { + key: "nrow", + value: function nrow() { + return this.effectiveLength; + } + }]); + + return DataFrame; +}(); + +exports["default"] = DataFrame; + + +},{"./util":17}],5:[function(require,module,exports){ +"use strict"; + +var _leaflet = require("./global/leaflet"); + +var _leaflet2 = _interopRequireDefault(_leaflet); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +// In RMarkdown's self-contained mode, we don't have a way to carry around the +// images that Leaflet needs but doesn't load into the page. Instead, we'll use +// the unpkg CDN. +if (typeof _leaflet2["default"].Icon.Default.imagePath === "undefined") { + _leaflet2["default"].Icon.Default.imagePath = "https://unpkg.com/leaflet@1.3.1/dist/images/"; +} + + +},{"./global/leaflet":10}],6:[function(require,module,exports){ +"use strict"; + +var _leaflet = require("./global/leaflet"); + +var _leaflet2 = _interopRequireDefault(_leaflet); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +// add texxtsize, textOnly, and style +_leaflet2["default"].Tooltip.prototype.options.textsize = "10px"; +_leaflet2["default"].Tooltip.prototype.options.textOnly = false; +_leaflet2["default"].Tooltip.prototype.options.style = null; // copy original layout to not completely stomp it. + +var initLayoutOriginal = _leaflet2["default"].Tooltip.prototype._initLayout; + +_leaflet2["default"].Tooltip.prototype._initLayout = function () { + initLayoutOriginal.call(this); + this._container.style.fontSize = this.options.textsize; + + if (this.options.textOnly) { + _leaflet2["default"].DomUtil.addClass(this._container, "leaflet-tooltip-text-only"); + } + + if (this.options.style) { + for (var property in this.options.style) { + this._container.style[property] = this.options.style[property]; + } + } +}; + + +},{"./global/leaflet":10}],7:[function(require,module,exports){ +"use strict"; + +var _leaflet = require("./global/leaflet"); + +var _leaflet2 = _interopRequireDefault(_leaflet); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +var protocolRegex = /^\/\//; + +var upgrade_protocol = function upgrade_protocol(urlTemplate) { + if (protocolRegex.test(urlTemplate)) { + if (window.location.protocol === "file:") { + // if in a local file, support http + // http should auto upgrade if necessary + urlTemplate = "http:" + urlTemplate; + } + } + + return urlTemplate; +}; + +var originalLTileLayerInitialize = _leaflet2["default"].TileLayer.prototype.initialize; + +_leaflet2["default"].TileLayer.prototype.initialize = function (urlTemplate, options) { + urlTemplate = upgrade_protocol(urlTemplate); + originalLTileLayerInitialize.call(this, urlTemplate, options); +}; + +var originalLTileLayerWMSInitialize = _leaflet2["default"].TileLayer.WMS.prototype.initialize; + +_leaflet2["default"].TileLayer.WMS.prototype.initialize = function (urlTemplate, options) { + urlTemplate = upgrade_protocol(urlTemplate); + originalLTileLayerWMSInitialize.call(this, urlTemplate, options); +}; + + +},{"./global/leaflet":10}],8:[function(require,module,exports){ +(function (global){(function (){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = global.HTMLWidgets; + + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],9:[function(require,module,exports){ +(function (global){(function (){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = global.jQuery; + + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],10:[function(require,module,exports){ +(function (global){(function (){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = global.L; + + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],11:[function(require,module,exports){ +(function (global){(function (){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = global.L.Proj; + + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],12:[function(require,module,exports){ +(function (global){(function (){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = global.Shiny; + + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],13:[function(require,module,exports){ +"use strict"; + +var _jquery = require("./global/jquery"); + +var _jquery2 = _interopRequireDefault(_jquery); + +var _leaflet = require("./global/leaflet"); + +var _leaflet2 = _interopRequireDefault(_leaflet); + +var _shiny = require("./global/shiny"); + +var _shiny2 = _interopRequireDefault(_shiny); + +var _htmlwidgets = require("./global/htmlwidgets"); + +var _htmlwidgets2 = _interopRequireDefault(_htmlwidgets); + +var _util = require("./util"); + +var _crs_utils = require("./crs_utils"); + +var _controlStore = require("./control-store"); + +var _controlStore2 = _interopRequireDefault(_controlStore); + +var _layerManager = require("./layer-manager"); + +var _layerManager2 = _interopRequireDefault(_layerManager); + +var _methods = require("./methods"); + +var _methods2 = _interopRequireDefault(_methods); + +require("./fixup-default-icon"); + +require("./fixup-default-tooltip"); + +require("./fixup-url-protocol"); + +var _dataframe = require("./dataframe"); + +var _dataframe2 = _interopRequireDefault(_dataframe); + +var _clusterLayerStore = require("./cluster-layer-store"); + +var _clusterLayerStore2 = _interopRequireDefault(_clusterLayerStore); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +window.LeafletWidget = {}; +window.LeafletWidget.utils = {}; + +var methods = window.LeafletWidget.methods = _jquery2["default"].extend({}, _methods2["default"]); + +window.LeafletWidget.DataFrame = _dataframe2["default"]; +window.LeafletWidget.ClusterLayerStore = _clusterLayerStore2["default"]; +window.LeafletWidget.utils.getCRS = _crs_utils.getCRS; // Send updated bounds back to app. Takes a leaflet event object as input. + +function updateBounds(map) { + var id = map.getContainer().id; + var bounds = map.getBounds(); + + _shiny2["default"].onInputChange(id + "_bounds", { + north: bounds.getNorthEast().lat, + east: bounds.getNorthEast().lng, + south: bounds.getSouthWest().lat, + west: bounds.getSouthWest().lng + }); + + _shiny2["default"].onInputChange(id + "_center", { + lng: map.getCenter().lng, + lat: map.getCenter().lat + }); + + _shiny2["default"].onInputChange(id + "_zoom", map.getZoom()); +} + +function preventUnintendedZoomOnScroll(map) { + // Prevent unwanted scroll capturing. Similar in purpose to + // https://github.com/CliffCloud/Leaflet.Sleep but with a + // different set of heuristics. + // The basic idea is that when a mousewheel/DOMMouseScroll + // event is seen, we disable scroll wheel zooming until the + // user moves their mouse cursor or clicks on the map. This + // is slightly trickier than just listening for mousemove, + // because mousemove is fired when the page is scrolled, + // even if the user did not physically move the mouse. We + // handle this by examining the mousemove event's screenX + // and screenY properties; if they change, we know it's a + // "true" move. + // lastScreen can never be null, but its x and y can. + var lastScreen = { + x: null, + y: null + }; + (0, _jquery2["default"])(document).on("mousewheel DOMMouseScroll", "*", function (e) { + // Disable zooming (until the mouse moves or click) + map.scrollWheelZoom.disable(); // Any mousemove events at this screen position will be ignored. + + lastScreen = { + x: e.originalEvent.screenX, + y: e.originalEvent.screenY + }; + }); + (0, _jquery2["default"])(document).on("mousemove", "*", function (e) { + // Did the mouse really move? + if (map.options.scrollWheelZoom) { + if (lastScreen.x !== null && e.screenX !== lastScreen.x || e.screenY !== lastScreen.y) { + // It really moved. Enable zooming. + map.scrollWheelZoom.enable(); + lastScreen = { + x: null, + y: null + }; + } + } + }); + (0, _jquery2["default"])(document).on("mousedown", ".leaflet", function (e) { + // Clicking always enables zooming. + if (map.options.scrollWheelZoom) { + map.scrollWheelZoom.enable(); + lastScreen = { + x: null, + y: null + }; + } + }); +} + +_htmlwidgets2["default"].widget({ + name: "leaflet", + type: "output", + factory: function factory(el, width, height) { + var map = null; + return { + // we need to store our map in our returned object. + getMap: function getMap() { + return map; + }, + renderValue: function renderValue(data) { + // Create an appropriate CRS Object if specified + if (data && data.options && data.options.crs) { + data.options.crs = (0, _crs_utils.getCRS)(data.options.crs); + } // As per https://github.com/rstudio/leaflet/pull/294#discussion_r79584810 + + + if (map) { + map.remove(); + + map = function () { + return; + }(); // undefine map + + } + + if (data.options.mapFactory && typeof data.options.mapFactory === "function") { + map = data.options.mapFactory(el, data.options); + } else { + map = _leaflet2["default"].map(el, data.options); + } + + preventUnintendedZoomOnScroll(map); // Store some state in the map object + + map.leafletr = { + // Has the map ever rendered successfully? + hasRendered: false, + // Data to be rendered when resize is called with area != 0 + pendingRenderData: null + }; // Check if the map is rendered statically (no output binding) + + if (_htmlwidgets2["default"].shinyMode && /\bshiny-bound-output\b/.test(el.className)) { + map.id = el.id; // Store the map on the element so we can find it later by ID + + (0, _jquery2["default"])(el).data("leaflet-map", map); // When the map is clicked, send the coordinates back to the app + + map.on("click", function (e) { + _shiny2["default"].onInputChange(map.id + "_click", { + lat: e.latlng.lat, + lng: e.latlng.lng, + ".nonce": Math.random() // Force reactivity if lat/lng hasn't changed + + }); + }); + var groupTimerId = null; + map.on("moveend", function (e) { + updateBounds(e.target); + }).on("layeradd layerremove", function (e) { + // If the layer that's coming or going is a group we created, tell + // the server. + if (map.layerManager.getGroupNameFromLayerGroup(e.layer)) { + // But to avoid chattiness, coalesce events + if (groupTimerId) { + clearTimeout(groupTimerId); + groupTimerId = null; + } + + groupTimerId = setTimeout(function () { + groupTimerId = null; + + _shiny2["default"].onInputChange(map.id + "_groups", map.layerManager.getVisibleGroups()); + }, 100); + } + }); + } + + this.doRenderValue(data, map); + }, + doRenderValue: function doRenderValue(data, map) { + // Leaflet does not behave well when you set up a bunch of layers when + // the map is not visible (width/height == 0). Popups get misaligned + // relative to their owning markers, and the fitBounds calculations + // are off. Therefore we wait until the map is actually showing to + // render the value (we rely on the resize() callback being invoked + // at the appropriate time). + if (el.offsetWidth === 0 || el.offsetHeight === 0) { + map.leafletr.pendingRenderData = data; + return; + } + + map.leafletr.pendingRenderData = null; // Merge data options into defaults + + var options = _jquery2["default"].extend({ + zoomToLimits: "always" + }, data.options); + + if (!map.layerManager) { + map.controls = new _controlStore2["default"](map); + map.layerManager = new _layerManager2["default"](map); + } else { + map.controls.clear(); + map.layerManager.clear(); + } + + var explicitView = false; + + if (data.setView) { + explicitView = true; + map.setView.apply(map, data.setView); + } + + if (data.fitBounds) { + explicitView = true; + methods.fitBounds.apply(map, data.fitBounds); + } + + if (data.flyTo) { + if (!explicitView && !map.leafletr.hasRendered) { + // must be done to give a initial starting point + map.fitWorld(); + } + + explicitView = true; + map.flyTo.apply(map, data.flyTo); + } + + if (data.flyToBounds) { + if (!explicitView && !map.leafletr.hasRendered) { + // must be done to give a initial starting point + map.fitWorld(); + } + + explicitView = true; + methods.flyToBounds.apply(map, data.flyToBounds); + } + + if (data.options.center) { + explicitView = true; + } // Returns true if the zoomToLimits option says that the map should be + // zoomed to map elements. + + + function needsZoom() { + return options.zoomToLimits === "always" || options.zoomToLimits === "first" && !map.leafletr.hasRendered; + } + + if (!explicitView && needsZoom() && !map.getZoom()) { + if (data.limits && !_jquery2["default"].isEmptyObject(data.limits)) { + // Use the natural limits of what's being drawn on the map + // If the size of the bounding box is 0, leaflet gets all weird + var pad = 0.006; + + if (data.limits.lat[0] === data.limits.lat[1]) { + data.limits.lat[0] = data.limits.lat[0] - pad; + data.limits.lat[1] = data.limits.lat[1] + pad; + } + + if (data.limits.lng[0] === data.limits.lng[1]) { + data.limits.lng[0] = data.limits.lng[0] - pad; + data.limits.lng[1] = data.limits.lng[1] + pad; + } + + map.fitBounds([[data.limits.lat[0], data.limits.lng[0]], [data.limits.lat[1], data.limits.lng[1]]]); + } else { + map.fitWorld(); + } + } + + for (var i = 0; data.calls && i < data.calls.length; i++) { + var call = data.calls[i]; + if (methods[call.method]) methods[call.method].apply(map, call.args);else (0, _util.log)("Unknown method " + call.method); + } + + map.leafletr.hasRendered = true; + + if (_htmlwidgets2["default"].shinyMode) { + setTimeout(function () { + updateBounds(map); + }, 1); + } + }, + resize: function resize(width, height) { + if (map) { + map.invalidateSize(); + + if (map.leafletr.pendingRenderData) { + this.doRenderValue(map.leafletr.pendingRenderData, map); + } + } + } + }; + } +}); + +if (_htmlwidgets2["default"].shinyMode) { + _shiny2["default"].addCustomMessageHandler("leaflet-calls", function (data) { + var id = data.id; + var el = document.getElementById(id); + var map = el ? (0, _jquery2["default"])(el).data("leaflet-map") : null; + + if (!map) { + (0, _util.log)("Couldn't find map with id " + id); + return; + } // If the map has not rendered, stash the proposed `leafletProxy()` calls + // in `pendingRenderData.calls` to be run on display via `doRenderValue()`. + // This is necessary if the map has not been rendered. + // If new pendingRenderData is set via a new `leaflet()`, the previous calls will be discarded. + + + if (!map.leafletr.hasRendered) { + map.leafletr.pendingRenderData.calls = map.leafletr.pendingRenderData.calls.concat(data.calls); + return; + } + + for (var i = 0; i < data.calls.length; i++) { + var call = data.calls[i]; + var args = call.args; + + for (var _i = 0; _i < call.evals.length; _i++) { + window.HTMLWidgets.evaluateStringMember(args, call.evals[_i]); + } + + if (call.dependencies) { + _shiny2["default"].renderDependencies(call.dependencies); + } + + if (methods[call.method]) methods[call.method].apply(map, args);else (0, _util.log)("Unknown method " + call.method); + } + }); +} + + +},{"./cluster-layer-store":1,"./control-store":2,"./crs_utils":3,"./dataframe":4,"./fixup-default-icon":5,"./fixup-default-tooltip":6,"./fixup-url-protocol":7,"./global/htmlwidgets":8,"./global/jquery":9,"./global/leaflet":10,"./global/shiny":12,"./layer-manager":14,"./methods":15,"./util":17}],14:[function(require,module,exports){ +(function (global){(function (){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports["default"] = undefined; + +var _jquery = require("./global/jquery"); + +var _jquery2 = _interopRequireDefault(_jquery); + +var _leaflet = require("./global/leaflet"); + +var _leaflet2 = _interopRequireDefault(_leaflet); + +var _util = require("./util"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +var LayerManager = /*#__PURE__*/function () { + function LayerManager(map) { + _classCallCheck(this, LayerManager); + + this._map = map; // BEGIN layer indices + // {: {: layer}} + + this._byGroup = {}; // {: {: layer}} + + this._byCategory = {}; // {: layer} + + this._byLayerId = {}; // {: { + // "group": , + // "layerId": , + // "category": , + // "container": + // } + // } + + this._byStamp = {}; // {: {: [, , ...], ...}} + + this._byCrosstalkGroup = {}; // END layer indices + // {: L.layerGroup} + + this._categoryContainers = {}; // {: L.layerGroup} + + this._groupContainers = {}; + } + + _createClass(LayerManager, [{ + key: "addLayer", + value: function addLayer(layer, category, layerId, group, ctGroup, ctKey) { + var _this = this; + + // Was a group provided? + var hasId = typeof layerId === "string"; + var grouped = typeof group === "string"; + var stamp = _leaflet2["default"].Util.stamp(layer) + ""; // This will be the default layer group to add the layer to. + // We may overwrite this let before using it (i.e. if a group is assigned). + // This one liner creates the _categoryContainers[category] entry if it + // doesn't already exist. + + var container = this._categoryContainers[category] = this._categoryContainers[category] || _leaflet2["default"].layerGroup().addTo(this._map); + + var oldLayer = null; + + if (hasId) { + // First, remove any layer with the same category and layerId + var prefixedLayerId = this._layerIdKey(category, layerId); + + oldLayer = this._byLayerId[prefixedLayerId]; + + if (oldLayer) { + this._removeLayer(oldLayer); + } // Update layerId index + + + this._byLayerId[prefixedLayerId] = layer; + } // Update group index + + + if (grouped) { + this._byGroup[group] = this._byGroup[group] || {}; + this._byGroup[group][stamp] = layer; // Since a group is assigned, don't add the layer to the category's layer + // group; instead, use the group's layer group. + // This one liner creates the _groupContainers[group] entry if it doesn't + // already exist. + + container = this.getLayerGroup(group, true); + } // Update category index + + + this._byCategory[category] = this._byCategory[category] || {}; + this._byCategory[category][stamp] = layer; // Update stamp index + + var layerInfo = this._byStamp[stamp] = { + layer: layer, + group: group, + ctGroup: ctGroup, + ctKey: ctKey, + layerId: layerId, + category: category, + container: container, + hidden: false + }; // Update crosstalk group index + + if (ctGroup) { + if (layer.setStyle) { + // Need to save this info so we know what to set opacity to later + layer.options.origOpacity = typeof layer.options.opacity !== "undefined" ? layer.options.opacity : 0.5; + layer.options.origFillOpacity = typeof layer.options.fillOpacity !== "undefined" ? layer.options.fillOpacity : 0.2; + } + + var ctg = this._byCrosstalkGroup[ctGroup]; + + if (!ctg) { + ctg = this._byCrosstalkGroup[ctGroup] = {}; + var crosstalk = global.crosstalk; + + var handleFilter = function handleFilter(e) { + if (!e.value) { + var groupKeys = Object.keys(ctg); + + for (var i = 0; i < groupKeys.length; i++) { + var key = groupKeys[i]; + var _layerInfo = _this._byStamp[ctg[key]]; + + _this._setVisibility(_layerInfo, true); + } + } else { + var selectedKeys = {}; + + for (var _i = 0; _i < e.value.length; _i++) { + selectedKeys[e.value[_i]] = true; + } + + var _groupKeys = Object.keys(ctg); + + for (var _i2 = 0; _i2 < _groupKeys.length; _i2++) { + var _key = _groupKeys[_i2]; + var _layerInfo2 = _this._byStamp[ctg[_key]]; + + _this._setVisibility(_layerInfo2, selectedKeys[_groupKeys[_i2]]); + } + } + }; + + var filterHandle = new crosstalk.FilterHandle(ctGroup); + filterHandle.on("change", handleFilter); + + var handleSelection = function handleSelection(e) { + if (!e.value || !e.value.length) { + var groupKeys = Object.keys(ctg); + + for (var i = 0; i < groupKeys.length; i++) { + var key = groupKeys[i]; + var _layerInfo3 = _this._byStamp[ctg[key]]; + + _this._setOpacity(_layerInfo3, 1.0); + } + } else { + var selectedKeys = {}; + + for (var _i3 = 0; _i3 < e.value.length; _i3++) { + selectedKeys[e.value[_i3]] = true; + } + + var _groupKeys2 = Object.keys(ctg); + + for (var _i4 = 0; _i4 < _groupKeys2.length; _i4++) { + var _key2 = _groupKeys2[_i4]; + var _layerInfo4 = _this._byStamp[ctg[_key2]]; + + _this._setOpacity(_layerInfo4, selectedKeys[_groupKeys2[_i4]] ? 1.0 : 0.2); + } + } + }; + + var selHandle = new crosstalk.SelectionHandle(ctGroup); + selHandle.on("change", handleSelection); + setTimeout(function () { + handleFilter({ + value: filterHandle.filteredKeys + }); + handleSelection({ + value: selHandle.value + }); + }, 100); + } + + if (!ctg[ctKey]) ctg[ctKey] = []; + ctg[ctKey].push(stamp); + } // Add to container + + + if (!layerInfo.hidden) container.addLayer(layer); + return oldLayer; + } + }, { + key: "brush", + value: function brush(bounds, extraInfo) { + var _this2 = this; + + /* eslint-disable no-console */ + // For each Crosstalk group... + Object.keys(this._byCrosstalkGroup).forEach(function (ctGroupName) { + var ctg = _this2._byCrosstalkGroup[ctGroupName]; + var selection = []; // ...iterate over each Crosstalk key (each of which may have multiple + // layers)... + + Object.keys(ctg).forEach(function (ctKey) { + // ...and for each layer... + ctg[ctKey].forEach(function (stamp) { + var layerInfo = _this2._byStamp[stamp]; // ...if it's something with a point... + + if (layerInfo.layer.getLatLng) { + // ... and it's inside the selection bounds... + // TODO: Use pixel containment, not lat/lng containment + if (bounds.contains(layerInfo.layer.getLatLng())) { + // ...add the key to the selection. + selection.push(ctKey); + } + } + }); + }); + new global.crosstalk.SelectionHandle(ctGroupName).set(selection, extraInfo); + }); + } + }, { + key: "unbrush", + value: function unbrush(extraInfo) { + Object.keys(this._byCrosstalkGroup).forEach(function (ctGroupName) { + new global.crosstalk.SelectionHandle(ctGroupName).clear(extraInfo); + }); + } + }, { + key: "_setVisibility", + value: function _setVisibility(layerInfo, visible) { + if (layerInfo.hidden ^ visible) { + return; + } else if (visible) { + layerInfo.container.addLayer(layerInfo.layer); + layerInfo.hidden = false; + } else { + layerInfo.container.removeLayer(layerInfo.layer); + layerInfo.hidden = true; + } + } + }, { + key: "_setOpacity", + value: function _setOpacity(layerInfo, opacity) { + if (layerInfo.layer.setOpacity) { + layerInfo.layer.setOpacity(opacity); + } else if (layerInfo.layer.setStyle) { + layerInfo.layer.setStyle({ + opacity: opacity * layerInfo.layer.options.origOpacity, + fillOpacity: opacity * layerInfo.layer.options.origFillOpacity + }); + } + } + }, { + key: "getLayer", + value: function getLayer(category, layerId) { + return this._byLayerId[this._layerIdKey(category, layerId)]; + } + }, { + key: "removeLayer", + value: function removeLayer(category, layerIds) { + var _this3 = this; + + // Find layer info + _jquery2["default"].each((0, _util.asArray)(layerIds), function (i, layerId) { + var layer = _this3._byLayerId[_this3._layerIdKey(category, layerId)]; + + if (layer) { + _this3._removeLayer(layer); + } + }); + } + }, { + key: "clearLayers", + value: function clearLayers(category) { + var _this4 = this; + + // Find all layers in _byCategory[category] + var catTable = this._byCategory[category]; + + if (!catTable) { + return false; + } // Remove all layers. Make copy of keys to avoid mutating the collection + // behind the iterator you're accessing. + + + var stamps = []; + + _jquery2["default"].each(catTable, function (k, v) { + stamps.push(k); + }); + + _jquery2["default"].each(stamps, function (i, stamp) { + _this4._removeLayer(stamp); + }); + } + }, { + key: "getLayerGroup", + value: function getLayerGroup(group, ensureExists) { + var g = this._groupContainers[group]; + + if (ensureExists && !g) { + this._byGroup[group] = this._byGroup[group] || {}; + g = this._groupContainers[group] = _leaflet2["default"].featureGroup(); + g.groupname = group; + g.addTo(this._map); + } + + return g; + } + }, { + key: "getGroupNameFromLayerGroup", + value: function getGroupNameFromLayerGroup(layerGroup) { + return layerGroup.groupname; + } + }, { + key: "getVisibleGroups", + value: function getVisibleGroups() { + var _this5 = this; + + var result = []; + + _jquery2["default"].each(this._groupContainers, function (k, v) { + if (_this5._map.hasLayer(v)) { + result.push(k); + } + }); + + return result; + } + }, { + key: "getAllGroupNames", + value: function getAllGroupNames() { + var result = []; + + _jquery2["default"].each(this._groupContainers, function (k, v) { + result.push(k); + }); + + return result; + } + }, { + key: "clearGroup", + value: function clearGroup(group) { + var _this6 = this; + + // Find all layers in _byGroup[group] + var groupTable = this._byGroup[group]; + + if (!groupTable) { + return false; + } // Remove all layers. Make copy of keys to avoid mutating the collection + // behind the iterator you're accessing. + + + var stamps = []; + + _jquery2["default"].each(groupTable, function (k, v) { + stamps.push(k); + }); + + _jquery2["default"].each(stamps, function (i, stamp) { + _this6._removeLayer(stamp); + }); + } + }, { + key: "clear", + value: function clear() { + function clearLayerGroup(key, layerGroup) { + layerGroup.clearLayers(); + } // Clear all indices and layerGroups + + + this._byGroup = {}; + this._byCategory = {}; + this._byLayerId = {}; + this._byStamp = {}; + this._byCrosstalkGroup = {}; + + _jquery2["default"].each(this._categoryContainers, clearLayerGroup); + + this._categoryContainers = {}; + + _jquery2["default"].each(this._groupContainers, clearLayerGroup); + + this._groupContainers = {}; + } + }, { + key: "_removeLayer", + value: function _removeLayer(layer) { + var stamp; + + if (typeof layer === "string") { + stamp = layer; + } else { + stamp = _leaflet2["default"].Util.stamp(layer); + } + + var layerInfo = this._byStamp[stamp]; + + if (!layerInfo) { + return false; + } + + layerInfo.container.removeLayer(stamp); + + if (typeof layerInfo.group === "string") { + delete this._byGroup[layerInfo.group][stamp]; + } + + if (typeof layerInfo.layerId === "string") { + delete this._byLayerId[this._layerIdKey(layerInfo.category, layerInfo.layerId)]; + } + + delete this._byCategory[layerInfo.category][stamp]; + delete this._byStamp[stamp]; + + if (layerInfo.ctGroup) { + var ctGroup = this._byCrosstalkGroup[layerInfo.ctGroup]; + var layersForKey = ctGroup[layerInfo.ctKey]; + var idx = layersForKey ? layersForKey.indexOf(stamp) : -1; + + if (idx >= 0) { + if (layersForKey.length === 1) { + delete ctGroup[layerInfo.ctKey]; + } else { + layersForKey.splice(idx, 1); + } + } + } + } + }, { + key: "_layerIdKey", + value: function _layerIdKey(category, layerId) { + return category + "\n" + layerId; + } + }]); + + return LayerManager; +}(); + +exports["default"] = LayerManager; + + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./global/jquery":9,"./global/leaflet":10,"./util":17}],15:[function(require,module,exports){ +(function (global){(function (){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _jquery = require("./global/jquery"); + +var _jquery2 = _interopRequireDefault(_jquery); + +var _leaflet = require("./global/leaflet"); + +var _leaflet2 = _interopRequireDefault(_leaflet); + +var _shiny = require("./global/shiny"); + +var _shiny2 = _interopRequireDefault(_shiny); + +var _htmlwidgets = require("./global/htmlwidgets"); + +var _htmlwidgets2 = _interopRequireDefault(_htmlwidgets); + +var _util = require("./util"); + +var _crs_utils = require("./crs_utils"); + +var _dataframe = require("./dataframe"); + +var _dataframe2 = _interopRequireDefault(_dataframe); + +var _clusterLayerStore = require("./cluster-layer-store"); + +var _clusterLayerStore2 = _interopRequireDefault(_clusterLayerStore); + +var _mipmapper = require("./mipmapper"); + +var _mipmapper2 = _interopRequireDefault(_mipmapper); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +var methods = {}; +exports["default"] = methods; + +function mouseHandler(mapId, layerId, group, eventName, extraInfo) { + return function (e) { + if (!_htmlwidgets2["default"].shinyMode) return; + var latLng = e.target.getLatLng ? e.target.getLatLng() : e.latlng; + + if (latLng) { + // retrieve only lat, lon values to remove prototype + // and extra parameters added by 3rd party modules + // these objects are for json serialization, not javascript + var latLngVal = _leaflet2["default"].latLng(latLng); // make sure it has consistent shape + + + latLng = { + lat: latLngVal.lat, + lng: latLngVal.lng + }; + } + + var eventInfo = _jquery2["default"].extend({ + id: layerId, + ".nonce": Math.random() // force reactivity + + }, group !== null ? { + group: group + } : null, latLng, extraInfo); + + _shiny2["default"].onInputChange(mapId + "_" + eventName, eventInfo); + }; +} + +methods.mouseHandler = mouseHandler; + +methods.clearGroup = function (group) { + var _this = this; + + _jquery2["default"].each((0, _util.asArray)(group), function (i, v) { + _this.layerManager.clearGroup(v); + }); +}; + +methods.setView = function (center, zoom, options) { + this.setView(center, zoom, options); +}; + +methods.fitBounds = function (lat1, lng1, lat2, lng2, options) { + this.fitBounds([[lat1, lng1], [lat2, lng2]], options); +}; + +methods.flyTo = function (center, zoom, options) { + this.flyTo(center, zoom, options); +}; + +methods.flyToBounds = function (lat1, lng1, lat2, lng2, options) { + this.flyToBounds([[lat1, lng1], [lat2, lng2]], options); +}; + +methods.setMaxBounds = function (lat1, lng1, lat2, lng2) { + this.setMaxBounds([[lat1, lng1], [lat2, lng2]]); +}; + +methods.addPopups = function (lat, lng, popup, layerId, group, options) { + var _this2 = this; + + var df = new _dataframe2["default"]().col("lat", lat).col("lng", lng).col("popup", popup).col("layerId", layerId).col("group", group).cbind(options); + + var _loop = function _loop(i) { + if (_jquery2["default"].isNumeric(df.get(i, "lat")) && _jquery2["default"].isNumeric(df.get(i, "lng"))) { + (function () { + var popup = _leaflet2["default"].popup(df.get(i)).setLatLng([df.get(i, "lat"), df.get(i, "lng")]).setContent(df.get(i, "popup")); + + var thisId = df.get(i, "layerId"); + var thisGroup = df.get(i, "group"); + this.layerManager.addLayer(popup, "popup", thisId, thisGroup); + }).call(_this2); + } + }; + + for (var i = 0; i < df.nrow(); i++) { + _loop(i); + } +}; + +methods.removePopup = function (layerId) { + this.layerManager.removeLayer("popup", layerId); +}; + +methods.clearPopups = function () { + this.layerManager.clearLayers("popup"); +}; + +methods.addTiles = function (urlTemplate, layerId, group, options) { + this.layerManager.addLayer(_leaflet2["default"].tileLayer(urlTemplate, options), "tile", layerId, group); +}; + +methods.removeTiles = function (layerId) { + this.layerManager.removeLayer("tile", layerId); +}; + +methods.clearTiles = function () { + this.layerManager.clearLayers("tile"); +}; + +methods.addWMSTiles = function (baseUrl, layerId, group, options) { + if (options && options.crs) { + options.crs = (0, _crs_utils.getCRS)(options.crs); + } + + this.layerManager.addLayer(_leaflet2["default"].tileLayer.wms(baseUrl, options), "tile", layerId, group); +}; // Given: +// {data: ["a", "b", "c"], index: [0, 1, 0, 2]} +// returns: +// ["a", "b", "a", "c"] + + +function unpackStrings(iconset) { + if (!iconset) { + return iconset; + } + + if (typeof iconset.index === "undefined") { + return iconset; + } + + iconset.data = (0, _util.asArray)(iconset.data); + iconset.index = (0, _util.asArray)(iconset.index); + return _jquery2["default"].map(iconset.index, function (e, i) { + return iconset.data[e]; + }); +} + +function addMarkers(map, df, group, clusterOptions, clusterId, markerFunc) { + (function () { + var _this3 = this; + + var clusterGroup = this.layerManager.getLayer("cluster", clusterId), + cluster = clusterOptions !== null; + + if (cluster && !clusterGroup) { + clusterGroup = _leaflet2["default"].markerClusterGroup.layerSupport(clusterOptions); + + if (clusterOptions.freezeAtZoom) { + var freezeAtZoom = clusterOptions.freezeAtZoom; + delete clusterOptions.freezeAtZoom; + clusterGroup.freezeAtZoom(freezeAtZoom); + } + + clusterGroup.clusterLayerStore = new _clusterLayerStore2["default"](clusterGroup); + } + + var extraInfo = cluster ? { + clusterId: clusterId + } : {}; + + var _loop2 = function _loop2(i) { + if (_jquery2["default"].isNumeric(df.get(i, "lat")) && _jquery2["default"].isNumeric(df.get(i, "lng"))) { + (function () { + var marker = markerFunc(df, i); + var thisId = df.get(i, "layerId"); + var thisGroup = cluster ? null : df.get(i, "group"); + + if (cluster) { + clusterGroup.clusterLayerStore.add(marker, thisId); + } else { + this.layerManager.addLayer(marker, "marker", thisId, thisGroup, df.get(i, "ctGroup", true), df.get(i, "ctKey", true)); + } + + var popup = df.get(i, "popup"); + var popupOptions = df.get(i, "popupOptions"); + + if (popup !== null) { + if (popupOptions !== null) { + marker.bindPopup(popup, popupOptions); + } else { + marker.bindPopup(popup); + } + } + + var label = df.get(i, "label"); + var labelOptions = df.get(i, "labelOptions"); + + if (label !== null) { + if (labelOptions !== null) { + if (labelOptions.permanent) { + marker.bindTooltip(label, labelOptions).openTooltip(); + } else { + marker.bindTooltip(label, labelOptions); + } + } else { + marker.bindTooltip(label); + } + } + + marker.on("click", mouseHandler(this.id, thisId, thisGroup, "marker_click", extraInfo), this); + marker.on("mouseover", mouseHandler(this.id, thisId, thisGroup, "marker_mouseover", extraInfo), this); + marker.on("mouseout", mouseHandler(this.id, thisId, thisGroup, "marker_mouseout", extraInfo), this); + marker.on("dragend", mouseHandler(this.id, thisId, thisGroup, "marker_dragend", extraInfo), this); + }).call(_this3); + } + }; + + for (var i = 0; i < df.nrow(); i++) { + _loop2(i); + } + + if (cluster) { + this.layerManager.addLayer(clusterGroup, "cluster", clusterId, group); + } + }).call(map); +} + +methods.addGenericMarkers = addMarkers; + +methods.addMarkers = function (lat, lng, icon, layerId, group, options, popup, popupOptions, clusterOptions, clusterId, label, labelOptions, crosstalkOptions) { + var icondf; + var getIcon; + + if (icon) { + // Unpack icons + icon.iconUrl = unpackStrings(icon.iconUrl); + icon.iconRetinaUrl = unpackStrings(icon.iconRetinaUrl); + icon.shadowUrl = unpackStrings(icon.shadowUrl); + icon.shadowRetinaUrl = unpackStrings(icon.shadowRetinaUrl); // This cbinds the icon URLs and any other icon options; they're all + // present on the icon object. + + icondf = new _dataframe2["default"]().cbind(icon); // Constructs an icon from a specified row of the icon dataframe. + + getIcon = function getIcon(i) { + var opts = icondf.get(i); + + if (!opts.iconUrl) { + return new _leaflet2["default"].Icon.Default(); + } // Composite options (like points or sizes) are passed from R with each + // individual component as its own option. We need to combine them now + // into their composite form. + + + if (opts.iconWidth) { + opts.iconSize = [opts.iconWidth, opts.iconHeight]; + } + + if (opts.shadowWidth) { + opts.shadowSize = [opts.shadowWidth, opts.shadowHeight]; + } + + if (opts.iconAnchorX) { + opts.iconAnchor = [opts.iconAnchorX, opts.iconAnchorY]; + } + + if (opts.shadowAnchorX) { + opts.shadowAnchor = [opts.shadowAnchorX, opts.shadowAnchorY]; + } + + if (opts.popupAnchorX) { + opts.popupAnchor = [opts.popupAnchorX, opts.popupAnchorY]; + } + + return new _leaflet2["default"].Icon(opts); + }; + } + + if (!(_jquery2["default"].isEmptyObject(lat) || _jquery2["default"].isEmptyObject(lng)) || _jquery2["default"].isNumeric(lat) && _jquery2["default"].isNumeric(lng)) { + var df = new _dataframe2["default"]().col("lat", lat).col("lng", lng).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).cbind(options).cbind(crosstalkOptions || {}); + if (icon) icondf.effectiveLength = df.nrow(); + addMarkers(this, df, group, clusterOptions, clusterId, function (df, i) { + var options = df.get(i); + if (icon) options.icon = getIcon(i); + return _leaflet2["default"].marker([df.get(i, "lat"), df.get(i, "lng")], options); + }); + } +}; + +methods.addAwesomeMarkers = function (lat, lng, icon, layerId, group, options, popup, popupOptions, clusterOptions, clusterId, label, labelOptions, crosstalkOptions) { + var icondf; + var getIcon; + + if (icon) { + // This cbinds the icon URLs and any other icon options; they're all + // present on the icon object. + icondf = new _dataframe2["default"]().cbind(icon); // Constructs an icon from a specified row of the icon dataframe. + + getIcon = function getIcon(i) { + var opts = icondf.get(i); + + if (!opts) { + return new _leaflet2["default"].AwesomeMarkers.icon(); + } + + if (opts.squareMarker) { + opts.className = "awesome-marker awesome-marker-square"; + } + + return new _leaflet2["default"].AwesomeMarkers.icon(opts); + }; + } + + if (!(_jquery2["default"].isEmptyObject(lat) || _jquery2["default"].isEmptyObject(lng)) || _jquery2["default"].isNumeric(lat) && _jquery2["default"].isNumeric(lng)) { + var df = new _dataframe2["default"]().col("lat", lat).col("lng", lng).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).cbind(options).cbind(crosstalkOptions || {}); + if (icon) icondf.effectiveLength = df.nrow(); + addMarkers(this, df, group, clusterOptions, clusterId, function (df, i) { + var options = df.get(i); + if (icon) options.icon = getIcon(i); + return _leaflet2["default"].marker([df.get(i, "lat"), df.get(i, "lng")], options); + }); + } +}; + +function addLayers(map, category, df, layerFunc) { + var _loop3 = function _loop3(i) { + (function () { + var layer = layerFunc(df, i); + + if (!_jquery2["default"].isEmptyObject(layer)) { + var thisId = df.get(i, "layerId"); + var thisGroup = df.get(i, "group"); + this.layerManager.addLayer(layer, category, thisId, thisGroup, df.get(i, "ctGroup", true), df.get(i, "ctKey", true)); + + if (layer.bindPopup) { + var popup = df.get(i, "popup"); + var popupOptions = df.get(i, "popupOptions"); + + if (popup !== null) { + if (popupOptions !== null) { + layer.bindPopup(popup, popupOptions); + } else { + layer.bindPopup(popup); + } + } + } + + if (layer.bindTooltip) { + var label = df.get(i, "label"); + var labelOptions = df.get(i, "labelOptions"); + + if (label !== null) { + if (labelOptions !== null) { + layer.bindTooltip(label, labelOptions); + } else { + layer.bindTooltip(label); + } + } + } + + layer.on("click", mouseHandler(this.id, thisId, thisGroup, category + "_click"), this); + layer.on("mouseover", mouseHandler(this.id, thisId, thisGroup, category + "_mouseover"), this); + layer.on("mouseout", mouseHandler(this.id, thisId, thisGroup, category + "_mouseout"), this); + var highlightStyle = df.get(i, "highlightOptions"); + + if (!_jquery2["default"].isEmptyObject(highlightStyle)) { + var defaultStyle = {}; + + _jquery2["default"].each(highlightStyle, function (k, v) { + if (k != "bringToFront" && k != "sendToBack") { + if (df.get(i, k)) { + defaultStyle[k] = df.get(i, k); + } + } + }); + + layer.on("mouseover", function (e) { + this.setStyle(highlightStyle); + + if (highlightStyle.bringToFront) { + this.bringToFront(); + } + }); + layer.on("mouseout", function (e) { + this.setStyle(defaultStyle); + + if (highlightStyle.sendToBack) { + this.bringToBack(); + } + }); + } + } + }).call(map); + }; + + for (var i = 0; i < df.nrow(); i++) { + _loop3(i); + } +} + +methods.addGenericLayers = addLayers; + +methods.addCircles = function (lat, lng, radius, layerId, group, options, popup, popupOptions, label, labelOptions, highlightOptions, crosstalkOptions) { + if (!(_jquery2["default"].isEmptyObject(lat) || _jquery2["default"].isEmptyObject(lng)) || _jquery2["default"].isNumeric(lat) && _jquery2["default"].isNumeric(lng)) { + var df = new _dataframe2["default"]().col("lat", lat).col("lng", lng).col("radius", radius).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).col("highlightOptions", highlightOptions).cbind(options).cbind(crosstalkOptions || {}); + addLayers(this, "shape", df, function (df, i) { + if (_jquery2["default"].isNumeric(df.get(i, "lat")) && _jquery2["default"].isNumeric(df.get(i, "lng")) && _jquery2["default"].isNumeric(df.get(i, "radius"))) { + return _leaflet2["default"].circle([df.get(i, "lat"), df.get(i, "lng")], df.get(i, "radius"), df.get(i)); + } else { + return null; + } + }); + } +}; + +methods.addCircleMarkers = function (lat, lng, radius, layerId, group, options, clusterOptions, clusterId, popup, popupOptions, label, labelOptions, crosstalkOptions) { + if (!(_jquery2["default"].isEmptyObject(lat) || _jquery2["default"].isEmptyObject(lng)) || _jquery2["default"].isNumeric(lat) && _jquery2["default"].isNumeric(lng)) { + var df = new _dataframe2["default"]().col("lat", lat).col("lng", lng).col("radius", radius).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).cbind(crosstalkOptions || {}).cbind(options); + addMarkers(this, df, group, clusterOptions, clusterId, function (df, i) { + return _leaflet2["default"].circleMarker([df.get(i, "lat"), df.get(i, "lng")], df.get(i)); + }); + } +}; +/* + * @param lat Array of arrays of latitude coordinates for polylines + * @param lng Array of arrays of longitude coordinates for polylines + */ + + +methods.addPolylines = function (polygons, layerId, group, options, popup, popupOptions, label, labelOptions, highlightOptions) { + if (polygons.length > 0) { + var df = new _dataframe2["default"]().col("shapes", polygons).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).col("highlightOptions", highlightOptions).cbind(options); + addLayers(this, "shape", df, function (df, i) { + var shapes = df.get(i, "shapes"); + shapes = shapes.map(function (shape) { + return _htmlwidgets2["default"].dataframeToD3(shape[0]); + }); + + if (shapes.length > 1) { + return _leaflet2["default"].polyline(shapes, df.get(i)); + } else { + return _leaflet2["default"].polyline(shapes[0], df.get(i)); + } + }); + } +}; + +methods.removeMarker = function (layerId) { + this.layerManager.removeLayer("marker", layerId); +}; + +methods.clearMarkers = function () { + this.layerManager.clearLayers("marker"); +}; + +methods.removeMarkerCluster = function (layerId) { + this.layerManager.removeLayer("cluster", layerId); +}; + +methods.removeMarkerFromCluster = function (layerId, clusterId) { + var cluster = this.layerManager.getLayer("cluster", clusterId); + if (!cluster) return; + cluster.clusterLayerStore.remove(layerId); +}; + +methods.clearMarkerClusters = function () { + this.layerManager.clearLayers("cluster"); +}; + +methods.removeShape = function (layerId) { + this.layerManager.removeLayer("shape", layerId); +}; + +methods.clearShapes = function () { + this.layerManager.clearLayers("shape"); +}; + +methods.addRectangles = function (lat1, lng1, lat2, lng2, layerId, group, options, popup, popupOptions, label, labelOptions, highlightOptions) { + var df = new _dataframe2["default"]().col("lat1", lat1).col("lng1", lng1).col("lat2", lat2).col("lng2", lng2).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).col("highlightOptions", highlightOptions).cbind(options); + addLayers(this, "shape", df, function (df, i) { + if (_jquery2["default"].isNumeric(df.get(i, "lat1")) && _jquery2["default"].isNumeric(df.get(i, "lng1")) && _jquery2["default"].isNumeric(df.get(i, "lat2")) && _jquery2["default"].isNumeric(df.get(i, "lng2"))) { + return _leaflet2["default"].rectangle([[df.get(i, "lat1"), df.get(i, "lng1")], [df.get(i, "lat2"), df.get(i, "lng2")]], df.get(i)); + } else { + return null; + } + }); +}; +/* + * @param lat Array of arrays of latitude coordinates for polygons + * @param lng Array of arrays of longitude coordinates for polygons + */ + + +methods.addPolygons = function (polygons, layerId, group, options, popup, popupOptions, label, labelOptions, highlightOptions) { + if (polygons.length > 0) { + var df = new _dataframe2["default"]().col("shapes", polygons).col("layerId", layerId).col("group", group).col("popup", popup).col("popupOptions", popupOptions).col("label", label).col("labelOptions", labelOptions).col("highlightOptions", highlightOptions).cbind(options); + addLayers(this, "shape", df, function (df, i) { + // This code used to use L.multiPolygon, but that caused + // double-click on a multipolygon to fail to zoom in on the + // map. Surprisingly, putting all the rings in a single + // polygon seems to still work; complicated multipolygons + // are still rendered correctly. + var shapes = df.get(i, "shapes").map(function (polygon) { + return polygon.map(_htmlwidgets2["default"].dataframeToD3); + }).reduce(function (acc, val) { + return acc.concat(val); + }, []); + return _leaflet2["default"].polygon(shapes, df.get(i)); + }); + } +}; + +methods.addGeoJSON = function (data, layerId, group, style) { + // This time, self is actually needed because the callbacks below need + // to access both the inner and outer senses of "this" + var self = this; + + if (typeof data === "string") { + data = JSON.parse(data); + } + + var globalStyle = _jquery2["default"].extend({}, style, data.style || {}); + + var gjlayer = _leaflet2["default"].geoJson(data, { + style: function style(feature) { + if (feature.style || feature.properties.style) { + return _jquery2["default"].extend({}, globalStyle, feature.style, feature.properties.style); + } else { + return globalStyle; + } + }, + onEachFeature: function onEachFeature(feature, layer) { + var extraInfo = { + featureId: feature.id, + properties: feature.properties + }; + var popup = feature.properties ? feature.properties.popup : null; + if (typeof popup !== "undefined" && popup !== null) layer.bindPopup(popup); + layer.on("click", mouseHandler(self.id, layerId, group, "geojson_click", extraInfo), this); + layer.on("mouseover", mouseHandler(self.id, layerId, group, "geojson_mouseover", extraInfo), this); + layer.on("mouseout", mouseHandler(self.id, layerId, group, "geojson_mouseout", extraInfo), this); + } + }); + + this.layerManager.addLayer(gjlayer, "geojson", layerId, group); +}; + +methods.removeGeoJSON = function (layerId) { + this.layerManager.removeLayer("geojson", layerId); +}; + +methods.clearGeoJSON = function () { + this.layerManager.clearLayers("geojson"); +}; + +methods.addTopoJSON = function (data, layerId, group, style) { + // This time, self is actually needed because the callbacks below need + // to access both the inner and outer senses of "this" + var self = this; + + if (typeof data === "string") { + data = JSON.parse(data); + } + + var globalStyle = _jquery2["default"].extend({}, style, data.style || {}); + + var gjlayer = _leaflet2["default"].geoJson(null, { + style: function style(feature) { + if (feature.style || feature.properties.style) { + return _jquery2["default"].extend({}, globalStyle, feature.style, feature.properties.style); + } else { + return globalStyle; + } + }, + onEachFeature: function onEachFeature(feature, layer) { + var extraInfo = { + featureId: feature.id, + properties: feature.properties + }; + var popup = feature.properties.popup; + if (typeof popup !== "undefined" && popup !== null) layer.bindPopup(popup); + layer.on("click", mouseHandler(self.id, layerId, group, "topojson_click", extraInfo), this); + layer.on("mouseover", mouseHandler(self.id, layerId, group, "topojson_mouseover", extraInfo), this); + layer.on("mouseout", mouseHandler(self.id, layerId, group, "topojson_mouseout", extraInfo), this); + } + }); + + global.omnivore.topojson.parse(data, null, gjlayer); + this.layerManager.addLayer(gjlayer, "topojson", layerId, group); +}; + +methods.removeTopoJSON = function (layerId) { + this.layerManager.removeLayer("topojson", layerId); +}; + +methods.clearTopoJSON = function () { + this.layerManager.clearLayers("topojson"); +}; + +methods.addControl = function (html, position, layerId, classes) { + function onAdd(map) { + var div = _leaflet2["default"].DomUtil.create("div", classes); + + if (typeof layerId !== "undefined" && layerId !== null) { + div.setAttribute("id", layerId); + } + + this._div = div; // It's possible for window.Shiny to be true but Shiny.initializeInputs to + // not be, when a static leaflet widget is included as part of the shiny + // UI directly (not through leafletOutput or uiOutput). In this case we + // don't do the normal Shiny stuff as that will all happen when Shiny + // itself loads and binds the entire doc. + + if (window.Shiny && _shiny2["default"].initializeInputs) { + _shiny2["default"].renderHtml(html, this._div); + + _shiny2["default"].initializeInputs(this._div); + + _shiny2["default"].bindAll(this._div); + } else { + this._div.innerHTML = html; + } + + return this._div; + } + + function onRemove(map) { + if (window.Shiny && _shiny2["default"].unbindAll) { + _shiny2["default"].unbindAll(this._div); + } + } + + var Control = _leaflet2["default"].Control.extend({ + options: { + position: position + }, + onAdd: onAdd, + onRemove: onRemove + }); + + this.controls.add(new Control(), layerId, html); +}; + +methods.addCustomControl = function (control, layerId) { + this.controls.add(control, layerId); +}; + +methods.removeControl = function (layerId) { + this.controls.remove(layerId); +}; + +methods.getControl = function (layerId) { + this.controls.get(layerId); +}; + +methods.clearControls = function () { + this.controls.clear(); +}; + +methods.addLegend = function (options) { + var legend = _leaflet2["default"].control({ + position: options.position + }); + + var gradSpan; + + legend.onAdd = function (map) { + var div = _leaflet2["default"].DomUtil.create("div", options.className), + colors = options.colors, + labels = options.labels, + legendHTML = ""; + + if (options.type === "numeric") { + // # Formatting constants. + var singleBinHeight = 20; // The distance between tick marks, in px + + var vMargin = 8; // If 1st tick mark starts at top of gradient, how + // many extra px are needed for the top half of the + // 1st label? (ditto for last tick mark/label) + + var tickWidth = 4; // How wide should tick marks be, in px? + + var labelPadding = 6; // How much distance to reserve for tick mark? + // (Must be >= tickWidth) + // # Derived formatting parameters. + // What's the height of a single bin, in percentage (of gradient height)? + // It might not just be 1/(n-1), if the gradient extends past the tick + // marks (which can be the case for pretty cut points). + + var singleBinPct = (options.extra.p_n - options.extra.p_1) / (labels.length - 1); // Each bin is `singleBinHeight` high. How tall is the gradient? + + var totalHeight = 1 / singleBinPct * singleBinHeight + 1; // How far should the first tick be shifted down, relative to the top + // of the gradient? + + var tickOffset = singleBinHeight / singleBinPct * options.extra.p_1; + gradSpan = (0, _jquery2["default"])("").css({ + "background": "linear-gradient(" + colors + ")", + "opacity": options.opacity, + "height": totalHeight + "px", + "width": "18px", + "display": "block", + "margin-top": vMargin + "px" + }); + var leftDiv = (0, _jquery2["default"])("
").css("float", "left"), + rightDiv = (0, _jquery2["default"])("
").css("float", "left"); + leftDiv.append(gradSpan); + (0, _jquery2["default"])(div).append(leftDiv).append(rightDiv).append((0, _jquery2["default"])("
")); // Have to attach the div to the body at this early point, so that the + // svg text getComputedTextLength() actually works, below. + + document.body.appendChild(div); + var ns = "http://www.w3.org/2000/svg"; + var svg = document.createElementNS(ns, "svg"); + rightDiv.append(svg); + var g = document.createElementNS(ns, "g"); + (0, _jquery2["default"])(g).attr("transform", "translate(0, " + vMargin + ")"); + svg.appendChild(g); // max label width needed to set width of svg, and right-justify text + + var maxLblWidth = 0; // Create tick marks and labels + + _jquery2["default"].each(labels, function (i, label) { + var y = tickOffset + i * singleBinHeight + 0.5; + var thisLabel = document.createElementNS(ns, "text"); + (0, _jquery2["default"])(thisLabel).text(labels[i]).attr("y", y).attr("dx", labelPadding).attr("dy", "0.5ex"); + g.appendChild(thisLabel); + maxLblWidth = Math.max(maxLblWidth, thisLabel.getComputedTextLength()); + var thisTick = document.createElementNS(ns, "line"); + (0, _jquery2["default"])(thisTick).attr("x1", 0).attr("x2", tickWidth).attr("y1", y).attr("y2", y).attr("stroke-width", 1); + g.appendChild(thisTick); + }); // Now that we know the max label width, we can right-justify + + + (0, _jquery2["default"])(svg).find("text").attr("dx", labelPadding + maxLblWidth).attr("text-anchor", "end"); // Final size for + + (0, _jquery2["default"])(svg).css({ + width: maxLblWidth + labelPadding + "px", + height: totalHeight + vMargin * 2 + "px" + }); + + if (options.na_color && _jquery2["default"].inArray(options.na_label, labels) < 0) { + (0, _jquery2["default"])(div).append("
" + options.na_label + "
"); + } + } else { + if (options.na_color && _jquery2["default"].inArray(options.na_label, labels) < 0) { + colors.push(options.na_color); + labels.push(options.na_label); + } + + for (var i = 0; i < colors.length; i++) { + legendHTML += " " + labels[i] + "
"; + } + + div.innerHTML = legendHTML; + } + + if (options.title) (0, _jquery2["default"])(div).prepend("
" + options.title + "
"); + return div; + }; + + if (options.group) { + // Auto generate a layerID if not provided + if (!options.layerId) { + options.layerId = _leaflet2["default"].Util.stamp(legend); + } + + var map = this; + map.on("overlayadd", function (e) { + if (e.name === options.group) { + map.controls.add(legend, options.layerId); + } + }); + map.on("overlayremove", function (e) { + if (e.name === options.group) { + map.controls.remove(options.layerId); + } + }); + map.on("groupadd", function (e) { + if (e.name === options.group) { + map.controls.add(legend, options.layerId); + } + }); + map.on("groupremove", function (e) { + if (e.name === options.group) { + map.controls.remove(options.layerId); + } + }); + } + + this.controls.add(legend, options.layerId); +}; + +methods.addLayersControl = function (baseGroups, overlayGroups, options) { + var _this4 = this; + + // Only allow one layers control at a time + methods.removeLayersControl.call(this); + var firstLayer = true; + var base = {}; + + _jquery2["default"].each((0, _util.asArray)(baseGroups), function (i, g) { + var layer = _this4.layerManager.getLayerGroup(g, true); + + if (layer) { + base[g] = layer; // Check if >1 base layers are visible; if so, hide all but the first one + + if (_this4.hasLayer(layer)) { + if (firstLayer) { + firstLayer = false; + } else { + _this4.removeLayer(layer); + } + } + } + }); + + var overlay = {}; + + _jquery2["default"].each((0, _util.asArray)(overlayGroups), function (i, g) { + var layer = _this4.layerManager.getLayerGroup(g, true); + + if (layer) { + overlay[g] = layer; + } + }); + + this.currentLayersControl = _leaflet2["default"].control.layers(base, overlay, options); + this.addControl(this.currentLayersControl); +}; + +methods.removeLayersControl = function () { + if (this.currentLayersControl) { + this.removeControl(this.currentLayersControl); + this.currentLayersControl = null; + } +}; + +methods.addScaleBar = function (options) { + // Only allow one scale bar at a time + methods.removeScaleBar.call(this); + + var scaleBar = _leaflet2["default"].control.scale(options).addTo(this); + + this.currentScaleBar = scaleBar; +}; + +methods.removeScaleBar = function () { + if (this.currentScaleBar) { + this.currentScaleBar.remove(); + this.currentScaleBar = null; + } +}; + +methods.hideGroup = function (group) { + var _this5 = this; + + _jquery2["default"].each((0, _util.asArray)(group), function (i, g) { + var layer = _this5.layerManager.getLayerGroup(g, true); + + if (layer) { + _this5.removeLayer(layer); + } + }); +}; + +methods.showGroup = function (group) { + var _this6 = this; + + _jquery2["default"].each((0, _util.asArray)(group), function (i, g) { + var layer = _this6.layerManager.getLayerGroup(g, true); + + if (layer) { + _this6.addLayer(layer); + } + }); +}; + +function setupShowHideGroupsOnZoom(map) { + if (map.leafletr._hasInitializedShowHideGroups) { + return; + } + + map.leafletr._hasInitializedShowHideGroups = true; + + function setVisibility(layer, visible, group) { + if (visible !== map.hasLayer(layer)) { + if (visible) { + map.addLayer(layer); + map.fire("groupadd", { + "name": group, + "layer": layer + }); + } else { + map.removeLayer(layer); + map.fire("groupremove", { + "name": group, + "layer": layer + }); + } + } + } + + function showHideGroupsOnZoom() { + if (!map.layerManager) return; + var zoom = map.getZoom(); + map.layerManager.getAllGroupNames().forEach(function (group) { + var layer = map.layerManager.getLayerGroup(group, false); + + if (layer && typeof layer.zoomLevels !== "undefined") { + setVisibility(layer, layer.zoomLevels === true || layer.zoomLevels.indexOf(zoom) >= 0, group); + } + }); + } + + map.showHideGroupsOnZoom = showHideGroupsOnZoom; + map.on("zoomend", showHideGroupsOnZoom); +} + +methods.setGroupOptions = function (group, options) { + var _this7 = this; + + _jquery2["default"].each((0, _util.asArray)(group), function (i, g) { + var layer = _this7.layerManager.getLayerGroup(g, true); // This slightly tortured check is because 0 is a valid value for zoomLevels + + + if (typeof options.zoomLevels !== "undefined" && options.zoomLevels !== null) { + layer.zoomLevels = (0, _util.asArray)(options.zoomLevels); + } + }); + + setupShowHideGroupsOnZoom(this); + this.showHideGroupsOnZoom(); +}; + +methods.addRasterImage = function (uri, bounds, layerId, group, options) { + // uri is a data URI containing an image. We want to paint this image as a + // layer at (top-left) bounds[0] to (bottom-right) bounds[1]. + // We can't simply use ImageOverlay, as it uses bilinear scaling which looks + // awful as you zoom in (and sometimes shifts positions or disappears). + // Instead, we'll use a TileLayer.Canvas to draw pieces of the image. + // First, some helper functions. + // degree2tile converts latitude, longitude, and zoom to x and y tile + // numbers. The tile numbers returned can be non-integral, as there's no + // reason to expect that the lat/lng inputs are exactly on the border of two + // tiles. + // + // We'll use this to convert the bounds we got from the server, into coords + // in tile-space at a given zoom level. Note that once we do the conversion, + // we don't to do any more trigonometry to convert between pixel coordinates + // and tile coordinates; the source image pixel coords, destination canvas + // pixel coords, and tile coords all can be scaled linearly. + function degree2tile(lat, lng, zoom) { + // See http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames + var latRad = lat * Math.PI / 180; + var n = Math.pow(2, zoom); + var x = (lng + 180) / 360 * n; + var y = (1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2 * n; + return { + x: x, + y: y + }; + } // Given a range [from,to) and either one or two numbers, returns true if + // there is any overlap between [x,x1) and the range--or if x1 is omitted, + // then returns true if x is within [from,to). + + + function overlap(from, to, x, + /* optional */ + x1) { + if (arguments.length == 3) x1 = x; + return x < to && x1 >= from; + } + + function getCanvasSmoothingProperty(ctx) { + var candidates = ["imageSmoothingEnabled", "mozImageSmoothingEnabled", "webkitImageSmoothingEnabled", "msImageSmoothingEnabled"]; + + for (var i = 0; i < candidates.length; i++) { + if (typeof ctx[candidates[i]] !== "undefined") { + return candidates[i]; + } + } + + return null; + } // Our general strategy is to: + // 1. Load the data URI in an Image() object, so we can get its pixel + // dimensions and the underlying image data. (We could have done this + // by not encoding as PNG at all but just send an array of RGBA values + // from the server, but that would inflate the JSON too much.) + // 2. Create a hidden canvas that we use just to extract the image data + // from the Image (using Context2D.getImageData()). + // 3. Create a TileLayer.Canvas and add it to the map. + // We want to synchronously create and attach the TileLayer.Canvas (so an + // immediate call to clearRasters() will be respected, for example), but + // Image loads its data asynchronously. Fortunately we can resolve this + // by putting TileLayer.Canvas into async mode, which will let us create + // and attach the layer but have it wait until the image is loaded before + // it actually draws anything. + // These are the variables that we will populate once the image is loaded. + + + var imgData = null; // 1d row-major array, four [0-255] integers per pixel + + var imgDataMipMapper = null; + var w = null; // image width in pixels + + var h = null; // image height in pixels + // We'll use this array to store callbacks that need to be invoked once + // imgData, w, and h have been resolved. + + var imgDataCallbacks = []; // Consumers of imgData, w, and h can call this to be notified when data + // is available. + + function getImageData(callback) { + if (imgData != null) { + // Must not invoke the callback immediately; it's too confusing and + // fragile to have a function invoke the callback *either* immediately + // or in the future. Better to be consistent here. + setTimeout(function () { + callback(imgData, w, h, imgDataMipMapper); + }, 0); + } else { + imgDataCallbacks.push(callback); + } + } + + var img = new Image(); + + img.onload = function () { + // Save size + w = img.width; + h = img.height; // Create a dummy canvas to extract the image data + + var imgDataCanvas = document.createElement("canvas"); + imgDataCanvas.width = w; + imgDataCanvas.height = h; + imgDataCanvas.style.display = "none"; + document.body.appendChild(imgDataCanvas); + var imgDataCtx = imgDataCanvas.getContext("2d"); + imgDataCtx.drawImage(img, 0, 0); // Save the image data. + + imgData = imgDataCtx.getImageData(0, 0, w, h).data; + imgDataMipMapper = new _mipmapper2["default"](img); // Done with the canvas, remove it from the page so it can be gc'd. + + document.body.removeChild(imgDataCanvas); // Alert any getImageData callers who are waiting. + + for (var i = 0; i < imgDataCallbacks.length; i++) { + imgDataCallbacks[i](imgData, w, h, imgDataMipMapper); + } + + imgDataCallbacks = []; + }; + + img.src = uri; + + var canvasTiles = _leaflet2["default"].gridLayer(Object.assign({}, options, { + detectRetina: true, + async: true + })); // NOTE: The done() function MUST NOT be invoked until after the current + // tick; done() looks in Leaflet's tile cache for the current tile, and + // since it's still being constructed, it won't be found. + + + canvasTiles.createTile = function (tilePoint, done) { + var zoom = tilePoint.z; + + var canvas = _leaflet2["default"].DomUtil.create("canvas"); + + var error; // setup tile width and height according to the options + + var size = this.getTileSize(); + canvas.width = size.x; + canvas.height = size.y; + getImageData(function (imgData, w, h, mipmapper) { + try { + // The Context2D we'll being drawing onto. It's always 256x256. + var ctx = canvas.getContext("2d"); // Convert our image data's top-left and bottom-right locations into + // x/y tile coordinates. This is essentially doing a spherical mercator + // projection, then multiplying by 2^zoom. + + var topLeft = degree2tile(bounds[0][0], bounds[0][1], zoom); + var bottomRight = degree2tile(bounds[1][0], bounds[1][1], zoom); // The size of the image in x/y tile coordinates. + + var extent = { + x: bottomRight.x - topLeft.x, + y: bottomRight.y - topLeft.y + }; // Short circuit if tile is totally disjoint from image. + + if (!overlap(tilePoint.x, tilePoint.x + 1, topLeft.x, bottomRight.x)) return; + if (!overlap(tilePoint.y, tilePoint.y + 1, topLeft.y, bottomRight.y)) return; // The linear resolution of the tile we're drawing is always 256px per tile unit. + // If the linear resolution (in either direction) of the image is less than 256px + // per tile unit, then use nearest neighbor; otherwise, use the canvas's built-in + // scaling. + + var imgRes = { + x: w / extent.x, + y: h / extent.y + }; // We can do the actual drawing in one of three ways: + // - Call drawImage(). This is easy and fast, and results in smooth + // interpolation (bilinear?). This is what we want when we are + // reducing the image from its native size. + // - Call drawImage() with imageSmoothingEnabled=false. This is easy + // and fast and gives us nearest-neighbor interpolation, which is what + // we want when enlarging the image. However, it's unsupported on many + // browsers (including QtWebkit). + // - Do a manual nearest-neighbor interpolation. This is what we'll fall + // back to when enlarging, and imageSmoothingEnabled isn't supported. + // In theory it's slower, but still pretty fast on my machine, and the + // results look the same AFAICT. + // Is imageSmoothingEnabled supported? If so, we can let canvas do + // nearest-neighbor interpolation for us. + + var smoothingProperty = getCanvasSmoothingProperty(ctx); + + if (smoothingProperty || imgRes.x >= 256 && imgRes.y >= 256) { + // Use built-in scaling + // Turn off anti-aliasing if necessary + if (smoothingProperty) { + ctx[smoothingProperty] = imgRes.x >= 256 && imgRes.y >= 256; + } // Don't necessarily draw with the full-size image; if we're + // downscaling, use the mipmapper to get a pre-downscaled image + // (see comments on Mipmapper class for why this matters). + + + mipmapper.getBySize(extent.x * 256, extent.y * 256, function (mip) { + // It's possible that the image will go off the edge of the canvas-- + // that's OK, the canvas should clip appropriately. + ctx.drawImage(mip, // Convert abs tile coords to rel tile coords, then *256 to convert + // to rel pixel coords + (topLeft.x - tilePoint.x) * 256, (topLeft.y - tilePoint.y) * 256, // Always draw the whole thing and let canvas clip; so we can just + // convert from size in tile coords straight to pixels + extent.x * 256, extent.y * 256); + }); + } else { + // Use manual nearest-neighbor interpolation + // Calculate the source image pixel coordinates that correspond with + // the top-left and bottom-right of this tile. (If the source image + // only partially overlaps the tile, we use max/min to limit the + // sourceStart/End to only reflect the overlapping portion.) + var sourceStart = { + x: Math.max(0, Math.floor((tilePoint.x - topLeft.x) * imgRes.x)), + y: Math.max(0, Math.floor((tilePoint.y - topLeft.y) * imgRes.y)) + }; + var sourceEnd = { + x: Math.min(w, Math.ceil((tilePoint.x + 1 - topLeft.x) * imgRes.x)), + y: Math.min(h, Math.ceil((tilePoint.y + 1 - topLeft.y) * imgRes.y)) + }; // The size, in dest pixels, that each source pixel should occupy. + // This might be greater or less than 1 (e.g. if x and y resolution + // are very different). + + var pixelSize = { + x: 256 / imgRes.x, + y: 256 / imgRes.y + }; // For each pixel in the source image that overlaps the tile... + + for (var row = sourceStart.y; row < sourceEnd.y; row++) { + for (var col = sourceStart.x; col < sourceEnd.x; col++) { + // ...extract the pixel data... + var i = (row * w + col) * 4; + var r = imgData[i]; + var g = imgData[i + 1]; + var b = imgData[i + 2]; + var a = imgData[i + 3]; + ctx.fillStyle = "rgba(" + [r, g, b, a / 255].join(",") + ")"; // ...calculate the corresponding pixel coord in the dest image + // where it should be drawn... + + var pixelPos = { + x: (col / imgRes.x + topLeft.x - tilePoint.x) * 256, + y: (row / imgRes.y + topLeft.y - tilePoint.y) * 256 + }; // ...and draw a rectangle there. + + ctx.fillRect(Math.round(pixelPos.x), Math.round(pixelPos.y), // Looks crazy, but this is necessary to prevent rounding from + // causing overlap between this rect and its neighbors. The + // minuend is the location of the next pixel, while the + // subtrahend is the position of the current pixel (to turn an + // absolute coordinate to a width/height). Yes, I had to look + // up minuend and subtrahend. + Math.round(pixelPos.x + pixelSize.x) - Math.round(pixelPos.x), Math.round(pixelPos.y + pixelSize.y) - Math.round(pixelPos.y)); + } + } + } + } catch (e) { + error = e; + } finally { + done(error, canvas); + } + }); + return canvas; + }; + + this.layerManager.addLayer(canvasTiles, "image", layerId, group); +}; + +methods.removeImage = function (layerId) { + this.layerManager.removeLayer("image", layerId); +}; + +methods.clearImages = function () { + this.layerManager.clearLayers("image"); +}; + +methods.addMeasure = function (options) { + // if a measureControl already exists, then remove it and + // replace with a new one + methods.removeMeasure.call(this); + this.measureControl = _leaflet2["default"].control.measure(options); + this.addControl(this.measureControl); +}; + +methods.removeMeasure = function () { + if (this.measureControl) { + this.removeControl(this.measureControl); + this.measureControl = null; + } +}; + +methods.addSelect = function (ctGroup) { + var _this8 = this; + + methods.removeSelect.call(this); + this._selectButton = _leaflet2["default"].easyButton({ + states: [{ + stateName: "select-inactive", + icon: "ion-qr-scanner", + title: "Make a selection", + onClick: function onClick(btn, map) { + btn.state("select-active"); + _this8._locationFilter = new _leaflet2["default"].LocationFilter2(); + + if (ctGroup) { + var selectionHandle = new global.crosstalk.SelectionHandle(ctGroup); + selectionHandle.on("change", function (e) { + if (e.sender !== selectionHandle) { + if (_this8._locationFilter) { + _this8._locationFilter.disable(); + + btn.state("select-inactive"); + } + } + }); + + var handler = function handler(e) { + _this8.layerManager.brush(_this8._locationFilter.getBounds(), { + sender: selectionHandle + }); + }; + + _this8._locationFilter.on("enabled", handler); + + _this8._locationFilter.on("change", handler); + + _this8._locationFilter.on("disabled", function () { + selectionHandle.close(); + _this8._locationFilter = null; + }); + } + + _this8._locationFilter.addTo(map); + } + }, { + stateName: "select-active", + icon: "ion-close-round", + title: "Dismiss selection", + onClick: function onClick(btn, map) { + btn.state("select-inactive"); + + _this8._locationFilter.disable(); // If explicitly dismissed, clear the crosstalk selections + + + _this8.layerManager.unbrush(); + } + }] + }); + + this._selectButton.addTo(this); +}; + +methods.removeSelect = function () { + if (this._locationFilter) { + this._locationFilter.disable(); + } + + if (this._selectButton) { + this.removeControl(this._selectButton); + this._selectButton = null; + } +}; + +methods.createMapPane = function (name, zIndex) { + this.createPane(name); + this.getPane(name).style.zIndex = zIndex; +}; + + +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./cluster-layer-store":1,"./crs_utils":3,"./dataframe":4,"./global/htmlwidgets":8,"./global/jquery":9,"./global/leaflet":10,"./global/shiny":12,"./mipmapper":16,"./util":17}],16:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +// This class simulates a mipmap, which shrinks images by powers of two. This +// stepwise reduction results in "pixel-perfect downscaling" (where every +// pixel of the original image has some contribution to the downscaled image) +// as opposed to a single-step downscaling which will discard a lot of data +// (and with sparse images at small scales can give very surprising results). +var Mipmapper = /*#__PURE__*/function () { + function Mipmapper(img) { + _classCallCheck(this, Mipmapper); + + this._layers = [img]; + } // The various functions on this class take a callback function BUT MAY OR MAY + // NOT actually behave asynchronously. + + + _createClass(Mipmapper, [{ + key: "getBySize", + value: function getBySize(desiredWidth, desiredHeight, callback) { + var _this = this; + + var i = 0; + var lastImg = this._layers[0]; + + var testNext = function testNext() { + _this.getByIndex(i, function (img) { + // If current image is invalid (i.e. too small to be rendered) or + // it's smaller than what we wanted, return the last known good image. + if (!img || img.width < desiredWidth || img.height < desiredHeight) { + callback(lastImg); + return; + } else { + lastImg = img; + i++; + testNext(); + return; + } + }); + }; + + testNext(); + } + }, { + key: "getByIndex", + value: function getByIndex(i, callback) { + var _this2 = this; + + if (this._layers[i]) { + callback(this._layers[i]); + return; + } + + this.getByIndex(i - 1, function (prevImg) { + if (!prevImg) { + // prevImg could not be calculated (too small, possibly) + callback(null); + return; + } + + if (prevImg.width < 2 || prevImg.height < 2) { + // Can't reduce this image any further + callback(null); + return; + } // If reduce ever becomes truly asynchronous, we should stuff a promise or + // something into this._layers[i] before calling this.reduce(), to prevent + // redundant reduce operations from happening. + + + _this2.reduce(prevImg, function (reducedImg) { + _this2._layers[i] = reducedImg; + callback(reducedImg); + return; + }); + }); + } + }, { + key: "reduce", + value: function reduce(img, callback) { + var imgDataCanvas = document.createElement("canvas"); + imgDataCanvas.width = Math.ceil(img.width / 2); + imgDataCanvas.height = Math.ceil(img.height / 2); + imgDataCanvas.style.display = "none"; + document.body.appendChild(imgDataCanvas); + + try { + var imgDataCtx = imgDataCanvas.getContext("2d"); + imgDataCtx.drawImage(img, 0, 0, img.width / 2, img.height / 2); + callback(imgDataCanvas); + } finally { + document.body.removeChild(imgDataCanvas); + } + } + }]); + + return Mipmapper; +}(); + +exports["default"] = Mipmapper; + + +},{}],17:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.log = log; +exports.recycle = recycle; +exports.asArray = asArray; + +function log(message) { + /* eslint-disable no-console */ + if (console && console.log) console.log(message); + /* eslint-enable no-console */ +} + +function recycle(values, length, inPlace) { + if (length === 0 && !inPlace) return []; + + if (!(values instanceof Array)) { + if (inPlace) { + throw new Error("Can't do in-place recycling of a non-Array value"); + } + + values = [values]; + } + + if (typeof length === "undefined") length = values.length; + var dest = inPlace ? values : []; + var origLength = values.length; + + while (dest.length < length) { + dest.push(values[dest.length % origLength]); + } + + if (dest.length > length) { + dest.splice(length, dest.length - length); + } + + return dest; +} + +function asArray(value) { + if (value instanceof Array) return value;else return [value]; +} + + +},{}]},{},[13]); diff --git a/docs/authoring/_cross-references-listings.qmd b/docs/authoring/_cross-references-listings.qmd index 01c814519f..5da3517f9e 100644 --- a/docs/authoring/_cross-references-listings.qmd +++ b/docs/authoring/_cross-references-listings.qmd @@ -48,6 +48,7 @@ When rendered, this produces the following output: ```{python} #| label: fig-plot #| fig-cap: Figure caption +#| fig-alt: "Line plot of four values that rises steeply from 1 to 23, drops back to 2, then rises slightly to 4." #| lst-label: lst-plot #| lst-cap: Listing caption diff --git a/docs/authoring/article-layout.qmd b/docs/authoring/article-layout.qmd index 669088d343..e5783729bf 100644 --- a/docs/authoring/article-layout.qmd +++ b/docs/authoring/article-layout.qmd @@ -136,6 +136,10 @@ Column layouts like `screen-inset-shaded` will work with advanced figure layout. #| column: screen-inset-shaded #| layout-nrow: 1 #| echo: fenced +#| fig-alt: +#| - "Scatterplot of stopping distance against speed for 50 cars. Distance increases with speed." +#| - "Scatterplot matrix of the five iris variables, showing every pairwise combination of sepal length, sepal width, petal length, petal width, and species." +#| - "Scatterplot of vapor pressure against temperature for mercury. Pressure stays near zero until about 200 degrees Celsius, then rises steeply." plot(cars) plot(iris) @@ -179,6 +183,7 @@ Figures that you create using code cells can be placed in the margin by using th ```{r} #| label: fig-mtcars #| fig-cap: "MPG vs horsepower, colored by transmission." +#| fig-alt: "Scatterplot of miles per gallon against horsepower for 32 cars, with a smoothed trend line for each transmission type. Mileage falls as horsepower rises, and manual cars cluster at lower horsepower and higher mileage than automatic cars." #| column: margin #| echo: fenced @@ -212,6 +217,7 @@ You can also target specific output types (for example, figures) to be placed in ```{r} #| fig-column: margin +#| fig-alt: "Scatterplot of miles per gallon against horsepower for 32 cars, with a smoothed trend line for each transmission type. Mileage falls as horsepower rises, and manual cars cluster at lower horsepower and higher mileage than automatic cars." #| echo: fenced mtcars2 <- mtcars @@ -260,6 +266,7 @@ For figures and tables, you may leave the content in the body of the document wh ```{r} #| label: fig-cap-margin #| fig-cap: "MPG vs horsepower, colored by transmission." +#| fig-alt: "Scatterplot of miles per gallon against horsepower for 32 cars, with a smoothed trend line for each transmission type. Mileage falls as horsepower rises, and manual cars cluster at lower horsepower and higher mileage than automatic cars." #| cap-location: margin #| echo: fenced diff --git a/docs/authoring/cell-alignment.html b/docs/authoring/cell-alignment.html index dd7c67fa76..1ebc9fc299 100644 --- a/docs/authoring/cell-alignment.html +++ b/docs/authoring/cell-alignment.html @@ -1,6 +1,6 @@ - + diff --git a/docs/authoring/contents.qmd b/docs/authoring/contents.qmd index 9140e012fa..a8bdace132 100644 --- a/docs/authoring/contents.qmd +++ b/docs/authoring/contents.qmd @@ -38,7 +38,7 @@ Here we use the plot, inside a callout: The code above produces the following output: -![A screenshot of the resulting document](./images/use-cell-example.jpg) +![A screenshot of the resulting document](./images/use-cell-example.jpg){fig-alt="Screenshot of a rendered document with two sections. Under the heading 'A section' is the text 'Here we define a plot.' Under the heading 'Another section' is the text 'Here we use the plot, inside a callout:', followed by a note callout titled 'Note the following plot' containing a line rising steadily from 1 to 3."} ## Why diff --git a/docs/authoring/cross-references-divs.qmd b/docs/authoring/cross-references-divs.qmd index 2285c37957..99a65560d3 100644 --- a/docs/authoring/cross-references-divs.qmd +++ b/docs/authoring/cross-references-divs.qmd @@ -90,7 +90,7 @@ An image treated like a table ::: {#tbl-table .column-margin} -![](images/crossref-div-table.png) +![](images/crossref-div-table.png){fig-alt="A photograph of a wooden coffee table with a live-edge oak top and four tapered dark legs."} An image treated like a table diff --git a/docs/authoring/cross-references.qmd b/docs/authoring/cross-references.qmd index f5a48a1b6b..65d5ce9cda 100644 --- a/docs/authoring/cross-references.qmd +++ b/docs/authoring/cross-references.qmd @@ -282,7 +282,7 @@ kable(head(cars)) kable(head(pressure)) ``` -![](/docs/authoring/images/crossref-subtable-nocaption-knitr.png){fig-align="center" width="80%"} +![](/docs/authoring/images/crossref-subtable-nocaption-knitr.png){fig-alt="Two tables side-by-side, with identifier-only subcaptions. The table on the left is titled '(a)' and has columns 'speed' and 'dist'. The table on the right is titled '(b)' and has columns 'temperature' and 'pressure'. Centered above both tables is the text 'Table 1: Tables'." fig-align="center" width="80%"} ### Code Listings diff --git a/docs/authoring/penguins-qmd.qmd b/docs/authoring/penguins-qmd.qmd index ddfa719cd9..edaea486ea 100644 --- a/docs/authoring/penguins-qmd.qmd +++ b/docs/authoring/penguins-qmd.qmd @@ -23,6 +23,7 @@ colors <- c("#FF8C00", "#A020F0", "#008B8B") #| label: fig-size-scatter #| fig-width: 3 #| fig-height: 3 +#| fig-alt: "Scatterplot of flipper length against body mass for 344 penguins, colored by species. Flipper length increases with body mass, and Gentoo penguins sit apart from Adelie and Chinstrap at the highest values of both." ggplot(penguins, aes(body_mass_g, flipper_length_mm)) + geom_point(aes(color = species)) + scale_color_manual(values = colors) +
Placeholder image vertical-align: top vertical-align: middle vertical-align: bottom