mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 03:08:40 +00:00
fix(auto-render): concatenate content of successive text nodes (#3422)
* fix(auto-render): concatenate text nodes Concatenate successive text nodes to prevent auto-render from skipping math input when browsers split text nodes with long textContent. * Remove siblings only when math found Only remove siblings when math expressions were found to prevent removal of nodes that do not contain math. * Skip siblings if they do not contain math * Fixed typo in comments * Added first tests for large test nodes * Expanded testing to compare renderMathInElement with renderMathInText * Simplified text node test * Change description of test * Update contrib/auto-render/auto-render.js Co-authored-by: marcoesters <marco.esters@duke.edu> Co-authored-by: ylemkimon <y@ylem.kim>
This commit is contained in:
@@ -55,10 +55,29 @@ const renderElem = function(elem, optionsCopy) {
|
||||
const childNode = elem.childNodes[i];
|
||||
if (childNode.nodeType === 3) {
|
||||
// Text node
|
||||
const frag = renderMathInText(childNode.textContent, optionsCopy);
|
||||
// Concatenate all sibling text nodes.
|
||||
// Webkit browsers split very large text nodes into smaller ones,
|
||||
// so the delimiters may be split across different nodes.
|
||||
let textContentConcat = childNode.textContent;
|
||||
let sibling = childNode.nextSibling;
|
||||
let nSiblings = 0;
|
||||
while (sibling && (sibling.nodeType === Node.TEXT_NODE)) {
|
||||
textContentConcat += sibling.textContent;
|
||||
sibling = sibling.nextSibling;
|
||||
nSiblings++;
|
||||
}
|
||||
const frag = renderMathInText(textContentConcat, optionsCopy);
|
||||
if (frag) {
|
||||
// Remove extra text nodes
|
||||
for (let j = 0; j < nSiblings; j++) {
|
||||
childNode.nextSibling.remove();
|
||||
}
|
||||
i += frag.childNodes.length - 1;
|
||||
elem.replaceChild(frag, childNode);
|
||||
} else {
|
||||
// If the concatenated text does not contain math
|
||||
// the siblings will not either
|
||||
i += nSiblings;
|
||||
}
|
||||
} else if (childNode.nodeType === 1) {
|
||||
// Element node
|
||||
|
@@ -322,3 +322,42 @@ describe("Pre-process callback", function() {
|
||||
expect(el1.innerHTML).toEqual(el2.innerHTML);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Parse adjacent text nodes", function() {
|
||||
it("parse adjacent text nodes with math", function() {
|
||||
const textNodes = ['\\[',
|
||||
'x^2 + y^2 = r^2',
|
||||
'\\]'];
|
||||
const el = document.createElement('div');
|
||||
for (let i = 0; i < textNodes.length; i++) {
|
||||
const txt = document.createTextNode(textNodes[i]);
|
||||
el.appendChild(txt);
|
||||
}
|
||||
const el2 = document.createElement('div');
|
||||
const txt = document.createTextNode(textNodes.join(''));
|
||||
el2.appendChild(txt);
|
||||
const delimiters = [{left: "\\[", right: "\\]", display: true}];
|
||||
renderMathInElement(el, {delimiters});
|
||||
renderMathInElement(el2, {delimiters});
|
||||
expect(el).toStrictEqual(el2);
|
||||
});
|
||||
|
||||
it("parse adjacent text nodes without math", function() {
|
||||
const textNodes = ['Lorem ipsum dolor',
|
||||
'sit amet',
|
||||
'consectetur adipiscing elit'];
|
||||
const el = document.createElement('div');
|
||||
for (let i = 0; i < textNodes.length; i++) {
|
||||
const txt = document.createTextNode(textNodes[i]);
|
||||
el.appendChild(txt);
|
||||
}
|
||||
const el2 = document.createElement('div');
|
||||
for (let i = 0; i < textNodes.length; i++) {
|
||||
const txt = document.createTextNode(textNodes[i]);
|
||||
el2.appendChild(txt);
|
||||
}
|
||||
const delimiters = [{left: "\\[", right: "\\]", display: true}];
|
||||
renderMathInElement(el, {delimiters});
|
||||
expect(el).toStrictEqual(el2);
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user