UNPKG

statigen

Version:

A static site generator that supports html, ejs, and markdown source files

212 lines 8.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Project = void 0; const PluginManager_1 = require("./PluginManager"); const InternalPlugin_1 = require("./InternalPlugin"); const diagnosticUtils_1 = require("./diagnosticUtils"); const path = require("path"); const util_1 = require("./util"); const DiagnosticMessages_1 = require("./DiagnosticMessages"); const Tree_1 = require("./Tree"); const fsExtra = require("fs-extra"); class Project { constructor(options) { this.pluginManager = new PluginManager_1.default(); /** * Map of all files in the project, indexed by absolute path */ this.files = new Map(); this.pluginManager.add(new InternalPlugin_1.InternalPlugin()); this.setOptions(options); } /** * Get the diagnostics from all files */ getDiagnostics() { const result = []; for (const file of this.files.values()) { result.push(...file.diagnostics); } return result; } /** * Get the file with the specified path */ getFile(filePath) { filePath = path.resolve(this.options.sourceDir, filePath).replace(/[\\\/]/g, path.sep); return this.files.get(filePath); } /** * Get a tree of all the html files based on their output paths */ getTree() { if (!this.cache.tree) { this.cache.tree = new Tree_1.Tree(undefined, undefined, undefined); for (let file of this.files.values()) { const filename = path.basename(file.outPath); //skip files starting with underscore, and skip all non-html files if (filename.startsWith('_') || !filename.toLowerCase().endsWith('.html')) { continue; } const relativePath = file.outPath.replace(this.options.outDir + path.sep, '').replace(/\.\w$/, ''); this.cache.tree.add(relativePath, file); } this.cache.tree.sort(); } return this.cache.tree; } setFile(param) { var _a; let srcPath; let outPath; if (typeof param === 'string') { srcPath = path.resolve(this.options.sourceDir, param); outPath = (0, util_1.replacePath)(path.resolve(this.options.outDir, param), this.options.sourceDir, this.options.outDir); } else { srcPath = path.resolve(this.options.sourceDir, param.src); outPath = path.resolve(this.options.outDir, param.dest); } let file = this.files.get(srcPath); //add the file if (!file) { file = this.pluginManager.getFirst('provideFile', { project: this, srcPath: srcPath, outPath: outPath }); //link this project to the file file.project = this; this.files.set(srcPath, file); this.pluginManager.emit('onFileAdd', { project: this, file: file }); } this.pluginManager.emit('beforeFileLoad', { project: this, file: file }); //if the file has a load function (_a = file.load) === null || _a === void 0 ? void 0 : _a.call(file); this.pluginManager.emit('afterFileLoad', { project: this, file: file }); return file; } /** * Remove a file from the project */ removeFile(srcPath) { srcPath = path.resolve(this.options.sourceDir, srcPath); const file = this.files.get(srcPath); if (file) { this.pluginManager.emit('onFileRemove', { project: this, file: file }); this.files.delete(srcPath); //delete the file from the outDir too if (fsExtra.pathExistsSync(file.outPath)) { fsExtra.removeSync(file.outPath); } } } /** * Validate the entire project */ validate() { var _a, _b; for (const file of this.files.values()) { file.diagnostics = []; this.pluginManager.emit('beforeFileValidate', { project: this, file: file }); (_a = file.validate) === null || _a === void 0 ? void 0 : _a.call(file); this.pluginManager.emit('afterFileValidate', { project: this, file: file }); for (const diagnostic of (_b = file.diagnostics) !== null && _b !== void 0 ? _b : []) { (0, diagnosticUtils_1.printDiagnostic)(diagnostic); } } } /** * Determine if the given file exists somewhere within the sourceDir */ fileResidesInSourceDir(file) { return file.srcPath.startsWith(this.options.sourceDir); } /** * Get the template file for a given file */ getTemplateFile(file) { var _a; //if the file specified a template, use that file (even if it doesn't exist...) if (file.attributes.template) { const templateSrcPath = (0, util_1.standardizePath)(path.dirname(file.srcPath), file.attributes.template); if (!this.files.has(templateSrcPath)) { file.diagnostics.push(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.missingTemplate(templateSrcPath))); } return this.files.get(templateSrcPath); //files outside of sourceDir } else if (!this.fileResidesInSourceDir(file)) { return (_a = this.files.get((0, util_1.standardizePath)(path.dirname(file.srcPath), '_template.html'))) !== null && _a !== void 0 ? _a : this.files.get((0, util_1.standardizePath)(path.dirname(file.srcPath), '_template.ejs')); //files inside sourceDir } else { //walk up the directory tree and use the closest _template.{ejs,html} file let dir = file.srcPath.replace(this.options.sourceDir + path.sep, ''); // eslint-disable-next-line no-cond-assign while (dir = path.dirname(dir)) { for (const ext of ['.ejs', '.html']) { const templatePath = path.resolve(this.options.sourceDir, path.normalize(path.join(dir, '_template' + ext))); if (this.files.has(templatePath)) { return this.files.get(templatePath); } } //quit the loop if we didn't find a template if (dir === '.') { return; } } } } /** * Given a file, look up its template and then generate the output text * using the ejs templating engine. * If the template could not be found, the content is returned as-is */ generateWithTemplate(file, content) { var _a; const templateFile = this.getTemplateFile(file); if (templateFile === null || templateFile === void 0 ? void 0 : templateFile.renderAsTemplate) { //return template rendered (or empty string) return (_a = templateFile.renderAsTemplate(file, content)) !== null && _a !== void 0 ? _a : ''; } else { //no template was found. return the content as-is (or empty string) return content !== null && content !== void 0 ? content : ''; } } publish() { var _a; this.cache = {}; for (const file of this.files.values()) { this.pluginManager.emit('beforeFilePublish', { project: this, file: file }); const startsWithUnderscore = path.basename(file.srcPath).startsWith('_'); //skip publishing if the file starts with an underscore, or if the if (!startsWithUnderscore) { (_a = file.publish) === null || _a === void 0 ? void 0 : _a.call(file); } this.pluginManager.emit('afterFilePublish', { project: this, file: file }); } } /** * Sanitize the given options in-place */ setOptions(options) { var _a; this.options = {}; this.options.cwd = (0, util_1.standardizePath)(process.cwd(), options.cwd).replace(/[\\\/]+$/, ''); this.options.sourceDir = this.resolvePath(options.sourceDir, 'src').replace(/[\\\/]+$/, ''); this.options.outDir = this.resolvePath(options.outDir, 'dist').replace(/[\\\/]+$/, ''); this.options.files = (_a = options.files) !== null && _a !== void 0 ? _a : ['**/*']; this.options.watch = options.watch === true; return options; } /** * Given a path, convert to an absolute path and use the current OS path.sep */ resolvePath(thePath, defaultValue) { return path.normalize(path.resolve(this.options.cwd, thePath !== null && thePath !== void 0 ? thePath : defaultValue)).replace(/[\\\/]/g, path.sep); } } exports.Project = Project; //# sourceMappingURL=Project.js.map