UNPKG

@diplodoc/transform

Version:

A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML

105 lines 4.26 kB
"use strict"; const chalk_1 = require("chalk"); const utilsFS_1 = require("../../utilsFS"); const utils_1 = require("../../utils"); const INCLUDE_REGEXP = /^{%\s*include\s*(notitle)?\s*\[(.+?)]\((.+?)\)\s*%}$/; function stripTitleTokens(tokens) { const [open, _, close] = tokens; if ((open === null || open === void 0 ? void 0 : open.type) === 'heading_open' && (close === null || close === void 0 ? void 0 : close.type) === 'heading_close') { tokens.splice(0, 3); } } function unfoldIncludes(md, state, path, options) { var _a, _b; const { root, notFoundCb, log, noReplaceInclude = false } = options; const { tokens } = state; let i = 0; while (i < tokens.length) { const openToken = tokens[i]; const contentToken = tokens[i + 1]; const closeToken = tokens[i + 2]; let match; if (openToken.type === 'paragraph_open' && contentToken.type === 'inline' && (match = contentToken.content.match(INCLUDE_REGEXP)) && closeToken.type === 'paragraph_close') { try { const [, keyword /* description */, , includePath] = match; const fullIncludePath = (0, utilsFS_1.getFullIncludePath)(includePath, root, path); // Check the real path of the file in case of a symlink let pathname = (0, utilsFS_1.getRealPath)(fullIncludePath); if (!pathname.startsWith(root)) { i++; continue; } let hash = ''; const hashIndex = fullIncludePath.lastIndexOf('#'); if (hashIndex > -1 && !(0, utilsFS_1.isFileExists)(pathname)) { pathname = fullIncludePath.slice(0, hashIndex); hash = fullIncludePath.slice(hashIndex + 1); } // Check the existed included store and extract it const included = (_a = md.included) === null || _a === void 0 ? void 0 : _a[pathname]; const fileTokens = (0, utilsFS_1.getFileTokens)(pathname, state, options, included); let includedTokens; if (hash) { // TODO: add warning about missed block // TODO: findBlockTokens requires markdown-it-attrs plugin for find block with id=hash includedTokens = (0, utils_1.findBlockTokens)(fileTokens, hash); } else { includedTokens = fileTokens; } if (keyword === 'notitle') { stripTitleTokens(includedTokens); } if (noReplaceInclude) { i++; } else { tokens.splice(i, 3, ...includedTokens); i += includedTokens.length; } } catch (e) { // @ts-ignore for some reason typescript fails here const errPath = (_b = e.path) === null || _b === void 0 ? void 0 : _b.replace(root, ''); if (notFoundCb) { notFoundCb(errPath); } log.error(`Skip error: ${e} in ${errPath}`); i++; } } else { i++; } } } const index = (md, options) => { const { path: optPath, log } = options; const plugin = (state) => { const { env } = state; const path = env.path || optPath; env.includes = env.includes || []; const isCircularInclude = env.includes.includes(path); if (isCircularInclude && state.env.disableCircularError) { return; } if (isCircularInclude) { log.error(`Circular includes: ${(0, chalk_1.bold)(env.includes.concat(path).join(' ▶ '))}`); process.exit(1); } env.includes.push(path); unfoldIncludes(md, state, path, options); env.includes.pop(); }; try { md.core.ruler.before('curly_attributes', 'includes', plugin); } catch (e) { md.core.ruler.push('includes', plugin); } }; module.exports = index; //# sourceMappingURL=index.js.map