@diplodoc/transform
Version:
A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML
157 lines • 6.04 kB
JavaScript
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
;