UNPKG

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)

247 lines 9.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.safeAssignToken = exports.flushBufferedTokens = exports.flushTokensToInline = exports.parseListEnvRawToTokens = exports.createBufferedState = exports.buildBlockStateFromRaw = exports.shiftTokenAbsolutePositions = void 0; var tslib_1 = require("tslib"); var TokenCtor = require("markdown-it/lib/token"); var latex_list_env_block_1 = require("./latex-list-env-block"); /** Shallow clone but shift known position fields by baseOffset */ var shiftTokenAbsolutePositions = function (tok, baseOffset) { var e_1, _a, e_2, _b; if (!baseOffset) { return tok; } // inlinePos is the important one in your lists if (tok.inlinePos && typeof tok.inlinePos === "object") { if (typeof tok.inlinePos.start_content === "number") tok.inlinePos.start_content += baseOffset; if (typeof tok.inlinePos.end_content === "number") tok.inlinePos.end_content += baseOffset; if (typeof tok.inlinePos.start === "number") tok.inlinePos.start += baseOffset; if (typeof tok.inlinePos.end === "number") tok.inlinePos.end += baseOffset; } // Shift markerTokens too (if they have inlinePos) if (tok.markerTokens && Array.isArray(tok.markerTokens)) { try { for (var _c = tslib_1.__values(tok.markerTokens), _d = _c.next(); !_d.done; _d = _c.next()) { var child = _d.value; (0, exports.shiftTokenAbsolutePositions)(child, baseOffset); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_1) throw e_1.error; } } } // Shift children if some later pipeline attaches them (rare here, but safe) if (tok.children && Array.isArray(tok.children)) { try { for (var _e = tslib_1.__values(tok.children), _f = _e.next(); !_f.done; _f = _e.next()) { var child = _f.value; (0, exports.shiftTokenAbsolutePositions)(child, baseOffset); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_f && !_f.done && (_b = _e.return)) _b.call(_e); } finally { if (e_2) throw e_2.error; } } } return tok; }; exports.shiftTokenAbsolutePositions = shiftTokenAbsolutePositions; /** * Builds a minimal StateBlock-like object from a raw LaTeX environment string. * * Notes: * - Normalizes CRLF to LF. * - Computes `bMarks/eMarks/tShift` so `state.src.slice(bMarks[i]+tShift[i], eMarks[i])` * matches each logical line (without a trailing "\n" after the last line). * - `env` is shallow-copied and forced to `{ isBlock: true }` for downstream checks. */ var buildBlockStateFromRaw = function (md, raw, baseEnv) { var normalized = raw.replace(/\r\n/g, "\n"); var lines = normalized.split("\n"); var st = { md: md, src: normalized, env: tslib_1.__assign(tslib_1.__assign({}, (baseEnv || {})), { isBlock: true, isInline: true }), tokens: [], bMarks: [], eMarks: [], tShift: [], line: 0, startLine: 0, lineMax: lines.length, parentType: "root", level: 0, prentLevel: 0, }; var offset = 0; for (var i = 0; i < lines.length; i++) { st.bMarks[i] = offset; st.tShift[i] = 0; offset += lines[i].length; st.eMarks[i] = offset; // Only add '\n' between lines (not after last line) if (i !== lines.length - 1) offset += 1; } st.push = function (type, tag, nesting) { // const tok = new (Token as any)(type, tag, nesting); var tok = new TokenCtor(type, tag, nesting); tok.block = true; tok.level = st.level; if (nesting === 1) st.level++; if (nesting === -1) st.level--; st.tokens.push(tok); return tok; }; return st; }; exports.buildBlockStateFromRaw = buildBlockStateFromRaw; /** * Creates a buffered state that collects tokens into a local array instead of * mutating the original StateBlock tokens immediately. * * Useful when you want "all-or-nothing" token emission (e.g., for inline reuse, * strict parsing, rollback on failure). */ var createBufferedState = function (state) { // prototype-inherit all read-only properties (bMarks, eMarks, src, etc.) var tempState = Object.create(state); tempState.tokens = []; tempState.level = state.level; tempState.push = (function (type, tag, nesting) { var tok = new TokenCtor(type, tag, nesting); tok.block = true; tok.level = tempState.level; if (nesting === 1) { tempState.level++; } if (nesting === -1) { tempState.level--; } tempState.tokens.push(tok); return tok; }); return tempState; }; exports.createBufferedState = createBufferedState; /** * Run ListsInternal on raw env and return produced tokens. * baseOffset used later to shift positions to absolute. */ var parseListEnvRawToTokens = function (md, raw, baseEnv) { var blockState = (0, exports.buildBlockStateFromRaw)(md, raw, baseEnv); var ok = (0, latex_list_env_block_1.ListsInternal)(blockState, 0, blockState.lineMax); return { ok: ok, tokens: blockState.tokens, state: blockState }; }; exports.parseListEnvRawToTokens = parseListEnvRawToTokens; /** * Push cloned tokens into inline state and shift local positions by baseOffset. */ var flushTokensToInline = function (inlineState, tokens, baseOffset) { var e_3, _a, e_4, _b; var pushCloned = function (sourceToken) { var newToken = inlineState.push(sourceToken.type, sourceToken.tag, sourceToken.nesting); // Copy fields safely (0, exports.safeAssignToken)(newToken, sourceToken); // Fix positions (0, exports.shiftTokenAbsolutePositions)(newToken, baseOffset); }; try { for (var tokens_1 = tslib_1.__values(tokens), tokens_1_1 = tokens_1.next(); !tokens_1_1.done; tokens_1_1 = tokens_1.next()) { var srcToken = tokens_1_1.value; if ((srcToken === null || srcToken === void 0 ? void 0 : srcToken.type) === 'inline') { if (!srcToken.content) { continue; } var children = []; inlineState.md.inline.parse(srcToken.content, inlineState.md, inlineState.env, children); try { for (var children_1 = (e_4 = void 0, tslib_1.__values(children)), children_1_1 = children_1.next(); !children_1_1.done; children_1_1 = children_1.next()) { var child = children_1_1.value; pushCloned(child); } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (children_1_1 && !children_1_1.done && (_b = children_1.return)) _b.call(children_1); } finally { if (e_4) throw e_4.error; } } continue; } pushCloned(srcToken); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (tokens_1_1 && !tokens_1_1.done && (_a = tokens_1.return)) _a.call(tokens_1); } finally { if (e_3) throw e_3.error; } } }; exports.flushTokensToInline = flushTokensToInline; /** * Flushes buffered tokens into the real StateBlock using state.push(). * This preserves markdown-it internal level mechanics. * * NOTE: * - Do not blindly overwrite `level` during assignment, since state.push() already * applies correct nesting transitions. Prefer safeAssignToken() that skips level. */ var flushBufferedTokens = function (state, buffered) { var e_5, _a; try { for (var buffered_1 = tslib_1.__values(buffered), buffered_1_1 = buffered_1.next(); !buffered_1_1.done; buffered_1_1 = buffered_1.next()) { var t = buffered_1_1.value; var tok = state.push(t.type, t.tag, t.nesting); (0, exports.safeAssignToken)(tok, t); } } catch (e_5_1) { e_5 = { error: e_5_1 }; } finally { try { if (buffered_1_1 && !buffered_1_1.done && (_a = buffered_1.return)) _a.call(buffered_1); } finally { if (e_5) throw e_5.error; } } }; exports.flushBufferedTokens = flushBufferedTokens; /** * Safe assign: copy custom fields but do NOT overwrite core ones that markdown-it sets. */ var safeAssignToken = function (target, src) { var e_6, _a; var SKIP = new Set(["type", "tag", "nesting", "level", "block"]); try { for (var _b = tslib_1.__values(Object.keys(src)), _c = _b.next(); !_c.done; _c = _b.next()) { var key = _c.value; if (SKIP.has(key)) continue; target[key] = src[key]; } } catch (e_6_1) { e_6 = { error: e_6_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_6) throw e_6.error; } } return target; }; exports.safeAssignToken = safeAssignToken; //# sourceMappingURL=latex-list-env-engine.js.map