"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const immutable_1 = __importDefault(require("immutable")); const nunjucks_1 = __importDefault(require("nunjucks")); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const path_2 = __importDefault(require("../utils/path")); const ThemesLoader = nunjucks_1.default.Loader.extend({ // @ts-expect-error: Property 'extend' does not exist on type 'typeof Loader'. init: function (searchPaths) { this.searchPaths = immutable_1.default.List(searchPaths).map(path_1.default.normalize); }, /** * Read source of a resolved filepath * @param {string} * @return {Object} */ getSource: function (fullpath) { if (!fullpath) return null; fullpath = this.resolve(null, fullpath); const templateName = this.getTemplateName(fullpath); if (!fullpath) { return null; } let src = fs_1.default.readFileSync(fullpath, "utf-8"); src = `{% do %}var template = template || {}; template.stack = template.stack || []; template.stack.push(template.self); template.self = ${JSON.stringify(templateName)}{% enddo %}\n${src}\n{% do %}template.self = template.stack.pop();{% enddo %}`; return { src: src, path: fullpath, noCache: true }; }, /** * Nunjucks calls "isRelative" to determine when to call "resolve". * We handle absolute paths ourselves in ".resolve" so we always return true */ isRelative: function () { return true; }, /** * Get original search path containing a template * @param {string} filepath * @return {string} searchPath */ getSearchPath: function (filepath) { return this.searchPaths .sortBy((s) => { return -s.length; }) .find((basePath) => { return filepath && filepath.indexOf(basePath) === 0; }); }, /** * Get template name from a filepath * @param {string} filepath * @return {string} name */ getTemplateName: function (filepath) { const originalSearchPath = this.getSearchPath(filepath); return originalSearchPath ? path_1.default.relative(originalSearchPath, filepath) : null; }, /** * Resolve a template from a current template * @param {String|null} from * @param {string} to * @return {String|null} */ resolve: function (from, to) { let searchPaths = this.searchPaths; // Relative template like "./test.html" if (path_2.default.isPureRelative(to) && from) { return path_1.default.resolve(path_1.default.dirname(from), to); } // Determine in which search folder we currently are const originalSearchPath = this.getSearchPath(from); const originalFilename = this.getTemplateName(from); // If we are including same file from a different search path // Slice the search paths to avoid including from previous ones if (originalFilename == to) { const currentIndex = searchPaths.indexOf(originalSearchPath); searchPaths = searchPaths.slice(currentIndex + 1); } // Absolute template to resolve in root folder const resultFolder = searchPaths.find((basePath) => { const p = path_1.default.resolve(basePath, to); return p.indexOf(basePath) === 0 && fs_1.default.existsSync(p); }); if (!resultFolder) return null; return path_1.default.resolve(resultFolder, to); } }); exports.default = ThemesLoader;