From 9ef357424593f86578d15ab492522b7621ae6c15 Mon Sep 17 00:00:00 2001 From: Tavin Cole Date: Tue, 11 Jul 2023 01:08:54 +0200 Subject: [PATCH 1/6] katex \label and \eqref --- plugins/tiddlywiki/katex/styles.tid | 10 ++++++++++ plugins/tiddlywiki/katex/wrapper.js | 28 ++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/plugins/tiddlywiki/katex/styles.tid b/plugins/tiddlywiki/katex/styles.tid index 3e2ddc172..97db5ea8b 100644 --- a/plugins/tiddlywiki/katex/styles.tid +++ b/plugins/tiddlywiki/katex/styles.tid @@ -19,6 +19,16 @@ tags: [[$:/tags/Stylesheet]] counter-reset: katexEqnNo; } +/* Replace \eqref placeholder with generated eqnum */ + +.katex-eqref [data-katex-eqnum] > * { + display: none; +} + +.katex-eqref [data-katex-eqnum]::after { + content: attr(data-katex-eqnum); +} + /* Avoid TW5's max-width: 100% */ .katex svg { diff --git a/plugins/tiddlywiki/katex/wrapper.js b/plugins/tiddlywiki/katex/wrapper.js index ceda68c84..7f4d89726 100644 --- a/plugins/tiddlywiki/katex/wrapper.js +++ b/plugins/tiddlywiki/katex/wrapper.js @@ -16,7 +16,11 @@ var katex = require("$:/plugins/tiddlywiki/katex/katex.min.js"), chemParse = require("$:/plugins/tiddlywiki/katex/mhchem.min.js"), Widget = require("$:/core/modules/widgets/widget.js").widget; -katex.macros = {}; +katex.macros = { + '\\label': '\\htmlId{###1}{}', + '\\eqref': '\\htmlClass{katex-eqref}{(\\href{#####1}{\\htmlData{katex-label=#1}{\\text{#1}}})}', +}; + katex.updateMacros = function() { var tiddlers = $tw.wiki.getTiddlersWithTag("$:/tags/KaTeX/Macro"), regex = /#\d/g, // Remove the arguments like #1#2 @@ -57,6 +61,9 @@ KaTeXWidget.prototype.render = function(parent,nextSibling) { // Render it into a span var span = this.document.createElement("span"), options = {throwOnError: false, displayMode: displayMode, macros: katex.macros}; + options.trust = function (ctx) { + return ctx.command == '\\href' || ctx.command == '\\htmlClass' || ctx.command == '\\htmlData' || ctx.command == '\\htmlId' && ctx.id[0] == '#'; + }; try { if(!this.document.isTiddlyWikiFakeDom) { katex.render(text,span,options); @@ -70,6 +77,23 @@ KaTeXWidget.prototype.render = function(parent,nextSibling) { // Insert it into the DOM parent.insertBefore(span,nextSibling); this.domNodes.push(span); + var tiddlerFrame; + span.querySelectorAll('.katex-eqref [data-katex-label]:not([data-katex-eqnum])').forEach(element => { + // the tiddlyway requires a leading hash to jump inside a tiddler + var katexLabel = this.document.getElementById('#' + element.dataset.katexLabel); + if (!katexLabel) { + element.dataset.katexEqnum = element.dataset.katexLabel + '?'; + return; + } + // everything is a and the span holding a row doesn't even have a class + var katexRow = katexLabel.closest('.vlist > *'); + var katexPos = Array.prototype.indexOf.call(katexRow.parentElement.children, katexRow); // which row has the label + var katexEqn = katexRow.closest('.katex-html').querySelectorAll('.tag .eqn-num')[katexPos]; // which eqn num corresponds + // nodejs doesn't support ||= here ... wtf? + if (!tiddlerFrame) tiddlerFrame = span.closest('.tc-tiddler-frame'); + if (!tiddlerFrame._katex_eqn_num_elements) tiddlerFrame._katex_eqn_num_elements = tiddlerFrame.getElementsByClassName('eqn-num'); + element.dataset.katexEqnum = 1 + Array.prototype.indexOf.call(tiddlerFrame._katex_eqn_num_elements, katexEqn); + }); }; /* @@ -88,7 +112,7 @@ KaTeXWidget.prototype.refresh = function(changedTiddlers) { this.refreshSelf(); return true; } else { - return false; + return false; } }; From e9108f6987d8f714210dc6f0930fbc4ba6a8a2e6 Mon Sep 17 00:00:00 2001 From: Tavin Cole Date: Tue, 11 Jul 2023 12:40:50 +0200 Subject: [PATCH 2/6] make ids unique and use $tw.utils.each w/o arrows --- plugins/tiddlywiki/katex/wrapper.js | 34 +++++++++++++++++------------ 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/plugins/tiddlywiki/katex/wrapper.js b/plugins/tiddlywiki/katex/wrapper.js index 7f4d89726..dca418df5 100644 --- a/plugins/tiddlywiki/katex/wrapper.js +++ b/plugins/tiddlywiki/katex/wrapper.js @@ -17,7 +17,7 @@ var katex = require("$:/plugins/tiddlywiki/katex/katex.min.js"), Widget = require("$:/core/modules/widgets/widget.js").widget; katex.macros = { - '\\label': '\\htmlId{###1}{}', + '\\label': '\\htmlClass{katex-label}{\\htmlId{###1}{}}', '\\eqref': '\\htmlClass{katex-eqref}{(\\href{#####1}{\\htmlData{katex-label=#1}{\\text{#1}}})}', }; @@ -50,6 +50,7 @@ KaTeXWidget.prototype = new Widget(); Render this widget into the DOM */ KaTeXWidget.prototype.render = function(parent,nextSibling) { + var document = this.document; // Housekeeping this.parentDomNode = parent; this.computeAttributes(); @@ -59,13 +60,13 @@ KaTeXWidget.prototype.render = function(parent,nextSibling) { var displayMode = this.getAttribute("displayMode",this.parseTreeNode.displayMode || "false") === "true"; katex.updateMacros(); // Render it into a span - var span = this.document.createElement("span"), + var span = document.createElement("span"), options = {throwOnError: false, displayMode: displayMode, macros: katex.macros}; options.trust = function (ctx) { return ctx.command == '\\href' || ctx.command == '\\htmlClass' || ctx.command == '\\htmlData' || ctx.command == '\\htmlId' && ctx.id[0] == '#'; }; try { - if(!this.document.isTiddlyWikiFakeDom) { + if(!document.isTiddlyWikiFakeDom) { katex.render(text,span,options); } else { span.innerHTML = katex.renderToString(text,options); @@ -74,24 +75,29 @@ KaTeXWidget.prototype.render = function(parent,nextSibling) { span.className = "tc-error"; span.textContent = ex; } + // rewrite identifiers to make them unique + var tiddlerFrame = parent.closest('.tc-tiddler-frame'); + var tiddlerTitle = tiddlerFrame.dataset.tiddlerTitle; + $tw.utils.each(span.querySelectorAll('.katex-label [id^="#"]'), function (element) { + element.id = '#' + tiddlerTitle + element.id; + }); + $tw.utils.each(span.querySelectorAll('.katex-eqref [href^="##"]'), function (element) { + element.href = '##' + tiddlerTitle + element.getAttribute('href').substring(1); + }); // Insert it into the DOM parent.insertBefore(span,nextSibling); this.domNodes.push(span); - var tiddlerFrame; - span.querySelectorAll('.katex-eqref [data-katex-label]:not([data-katex-eqnum])').forEach(element => { - // the tiddlyway requires a leading hash to jump inside a tiddler - var katexLabel = this.document.getElementById('#' + element.dataset.katexLabel); - if (!katexLabel) { - element.dataset.katexEqnum = element.dataset.katexLabel + '?'; - return; - } + // compute data-katex-eqnum attributes + $tw.utils.each(span.querySelectorAll('.katex-eqref [data-katex-label]'), function (element) { + var katexLabel = document.getElementById('#' + tiddlerTitle + '#' + element.dataset.katexLabel); + if (!katexLabel) return; // everything is a and the span holding a row doesn't even have a class var katexRow = katexLabel.closest('.vlist > *'); var katexPos = Array.prototype.indexOf.call(katexRow.parentElement.children, katexRow); // which row has the label var katexEqn = katexRow.closest('.katex-html').querySelectorAll('.tag .eqn-num')[katexPos]; // which eqn num corresponds - // nodejs doesn't support ||= here ... wtf? - if (!tiddlerFrame) tiddlerFrame = span.closest('.tc-tiddler-frame'); - if (!tiddlerFrame._katex_eqn_num_elements) tiddlerFrame._katex_eqn_num_elements = tiddlerFrame.getElementsByClassName('eqn-num'); + if (!tiddlerFrame._katex_eqn_num_elements) { + tiddlerFrame._katex_eqn_num_elements = tiddlerFrame.getElementsByClassName('eqn-num'); + } element.dataset.katexEqnum = 1 + Array.prototype.indexOf.call(tiddlerFrame._katex_eqn_num_elements, katexEqn); }); }; From a9d1ce1674f10b27a6ad98bebbd3d5482fb396fc Mon Sep 17 00:00:00 2001 From: Tavin Cole Date: Tue, 11 Jul 2023 13:14:10 +0200 Subject: [PATCH 3/6] just don't use getElementById --- plugins/tiddlywiki/katex/wrapper.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/tiddlywiki/katex/wrapper.js b/plugins/tiddlywiki/katex/wrapper.js index dca418df5..75b158855 100644 --- a/plugins/tiddlywiki/katex/wrapper.js +++ b/plugins/tiddlywiki/katex/wrapper.js @@ -50,7 +50,6 @@ KaTeXWidget.prototype = new Widget(); Render this widget into the DOM */ KaTeXWidget.prototype.render = function(parent,nextSibling) { - var document = this.document; // Housekeeping this.parentDomNode = parent; this.computeAttributes(); @@ -60,13 +59,13 @@ KaTeXWidget.prototype.render = function(parent,nextSibling) { var displayMode = this.getAttribute("displayMode",this.parseTreeNode.displayMode || "false") === "true"; katex.updateMacros(); // Render it into a span - var span = document.createElement("span"), + var span = this.document.createElement("span"), options = {throwOnError: false, displayMode: displayMode, macros: katex.macros}; options.trust = function (ctx) { return ctx.command == '\\href' || ctx.command == '\\htmlClass' || ctx.command == '\\htmlData' || ctx.command == '\\htmlId' && ctx.id[0] == '#'; }; try { - if(!document.isTiddlyWikiFakeDom) { + if(!this.document.isTiddlyWikiFakeDom) { katex.render(text,span,options); } else { span.innerHTML = katex.renderToString(text,options); @@ -79,6 +78,7 @@ KaTeXWidget.prototype.render = function(parent,nextSibling) { var tiddlerFrame = parent.closest('.tc-tiddler-frame'); var tiddlerTitle = tiddlerFrame.dataset.tiddlerTitle; $tw.utils.each(span.querySelectorAll('.katex-label [id^="#"]'), function (element) { + element.classList.add('katex-label' + element.id); element.id = '#' + tiddlerTitle + element.id; }); $tw.utils.each(span.querySelectorAll('.katex-eqref [href^="##"]'), function (element) { @@ -87,12 +87,13 @@ KaTeXWidget.prototype.render = function(parent,nextSibling) { // Insert it into the DOM parent.insertBefore(span,nextSibling); this.domNodes.push(span); - // compute data-katex-eqnum attributes + // compute data-katex-eqnum attributes on elements made by \eqref $tw.utils.each(span.querySelectorAll('.katex-eqref [data-katex-label]'), function (element) { - var katexLabel = document.getElementById('#' + tiddlerTitle + '#' + element.dataset.katexLabel); - if (!katexLabel) return; + // find a unique matching element made by \label (or quit) + var katexLabels = tiddlerFrame.getElementsByClassName('katex-label#' + element.dataset.katexLabel); + if (katexLabels.length != 1) return; // everything is a and the span holding a row doesn't even have a class - var katexRow = katexLabel.closest('.vlist > *'); + var katexRow = katexLabels[0].closest('.vlist > *'); var katexPos = Array.prototype.indexOf.call(katexRow.parentElement.children, katexRow); // which row has the label var katexEqn = katexRow.closest('.katex-html').querySelectorAll('.tag .eqn-num')[katexPos]; // which eqn num corresponds if (!tiddlerFrame._katex_eqn_num_elements) { From 75d8fbbd0adedf0355086ec939483db569502a7e Mon Sep 17 00:00:00 2001 From: Tavin Cole Date: Tue, 11 Jul 2023 21:28:06 +0200 Subject: [PATCH 4/6] hyperlink cosmetics --- plugins/tiddlywiki/katex/styles.tid | 10 ++++++++++ plugins/tiddlywiki/katex/wrapper.js | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/plugins/tiddlywiki/katex/styles.tid b/plugins/tiddlywiki/katex/styles.tid index 97db5ea8b..bd8ac64ca 100644 --- a/plugins/tiddlywiki/katex/styles.tid +++ b/plugins/tiddlywiki/katex/styles.tid @@ -29,6 +29,16 @@ tags: [[$:/tags/Stylesheet]] content: attr(data-katex-eqnum); } +/* Emulate tiddlylink style but w/o decorating the parentheses */ + +.katex-eqref a { + text-decoration: none; +} + +.katex-eqref a:hover .enclosing { + text-decoration: underline; +} + /* Avoid TW5's max-width: 100% */ .katex svg { diff --git a/plugins/tiddlywiki/katex/wrapper.js b/plugins/tiddlywiki/katex/wrapper.js index 75b158855..0dcb0e2a3 100644 --- a/plugins/tiddlywiki/katex/wrapper.js +++ b/plugins/tiddlywiki/katex/wrapper.js @@ -18,7 +18,7 @@ var katex = require("$:/plugins/tiddlywiki/katex/katex.min.js"), katex.macros = { '\\label': '\\htmlClass{katex-label}{\\htmlId{###1}{}}', - '\\eqref': '\\htmlClass{katex-eqref}{(\\href{#####1}{\\htmlData{katex-label=#1}{\\text{#1}}})}', + '\\eqref': '\\htmlClass{katex-eqref}{\\href{#####1}{(\\htmlData{katex-label=#1}{\\text{#1}})}}', }; katex.updateMacros = function() { From 618af924cb330daa64b8afb997481afce940bc82 Mon Sep 17 00:00:00 2001 From: Tavin Cole Date: Tue, 11 Jul 2023 22:22:36 +0200 Subject: [PATCH 5/6] space phobia --- plugins/tiddlywiki/katex/wrapper.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/tiddlywiki/katex/wrapper.js b/plugins/tiddlywiki/katex/wrapper.js index 0dcb0e2a3..1e26bdf0c 100644 --- a/plugins/tiddlywiki/katex/wrapper.js +++ b/plugins/tiddlywiki/katex/wrapper.js @@ -76,13 +76,14 @@ KaTeXWidget.prototype.render = function(parent,nextSibling) { } // rewrite identifiers to make them unique var tiddlerFrame = parent.closest('.tc-tiddler-frame'); - var tiddlerTitle = tiddlerFrame.dataset.tiddlerTitle; + var safeTitle = tiddlerFrame.dataset.tiddlerTitle.replaceAll(/\s+/g, ''); $tw.utils.each(span.querySelectorAll('.katex-label [id^="#"]'), function (element) { - element.classList.add('katex-label' + element.id); - element.id = '#' + tiddlerTitle + element.id; + var safeId = element.id.replaceAll(/\s+/g, '~'); + element.setAttribute('id', '#' + safeTitle + safeId); + element.classList.add('katex-label' + safeId); }); $tw.utils.each(span.querySelectorAll('.katex-eqref [href^="##"]'), function (element) { - element.href = '##' + tiddlerTitle + element.getAttribute('href').substring(1); + element.href = '##' + safeTitle + element.getAttribute('href').substring(1).replaceAll(/\s+/g, '~'); }); // Insert it into the DOM parent.insertBefore(span,nextSibling); @@ -90,7 +91,7 @@ KaTeXWidget.prototype.render = function(parent,nextSibling) { // compute data-katex-eqnum attributes on elements made by \eqref $tw.utils.each(span.querySelectorAll('.katex-eqref [data-katex-label]'), function (element) { // find a unique matching element made by \label (or quit) - var katexLabels = tiddlerFrame.getElementsByClassName('katex-label#' + element.dataset.katexLabel); + var katexLabels = tiddlerFrame.getElementsByClassName('katex-label#' + element.dataset.katexLabel.replaceAll(/\s+/g, '~')); if (katexLabels.length != 1) return; // everything is a and the span holding a row doesn't even have a class var katexRow = katexLabels[0].closest('.vlist > *'); From c6d64311c1582a88ee6a6c4af849e1dafcd94b92 Mon Sep 17 00:00:00 2001 From: Tavin Cole Date: Fri, 14 Jul 2023 11:27:49 +0200 Subject: [PATCH 6/6] lost case that \eqref precedes \label --- plugins/tiddlywiki/katex/wrapper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tiddlywiki/katex/wrapper.js b/plugins/tiddlywiki/katex/wrapper.js index 1e26bdf0c..f315f975b 100644 --- a/plugins/tiddlywiki/katex/wrapper.js +++ b/plugins/tiddlywiki/katex/wrapper.js @@ -89,7 +89,7 @@ KaTeXWidget.prototype.render = function(parent,nextSibling) { parent.insertBefore(span,nextSibling); this.domNodes.push(span); // compute data-katex-eqnum attributes on elements made by \eqref - $tw.utils.each(span.querySelectorAll('.katex-eqref [data-katex-label]'), function (element) { + $tw.utils.each(tiddlerFrame.querySelectorAll('.katex-eqref [data-katex-label]:not([data-katex-eqnum])'), function (element) { // find a unique matching element made by \label (or quit) var katexLabels = tiddlerFrame.getElementsByClassName('katex-label#' + element.dataset.katexLabel.replaceAll(/\s+/g, '~')); if (katexLabels.length != 1) return;