UNPKG

mystjs

Version:
607 lines 21.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.tokensToMyst = void 0; const fromMarkdown_1 = require("./fromMarkdown"); const types_1 = require("./types"); const unist_util_visit_1 = require("unist-util-visit"); const unist_util_remove_1 = require("unist-util-remove"); const unist_builder_1 = require("unist-builder"); const he_1 = __importDefault(require("he")); const utils_1 = require("./utils"); const unist_util_select_1 = require("unist-util-select"); const transforms_1 = require("./transforms"); const NUMBERED_CLASS = /^numbered$/; const ALIGN_CLASS = /(?:(?:align-)|^)(left|right|center)/; function getClassName(token, exclude) { var _a, _b, _c; const allClasses = new Set([ // Grab the trimmed classes from the token ...((_a = token.attrGet('class')) !== null && _a !== void 0 ? _a : '') .split(' ') .map((c) => c.trim()) .filter((c) => c), // Add any from the meta information (these are often repeated) ...((_c = (_b = token.meta) === null || _b === void 0 ? void 0 : _b.class) !== null && _c !== void 0 ? _c : []), ]); const className = [...allClasses].join(' '); if (!className) return undefined; return (className .split(' ') .map((c) => c.trim()) .filter((c) => { if (!c) return false; if (!exclude) return true; return !exclude.reduce((doExclude, test) => doExclude || !!c.match(test), false); }) .join(' ') || undefined); } function hasClassName(token, matcher) { const className = getClassName(token); if (!className) return false; const matches = className .split(' ') .map((c) => c.match(matcher)) .filter((c) => c); if (matches.length === 0) return false; return matches[0]; } function getLang(t) { return he_1.default.decode(t.info).trim().split(' ')[0].replace('\\', ''); } function getColAlign(t) { var _a; if ((_a = t.attrs) === null || _a === void 0 ? void 0 : _a.length) { for (const attrPair of t.attrs) { if (attrPair[0] === 'style') { const match = attrPair[1].match(/text-align:(left|right|center)/); if (match) { return match[1]; } } } } } const defaultMdast = { heading: { type: 'heading', getAttrs(token) { var _a; return { depth: Number(token.tag[1]), enumerated: (_a = token.meta) === null || _a === void 0 ? void 0 : _a.enumerated, }; }, }, hr: { type: 'thematicBreak', noCloseToken: true, isLeaf: true, }, paragraph: { type: 'paragraph', }, blockquote: { type: 'blockquote', }, ordered_list: { type: 'list', getAttrs(token, tokens, index) { var _a, _b; const info = (_a = tokens[index + 1]) === null || _a === void 0 ? void 0 : _a.info; const start = Number((_b = tokens[index + 1]) === null || _b === void 0 ? void 0 : _b.info); return { ordered: true, start: isNaN(start) || !info ? 1 : start, spread: false, }; }, }, bullet_list: { type: 'list', attrs: { ordered: false, spread: false, }, }, list_item: { type: 'listItem', attrs: { spread: true, }, }, em: { type: 'emphasis', }, strong: { type: 'strong', }, colon_fence: { type: 'code', isLeaf: true, noCloseToken: true, getAttrs(t) { return { lang: getLang(t), value: (0, utils_1.withoutTrailingNewline)(t.content) }; }, }, fence: { type: 'code', isLeaf: true, getAttrs(t) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; const name = ((_a = t.meta) === null || _a === void 0 ? void 0 : _a.name) || undefined; const showLineNumbers = !!(((_b = t.meta) === null || _b === void 0 ? void 0 : _b.linenos) || ((_c = t.meta) === null || _c === void 0 ? void 0 : _c.linenos) === null || // Weird docutils implementation ((_d = t.meta) === null || _d === void 0 ? void 0 : _d['number-lines']) || ( // If lineno-start is present, linenos option is also automatically activated // https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-option-code-block-lineno-start (_e = t.meta) === null || _e === void 0 ? void 0 : _e['lineno-start'])); const lineno = (_g = (_f = t.meta) === null || _f === void 0 ? void 0 : _f['lineno-start']) !== null && _g !== void 0 ? _g : (_h = t.meta) === null || _h === void 0 ? void 0 : _h['number-lines']; const startingLineNumber = lineno && lineno !== 1 && !isNaN(Number(lineno)) ? Number(lineno) : undefined; const emphasizeLines = ((_j = t.meta) === null || _j === void 0 ? void 0 : _j['emphasize-lines']) ? (_k = t.meta) === null || _k === void 0 ? void 0 : _k['emphasize-lines'].split(',').map((n) => Number(n.trim())).filter((n) => !isNaN(n) && n > 0) : undefined; return Object.assign(Object.assign({ lang: getLang(t) }, (0, utils_1.normalizeLabel)(name)), { class: getClassName(t), showLineNumbers: showLineNumbers || undefined, startingLineNumber: showLineNumbers ? startingLineNumber : undefined, // Only if showing line numbers! emphasizeLines, value: (0, utils_1.withoutTrailingNewline)(t.content) }); }, }, code_block: { type: 'code', isLeaf: true, getAttrs(t) { return { lang: getLang(t), value: (0, utils_1.withoutTrailingNewline)(t.content) }; }, }, code_inline: { type: 'inlineCode', noCloseToken: true, isText: true, }, hardbreak: { type: 'break', noCloseToken: true, isLeaf: true, }, link: { type: 'link', getAttrs(token) { var _a; return { url: token.attrGet('href'), title: (_a = token.attrGet('title')) !== null && _a !== void 0 ? _a : undefined, }; }, }, image: { type: 'image', noCloseToken: true, isLeaf: true, getAttrs(token) { var _a; const alt = token.attrGet('alt') || ((_a = token.children) === null || _a === void 0 ? void 0 : _a.reduce((i, t) => i + (t === null || t === void 0 ? void 0 : t.content), '')); const alignMatch = hasClassName(token, ALIGN_CLASS); const align = alignMatch ? alignMatch[1] : undefined; return { url: token.attrGet('src'), alt: alt || undefined, title: token.attrGet('title') || undefined, class: getClassName(token, [ALIGN_CLASS]), width: token.attrGet('width') || undefined, height: token.attrGet('height') || undefined, align, }; }, }, abbr: { type: 'abbreviation', getAttrs(token) { var _a, _b, _c; const value = (_b = (_a = token.children) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.content; return { title: (_c = token.attrGet('title')) !== null && _c !== void 0 ? _c : undefined, value, }; }, }, sub: { type: 'subscript', }, sup: { type: 'superscript', }, dl: { type: 'definitionList', }, dt: { type: 'definitionTerm', }, dd: { type: 'definitionDescription', }, admonition: { type: 'admonition', getAttrs(token) { var _a; const kind = ((_a = token.meta) === null || _a === void 0 ? void 0 : _a.kind) || undefined; return { kind, class: getClassName(token, [new RegExp(`admonition|${kind}`)]), }; }, }, admonition_title: { type: 'admonitionTitle', }, figure: { type: 'container', getAttrs(token) { var _a, _b; const name = ((_a = token.meta) === null || _a === void 0 ? void 0 : _a.name) || undefined; return Object.assign(Object.assign({ kind: 'figure' }, (0, utils_1.normalizeLabel)(name)), { enumerated: (_b = token.meta) === null || _b === void 0 ? void 0 : _b.enumerated, class: getClassName(token, [NUMBERED_CLASS]) }); }, }, figure_caption: { type: 'caption', }, figure_legend: { type: 'legend', }, table: { type: 'table', getAttrs(token) { var _a, _b, _c; const name = ((_a = token.meta) === null || _a === void 0 ? void 0 : _a.name) || undefined; return Object.assign(Object.assign({ kind: undefined }, (0, utils_1.normalizeLabel)(name)), { enumerated: (_b = token.meta) === null || _b === void 0 ? void 0 : _b.enumerated, class: getClassName(token, [NUMBERED_CLASS, ALIGN_CLASS]), align: ((_c = token.meta) === null || _c === void 0 ? void 0 : _c.align) || undefined }); }, }, table_caption: { type: 'caption', }, thead: { type: '_lift', }, tbody: { type: '_lift', }, tr: { type: 'tableRow', }, th: { type: 'tableCell', getAttrs(t) { return { header: true, align: getColAlign(t) || undefined }; }, }, td: { type: 'tableCell', getAttrs(t) { return { align: getColAlign(t) || undefined }; }, }, math_inline: { type: 'inlineMath', noCloseToken: true, isText: true, }, math_inline_double: { type: 'math', noCloseToken: true, isText: true, getAttrs(t) { var _a; return { enumerated: (_a = t.meta) === null || _a === void 0 ? void 0 : _a.enumerated, }; }, }, math_block: { type: 'math', noCloseToken: true, isText: true, getAttrs(t) { var _a; const name = t.info || undefined; return Object.assign(Object.assign({}, (0, utils_1.normalizeLabel)(name)), { enumerated: (_a = t.meta) === null || _a === void 0 ? void 0 : _a.enumerated }); }, }, math_block_label: { type: 'math', noCloseToken: true, isText: true, getAttrs(t) { var _a; const name = t.info || undefined; return Object.assign(Object.assign({}, (0, utils_1.normalizeLabel)(name)), { enumerated: (_a = t.meta) === null || _a === void 0 ? void 0 : _a.enumerated }); }, }, amsmath: { type: 'math', noCloseToken: true, isText: true, getAttrs(t) { var _a; return { enumerated: (_a = t.meta) === null || _a === void 0 ? void 0 : _a.enumerated, }; }, }, ref: { type: 'crossReference', isLeaf: true, getAttrs(t) { var _a, _b, _c; return Object.assign(Object.assign({ kind: (_a = t.meta) === null || _a === void 0 ? void 0 : _a.kind }, (0, utils_1.normalizeLabel)((_b = t.meta) === null || _b === void 0 ? void 0 : _b.label)), { value: ((_c = t.meta) === null || _c === void 0 ? void 0 : _c.value) || undefined }); }, }, footnote_ref: { type: 'footnoteReference', noCloseToken: true, isLeaf: true, getAttrs(t) { var _a; return Object.assign({}, (0, utils_1.normalizeLabel)((_a = t === null || t === void 0 ? void 0 : t.meta) === null || _a === void 0 ? void 0 : _a.label)); }, }, footnote_anchor: { type: '_remove', noCloseToken: true, }, footnote_block: { // The footnote block is a view concern, not AST // Lift footnotes out of the tree type: '_lift', }, footnote: { type: 'footnoteDefinition', getAttrs(t) { var _a; return Object.assign({}, (0, utils_1.normalizeLabel)((_a = t === null || t === void 0 ? void 0 : t.meta) === null || _a === void 0 ? void 0 : _a.label)); }, }, directive: { type: 'mystDirective', noCloseToken: true, isLeaf: true, getAttrs(t) { var _a; return { name: t.info, args: ((_a = t === null || t === void 0 ? void 0 : t.meta) === null || _a === void 0 ? void 0 : _a.arg) || undefined, value: t.content.trim(), }; }, }, parsed_directive: { type: 'mystDirective', getAttrs(t) { var _a, _b; let opts = (_a = t.meta) === null || _a === void 0 ? void 0 : _a.opts; if (!opts || !Object.keys(opts).length) { opts = undefined; } else { if (opts.class) opts.class = opts.class.join(' '); Object.keys(opts).forEach((k) => { // Handle flags, where option is simply present. // This simple solution is very unlikely to be sufficient long term. if (opts[k] === null) opts[k] = true; }); } return { name: t.info, args: ((_b = t.meta) === null || _b === void 0 ? void 0 : _b.arg) || undefined, options: opts, value: t.content.trim() || undefined, }; }, }, directive_error: { type: 'mystDirectiveError', noCloseToken: true, }, role: { type: 'mystRole', noCloseToken: true, isLeaf: true, getAttrs(t) { var _a; return { name: (_a = t.meta) === null || _a === void 0 ? void 0 : _a.name, value: t.content, }; }, }, parsed_role: { type: 'mystRole', getAttrs(t) { return { name: t.meta.name, value: t.content, }; }, }, role_error: { type: 'mystRoleError', noCloseToken: true, isLeaf: true, getAttrs(t) { return { value: t.content, }; }, }, myst_target: { type: 'mystTarget', noCloseToken: true, isLeaf: true, getAttrs(t) { return { label: t.content, }; }, }, html_inline: { type: 'html', noCloseToken: true, isText: true, }, html_block: { type: 'html', noCloseToken: true, isText: true, }, myst_block_break: { type: 'blockBreak', noCloseToken: true, isLeaf: true, getAttrs(t) { return { meta: t.content || undefined, }; }, }, myst_line_comment: { type: 'mystComment', noCloseToken: true, isLeaf: true, getAttrs(t) { return { value: t.content.trim() || undefined, }; }, }, }; function hoistSingleImagesOutofParagraphs(tree) { // Hoist up all paragraphs with a single image (0, unist_util_visit_1.visit)(tree, 'paragraph', (node) => { var _a, _b; if (!(((_a = node.children) === null || _a === void 0 ? void 0 : _a.length) === 1 && ((_b = node.children) === null || _b === void 0 ? void 0 : _b[0].type) === 'image')) return; const child = node.children[0]; Object.keys(node).forEach((k) => { delete node[k]; }); Object.assign(node, child); }); } function nestSingleImagesIntoParagraphs(tree) { tree.children = tree.children.map((node) => { if (node.type === 'image') { return { type: 'paragraph', children: [node] }; } else { return node; } }); } const defaultOptions = { handlers: defaultMdast, hoistSingleImagesOutofParagraphs: true, nestBlocks: true, }; function tokensToMyst(tokens, options = defaultOptions) { var _a; const opts = Object.assign(Object.assign(Object.assign({}, defaultOptions), options), { handlers: Object.assign(Object.assign({}, defaultOptions.handlers), options === null || options === void 0 ? void 0 : options.handlers) }); const state = new fromMarkdown_1.MarkdownParseState(opts.handlers); state.parseTokens(tokens); let tree; do { tree = state.closeNode(); } while (state.stack.length); // Remove all redundant nodes marked for removal (0, unist_util_remove_1.remove)(tree, '_remove'); // Lift up all nodes that are named "lift" (0, transforms_1.liftChildren)(tree, '_lift'); // Remove unnecessary admonition titles from AST // These are up to the serializer to put in (0, unist_util_visit_1.visit)(tree, 'admonition', (node) => { var _a, _b; const { kind, children } = node; if (!kind || !children || kind === types_1.AdmonitionKind.admonition) return; const expectedTitle = (0, utils_1.admonitionKindToTitle)(kind); const titleNode = children[0]; if (titleNode.type === 'admonitionTitle' && ((_b = (_a = titleNode.children) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.value) === expectedTitle) node.children = children.slice(1); }); // Move crossReference text value to children (0, unist_util_visit_1.visit)(tree, 'crossReference', (node) => { delete node.children; if (node.value) { (0, utils_1.setTextAsChild)(node, node.value); delete node.value; } }); // Nest block content inside of a block if (opts.nestBlocks) { const newTree = (0, unist_builder_1.u)('root', []); let lastBlock; const pushBlock = () => { var _a; if (!lastBlock) return; if (((_a = lastBlock.children) === null || _a === void 0 ? void 0 : _a.length) === 0) { delete lastBlock.children; } newTree.children.push(lastBlock); }; (_a = tree.children) === null || _a === void 0 ? void 0 : _a.forEach((node) => { var _a, _b; if (node.type === 'blockBreak') { pushBlock(); lastBlock = node; node.type = 'block'; node.children = (_a = node.children) !== null && _a !== void 0 ? _a : []; return; } const stack = lastBlock ? lastBlock : newTree; (_b = stack.children) === null || _b === void 0 ? void 0 : _b.push(node); }); pushBlock(); tree = newTree; } (0, transforms_1.ensureCaptionIsParagraph)(tree); // Replace "table node with caption" with "figure node with table and caption" // TODO: Clean up when we update to typescript > 4.6.2 and we have access to // parent in visitor function. // i.e. visit(tree, 'table', (node, index parent) => {...}) // https://github.com/microsoft/TypeScript/issues/46900 (0, unist_util_select_1.selectAll)('table', tree).forEach((node) => { var _a, _b; const captionChildren = (_a = node.children) === null || _a === void 0 ? void 0 : _a.filter((n) => n.type === 'caption'); if (captionChildren === null || captionChildren === void 0 ? void 0 : captionChildren.length) { const tableChildren = (_b = node.children) === null || _b === void 0 ? void 0 : _b.filter((n) => n.type !== 'caption'); const newTableNode = { type: 'table', align: node.align, children: tableChildren, }; node.type = 'container'; node.kind = 'table'; node.children = [...captionChildren, newTableNode]; delete node.align; } else { delete node.enumerated; } }); if (opts.hoistSingleImagesOutofParagraphs) { hoistSingleImagesOutofParagraphs(tree); } else { nestSingleImagesIntoParagraphs(tree); } return tree; } exports.tokensToMyst = tokensToMyst; //# sourceMappingURL=tokensToMyst.js.map