UNPKG

markugen

Version:

Markdown to HTML/PDF static site generation tool

100 lines (99 loc) 3.51 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Preprocessor = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); const node_path_1 = __importDefault(require("node:path")); const node_os_1 = __importDefault(require("node:os")); const colors_1 = __importDefault(require("colors")); const markugen_1 = __importDefault(require("./markugen")); class Preprocessor { /** * The regular expression used to find the templates */ regex = /\{\{([^{].*?[^\\])\}\}/gs; /** * The regular expression used to filter the js code */ filter = /(\\\}\})|(process\s*.\s*exit\s*\(.*?\))|(import\s*\(.*?\))/gs; /** * Instance of the generator */ generator; /** * Variables to define before template expansion */ vars; /** * Constructs a new preprocessor with the given variables */ constructor(generator) { this.generator = generator; this.vars = structuredClone(generator.options.vars); this.vars['markugen'] = markugen_1.default.toObject(generator.options.timestamp ? new Date() : undefined); } /** * Expands the given string by replacing template parameters * @param input the string to expand * @param file file being expanded if given one * @returns input expanded and template vars replaced */ process(input, file) { if (!input) return input; // copy the string so as to not modify the original let out = ''; let match, lastIndex = 0; while ((match = this.regex.exec(input)) !== null) { const last = lastIndex; lastIndex = this.regex.lastIndex; // check for an escaped template expansion if (match.index && input[match.index - 1] === '\\') { out += input.slice(last, match.index - 1) + match[0]; continue; } out += input.slice(last, match.index); // if the expression is empty const code = match[1]; if (code.trim() === '') continue; const result = this.safeFunction(code, file); if (result != undefined) out += result.toString(); } if (lastIndex < input.length) out += input.slice(lastIndex); return out; } /** * * @param code the code to execute * @param file file being expanded if given one * @returns whatever is returned from the code call */ safeFunction(code, file) { const filtered = code.replace(this.filter, (match, p1) => { if (p1) return '}}'; return ''; }); const safe = `'use strict';\n${filtered}`; const utils = { fs: fs_extra_1.default, path: node_path_1.default, os: node_os_1.default, }; try { const func = Function('vars', 'utils', safe); const result = func(this.vars, utils); return result; } catch (e) { this.generator.warning(`Preprocesser failed when expanding ${colors_1.default.yellow(`{{${filtered}}}`)} ` + colors_1.default.red(`[${e.message}` + (file ? ` in ${file}]` : ']'))); } } } exports.Preprocessor = Preprocessor;