Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(auto-render): add option to ignore escaped special characters outside of LaTeX math mode (#437) #3798

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 17 additions & 2 deletions contrib/auto-render/auto-render.js
Expand Up @@ -7,18 +7,30 @@ import splitAtDelimiters from "./splitAtDelimiters";
* API, we should copy it before mutating.
*/
const renderMathInText = function(text, optionsCopy) {
const data = splitAtDelimiters(text, optionsCopy.delimiters);
const data = splitAtDelimiters(text, optionsCopy.delimiters,
optionsCopy.supportEscapedSpecialCharsInText);
if (data.length === 1 && data[0].type === 'text') {
// There is no formula in the text.
// Let's return null which means there is no need to replace
// the current text node with a new one.
return null;
if (!optionsCopy.supportEscapedSpecialCharsInText) {
return null;
}
}

const fragment = document.createDocumentFragment();

for (let i = 0; i < data.length; i++) {
if (data[i].type === "text") {
if (optionsCopy.supportEscapedSpecialCharsInText) {
data[i].data = data[i].data.replace(/\\\$/g, '$');
data[i].data = data[i].data.replace(/\\%/g, '%');
data[i].data = data[i].data.replace(/\\_/g, '_');
data[i].data = data[i].data.replace(/\\&/g, '&');
data[i].data = data[i].data.replace(/\\#/g, '#');
data[i].data = data[i].data.replace(/\\{/g, '{');
data[i].data = data[i].data.replace(/\\}/g, '}');
}
fragment.appendChild(document.createTextNode(data[i].data));
} else {
const span = document.createElement("span");
Expand Down Expand Up @@ -136,6 +148,9 @@ const renderMathInElement = function(elem, options) {
// math elements within a single call to `renderMathInElement`.
optionsCopy.macros = optionsCopy.macros || {};

optionsCopy.supportEscapedSpecialCharsInText =
optionsCopy.supportEscapedSpecialCharsInText || false;

renderElem(elem, optionsCopy);
};

Expand Down
31 changes: 25 additions & 6 deletions contrib/auto-render/splitAtDelimiters.js
Expand Up @@ -27,19 +27,38 @@ const findEndOfMath = function(delimiter, text, startIndex) {
return -1;
};

const escapeRegex = function(string) {
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
const escapeRegex = function(string, supportEscapedSpecialCharsInText) {
if (supportEscapedSpecialCharsInText) {
if (string === "$") {
/* negative lookbehind to find any dollar not preceded by a
backslash */
return "(?<!\\\\)\\$";
} else if (string === "(") {
/* negative lookbehind to find any parenthesis not preceded by a
backslash */
return "(?<!\\\\)\\(";
} else if (string === "\\(") {
return "\\\\\\(";
} else if (string === "\\$") {
return "\\\\\\$";
} else {
return string.replace(/[-/\\^$*+?.)|[\]{}]/g, "\\$&");
}
} else {
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
}
};

const amsRegex = /^\\begin{/;

const splitAtDelimiters = function(text, delimiters) {
const splitAtDelimiters = function(text, delimiters,
supportEscapedSpecialCharsInText) {
let index;
const data = [];

const regexLeft = new RegExp(
"(" + delimiters.map((x) => escapeRegex(x.left)).join("|") + ")"
);
const regexLeft = new RegExp("(" + delimiters.map((x) =>
escapeRegex(x.left, supportEscapedSpecialCharsInText),
).join("|") + ")");

while (true) {
index = text.search(regexLeft);
Expand Down