UNPKG

@diplodoc/transform

Version:

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

110 lines 4.66 kB
"use strict"; const utils_1 = require("../utils"); const termDefinitions_1 = require("./termDefinitions"); const constants_1 = require("./constants"); const term = (md, options) => { const escapeRE = md.utils.escapeRE; const arrayReplaceAt = md.utils.arrayReplaceAt; const { isLintRun } = options; // Don't parse urls that starts with * const defaultLinkValidation = md.validateLink; md.validateLink = function (url) { if (url.startsWith('*')) { return false; } return defaultLinkValidation(url); }; function termReplace(state) { let i, j, l, tokens, token, text, nodes, pos, term, currentToken; const blockTokens = state.tokens; if (!state.env.terms) { return; } const regTerms = Object.keys(state.env.terms) .map((el) => el.substr(1)) .map(escapeRE) .join('|'); const regText = '\\[([^\\[]+)\\](\\(\\*(' + regTerms + ')\\))'; const reg = new RegExp(regText, 'g'); for (j = 0, l = blockTokens.length; j < l; j++) { if (blockTokens[j].type === 'heading_open') { while (blockTokens[j].type !== 'heading_close') { j++; } continue; } if (blockTokens[j].type !== 'inline') { continue; } tokens = blockTokens[j].children; for (i = tokens.length - 1; i >= 0; i--) { currentToken = tokens[i]; if (currentToken.type === 'link_close') { while (tokens[i].type !== 'link_open') { i--; } continue; } if (!(currentToken.type === 'text')) { continue; } pos = 0; text = currentToken.content; reg.lastIndex = 0; nodes = []; // Find terms without definitions const regexAllTerms = new RegExp(constants_1.BASIC_TERM_REGEXP, 'gm'); const uniqueTerms = [ ...new Set([...text.matchAll(regexAllTerms)].map((el) => `:${el[3]}`)), ]; const notDefinedTerms = uniqueTerms.filter((el) => !Object.keys(state.env.terms).includes(el)); if (notDefinedTerms.length && isLintRun) { token = new state.Token('__yfm_lint', '', 0); token.hidden = true; token.map = blockTokens[j].map; token.attrSet('YFM007', 'true'); nodes.push(token); } while ((term = reg.exec(text))) { const termTitle = term[1]; const termKey = term[3]; if (term.index > 0 || term[1].length > 0) { token = new state.Token('text', '', 0); token.content = text.slice(pos, term.index); nodes.push(token); } token = new state.Token('term_open', 'i', 1); token.attrSet('class', 'yfm yfm-term_title'); token.attrSet('term-key', ':' + termKey); token.attrSet('role', 'button'); token.attrSet('aria-describedby', ':' + termKey + '_element'); token.attrSet('tabindex', '0'); token.attrSet('id', (0, utils_1.generateID)()); nodes.push(token); token = new state.Token('text', '', 0); token.content = termTitle; nodes.push(token); token = new state.Token('term_close', 'i', -1); nodes.push(token); pos = reg.lastIndex; } if (!nodes.length) { continue; } if (pos < text.length) { token = new state.Token('text', '', 0); token.content = text.slice(pos); nodes.push(token); } // replace current node blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes); } } } md.block.ruler.before('reference', 'termDefinitions', (0, termDefinitions_1.termDefinitions)(md, options), { alt: ['paragraph', 'reference'], }); md.core.ruler.after('linkify', 'termReplace', termReplace); }; module.exports = term; //# sourceMappingURL=index.js.map