@diplodoc/transform
Version:
A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML
79 lines • 4.13 kB
JavaScript
const path_1 = require("path");
const chalk_1 = require("chalk");
const fs_1 = require("fs");
const utilsFS_1 = require("../../utilsFS");
const includesPaths = [];
function processRecursive(relativePath, includePath, targetDestPath, options) {
var _a, _b;
const { path, log, copyFile, includedParentPath: includedParentPathNullable, included } = options;
const includedParentPath = includedParentPathNullable || [];
const includeOptions = Object.assign(Object.assign({}, options), { path: includePath, destPath: targetDestPath });
try {
const contentProcessed = copyFile(includePath, targetDestPath, includeOptions);
// To reduce file reading we can include the file content into the generated content
if (included !== false) {
const content = contentProcessed !== null && contentProcessed !== void 0 ? contentProcessed : (0, fs_1.readFileSync)(targetDestPath, 'utf8');
if (content) {
const key = [...includedParentPath, relativePath];
const hash = key.join(':');
// The appendix is the map that protects from multiple include files
if (!((_a = options.appendix) === null || _a === void 0 ? void 0 : _a.has(hash))) {
// Recursive function to include the depth structure
const includeContent = collectRecursive(content, Object.assign(Object.assign({}, options), { path: includePath, includedParentPath: key }));
// Add to appendix set structure
(_b = options.appendix) === null || _b === void 0 ? void 0 : _b.set(relativePath, `{% included (${hash}) %}\n${includeContent}\n{% endincluded %}`);
}
}
}
}
catch (e) {
log.error(`No such file or has no access to ${(0, chalk_1.bold)(includePath)} in ${(0, chalk_1.bold)(path)}`);
}
}
function collectRecursive(result, options) {
const { root, path, destPath = '', log, singlePage } = options;
const INCLUDE_REGEXP = /{%\s*include\s*(notitle)?\s*\[(.+?)]\((.+?)\)\s*%}/g;
let match;
while ((match = INCLUDE_REGEXP.exec(result)) !== null) {
let [, , , relativePath] = match;
const [matchedInclude] = match;
let includePath = (0, utilsFS_1.resolveRelativePath)(path, relativePath);
const hashIndex = relativePath.lastIndexOf('#');
if (hashIndex > -1 && !(0, utilsFS_1.isFileExists)(includePath)) {
includePath = includePath.slice(0, includePath.lastIndexOf('#'));
relativePath = relativePath.slice(0, hashIndex);
}
const targetDestPath = (0, utilsFS_1.resolveRelativePath)(destPath, relativePath);
if (includesPaths.includes(includePath)) {
log.error(`Circular includes: ${(0, chalk_1.bold)(includesPaths.concat(path).join(' ▶ '))}`);
break;
}
if (singlePage && !includesPaths.length) {
const newRelativePath = (0, path_1.relative)(root, includePath);
const newInclude = matchedInclude.replace(relativePath, newRelativePath);
result = result.replace(matchedInclude, newInclude);
const delta = matchedInclude.length - newInclude.length;
INCLUDE_REGEXP.lastIndex = INCLUDE_REGEXP.lastIndex - delta;
}
includesPaths.push(includePath);
processRecursive(relativePath, includePath, targetDestPath, options);
includesPaths.pop();
}
return result;
}
function collect(input, options) {
var _a;
const shouldWriteAppendix = !options.appendix;
options.appendix = (_a = options.appendix) !== null && _a !== void 0 ? _a : new Map();
input = collectRecursive(input, options);
if (shouldWriteAppendix) {
// Appendix should be appended to the end of the file (it supports depth structure, so the included files will have included as well)
if (options.appendix.size > 0) {
input += '\n' + [...options.appendix.values()].join('\n');
}
}
return input;
}
module.exports = collect;
//# sourceMappingURL=collect.js.map
;