Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions _extensions/div-anchors/div-anchors.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,30 @@ const theoremLikeClasses = new Set([
"exr",
"exercise",
"proof",
"rem",
"remark",
"sol",
"solution"
]);
const theoremLikePrefixes = [
"thm-",
"lem-",
"cor-",
"prp-",
"cnj-",
"def-",
"exm-",
"exr-",
"rem-",
"sol-"
];
const inlineAnchorSeparator = "\u00A0";
const maxAnchorRetryAttempts = 5;
const anchorRetryDelayMs = 50;

const isTheoremLikeDiv = (div) =>
Array.from(div.classList).some((className) => theoremLikeClasses.has(className));
Array.from(div.classList).some((className) => theoremLikeClasses.has(className)) ||
(div.id && theoremLikePrefixes.some((prefix) => div.id.startsWith(prefix)));

const addTheoremLikeDivAnchors = () => {
for (const theoremDiv of window.document.querySelectorAll("div[id]")) {
Expand Down Expand Up @@ -85,7 +100,7 @@ const moveTheoremDivAnchorsInline = () => {
continue;
}

const theoremTitle = theoremDiv.querySelector(".theorem-title");
const theoremTitle = theoremDiv.querySelector(".theorem-title, .proof-title");
if (!theoremTitle) {
continue;
}
Expand All @@ -107,6 +122,22 @@ const moveTheoremDivAnchorsInline = () => {
}

anchorLink.classList.remove("external");

// If the title ends with whitespace (e.g. Quarto's proof-title ending in ". "),
// trim the trailing whitespace so the non-breaking separator and anchor stay attached
// to the title text, and ensure a trailing space separates the anchor from following content.
let lastTextNode = theoremTitle.lastChild;
while (lastTextNode && lastTextNode.nodeType !== Node.TEXT_NODE && lastTextNode.lastChild) {
lastTextNode = lastTextNode.lastChild;
}
if (lastTextNode && lastTextNode.nodeType === Node.TEXT_NODE && /\s+$/.test(lastTextNode.textContent)) {
lastTextNode.textContent = lastTextNode.textContent.replace(/\s+$/, "");
if (theoremTitle.nextSibling &&
!(theoremTitle.nextSibling.nodeType === Node.TEXT_NODE && /^\s/.test(theoremTitle.nextSibling.textContent))) {
theoremTitle.after(" ");
}
}

theoremTitle.append(inlineAnchorSeparator);
theoremTitle.append(anchorLink);
}
Expand Down
33 changes: 33 additions & 0 deletions _extensions/div-anchors/div-anchors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,39 @@ local theorem_div_classes = {
"exr",
"exercise",
"proof",
"rem",
"remark",
"sol",
"solution"
}

local theorem_id_prefixes = {
"thm-",
"lem-",
"cor-",
"prp-",
"cnj-",
"def-",
"exm-",
"exr-",
"rem-",
"sol-"
}

local function id_is_theorem_like(id)
if not id then
return false
end

for _, prefix in ipairs(theorem_id_prefixes) do
if id:sub(1, #prefix) == prefix then
return true
end
end

return false
end

local function class_is_theorem_like(class)
for _, theorem_class in ipairs(theorem_div_classes) do
if class == theorem_class then
Expand All @@ -31,6 +60,10 @@ local function class_is_theorem_like(class)
end

local function is_theorem_div(div)
if id_is_theorem_like(div.identifier) then
return true
end

for _, class in ipairs(div.classes) do
if class_is_theorem_like(class) then
return true
Expand Down
Loading