diff --git a/CHANGELOG.md b/CHANGELOG.md index ecd6d3e..9900fe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - 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) - fix: Check every code block attribute in the code-window group against the schema, so a value nothing validated before, such as code-window-enabled, is now reported when it is wrong. The extension's own duplicate warnings for an invalid code-window-style or code-window-collapse are removed, since the schema already names the same mistake. (#60) - fix: Honour an explicit code-window-no-auto-filename="false", which previously suppressed auto-filename exactly like "true". (#60) +- fix: Honour `code-window-collapse="false"` on a block, which could not turn off a document that sets `collapse`. The block fell back to the document setting and was folded anyway. - fix: Remove the extension's own duplicate collapse and style warnings at the document option level, now that the schema reports each mistake once. (#60) - fix: Match the code-window-collapse attribute schema to the string Pandoc always provides, so a documented "true" or "false" value no longer warns. (#60) - fix: Validate a code block's attributes on the HTML path the same way the Typst path already does, so an invalid attribute on a block holding executed-cell output is now reported on HTML too, instead of being silently accepted. (#60) diff --git a/_extensions/code-window/code-window.lua b/_extensions/code-window/code-window.lua index 55586c0..ca8c465 100644 --- a/_extensions/code-window/code-window.lua +++ b/_extensions/code-window/code-window.lua @@ -248,12 +248,20 @@ end --- test needed. --- @param resolved table This block's attributes, resolved against the schema --- @return string|nil Resolved collapse mode ("open"/"closed") or nil when off +--- @return boolean Whether this block decided, which is what separates an +--- explicit "false" from an attribute the block never wrote local function read_block_collapse(resolved) local raw = resolved['code-window-collapse'] if raw == nil then - return nil + return nil, false + end + local mode = VALID_COLLAPSE[raw] + if mode == nil then + -- A value the schema does not accept. The check reports it, and the + -- document option decides as though the block had written nothing. + return nil, false end - return resolve_collapse(raw) + return mode or nil, true end --- Read a highlight-lines spec from the block, looking at the @@ -664,7 +672,11 @@ local function process_html(block, resolved, auto_label) return block end - local effective_collapse = read_block_collapse(resolved) or CONFIG.collapse + local block_collapse, block_decided = read_block_collapse(resolved) + local effective_collapse = block_collapse + if not block_decided then + effective_collapse = CONFIG.collapse + end local explicit_filename = block.attributes['filename'] -- Add the marker classes and the chip the injected script reads. Both @@ -673,8 +685,13 @@ local function process_html(block, resolved, auto_label) if overrides.style then table.insert(block.classes, 'cw-style-' .. overrides.style) end + -- A block that turned collapsing off is marked as well. The script reads + -- the absence of a marker as "this block said nothing" and falls back to + -- the document setting, so an opt-out needs a marker of its own. if effective_collapse then table.insert(block.classes, 'cw-collapse-' .. effective_collapse) + elseif block_decided and CONFIG.collapse then + table.insert(block.classes, 'cw-collapse-none') end if overrides.lines_label then block.attributes['code-window-lines-label'] = overrides.lines_label @@ -755,8 +772,8 @@ document.addEventListener("DOMContentLoaded",function(){ } var collapse=null; if(marker){ - var cm=marker.className.match(/cw-collapse-(open|closed)/); - if(cm){collapse=cm[1];marker.classList.remove(cm[0]);} + var cm=marker.className.match(/cw-collapse-(open|closed|none)/); + if(cm){collapse=cm[1]==='none'?false:cm[1];marker.classList.remove(cm[0]);} } if(collapse===null&&DEFAULT_COLLAPSE){collapse=DEFAULT_COLLAPSE;} if(marker&&marker.hasAttribute("data-code-window-lines-label")){ diff --git a/tests/fixtures/collapse-block-off.qmd b/tests/fixtures/collapse-block-off.qmd new file mode 100644 index 0000000..0788196 --- /dev/null +++ b/tests/fixtures/collapse-block-off.qmd @@ -0,0 +1,20 @@ +--- +title: "Collapse turned off for one block" +format: html +filters: + - code-window +extensions: + code-window: + collapse: true +--- + +The document folds every block. +The first block opts out, and the second takes the document setting. + +```{.python filename="opted-out.py" code-window-collapse="false"} +x = 1 +``` + +```{.python filename="inherits.py"} +y = 2 +``` diff --git a/tests/run.sh b/tests/run.sh index cae2fc8..7b060b5 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -280,6 +280,33 @@ else "a #code-window( call in wrapper-default.typ" fi +# ============================================================================ +# A block opts out of the document's collapse setting +# ============================================================================ + +render collapse-block-off html + +# The script folds a block that carries no marker, reading the absence as +# "this block said nothing", so the opt-out is a marker of its own rather +# than a missing one. The second block is here to show the two differ. +collapse_markers="$(block_classes "${work_dir}/collapse-block-off.html" | grep -o 'cw-collapse-[a-z]*' | sort | tr '\n' ' ')" + +if [ "${collapse_markers}" = "cw-collapse-closed cw-collapse-none " ]; then + report pass "collapse-block-off: the block opts out and its neighbour does not" +else + report fail "collapse-block-off: the block opts out and its neighbour does not" \ + "cw-collapse-none on one block and cw-collapse-closed on the other, got: ${collapse_markers}" +fi + +# The document setting still reaches the page, which is what the opt-out has +# to override. +if grep -q 'DEFAULT_COLLAPSE="closed"' "${work_dir}/collapse-block-off.html"; then + report pass "collapse-block-off: the document setting reaches the page" +else + report fail "collapse-block-off: the document setting reaches the page" \ + 'DEFAULT_COLLAPSE="closed" in collapse-block-off.html' +fi + # ============================================================================ printf '\n%s passed, %s failed\n' "${passed}" "${failed}"