From 1e2fc5561e75aeb9c128f0a59efc2ff4b497b58a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 21 Sep 2026 00:54:45 +0200 Subject: [PATCH 1/7] fix: stop relabelling a language when the filter is off The pass that labels a block whose language Pandoc cannot highlight ran whether the extension was on or off, so a disabled filter handed the author back the "default" class in place of their own language. Nothing read the label in that state, because only the derived filename does and that never runs with the filter off. The cell-output pass loses the case it only had to serve that one, and the examples page no longer says a disabled filter relabels a block. --- _extensions/code-window/main.lua | 28 +++++++++++++++++++++++----- docs/examples.qmd | 5 +++-- tests/fixtures/filter-disabled.qmd | 16 ++++++++++++++++ tests/run.sh | 14 ++++++++++++++ 4 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 tests/fixtures/filter-disabled.qmd diff --git a/_extensions/code-window/main.lua b/_extensions/code-window/main.lua index 1f9570f..1dc7f5b 100644 --- a/_extensions/code-window/main.lua +++ b/_extensions/code-window/main.lua @@ -43,20 +43,38 @@ code_window.set_checker(checker) --- Mark the code blocks that hold the output of an executed cell, so the later --- passes leave them as Quarto wrote them. Reads the configuration once and ---- walks the document only when the output has to stay unframed. The language ---- pass runs whether the extension is on or off, so the mark is set in both ---- cases; the window passes remove it either way. +--- walks the document only when there is a pass to hold back: the extension is +--- on, and the output has to stay unframed. The window passes remove the mark. --- @param doc pandoc.Pandoc --- @return pandoc.Pandoc|nil Marked document, or nil when the pass is skipped local function mark_cell_output(doc) local config = code_window.CONFIG() - if not config or (config.enabled and config.cell_output) then + if not config or not config.enabled or config.cell_output then return nil end doc.blocks = doc.blocks:walk({ Div = cell_output.Div }) return doc end +-- ============================================================================ +-- LANGUAGE +-- ============================================================================ + +--- Normalise a block's language only where something reads the result. +--- The pass labels a block whose language Pandoc cannot highlight, and the +--- derived filename is the only reader of that label. That reader never runs +--- with the extension off, so the pass would rewrite a class for nobody and +--- hand the author back a language they did not write. +--- @param block pandoc.CodeBlock +--- @return pandoc.CodeBlock|nil Relabelled block, or nil when the pass is skipped +local function normalise_language(block) + local config = code_window.CONFIG() + if not config or not config.enabled then + return nil + end + return language.CodeBlock(block) +end + -- ============================================================================ -- SKYLIGHTING HOT-FIX -- ============================================================================ @@ -88,7 +106,7 @@ end local filters = { { Meta = code_window.Meta }, { Pandoc = mark_cell_output }, - { CodeBlock = language.CodeBlock }, + { CodeBlock = normalise_language }, { Pandoc = code_window.Pandoc }, { CodeBlock = code_window.CodeBlock }, } diff --git a/docs/examples.qmd b/docs/examples.qmd index 4e14cbe..ebb5c37 100644 --- a/docs/examples.qmd +++ b/docs/examples.qmd @@ -165,8 +165,9 @@ It then adds no chrome to any block, and loads neither the stylesheet nor the sc So `code-window-enabled="true"` on a block cannot switch the chrome back on. `code-window-enabled` can only turn a block off, never on. -Switching the filter off does not put the document back exactly as Quarto would write it. -The pass that normalises a block's language runs either way, so a block with no language still gains the `default` class. +With the filter off, every code block keeps the classes Quarto gives it. +A block whose language Pandoc cannot highlight keeps that language, and a block with no language gains none. +The attributes the filter reads stay on the block too, and reach the HTML as `data-code-window-*`, which is what a document without the extension also produces. A block that names a file still gets the plain title bar Quarto builds for it. That bar carries no traffic lights, no fold, and no line chip. diff --git a/tests/fixtures/filter-disabled.qmd b/tests/fixtures/filter-disabled.qmd new file mode 100644 index 0000000..cc8693e --- /dev/null +++ b/tests/fixtures/filter-disabled.qmd @@ -0,0 +1,16 @@ +--- +title: "The filter turned off" +filters: + - code-window +extensions: + code-window: + enabled: false +--- + +A filter that is off leaves every block as Quarto writes it. The block below +keeps the language its author gave it, even though Pandoc cannot highlight it +and the filter would relabel it when it is on. + +```foo +x = 1 +``` diff --git a/tests/run.sh b/tests/run.sh index 0b5c929..17178f2 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -178,6 +178,20 @@ else report pass "unsupported-format: the internal label stays out of the output" fi +# ============================================================================ +# A filter that draws no chrome leaves a block's language alone +# ============================================================================ + +# The pass that relabels a language serves the derived filename, and nothing +# derives a filename with the filter off. +render filter-disabled html +if block_classes "${work_dir}/filter-disabled.html" | grep -q 'foo'; then + report pass "filter-disabled: the block keeps its own language" +else + report fail "filter-disabled: the block keeps its own language" \ + "a foo class on the block" +fi + # ============================================================================ printf '\n%s passed, %s failed\n' "${passed}" "${failed}" From 3d4f59421c973d9faf55c0bd5ce6b3e5cdee9f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 21 Sep 2026 00:55:51 +0200 Subject: [PATCH 2/7] fix: relabel a language only where the chrome is drawn With the filter on and the output format neither HTML nor Typst, the pass still rewrote the class, and again nothing read the result: the derived filename is the only reader, and it runs for those two formats alone. A render to markdown printed "``` default" where the source said "```foo". code-window.lua exposes the current format, as it already exposes the configuration, so the guard can read it. --- _extensions/code-window/code-window.lua | 1 + _extensions/code-window/main.lua | 12 +++++++++--- tests/run.sh | 8 ++++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/_extensions/code-window/code-window.lua b/_extensions/code-window/code-window.lua index 851f6a2..1862217 100644 --- a/_extensions/code-window/code-window.lua +++ b/_extensions/code-window/code-window.lua @@ -1308,4 +1308,5 @@ return { Pandoc = Pandoc, CodeBlock = CodeBlock, CONFIG = function() return CONFIG end, + FORMAT = function() return CURRENT_FORMAT end, } diff --git a/_extensions/code-window/main.lua b/_extensions/code-window/main.lua index 1dc7f5b..f054220 100644 --- a/_extensions/code-window/main.lua +++ b/_extensions/code-window/main.lua @@ -62,9 +62,11 @@ end --- Normalise a block's language only where something reads the result. --- The pass labels a block whose language Pandoc cannot highlight, and the ---- derived filename is the only reader of that label. That reader never runs ---- with the extension off, so the pass would rewrite a class for nobody and ---- hand the author back a language they did not write. +--- derived filename is the only reader of that label. That reader runs for +--- html and typst, and only while the extension is on, so anywhere else the +--- pass would rewrite a class for nobody and hand the author back a language +--- they did not write. A render to markdown printed the "default" class in +--- place of the author's own language for exactly that reason. --- @param block pandoc.CodeBlock --- @return pandoc.CodeBlock|nil Relabelled block, or nil when the pass is skipped local function normalise_language(block) @@ -72,6 +74,10 @@ local function normalise_language(block) if not config or not config.enabled then return nil end + local format = code_window.FORMAT() + if format ~= 'html' and format ~= 'typst' then + return nil + end return language.CodeBlock(block) end diff --git a/tests/run.sh b/tests/run.sh index 17178f2..33b13d1 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -192,6 +192,14 @@ else "a foo class on the block" fi +# The same pass serves no reader on a format that gets no chrome either. +if grep -q '^``` foo' "${work_dir}/unsupported-format.md"; then + report pass "unsupported-format: the block keeps its own language" +else + report fail "unsupported-format: the block keeps its own language" \ + "a fence reading \`\`\` foo in unsupported-format.md" +fi + # ============================================================================ printf '\n%s passed, %s failed\n' "${passed}" "${failed}" From e479b95daf5d12f1e5ff8c4ec3da82ea717fae56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 21 Sep 2026 01:00:54 +0200 Subject: [PATCH 3/7] refactor: ask one question about whether chrome is drawn Three places asked some part of "is this render drawing chrome": the options check compared the two formats inline, and the two passes that serve the chrome each carried their own copy of the configuration test. draws_chrome answers it once, built on acts_on_format, which holds the format union the file used to spell out. The cell-output pass gains the format half it was missing, so a render that draws no chrome no longer walks the whole document to set a mark nothing reads. --- _extensions/code-window/code-window.lua | 25 +++++++++++++++++++---- _extensions/code-window/main.lua | 27 ++++++++++--------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/_extensions/code-window/code-window.lua b/_extensions/code-window/code-window.lua index 1862217..997ec78 100644 --- a/_extensions/code-window/code-window.lua +++ b/_extensions/code-window/code-window.lua @@ -72,6 +72,23 @@ local ANNOTATION_BLOCK_COUNTER = 0 -- CELL OUTPUT -- ============================================================================ +--- Check whether the extension acts on the format being rendered. It draws +--- chrome for html, which covers Reveal.js, and for typst, and leaves every +--- other format as Quarto writes it. +--- @return boolean +local function acts_on_format() + return CURRENT_FORMAT == 'html' or CURRENT_FORMAT == 'typst' +end + +--- Check whether this render draws chrome at all: the extension is on, and the +--- format is one it acts on. Every pass that exists only to serve the chrome +--- asks this before it does any work, so none of them has to carry its own +--- copy of the two conditions. +--- @return boolean +local function draws_chrome() + return CONFIG ~= nil and CONFIG.enabled and acts_on_format() +end + --- Check whether a block holds the output of an executed cell that the engine --- did not name. Such a block keeps the shape Quarto gave it. --- @param block pandoc.CodeBlock Code block element @@ -749,9 +766,9 @@ function Meta(meta) -- This is the pass that reads the configuration, so the check runs here, -- before the first option is read. An option the check rejects is still -- read below, because the report says what the extension cannot use and the - -- document renders either way. The extension only acts on html and typst, - -- so the check is gated on the same union those formats already use below. - if CURRENT_FORMAT == 'html' or CURRENT_FORMAT == 'typst' then + -- document renders either way. Only a format the extension acts on reports, + -- because nothing it could say applies anywhere else. + if acts_on_format() then checker:options(meta) end @@ -1308,5 +1325,5 @@ return { Pandoc = Pandoc, CodeBlock = CodeBlock, CONFIG = function() return CONFIG end, - FORMAT = function() return CURRENT_FORMAT end, + draws_chrome = draws_chrome, } diff --git a/_extensions/code-window/main.lua b/_extensions/code-window/main.lua index f054220..b42c62b 100644 --- a/_extensions/code-window/main.lua +++ b/_extensions/code-window/main.lua @@ -42,14 +42,16 @@ code_window.set_checker(checker) -- ============================================================================ --- Mark the code blocks that hold the output of an executed cell, so the later ---- passes leave them as Quarto wrote them. Reads the configuration once and ---- walks the document only when there is a pass to hold back: the extension is ---- on, and the output has to stay unframed. The window passes remove the mark. +--- passes leave them as Quarto wrote them. Walks the document only when there +--- is a pass to hold back, which means this render draws chrome and the output +--- has to stay unframed. Only the two window paths read the mark, so a render +--- that draws no chrome would walk the whole document to set an attribute +--- nothing goes on to read. draws_chrome answers false when there is no +--- configuration yet, so the second test below always has one in hand. --- @param doc pandoc.Pandoc --- @return pandoc.Pandoc|nil Marked document, or nil when the pass is skipped local function mark_cell_output(doc) - local config = code_window.CONFIG() - if not config or not config.enabled or config.cell_output then + if not code_window.draws_chrome() or code_window.CONFIG().cell_output then return nil end doc.blocks = doc.blocks:walk({ Div = cell_output.Div }) @@ -62,20 +64,13 @@ end --- Normalise a block's language only where something reads the result. --- The pass labels a block whose language Pandoc cannot highlight, and the ---- derived filename is the only reader of that label. That reader runs for ---- html and typst, and only while the extension is on, so anywhere else the ---- pass would rewrite a class for nobody and hand the author back a language ---- they did not write. A render to markdown printed the "default" class in ---- place of the author's own language for exactly that reason. +--- derived filename is the only reader of that label. Nothing derives a +--- filename in a render that draws no chrome, so the pass would rewrite a +--- class for nobody and hand the author back a language they did not write. --- @param block pandoc.CodeBlock --- @return pandoc.CodeBlock|nil Relabelled block, or nil when the pass is skipped local function normalise_language(block) - local config = code_window.CONFIG() - if not config or not config.enabled then - return nil - end - local format = code_window.FORMAT() - if format ~= 'html' and format ~= 'typst' then + if not code_window.draws_chrome() then return nil end return language.CodeBlock(block) From b0c5e2ca1abfb1c54e939142be7bb6c4fdc79bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 21 Sep 2026 01:05:27 +0200 Subject: [PATCH 4/7] test: check the pass still runs where the chrome is drawn The two new tests both asserted that the pass does not run, so a gate that closed on a render it should let through would have left the suite green. A fixture with the filter on now asserts the class becomes "default", the block is framed, and the title bar keeps the language the author wrote. Forcing the gate shut turns it red, along with the cell-output test. The fixture prose and the comment beside the older markdown test described the label as written and then stripped, which is no longer what happens. --- tests/fixtures/language-relabelled.qmd | 13 +++++++++++++ tests/fixtures/unsupported-format.qmd | 6 +++--- tests/run.sh | 19 +++++++++++++++++-- 3 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 tests/fixtures/language-relabelled.qmd diff --git a/tests/fixtures/language-relabelled.qmd b/tests/fixtures/language-relabelled.qmd new file mode 100644 index 0000000..84d77a6 --- /dev/null +++ b/tests/fixtures/language-relabelled.qmd @@ -0,0 +1,13 @@ +--- +title: "A language Pandoc cannot highlight" +filters: + - code-window +--- + +The filter labels a block whose language Pandoc cannot highlight, and frames it +like any other. The label keeps the language the author wrote, and the class +becomes `default`, which is the one Pandoc has a theme for. + +```foo +x = 1 +``` diff --git a/tests/fixtures/unsupported-format.qmd b/tests/fixtures/unsupported-format.qmd index e5e1b72..5c7b9a7 100644 --- a/tests/fixtures/unsupported-format.qmd +++ b/tests/fixtures/unsupported-format.qmd @@ -4,9 +4,9 @@ filters: - code-window --- -The filter draws no chrome outside HTML and Typst. The language module still -labels the block below, and that label is the filter's own, so it does not -reach the output. +The filter draws no chrome outside HTML and Typst. Nothing reads a label here, +so the block below keeps the language its author wrote, and the filter's own +label for it is never written at all. ```foo x = 1 diff --git a/tests/run.sh b/tests/run.sh index 33b13d1..f853c79 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -168,8 +168,9 @@ for fixture in disabled-block lines-label-off; do fi done -# The label the language module writes is the filter's own, so a format that -# draws no chrome drops it rather than printing it. +# The label is the filter's own name for a block, and no reader of it exists on +# a format that draws no chrome, so neither the label nor the pass that writes +# it reaches the output. render unsupported-format markdown if grep -q 'code-window-auto-label' "${work_dir}/unsupported-format.md"; then report fail "unsupported-format: the internal label stays out of the output" \ @@ -200,6 +201,20 @@ else "a fence reading \`\`\` foo in unsupported-format.md" fi +# Where the chrome is drawn, the pass has work to do: the class becomes the one +# Pandoc has a theme for, the block is framed, and the title bar keeps the +# language the author wrote. Without this, the two tests above would stay green +# if the gate ever closed on a render it should let through. +render language-relabelled html +if block_classes "${work_dir}/language-relabelled.html" | grep -q 'default' && + block_classes "${work_dir}/language-relabelled.html" | grep -q 'cw-auto' && + block_wrappers "${work_dir}/language-relabelled.html" | grep -q 'data-filename="foo"'; then + report pass "language-relabelled: the block is relabelled and framed" +else + report fail "language-relabelled: the block is relabelled and framed" \ + "a default class, a cw-auto class, and data-filename=\"foo\" on the block" +fi + # ============================================================================ printf '\n%s passed, %s failed\n' "${passed}" "${failed}" From 63947dc7c8f9e94637691a786c3dcb1027d5f929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 21 Sep 2026 01:06:06 +0200 Subject: [PATCH 5/7] docs: record the language relabelling fix in the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4db0b6d..5b7112d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Bug Fixes +- fix: Keep a block's own language where the filter draws no chrome, which means the filter is off, or the output format is neither HTML nor Typst. The block was relabelled as `default` before, and the language the author wrote was lost. (#66) - fix: Keep inline code in a Typst document as a code element, so Pandoc writes the syntax highlighting definitions for it. A document with inline code and no code block failed to compile before. (#65) - fix: Remove the code-window attributes from a block that sets code-window-enabled="false", and from a block that sets code-window-lines when lines-label is off. They reached the HTML output as data-code-window-* attributes before. (#63) - fix: Remove the extension's own label attribute when the output format gets no window chrome, so a writer that keeps attributes no longer prints it. (#63) From 5021f65544325f63882486786df94fe8a5bd32dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 21 Sep 2026 01:10:44 +0200 Subject: [PATCH 6/7] docs: say what the gate answers, and what it does not --- _extensions/code-window/main.lua | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/_extensions/code-window/main.lua b/_extensions/code-window/main.lua index b42c62b..3ad4a60 100644 --- a/_extensions/code-window/main.lua +++ b/_extensions/code-window/main.lua @@ -44,7 +44,8 @@ code_window.set_checker(checker) --- Mark the code blocks that hold the output of an executed cell, so the later --- passes leave them as Quarto wrote them. Walks the document only when there --- is a pass to hold back, which means this render draws chrome and the output ---- has to stay unframed. Only the two window paths read the mark, so a render +--- has to stay unframed. The readers of the mark are the language pass below +--- and the two window paths, and all three ask draws_chrome first, so a render --- that draws no chrome would walk the whole document to set an attribute --- nothing goes on to read. draws_chrome answers false when there is no --- configuration yet, so the second test below always has one in hand. @@ -62,11 +63,17 @@ end -- LANGUAGE -- ============================================================================ ---- Normalise a block's language only where something reads the result. +--- Normalise a block's language where the render draws chrome. --- The pass labels a block whose language Pandoc cannot highlight, and the --- derived filename is the only reader of that label. Nothing derives a --- filename in a render that draws no chrome, so the pass would rewrite a --- class for nobody and hand the author back a language they did not write. +--- The question this asks is about the render, not about one block. A block +--- can still draw no chrome inside a render that does, through +--- "auto-filename: false", "code-window-no-auto-filename" or +--- "code-window-enabled", and its class is rewritten with no reader either. +--- Answering that per block means relabelling where the name is built, which +--- is a change to the two window paths rather than to this gate. --- @param block pandoc.CodeBlock --- @return pandoc.CodeBlock|nil Relabelled block, or nil when the pass is skipped local function normalise_language(block) From 8debb36406e6cc3b67596b4cac5e121e5f4ec0a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 21 Sep 2026 01:19:27 +0200 Subject: [PATCH 7/7] fix: relabel only where a name is actually derived "auto-filename" is the reader itself: with no derived name to build, both window paths return before they read the label, so the pass rewrote a class for nobody there too. The documentation site sets that option off, and its own blocks were relabelled. Two fixtures cover the branch of the pass that inserts a class where a block had none, and the option itself. Two comments are corrected: the cell-output mark has a reader that only removes it, and the label the disabled branches clear is now only ever one a document wrote by hand. --- CHANGELOG.md | 2 +- _extensions/code-window/code-window.lua | 14 ++++++---- _extensions/code-window/main.lua | 27 +++++++++++-------- tests/fixtures/auto-filename-off.qmd | 16 +++++++++++ .../fixtures/filter-disabled-no-language.qmd | 13 +++++++++ tests/run.sh | 20 ++++++++++++++ 6 files changed, 75 insertions(+), 17 deletions(-) create mode 100644 tests/fixtures/auto-filename-off.qmd create mode 100644 tests/fixtures/filter-disabled-no-language.qmd diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b7112d..ecd6d3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ ### Bug Fixes -- fix: Keep a block's own language where the filter draws no chrome, which means the filter is off, or the output format is neither HTML nor Typst. The block was relabelled as `default` before, and the language the author wrote was lost. (#66) +- fix: Keep a block's own language where the filter derives no name for it, which means the filter is off, or `auto-filename` is off, or the output format is neither HTML nor Typst. The block was relabelled as `default` before, and the language the author wrote was lost. (#66) - fix: Keep inline code in a Typst document as a code element, so Pandoc writes the syntax highlighting definitions for it. A document with inline code and no code block failed to compile before. (#65) - fix: Remove the code-window attributes from a block that sets code-window-enabled="false", and from a block that sets code-window-lines when lines-label is off. They reached the HTML output as data-code-window-* attributes before. (#63) - fix: Remove the extension's own label attribute when the output format gets no window chrome, so a writer that keeps attributes no longer prints it. (#63) diff --git a/_extensions/code-window/code-window.lua b/_extensions/code-window/code-window.lua index 997ec78..ad65751 100644 --- a/_extensions/code-window/code-window.lua +++ b/_extensions/code-window/code-window.lua @@ -919,9 +919,12 @@ function CodeBlock(block) -- A filter that draws nothing changes nothing an author wrote. The -- attributes it would read stay on the block and reach the output, which is -- also what a document with this extension not installed produces. Only - -- code-window-auto-label goes, because the language module wrote it and no - -- author did. This holds for a filter switched off, below, and for a format - -- the extension does not act on, at the end of this function. + -- code-window-auto-label goes. The language module no longer writes it in + -- either of the two branches that clear it, since it asks the same question + -- before it runs, so what is left to clear is a document that wrote the + -- extension's own attribute name on a fence by hand. This holds for a filter + -- switched off, below, and for a format the extension does not act on, at + -- the end of this function. if not CURRENT_FORMAT or not CONFIG or not CONFIG.enabled then checker:attributes(block.attributes, 'CodeBlock') block.attributes['code-window-auto-label'] = nil @@ -938,8 +941,9 @@ function CodeBlock(block) -- Typst is finished by the Pandoc filter ahead of this one, which takes the -- attributes off there. Every other format draws no chrome, so the block - -- keeps what its author wrote and loses only the language module's label, - -- which a writer that preserves attributes would otherwise print. + -- keeps what its author wrote and loses only the label, which a writer that + -- preserves attributes would otherwise print. Nothing writes that label here + -- any more, for the reason given above, so this guards a hand-written one. block.attributes['code-window-auto-label'] = nil return block end diff --git a/_extensions/code-window/main.lua b/_extensions/code-window/main.lua index 3ad4a60..3f691a4 100644 --- a/_extensions/code-window/main.lua +++ b/_extensions/code-window/main.lua @@ -44,11 +44,13 @@ code_window.set_checker(checker) --- Mark the code blocks that hold the output of an executed cell, so the later --- passes leave them as Quarto wrote them. Walks the document only when there --- is a pass to hold back, which means this render draws chrome and the output ---- has to stay unframed. The readers of the mark are the language pass below ---- and the two window paths, and all three ask draws_chrome first, so a render ---- that draws no chrome would walk the whole document to set an attribute ---- nothing goes on to read. draws_chrome answers false when there is no ---- configuration yet, so the second test below always has one in hand. +--- has to stay unframed. Every reader that acts on the mark asks draws_chrome +--- first: the language pass below, and the two window paths. CodeBlock reads it +--- too, but only to remove it, and a mark that was never set costs nothing +--- there. So a render that draws no chrome would walk the whole document to set +--- an attribute nothing goes on to act on. draws_chrome answers false when +--- there is no configuration yet, so the second test below always has one in +--- hand. --- @param doc pandoc.Pandoc --- @return pandoc.Pandoc|nil Marked document, or nil when the pass is skipped local function mark_cell_output(doc) @@ -68,16 +70,19 @@ end --- derived filename is the only reader of that label. Nothing derives a --- filename in a render that draws no chrome, so the pass would rewrite a --- class for nobody and hand the author back a language they did not write. ---- The question this asks is about the render, not about one block. A block +--- "auto-filename" belongs in the same question, because it is the reader +--- itself: with no derived name to build, both window paths return before they +--- read the label, so the pass would rewrite a class for nobody again. +--- Every question this asks is about the render, not about one block. A block --- can still draw no chrome inside a render that does, through ---- "auto-filename: false", "code-window-no-auto-filename" or ---- "code-window-enabled", and its class is rewritten with no reader either. ---- Answering that per block means relabelling where the name is built, which ---- is a change to the two window paths rather than to this gate. +--- "code-window-no-auto-filename" or "code-window-enabled", and its class is +--- rewritten with no reader either. Answering that per block means relabelling +--- where the name is built, which is a change to the two window paths rather +--- than to this gate. --- @param block pandoc.CodeBlock --- @return pandoc.CodeBlock|nil Relabelled block, or nil when the pass is skipped local function normalise_language(block) - if not code_window.draws_chrome() then + if not code_window.draws_chrome() or not code_window.CONFIG().auto_filename then return nil end return language.CodeBlock(block) diff --git a/tests/fixtures/auto-filename-off.qmd b/tests/fixtures/auto-filename-off.qmd new file mode 100644 index 0000000..56bbd28 --- /dev/null +++ b/tests/fixtures/auto-filename-off.qmd @@ -0,0 +1,16 @@ +--- +title: "No derived names anywhere" +filters: + - code-window +extensions: + code-window: + auto-filename: false +--- + +With no derived name to build, nothing reads the label, so the block below keeps +the language its author wrote even though the filter is on and the format gets +chrome. + +```foo +x = 1 +``` diff --git a/tests/fixtures/filter-disabled-no-language.qmd b/tests/fixtures/filter-disabled-no-language.qmd new file mode 100644 index 0000000..4f9e3e6 --- /dev/null +++ b/tests/fixtures/filter-disabled-no-language.qmd @@ -0,0 +1,13 @@ +--- +title: "The filter turned off, and a block with no language" +filters: + - code-window +extensions: + code-window: + enabled: false +--- + +A block with no language gains none while the filter is off. The block below is +indented rather than fenced, which gives the same code block with no language. + + x = 1 diff --git a/tests/run.sh b/tests/run.sh index f853c79..31e0e19 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -193,6 +193,26 @@ else "a foo class on the block" fi +# The other branch of the same pass inserts a class where the block had none, +# which turns a bare block into a highlighted one. +render filter-disabled-no-language html +if block_classes "${work_dir}/filter-disabled-no-language.html" | grep -q 'default'; then + report fail "filter-disabled-no-language: the block gains no class" \ + "no default class on the block" +else + report pass "filter-disabled-no-language: the block gains no class" +fi + +# A render with no derived name to build reads no label either, whatever the +# format, so the pass has no reader there. +render auto-filename-off html +if block_classes "${work_dir}/auto-filename-off.html" | grep -q 'foo'; then + report pass "auto-filename-off: the block keeps its own language" +else + report fail "auto-filename-off: the block keeps its own language" \ + "a foo class on the block" +fi + # The same pass serves no reader on a format that gets no chrome either. if grep -q '^``` foo' "${work_dir}/unsupported-format.md"; then report pass "unsupported-format: the block keeps its own language"