UNPKG

@diplodoc/transform

Version:

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

100 lines 4.61 kB
"use strict"; const chalk_1 = require("chalk"); const utils_1 = require("../utils"); const constants_1 = require("./constants"); const ALERT_RE = /^{% note (alert|info|tip|warning)\s*(?:"(.*?)")? %}$/; const WRONG_NOTES = /^{% note (.*)%}/; function getTitle(type, originLang) { let lang = originLang; if (!lang || !Object.keys(constants_1.TITLES).includes(lang)) { lang = 'ru'; } return constants_1.TITLES[lang][type]; } const matchCloseToken = (tokens, i) => { return (tokens[i].type === 'paragraph_open' && tokens[i + 1].type === 'inline' && tokens[i + 1].content.trim() === '{% endnote %}'); }; function matchOpenToken(tokens, i) { return (tokens[i].type === 'paragraph_open' && tokens[i + 1].type === 'inline' && tokens[i + 1].content.match(ALERT_RE)); } function matchWrongNotes(tokens, i) { return (tokens[i].type === 'paragraph_open' && tokens[i + 1].type === 'inline' && tokens[i + 1].content.match(WRONG_NOTES)); } const findCloseTokenIdx = (0, utils_1.nestedCloseTokenIdxFactory)('Note', matchOpenToken, matchCloseToken); // @ts-ignore const index = (md, { lang, notesAutotitle, path: optPath, log }) => { notesAutotitle = typeof notesAutotitle === 'boolean' ? notesAutotitle : true; const plugin = (state) => { const { tokens, env } = state; const path = env.path || optPath; let i = 0; while (i < tokens.length) { const match = matchOpenToken(tokens, i); if (match) { // Skip paragraph_close for open token (+1) and paragraph_open for close token (+1) // This is minimal useless content length const closeTokenIdx = findCloseTokenIdx(tokens, i + 2, path, log); if (!closeTokenIdx) { i += 3; continue; } const type = match[1].toLowerCase(); const newOpenToken = new state.Token('yfm_note_open', 'div', 1); newOpenToken.attrSet('class', `yfm-note yfm-accent-${type}`); newOpenToken.attrSet('note-type', type); newOpenToken.map = tokens[i].map; const closeTokenMap = tokens[closeTokenIdx].map; if (closeTokenMap && newOpenToken.map) { newOpenToken.map[1] = closeTokenMap[1]; } const newCloseToken = new state.Token('yfm_note_close', 'div', -1); newCloseToken.map = tokens[closeTokenIdx].map; // Add extra paragraph const titleOpen = new state.Token('yfm_note_title_open', 'p', 1); titleOpen.attrSet('class', 'yfm-note-title'); const titleInline = new state.Token('inline', '', 0); const titleClose = new state.Token('yfm_note_title_close', 'p', -1); titleOpen.block = true; titleClose.block = true; const autotitle = notesAutotitle ? getTitle(type, lang) : ''; titleInline.content = match[2] === undefined ? autotitle : match[2]; titleInline.children = []; const contentOpen = new state.Token('yfm_note_content_open', 'div', 1); contentOpen.attrSet('class', 'yfm-note-content'); const contentClose = new state.Token('yfm_note_content_close', 'div', -1); if (newOpenToken.map) { contentOpen.map = [newOpenToken.map[0] + 2, newOpenToken.map[1] - 2]; } state.md.inline.parse(titleInline.content, state.md, state.env, titleInline.children); const insideTokens = [newOpenToken]; if (titleInline.content) { insideTokens.push(titleOpen, titleInline, titleClose); } insideTokens.push(contentOpen, ...tokens.slice(i + 3, closeTokenIdx), contentClose, newCloseToken); tokens.splice(i, closeTokenIdx - i + 3, ...insideTokens); i++; } else if (matchWrongNotes(tokens, i) && tokens[i + 1].content !== '{% endnote %}') { log.warn(`Incorrect syntax for notes${path ? `, file ${(0, chalk_1.bold)(path)}` : ''}`); i += 3; } else { i++; } } }; try { md.core.ruler.before('curly_attributes', 'notes', plugin); } catch (e) { md.core.ruler.push('notes', plugin); } }; module.exports = index; //# sourceMappingURL=index.js.map