@diplodoc/transform
Version:
A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML
174 lines • 6.72 kB
JavaScript
"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 = __importDefault(require("./evaluation"));
const lexical_1 = require("./lexical");
const utils_1 = require("./utils");
const sourceMap_1 = require("./sourceMap");
function changeSourceMap({ firstLineNumber, lastLineNumber, resFirstLineNumber, resLastLineNumber, linesTotal, sourceMap, }) {
if (!sourceMap) {
return;
}
const { getSourceMapValue, moveLines, removeLines } = (0, sourceMap_1.createSourceMapApi)(sourceMap);
let offsetRestLines;
if (resFirstLineNumber) {
// Move condition's content to the top
const offsetContentLines = firstLineNumber - resFirstLineNumber;
moveLines({
start: resFirstLineNumber,
end: resLastLineNumber - 1,
offset: offsetContentLines,
withReplace: true,
});
// Remove the rest lines of the condition block
removeLines({ start: firstLineNumber, end: resFirstLineNumber - 1 });
removeLines({ start: resLastLineNumber, end: lastLineNumber });
// Calculate an offset of the rest lines
offsetRestLines = getSourceMapValue(resLastLineNumber - 1) - lastLineNumber;
}
else {
// Remove the whole condition block
removeLines({ start: firstLineNumber, end: lastLineNumber });
// Calculate offset of the rest lines
offsetRestLines = firstLineNumber - lastLineNumber - 1;
}
// Offset the rest lines
moveLines({ start: lastLineNumber + 1, end: linesTotal, offset: offsetRestLines });
}
function getElseProp({ elses }, propName, index = 0) {
if (!elses.length || index >= elses.length) {
return undefined;
}
return elses[index][propName];
}
function inlineConditions({ ifTag, vars, content, match, lastIndex, sourceMap, linesTotal }) {
let res = '';
const firstLineNumber = (0, sourceMap_1.getLineNumber)(content, ifTag.startPos);
const lastLineNumber = (0, sourceMap_1.getLineNumber)(content, lastIndex);
let resFirstLineNumber = 0;
let resLastLineNumber = 0;
if ((0, evaluation_1.default)(ifTag.condition, vars)) {
const ifRawLastIndex = ifTag.startPos + ifTag.ifRaw.length;
const contentLastIndex = getElseProp(ifTag, 'startPos') || match.index;
res = content.substring(ifRawLastIndex, contentLastIndex);
resFirstLineNumber = (0, sourceMap_1.getLineNumber)(content, ifRawLastIndex + 1);
resLastLineNumber = (0, sourceMap_1.getLineNumber)(content, contentLastIndex + 1);
}
else {
ifTag.elses.some(({ condition, startPos, raw }, index) => {
const isTruthy = !condition || (0, evaluation_1.default)(condition, vars);
if (isTruthy) {
const elseRawLastIndex = startPos + raw.length;
const contentLastIndex = getElseProp(ifTag, 'startPos', index + 1) || match.index;
res = content.substring(elseRawLastIndex, contentLastIndex);
resFirstLineNumber = (0, sourceMap_1.getLineNumber)(content, elseRawLastIndex + 1);
resLastLineNumber = (0, sourceMap_1.getLineNumber)(content, contentLastIndex + 1);
return true;
}
return false;
});
}
changeSourceMap({
firstLineNumber,
lastLineNumber,
resFirstLineNumber,
resLastLineNumber,
linesTotal,
sourceMap,
});
const preparedLeftContent = (0, utils_1.getPreparedLeftContent)({
content,
tagStartPos: ifTag.startPos,
tagContent: res,
});
let shift = 0;
if (res === '' &&
preparedLeftContent[preparedLeftContent.length - 1] === '\n' &&
content[lastIndex] === '\n') {
shift = 1;
}
if (res !== '') {
if (res[0] === '\n') {
res = res.substring(1);
}
res = (0, utils_1.removeIndentBlock)(res);
if (res[res.length - 1] === '\n') {
res = res.slice(0, -1);
}
}
const leftPart = preparedLeftContent + res;
return {
result: leftPart + content.substring(lastIndex + shift),
idx: leftPart.length,
};
}
module.exports = function legacyConditions(originInput, vars, path, settings) {
const sourceMap = (settings === null || settings === void 0 ? void 0 : settings.sourceMap) || {};
const R_LIQUID = /({%-?([\s\S]*?)-?%})/g;
let match;
const tagStack = [];
let input = originInput;
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 'if':
tagStack.push({
isOpen: true,
condition: args,
startPos: match.index,
ifRaw: match[1],
elses: [],
});
break;
case 'else':
tagStack[tagStack.length - 1].elses.push({
startPos: match.index,
raw: match[1],
});
break;
case 'elsif':
tagStack[tagStack.length - 1].elses.push({
condition: args,
startPos: match.index,
raw: match[1],
});
break;
case 'endif': {
const ifTag = tagStack.pop();
if (!ifTag) {
log_1.log.error(`If block must be opened before close${path ? ` in ${(0, chalk_1.bold)(path)}` : ''}`);
break;
}
const { idx, result } = inlineConditions({
ifTag,
vars,
content: input,
match,
lastIndex: R_LIQUID.lastIndex,
sourceMap,
linesTotal,
});
R_LIQUID.lastIndex = idx;
input = result;
linesTotal = result.split('\n').length;
break;
}
}
}
if (tagStack.length !== 0) {
log_1.log.error(`Condition block must be closed${path ? ` in ${(0, chalk_1.bold)(path)}` : ''}`);
}
return input;
};
//# sourceMappingURL=legacyConditions.js.map