diff --git a/_extensions/pandoc-ext/list-table/_extension.yaml b/_extensions/pandoc-ext/list-table/_extension.yaml new file mode 100644 index 0000000000..e9f55c5b9a --- /dev/null +++ b/_extensions/pandoc-ext/list-table/_extension.yaml @@ -0,0 +1,7 @@ +title: list-table +author: Martin Fischer, pandoc extensions contributors +version: 1.0.0 +quarto-required: ">=1.3" +contributes: + filters: + - list-table.lua diff --git a/_extensions/pandoc-ext/list-table/list-table.lua b/_extensions/pandoc-ext/list-table/list-table.lua new file mode 100644 index 0000000000..53fadab893 --- /dev/null +++ b/_extensions/pandoc-ext/list-table/list-table.lua @@ -0,0 +1,270 @@ +-- lua filter for RST-like list-tables in Markdown. +-- Copyright (C) 2021 Martin Fischer, released under MIT license + +if PANDOC_VERSION and PANDOC_VERSION.must_be_at_least then + PANDOC_VERSION:must_be_at_least("2.11") +else + error("pandoc version >=2.11 is required") +end + +-- Get the list of cells in a row. +local row_cells = function (row) return row.cells or {} end + +-- "Polyfill" for older pandoc versions. +if PANDOC_VERSION <= '2.16.2' then + -- previous pandoc versions used simple Attr/list pairs + pandoc.Row = function (cells) return {{}, cells} end + pandoc.TableHead = function (rows) return {{}, rows or {}} end + pandoc.TableFoot = function (rows) return {{}, rows or {}} end + pandoc.Cell = function (contents, align, rowspan, colspan, attr) + return { + attr = attr or pandoc.Attr(), + alignment = align or pandoc.AlignDefault, + contents = contents or {}, + col_span = colspan or 1, + row_span = rowspan or 1 + } + end + row_cells = function (row) return row[2] end +end + +local alignments = { + d = 'AlignDefault', + l = 'AlignLeft', + r = 'AlignRight', + c = 'AlignCenter' +} + + +-- This is like assert() but it can take a Block or Blocks 'where' argument +-- and will output the corresponding markdown (truncated at 1024 characters). +local function assert_(assertion, message, where) + message = message or 'assertion failed!' + if not assertion then + local extra = '' + if where then + local blocks = pandoc.Blocks(where) + local markdown = pandoc.write(pandoc.Pandoc(blocks), 'markdown') + extra = ' at\n' .. markdown:sub(1, 1024) .. + (#markdown > 1024 and '...' or '') + end + error(message .. extra, 2) + end +end + +-- Skip data-pos Divs inserted by the sourcepos extension +local function block_skip_data_pos(block) + if (block.t == "Div" and block.attr.attributes["data-pos"]) then + block = block.content[1] + end + return block +end + +local function blocks_skip_data_pos(blocks) + local new_blocks = {} + for _, block in ipairs(blocks) do + table.insert(new_blocks, block_skip_data_pos(block)) + end + return new_blocks +end + +local function get_colspecs(div_attributes, column_count) + -- list of (align, width) pairs + local colspecs = {} + + for i = 1, column_count do + table.insert(colspecs, {pandoc.AlignDefault, nil}) + end + + if div_attributes.aligns then + local i = 1 + for a in div_attributes.aligns:gmatch('[^,]+') do + assert_(alignments[a] ~= nil, + "unknown column alignment " .. tostring(a)) + colspecs[i][1] = alignments[a] + i = i + 1 + end + div_attributes.aligns = nil + end + + if div_attributes.widths then + local total = 0 + local widths = {} + for w in div_attributes.widths:gmatch('[^,]+') do + table.insert(widths, tonumber(w)) + total = total + tonumber(w) + end + for i = 1, column_count do + colspecs[i][2] = widths[i] / total + end + div_attributes.widths = nil + end + + return colspecs +end + +local function new_table_body(rows, attr, header_col_count) + attr = attr or {} + return { + attr = attr, + body = rows, + head = {}, + row_head_columns = header_col_count + } +end + +local function new_cell(contents) + local attr = {} + local colspan = 1 + local rowspan = 1 + local align = pandoc.AlignDefault + + contents = blocks_skip_data_pos(contents) + + -- At the time of writing this Pandoc does not support attributes + -- on list items, so we use empty spans as a workaround. + if contents[1] and contents[1].content then + if contents[1].content[1] and contents[1].content[1].t == "Span" then + if #contents[1].content[1].content == 0 then + attr = contents[1].content[1].attr + table.remove(contents[1].content, 1) + colspan = attr.attributes.colspan or 1 + attr.attributes.colspan = nil + rowspan = attr.attributes.rowspan or 1 + attr.attributes.rowspan = nil + align = alignments[attr.attributes.align] or pandoc.AlignDefault + attr.attributes.align = nil + end + end + end + + return pandoc.Cell(contents, align, rowspan, colspan, attr) +end + +local function process(div) + if (div.attr.classes[1] ~= "list-table" and + div.attr.classes[1] ~= "list-table-body") then return nil end + local class = div.attr.classes[1] + table.remove(div.attr.classes, 1) + + if #div.content == 0 then return nil end + + local content = blocks_skip_data_pos(div.content) + + local caption = {} + if content[1].t == "Para" then + local para = table.remove(content, 1) + caption = {pandoc.Plain(para.content)} + end + + if #content == 0 then return nil end + + assert_(content[1].t == "BulletList", + "expected bullet list, found " .. content[1].t, content[1]) + local list = content[1] + + -- rows points to the current body's rows + local bodies = {attr=nil, {rows={}}} + local rows = bodies[#bodies].rows + + for i = 1, #list.content do + local attr = nil + local items = list.content[i] + if (#items > 1) then + local item = block_skip_data_pos(items[1]) + assert_(item.content, "expected list item to have row attrs", + item) + assert_(#item.content == 1, "expected row attrs to contain " .. + "only one inline", item.content) + assert_(item.content[1].t == "Span", "expected row attrs to " .. + "contain a span", item.content[1]) + assert_(#item.content[1].content == 0, "expected row attrs " .. + "span to be empty", item.content[1]) + attr = item.content[1].attr + table.remove(items, 1) + end + + assert_(#items == 1, "expected item to contain only one block", items) + + local item = block_skip_data_pos(items[1]) + if (item.t ~= 'Table') then + assert_(item.t == "BulletList", "expected bullet list, found " .. + item.t, item) + local cells = {} + for _, cell_content in pairs(item.content) do + table.insert(cells, new_cell(cell_content)) + end + local row = pandoc.Row(cells, attr) + table.insert(rows, row) + + else + local tab = item + -- XXX is there a better way to check that there's no caption? + assert_((not tab.caption.long or #tab.caption.long == 0) and + (not tab.caption.short or #tab.caption.short == 0), + "table bodies can't have captions (they'd be " .. + "ignored)", tab) + -- XXX would have to check against default colspecs to know whether + -- any have been defined? + -- assert_(#tab.colspecs == 0, "table bodies can't (yet) have " .. + -- "column specs", tab) + -- XXX should allow empty headers; this can happen with pipe tables + -- assert_(not tab.head or #tab.head.rows == 0, + -- "table bodies can't (yet) have headers", tab) + assert_(#tab.bodies == 1, "table bodies can't contain other " .. + "table bodies", tab) + + if #rows > 0 then + table.insert(bodies, {attr=nil, rows={}}) + rows = bodies[#bodies].rows + end + + bodies[#bodies].attr = tab.attr + for _, row in ipairs(tab.bodies[1].body) do + table.insert(rows, row) + end + end + end + + -- switch back to the first body + rows = bodies[1].rows + + local header_row_count = tonumber(div.attr.attributes['header-rows']) or + (class == 'list-table' and 1 or 0) + div.attr.attributes['header-rows'] = nil + + local header_col_count = tonumber(div.attr.attributes['header-cols']) or 0 + div.attr.attributes['header-cols'] = nil + + local column_count = 0 + for i = 1, #row_cells(rows[1] or {}) do + column_count = column_count + row_cells(rows[1])[i].col_span + end + + local colspecs = get_colspecs(div.attr.attributes, column_count) + local thead_rows = {} + for i = 1, header_row_count do + table.insert(thead_rows, table.remove(rows, 1)) + end + + local new_bodies = {} + for _, body in ipairs(bodies) do + if #body.rows > 0 then + table.insert(new_bodies, new_table_body(body.rows, body.attr, + header_col_count)) + end + -- XXX this should be a body property + header_col_count = 0 + end + + return pandoc.Table( + {long = caption, short = {}}, + colspecs, + pandoc.TableHead(thead_rows), + new_bodies, + pandoc.TableFoot(), + div.attr + ) +end + +return {{Div = process}} diff --git a/_freeze/docs/authoring/tables/execute-results/html.json b/_freeze/docs/authoring/tables/execute-results/html.json index 468d9d2bfc..43a2d0f836 100644 --- a/_freeze/docs/authoring/tables/execute-results/html.json +++ b/_freeze/docs/authoring/tables/execute-results/html.json @@ -2,7 +2,7 @@ "hash": "f5ba4756cc531f11e9ea2b640cae0834", "result": { "engine": "jupyter", - "markdown": "---\ntitle: Tables\nengine: jupyter\naliases: \n - /docs/prerelease/1.5/lua-table-processing.html\n---\n\n\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\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![](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\nSee the article on [Cross References](cross-references.qmd) for additional details.\n\n### Subtables\n\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\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## 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## 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\n\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::::\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 tables.\nThis is done by providing a data attribute `qmd` or `qmd-base64` in an embedded `span` or `div` node.\nThese 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\n\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\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\n\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\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\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\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\n\n\n````{markdown}\n```{{r}}\n#| html-table-processing: none\n\n# R Code that generates an HTML table\n```\n````\n\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=3}\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=\"100%\"}\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=\"100%\"}\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=4}\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## 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## 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 tables.\nThis is done by providing a data attribute `qmd` or `qmd-base64` in an embedded `span` or `div` node.\nThese 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### 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", "supporting": [ "tables_files" ], diff --git a/docs/authoring/_figure-examples/_examples.qmd b/docs/authoring/_figure-examples/_examples.qmd index 95f3206142..186fd1c37b 100644 --- a/docs/authoring/_figure-examples/_examples.qmd +++ b/docs/authoring/_figure-examples/_examples.qmd @@ -12,7 +12,13 @@ quarto run take-screenshots.R ## Figure Basics +::: light-content ![Elephant](elephant.png){width="400px"} +::: + +::: dark-content +![Elephant](elephant-dark.png){width="400px"} +::: ## Subfigures diff --git a/docs/authoring/_table-crossrefs.md b/docs/authoring/_table-crossrefs.md index 4ecf522057..3f8ce2f422 100644 --- a/docs/authoring/_table-crossrefs.md +++ b/docs/authoring/_table-crossrefs.md @@ -16,4 +16,10 @@ See @tbl-letters. Which looks like this when rendered to HTML: -![](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"} +::: light-content +![](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="100%"} +::: + +::: dark-content +![](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="100%"} +::: \ No newline at end of file diff --git a/docs/authoring/elephant-dark.png b/docs/authoring/elephant-dark.png new file mode 100644 index 0000000000..b379ed621e Binary files /dev/null and b/docs/authoring/elephant-dark.png differ diff --git a/docs/authoring/figures.qmd b/docs/authoring/figures.qmd index 1c5843d02e..ba6c8c60c7 100644 --- a/docs/authoring/figures.qmd +++ b/docs/authoring/figures.qmd @@ -4,6 +4,8 @@ format: html aliases: - figures-and-layout.html - figure-layout.html +filters: + - list-table --- Quarto includes a number of features aimed at making it easier to work with figures and subfigures, as well as for laying out panels that contain multiple figures, tables, or other content. @@ -18,9 +20,23 @@ In Pandoc markdown, a figure is created whenever a captioned image appears by-it This results in the following treatment for various output types: -| HTML | PDF | Word | -|---------------------------|-----------------------|-----------------------| -| ![](images/html-figure.png){fig-alt="A line drawing of an elephant." width="340"} | ![](images/pdf-figure.png){fig-alt="A line drawing of an elephant."} | ![](images/word-figure.png){fig-alt="A line drawing of an elephant."} | +::: {.list-table header-rows=1 tbl-colwidths="[33, 33, 33]"} + +* - HTML + - PDF + - Word +* + - ::: light-content + ![](images/html-figure.png){fig-alt="A line drawing of an elephant." width="340"} + ::: + + ::: dark-content + ![](images/html-figure-dark.png){fig-alt="A line drawing of an elephant." width="340"} + ::: + - ![](images/pdf-figure.png){fig-alt="A line drawing of an elephant."} + - ![](images/word-figure.png){fig-alt="A line drawing of an elephant."} + +::: Note that for LaTeX / PDF output figures are automatically numbered (you can arrange for figures to be numbered in other formats using [Cross References](cross-references.qmd)). @@ -115,7 +131,13 @@ format: In HTML output formats you can add lightbox styling and behavior to images to allow a reader to click to see a larger version of the image. For example, the following image has lightbox treatment (click on the image to see lightbox in action): +::: light-content ![An elephant](elephant.png){.lightbox width=50%} +::: + +::: dark-content +![An elephant](elephant-dark.png){.lightbox width=50%} +::: Lightbox treatment can be added by adding the class `.lightbox` to an image: @@ -181,7 +203,13 @@ Famous Elephants Again, the last paragraph provides the main caption, and the individual figures carry the sub-captions. Here is what this looks like when rendered as HTML: +::: light-content ![](images/elephant-subfigures.png){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."} +::: + +::: dark-content +![](images/elephant-subfigures-dark.png){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."} +::: Note that the empty lines between the figures (and between the last figure and the caption) are required (it's what indicates that these images belong to their own paragraphs rather than being multiple images within the same paragraph). @@ -201,7 +229,13 @@ To layout two figures with their own standalone captions (and no main caption), ::: ``` +::: light-content ![](images/elephant-figures-no-subcaption.png){fig-alt="An artistic rendition of Surus, Hannibal's last war elephant, is on the left. Underneath this picture is the caption 'Surus.' On the right is a line drawing of Hanno, a famous elephant. Underneath this picture is the caption 'Hanno.'"} +::: + +::: dark-content +![](images/elephant-figures-no-subcaption-dark.png){fig-alt="An artistic rendition of Surus, Hannibal's last war elephant, is on the left. Underneath this picture is the caption 'Surus.' On the right is a line drawing of Hanno, a famous elephant. Underneath this picture is the caption 'Hanno.'"} +::: You can also eliminate the captions entirely: @@ -229,7 +263,13 @@ If you have more than 2 images, you might want to lay them out across multiple r ::: ``` +::: light-content ![](images/elephant-rows.png){fig-alt="A 2x2 grid of pictures of elephants. There are labels underneath each of the pictures. Clockwise from the upper left, the labels say: Surus, Hanno, Lin Wang, and Abdul Abbas."} +::: + +::: dark-content +![](images/elephant-rows-dark.png){fig-alt="A 2x2 grid of pictures of elephants. There are labels underneath each of the pictures. Clockwise from the upper left, the labels say: Surus, Hanno, Lin Wang, and Abdul Abbas."} +::: More complex figure arrangements (e.g. rows with varying column layouts) are possible. See the [Custom Layouts](#complex-layouts) section below for more details. @@ -380,7 +420,14 @@ For example, this defines a layout with two equally sized figures in the first r ::: ``` +::: light-content ![](images/layout-attrib.png){fig-alt="Three elephant pictures arranged such that two pictures are side-by-side in the first row, and the third picture is underneath both of these. The picture on the left in the first row is captioned 'Surus' and the picture on the right is captioned 'Hanno'. The picture underneath these two is captioned 'Lin Wang' and is as as wide and tall as the other two put together."} +::: + +::: dark-content +![](images/layout-attrib-dark.png){fig-alt="Three elephant pictures arranged such that two pictures are side-by-side in the first row, and the third picture is underneath both of these. The picture on the left in the first row is captioned 'Surus' and the picture on the right is captioned 'Hanno'. The picture underneath these two is captioned 'Lin Wang' and is as as wide and tall as the other two put together."} +::: + The `layout` attribute is a 2-dimensional array where the first dimension defines rows and the second columns. In this case `"layout="[[1,1], [1]]"` translates to: create two rows, the first of which has two columns of equal size and the second of which has a single column. @@ -422,7 +469,13 @@ If you have a layout with a row of images of differing heights, you can control ::: ``` +::: light-content ![](images/valign.png){fig-alt="Two pictures of elephants side by side. The picture on the left has the label 'Figure 1: Surus' underneath it. The picture on the right has the label 'Figure 2: Lin Wang' underneath it. The figure on the left is more than twice the width and height of the figure on the right."} +::: + +::: dark-content +![](images/valign-dark.png){fig-alt="Two pictures of elephants side by side. The picture on the left has the label 'Figure 1: Surus' underneath it. The picture on the right has the label 'Figure 2: Lin Wang' underneath it. The figure on the left is more than twice the width and height of the figure on the right."} +::: Note that vertical alignment isn't limited to images, you can also vertically align any other elements that are included in a panel. diff --git a/docs/authoring/images/crossref-table-dark.png b/docs/authoring/images/crossref-table-dark.png new file mode 100644 index 0000000000..c1a85aa7e6 Binary files /dev/null and b/docs/authoring/images/crossref-table-dark.png differ diff --git a/docs/authoring/images/crossref-table.png b/docs/authoring/images/crossref-table.png index 60b47b7a0a..fb3e986842 100644 Binary files a/docs/authoring/images/crossref-table.png and b/docs/authoring/images/crossref-table.png differ diff --git a/docs/authoring/images/elephant-figures-no-subcaption-dark.png b/docs/authoring/images/elephant-figures-no-subcaption-dark.png new file mode 100644 index 0000000000..0f467d7470 Binary files /dev/null and b/docs/authoring/images/elephant-figures-no-subcaption-dark.png differ diff --git a/docs/authoring/images/elephant-figures-no-subcaption.png b/docs/authoring/images/elephant-figures-no-subcaption.png index ab3ba591e4..b81e87f9c9 100644 Binary files a/docs/authoring/images/elephant-figures-no-subcaption.png and b/docs/authoring/images/elephant-figures-no-subcaption.png differ diff --git a/docs/authoring/images/elephant-rows-dark.png b/docs/authoring/images/elephant-rows-dark.png new file mode 100644 index 0000000000..67335d687e Binary files /dev/null and b/docs/authoring/images/elephant-rows-dark.png differ diff --git a/docs/authoring/images/elephant-rows.png b/docs/authoring/images/elephant-rows.png index f6db4c6c40..5c247bef8e 100644 Binary files a/docs/authoring/images/elephant-rows.png and b/docs/authoring/images/elephant-rows.png differ diff --git a/docs/authoring/images/elephant-subfigures-dark.png b/docs/authoring/images/elephant-subfigures-dark.png new file mode 100644 index 0000000000..3add5f9028 Binary files /dev/null and b/docs/authoring/images/elephant-subfigures-dark.png differ diff --git a/docs/authoring/images/elephant-subfigures.png b/docs/authoring/images/elephant-subfigures.png index 2c0f39242f..749c52d42a 100644 Binary files a/docs/authoring/images/elephant-subfigures.png and b/docs/authoring/images/elephant-subfigures.png differ diff --git a/docs/authoring/images/html-figure-dark.png b/docs/authoring/images/html-figure-dark.png new file mode 100644 index 0000000000..44f2b28d87 Binary files /dev/null and b/docs/authoring/images/html-figure-dark.png differ diff --git a/docs/authoring/images/layout-attrib-dark.png b/docs/authoring/images/layout-attrib-dark.png new file mode 100644 index 0000000000..b9f9103a30 Binary files /dev/null and b/docs/authoring/images/layout-attrib-dark.png differ diff --git a/docs/authoring/images/layout-attrib-negative-dark.png b/docs/authoring/images/layout-attrib-negative-dark.png new file mode 100644 index 0000000000..6495ea275f Binary files /dev/null and b/docs/authoring/images/layout-attrib-negative-dark.png differ diff --git a/docs/authoring/images/layout-attrib-negative.png b/docs/authoring/images/layout-attrib-negative.png index f625e32c5b..369dfa9c3e 100644 Binary files a/docs/authoring/images/layout-attrib-negative.png and b/docs/authoring/images/layout-attrib-negative.png differ diff --git a/docs/authoring/images/layout-attrib.png b/docs/authoring/images/layout-attrib.png index 7f5a514ec1..b5ccd1ac57 100644 Binary files a/docs/authoring/images/layout-attrib.png and b/docs/authoring/images/layout-attrib.png differ diff --git a/docs/authoring/images/valign-dark.png b/docs/authoring/images/valign-dark.png new file mode 100644 index 0000000000..6f9fdc93f9 Binary files /dev/null and b/docs/authoring/images/valign-dark.png differ diff --git a/docs/authoring/images/valign.png b/docs/authoring/images/valign.png index 5d05121e72..48cdc740d9 100644 Binary files a/docs/authoring/images/valign.png and b/docs/authoring/images/valign.png differ diff --git a/docs/authoring/markdown-basics.css b/docs/authoring/markdown-basics.css new file mode 100644 index 0000000000..7d0deb2911 --- /dev/null +++ b/docs/authoring/markdown-basics.css @@ -0,0 +1,9 @@ +.heading-output { + border-bottom: none; + margin-top: 0; + margin-bottom: 0; +} + +.pad-to-code-block { + padding-top: 1rem; +} \ No newline at end of file diff --git a/docs/authoring/markdown-basics.qmd b/docs/authoring/markdown-basics.qmd index 3c301a4b98..227ba60250 100644 --- a/docs/authoring/markdown-basics.qmd +++ b/docs/authoring/markdown-basics.qmd @@ -5,17 +5,21 @@ language: section-title-footnotes: Example Footnotes aliases: - /docs/authoring/ +filters: + - list-table +css: + - markdown-basics.css --- ## Overview -Quarto is based on Pandoc and uses its variation of markdown as its underlying document syntax. Pandoc markdown is an extended and slightly revised version of John Gruber's [Markdown](https://daringfireball.net/projects/markdown/) syntax. +Quarto is based on Pandoc and uses its variation of Markdown as its underlying document syntax. Pandoc Markdown is an extended and slightly revised version of John Gruber's [Markdown](https://daringfireball.net/projects/markdown/) syntax. Markdown is a plain text format that is designed to be easy to write, and, even more importantly, easy to read: > A Markdown-formatted document should be publishable as-is, as plain text, without looking like it's been marked up with tags or formatting instructions. -- [John Gruber](https://daringfireball.net/projects/markdown/syntax#philosophy) -This document provides examples of the most commonly used markdown syntax. See the full documentation of [Pandoc's Markdown](https://pandoc.org/MANUAL.html#pandocs-markdown) for more in-depth documentation. +This document provides examples of the most commonly used Markdown syntax. See the full documentation of [Pandoc's Markdown](https://pandoc.org/MANUAL.html#pandocs-markdown) for more in-depth documentation. ## Text Formatting @@ -71,44 +75,87 @@ This document provides examples of the most commonly used markdown syntax. See t : {tbl-colwidths="[50, 50]"} -```{=html} - -``` ## Links & Images -+--------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+ -| Markdown Syntax | Output | -+==============================================================+========================================================================================================+ -| ``` markdown | | -| | | -| ``` | | -+--------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+ -| ``` markdown | [Quarto](https://quarto.org) | -| [Quarto](https://quarto.org) | | -| ``` | | -+--------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+ -| ``` markdown | ![Caption](elephant.png){fig-alt="A line drawing of an elephant."} | -| ![Caption](elephant.png) | | -| ``` | | -+--------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+ -| ``` markdown | [![Caption](elephant.png)](https://quarto.org) | -| [![Caption](elephant.png)](https://quarto.org) | | -| ``` | | -+--------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+ -| ``` markdown | [![Caption](elephant.png "An elephant"){fig-alt="A line drawing of an elephant."}](https://quarto.org) | -| [![Caption](elephant.png "An elephant")](https://quarto.org) | | -| ``` | | -+--------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+ -| ``` markdown | [![](elephant.png){fig-alt="A line drawing of an elephant."}](https://quarto.org) | -| [![](elephant.png){fig-alt="Alt text"}](https://quarto.org) | | -| ``` | | -+--------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+ +::: {.list-table header-rows=1 tbl-colwidths="[50, 50]"} + +* - Markdown Syntax + - Output +* + - ```markdown + +``` + - ::: pad-to-code-block + + ::: +* + - ```markdown +[Quarto](https://quarto.org) +``` + - ::: pad-to-code-block + [Quarto](https://quarto.org) + ::: +* + - ```markdown +![Caption](elephant.png){fig-alt="A line drawing of an elephant."} +``` + - ::: pad-to-code-block + + ::: light-content + ![Caption](elephant.png){fig-alt="A line drawing of an elephant."} + ::: + + ::: dark-content + ![Caption](elephant-dark.png){fig-alt="A line drawing of an elephant."} + ::: + + ::: +* + - ```markdown +[![Caption](elephant.png)](https://quarto.org) +``` + - ::: pad-to-code-block + + ::: light-content + [![Caption](elephant.png)](https://quarto.org) + ::: + + ::: dark-content + [![Caption](elephant-dark.png)](https://quarto.org) + ::: + + ::: +* + - ```markdown +[![Caption](elephant.png "An elephant"){fig-alt="A line drawing of an elephant."}](https://quarto.org) +``` + - ::: pad-to-code-block + + ::: light-content + [![Caption](elephant.png "An elephant"){fig-alt="A line drawing of an elephant."}](https://quarto.org) + ::: + + ::: dark-content + [![Caption](elephant-dark.png "An elephant"){fig-alt="A line drawing of an elephant."}](https://quarto.org) + ::: + + ::: +* + - ```markdown +[![](elephant.png){fig-alt="A line drawing of an elephant."}](https://quarto.org) +``` + - ::: pad-to-code-block + + ::: light-content + [![](elephant.png){fig-alt="A line drawing of an elephant."}](https://quarto.org) + ::: + + ::: dark-content + [![](elephant-dark.png){fig-alt="A line drawing of an elephant."}](https://quarto.org) + ::: + + ::: +::: ## Lists