diff --git a/news/changelog-1.4.md b/news/changelog-1.4.md index bea3587246..409e17bdb5 100644 --- a/news/changelog-1.4.md +++ b/news/changelog-1.4.md @@ -91,7 +91,6 @@ - ([#5969](https://github.com/quarto-dev/quarto-cli/issues/5969)): Correctly detect a required rerun for biblatex when using backref link options. - ([#5690](https://github.com/quarto-dev/quarto-cli/issues/5690)): Improve validation of `pdf-engine` - ([#6077](https://github.com/quarto-dev/quarto-cli/issues/6077)): Make sure proof environments are tight around contents. -- ([#6298](https://github.com/quarto-dev/quarto-cli/issues/6298)): Handle multiple margin and caption specifiers on a single image. - ([#6907](https://github.com/quarto-dev/quarto-cli/issues/6907)): Fix issue with footnote mark line processor not triggering. - ([#6990](https://github.com/quarto-dev/quarto-cli/issues/6990)): Fix an issue where underscore in `filename` code cell attribute were not escaped. - ([#7175](https://github.com/quarto-dev/quarto-cli/issues/7175)): Fix an issue with code annotations when more than one digit is used for annotation number. diff --git a/src/project/project-config.ts b/src/project/project-config.ts index a80940b1d7..02f0f82675 100644 --- a/src/project/project-config.ts +++ b/src/project/project-config.ts @@ -1,8 +1,9 @@ /* - * project-config.ts - * - * Copyright (C) 2020-2022 Posit Software, PBC - */ +* project-config.ts +* +* Copyright (C) 2020-2022 Posit Software, PBC +* +*/ import { join } from "path/mod.ts"; @@ -16,34 +17,28 @@ import { SidebarItem } from "./types.ts"; export type SidebarContext = { counter: number; - itemCounter: number; }; export const sidebarContext = (): SidebarContext => { - return { counter: 0, itemCounter: 0 }; + return { counter: 0 }; }; export function normalizeSidebarItem( projectDir: string, item: SidebarItem, - context: SidebarContext, + context: { counter: number }, ): SidebarItem { // clone so we can mutate item = ld.cloneDeep(item); - if (typeof item === "string") { - context.itemCounter = context.itemCounter + 1; - const id = `${kQuartoSidebarItemPrefix}${context.itemCounter}`; - + if (typeof (item) === "string") { if (safeExistsSync(join(projectDir, item))) { item = { href: item, - id, }; } else { item = { text: item, - id, }; } } else { @@ -72,11 +67,6 @@ export function normalizeSidebarItem( // If this is a section, we should insist that it have 'contents' // even if they are empty. item.contents = item.contents || []; - } else { - context.itemCounter = context.itemCounter + 1; - item.id = item.id === undefined - ? `${kQuartoSidebarItemPrefix}${context.itemCounter}` - : item.id; } // handle subitems @@ -95,7 +85,6 @@ export function normalizeSidebarItem( } const kQuartoSidebarPrefix = "quarto-sidebar-section-"; -const kQuartoSidebarItemPrefix = "quarto-sidebar-item-"; export function resolveHrefAttribute( item: { href?: string; file?: string; url?: string }, diff --git a/src/project/types/website/website-navigation-md.ts b/src/project/types/website/website-navigation-md.ts index 8b5f81eb6d..4985f29d63 100644 --- a/src/project/types/website/website-navigation-md.ts +++ b/src/project/types/website/website-navigation-md.ts @@ -243,7 +243,7 @@ const sidebarContentsHandler = (context: NavigationPipelineContext) => { if (item.sectionId) { markdown[`${kSidebarIdPrefix}${item.sectionId}`] = item.text; } else { - markdown[`${kSidebarIdPrefix}${item.id || ""}${item.href}`] = + markdown[`${kSidebarIdPrefix}${item.href}${item.text}`] = item.text; } } @@ -258,11 +258,11 @@ const sidebarContentsHandler = (context: NavigationPipelineContext) => { ); for (let i = 0; i < sidebarItemEls.length; i++) { const sidebarEl = sidebarItemEls[i] as Element; - const link = sidebarEl.querySelector(".menu-text"); const href = sidebarEl.getAttribute("href"); + const link = sidebarEl.querySelector(".menu-text"); if (link) { const sidebarText = - rendered[`${kSidebarIdPrefix}${sidebarEl.id}${href}`]; + rendered[`${kSidebarIdPrefix}${href}${link.innerText}`]; if (sidebarText) { link.innerHTML = sidebarText.innerHTML; } diff --git a/src/project/types/website/website-navigation.ts b/src/project/types/website/website-navigation.ts index 163fb2de8a..241ed3cbfe 100644 --- a/src/project/types/website/website-navigation.ts +++ b/src/project/types/website/website-navigation.ts @@ -75,7 +75,6 @@ import { import { normalizeSidebarItem, resolveHrefAttribute, - SidebarContext, sidebarContext, } from "../../project-config.ts"; import { projectType } from "../project-types.ts"; @@ -1058,10 +1057,7 @@ async function resolveSidebarItems( } } -async function resolveSidebarItem( - project: ProjectContext, - item: SidebarItem, -) { +async function resolveSidebarItem(project: ProjectContext, item: SidebarItem) { if (item.href) { item = await resolveItem( project, diff --git a/src/resources/filters/common/theorems.lua b/src/resources/filters/common/theorems.lua index 49ff6d173d..a88eb355a5 100644 --- a/src/resources/filters/common/theorems.lua +++ b/src/resources/filters/common/theorems.lua @@ -1,27 +1,2 @@ -- theorems.lua -- Copyright (C) 2020-2022 Posit Software, PBC - -proofTypes = { - proof = { - env = 'proof', - title = 'Proof' - }, - remark = { - env = 'remark', - title = 'Remark' - }, - solution = { - env = 'solution', - title = 'Solution' - } -} - -function proofType(el) - local type = el.attr.classes:find_if(function(clz) return proofTypes[clz] ~= nil end) - if type ~= nil then - return proofTypes[type] - else - return nil - end - -end \ No newline at end of file diff --git a/src/resources/filters/crossref/crossref.lua b/src/resources/filters/crossref/crossref.lua index 1ea56d0acf..e97d3cdcb7 100644 --- a/src/resources/filters/crossref/crossref.lua +++ b/src/resources/filters/crossref/crossref.lua @@ -97,6 +97,7 @@ import("../quarto-pre/panel-input.lua") import("../quarto-pre/panel-layout.lua") import("../quarto-pre/panel-sidebar.lua") import("../quarto-pre/parsefiguredivs.lua") +import("../quarto-pre/parseblockreftargets.lua") import("../quarto-pre/project-paths.lua") import("../quarto-pre/resourcefiles.lua") import("../quarto-pre/results.lua") @@ -117,6 +118,7 @@ import("../customnodes/decoratedcodeblock.lua") import("../customnodes/callout.lua") import("../customnodes/panel-tabset.lua") import("../customnodes/floatreftarget.lua") +import("../customnodes/proof.lua") import("../customnodes/theorem.lua") import("../customnodes/panellayout.lua") @@ -176,7 +178,8 @@ local quarto_normalize_filters = { name = "normalize-combine-2", filter = combineFilters({ parse_md_in_html_rawblocks(), - parse_reftargets(), + parse_floatreftargets(), + parse_blockreftargets(), }), }, } diff --git a/src/resources/filters/crossref/theorems.lua b/src/resources/filters/crossref/theorems.lua index 7899ed0ea8..a006ad0905 100644 --- a/src/resources/filters/crossref/theorems.lua +++ b/src/resources/filters/crossref/theorems.lua @@ -3,11 +3,10 @@ -- preprocess theorem to ensure that embedded headings are unnumered function crossref_preprocess_theorems() - local types = theorem_types return { Div = function(el) local type = refType(el.attr.identifier) - if types[type] ~= nil or proofType(el) ~= nil then + if theorem_types[type] ~= nil or proof_type(el) ~= nil then return _quarto.ast.walk(el, { Header = function(el) el.classes:insert("unnumbered") @@ -15,15 +14,11 @@ function crossref_preprocess_theorems() end }) end - end } end function crossref_theorems() - - local types = theorem_types - return { Theorem = function(thm) local label = thm.identifier @@ -32,19 +27,29 @@ function crossref_theorems() thm.order = add_crossref(label, type, title) return thm end, + Proof = function(proof) + local label = proof.identifier + if label == "" then + return nil -- it's an unnumbered proof + end + local type = refType(label) + local title = quarto.utils.as_blocks(proof.name) + proof.order = add_crossref(label, type, title) + return proof + end, Div = function(el) local type = refType(el.attr.identifier) - local theoremType = types[type] + local theoremType = theorem_types[type] if theoremType then internal_error() else -- see if this is a proof, remark, or solution - local proof = proofType(el) + local proof = proof_type(el) if proof ~= nil then -- ensure requisite latex is injected - crossref.usingTheorems = true + crossref.using_theorems = true if proof.env ~= "proof" then el.attr.classes:insert("proof") @@ -135,7 +140,7 @@ function jatsTheorem(el, label, title) --

-- - if title then + if #title > 0 then tprepend(el.content, { pandoc.RawBlock("jats", ""), pandoc.Plain(title), @@ -179,19 +184,17 @@ end function theoremLatexIncludes() -- determine which theorem types we are using - local types = theorem_types - local refs = tkeys(crossref.index.entries) - local usingTheorems = crossref.usingTheorems + local using_theorems = crossref.using_theorems for k,v in pairs(crossref.index.entries) do local type = refType(k) - if types[type] then - usingTheorems = true - types[type].active = true + if theorem_types[type] then + using_theorems = true + theorem_types[type].active = true end end -- return requisite latex if we are using theorems - if usingTheorems then + if using_theorems then local secType if crossrefOption("chapters", false) then secType = "chapter" @@ -199,19 +202,22 @@ function theoremLatexIncludes() secType = "section" end local theoremIncludes = "\\usepackage{amsthm}\n" - for _, type in ipairs(tkeys(types)) do - if types[type].active then + for _, type in ipairs(tkeys(theorem_types)) do + if theorem_types[type].active then theoremIncludes = theoremIncludes .. - "\\theoremstyle{" .. types[type].style .. "}\n" .. - "\\newtheorem{" .. types[type].env .. "}{" .. - titleString(type, types[type].title) .. "}[" .. secType .. "]\n" + "\\theoremstyle{" .. theorem_types[type].style .. "}\n" .. + "\\newtheorem{" .. theorem_types[type].env .. "}{" .. + titleString(type, theorem_types[type].title) .. "}[" .. secType .. "]\n" end end theoremIncludes = theoremIncludes .. "\\theoremstyle{remark}\n" .. "\\AtBeginDocument{\\renewcommand*{\\proofname}{" .. envTitle("proof", "Proof") .. "}}\n" .. "\\newtheorem*{remark}{" .. envTitle("remark", "Remark") .. "}\n" .. - "\\newtheorem*{solution}{" .. envTitle("solution", "Solution") .. "}\n" + "\\newtheorem*{solution}{" .. envTitle("solution", "Solution") .. "}\n" .. + "\\newtheorem{refremark}{" .. envTitle("remark", "Remark") .. "}[" .. secType .. "]\n" .. + "\\newtheorem{refsolution}{" .. envTitle("solution", "Solution") .. "}[" .. secType .. "]\n" + return theoremIncludes else return nil diff --git a/src/resources/filters/customnodes/floatreftarget.lua b/src/resources/filters/customnodes/floatreftarget.lua index 25f11deadd..483e35886a 100644 --- a/src/resources/filters/customnodes/floatreftarget.lua +++ b/src/resources/filters/customnodes/floatreftarget.lua @@ -363,7 +363,7 @@ end, function(float) -- do the longtable fixups below float.content = _quarto.ast.walk(quarto.utils.as_blocks(float.content), { Table = function(tbl) - return pandoc.RawBlock("latex-merge", pandoc.write(pandoc.Pandoc({tbl}), "latex")) + return pandoc.RawBlock("latex", pandoc.write(pandoc.Pandoc({tbl}), "latex")) end }) @@ -371,33 +371,12 @@ end, function(float) local raw -- have to call as_blocks() again here because assigning to float.content -- goes through our AST metaclasses which coalesce a singleton list to a single AST element - float.content = _quarto.ast.walk(quarto.utils.as_blocks(float.content), { - -- coalesce rawblocks ahead of table fixups - Blocks = function(blocks) - local result = pandoc.Blocks({}) - local prev - for _,block in ipairs(blocks) do - if prev == nil then - prev = block - elseif prev.t == "RawBlock" and block.t == "RawBlock" and prev.format == block.format then - prev.text = prev.text .. "\n" .. block.text - else - result:insert(prev) - prev = block - end - end - if prev ~= nil then - result:insert(prev) - end - return result - end - }) _quarto.ast.walk(quarto.utils.as_blocks(float.content), { RawBlock = function(el) if _quarto.format.isRawLatex(el) and el.text:match(_quarto.patterns.latexLongtablePattern) then raw = el end - end, + end }) -- special case for singleton longtable floats if raw then @@ -434,14 +413,14 @@ end, function(float) local result = pandoc.Blocks({latex_caption, pandoc.RawInline("latex", "\\tabularnewline")}) -- if cap_loc is top, insert content on bottom if cap_loc == "top" then - result:insert(pandoc.RawBlock("latex-merge", content)) + result:insert(pandoc.RawBlock("latex", content)) else - result:insert(1, pandoc.RawBlock("latex-merge", content)) + result:insert(1, pandoc.RawBlock("latex", content)) end - result:insert(1, pandoc.RawBlock("latex-merge", start)) - result:insert(1, pandoc.RawBlock("latex-merge", longtable_preamble)) - result:insert(pandoc.RawBlock("latex-merge", "\\end{longtable}")) - result:insert(pandoc.RawBlock("latex-merge", longtable_postamble)) + result:insert(1, pandoc.RawBlock("latex", start)) + result:insert(1, pandoc.RawBlock("latex", longtable_preamble)) + result:insert(pandoc.RawBlock("latex", "\\end{longtable}")) + result:insert(pandoc.RawBlock("latex", longtable_postamble)) return result end end diff --git a/src/resources/filters/customnodes/proof.lua b/src/resources/filters/customnodes/proof.lua new file mode 100644 index 0000000000..fa7d27be6a --- /dev/null +++ b/src/resources/filters/customnodes/proof.lua @@ -0,0 +1,177 @@ +-- proof.lua +-- custom AST node for proofs, remarks, solutions, etc. + +-- Copyright (C) 2023 Posit Software, PBC + +-- available proof types + +proof_types = { + proof = { + env = 'proof', + title = 'Proof' + }, + remark = { + env = 'remark', + title = 'Remark' + }, + solution = { + env = 'solution', + title = 'Solution' + } +} + +function proof_type(el) + local type = el.attr.classes:find_if(function(clz) return proof_types[clz] ~= nil end) + if type ~= nil then + return proof_types[type] + else + return nil + end +end + +_quarto.ast.add_handler({ + -- empty table so this handler is only called programmatically + class_name = {}, + + -- the name of the ast node, used as a key in extended ast filter tables + ast_name = "Proof", + + -- generic names this custom AST node responds to + -- this is still unimplemented + interfaces = {"Crossref"}, + + -- Proofs are always blocks + kind = "Block", + + parse = function(div) + -- luacov: disable + internal_error() + -- luacov: enable + end, + + slots = { "div", "name" }, + + constructor = function(tbl) + return { + name = tbl.name, + div = tbl.div, + identifier = tbl.identifier, + type = tbl.type -- proofs can be unnumbered and lack an identifier; we need to know the type explicitly + } + end +}) + +function is_proof_div(div) + local ref = refType(div.identifier) + if ref ~= nil then + local tbl = crossref.categories.by_ref_type[ref] + if tbl then + local key = tbl.name:lower() + return proof_types[key] + end + end + return is_regular_node(div, "Div") and proof_type(div) ~= nil +end + +_quarto.ast.add_renderer("Proof", function() + return true +end, function(proof_tbl) + local el = proof_tbl.div + -- see if this is a proof, remark, or solution + local proof = proof_types[proof_tbl.type:lower()] + if proof == nil then + internal_error() + return pandoc.Blocks({}) + end + + -- ensure requisite latex is injected + crossref.using_theorems = true + + if proof.env ~= "proof" then + el.attr.classes:insert("proof") + end + + local name = quarto.utils.as_inlines(proof_tbl.name or pandoc.Inlines({})) + + -- output + if _quarto.format.isLatexOutput() then + local preamble = pandoc.List() + local env = proof.env + + local has_ref = refType(proof_tbl.identifier) ~= nil + if has_ref then + env = "ref" .. env + end + + preamble:insert(pandoc.RawInline("latex", "\\begin{" .. env .. "}")) + if #name ~= 0 then + preamble:insert(pandoc.RawInline("latex", "[")) + tappend(preamble, name) + preamble:insert(pandoc.RawInline("latex", "]")) + end + preamble:insert(pandoc.RawInline("latex", "\n")) + -- https://github.com/quarto-dev/quarto-cli/issues/6077 + if el.content[1].t == "Para" then + preamble:extend(el.content[1].content) + el.content[1].content = preamble + else + if (el.content[1].t ~= "Para") then + -- required trick to get correct alignement when non Para content first + preamble:insert(pandoc.RawInline('latex', "\\leavevmode")) + end + el.content:insert(1, pandoc.Plain(preamble)) + end + if has_ref then + el.content:insert(pandoc.RawInline("latex", + "\\label{" .. proof_tbl.identifier .. "}") + ) + end + local end_env = "\\end{" .. env .. "}" + -- https://github.com/quarto-dev/quarto-cli/issues/6077 + if el.content[#el.content].t == "Para" then + el.content[#el.content].content:insert(pandoc.RawInline("latex", "\n" .. end_env)) + elseif el.content[#el.content].t == "RawBlock" and el.content[#el.content].format == "latex" then + -- this is required for no empty line between end_env and previous latex block + el.content[#el.content].text = el.content[#el.content].text .. "\n" .. end_env + else + el.content:insert(pandoc.RawBlock("latex", end_env)) + end + elseif _quarto.format.isJatsOutput() then + el = jatsTheorem(el, nil, name ) + else + el.classes:insert(proof.title:lower()) + local span_title = pandoc.Emph(pandoc.Str(envTitle(proof.env, proof.title))) + local entry = crossref.index.entries[proof_tbl.identifier] + local type = refType(proof_tbl.identifier) + if type then + el.identifier = proof_tbl.identifier + end + if entry then + span_title.content:insert(pandoc.Space()) + span_title.content:extend(refNumberOption(type, entry)) + end + + local span = pandoc.Span({ span_title }, pandoc.Attr("", { "proof-title" })) + if #name > 0 then + span.content:insert(pandoc.Str(" (")) + tappend(span.content, name) + span.content:insert(pandoc.Str(")")) + end + tappend(span.content, { pandoc.Str(". ")}) + + -- if the first block is a paragraph, then prepend the title span + if #el.content > 0 and + el.content[1].t == "Para" and + el.content[1].content ~= nil and + #el.content[1].content > 0 then + el.content[1].content:insert(1, span) + else + -- else insert a new paragraph + el.content:insert(1, pandoc.Para{span}) + end + print(el) + end + + return el + +end) \ No newline at end of file diff --git a/src/resources/filters/layout/columns-preprocess.lua b/src/resources/filters/layout/columns-preprocess.lua index d4bd98f314..d68df8e366 100644 --- a/src/resources/filters/layout/columns-preprocess.lua +++ b/src/resources/filters/layout/columns-preprocess.lua @@ -9,9 +9,7 @@ function columns_preprocess() end local location = cap_location(float) if location == 'margin' then - if not float.classes:includes("column-margin") then - float.classes:insert('margin-caption') - end + float.classes:insert('margin-caption') noteHasColumns() return float end @@ -34,13 +32,7 @@ function columns_preprocess() resolveElementForScopedColumns(figure, 'fig') end return el - end, - - Image = function(img) - if img.classes:find_if(function(class) return class:match("^column%-") end) then - noteHasColumns() - end - end + end } end diff --git a/src/resources/filters/main.lua b/src/resources/filters/main.lua index dd173c01e0..4d90c54856 100644 --- a/src/resources/filters/main.lua +++ b/src/resources/filters/main.lua @@ -145,6 +145,7 @@ import("./quarto-pre/panel-input.lua") import("./quarto-pre/panel-layout.lua") import("./quarto-pre/panel-sidebar.lua") import("./quarto-pre/parsefiguredivs.lua") +import("./quarto-pre/parseblockreftargets.lua") import("./quarto-pre/project-paths.lua") import("./quarto-pre/resourcefiles.lua") import("./quarto-pre/results.lua") @@ -174,6 +175,7 @@ import("./customnodes/callout.lua") import("./customnodes/panel-tabset.lua") import("./customnodes/floatreftarget.lua") import("./customnodes/theorem.lua") +import("./customnodes/proof.lua") import("./layout/confluence.lua") import("./layout/ipynb.lua") diff --git a/src/resources/filters/mainstateinit.lua b/src/resources/filters/mainstateinit.lua index f3f7bfccb4..079aa972f8 100644 --- a/src/resources/filters/mainstateinit.lua +++ b/src/resources/filters/mainstateinit.lua @@ -19,7 +19,7 @@ quarto_global_state = { } crossref = { - usingTheorems = false, + using_theorems = false, startAppendix = nil, -- initialize autolabels table @@ -87,10 +87,29 @@ crossref = { prefix = "Important", ref_type = "imp", -- this will look weird but we decided to do it for consistency with the original callout types }, + + -- proof envs + { + kind = "Block", + name = "Proof", + prefix = "Proof", + ref_type = "prf", + }, + { + kind = "Block", + name = "Remark", + prefix = "Remark", + ref_type = "rem", + }, + { + kind = "Block", + name = "Solution", + prefix = "Solution", + ref_type = "sol", + }, } - -- eventually we'll have other block kinds here - -- with theorem and proof envs + -- eventually we'll have other block kinds here, specifically theorem envs -- eventually we'll have inline kinds here -- with equation refs diff --git a/src/resources/filters/normalize/astpipeline.lua b/src/resources/filters/normalize/astpipeline.lua index 6a97cb9501..80ba526a75 100644 --- a/src/resources/filters/normalize/astpipeline.lua +++ b/src/resources/filters/normalize/astpipeline.lua @@ -21,7 +21,8 @@ function quarto_ast_pipeline() name = "normalize-combine-2", filter = combineFilters({ parse_md_in_html_rawblocks(), - parse_reftargets(), + parse_floatreftargets(), + parse_blockreftargets() }), }, } diff --git a/src/resources/filters/normalize/flags.lua b/src/resources/filters/normalize/flags.lua index f080de6d72..5f3bddd2a3 100644 --- a/src/resources/filters/normalize/flags.lua +++ b/src/resources/filters/normalize/flags.lua @@ -69,7 +69,7 @@ function compute_flags() end, Div = function(node) local type = refType(node.attr.identifier) - if theorem_types[type] ~= nil or proofType(node) ~= nil then + if theorem_types[type] ~= nil or proof_type(node) ~= nil then flags.has_theorem_refs = true end diff --git a/src/resources/filters/quarto-post/latex.lua b/src/resources/filters/quarto-post/latex.lua index 55b65a7e92..42ab1a765c 100644 --- a/src/resources/filters/quarto-post/latex.lua +++ b/src/resources/filters/quarto-post/latex.lua @@ -276,10 +276,6 @@ function render_latex() }) return float, false end, - Figure = function(fig) - -- defer rendering of figure to own pass - return nil, false - end, Image = function(img) if img.classes:includes("column-margin") then return handle_column_classes(pandoc.Span(img, img.attr)) diff --git a/src/resources/filters/quarto-pre/parseblockreftargets.lua b/src/resources/filters/quarto-pre/parseblockreftargets.lua new file mode 100644 index 0000000000..68631e69f5 --- /dev/null +++ b/src/resources/filters/quarto-pre/parseblockreftargets.lua @@ -0,0 +1,73 @@ +-- parseblockreftargets.lua +-- Copyright (C) 2023 Posit Software, PBC + +-- parses Proofs, Theorems, Lemmas, etc. + +function parse_blockreftargets() + + local function parse_theorem_div(el) + if not has_theorem_ref(el) then + return + end + -- capture then remove name + local name = markdownToInlines(el.attr.attributes["name"]) + if not name or #name == 0 then + name = resolveHeadingCaption(el) + end + el.attr.attributes["name"] = nil + local identifier = el.attr.identifier + -- remove identifier to avoid infinite recursion + el.attr.identifier = "" + return quarto.Theorem { + identifier = identifier, + name = name, + div = el + }, false + end + + local function parse_proof_div(el) + if not is_proof_div(el) then + return + end + + local name = string_to_quarto_ast_inlines(el.attributes["name"] or "") + if not name or #name == 0 then + name = resolveHeadingCaption(el) or pandoc.Inlines({}) + end + el.attributes["name"] = nil + local identifier = el.identifier + el.identifier = "" + + local ref = refType(identifier) + local proof_type + if ref ~= nil then + proof_type = crossref.categories.by_ref_type[ref].name + else + proof_type = el.classes:find_if(function(clz) return proof_types[clz] ~= nil end) + if proof_type == nil then + internal_error() + return + end + proof_type = proof_types[proof_type].title + end + el.classes = el.classes:filter(function(clz) return proof_types[clz] == nil end) + crossref.using_theorems = true + local tbl = { + identifier = identifier, + name = name, + div = el, + type = proof_type + } + return quarto.Proof(tbl), false + end + + return { + Div = function(div) + if is_theorem_div(div) then + return parse_theorem_div(div) + elseif is_proof_div(div) then + return parse_proof_div(div) + end + end + } +end \ No newline at end of file diff --git a/src/resources/filters/quarto-pre/parsefiguredivs.lua b/src/resources/filters/quarto-pre/parsefiguredivs.lua index fe57eee022..34e8a80de6 100644 --- a/src/resources/filters/quarto-pre/parsefiguredivs.lua +++ b/src/resources/filters/quarto-pre/parsefiguredivs.lua @@ -126,33 +126,8 @@ local function kable_raw_latex_fixups(content, identifier) return matches, content end -function parse_reftargets() +function parse_floatreftargets() - local function parse_theorem_div(div) - if has_theorem_ref(div) then - local el = div - -- capture then remove name - local name = markdownToInlines(el.attr.attributes["name"]) - if not name or #name == 0 then - name = resolveHeadingCaption(el) - end - el.attr.attributes["name"] = nil - local identifier = el.attr.identifier - -- remove identifier to avoid infinite recursion - el.attr.identifier = "" - return quarto.Theorem { - identifier = identifier, - name = name, - div = div - }, false - end - -- local types = theorem_types - -- local type = refType(el.attr.identifier) - -- local theorem_type = types[type] - -- if theorem_type then - -- end - end - local function parse_float_div(div) process_div_caption_classes(div) local ref = refType(div.identifier) @@ -253,9 +228,6 @@ function parse_reftargets() local layout_classes = attr.classes:filter( function(c) return c:match("^column-") end ) - div.classes = div.classes:filter( - function(c) return not c:match("^column-") end - ) if #layout_classes then attr.classes = attr.classes:filter( function(c) return not layout_classes:includes(c) end) @@ -423,8 +395,6 @@ function parse_reftargets() return parse_float_div(div) elseif isTableDiv(div) then return parse_float_div(div) - elseif is_theorem_div(div) then - return parse_theorem_div(div) end if div.classes:includes("cell") then diff --git a/src/resources/pandoc/datadir/_format.lua b/src/resources/pandoc/datadir/_format.lua index 5f61bc624c..a709357b62 100644 --- a/src/resources/pandoc/datadir/_format.lua +++ b/src/resources/pandoc/datadir/_format.lua @@ -21,7 +21,7 @@ local function isRawHtml(rawEl) end local function isRawLatex(rawEl) - return isRaw(rawEl) and (rawEl.format == "tex" or rawEl.format == "latex" or rawEl.format == "latex-merge" or rawEl.format == "tex-merge") + return isRaw(rawEl) and (rawEl.format == "tex" or rawEl.format == "latex") end -- check for latex output diff --git a/src/resources/projects/website/templates/sidebaritem.ejs b/src/resources/projects/website/templates/sidebaritem.ejs index 7b68805cba..8796ad6689 100644 --- a/src/resources/projects/website/templates/sidebaritem.ejs +++ b/src/resources/projects/website/templates/sidebaritem.ejs @@ -1,7 +1,7 @@ <% if (item.href && item.text && !item.contents) { %> <li class="sidebar-item"> <div class="sidebar-item-container"> - <a href="<%- item.href %>" <%= item.id ? `id="${item.id}" ` : "" %>class="sidebar-item-text sidebar-link<%- item.active ? " active" : "" %>"<%- item.target ? ` target="${item.target}"` : "" %>><% partial('navicon.ejs', { item }) %> <span class="menu-text"><%= item.text %></span></a> + <a href="<%- item.href %>" class="sidebar-item-text sidebar-link<%- item.active ? " active" : "" %>"<%- item.target ? ` target="${item.target}"` : "" %>><% partial('navicon.ejs', { item }) %> <span class="menu-text"><%= item.text %></span></a> </div> </li> <% } else if (item.contents && item.text) { %> @@ -17,11 +17,11 @@ <% if (item.contents.length > 0) { %> <div class="sidebar-item-container"> <% if (item.href) { %> - <a href="<%- item.href %>" <%= item.id ? `id="${item.id}" ` : "" %>class="sidebar-item-text sidebar-link<%- item.active ? " active" : "" %>"<%- item.target ? ` target="${item.target}"` : "" %>><% partial('navicon.ejs', { item }) %> <span class="menu-text"><%= item.text %></span></a> + <a href="<%- item.href %>" class="sidebar-item-text sidebar-link<%- item.active ? " active" : "" %>"<%- item.target ? ` target="${item.target}"` : "" %>><% partial('navicon.ejs', { item }) %> <span class="menu-text"><%= item.text %></span></a> <% } else { %> - <a <%= item.id ? `id="${item.id}" ` : "" %>class="sidebar-item-text sidebar-link text-start<%- isCollapsed ? " collapsed" : "" %>" data-bs-toggle="collapse" data-bs-target="#<%- sectionId %>" aria-expanded="<%- isCollapsed ? "false" : "true" %>"><% partial('navicon.ejs', { item }) %> <span class="menu-text"><%= item.text %></span></a> + <a class="sidebar-item-text sidebar-link text-start<%- isCollapsed ? " collapsed" : "" %>" data-bs-toggle="collapse" data-bs-target="#<%- sectionId %>" aria-expanded="<%- isCollapsed ? "false" : "true" %>"><% partial('navicon.ejs', { item }) %> <span class="menu-text"><%= item.text %></span></a> <% } %> - <a <%= item.id ? `id="${item.id}-toggle" ` : "" %>class="sidebar-item-toggle text-start<%- isCollapsed ? " collapsed" : "" %>" data-bs-toggle="collapse" data-bs-target="#<%- sectionId %>" aria-expanded="<%- isCollapsed ? "false" : "true" %>" aria-label="<%- language['toggle-section'] %>"> + <a class="sidebar-item-toggle text-start<%- isCollapsed ? " collapsed" : "" %>" data-bs-toggle="collapse" data-bs-target="#<%- sectionId %>" aria-expanded="<%- isCollapsed ? "false" : "true" %>" aria-label="<%- language['toggle-section'] %>"> <i class="bi bi-chevron-right ms-2"></i> </a> </div> @@ -31,8 +31,8 @@ <% }) %> </ul> <% } else { %> - <span class="sidebar-item-text sidebar-link text-start" <%- item.id ? `id="${item.id}" ` : "" %>><% partial('navicon.ejs', { item }) %> <span class="menu-text"><%= item.text %></span></span> - <% } %> + <span class="sidebar-item-text sidebar-link text-start"><% partial('navicon.ejs', { item }) %> <span class="menu-text"><%= item.text %></span></span> + <% } %> </li> <% } else if (item.text && item.text.match(/^\-+$/)) { %> diff --git a/version.txt b/version.txt index a0d80da657..fb7a165737 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.4.529 +1.4.528