UNPKG

@diplodoc/transform

Version:

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

99 lines 4.6 kB
"use strict"; const chalk_1 = require("chalk"); const utils_1 = require("../utils"); const constants_1 = require("../../constants"); const constants_2 = require("./constants"); const ALERT_RE = /^{% note (alert|info|tip|warning)\s*(?:"(.*?)")? %}$/; const WRONG_NOTES = /^{% note (.*)%}/; const matchCloseToken = (tokens, i) => { return (tokens[i].type === 'paragraph_open' && tokens[i + 1].type === 'inline' && tokens[i + 1].content.trim() === '{% endnote %}'); }; function getTitle(type, originLang) { let lang = originLang; if (!lang || !Object.keys(constants_2.TITLES).includes(lang)) { lang = constants_1.DEFAULT_LANG; } return constants_2.TITLES[lang][type]; } 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); const index = (md, { lang = constants_1.DEFAULT_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 autotitle = notesAutotitle ? getTitle(type, lang) : ''; const titleContent = match[2] === undefined ? autotitle : match[2]; const titleInline = state.md.parseInline(titleContent, state.env)[0]; titleInline.map = null; const titleClose = new state.Token('yfm_note_title_close', 'p', -1); titleOpen.block = true; titleClose.block = true; 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]; } 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