@diplodoc/transform
Version:
A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML
133 lines • 5.78 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.liquidSnippet = exports.liquidDocument = void 0;
const cloneDeepWith_1 = __importDefault(require("lodash/cloneDeepWith"));
const frontmatter_1 = require("../frontmatter");
const substitutions_1 = __importDefault(require("./substitutions"));
const sourceMap_1 = require("./sourceMap");
const cycles_1 = __importDefault(require("./cycles"));
const conditions_1 = __importDefault(require("./conditions"));
const argv_1 = __importDefault(require("./services/argv"));
const fence = '```';
const find = (open, close, string, index) => {
const start = string.indexOf(open, index);
const end = start > -1 ? string.indexOf(close, start + open.length) : -1;
return [start, end];
};
const replace = (open, close, value, string) => {
let result = '';
let carriage = 0;
let [start, end] = find(open, close, string, carriage);
while (start > -1 && end > -1) {
const fragment = string.slice(start + open.length, end);
result += string.slice(carriage, start) + open + value(fragment) + close;
carriage = end + close.length;
[start, end] = find(open, close, string, carriage);
}
result += string.slice(carriage);
return result;
};
function saveCode(str, vars, codes, path, substitutions) {
return replace(fence, fence, (code) => {
const codeWithVars = substitutions ? (0, substitutions_1.default)(code, vars, path) : code;
const index = codes.push(codeWithVars) - 1;
/* Keep the same count of lines to avoid transformation of the source map */
const codeLines = codeWithVars.split('\n');
const emptyLines = codeLines.length > 1 ? '\n'.repeat(codeLines.length) : '';
return `${index}${emptyLines}`;
}, str);
}
function repairCode(str, codes) {
return replace(fence, fence, (code) => codes[Number(code)], str);
}
function liquidSnippet(originInput, vars, path, settings) {
const { cycles = true, conditions = true, substitutions = true, conditionsInCode = false, useLegacyConditions = false, keepNotVar = false, withSourceMap, } = settings || {};
argv_1.default.init({
cycles,
conditions,
substitutions,
conditionsInCode,
useLegacyConditions,
keepNotVar,
withSourceMap,
});
const codes = [];
let output = conditionsInCode
? originInput
: saveCode(originInput, vars, codes, path, substitutions);
let sourceMap = {};
if (withSourceMap) {
const lines = output.split('\n');
sourceMap = lines.reduce((acc, _cur, index) => {
acc[index + 1] = index + 1;
return acc;
}, {});
}
if (cycles) {
output = (0, cycles_1.default)(output, vars, path, { sourceMap });
}
if (conditions) {
const strict = conditions === 'strict';
output = (0, conditions_1.default)(output, vars, path, { sourceMap, strict, useLegacyConditions });
}
if (substitutions) {
output = (0, substitutions_1.default)(output, vars, path);
}
if (!conditionsInCode && typeof output === 'string') {
output = repairCode(output, codes);
}
codes.length = 0;
if (withSourceMap) {
return {
output,
sourceMap: (0, sourceMap_1.prepareSourceMap)(sourceMap),
};
}
return output;
}
exports.liquidSnippet = liquidSnippet;
function linesCount(content) {
let count = 1, index = -1;
while ((index = content.indexOf('\n', index + 1)) > -1) {
count++;
}
return count;
}
function liquidDocument(input, vars, path, settings) {
const [frontMatter, strippedContent] = (0, frontmatter_1.extractFrontMatter)(input, path);
const liquidedFrontMatter = (0, cloneDeepWith_1.default)(frontMatter, (value) => typeof value === 'string'
? liquidSnippet(value, vars, path, Object.assign(Object.assign({}, settings), { withSourceMap: false }))
: undefined);
const liquidedResult = liquidSnippet(strippedContent, vars, path, settings);
const liquidedContent = typeof liquidedResult === 'object' ? liquidedResult.output : liquidedResult;
const output = (0, frontmatter_1.composeFrontMatter)(liquidedFrontMatter, liquidedContent);
if (typeof liquidedResult === 'object') {
const inputLinesCount = linesCount(input);
const outputLinesCount = linesCount(output);
const contentLinesCount = linesCount(strippedContent);
const contentLinesDiff = linesCount(liquidedContent) - contentLinesCount;
const fullLinesDiff = outputLinesCount - inputLinesCount;
// Always >= 0
const sourceOffset = inputLinesCount - contentLinesCount;
// Content lines diff already counted in source map
const resultOffset = fullLinesDiff - contentLinesDiff;
liquidedResult.sourceMap = Object.fromEntries(Object.entries(liquidedResult.sourceMap).map(([lineInResult, lineInSource]) => [
(Number(lineInResult) + resultOffset).toString(),
(Number(lineInSource) + sourceOffset).toString(),
]));
}
// typeof check for better inference; the catch is that return of liquidSnippet can be an
// object even with source maps off, see `substitutions.test.ts`
return ((settings === null || settings === void 0 ? void 0 : settings.withSourceMap) && typeof liquidedResult === 'object'
? {
output,
sourceMap: liquidedResult.sourceMap,
}
: output);
}
exports.liquidDocument = liquidDocument;
exports.default = liquidDocument;
//# sourceMappingURL=index.js.map