From 6db3bf095409562169acf75178944bbc4f11dd6d 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 11:17:43 +0200 Subject: [PATCH 1/4] refactor: let the schema decide an option's default The schema declares a default for each of the seven options, and a table in the Lua declared the same seven again. The check already answers what the schema says, and that answer was dropped, so the literals decided while the schema was what the editor showed. Changing a default in _schema.yml alone did nothing. The check's answer is kept now. The table stays as a fallback for the two cases the schema cannot answer: a format the extension does not act on, where the check never runs, and a schema that could not be read, which is a state the extension renders through. Three fixtures cover it: the wrapper name comes from the schema, follows a change made there alone, and falls back when the file is gone. The three hotfix defaults are still declared twice. They are nested in the schema and read through a different path, so they are left alone here. --- _extensions/code-window/code-window.lua | 26 +++++++++++++-- tests/fixtures/wrapper-default.qmd | 16 ++++++++++ tests/run.sh | 42 +++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 tests/fixtures/wrapper-default.qmd diff --git a/_extensions/code-window/code-window.lua b/_extensions/code-window/code-window.lua index 350cfd9..c886892 100644 --- a/_extensions/code-window/code-window.lua +++ b/_extensions/code-window/code-window.lua @@ -40,7 +40,12 @@ local VALID_STYLES = { ['default'] = true, ['macos'] = true, ['windows'] = true --- schema declares and the internal label the language module writes alike. local ATTRIBUTE_PREFIX = 'code-window-' -local DEFAULTS = { +--- Defaults for the two cases where the schema cannot answer: a format the +--- extension does not act on, where the check never runs, and a schema that +--- could not be read, which is a state this extension renders through rather +--- than stopping for. Everywhere else _schema.yml decides, so these values +--- are a fallback and not a second place to change an option's default. +local FALLBACK_DEFAULTS = { ['enabled'] = 'true', ['auto-filename'] = 'true', ['style'] = 'macos', @@ -782,8 +787,23 @@ function Meta(meta) -- read below, because the report says what the extension cannot use and the -- document renders either way. Only a format the extension acts on reports, -- because nothing it could say applies anywhere else. + -- The check also answers what the schema declares each option defaults to, + -- so those values are kept rather than dropped and rebuilt by hand here. + -- They arrive typed, and every comparison below reads a string, so each one + -- goes through stringify_bool on the way into the table. + local schema_defaults = {} if acts_on_format() then - checker:options(meta) + schema_defaults = checker:options(meta) + end + + local defaults = {} + for key, fallback in pairs(FALLBACK_DEFAULTS) do + local declared = schema_defaults[key] + if declared == nil then + defaults[key] = fallback + else + defaults[key] = stringify_bool(declared) + end end local opts = meta_mod.get_options({ @@ -792,7 +812,7 @@ function Meta(meta) 'enabled', 'auto-filename', 'style', 'cell-output', 'wrapper', 'collapse', 'lines-label', }, meta = meta, - defaults = DEFAULTS, + defaults = defaults, }) -- checker:options (above) already reports an unrecognised "style" value in diff --git a/tests/fixtures/wrapper-default.qmd b/tests/fixtures/wrapper-default.qmd new file mode 100644 index 0000000..9598b66 --- /dev/null +++ b/tests/fixtures/wrapper-default.qmd @@ -0,0 +1,16 @@ +--- +title: "The Typst wrapper name" +filters: + - code-window +format: + typst: + keep-typ: true +--- + +The block below is framed, so the document calls the wrapper function by the +name the configuration gives it. Nothing here sets that name, so the default +decides, and the schema is where the default is written down. + +```{.python filename="a.py"} +x = 1 +``` diff --git a/tests/run.sh b/tests/run.sh index 31e0e19..29e8488 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -235,6 +235,48 @@ else "a default class, a cw-auto class, and data-filename=\"foo\" on the block" fi +# ============================================================================ +# The schema is where an option's default is written down +# ============================================================================ + +# The schema declares a default for every option, and so did a table in the +# Lua. Changing the schema alone has to change the render, or the two can +# disagree with nothing to say so. The wrapper name is the option under test +# because it reaches the Typst output word for word. +render wrapper-default typst +if grep -q '^#code-window(' "${work_dir}/wrapper-default.typ"; then + report pass "wrapper-default: the schema default names the wrapper" +else + report fail "wrapper-default: the schema default names the wrapper" \ + "a #code-window( call in wrapper-default.typ" +fi + +sed -i.aside 's/default: "code-window"/default: "my-window"/' \ + "${work_dir}/_extensions/code-window/_schema.yml" +render wrapper-default typst +mv "${work_dir}/_extensions/code-window/_schema.yml.aside" \ + "${work_dir}/_extensions/code-window/_schema.yml" + +if grep -q '^#my-window(' "${work_dir}/wrapper-default.typ"; then + report pass "wrapper-default: a default changed in the schema alone is followed" +else + report fail "wrapper-default: a default changed in the schema alone is followed" \ + "a #my-window( call in wrapper-default.typ" +fi + +# With no schema to read, the fallback in the Lua answers instead, and the +# document still renders rather than stopping. +mv "${work_dir}/_extensions/code-window/_schema.yml" "${work_dir}/schema.yml.aside" +render wrapper-default typst +mv "${work_dir}/schema.yml.aside" "${work_dir}/_extensions/code-window/_schema.yml" + +if grep -q '^#code-window(' "${work_dir}/wrapper-default.typ"; then + report pass "wrapper-default: the fallback answers when the schema cannot be read" +else + report fail "wrapper-default: the fallback answers when the schema cannot be read" \ + "a #code-window( call in wrapper-default.typ" +fi + # ============================================================================ printf '\n%s passed, %s failed\n' "${passed}" "${failed}" From 4a0577af9c67bb6b8ec40f220f40f66fa92e4147 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 11:21:12 +0200 Subject: [PATCH 2/4] refactor: read the schema first and let the fallback fill gaps --- _extensions/code-window/code-window.lua | 15 +++++++++++---- tests/run.sh | 7 +++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/_extensions/code-window/code-window.lua b/_extensions/code-window/code-window.lua index c886892..c329cf8 100644 --- a/_extensions/code-window/code-window.lua +++ b/_extensions/code-window/code-window.lua @@ -796,13 +796,20 @@ function Meta(meta) schema_defaults = checker:options(meta) end + -- The schema is read first and the fallback fills only what it leaves + -- unanswered, so an option added to _schema.yml and to the key list below + -- needs nothing here. Reading the fallback first would have made it the list + -- of options allowed to have a default at all, which is the coupling this + -- change exists to remove. The schema's answer also carries the nested + -- hotfix entry, which get_options never reads, since it reads the keys named + -- below and nothing else. local defaults = {} + for key, declared in pairs(schema_defaults) do + defaults[key] = stringify_bool(declared) + end for key, fallback in pairs(FALLBACK_DEFAULTS) do - local declared = schema_defaults[key] - if declared == nil then + if defaults[key] == nil then defaults[key] = fallback - else - defaults[key] = stringify_bool(declared) end end diff --git a/tests/run.sh b/tests/run.sh index 29e8488..cae2fc8 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -257,11 +257,14 @@ render wrapper-default typst mv "${work_dir}/_extensions/code-window/_schema.yml.aside" \ "${work_dir}/_extensions/code-window/_schema.yml" -if grep -q '^#my-window(' "${work_dir}/wrapper-default.typ"; then +# The old name has to be gone as well as the new one present, because a rename +# that missed a call site would leave both in the document. +if grep -q '^#my-window(' "${work_dir}/wrapper-default.typ" && + ! grep -q '^#code-window(' "${work_dir}/wrapper-default.typ"; then report pass "wrapper-default: a default changed in the schema alone is followed" else report fail "wrapper-default: a default changed in the schema alone is followed" \ - "a #my-window( call in wrapper-default.typ" + "a #my-window( call and no #code-window( call in wrapper-default.typ" fi # With no schema to read, the fallback in the Lua answers instead, and the From f83dc864130f0f7f3505c0788d5fa83423f7f867 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 11:26:44 +0200 Subject: [PATCH 3/4] docs: correct what the schema answers, and why all seven stay --- _extensions/code-window/code-window.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/_extensions/code-window/code-window.lua b/_extensions/code-window/code-window.lua index c329cf8..43a51f5 100644 --- a/_extensions/code-window/code-window.lua +++ b/_extensions/code-window/code-window.lua @@ -45,6 +45,12 @@ local ATTRIBUTE_PREFIX = 'code-window-' --- could not be read, which is a state this extension renders through rather --- than stopping for. Everywhere else _schema.yml decides, so these values --- are a fallback and not a second place to change an option's default. +--- All seven stay listed, because the second case has nothing else to read +--- from. Where the two disagree, the schema wins on html and typst, and a +--- format the extension does not act on reads "enabled" alone, which is the +--- one that chooses whether a block's attributes are checked at all. So keep +--- that one in step with the schema, and treat a difference in the other six +--- as a thing to correct rather than a thing that shows. local FALLBACK_DEFAULTS = { ['enabled'] = 'true', ['auto-filename'] = 'true', @@ -800,9 +806,9 @@ function Meta(meta) -- unanswered, so an option added to _schema.yml and to the key list below -- needs nothing here. Reading the fallback first would have made it the list -- of options allowed to have a default at all, which is the coupling this - -- change exists to remove. The schema's answer also carries the nested - -- hotfix entry, which get_options never reads, since it reads the keys named - -- below and nothing else. + -- change exists to remove. What arrives is one entry per option that + -- declares a default of its own, and get_options reads only the keys named + -- below. local defaults = {} for key, declared in pairs(schema_defaults) do defaults[key] = stringify_bool(declared) From 698505cc412ccb85c9bb73338d96f2eb188509b6 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 11:30:50 +0200 Subject: [PATCH 4/4] docs: name the hotfix table and the format the fallback serves --- _extensions/code-window/code-window.lua | 33 +++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/_extensions/code-window/code-window.lua b/_extensions/code-window/code-window.lua index 43a51f5..55586c0 100644 --- a/_extensions/code-window/code-window.lua +++ b/_extensions/code-window/code-window.lua @@ -43,14 +43,19 @@ local ATTRIBUTE_PREFIX = 'code-window-' --- Defaults for the two cases where the schema cannot answer: a format the --- extension does not act on, where the check never runs, and a schema that --- could not be read, which is a state this extension renders through rather ---- than stopping for. Everywhere else _schema.yml decides, so these values ---- are a fallback and not a second place to change an option's default. +--- than stopping for. Everywhere else _schema.yml decides these seven, so the +--- values below are a fallback and not a second place to change one of them. +--- The hotfix defaults are a different story, and are still kept by hand in +--- HOTFIX_DEFAULTS: they are nested in the schema and read on their own path, +--- so changing one in _schema.yml alone still changes nothing. --- All seven stay listed, because the second case has nothing else to read ---- from. Where the two disagree, the schema wins on html and typst, and a ---- format the extension does not act on reads "enabled" alone, which is the ---- one that chooses whether a block's attributes are checked at all. So keep ---- that one in step with the schema, and treat a difference in the other six ---- as a thing to correct rather than a thing that shows. +--- from, and an option added to the schema needs an entry here as well or it +--- has no default at all on a format the extension does not act on. +--- Where the two disagree, the schema wins on html and typst, and a format +--- the extension does not act on reads "enabled" alone, which is the one that +--- chooses whether a block's attributes are checked. So keep that one in step +--- with the schema, and treat a difference in the other six as a thing to +--- correct rather than a thing that shows. local FALLBACK_DEFAULTS = { ['enabled'] = 'true', ['auto-filename'] = 'true', @@ -803,12 +808,14 @@ function Meta(meta) end -- The schema is read first and the fallback fills only what it leaves - -- unanswered, so an option added to _schema.yml and to the key list below - -- needs nothing here. Reading the fallback first would have made it the list - -- of options allowed to have a default at all, which is the coupling this - -- change exists to remove. What arrives is one entry per option that - -- declares a default of its own, and get_options reads only the keys named - -- below. + -- unanswered, so on html and typst an option added to _schema.yml and to the + -- key list below needs nothing more. Anywhere else the check above never + -- runs, so the same option also needs an entry in FALLBACK_DEFAULTS or it + -- has no default there. Reading the fallback first would have made it the + -- list of options allowed to have a default at all, on every format, which + -- is the coupling this change exists to remove. What arrives is one entry + -- per option that declares a default of its own, and get_options reads only + -- the keys named below. local defaults = {} for key, declared in pairs(schema_defaults) do defaults[key] = stringify_bool(declared)