UNPKG

myst-parser

Version:
112 lines (111 loc) 4.39 kB
import MarkdownIt from 'markdown-it'; import { defaultDirectives } from 'myst-directives'; import { defaultRoles } from 'myst-roles'; import { VFile } from 'vfile'; import { tlds } from './tlds.js'; import { EXCLUDE_TLDS, MARKDOWN_IT_CONFIG } from './config.js'; import { tokensToMyst } from './tokensToMyst.js'; import { mathPlugin, convertFrontMatter, frontMatterPlugin, colonFencePlugin, mystBlockPlugin, footnotePlugin, mystPlugin, deflistPlugin, tasklistPlugin, citationsPlugin, } from './plugins.js'; import { applyDirectives } from './directives.js'; import { applyRoles } from './roles.js'; import { visit } from 'unist-util-visit'; export const defaultOptions = { markdownit: { html: true, }, extensions: { smartquotes: true, colonFences: true, frontmatter: true, math: true, footnotes: true, citations: true, deflist: true, tasklist: true, tables: true, blocks: true, strikethrough: false, }, mdast: {}, directives: defaultDirectives, roles: defaultRoles, }; function parseOptions(opts) { var _a, _b, _c; const parsedOpts = { vfile: (_a = opts === null || opts === void 0 ? void 0 : opts.vfile) !== null && _a !== void 0 ? _a : new VFile(), mdast: { ...defaultOptions.mdast, ...opts === null || opts === void 0 ? void 0 : opts.mdast }, markdownit: { ...defaultOptions.markdownit, ...opts === null || opts === void 0 ? void 0 : opts.markdownit }, extensions: { ...defaultOptions.extensions, ...opts === null || opts === void 0 ? void 0 : opts.extensions }, directives: [...defaultOptions.directives, ...((_b = opts === null || opts === void 0 ? void 0 : opts.directives) !== null && _b !== void 0 ? _b : [])], roles: [...defaultOptions.roles, ...((_c = opts === null || opts === void 0 ? void 0 : opts.roles) !== null && _c !== void 0 ? _c : [])], }; return parsedOpts; } export function createTokenizer(opts) { const parsedOpts = parseOptions(opts); const { extensions, markdownit } = parsedOpts; const tokenizer = MarkdownIt({ ...MARKDOWN_IT_CONFIG, options: { ...MARKDOWN_IT_CONFIG.options, typographer: extensions.smartquotes ? true : false, }, }, markdownit); if (markdownit.linkify) { tokenizer.linkify.tlds(tlds.filter((tld) => !EXCLUDE_TLDS.includes(tld))); } if (extensions.strikethrough) tokenizer.enable('strikethrough'); if (extensions.smartquotes) tokenizer.enable('smartquotes'); if (extensions.tables) tokenizer.enable('table'); if (extensions.colonFences) tokenizer.use(colonFencePlugin); if (extensions.frontmatter) tokenizer.use(frontMatterPlugin, () => ({})).use(convertFrontMatter); if (extensions.blocks) tokenizer.use(mystBlockPlugin); if (extensions.footnotes) tokenizer.use(footnotePlugin).disable('footnote_inline'); // not yet implemented in myst-parser if (extensions.citations) tokenizer.use(citationsPlugin); tokenizer.use(mystPlugin); if (extensions.math) tokenizer.use(mathPlugin, extensions.math); if (extensions.deflist) tokenizer.use(deflistPlugin); if (extensions.tasklist) tokenizer.use(tasklistPlugin); return tokenizer; } export function mystParse(content, opts) { const { vfile } = opts || {}; const parsedOpts = parseOptions(opts); const tokenizer = createTokenizer(parsedOpts); const tree = tokensToMyst(content, tokenizer.parse(content, { vfile }), parsedOpts.mdast); applyDirectives(tree, parsedOpts.directives, parsedOpts.vfile, { parseMyst: (source, offset = 0) => { const mdast = mystParse(source, opts); // Fix-up the node's (global) position offsets visit(mdast, (node) => { if (node.position) { node.position.start.line += offset; node.position.end.line += offset; } }); return mdast; }, }); applyRoles(tree, parsedOpts.roles, parsedOpts.vfile); return tree; } /** * MyST Parser as a Unified Plugin */ export const mystParser = function mystParser(opts) { this.Parser = (content) => { return mystParse(content, opts); }; };