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)
610 lines • 28 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.render_enumerate_list_close = exports.render_itemize_list_close = exports.render_latex_list_item_close = exports.render_latex_list_item_open = exports.render_item_inline = exports.render_enumerate_list_open = exports.render_itemize_list_open = void 0;
var tslib_1 = require("tslib");
var rules_1 = require("../rules");
var re_level_1 = require("./re-level");
var render_tabular_1 = require("../md-renderer-rules/render-tabular");
var common_1 = require("../highlight/common");
var convert_scv_to_base64_1 = require("../md-svg-to-base64/convert-scv-to-base64");
var consts_1 = require("../common/consts");
var utils_1 = require("../utils");
var level_itemize = 0;
var level_enumerate = 0;
var listState = {
enumerateCounters: [],
};
/**
* Resets enumerate counters at the given nesting level.
* Ensures the counters array is large enough, truncates deeper levels,
* and sets the counter for `level` to zero (start of a new list at that level).
*
* @param level - Enumerate nesting level (1-based).
*/
var resetEnumerateCountersFromLevel = function (level) {
var safeLevel = Math.max(1, level);
var counters = listState.enumerateCounters;
while (counters.length < safeLevel) {
counters.push(0);
}
// Drop counters for deeper levels when a new list starts at this level.
counters.length = safeLevel;
counters[safeLevel - 1] = 0;
};
/**
* Increments and returns the next enumerate index for the given nesting level.
* Ensures the counters array is large enough and truncates deeper levels
* (so returning to a higher level resets deeper numbering).
*
* @param level - Enumerate nesting level (1-based).
* @returns The next 1-based item index for this enumerate level.
*/
var nextEnumerateIndex = function (level) {
var _a;
var safeLevel = Math.max(1, level);
var counters = listState.enumerateCounters;
while (counters.length < safeLevel) {
counters.push(0);
}
// Drop deeper levels when we emit an item at this level.
counters.length = safeLevel;
counters[safeLevel - 1] = ((_a = counters[safeLevel - 1]) !== null && _a !== void 0 ? _a : 0) + 1;
return counters[safeLevel - 1];
};
/**
* Clears all enumerate counters for all nesting levels.
* Useful when starting a fresh top-level enumerate list.
*/
var resetAllEnumerateCounters = function () {
listState.enumerateCounters.length = 0;
};
var list_injectLineNumbers = function (tokens, idx, className) {
if (className === void 0) { className = ''; }
var line, endLine, listLine;
if (tokens[idx].map) {
line = tokens[idx].map[0];
endLine = tokens[idx].map[1];
listLine = [];
for (var i = line; i < endLine; i++) {
listLine.push(i);
}
tokens[idx].attrJoin("class", className + ' ' + rules_1.PREVIEW_PARAGRAPH_PREFIX + String(line)
+ ' ' + rules_1.PREVIEW_LINE_CLASS + ' ' + listLine.join(' '));
tokens[idx].attrJoin("data_line_start", "".concat(String(line)));
tokens[idx].attrJoin("data_line_end", "".concat(String(endLine - 1)));
tokens[idx].attrJoin("data_line", "".concat(String([line, endLine])));
tokens[idx].attrJoin("count_line", "".concat(String(endLine - line)));
if (tokens[idx].hasOwnProperty('parentStart')) {
tokens[idx].attrJoin("data_parent_line_start", "".concat(String(tokens[idx].parentStart)));
}
}
else {
tokens[idx].attrJoin("class", className);
}
};
/**
* Renderer for opening an itemize list (`itemize_list_open`).
*
* Responsibilities:
* - Tracks nested itemize depth with `level_itemize`.
* - Adds a base "itemize" class and optional line-numbering attributes.
* - For DOCX output (`options.forDocx`), computes custom bullet metadata
* (`data-custom-marker-type`, `data-custom-marker-content`) based on
* precomputed `itemizeLevel` and `itemizeLevelContents`.
* - Emits:
* - `<ul ... style="list-style-type: none">` for nested lists,
* - optionally wraps nested `<ul>` in `<li>` when a list is directly
* nested under another `itemize_list_open`.
* - For top-level lists, respects `data-padding-inline-start` attribute
* (translating it into inline CSS `padding-inline-start`).
*/
var render_itemize_list_open = function (tokens, idx, options, env, slf) {
var token = tokens[idx];
// Reset nesting level for top-level lists
if (token.isTopLevelList) {
level_itemize = 0;
}
var prevToken = tokens[idx - 1];
level_itemize++;
var dataAttr = "";
var className = "itemize";
// Attach line-numbering or basic class
if (options === null || options === void 0 ? void 0 : options.lineNumbering) {
list_injectLineNumbers(tokens, idx, className);
}
else {
token.attrJoin("class", className);
}
// Translate data-padding-inline-start into inline style for top-level lists
var paddingInlineAttr = token.attrGet("data-padding-inline-start");
var paddingInlineStyle = paddingInlineAttr
? "padding-inline-start: ".concat(paddingInlineAttr, "px; ")
: "";
// DOCX-specific: compute custom bullet metadata
if (options.forDocx) {
var itemizeLevelTokens = (0, re_level_1.GetItemizeLevelTokens)(token.itemizeLevel);
if (level_itemize > 0 && itemizeLevelTokens.length >= level_itemize) {
var itemizeLevelContents = (0, re_level_1.GetItemizeLevel)(token.itemizeLevelContents);
if (itemizeLevelContents.length >= level_itemize) {
var levelIndex = level_itemize - 1;
var markerInfo = isTextMarkerTokens(itemizeLevelTokens[levelIndex], slf, options, env);
dataAttr += " data-custom-marker-type=\"".concat(markerInfo.markerType, "\"");
if (markerInfo.markerType === 'text') {
dataAttr += " data-custom-marker-content=\"".concat(encodeURI(markerInfo.textContent), "\"");
}
else {
dataAttr += " data-custom-marker-content=\"".concat(encodeURI(itemizeLevelContents[levelIndex]), "\"");
}
}
}
}
var attrs = slf.renderAttrs(token) + dataAttr;
var style = level_itemize > 1
? 'list-style-type: none'
: "".concat(paddingInlineStyle, "list-style-type: none");
var ulOpen = "<ul".concat(attrs, " style=\"").concat(style, "\">");
if ((prevToken === null || prevToken === void 0 ? void 0 : prevToken.type) === 'itemize_list_open') {
return "<li class=\"li_itemize\" data-custom-marker=\"true\" data-marker-empty=\"true\">".concat(ulOpen);
}
if ((prevToken === null || prevToken === void 0 ? void 0 : prevToken.type) === 'enumerate_list_open') {
return "<li class=\"li_enumerate not_number\" data-custom-marker=\"true\" data-marker-empty=\"true\" style=\"display: block\">".concat(ulOpen);
}
return ulOpen;
};
exports.render_itemize_list_open = render_itemize_list_open;
/**
* Renderer for opening an enumerate list (`enumerate_list_open`).
*
* Responsibilities:
* - Tracks nested enumerate depth via `level_enumerate`.
* - Resolves the current list-style type (e.g. `decimal`, `lower-alpha`)
* from `token.enumerateLevel` with a fallback to `"decimal"`.
* - Adds CSS class `enumerate <style>` (e.g. `enumerate decimal`).
* - Injects line-numbering attributes when `options.lineNumbering` is enabled.
* - For DOCX (`options.forDocx`), adds `data-list-style-type="<style>"`.
* - For top-level lists, respects `data-padding-inline-start` attribute
* and converts it into inline `padding-inline-start` CSS.
*/
var render_enumerate_list_open = function (tokens, idx, options, env, slf) {
var token = tokens[idx];
// Reset nesting level for top-level enumerate lists
if (token.isTopLevelList) {
level_enumerate = 0;
resetAllEnumerateCounters();
}
var prevToken = tokens[idx - 1];
level_enumerate++;
resetEnumerateCountersFromLevel(level_enumerate);
var dataAttr = '';
// Determine current enumerate style (e.g. decimal, lower-alpha, ...)
var enumerateLevels = (0, re_level_1.GetEnumerateLevel)(token.enumerateLevel);
var currentStyle = enumerateLevels.length >= level_enumerate
? enumerateLevels[level_enumerate - 1]
: "decimal";
var className = "enumerate ".concat(currentStyle);
// Line numbering or basic class
if (options === null || options === void 0 ? void 0 : options.lineNumbering) {
list_injectLineNumbers(tokens, idx, className);
}
else {
token.attrJoin("class", className);
}
// Map data-padding-inline-start → inline CSS for top-level lists
var paddingInlineAttr = token.attrGet("data-padding-inline-start");
var paddingInlineStyle = paddingInlineAttr
? "padding-inline-start: ".concat(paddingInlineAttr, "px; ")
: "";
// DOCX: pass style type to consumer
if (options.forDocx) {
dataAttr = " data-list-style-type=\"".concat(currentStyle, "\"");
}
var attrs = slf.renderAttrs(token) + dataAttr;
var style = level_enumerate > 1
? "list-style-type: ".concat(currentStyle)
: "".concat(paddingInlineStyle, "list-style-type: ").concat(currentStyle);
var olOpen = "<ol".concat(attrs, " style=\"").concat(style, "\">");
if ((prevToken === null || prevToken === void 0 ? void 0 : prevToken.type) === 'itemize_list_open') {
return "<li class=\"li_itemize\" data-custom-marker=\"true\" data-marker-empty=\"true\">".concat(olOpen);
}
if ((prevToken === null || prevToken === void 0 ? void 0 : prevToken.type) === 'enumerate_list_open') {
return "<li class=\"li_enumerate not_number\" data-custom-marker=\"true\" data-marker-empty=\"true\" style=\"display: block\">".concat(olOpen);
}
return olOpen;
};
exports.render_enumerate_list_open = render_enumerate_list_open;
var generateHtmlForMarkerTokens = function (markerTokens, slf, options, env) {
var htmlMarker = '';
var markerType = 'text';
var textContent = '';
if (markerTokens.length === 1 && consts_1.mathTokenTypes.includes(markerTokens[0].type)) {
markerType = 'math';
if (markerTokens[0].mathEquation) {
try {
var svg = '';
var svgStart = markerTokens[0].mathEquation.indexOf('<svg');
var svgEnd = markerTokens[0].mathEquation.indexOf('</mjx-container>');
svg = svgStart >= 0 && svgEnd > 0 ? markerTokens[0].mathEquation.slice(svgStart, svgEnd) : '';
var resSvg = (0, convert_scv_to_base64_1.default)(svg);
htmlMarker += resSvg;
}
catch (e) {
htmlMarker += markerTokens[0].mathEquation;
}
}
else {
htmlMarker += slf.renderInline([markerTokens[0]], options, env);
}
return {
htmlMarker: htmlMarker,
markerType: markerType,
textContent: ''
};
}
for (var j = 0; j < markerTokens.length; j++) {
if (markerTokens[j].type !== 'text') {
markerType = 'multi';
}
if (markerTokens[j].mathEquation) {
try {
var svg = '';
var svgStart = markerTokens[j].mathEquation.indexOf('<svg');
var svgEnd = markerTokens[j].mathEquation.indexOf('</mjx-container>');
svg = svgStart >= 0 && svgEnd > 0 ? markerTokens[j].mathEquation.slice(svgStart, svgEnd) : '';
var resSvg = (0, convert_scv_to_base64_1.default)(svg);
htmlMarker += resSvg;
}
catch (e) {
htmlMarker += markerTokens[j].mathEquation;
}
continue;
}
var renderdToken = slf.renderInline([markerTokens[j]], options, env);
if (markerType === 'text') {
textContent += renderdToken;
}
else {
textContent = '';
}
htmlMarker += renderdToken;
}
return {
htmlMarker: htmlMarker,
markerType: markerType,
textContent: textContent
};
};
var isTextMarkerTokens = function (markerTokens, slf, options, env) {
var markerType = 'text';
if (markerTokens.length === 1 && consts_1.mathTokenTypes.includes(markerTokens[0].type)) {
markerType = 'math';
return {
markerType: markerType,
textContent: ''
};
}
var textContent = '';
for (var j = 0; j < markerTokens.length; j++) {
if (markerTokens[j].type !== 'text') {
markerType = 'multi';
break;
}
textContent += slf.renderInline([markerTokens[j]], options, env);
}
return {
markerType: markerType,
textContent: textContent
};
};
/**
* Builds HTML for a custom \item[...] marker and reports whether the marker is empty.
* "Empty" means: marker is present but contains only whitespace / no visible content.
*/
var generateHtmlForCustomMarker = function (token, options, slf, env) {
var _a, _b, _c, _d, _e;
var rawMarker = token.marker;
var markerTokens = (_a = token.markerTokens) !== null && _a !== void 0 ? _a : [];
// Marker is considered "present" only if \item[...] was used.
var markerProvided = Object.prototype.hasOwnProperty.call(token, "marker");
// Fast path: if we have raw marker string, use it to detect empty marker reliably.
var hasNonEmptyMarker = markerProvided
? Boolean(rawMarker && rawMarker.trim().length > 0)
: false;
if (!markerProvided) {
return { htmlMarker: "", markerType: "text", textContent: "", isMarkerEmpty: false };
}
if (options.forDocx) {
var data = generateHtmlForMarkerTokens(markerTokens, slf, options, env);
// Fallback empty check: if raw marker is missing, use extracted textContent
var isEmpty = rawMarker != null
? rawMarker.trim().length === 0
: ((_b = data.textContent) !== null && _b !== void 0 ? _b : "").trim().length === 0;
return {
htmlMarker: (_c = data.htmlMarker) !== null && _c !== void 0 ? _c : "",
markerType: (_d = data.markerType) !== null && _d !== void 0 ? _d : "text",
textContent: (_e = data.textContent) !== null && _e !== void 0 ? _e : "",
isMarkerEmpty: isEmpty,
};
}
// Non-DOCX path: render inline marker tokens if marker is non-empty.
var htmlMarker = hasNonEmptyMarker
? slf.renderInline(markerTokens, options, env)
: "";
return {
htmlMarker: htmlMarker,
markerType: "text",
textContent: "",
isMarkerEmpty: !hasNonEmptyMarker,
};
};
/**
* Builds HTML marker information for list items that define a custom marker.
*
* Extracts the rendered marker (HTML) and assembles the corresponding
* `data-*` attributes used for HTML and DOCX export.
*/
var buildCustomMarkerInfo = function (token, options, slf, env) {
var dataAttrs = ['data-custom-marker="true"'];
var data = generateHtmlForCustomMarker(token, options, slf, env);
if (data === null || data === void 0 ? void 0 : data.isMarkerEmpty) {
dataAttrs.push('data-marker-empty="true"');
}
var htmlMarker = data.htmlMarker;
if (options.forDocx) {
dataAttrs.push("data-custom-marker-type=\"".concat(data.markerType, "\""));
var content = data.markerType === 'text'
? data.textContent
: token.marker;
dataAttrs.push("data-custom-marker-content=\"".concat(encodeURI(content), "\""));
}
var dataAttr = dataAttrs.length ? ' ' + dataAttrs.join(' ') : '';
return { htmlMarker: htmlMarker, dataAttr: dataAttr };
};
/**
* Builds marker information for LaTeX-style itemize list items.
*
* If the token defines a custom marker, delegates to `buildCustomMarkerInfo`.
* Otherwise, derives the marker from the itemize level tokens and, when
* exporting to DOCX, attaches appropriate `data-*` attributes (including
* math markers and their raw LaTeX content).
*/
var buildItemizeMarkerInfo = function (token, options, env, slf, level_itemize) {
var itemizeLevelTokens = (0, re_level_1.GetItemizeLevelTokens)(token.itemizeLevel);
var dataAttr = '';
var htmlMarker = '·';
if (token.hasOwnProperty('marker') && token.markerTokens) {
return buildCustomMarkerInfo(token, options, slf, env);
}
if (level_itemize > 0 && itemizeLevelTokens.length >= level_itemize) {
if (options.forDocx) {
var data = generateHtmlForMarkerTokens(itemizeLevelTokens[level_itemize - 1], slf, options, env);
htmlMarker = data.htmlMarker;
if (data.markerType === 'math') {
var itemizeLevel = (0, re_level_1.GetItemizeLevel)(token.itemizeLevelContents);
if (itemizeLevel.length >= level_itemize) {
dataAttr += " data-custom-marker-content=\"".concat(encodeURI(itemizeLevel[level_itemize - 1]), "\"");
}
dataAttr += ' data-custom-marker="true"';
dataAttr += " data-custom-marker-type=\"".concat(data.markerType, "\"");
}
}
else {
htmlMarker = slf.renderInline(itemizeLevelTokens[level_itemize - 1], options, env);
}
}
return { htmlMarker: htmlMarker, dataAttr: dataAttr };
};
/**
* Core renderer for LaTeX list items (both `enumerate` and `itemize`).
*
* Responsibilities:
* - Decide whether the current <li> belongs to LaTeX list context
* (`parentType` is "itemize" or "enumerate") or is just a plain HTML list.
* - Build the correct <li> markup for:
* - numbered lists (`enumerate`) with optional custom markers;
* - bulleted lists (`itemize`) with level-dependent markers;
* - Inject line-numbering classes when `options.lineNumbering` is enabled;
* - Add a leading non-breaking space for PPTX when the item begins
* with a math-only inline token;
* - Support two modes:
* - "open" — return only the opening part (no content, no closing </li>);
* - "full" — return opening tag, `content`, and closing </li>.
*/
var renderLatexListItemCore = function (tokens, index, options, env, slf, sContent, mode) {
var _a, _b, _c, _d, _e, _f, _g;
var token = tokens[index];
var isOpen = mode === "open";
var content = sContent !== null && sContent !== void 0 ? sContent : "";
// Helper: should we insert an extra at the start for PPTX/math-only items?
var needsPptxLeadingSpace = function () {
var _a;
if (!(options === null || options === void 0 ? void 0 : options.forPptx))
return false;
var next = tokens[index + 1];
if ((next === null || next === void 0 ? void 0 : next.type) !== "inline" || !((_a = next.children) === null || _a === void 0 ? void 0 : _a.length))
return false;
var firstChild = next.children[0];
return ["equation_math", "equation_math_not_number", "display_math"].includes(firstChild.type);
};
// Not in LaTeX list context at all → render a normal <li>
if (token.parentType !== "itemize" && token.parentType !== "enumerate") {
return isOpen ? "<li>" : "<li>".concat(content, "</li>");
}
var isEnumerate = token.parentType === "enumerate";
var dataAttr = "";
var htmlMarker = "";
// ENUMERATE
if (isEnumerate) {
var hasCustomMarker = token.hasOwnProperty('marker') && token.markerTokens;
var enumerateLevel = Math.max(1, (_c = (_b = (_a = token.meta) === null || _a === void 0 ? void 0 : _a.enumerateLevel) !== null && _b !== void 0 ? _b : level_enumerate) !== null && _c !== void 0 ? _c : 1);
var enumerateIndex = nextEnumerateIndex(enumerateLevel);
token.meta = tslib_1.__assign(tslib_1.__assign({}, ((_d = token.meta) !== null && _d !== void 0 ? _d : {})), { enumerateLevel: enumerateLevel, enumerateIndex: enumerateIndex });
// Case 1: custom marker (e.g. \item[foo])
if (hasCustomMarker) {
var className_1 = 'li_enumerate not_number';
if (options === null || options === void 0 ? void 0 : options.lineNumbering) {
// line numbers
list_injectLineNumbers(tokens, index, className_1);
}
else {
tokens[index].attrJoin("class", className_1);
}
var markerInfo = buildCustomMarkerInfo(token, options, slf, env);
dataAttr += markerInfo.dataAttr;
htmlMarker = markerInfo.htmlMarker;
var prefix_1 = "<li".concat(slf.renderAttrs(token)).concat(dataAttr, " style=\"display: block\">") +
"<span class=\"li_level\"".concat(dataAttr, ">").concat(htmlMarker, "</span>");
if (isOpen) {
return prefix_1;
}
return "".concat(prefix_1).concat(sContent, "</li>");
}
// Case 2: regular numbered enumerate element
var className_2 = ((_e = token.meta) === null || _e === void 0 ? void 0 : _e.isBlock)
? 'li_enumerate block'
: 'li_enumerate';
if (options === null || options === void 0 ? void 0 : options.lineNumbering) {
list_injectLineNumbers(tokens, index, className_2);
}
else {
tokens[index].attrJoin("class", className_2);
}
var prefix_2 = "<li".concat(slf.renderAttrs(token), ">");
if (isOpen) {
if (needsPptxLeadingSpace()) {
return prefix_2 + "<span> </span>";
}
return prefix_2;
}
return "".concat(prefix_2).concat(sContent, "</li>");
}
// ITEMIZE
var itemizeInfo = buildItemizeMarkerInfo(token, options, env, slf, level_itemize);
token.meta = tslib_1.__assign(tslib_1.__assign({}, ((_f = token.meta) !== null && _f !== void 0 ? _f : {})), { itemizeLevel: level_itemize });
htmlMarker = itemizeInfo.htmlMarker;
dataAttr += itemizeInfo.dataAttr || "";
var className = ((_g = token.meta) === null || _g === void 0 ? void 0 : _g.isBlock)
? 'li_itemize block'
: 'li_itemize';
if (options === null || options === void 0 ? void 0 : options.lineNumbering) {
list_injectLineNumbers(tokens, index, className);
}
else {
tokens[index].attrJoin("class", className);
}
var prefix = "<li".concat(slf.renderAttrs(token)).concat(dataAttr, ">") +
"<span class=\"li_level\"".concat(dataAttr, ">").concat(htmlMarker, "</span>");
if (isOpen) {
if (needsPptxLeadingSpace()) {
return prefix + "<span> </span>";
}
return prefix;
}
return "".concat(prefix).concat(sContent, "</li>");
};
/**
* Renders the content of a LaTeX list item (`latex_list_item_open`).
*
* Responsibilities:
* - Renders child tokens (including nested inline/tabular content).
* - Marks math fragments with `data-math-in-text` when needed.
* - Applies highlight wrappers when `token.highlights` is present.
* - Adds a dummy ` ` for empty list items (to keep bullet visible).
* - Delegates final <li> markup to `renderLatexListItemCore`
* for plain / nested list cases.
*/
var render_item_inline = function (tokens, idx, options, env, slf) {
var _a, _b, _c;
var token = tokens[idx];
var renderedContent = '';
var children = (_a = token.children) !== null && _a !== void 0 ? _a : null;
if (children && children.length > 0) {
var content = "";
for (var i = 0; i < children.length; i++) {
var childToken = children[i];
if (((_b = childToken === null || childToken === void 0 ? void 0 : childToken.children) === null || _b === void 0 ? void 0 : _b.length) > 0) {
// Nested inline content or special inline structures
if (childToken.type === "tabular_inline") {
content = (0, render_tabular_1.renderTabularInline)(token.children, childToken, options, env, slf);
}
else {
content = slf.renderInline(childToken.children, options, env);
}
}
else {
if ((0, utils_1.isMathInText)(token.children, i, options)) {
childToken.attrSet('data-math-in-text', "true");
}
content = slf.renderInline([childToken], options, env);
// For PPTX we prepend a non-breaking space before math-only first item
if ((options === null || options === void 0 ? void 0 : options.forPptx)
&& i === 0
&& ['equation_math', 'equation_math_not_number', 'display_math'].includes(childToken.type)) {
content = '<span> </span>' + content;
}
}
renderedContent += content;
}
}
// Apply highlighting if requested
if (((_c = token.highlights) === null || _c === void 0 ? void 0 : _c.length) && (0, common_1.needToHighlightAll)(token)) {
renderedContent = (0, common_1.highlightText)(token, renderedContent);
}
// If this <li> is not inside LaTeX itemize/enumerate → render simple <li>
if (token.parentType !== "itemize" && token.parentType !== "enumerate") {
return "<li>".concat(renderedContent, "</li>");
}
// Keep bullet visible for empty list items
if (!renderedContent) {
renderedContent = ' ';
}
var nextToken = tokens[idx + 1];
if ((nextToken === null || nextToken === void 0 ? void 0 : nextToken.type) === 'itemize_list_open') {
return renderLatexListItemCore(tokens, idx, options, env, slf, renderedContent, 'open');
}
return renderLatexListItemCore(tokens, idx, options, env, slf, renderedContent, 'full');
};
exports.render_item_inline = render_item_inline;
var render_latex_list_item_open = function (tokens, idx, options, env, slf) {
if (options === void 0) { options = {}; }
if (env === void 0) { env = {}; }
return renderLatexListItemCore(tokens, idx, options, env, slf, null, 'open');
};
exports.render_latex_list_item_open = render_latex_list_item_open;
var render_latex_list_item_close = function () {
return "</li>";
};
exports.render_latex_list_item_close = render_latex_list_item_close;
/**
* Renderer for closing an itemize list (`itemize_list_close`).
*
* Decreases nested itemize depth and, when another `itemize_list_close`
* follows immediately and we are still in nested context, outputs
* `</ul></li>` to close both the nested list and its `<li>`.
*/
var render_itemize_list_close = function (tokens, idx, options, env, slf) {
if (options === void 0) { options = {}; }
if (env === void 0) { env = {}; }
level_itemize--;
var nextToken = tokens[idx + 1];
if ((level_itemize > 0 || level_enumerate > 0)
&& (nextToken === null || nextToken === void 0 ? void 0 : nextToken.type)
&& ["enumerate_list_close", "itemize_list_close"].includes(nextToken.type)) {
return "</ul></li>";
}
return "</ul>";
};
exports.render_itemize_list_close = render_itemize_list_close;
var render_enumerate_list_close = function (tokens, idx, options, env, slf) {
if (options === void 0) { options = {}; }
if (env === void 0) { env = {}; }
level_enumerate--;
var nextToken = tokens[idx + 1];
if ((level_itemize > 0 || level_enumerate > 0)
&& (nextToken === null || nextToken === void 0 ? void 0 : nextToken.type)
&& ["enumerate_list_close", "itemize_list_close"].includes(nextToken.type)) {
return "</ol></li>";
}
return "</ol>";
};
exports.render_enumerate_list_close = render_enumerate_list_close;
//# sourceMappingURL=render-latex-list-env.js.map