UNPKG

@diplodoc/transform

Version:

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

157 lines 6.04 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; const chalk_1 = require("chalk"); const log_1 = require("../log"); const evaluation_1 = require("./evaluation"); const lexical_1 = require("./lexical"); const utils_1 = require("./utils"); const sourceMap_1 = require("./sourceMap"); const index_1 = __importDefault(require("./index")); function changeSourceMap({ firstLineNumber, lastLineNumber, resFirstLineNumber, resLastLineNumber, contentLinesTotal, linesTotal, sourceMap, }) { if (!sourceMap) { return; } const isInlineTag = firstLineNumber === lastLineNumber; const { moveLines, removeLine } = (0, sourceMap_1.createSourceMapApi)(sourceMap); if (isInlineTag || !resFirstLineNumber) { return; } const offsetRestLines = contentLinesTotal - (lastLineNumber - firstLineNumber + 1); // Move condition's content to the top const offsetContentLines = firstLineNumber - resFirstLineNumber; moveLines({ start: resFirstLineNumber, end: resLastLineNumber - 1, offset: offsetContentLines, withReplace: true, }); // Remove tags removeLine(firstLineNumber); removeLine(lastLineNumber); // Offset the rest lines moveLines({ start: lastLineNumber + 1, end: linesTotal, offset: offsetRestLines }); } function inlineConditions({ forTag, vars, content, match, path, lastIndex, sourceMap, linesTotal, }) { let res = ''; const firstLineNumber = (0, sourceMap_1.getLineNumber)(content, forTag.startPos); const lastLineNumber = (0, sourceMap_1.getLineNumber)(content, lastIndex); const forRawLastIndex = forTag.startPos + forTag.forRaw.length; const contentLastIndex = match.index; const forTemplate = content.substring(forRawLastIndex, contentLastIndex); const resFirstLineNumber = (0, sourceMap_1.getLineNumber)(content, forRawLastIndex + 1); const resLastLineNumber = (0, sourceMap_1.getLineNumber)(content, contentLastIndex + 1); let collection = (0, evaluation_1.evalExp)(forTag.collectionName, vars); if (!collection || !Array.isArray(collection)) { collection = []; log_1.log.error(`${(0, chalk_1.bold)(forTag.collectionName)} is undefined or not iterable`); } collection.forEach((item) => { const newVars = Object.assign(Object.assign({}, vars), { [forTag.variableName]: item }); res += (0, index_1.default)(forTemplate, newVars, path).trimRight(); }); const contentLinesTotal = res.split('\n').length - 1; changeSourceMap({ firstLineNumber, lastLineNumber, resFirstLineNumber, resLastLineNumber, linesTotal, sourceMap, contentLinesTotal, }); const preparedLeftContent = (0, utils_1.getPreparedLeftContent)({ content, tagStartPos: forTag.startPos, tagContent: res, }); let shift = 0; if (res === '' && preparedLeftContent[preparedLeftContent.length - 1] === '\n' && content[lastIndex] === '\n') { shift = 1; } if (res !== '') { if (res[0] === ' ' || res[0] === '\n') { res = res.substring(1); } } const leftPart = preparedLeftContent + res; return { result: leftPart + content.substring(lastIndex + shift), idx: leftPart.length, }; } module.exports = function cycles(originInput, vars, path, settings = {}) { const { sourceMap } = settings; const R_LIQUID = /({%-?([\s\S]*?)-?%})/g; const FOR_SYNTAX = new RegExp(`(\\w+)\\s+in\\s+(${lexical_1.variable.source})`); let match; const tagStack = []; let input = originInput; let countSkippedInnerTags = 0; let linesTotal = originInput.split('\n').length; while ((match = R_LIQUID.exec(input)) !== null) { if (!match[1]) { continue; } const tagMatch = match[2].trim().match(lexical_1.tagLine); if (!tagMatch) { continue; } const [type, args] = tagMatch.slice(1); switch (type) { case 'for': { if (tagStack.length) { countSkippedInnerTags += 1; break; } const matches = args.match(FOR_SYNTAX); if (!matches) { log_1.log.error(`Incorrect syntax in if condition${path ? ` in ${(0, chalk_1.bold)(path)}` : ''}`); break; } const [variableName, collectionName] = matches.slice(1); tagStack.push({ item: args, variableName, collectionName, startPos: match.index, forRaw: match[1], }); break; } case 'endfor': { if (countSkippedInnerTags > 0) { countSkippedInnerTags -= 1; break; } const forTag = tagStack.pop(); if (!forTag) { log_1.log.error(`For block must be opened before close${path ? ` in ${(0, chalk_1.bold)(path)}` : ''}`); break; } const { idx, result } = inlineConditions({ forTag, vars, content: input, match, path, lastIndex: R_LIQUID.lastIndex, sourceMap: sourceMap || {}, linesTotal, }); R_LIQUID.lastIndex = idx; input = result; linesTotal = result.split('\n').length; break; } } } if (tagStack.length !== 0) { log_1.log.error(`For block must be closed${path ? ` in ${(0, chalk_1.bold)(path)}` : ''}`); } return input; }; //# sourceMappingURL=cycles.js.map