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)
216 lines • 8.65 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var chemistry_drawer_1 = require("./chemistry-drawer");
var rules_1 = require("../rules");
var utils_1 = require("../utils");
var convert_scv_to_base64_1 = require("../md-svg-to-base64/convert-scv-to-base64");
var consts_1 = require("../common/consts");
function injectLineNumbersSmiles(tokens, idx, options, env, slf) {
var line, endLine, listLine;
var token = tokens[idx];
if (token.map && token.level === 0) {
line = token.map[0];
endLine = token.map[1];
listLine = [];
for (var i = line; i < endLine; i++) {
listLine.push(i);
}
token.attrJoin("class", rules_1.PREVIEW_PARAGRAPH_PREFIX + String(line)
+ ' ' + rules_1.PREVIEW_LINE_CLASS + ' ' + listLine.join(' '));
token.attrJoin("data_line_start", "".concat(String(line)));
token.attrJoin("data_line_end", "".concat(String(endLine - 1)));
token.attrJoin("data_line", "".concat(String([line, endLine])));
token.attrJoin("count_line", "".concat(String(endLine - line)));
}
return slf.renderAttrs(token);
}
var smilesDrawerBlock = function (state, startLine, endLine, silent) {
var pos = state.bMarks[startLine] + state.tShift[startLine];
var max = state.eMarks[startLine];
var haveEndMarker;
var token;
// if it's indented more than 3 spaces, it should be a code block
if (state.sCount[startLine] - state.blkIndent >= 4) {
return false;
}
if (pos + 3 > max) {
return false;
}
var marker = state.src.charCodeAt(pos);
if (marker !== 0x60 /* ` */) {
return false;
}
// scan marker length
var mem = pos;
pos = state.skipChars(pos, marker);
var len = pos - mem;
if (len < 3) {
return false;
}
var markup = state.src.slice(mem, pos);
var params = state.src.slice(pos, max);
if (params.indexOf(String.fromCharCode(marker)) >= 0) {
return false;
}
if (params !== 'smiles') {
return false;
}
// Since start is found, we can report success here in validation mode
if (silent) {
return true;
}
// search end of block
var nextLine = startLine;
for (;;) {
nextLine++;
if (nextLine >= endLine) {
// unclosed block should be autoclosed by end of document.
// also block seems to be autoclosed by end of parent
break;
}
pos = mem = state.bMarks[nextLine] + state.tShift[nextLine];
max = state.eMarks[nextLine];
if (pos < max && state.sCount[nextLine] < state.blkIndent) {
// non-empty line with negative indent should stop the list:
// - ```
// test
break;
}
if (state.src.charCodeAt(pos) !== marker) {
continue;
}
if (state.sCount[nextLine] - state.blkIndent >= 4) {
// closing fence should be indented less than 4 spaces
continue;
}
pos = state.skipChars(pos, marker);
// closing code fence must be at least as long as the opening one
if (pos - mem < len) {
continue;
}
// make sure tail has spaces only
pos = state.skipSpaces(pos);
if (pos < max) {
continue;
}
haveEndMarker = true;
// found!
break;
}
// If a fence has heading spaces, they should be removed from its inner block
len = state.sCount[startLine];
state.line = nextLine + (haveEndMarker ? 1 : 0);
token = state.push('smiles', 'div', 0);
token.info = params;
var content = state.getLines(startLine + 1, nextLine, len, true);
content = content.trim();
content = content.replace(/\r|\n|\s+/g, '');
token.content = content;
token.markup = markup;
token.map = [startLine, state.line];
return true;
};
var smilesDrawerInline = function (state, silent) {
var startPos = state.pos;
var beginMarker = consts_1.reOpenTagSmiles;
var endMarker = '</smiles>';
if (state.src.charCodeAt(startPos) !== 0x3C /* < */) {
return false;
}
if (!beginMarker.test(state.src.slice(startPos))) {
return false;
}
var match = state.src
.slice(startPos)
.match(beginMarker);
if (!match) {
return false;
}
startPos += match[0].length;
var endPos = state.src.indexOf(endMarker, startPos);
if (endPos === -1) {
return false;
}
var nextPos = endPos + endMarker.length;
if (!silent) {
var content = state.src.slice(startPos, endPos);
content = content.trim();
content = content.replace(/\s+/g, '');
var token = state.push('smiles_inline', "", 0);
token.content = content.trim();
}
state.pos = nextPos;
return true;
};
var renderSmilesDrawerBlock = function (tokens, idx, options, env, slf) {
var _a = options.outMath, outMath = _a === void 0 ? {} : _a;
var _b = outMath.include_smiles, include_smiles = _b === void 0 ? false : _b, _c = outMath.include_svg, include_svg = _c === void 0 ? true : _c;
var token = tokens[idx];
if (!token.content) {
return '';
}
var id = !options.isTesting
? (0, utils_1.uid)()
: '';
var resSvg = include_svg || options.forDocx
? chemistry_drawer_1.ChemistryDrawer.drawSvgSync(token.content.trim(), id, options, options.forPptx)
: '';
if (resSvg && (options.forDocx || options.forLatex)) {
var imgId = options.forLatex ? id : '';
resSvg = (0, convert_scv_to_base64_1.default)(resSvg, imgId);
}
var attrs = (options === null || options === void 0 ? void 0 : options.lineNumbering)
? injectLineNumbersSmiles(tokens, idx, options, env, slf)
: '';
var outputSmiles = include_smiles
? '<smiles style="display: none;">' + token.content.trim() + '</smiles>'
: '';
var maxWidth = options.maxWidth ? " max-width: ".concat(options.maxWidth, "; overflow-x: auto;") : '';
if (attrs) {
return maxWidth
? "<div ".concat(attrs, "><div class=\"smiles\" style=\"").concat(maxWidth, "\">").concat(outputSmiles).concat(resSvg, "</div></div>")
: "<div ".concat(attrs, "><div class=\"smiles\">").concat(outputSmiles).concat(resSvg, "</div></div>");
}
return maxWidth
? "<div><div class=\"smiles\" style=\"".concat(maxWidth, "\">").concat(outputSmiles).concat(resSvg, "</div></div>")
: "<div><div class=\"smiles\">".concat(outputSmiles).concat(resSvg, "</div></div>");
};
var renderSmilesDrawerInline = function (tokens, idx, options, env, slf) {
var _a = options.outMath, outMath = _a === void 0 ? {} : _a;
var _b = outMath.include_smiles, include_smiles = _b === void 0 ? false : _b, _c = outMath.include_svg, include_svg = _c === void 0 ? true : _c;
var token = tokens[idx];
if (!token.content) {
return '';
}
var id = !options.isTesting
? (0, utils_1.uid)()
: '';
var resSvg = include_svg || options.forDocx
? chemistry_drawer_1.ChemistryDrawer.drawSvgSync(token.content.trim(), id, options, options.forPptx)
: '';
if (resSvg && (options.forDocx || options.forLatex)) {
var imgId = options.forLatex ? id : '';
resSvg = (0, convert_scv_to_base64_1.default)(resSvg, imgId);
}
var outputSmiles = include_smiles
? '<smiles style="display: none;">' + token.content.trim() + '</smiles>'
: '';
var maxWidth = options.maxWidth ? " max-width: ".concat(options.maxWidth, "; overflow-x: auto;") : '';
return maxWidth
? "<div class=\"smiles-inline\" style=\"display: inline-block;".concat(maxWidth, "\">").concat(outputSmiles).concat(resSvg, "</div>")
: "<div class=\"smiles-inline\" style=\"display: inline-block;\">".concat(outputSmiles).concat(resSvg, "</div>");
};
exports.default = (function (md, options) {
Object.assign(md.options, options);
md.block.ruler.before('fence', 'smilesDrawerBlock', smilesDrawerBlock, {
alt: ["paragraph", "reference", "blockquote", "list"]
});
md.inline.ruler.before('html_inline', 'smilesDrawerInline', smilesDrawerInline);
md.renderer.rules.smiles = function (tokens, idx, options, env, slf) {
return renderSmilesDrawerBlock(tokens, idx, options, env, slf);
};
md.renderer.rules.smiles_inline = function (tokens, idx, options, env, slf) {
return renderSmilesDrawerInline(tokens, idx, options, env, slf);
};
});
//# sourceMappingURL=index.js.map