UNPKG

@vivliostyle/vfm

Version:

Custom Markdown syntax specialized in book authoring.

189 lines (188 loc) 6.62 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.hast = exports.handlerDisplayMath = exports.handlerInlineMath = exports.mdast = void 0; var hast_util_select_1 = require("hast-util-select"); var mdast_util_find_and_replace_1 = __importDefault(require("mdast-util-find-and-replace")); var unist_builder_1 = __importDefault(require("unist-builder")); var unist_util_visit_1 = __importDefault(require("unist-util-visit")); /** * Inline math format, e.g. `$...$`. * - OK: `$x = y$`, `$x = \$y$` * - NG: `$$x = y$`, `$x = y$$`, `$ x = y$`, `$x = y $`, `$x = y$7` */ var REGEXP_INLINE = /\$([^$\s].*?(?<=[^\\$\s]|[^\\](?:\\\\)+))\$(?!\$|\d)/gs; /** Display math format, e.g. `$$...$$`. */ var REGEXP_DISPLAY = /\$\$([^$].*?(?<=[^$]))\$\$(?!\$)/gs; /** Type of inline math in Markdown AST. */ var TYPE_INLINE = 'inlineMath'; /** Type of display math in Markdown AST. */ var TYPE_DISPLAY = 'displayMath'; /** URL of MathJax v2 supported by Vivliostyle. */ var MATH_URL = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_CHTML'; /** * Create tokenizers for remark-parse. * @returns Tokenizers. */ var createTokenizers = function () { var tokenizerInlineMath = function (eat, value, silent) { if (!value.startsWith('$') || value.startsWith('$ ') || value.startsWith('$$')) { return; } var match = new RegExp(REGEXP_INLINE).exec(value); if (!match) { return; } if (silent) { return true; } var eaten = match[0], valueText = match[1]; var now = eat.now(); now.column += 1; now.offset += 1; return eat(eaten)({ type: TYPE_INLINE, children: [], data: { hName: TYPE_INLINE, value: valueText }, }); }; tokenizerInlineMath.notInLink = true; tokenizerInlineMath.locator = function (value, fromIndex) { return value.indexOf('$', fromIndex); }; var tokenizerDisplayMath = function (eat, value, silent) { if (!value.startsWith('$$') || value.startsWith('$$$')) { return; } var match = new RegExp(REGEXP_DISPLAY).exec(value); if (!match) { return; } if (silent) { return true; } var eaten = match[0], valueText = match[1]; var now = eat.now(); now.column += 1; now.offset += 1; return eat(eaten)({ type: TYPE_DISPLAY, children: [], data: { hName: TYPE_DISPLAY, value: valueText }, }); }; tokenizerDisplayMath.notInLink = true; tokenizerDisplayMath.locator = function (value, fromIndex) { return value.indexOf('$$', fromIndex); }; return { tokenizerInlineMath: tokenizerInlineMath, tokenizerDisplayMath: tokenizerDisplayMath }; }; /** * Process Markdown AST. * @returns Transformer or undefined (less than remark 13). */ var mdast = function () { // For less than remark 13 with exclusive other markdown syntax if (this.Parser && this.Parser.prototype.inlineTokenizers && this.Parser.prototype.inlineMethods) { var _a = this.Parser.prototype, inlineTokenizers = _a.inlineTokenizers, inlineMethods = _a.inlineMethods; var tokenizers = createTokenizers(); inlineTokenizers[TYPE_INLINE] = tokenizers.tokenizerInlineMath; inlineTokenizers[TYPE_DISPLAY] = tokenizers.tokenizerDisplayMath; inlineMethods.splice(inlineMethods.indexOf('text'), 0, TYPE_INLINE); inlineMethods.splice(inlineMethods.indexOf('text'), 0, TYPE_DISPLAY); return; } return function (tree) { (0, mdast_util_find_and_replace_1.default)(tree, REGEXP_INLINE, function (_, valueText) { return { type: TYPE_INLINE, data: { hName: TYPE_INLINE, value: valueText, }, children: [], }; }); (0, mdast_util_find_and_replace_1.default)(tree, REGEXP_DISPLAY, function (_, valueText) { return { type: TYPE_DISPLAY, data: { hName: TYPE_DISPLAY, value: valueText, }, children: [], }; }); }; }; exports.mdast = mdast; /** * Handle inline math to Hypertext AST. * @param h Hypertext AST formatter. * @param node Node. * @returns Hypertext AST. */ var handlerInlineMath = function (h, node) { if (!node.data) { node.data = {}; } return h({ type: 'element', }, 'span', { class: 'math inline', 'data-math-typeset': 'true', }, [(0, unist_builder_1.default)('text', "\\(".concat(node.data.value, "\\)"))]); }; exports.handlerInlineMath = handlerInlineMath; /** * Handle display math to Hypertext AST. * @param h Hypertext AST formatter. * @param node Node. * @returns Hypertext AST. */ var handlerDisplayMath = function (h, node) { if (!node.data) { node.data = {}; } return h({ type: 'element', }, 'span', { class: 'math display', 'data-math-typeset': 'true', }, [(0, unist_builder_1.default)('text', "$$".concat(node.data.value, "$$"))]); }; exports.handlerDisplayMath = handlerDisplayMath; /** * Process math related Hypertext AST. * Set the `<script>` to load MathJax and `<body>` attribute that enable math typesetting. * * This function does the work even if it finds a `<math>` that it does not treat as a VFM. Therefore, call it only if the VFM option is `math: true`. */ var hast = function () { return function (tree) { if (!((0, hast_util_select_1.select)('[data-math-typeset="true"]', tree) || (0, hast_util_select_1.select)('math', tree))) { return; } (0, unist_util_visit_1.default)(tree, 'element', function (node) { switch (node.tagName) { case 'head': node.children.push({ type: 'element', tagName: 'script', properties: { async: true, src: MATH_URL, }, children: [], }); node.children.push({ type: 'text', value: '\n' }); break; } }); }; }; exports.hast = hast;