UNPKG

@diplodoc/transform

Version:

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

142 lines 5.55 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; const chalk_1 = require("chalk"); const github_slugger_1 = __importDefault(require("github-slugger")); const utils_1 = require("markdown-it/lib/common/utils"); const slugify_1 = __importDefault(require("slugify")); const utils_2 = require("../../utils"); const constants_1 = require("./constants"); function createLinkTokens(state, id, title, setId = false, href) { const open = new state.Token('link_open', 'a', 1); const close = new state.Token('link_close', 'a', -1); if (setId) { open.attrSet('id', id); } open.attrSet('href', href + '#' + id); open.attrSet('class', 'yfm-anchor'); open.attrSet('aria-hidden', 'true'); // SEO: render invisible heading title because link must have text content. const hiddenDesc = new state.Token('anchor_hidden_desc', '', 0); hiddenDesc.content = title; return [open, hiddenDesc, close]; } const getCustomIds = (content) => { const ids = []; content.replace(constants_1.CUSTOM_ID_REGEXP, (match, customId) => { if (match !== constants_1.CUSTOM_ID_EXCEPTION) { ids.push(customId); } return ''; }); return ids.length ? ids : null; }; const removeCustomId = (content) => { if (constants_1.CUSTOM_ID_REGEXP.test(content)) { return content .replace(constants_1.CUSTOM_ID_REGEXP, (match) => { if (match === constants_1.CUSTOM_ID_EXCEPTION) { return match; } return ''; }) .trim(); } return content; }; const removeCustomIds = (token) => { var _a; token.content = removeCustomId(token.content); (_a = token.children) === null || _a === void 0 ? void 0 : _a.forEach((child) => { child.content = removeCustomId(child.content); }); }; const index = (md, options) => { const { extractTitle, path, log, supportGithubAnchors, getPublicPath, disableCommonAnchors } = options; const plugin = (state) => { /* Do not use the plugin if it is included in the file */ if (state.env.includes && state.env.includes.length) { return; } const href = getPublicPath ? getPublicPath(options, state.env.path) : ''; const ids = {}; const tokens = state.tokens; let i = 0; const slugger = new github_slugger_1.default(); while (i < tokens.length) { const token = tokens[i]; const isHeading = token.type === 'heading_open'; if (isHeading) { const { title, level } = (0, utils_2.headingInfo)(tokens, i); const inlineToken = tokens[i + 1]; let id = token.attrGet('id'); let ghId; if (!title) { log.warn(`Header without title${path ? ` in ${(0, chalk_1.bold)(path)}` : ''}`); } if (level < 2 && extractTitle) { // if there are any custom ids in the level 1 heading we should clear them removeCustomIds(tokens[i + 1]); i += 3; continue; } const customIds = getCustomIds(inlineToken.content); if (customIds) { id = customIds[0]; removeCustomIds(tokens[i + 1]); } else { id = (0, slugify_1.default)(title, { lower: true, remove: /[^\w\s$_\-,;=/]+/g, }); ghId = slugger.slug(title); } token.attrSet('id', id); if (ids[id]) { id = id + ids[id]++; token.attrSet('id', id); } else { ids[id] = 1; } const allAnchorIds = customIds ? customIds : [id]; const anchorTitle = removeCustomId(title).replace(/`/g, ''); allAnchorIds.forEach((customId) => { var _a, _b; const setId = id !== customId; if (!disableCommonAnchors) { const linkTokens = createLinkTokens(state, customId, anchorTitle, setId, href); (_a = inlineToken.children) === null || _a === void 0 ? void 0 : _a.unshift(...linkTokens); } if (supportGithubAnchors) { const ghLinkTokens = createLinkTokens(state, ghId, anchorTitle, true, href); (_b = inlineToken.children) === null || _b === void 0 ? void 0 : _b.unshift(...ghLinkTokens); } }); i += 3; continue; } i++; } }; try { md.core.ruler.after('includes', 'anchors', plugin); } catch (_a) { try { md.core.ruler.after('curly_attributes', 'anchors', plugin); } catch (_b) { md.core.ruler.push('anchors', plugin); } } md.renderer.rules.anchor_hidden_desc = function (tokens, index) { return ('<span class="visually-hidden" data-no-index="true">' + (0, utils_1.escapeHtml)(tokens[index].content) + '</span>'); }; }; module.exports = index; //# sourceMappingURL=index.js.map