UNPKG

@diplodoc/transform

Version:

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

79 lines 4.13 kB
"use strict"; 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