From c936d9c5b68e85089ba6a5bcab6b453be0d4fa82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Sat, 1 Aug 2026 18:54:45 +0200 Subject: [PATCH] fix: honour a boolean option written as a bare YAML false The shared metadata accessor guarded on truthiness, so `auto-filename: false` and its siblings were read as absent and the default applied in their place. Only the quoted string worked, which the site itself had adopted. Also corrects the reference and the examples page. They said a derived filename frames nothing in HTML, which is wrong: Quarto builds its wrapper before this filter runs, so the block carries a marker class instead and the injected script builds the window at page load, as it does for the rest of the HTML chrome. Checked in a browser rather than in the static output. --- CHANGELOG.md | 6 +++ _extensions/code-window/_modules/metadata.lua | 44 ++++++++++++++++++- docs/_quarto.yml | 5 +-- docs/examples.qmd | 6 +-- docs/reference.qmd | 12 ++--- 5 files changed, 59 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75b80a7..caab051 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,14 @@ ## Unreleased +### Bug Fixes + +- fix: Honour a boolean option written as a bare YAML `false`, such as `auto-filename: false`, `enabled: false`, or `lines-label: false`. The value was read as an absent option, so the default applied instead and only the quoted string worked. + ### Documentation +- docs: Correct the reference and the examples page, which said a derived filename frames nothing in HTML. It frames the block through the injected script, as the rest of the HTML chrome does. + - docs: Add a documentation website under `docs/`, built on the `atelier` project type and published to , framed by the extension itself. - docs: Record that the filter claims code blocks at `pre-quarto`, which prevents `typst-render` from seeing its own `{typst}` blocks and double-decorates alongside `language-cell-decorator`. - docs: Trim `README.md` to a landing page pointing at the website. diff --git a/_extensions/code-window/_modules/metadata.lua b/_extensions/code-window/_modules/metadata.lua index bab2087..2e1b6d5 100644 --- a/_extensions/code-window/_modules/metadata.lua +++ b/_extensions/code-window/_modules/metadata.lua @@ -42,8 +42,12 @@ end --- @param key string The metadata key to retrieve --- @return string|nil The metadata value as a string, or nil if not found --- @usage local repo = M.get_metadata_value(meta, "github", "repository-name") +--- @note A boolean `false` is a value, not an absence, so the test is against +--- `nil` rather than truthiness. Stringifying it yields "false", which is what +--- a caller comparing against the string form already expects. function M.get_metadata_value(meta, extension_name, key) - if meta['extensions'] and meta['extensions'][extension_name] and meta['extensions'][extension_name][key] then + if meta['extensions'] and meta['extensions'][extension_name] + and meta['extensions'][extension_name][key] ~= nil then return str.stringify(meta['extensions'][extension_name][key]) end return nil @@ -175,6 +179,44 @@ function M.get_options(spec) return result end +-- ============================================================================ +-- PROJECT METADATA UTILITIES +-- ============================================================================ + +--- Get repo-url from Quarto project metadata via QUARTO_EXECUTE_INFO. +--- Reads the JSON file pointed to by the QUARTO_EXECUTE_INFO environment variable +--- and extracts repo-url from website or book metadata. +--- @return string|nil The repo-url value, or nil if not available +function M.get_project_repo_url() + local path = os.getenv("QUARTO_EXECUTE_INFO") + if not path then return nil end + + local file = io.open(path, "r") + if not file then return nil end + + local content = file:read("*a") + file:close() + + if str.is_empty(content) then return nil end + + local ok, info = pcall(quarto.json.decode, content) + if not ok or not info then return nil end + + local format_meta = info["format"] and info["format"]["metadata"] + if not format_meta then return nil end + + -- Try website.repo-url first, then book.repo-url + local repo_url = nil + if format_meta["website"] and format_meta["website"]["repo-url"] then + repo_url = format_meta["website"]["repo-url"] + elseif format_meta["book"] and format_meta["book"]["repo-url"] then + repo_url = format_meta["book"]["repo-url"] + end + + if str.is_empty(repo_url) then return nil end + return repo_url +end + -- ============================================================================ -- MODULE EXPORT -- ============================================================================ diff --git a/docs/_quarto.yml b/docs/_quarto.yml index b586862..6068cbf 100644 --- a/docs/_quarto.yml +++ b/docs/_quarto.yml @@ -124,7 +124,4 @@ extensions: style: "macos" # Blocks here are configuration to copy rather than files to save, so a # filename derived from the language would only add noise. - # - # Quoted deliberately. A bare `false` is read as unset and reverts to the - # default, because the option lookup treats a Lua `false` as absent. - auto-filename: "false" + auto-filename: false diff --git a/docs/examples.qmd b/docs/examples.qmd index a6d4afb..06cba1a 100644 --- a/docs/examples.qmd +++ b/docs/examples.qmd @@ -11,7 +11,7 @@ The site sets: extensions: code-window: style: macos - auto-filename: "false" + auto-filename: false ``` ## Naming the window @@ -30,8 +30,8 @@ project: type: website ``` -A block with no `filename` is left alone in HTML, whatever `auto-filename` says. -Under Typst that same block is framed and labelled with its language. +A block with no `filename` is left alone here, because this site turns `auto-filename` off. +With it on, that same block is framed and labelled with its language, in HTML and under Typst alike. ## The three styles diff --git a/docs/reference.qmd b/docs/reference.qmd index 4223ee5..1214f61 100644 --- a/docs/reference.qmd +++ b/docs/reference.qmd @@ -54,10 +54,11 @@ extensions: Quarto's own `filename` attribute names the window. -::: {.callout-important} -In HTML output only a block with an author-set `filename` is framed. -Quarto builds the wrapper the chrome attaches to before this filter runs, so a filename derived by `auto-filename` arrives too late: the block keeps its language as a `data-filename` attribute and renders without a window. -Typst is unaffected, and frames derived and author-set filenames alike. +::: {.callout-note} +A derived filename is applied later than an author-set one. +Quarto builds its own wrapper before this filter runs, so a block with no `filename` leaves the filter carrying a `data-filename` attribute and a marker class instead, and the injected script builds the wrapper at page load. +The result is the same window; it needs JavaScript, as the rest of the HTML chrome does. +Typst frames derived and author-set filenames alike, without a script. ::: ## How the chrome is applied @@ -104,5 +105,4 @@ Two extensions in this family are affected: [`typst-render`](https://m.canouil.d - HTML formats and Typst. Elsewhere the code block is left as it is. - Folding is HTML only; Typst has no equivalent. - The HTML chrome is built by script at page load, so a reader with JavaScript off sees plain code blocks. -- `auto-filename` frames nothing in HTML; give a block an explicit `filename` there. -- A boolean option written as `false` under `extensions.code-window` is read as unset and reverts to its default. Write `"false"` in quotes until this is fixed. +- A block with a derived filename is framed by the script rather than by the wrapper Quarto builds, so it needs JavaScript in HTML like the rest of the chrome.