mathpix-markdown-it
Version:
Mathpix-markdown-it is an open source implementation of the mathpix-markdown spec written in Typescript. It relies on the following open source libraries: MathJax v3 (to render math with SVGs), markdown-it (for standard Markdown parsing)
832 lines • 27.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyAttrToInlineMath = exports.applyAttrToMathml = exports.isMathInText = exports.addAttributesToParentToken = exports.addAttributesToParentTokenByType = exports.getSpacesFromLeft = exports.canonicalMathPositions = exports.canonicalMath = exports.findOpenCloseTagsMathEnvironment = exports.findOpenCloseTags = exports.findBackTick = exports.attrSetToBegin = exports.uid = exports.arrayResortFromElement = exports.arrayDelElement = exports.arraysCompare = exports.includesMultiMathTag = exports.includesMultiMathBeginTag = exports.includesSimpleMathTag = exports.isNotBackticked = exports.getLatexTextWidth = exports.getWidthFromDocument = exports.getTextWidth = exports.beginTag = exports.endTag = void 0;
var tslib_1 = require("tslib");
var consts_1 = require("./common/consts");
var endTag = function (arg, shouldBeFirst) {
if (shouldBeFirst === void 0) { shouldBeFirst = false; }
try {
if (arg.indexOf('*') !== -1) {
/** The '*' character must be escaped in a regular expression */
arg = arg.replace(/\*/, '\\*');
}
return shouldBeFirst
? new RegExp('^\\\\end\s{0,}\{(' + arg + ')\}')
: new RegExp('\\\\end\s{0,}\{(' + arg + ')\}');
}
catch (e) {
return null;
}
};
exports.endTag = endTag;
var beginTag = function (arg, shouldBeFirst) {
if (shouldBeFirst === void 0) { shouldBeFirst = false; }
try {
if (arg.indexOf('*') !== -1) {
/** The '*' character must be escaped in a regular expression */
arg = arg.replace(/\*/, '\\*');
}
return shouldBeFirst
? new RegExp('^\\\\begin\s{0,}\{(' + arg + ')\}')
: new RegExp('\\\\begin\s{0,}\{(' + arg + ')\}');
}
catch (e) {
return null;
}
};
exports.beginTag = beginTag;
var getTextWidth = function () {
var el_container = document ? document.getElementById('container-ruller') : null;
return el_container ? el_container.offsetWidth : 800;
};
exports.getTextWidth = getTextWidth;
var getWidthFromDocument = function (cwidth) {
if (cwidth === void 0) { cwidth = 1200; }
try {
var el_container = document.getElementById('container-ruller');
return el_container ? el_container.offsetWidth : 1200;
}
catch (e) {
return cwidth;
}
};
exports.getWidthFromDocument = getWidthFromDocument;
var getLatexTextWidth = function (strWidth, cWidth) {
if (cWidth === void 0) { cWidth = 1200; }
var res = '';
try {
var reTextWidthTag = /\\textwidth/;
var match = strWidth.match(reTextWidthTag);
if (!match) {
return res;
}
cWidth = (0, exports.getWidthFromDocument)(cWidth);
var sWidth = strWidth.slice(0, match.index);
sWidth = sWidth ? sWidth.trim() : '';
var dWidth = parseFloat(sWidth);
dWidth = !dWidth ? 1 : dWidth;
res = "width: ".concat(dWidth * cWidth, "px; ");
return res;
}
catch (e) {
return res;
}
};
exports.getLatexTextWidth = getLatexTextWidth;
var isNotBackticked = function (str, tag) {
var pos = 0, max = str.length, ch, escapes = 0, backTicked = false, lastBackTick = 0;
ch = str.charCodeAt(pos);
var st = '';
var st2 = '';
var isIgnore = false;
while (pos < max) {
if (ch === 0x60 /* ` */) {
if (backTicked) {
backTicked = false;
lastBackTick = pos;
if (st.includes(tag)) {
isIgnore = true;
st = '';
}
}
else if (escapes % 2 === 0) {
backTicked = true;
lastBackTick = pos;
}
}
else {
if (backTicked) {
// isIgnore = false;
st += str[pos];
}
else {
st2 += str[pos];
}
}
if (ch === 0x5c /* \ */
&& (pos + 1 < max && str.charCodeAt(pos + 1) === 0x60)) {
escapes++;
}
else {
escapes = 0;
}
pos++;
// If there was an un-closed backtick, go back to just after
// the last backtick, but as if it was a normal character
if (pos === max && backTicked) {
backTicked = false;
pos = lastBackTick + 1;
}
ch = str.charCodeAt(pos);
}
return !isIgnore || st2.includes(tag);
};
exports.isNotBackticked = isNotBackticked;
var includesSimpleMathTag = function (str, tag) {
if (tag === void 0) { tag = '$$'; }
return str.includes(tag) && (0, exports.isNotBackticked)(str, tag);
};
exports.includesSimpleMathTag = includesSimpleMathTag;
var includesMultiMathBeginTag = function (str, tag) {
var result = null;
try {
if (!tag.test(str)) {
return result;
}
var match = void 0;
for (var i = 0; i < str.length; i++) {
result = null;
var str1 = i < str.length ? str.slice(i) : '';
match = str1 ? str1.match(tag) : null;
if (!match) {
break;
}
if ((0, exports.isNotBackticked)(str, match[0])) {
result = null;
if (match[0] === "\\[" || match[0] === "\[") {
result = /\\\]/;
}
else if (match[0] === "\\(" || match[0] === "\(") {
result = /\\\)/;
}
else if (match[1]) {
result = (0, exports.endTag)(match[1]);
}
break;
}
else {
i += match.index + match[0].length - 1;
}
}
return result;
}
catch (e) {
return null;
}
};
exports.includesMultiMathBeginTag = includesMultiMathBeginTag;
var includesMultiMathTag = function (str, tag) {
var result = false;
if (!tag.test(str)) {
return result;
}
var match;
for (var i = 0; i < str.length; i++) {
result = false;
var str1 = i < str.length ? str.slice(i) : '';
match = str1 ? str1.match(tag) : null;
if (!match) {
break;
}
if ((0, exports.isNotBackticked)(str, match[0])) {
result = true;
break;
}
else {
i += match.index + match[0].length;
}
}
return result;
};
exports.includesMultiMathTag = includesMultiMathTag;
var arraysCompare = function (a1, a2) {
if (a1.length < 2 || a2.length < 2) {
return false;
}
if (a1.length == a2.length) {
return a1.every(function (v, i) { return v === a2[i]; });
}
else {
if (a1.length < a2.length) {
return a1.filter(function (item) { return a2.indexOf(item) === -1; }).length === 0;
}
else {
return a2.filter(function (item) { return a1.indexOf(item) === -1; }).length === 0;
// return a2.every((v,i)=>v === a1[i])
}
}
// return a1.length == a2.length && a1.every((v,i)=>v === a2[i])
};
exports.arraysCompare = arraysCompare;
var arrayDelElement = function (arr, el) {
var index = arr.indexOf(el);
if (index === -1) {
return arr;
}
return arr.splice(index, 1);
};
exports.arrayDelElement = arrayDelElement;
var arrayResortFromElement = function (arr, el, notReverse, nextEl) {
if (notReverse === void 0) { notReverse = false; }
if (nextEl === void 0) { nextEl = -1; }
var index = arr.indexOf(el);
var arrN1 = tslib_1.__spreadArray([], tslib_1.__read(arr), false);
var arrN2 = tslib_1.__spreadArray([], tslib_1.__read(arr), false);
if (index < arrN1.length - 1) {
if (notReverse) {
var arr1 = arrN1.splice(0, index);
var arr2 = arrN2.splice(index + 1);
if (nextEl !== -1) {
if (arr1.indexOf(nextEl) !== -1) {
return [el].concat(arr1.reverse(), arr2.reverse());
}
if (arr2.indexOf(nextEl) !== -1) {
return [el].concat(arr2, arr1);
}
}
return [el].concat(arr1.reverse(), arr2.reverse());
// return [el].concat(arr2, arr1)
}
else {
var arr1 = arrN1.splice(0, index);
var arr2 = arrN2.splice(index + 1);
return [el].concat(arr1.reverse(), arr2.reverse());
}
}
else {
var arr1 = arrN1.splice(0, index);
if (notReverse) {
return [el].concat(arr1);
}
else {
return [el].concat(arr1.reverse());
}
}
};
exports.arrayResortFromElement = arrayResortFromElement;
var uid = function () {
return Date.now().toString(36)
+ Math.random().toString(36).substr(2);
};
exports.uid = uid;
/** Add attribute to begin of attribute list */
var attrSetToBegin = function (attrs, name, value) {
var index = (attrs === null || attrs === void 0 ? void 0 : attrs.length)
? attrs.findIndex(function (item) { return item[0] === name; })
: -1;
if (index < 0) {
attrs.unshift([name, value]);
}
else {
attrs[index] = [name, value];
}
};
exports.attrSetToBegin = attrSetToBegin;
var findBackTick = function (posStart, str, pending) {
if (pending === void 0) { pending = ''; }
var pos = posStart;
var matchStart, matchEnd;
var max = str.length;
var ch = str.charCodeAt(pos);
if (ch !== 0x60 /* ` */) {
return null;
}
var start = pos;
pos++;
while (pos < max && str.charCodeAt(pos) === 0x60 /* ` */) {
pos++;
}
var marker = str.slice(start, pos);
if (pending === marker) {
return {
marker: marker,
posEnd: pos
};
}
matchStart = matchEnd = pos;
while ((matchStart = str.indexOf('`', matchEnd)) !== -1) {
matchEnd = matchStart + 1;
while (matchEnd < max && str.charCodeAt(matchEnd) === 0x60 /* ` */) {
matchEnd++;
}
if (matchEnd - matchStart === marker.length) {
var content = str.slice(pos, matchStart)
.replace(/\n/g, ' ')
.replace(/^ (.+) $/, '$1');
var posEnd_1 = matchEnd;
return {
marker: marker,
content: content,
posEnd: posEnd_1
};
}
}
var posEnd = posStart + marker.length;
return {
marker: marker,
posEnd: posEnd,
pending: marker
};
};
exports.findBackTick = findBackTick;
var findOpenCloseTags = function (str, tagOpen, tagClose, pendingBackTick, noBreakBackTick) {
if (pendingBackTick === void 0) { pendingBackTick = ''; }
if (noBreakBackTick === void 0) { noBreakBackTick = false; }
var max = str.length;
var arrOpen = [];
var arrClose = [];
var pending = '';
var posStart = 0;
if (pendingBackTick) {
var index = str.indexOf(pendingBackTick);
if (index === -1) {
return {
arrOpen: arrOpen,
arrClose: arrClose,
pending: pendingBackTick
};
}
posStart = index + pendingBackTick.length;
pendingBackTick = '';
}
for (var pos = posStart; pos < max; pos++) {
var ch = str.charCodeAt(pos);
if (ch === 0x60 /* ` */) {
var data = (0, exports.findBackTick)(pos, str, pendingBackTick);
if (data) {
if (data.pending) {
pending = data.pending;
if (!noBreakBackTick) {
break;
}
}
pos = noBreakBackTick ? data.posEnd - 1 : data.posEnd;
continue;
}
}
if (str.charCodeAt(pos) === 0x5c /* \ */) {
var match = str
.slice(pos)
.match(tagOpen);
if (match) {
var posEnd = pos + match[0].length;
arrOpen.push({
posStart: pos + match.index,
content: match[0],
posEnd: posEnd
});
pos = posEnd;
}
else {
if (!tagClose) {
continue;
}
match = str
.slice(pos)
.match(tagClose);
if (match) {
var posEnd = pos + match[0].length;
arrClose.push({
posStart: pos + match.index,
content: match[0],
posEnd: posEnd
});
pos = posEnd < max ? posEnd - 1 : posEnd;
}
}
}
}
return {
arrOpen: arrOpen,
arrClose: arrClose,
pending: pending
};
};
exports.findOpenCloseTags = findOpenCloseTags;
/** To search for start and end markers in the entire string.
* The search stops if the end of the string is reached
* or if the number of end markers is equal to the number of start markers (for inline parser only isInline = true)
* */
var findOpenCloseTagsMathEnvironment = function (str, tagOpen, tagClose, isInline) {
if (isInline === void 0) { isInline = true; }
var max = str.length;
var arrOpen = [];
var arrClose = [];
var posStart = 0;
for (var pos = posStart; pos < max; pos++) {
if (str.charCodeAt(pos) === 0x5c /* \ */) {
var match = str
.slice(pos)
.match(tagOpen);
if (match) {
var posEnd = pos + match[0].length;
arrOpen.push({
posStart: pos + match.index,
content: match[0],
posEnd: posEnd
});
pos = posEnd - 1;
}
else {
match = str
.slice(pos)
.match(tagClose);
if (match) {
var posEnd = pos + match[0].length;
arrClose.push({
posStart: pos + match.index,
content: match[0],
posEnd: posEnd
});
if (isInline && arrClose.length === (arrOpen === null || arrOpen === void 0 ? void 0 : arrOpen.length)) {
break;
}
pos = posEnd - 1;
}
}
}
}
return {
arrOpen: arrOpen,
arrClose: arrClose,
};
};
exports.findOpenCloseTagsMathEnvironment = findOpenCloseTagsMathEnvironment;
/**
* @return {string} Get and return a control-sequence name
*/
var GetCS = function (str, i) {
var CS = str.slice(i).match(/^([a-z]+|.) ?/i);
if (CS) {
i += CS[1].length;
return {
cs: CS[1],
next: i
};
}
else {
i++;
return {
cs: ' ',
next: i
};
}
};
var getDigit = function (str, i) {
var CS = str.slice(i).match(/^([0-9.,]+|) ?/i);
if (CS) {
i += CS[1].length;
return {
cs: CS[1],
next: i
};
}
else {
i++;
return {
cs: '',
next: i
};
}
};
var getLetter = function (str, i) {
var CS = str.slice(i).match(/^([a-z]+|) ?/i);
if (CS) {
i += CS[1].length;
return {
cs: CS[1],
next: i
};
}
else {
i++;
return {
cs: '',
next: i
};
}
};
var nextIsSpace = function (str, i) {
return str.charAt(i).match(/\s/);
};
// const GetNext = (str, i) => {
// while (nextIsSpace(str, i)) {
// i++;
// }
// return {
// char: str.charAt(i),
// next: i
// };
// };
var canonicalMath = function (math) {
if (!math || !math.trim()) {
return [];
}
var arr = [];
var i = 0;
var c;
var n;
while (i < math.length) {
if (nextIsSpace(math, i)) {
i++;
}
c = math.charAt(i++);
n = c.charCodeAt(0);
if (n >= 0xD800 && n < 0xDC00) {
c += math.charAt(i++);
}
/** command */
if (/^\\/.test(c)) {
var _a = GetCS(math, i), cs = _a.cs, next = _a.next;
i = next;
arr.push(c + cs);
continue;
}
/** numbers */
if (/[0-9.,]/.test(c)) {
var _b = getDigit(math, i), cs = _b.cs, next = _b.next;
i = next;
arr.push(c + cs);
continue;
}
/** letters */
if (/[a-z]/i.test(c)) {
var _c = getLetter(math, i), cs = _c.cs, next = _c.next;
i = next;
arr.push(c + cs);
continue;
}
arr.push(c);
}
return arr;
};
exports.canonicalMath = canonicalMath;
var canonicalMathPositions = function (math) {
if (!math || !math.trim()) {
return [];
}
var arr = [];
var i = 0;
var c;
var n;
var startPos = 0;
var isTextBlock = false;
var textBlockOpen = 0;
var fontControl = null;
var braceOpen = 0;
var braceOpenFont = 0;
var parentCommand = '';
var braceOpenParentCommand = 0;
while (i < math.length) {
if (nextIsSpace(math, i)) {
i++;
}
startPos = i;
c = math.charAt(i++);
n = c.charCodeAt(0);
if (n >= 0xD800 && n < 0xDC00) {
c += math.charAt(i++);
}
/** command */
if (/^\\/.test(c)) {
if (braceOpen === braceOpenParentCommand) {
parentCommand = '';
}
var _a = GetCS(math, i), cs = _a.cs, next = _a.next;
var content = c + cs;
if (isTextBlock && textBlockOpen === 0) {
isTextBlock = false;
}
if (!isTextBlock) {
arr.push({
content: content,
contentSlice: math.slice(startPos, next),
type: 'command',
positions: {
start: startPos,
end: next
},
fontControl: fontControl,
parentCommand: parentCommand
});
}
i = next;
if (braceOpen === braceOpenFont && (fontControl === null || fontControl === void 0 ? void 0 : fontControl.command) === '\\Bbb') {
fontControl = null;
}
/** Text control */
if (['\\text',
'\\textsf', '\\textit', '\\textbf', '\\textrm', '\\texttt'].includes(content)) {
isTextBlock = true;
}
/** Font control */
if (['\\mit', '\\rm', '\\oldstyle', '\\cal', '\\it', '\\bf', '\\bbFont', '\\scr', '\\frak', '\\sf', '\\tt',
'\\Bbb', '\\emph'].includes(content)) {
fontControl = {
command: content,
includeIntoBraces: ['\\Bbb'].includes(content)
};
braceOpenFont = braceOpen;
}
braceOpenParentCommand = braceOpen;
parentCommand = content;
continue;
}
/** numbers */
if (/[0-9.,]/.test(c)) {
if (braceOpen === braceOpenParentCommand) {
parentCommand = '';
}
var _b = getDigit(math, i), cs = _b.cs, next = _b.next;
if (isTextBlock && textBlockOpen === 0) {
isTextBlock = false;
}
if (!isTextBlock) {
arr.push({
content: c + cs,
contentSlice: math.slice(startPos, next),
type: 'numbers',
positions: {
start: startPos,
end: next
},
fontControl: fontControl,
parentCommand: parentCommand
});
}
i = next;
if (braceOpen === braceOpenFont && (fontControl === null || fontControl === void 0 ? void 0 : fontControl.command) === '\\Bbb') {
fontControl = null;
}
continue;
}
/** letters */
if (/[a-z]/i.test(c)) {
if (braceOpen === braceOpenParentCommand) {
parentCommand = '';
}
var _c = getLetter(math, i), cs = _c.cs, next = _c.next;
if (isTextBlock && textBlockOpen === 0) {
isTextBlock = false;
}
if (!isTextBlock) {
arr.push({
content: c + cs,
contentSlice: math.slice(startPos, next),
type: 'letters',
positions: {
start: startPos,
end: next
},
fontControl: fontControl,
parentCommand: parentCommand
});
}
i = next;
if (braceOpen === braceOpenFont && (fontControl === null || fontControl === void 0 ? void 0 : fontControl.command) === '\\Bbb') {
fontControl = null;
}
continue;
}
if (c !== '{' && c !== '}') {
if (braceOpen === braceOpenParentCommand) {
parentCommand = '';
}
if (braceOpen === braceOpenFont && (fontControl === null || fontControl === void 0 ? void 0 : fontControl.command) === '\\Bbb') {
fontControl = null;
}
}
if (c === '{') {
braceOpen++;
}
if (c === '}') {
if (braceOpen === braceOpenFont) {
fontControl = null;
}
braceOpen--;
if (braceOpen === braceOpenParentCommand) {
parentCommand = '';
}
braceOpen--;
}
if (isTextBlock) {
if (c === '{') {
textBlockOpen++;
}
if (c === '}') {
textBlockOpen--;
}
if (textBlockOpen === 0) {
var lastItem = arr[arr.length - 1];
lastItem.positions.end = i;
lastItem.content = math.slice(lastItem.positions.start, lastItem.positions.end);
lastItem.contentSlice = math.slice(lastItem.positions.start, lastItem.positions.end);
isTextBlock = false;
}
}
else {
arr.push({
content: c,
contentSlice: math.slice(startPos, startPos + c.length),
type: 'other',
positions: {
start: startPos,
end: i
},
fontControl: fontControl,
parentCommand: parentCommand
});
}
}
return arr;
};
exports.canonicalMathPositions = canonicalMathPositions;
var getSpacesFromLeft = function (str) {
var strTrimLeft = str ? str.trimLeft() : '';
return str ? str.length - strTrimLeft.length : 0;
};
exports.getSpacesFromLeft = getSpacesFromLeft;
/** add additional attributes to the parent token */
var addAttributesToParentTokenByType = function (parentToken, token, tokenType, attrs, reTagFind) {
var _a;
if (reTagFind === void 0) { reTagFind = null; }
try {
if (!token.content || !(token === null || token === void 0 ? void 0 : token.children.length)) {
return;
}
if (reTagFind && !reTagFind.test(token.content)) {
return;
}
if (token.children.find(function (item) { return item.type === tokenType; })) {
if ((_a = parentToken.attrs) === null || _a === void 0 ? void 0 : _a.length) {
parentToken.attrs.push(attrs);
}
else {
parentToken.attrs = [attrs];
}
}
}
catch (e) {
console.log("[MMD]=>[addAttributesToParentTokenByType]=>ERROR=>", e);
}
};
exports.addAttributesToParentTokenByType = addAttributesToParentTokenByType;
var addAttributesToParentToken = function (parentToken, token) {
try {
if (!token.content || !(token === null || token === void 0 ? void 0 : token.children.length)) {
return;
}
(0, exports.addAttributesToParentTokenByType)(parentToken, token, "dotfill", ['data-has-dotfill', 'true'], /\\dotfill/);
}
catch (e) {
console.log("[MMD]=>[addAttributesToParentToken]=>ERROR=>", e);
}
};
exports.addAttributesToParentToken = addAttributesToParentToken;
var isMathInText = function (tokens, idx, options) {
try {
if (!options.forDocx || idx < 0 || idx >= tokens.length) {
return false;
}
var token = tokens[idx];
if (!["inline_math", "inline_mathML"].includes(token.type)) {
return false;
}
if (token.attrGet("data-math-in-text")) {
return true;
}
var tokenBefore = (idx > 0) ? tokens[idx - 1] : null;
if ((tokenBefore === null || tokenBefore === void 0 ? void 0 : tokenBefore.type) && consts_1.INLINE_ELEMENT_TOKENS.includes(tokenBefore.type)) {
return true;
}
for (var i = idx + 1; i < tokens.length; i++) {
var nextToken = tokens[i];
if (consts_1.CLOSING_STYLE_TOKENS.includes(nextToken.type)) {
continue;
}
if (consts_1.OPENING_STYLE_TOKENS.includes(nextToken.type) || consts_1.INLINE_ELEMENT_TOKENS.includes(nextToken.type)) {
return true;
}
break;
}
return false;
}
catch (err) {
console.log("[MMD][isMathInText]=>[ERROR]=>", err);
return false;
}
};
exports.isMathInText = isMathInText;
var applyAttrToMathml = function (mathEquation, attr, options) {
try {
if (!options.forDocx || !attr) {
return mathEquation;
}
return mathEquation
.replace(/<mathmlword(\s|>)/g, "<mathmlword ".concat(attr, "$1"))
.replace(/<mathml(\s|>)/g, "<mathml ".concat(attr, "$1"));
}
catch (e) {
return mathEquation;
}
};
exports.applyAttrToMathml = applyAttrToMathml;
var applyAttrToInlineMath = function (tokens, attrName, attrVal) {
tokens.forEach(function (token) {
if (["inline_math", "inline_mathML"].includes(token.type)) {
token.attrSet(attrName, attrVal);
}
});
};
exports.applyAttrToInlineMath = applyAttrToInlineMath;
//# sourceMappingURL=utils.js.map