diff --git a/news/changelog-1.11.md b/news/changelog-1.11.md index e5a1c1f3db8..4b9c334c4ba 100644 --- a/news/changelog-1.11.md +++ b/news/changelog-1.11.md @@ -80,6 +80,7 @@ All changes included in 1.11: - ([#11683](https://github.com/quarto-dev/quarto-cli/issues/11683)): Fix `unknown font family` warnings, and wrong fonts, when a `font-family` list or brand typography uses a CSS generic family (`serif`, `sans-serif`, `monospace`, `cursive`, `fantasy`, `math`, `system-ui`, `ui-*`). Typst has no generic families, so each one is now replaced by the first installed font from a list of well-known candidates, and the keyword is no longer passed to Typst. No fonts are bundled. - ([#14081](https://github.com/quarto-dev/quarto-cli/issues/14081)): Support `lof` and `lot` in Typst documents, which previously had no effect. The list titles follow `lang` and can be set with `crossref: lof-title` and `lot-title`. +- ([#14290](https://github.com/quarto-dev/quarto-cli/issues/14290)): Fix `proof`, `remark` and `solution` blocks in Typst output, which rendered as plain text and could not be cross-referenced. They now use the same frames as theorems. Theorem and proof titles set in the language files may now contain Typst markup characters, and a `style` attribute on a theorem or proof now applies in Typst too. (author: @mcanouil) - ([#14847](https://github.com/quarto-dev/quarto-cli/pull/14847)): Fix `toc_title` auto-fallback in typst outline template that was ignoring the computed fallback value when `toc_title` is `none`. - ([#14947](https://github.com/quarto-dev/quarto-cli/issues/14947)): Fix Typst compilation failing with `invalid number suffix: px` when an image with alt text (`fig-alt`, `alt`, or an inline image caption) has its `width` or `height` in pixels. These images are now written by Pandoc's Typst writer like other images, which also fixes URL-encoded image paths and unsupported size units for them. diff --git a/src/resources/filters/customnodes/proof.lua b/src/resources/filters/customnodes/proof.lua index 6d700c0664d..b1e5a1bb5a4 100644 --- a/src/resources/filters/customnodes/proof.lua +++ b/src/resources/filters/customnodes/proof.lua @@ -61,6 +61,36 @@ _quarto.ast.add_handler({ end }) +-- Color mapping for clouds/rainbow themes (per proof type) +local proof_theme_colors = { + proof = "gray", remark = "orange", solution = "teal" +} + +-- A proof is numbered only when its identifier is a crossref id (`prf-`, +-- `rem-` or `sol-`). +local function is_numbered_proof(identifier) + local ref = identifier and refType(identifier) + return ref ~= nil and crossref.categories.by_ref_type[ref] ~= nil +end + +local function ensure_typst_proofs(proof_env) + local appearance = _quarto.modules.theorems.ensure_appearance_imports() + local proof_info = proof_types[proof_env] + local title = envTitle(proof_env, proof_info.title) + local render_code = _quarto.modules.theorems.render_code(appearance, { + color_scheme = "tertiary", + color = proof_theme_colors[proof_env] or "gray", + simple_render = "simple-proof-render", + simple_style = "proof", + }) + + -- the simple renderer writes the header in italic, like LaTeX and HTML; + -- the other appearances keep theorion's bold header, as theorems do + local bold = appearance ~= "simple" + _quarto.modules.theorems.ensure_frame(proof_env, title, render_code, bold) + return bold +end + function is_proof_div(div) local ref = refType(div.identifier) if ref ~= nil then @@ -141,6 +171,40 @@ end, function(proof_tbl) end elseif _quarto.format.isJatsOutput() then el = jatsTheorem(el, nil, name ) + elseif _quarto.format.isTypstOutput() then + -- a block holding only a title still needs its frame, so that its label + -- exists for references; theorems do the same + if #el.content == 0 then + el.content = pandoc.Blocks({pandoc.Para({pandoc.Str '\u{a0}'})}) + end + local bold = ensure_typst_proofs(proof.env) + local preamble = pandoc.Plain({pandoc.RawInline("typst", "#" .. proof.env .. "(")}) + local numbered = is_numbered_proof(proof_tbl.identifier) + if not numbered then + -- theorion steps the counter and prints the number only for + -- `number: auto`, and its prefix would keep a space before the empty + -- number, so an unnumbered block pins both + preamble.content:insert(pandoc.RawInline("typst", + 'number: "", get-prefix: (..args) => ' .. + _quarto.modules.theorems.header_code(envTitle(proof.env, proof.title), bold))) + end + if name and #name > 0 then + if not numbered then + preamble.content:insert(pandoc.RawInline("typst", ", ")) + end + preamble.content:insert(pandoc.RawInline("typst", 'title: [')) + tappend(preamble.content, name) + preamble.content:insert(pandoc.RawInline("typst", ']')) + end + preamble.content:insert(pandoc.RawInline("typst", ")[")) + local callproof = make_scaffold(pandoc.Div, preamble) + tappend(callproof.content, quarto.utils.as_blocks(el.content)) + if proof_tbl.identifier and proof_tbl.identifier ~= "" then + callproof.content:insert(pandoc.RawInline("typst", "] <" .. proof_tbl.identifier .. ">")) + else + callproof.content:insert(pandoc.RawInline("typst", "]")) + end + return _quarto.modules.theorems.keep_attributes(callproof, el.attr.attributes) else el.classes:insert(proof.title:lower()) local span_title = pandoc.Emph(pandoc.Str(envTitle(proof.env, proof.title))) @@ -176,4 +240,4 @@ end, function(proof_tbl) return el -end) \ No newline at end of file +end) diff --git a/src/resources/filters/customnodes/theorem.lua b/src/resources/filters/customnodes/theorem.lua index 29c222aae51..207b4959322 100644 --- a/src/resources/filters/customnodes/theorem.lua +++ b/src/resources/filters/customnodes/theorem.lua @@ -93,115 +93,30 @@ _quarto.ast.add_handler({ end }) --- Get theorem-appearance option (simple, fancy, clouds, rainbow) -local function get_theorem_appearance() - local appearance = option("theorem-appearance", "simple") - if appearance ~= nil and type(appearance) == "table" then - appearance = pandoc.utils.stringify(appearance) - end - return appearance or "simple" -end - -- Color mapping for clouds/rainbow themes (per theorem type) local theme_colors = { thm = "red", lem = "teal", cor = "navy", prp = "blue", cnj = "navy", def = "olive", exm = "green", exr = "purple", alg = "maroon" } -local included_typst_theorems = false -local letted_typst_theorem = {} local function ensure_typst_theorems(reftype) - local appearance = get_theorem_appearance() - - if not included_typst_theorems then - included_typst_theorems = true - - if appearance == "fancy" then - -- Import theorion's make-frame and fancy-box theming - quarto.doc.include_text("in-header", [[ -#import "@preview/theorion:0.4.1": make-frame, cosmos -#import cosmos.fancy: fancy-box, set-primary-border-color, set-primary-body-color, set-secondary-border-color, set-secondary-body-color, set-tertiary-border-color, set-tertiary-body-color, get-primary-border-color, get-primary-body-color, get-secondary-border-color, get-secondary-body-color, get-tertiary-border-color, get-tertiary-body-color -]]) - -- Set theorem colors from brand-color (runs in before-body, after brand-color is defined) - quarto.doc.include_text("before-body", [[ -#set-primary-border-color(brand-color.at("primary", default: green.darken(30%))) -#set-primary-body-color(brand-color.at("primary", default: green).lighten(90%)) -#set-secondary-border-color(brand-color.at("secondary", default: orange)) -#set-secondary-body-color(brand-color.at("secondary", default: orange).lighten(90%)) -#set-tertiary-border-color(brand-color.at("tertiary", default: blue.darken(30%))) -#set-tertiary-body-color(brand-color.at("tertiary", default: blue).lighten(90%)) -]]) - elseif appearance == "clouds" then - -- Import theorion's make-frame and clouds render function - quarto.doc.include_text("in-header", [[ -#import "@preview/theorion:0.4.1": make-frame, cosmos -#import cosmos.clouds: render-fn as clouds-render -]]) - elseif appearance == "rainbow" then - -- Import theorion's make-frame and rainbow render function - quarto.doc.include_text("in-header", [[ -#import "@preview/theorion:0.4.1": make-frame, cosmos -#import cosmos.rainbow: render-fn as rainbow-render -]]) - else -- simple (default) - -- Import only make-frame and define simple render function - quarto.doc.include_text("in-header", [[ -#import "@preview/theorion:0.4.1": make-frame - -// Simple theorem render: bold title with period, italic body -#let simple-theorem-render(prefix: none, title: "", full-title: auto, body) = { - if full-title != "" and full-title != auto and full-title != none { - strong[#full-title.] - h(0.5em) - } - emph(body) - parbreak() -} -]]) - end - end - - if not letted_typst_theorem[reftype] then - letted_typst_theorem[reftype] = true - local theorem_type = theorem_types[reftype] - local title = titleString(reftype, theorem_type.title) - - -- Build render code based on appearance - local render_code - if appearance == "fancy" then - -- Map theorem styles to color schemes (primary=definitions, secondary=theorems, tertiary=propositions) - local color_scheme = "secondary" -- default for most theorem types - if theorem_type.style == "definition" then - color_scheme = "primary" - elseif reftype == "prp" then - color_scheme = "tertiary" - end - render_code = " render: fancy-box.with(\n" .. - " get-border-color: get-" .. color_scheme .. "-border-color,\n" .. - " get-body-color: get-" .. color_scheme .. "-body-color,\n" .. - " get-symbol: loc => none,\n" .. - " ),\n" - elseif appearance == "clouds" then - local color = theme_colors[reftype] or "gray" - render_code = " render: clouds-render.with(fill: " .. color .. ".lighten(85%)),\n" - elseif appearance == "rainbow" then - local color = theme_colors[reftype] or "gray" - render_code = " render: rainbow-render.with(fill: " .. color .. ".darken(20%)),\n" - else -- simple - render_code = " render: simple-theorem-render,\n" - end - - -- Use theorion's make-frame with appropriate render - quarto.doc.include_text("in-header", "#let (" .. theorem_type.env .. "-counter, " .. theorem_type.env .. "-box, " .. - theorem_type.env .. ", show-" .. theorem_type.env .. ") = make-frame(\n" .. - " \"" .. theorem_type.env .. "\",\n" .. - " text(weight: \"bold\")[" .. title .. "],\n" .. - " inherited-levels: theorem-inherited-levels,\n" .. - " numbering: theorem-numbering,\n" .. - render_code .. - ")") - quarto.doc.include_text("in-header", "#show: show-" .. theorem_type.env) + local appearance = _quarto.modules.theorems.ensure_appearance_imports() + local theorem_type = theorem_types[reftype] + local title = titleString(reftype, theorem_type.title) + local color_scheme = "secondary" + if theorem_type.style == "definition" then + color_scheme = "primary" + elseif reftype == "prp" then + color_scheme = "tertiary" end + local render_code = _quarto.modules.theorems.render_code(appearance, { + color_scheme = color_scheme, + color = theme_colors[reftype] or "gray", + simple_render = "simple-theorem-render", + simple_style = "theorem", + }) + + _quarto.modules.theorems.ensure_frame(theorem_type.env, title, render_code, true) end @@ -267,7 +182,7 @@ end, function(thm) local callthm = make_scaffold(pandoc.Div, preamble) tappend(callthm.content, quarto.utils.as_blocks(el.content)) callthm.content:insert(pandoc.RawInline("typst", "] <" .. el.attr.identifier .. ">")) - return callthm + return _quarto.modules.theorems.keep_attributes(callthm, el.attr.attributes) else -- order might be nil in the case of an ipynb rendering in diff --git a/src/resources/filters/modules/import_all.lua b/src/resources/filters/modules/import_all.lua index b642911129f..78512ac6a15 100644 --- a/src/resources/filters/modules/import_all.lua +++ b/src/resources/filters/modules/import_all.lua @@ -21,6 +21,7 @@ _quarto.modules = { scope = require("modules/scope"), string = require("modules/string"), tablecolwidths = require("modules/tablecolwidths"), + theorems = require("modules/theorems"), typst = require("modules/typst"), listtable = require("modules/listtable"), tableutils = require("modules/tableutils"), diff --git a/src/resources/filters/modules/theorems.lua b/src/resources/filters/modules/theorems.lua new file mode 100644 index 00000000000..a0217ce2364 --- /dev/null +++ b/src/resources/filters/modules/theorems.lua @@ -0,0 +1,156 @@ +-- theorems.lua +-- Shared Typst theorem/proof setup logic using theorion +-- Copyright (C) 2026 Posit Software, PBC + +local typst_theorem_appearance_imported = false +local typst_theorem_like_frames = {} +local typst_simple_renderers = {} + +local function appearance() + local val = option("theorem-appearance", "simple") + if type(val) == "table" then + val = pandoc.utils.stringify(val) + end + return val or "simple" +end + +local function ensure_appearance_imports() + local val = appearance() + if typst_theorem_appearance_imported then + return val + end + + typst_theorem_appearance_imported = true + if val == "fancy" then + quarto.doc.include_text("in-header", [[ +#import "@preview/theorion:0.4.1": make-frame, cosmos +#import cosmos.fancy: fancy-box, set-primary-border-color, set-primary-body-color, set-secondary-border-color, set-secondary-body-color, set-tertiary-border-color, set-tertiary-body-color, get-primary-border-color, get-primary-body-color, get-secondary-border-color, get-secondary-body-color, get-tertiary-border-color, get-tertiary-body-color +]]) + quarto.doc.include_text("before-body", [[ +#set-primary-border-color(brand-color.at("primary", default: green.darken(30%))) +#set-primary-body-color(brand-color.at("primary", default: green).lighten(90%)) +#set-secondary-border-color(brand-color.at("secondary", default: orange)) +#set-secondary-body-color(brand-color.at("secondary", default: orange).lighten(90%)) +#set-tertiary-border-color(brand-color.at("tertiary", default: blue.darken(30%))) +#set-tertiary-body-color(brand-color.at("tertiary", default: blue).lighten(90%)) +]]) + elseif val == "clouds" then + quarto.doc.include_text("in-header", [[ +#import "@preview/theorion:0.4.1": make-frame, cosmos +#import cosmos.clouds: render-fn as clouds-render +]]) + elseif val == "rainbow" then + quarto.doc.include_text("in-header", [[ +#import "@preview/theorion:0.4.1": make-frame, cosmos +#import cosmos.rainbow: render-fn as rainbow-render +]]) + else + quarto.doc.include_text("in-header", [[ +#import "@preview/theorion:0.4.1": make-frame +]]) + end + + return val +end + +-- Defines a simple renderer once. The "theorem" style writes a bold header and +-- an italic body; the "proof" style writes an italic header and an upright +-- body, with the name in brackets, as amsthm and the HTML output do. +local function ensure_simple_render(render_name, style) + if typst_simple_renderers[render_name] then + return + end + + typst_simple_renderers[render_name] = true + if style == "proof" then + quarto.doc.include_text("in-header", "#let " .. render_name .. [[(prefix: none, title: "", full-title: auto, body) = { + emph(prefix) + if title != "" and title != none [ (#title)] + [. ] + body + parbreak() +} +]]) + return + end + + quarto.doc.include_text("in-header", "#let " .. render_name .. [[(prefix: none, title: "", full-title: auto, body) = { + if full-title != "" and full-title != auto and full-title != none { + strong[#full-title.] + h(0.5em) + } + emph(body) + parbreak() +} +]]) +end + +-- Writes text as a Typst string literal, so that titles from the language +-- files reach the page as written instead of being read as Typst markup. +local function typst_string(text) + return '"' .. text:gsub("\\", "\\\\"):gsub('"', '\\"') .. '"' +end + +-- Returns the `render:` argument of make-frame for the theorem appearance. +-- opts.color_scheme: fancy color set (primary, secondary or tertiary) +-- opts.color: clouds and rainbow fill color +-- opts.simple_render, opts.simple_style: name and style ("theorem" or "proof") +-- of the simple renderer +local function render_code(appearance_name, opts) + if appearance_name == "fancy" then + return " render: fancy-box.with(\n" .. + " get-border-color: get-" .. opts.color_scheme .. "-border-color,\n" .. + " get-body-color: get-" .. opts.color_scheme .. "-body-color,\n" .. + " get-symbol: loc => none,\n" .. + " ),\n" + elseif appearance_name == "clouds" then + return " render: clouds-render.with(fill: " .. opts.color .. ".lighten(85%)),\n" + elseif appearance_name == "rainbow" then + return " render: rainbow-render.with(fill: " .. opts.color .. ".darken(20%)),\n" + end + ensure_simple_render(opts.simple_render, opts.simple_style) + return " render: " .. opts.simple_render .. ",\n" +end + +-- Returns the Typst code for a frame header: bold, or plain for blocks whose +-- renderer styles the header itself. +local function header_code(title, bold) + if bold then + return 'text(weight: "bold", ' .. typst_string(title) .. ')' + end + return typst_string(title) +end + +local function ensure_frame(env_name, title, render_arg, bold) + if typst_theorem_like_frames[env_name] then + return + end + + typst_theorem_like_frames[env_name] = true + quarto.doc.include_text("in-header", "#let (" .. env_name .. "-counter, " .. env_name .. "-box, " .. + env_name .. ", show-" .. env_name .. ") = make-frame(\n" .. + " \"" .. env_name .. "\",\n" .. + " " .. header_code(title, bold) .. ",\n" .. + " inherited-levels: theorem-inherited-levels,\n" .. + " numbering: theorem-numbering,\n" .. + render_arg .. + ")") + quarto.doc.include_text("in-header", "#show: show-" .. env_name) +end + +-- Keeps the block's attributes, such as `style`, on a wrapper div, so the Typst +-- CSS support turns them into a block around the frame, as for other divs. +local function keep_attributes(frame, attributes) + if #attributes > 0 then + return pandoc.Div({frame}, pandoc.Attr("", {}, attributes)) + end + return frame +end + +return { + ensure_appearance_imports = ensure_appearance_imports, + ensure_frame = ensure_frame, + header_code = header_code, + keep_attributes = keep_attributes, + render_code = render_code, +} diff --git a/tests/docs/smoke-all/2026/02/04/issue-13992-proof.qmd b/tests/docs/smoke-all/2026/02/04/issue-13992-proof.qmd index 00db55838c3..3814834f8e3 100644 --- a/tests/docs/smoke-all/2026/02/04/issue-13992-proof.qmd +++ b/tests/docs/smoke-all/2026/02/04/issue-13992-proof.qmd @@ -14,7 +14,7 @@ _quarto: - ['Proof content visible'] typst: ensureTypstFileRegexMatches: - - ['#emph\[Proof\]\\?\. Proof content visible'] + - ['#proof\(', 'Proof content visible'] - [] --- diff --git a/tests/docs/smoke-all/2026/04/04/issue-14290-simple-style.qmd b/tests/docs/smoke-all/2026/04/04/issue-14290-simple-style.qmd new file mode 100644 index 00000000000..ffdee89c414 --- /dev/null +++ b/tests/docs/smoke-all/2026/04/04/issue-14290-simple-style.qmd @@ -0,0 +1,57 @@ +--- +title: "Proof-like blocks keep the LaTeX style in the simple appearance" +format: typst +keep-typ: true +_quarto: + tests: + typst: + ensureTypstFileRegexMatches: + - + # the header is italic and the body upright, as in LaTeX and HTML + - '#let simple-proof-render\(prefix: none, title: "", full-title: auto, body\) = \{(\r\n?|\n)\s*emph\(prefix\)' + - 'make-frame\((\r\n?|\n)\s*"proof",(\r\n?|\n)\s*"Proof",' + - 'make-frame\((\r\n?|\n)\s*"remark",(\r\n?|\n)\s*"Remark",' + - '#proof\(number: "", get-prefix: \(\.\.args\) => "Proof"\)\[' + # theorems keep the bold header + - 'make-frame\((\r\n?|\n)\s*"theorem",(\r\n?|\n)\s*text\(weight: "bold", "Theorem"\),' + # attributes on the block still reach the output + - '#block\(fill: yellow\)\[(\r\n?|\n)#set text\(fill: red\);(\r\n?|\n)#proof\(' + - '#block\(fill: aqua\)\[(\r\n?|\n)#set text\(fill: blue\);(\r\n?|\n)#theorem\(\)\[' + - + - 'text\(weight: "bold", "Proof"\)' + - 'text\(weight: "bold", "Remark"\)' + ensurePdfRegexMatches: + - + - 'Remark 1 \(Named\)\. A numbered remark' + - 'Proof\. An unnumbered proof' + - [] +--- + +In the `simple` appearance, which the documentation describes as classic +LaTeX style, `proof`, `remark` and `solution` headers are italic with an +upright body, as amsthm and the HTML output write them. Theorems keep a bold +header. A `style` attribute on a proof or a theorem still reaches the Typst +output. + +::: {#thm-a} +A theorem. +::: + +::: {.proof} +An unnumbered proof. +::: + +::: {#rem-a} +## Named +A numbered remark. +::: + +::: {.proof style="background-color: yellow; color: red"} +A styled proof. +::: + +::: {#thm-b style="background-color: aqua; color: blue"} +A styled theorem. +::: + +See @rem-a. diff --git a/tests/docs/smoke-all/2026/04/04/issue-14290-title-markup.qmd b/tests/docs/smoke-all/2026/04/04/issue-14290-title-markup.qmd new file mode 100644 index 00000000000..62202e6b964 --- /dev/null +++ b/tests/docs/smoke-all/2026/04/04/issue-14290-title-markup.qmd @@ -0,0 +1,32 @@ +--- +title: "Theorem and proof titles that hold Typst markup" +format: typst +language: + crossref-thm-title: "Thm #y [*x*]" + environment-proof-title: "Pf #y [*x*] \"q\"" +_quarto: + tests: + typst: + ensurePdfRegexMatches: + - + - 'Thm #y \[\*x\*\] 1\. A theorem' + - 'Pf #y \[\*x\*\] "q"\. An unnumbered proof' + - [] +--- + +Theorem and proof titles come from the language files, so an author can put +any text in them. The titles are written into the Typst frame definitions and +the unnumbered proof prefix, and must reach the page as written instead of +being read as Typst markup. + +::: {#thm-a} + +A theorem. + +::: + +::: {.proof} + +An unnumbered proof. + +::: diff --git a/tests/docs/smoke-all/2026/04/04/issue-14290.qmd b/tests/docs/smoke-all/2026/04/04/issue-14290.qmd new file mode 100644 index 00000000000..dc59faa13a0 --- /dev/null +++ b/tests/docs/smoke-all/2026/04/04/issue-14290.qmd @@ -0,0 +1,94 @@ +--- +title: "Cross-reference remark and solution in Typst (#14290)" +keep-typ: true +_quarto: + tests: + typst: + ensureTypstFileRegexMatches: + - + - '#remark\(' + - '#solution\(' + - '' + - '' + - '#show: show-remark' + - '#show: show-solution' + - '#ref\(' + - '#ref\(' + # unnumbered blocks pin their number and keep the counter still + - '#remark\(number: "", get-prefix: \(\.\.args\) => "Remark"\)' + - '#proof\(number: "", get-prefix: \(\.\.args\) => "Proof"\)' + # a numbered proof keeps theorion's own number + - '#proof\(\)\[(\r\n?|\n)Numbered proof\.' + # a block holding only a title keeps its label for references + - '' + - [] + ensurePdfRegexMatches: + - + - 'Remark\. An unnumbered remark' + - 'Remark 1 \(A Remark\)' + - 'Solution 1 \(A Solution\)' + - 'Proof\. This is an unnumbered proof' + - 'Proof 1\. Numbered proof' + - 'Proof \(With code\)\. A named proof' + - 'Proof 2 \(Only a title\)' + - 'See Remark 1, Solution 1, Proof 1 and Proof 2' + - + - 'Remark 2' + - 'Proof 3' + - 'Proof \.' +--- + +An unnumbered `proof`, `remark` or `solution` block uses the same theorion +frame, and so the same counter, as the numbered block of that kind. It must +show no number and must not move the counter, so that `rem-example` is still +Remark 1 although an unnumbered remark comes before it. + +::: {.remark} + +An unnumbered remark. + +::: + +::: {#rem-example} + +## A Remark + +This is a remark that should be cross-referenceable. + +::: + +::: {#sol-exercise} + +## A Solution + +This is a solution that should be cross-referenceable. + +::: + +::: {.proof} + +This is an unnumbered proof. + +::: + +::: {#prf-a} + +Numbered proof. + +::: + +::: {.proof} + +## With `code` + +A named proof. + +::: + +::: {#prf-b} + +## Only a title + +::: + +See @rem-example, @sol-exercise, @prf-a and @prf-b. diff --git a/tests/docs/smoke-all/typst/theorem/proof-fancy.qmd b/tests/docs/smoke-all/typst/theorem/proof-fancy.qmd new file mode 100644 index 00000000000..1a0785178ce --- /dev/null +++ b/tests/docs/smoke-all/typst/theorem/proof-fancy.qmd @@ -0,0 +1,42 @@ +--- +format: + typst: + keep-typ: true + theorem-appearance: fancy +_quarto: + tests: + typst: + ensureTypstFileRegexMatches: + - + # proof-like frames use the tertiary fancy colours and a bold header + - 'make-frame\((\r\n?|\n)\s*"proof",(\r\n?|\n)\s*text\(weight: "bold", "Proof"\),' + - 'make-frame\((\r\n?|\n)\s*"remark",(\r\n?|\n)\s*text\(weight: "bold", "Remark"\),' + - 'get-border-color: get-tertiary-border-color' + - '#proof\(number: "", get-prefix: \(\.\.args\) => text\(weight: "bold", "Proof"\)\)\[' + - '#remark\(\)\[' + - + - "simple-proof-render" + - "clouds-render" + - "rainbow-render" + ensurePdfRegexMatches: + - + - "Proof" + - "Remark 1" + - + - "Proof 1" + - "Remark 2" +--- + +::: {.proof} +An unnumbered proof. +::: + +::: {.remark} +An unnumbered remark. +::: + +::: {#rem-a} +A numbered remark. +::: + +See @rem-a.