From 459ad5714e9552634b1111b6091844d89caa9717 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Wed, 20 Aug 2025 09:35:01 -0500 Subject: [PATCH 1/2] document new env var from quarto-cli/#13171 --- .../pandoc-ext/list-table/_extension.yaml | 7 + .../pandoc-ext/list-table/list-table.lua | 270 ++++++++++++++++++ docs/advanced/environment-vars.qmd | 128 ++++++--- 3 files changed, 359 insertions(+), 46 deletions(-) create mode 100644 _extensions/pandoc-ext/list-table/_extension.yaml create mode 100644 _extensions/pandoc-ext/list-table/list-table.lua 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/docs/advanced/environment-vars.qmd b/docs/advanced/environment-vars.qmd index d6fa25def7..2fcb03c200 100644 --- a/docs/advanced/environment-vars.qmd +++ b/docs/advanced/environment-vars.qmd @@ -2,6 +2,8 @@ title: "Environment Variables" summary: Environment variables Quarto inspects and sets format: html +filters: + - list-table --- ## Variables Quarto inspects @@ -15,37 +17,55 @@ quarto render You can read about other ways to set environment variables in Quarto Projects in [Environment Variables](/docs/projects/environment.qmd). -+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Variable | Description | -+=================================+=============================================================================================================================================================================================================================================================================================================================================================================================================================================================+ -| `QUARTO_R` | Explicit path to the version of `Rscript` to be used by the `knitr` engine and `quarto run *.R` command. | -+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_PYTHON` | Explicit path to the version of `python` to be used by the `jupyter` engine and `quarto run *.py` command. | -+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_JULIA` | Explicit path to the version of `julia` to be used by the `julia` engine. | -+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_VERSION_REQUIREMENT` | A [`semver`](https://semver.org/) string describing the Quarto version requested by the environment. If this check fails, Quarto will not run. | -+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_KNITR_RSCRIPT_ARGS` | Comma separated list of command line argument to pass to `Rscript` started by Quarto when rendering with `knitr` engine, e.g. | -| | | -| | ``` | -| | QUARTO_KNITR_RSCRIPT_ARGS="--no-init-file,--max-connections=258" | -| | ``` | -+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_TEXLIVE_BINPATH` | Explicit path to the TeX Live binaries to be passed to `tlmgr option sys_bin` used when setting `tlmgr` and related to `PATH` using `tlmgr add path` . By default, Quarto looks in known places. | -+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_CHROMIUM` | Explicit path to binary to use for chrome headless. Quarto uses [Chrome Devtools Protocol](https://chromedevtools.github.io/devtools-protocol/) to do screenshot of HTML diagrams for PDF insertion. The binary must be compatible with this protocol. (e.g. Chrome, Chromium, Chrome Headless Shell, Edge, ...) | -+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_CHROMIUM_HEADLESS_MODE` | Used for adaption of the `--headless` mode used with `QUARTO_CHROMIUM` binary. Set to `"none"` for `--headless` , or to `"old"` or `"new"` to pass as argument, e.g. `--headless=` . Quarto 1.6 sets `"old"` as default, which works from Chrome 112 to 131. Starting Quarto 1.7.13, `"none"` is the default as [Chrome 132 removed old headless mode](https://developer.chrome.com/blog/removing-headless-old-from-chrome). | -+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_LOG` | Those variables controls the logging behavior: | -| | | -| `QUARTO_LOG_LEVEL` | - `QUARTO_LOG` is the same as using `--log` at command line. It is used to set the path to the log file | -| | | -| `QUARTO_LOG_FORMAT` | - `QUARTO_LOG_LEVEL` is the same as using `--log-level` at command line. It is used to set the max level that will be log. Possible values are `DEBUG`, `INFO`(default), `WARNING`, and `ERROR`. | -| | | -| | - `QUARTO_LOG_FORMAT` is the same as using `--log-format` at command line. It is used to set the format for the log. Possible values are `plain` (default) and `json-stream`. | -+---------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +::: list-table + +* - Variable + - Description + +* - `QUARTO_R` + - Explicit path to the version of `Rscript` to be used by the `knitr` engine and `quarto run *.R` command. + +* - `QUARTO_PYTHON` + - Explicit path to the version of `python` to be used by the `jupyter` engine and `quarto run *.py` command. + +* - `QUARTO_JULIA` + - Explicit path to the version of `julia` to be used by the `julia` engine. + +* - `QUARTO_VERSION_REQUIREMENT` + - A [`semver`](https://semver.org/) string describing the Quarto version requested by the environment. + If this check fails, Quarto will not run. + +* - `QUARTO_KNITR_RSCRIPT_ARGS` + - Comma separated list of command line argument to pass to `Rscript` started by Quarto when rendering with `knitr` engine, e.g. + + ``` + QUARTO_KNITR_RSCRIPT_ARGS="--no-init-file,--max-connections=258" + ``` + +* - `QUARTO_TEXLIVE_BINPATH` + - Explicit path to the TeX Live binaries to be passed to `tlmgr option sys_bin` used when setting `tlmgr` and related to `PATH` using `tlmgr add path` . By default, Quarto looks in known places. + +* - `QUARTO_CHROMIUM` + - Explicit path to binary to use for chrome headless. Quarto uses [Chrome Devtools Protocol](https://chromedevtools.github.io/devtools-protocol/) to do screenshot of HTML diagrams for PDF insertion. The binary must be compatible with this protocol. (e.g. Chrome, Chromium, Chrome Headless Shell, Edge, ...) + +* - `QUARTO_CHROMIUM_HEADLESS_MODE` + - Used for adaption of the `--headless` mode used with `QUARTO_CHROMIUM` binary. Set to `"none"` for `--headless` , or to `"old"` or `"new"` to pass as argument, e.g. `--headless=` . Quarto 1.6 sets `"old"` as default, which works from Chrome 112 to 131. Starting Quarto 1.7.13, `"none"` is the default as [Chrome 132 removed old headless mode](https://developer.chrome.com/blog/removing-headless-old-from-chrome). + +* - `QUARTO_LOG` + + `QUARTO_LOG_LEVEL` + + `QUARTO_LOG_FORMAT` + + - These variables control the logging behavior: + + `QUARTO_LOG` is the same as using `--log` at command line. It is used to set the path to the log file. + + `QUARTO_LOG_LEVEL` is the same as using `--log-level` at command line. It is used to set the max level that will be log. Possible values are `DEBUG`, `INFO`(default), `WARNING`, and `ERROR`. + + `QUARTO_LOG_FORMAT` is the same as using `--log-format` at command line. It is used to set the format for the log. Possible values are `plain` (default) and `json-stream`. + +::: ## Variables Quarto sets @@ -72,18 +92,34 @@ ENV["QUARTO_DOCUMENT_PATH"] ``` ::: -+--------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Variable | Description | -+============================================+=================================================================================================================================================================================================+ -| `QUARTO_PROJECT_ROOT` | Root of the project, or the directory of the file if not in project mode | -+--------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_DOCUMENT_PATH` | Directory of the document being rendered | -+--------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_DOCUMENT_FILE` | Name of the file being rendered | -+--------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_PROFILE` | Profile used, e.g `QUARTO_PROFILE=advanced,production` for `quarto render --profile advanced,production` | -+--------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_FIG_WIDTH` and `QUARTO_FIG_HEIGHT` | Values for `fig-width` and `fig-height` as set in the document metadata | -+--------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `QUARTO_RUN_NO_NETWORK` | When `true`, Quarto project scripts written in TypeScript won't be allowed to use the network to download sources. In this setting, those scripts will not have access to the standard library. | -+--------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ \ No newline at end of file +::: list-table + +* - Variable + - Description + +* - `QUARTO_PROJECT_ROOT` + - Root of the project, or the directory of the file if not in project mode + +* - `QUARTO_DOCUMENT_PATH` + - Directory of the document being rendered + +* - `QUARTO_DOCUMENT_FILE` + - Name of the file being rendered + +* - `QUARTO_PROFILE` + - Profile used, e.g `QUARTO_PROFILE=advanced,production` for `quarto render --profile advanced,production` + +* - `QUARTO_FIG_WIDTH` and `QUARTO_FIG_HEIGHT` + - Values for `fig-width` and `fig-height` as set in the document metadata + +* - `QUARTO_RUN_NO_NETWORK` + - When `true`, Quarto project scripts written in TypeScript won't be allowed to use the network to download sources. + In this setting, those scripts will not have access to the standard library. + +* - `QUARTO_EXECUTE_INFO` + - Path to a file on disk with a JSON object encoding information about the execution environment for the document being rendered. + +::: + +## `QUARTO_EXECUTE_INFO` + From c4d9baa6b13c7793fd734800dbf3ea8337655e2e Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Wed, 20 Aug 2025 09:40:47 -0500 Subject: [PATCH 2/2] whitespace cleanup --- docs/advanced/environment-vars.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/advanced/environment-vars.qmd b/docs/advanced/environment-vars.qmd index 2fcb03c200..4df29de845 100644 --- a/docs/advanced/environment-vars.qmd +++ b/docs/advanced/environment-vars.qmd @@ -36,7 +36,7 @@ You can read about other ways to set environment variables in Quarto Projects in If this check fails, Quarto will not run. * - `QUARTO_KNITR_RSCRIPT_ARGS` - - Comma separated list of command line argument to pass to `Rscript` started by Quarto when rendering with `knitr` engine, e.g. + - Comma separated list of command line argument to pass to `Rscript` started by Quarto when rendering with `knitr` engine, e.g. ``` QUARTO_KNITR_RSCRIPT_ARGS="--no-init-file,--max-connections=258"