diff --git a/spec/assets/mathml_cleanup.js b/spec/assets/mathml_cleanup.js new file mode 100644 index 000000000..33075c56d --- /dev/null +++ b/spec/assets/mathml_cleanup.js @@ -0,0 +1,69 @@ +(() => { + // Fix 1: explicitly set "stretchy=false" for parentheses that don't need to, + // so that chrome doesn't mess up the kerning/horizontal padding + // Related bug report: https://issues.chromium.org/issues/40256468 + function isBig(node) { + const selector = "mfrac,munder,mover,munderover,mtable,msup,msub,msubsup"; + return !!node.querySelector(selector) || node.matches(selector) + } + + const open = "([{⌊⌈"; + const close = ")]}⌋⌉"; + for (let mrow of document.querySelectorAll("math mrow")) { + let stack = []; + for (let child of mrow.children) { + if (child.tagName == "mo" && open.indexOf(child.textContent) != -1) { + stack.push(child, false); + } else if (child.tagName == "mo" && close.indexOf(child.textContent) != -1) { + // We intentionally don't match parens, because of things like half open intervals and round + if (!stack.length) continue; + let big = stack.pop(); + if (!big) { + child.setAttribute("stretchy", "false"); + stack.pop().setAttribute("stretchy", "false"); + } else { + stack.pop(); + } + if (stack.length) { + stack.push(stack.pop() || big); + } + } else { + if (!stack.length) continue; + stack.push(stack.pop() || isBig(child)); + } + } + + let big = false; + while (stack.length) { + big = stack.pop() || big; + if (!big) { + stack.pop().setAttribute("stretchy", "false"); + } + } + } + + + // Fix 2: Replace the combining accent for `dash` (code point 0x0305) with + // the overline character (code point 0x203E), for two reasons: + // - So that nested overlines render properly stretched in Firefox + // - So that chrome renders it centrally and not offset to the left + function isOverline(c) { + return c != "" && "\u0305\u203e\u00af".indexOf(c) != -1; + } + for (let elem of document.body.querySelectorAll("mover mo:last-child")) { + if (isOverline(elem.textContent)) { + elem.textContent = "\u203e"; + } + } + + + // Fix 3: Replace overlines with a border-top CSS rule for browsers that + // do not stretch the top line properly. (e.g. chromium (and forks like Brave)) + for (let elem of document.body.querySelectorAll("mover mo:last-child")) { + if (isOverline(elem.textContent) && elem.getBoundingClientRect().width < elem.parentElement.getBoundingClientRect().width * 0.9) { + elem.style.display = "none"; + elem.parentElement.style.borderTop = "0.06em solid currentColor"; + elem.parentElement.style.paddingTop = "0.12em"; + } + } +})() diff --git a/spec/assets/sidenotes.js b/spec/assets/sidenotes.js index 3e4bcbc99..50c5898e2 100644 --- a/spec/assets/sidenotes.js +++ b/spec/assets/sidenotes.js @@ -21,7 +21,17 @@ // incomplete selector, but could be extended if anything becomes relevant, ever aside.querySelectorAll("a, summary, iframe, [tabindex]").forEach(el => el.setAttribute("tabindex", "-1")); - sup.after(aside); + let container = null; + for (let parent = sup; parent.tagName != "MAIN"; parent = parent.parentElement) { + if (parent.matches("figure,math,table,pre,dl")) container = parent; + } + if (container !== null) { + // before so we align along the top of the container instead of from the end + container.before(aside); + } else { + // after for the common case, since it makes more semantic sense + sup.after(aside); + } } } })(); diff --git a/spec/assets/style.css b/spec/assets/style.css index 75a27dbc7..48372bcc4 100644 --- a/spec/assets/style.css +++ b/spec/assets/style.css @@ -470,7 +470,7 @@ figure[data-kind="highlight"] figcaption { /* Colors are provided through typst */ padding: 0.4em 1em; - font-weight: 600; + font-weight: bold; display: block; text-align: center; } @@ -618,7 +618,6 @@ math { } math[display="block"] { - display: block; text-align: center; font-size: 1.12em; margin: 1.2em 0; diff --git a/spec/bundle.typ b/spec/bundle.typ index 742ed452a..271e26cab 100644 --- a/spec/bundle.typ +++ b/spec/bundle.typ @@ -106,9 +106,9 @@ html.link(href: "/style.css", rel: "stylesheet") html.link(href: "/fonts.css", rel: "stylesheet") html.link(href: "/sidenotes.css", rel: "stylesheet") - html.script(src: "/sidenotes.js", defer: true) + html.script(src: "/deferred.js", defer: true) html.div(class: "headerButtons") - html.script(src: "/themetoggle.js") + html.script(src: "/instant.js") html.header(title(link(, vistitle))) html.main(mainbody) nav(filename) @@ -116,11 +116,9 @@ })#label("doc:"+filename) ] -#asset("/style.css", read("/assets/style.css")) -#asset("/fonts.css", read("/assets/fonts.css")) -#asset("/sidenotes.css", read("/assets/sidenotes.css")) -#asset("/sidenotes.js", read("/assets/sidenotes.js")) -#asset("/themetoggle.js", read("/assets/themetoggle.js")) +#asset("/style.css", read("/assets/style.css") + read("/assets/fonts.css") + read("/assets/sidenotes.css")) +#asset("/deferred.js", read("/assets/sidenotes.js") + read("/assets/mathml_cleanup.js")) +#asset("/instant.js", read("/assets/themetoggle.js")) // Bundled fonts #for f in ( diff --git a/spec/meta.typ b/spec/meta.typ index 68fe24ba4..2b6672b48 100644 --- a/spec/meta.typ +++ b/spec/meta.typ @@ -109,7 +109,11 @@ width: 100% + 1em, fill: highlights.at(it.kind).at(1), stroke: rgb("#d7d5cd"), - align(center, strong(text(fill: highlights.at(it.kind).at(2), cap))) + sticky: true, + { + set text(weight: "bold") + align(center, cap) + } ) block(inset: (left: 1em, right: 1em, bottom: 1em), stroke: rgb("#d7d5cd"), breakable: false, align(left, it)) }