158 lines
5.1 KiB
JavaScript

"use strict";
require("../");
const path = require("path");
const resolveFrom = require("resolve-from");
const fs = require("fs");
const fsReadOptions = { encoding: "utf8" };
const MARKO_EXTENSIONS = Symbol("MARKO_EXTENSIONS");
function normalizeExtension(extension) {
if (extension.charAt(0) !== ".") {
extension = "." + extension;
}
return extension;
}
function compile(templatePath, markoCompiler, compilerOptions) {
if (compilerOptions) {
compilerOptions = Object.assign(
{},
markoCompiler.defaultOptions,
compilerOptions
);
} else {
compilerOptions = markoCompiler.defaultOptions;
}
var writeToDisk = compilerOptions.writeToDisk;
var templateSrc;
var compiledSrc;
if (writeToDisk === false) {
// Don't write the compiled template to disk. Instead, load it
// directly from the compiled source using the internals of the
// Node.js module loading system.
templateSrc = fs.readFileSync(templatePath, fsReadOptions);
compiledSrc = markoCompiler.compile(templateSrc, templatePath);
} else {
var targetFile = templatePath + ".js";
if (
markoCompiler.defaultOptions.assumeUpToDate &&
fs.existsSync(targetFile)
) {
// If the target file already exists and "assumeUpToDate" then just use the previously
// compiled template.
return fs.readFileSync(targetFile, fsReadOptions);
}
var targetDir = path.dirname(templatePath);
var isUpToDate = markoCompiler.checkUpToDate(targetFile);
if (isUpToDate) {
compiledSrc = fs.readFileSync(targetFile, fsReadOptions);
} else {
templateSrc = fs.readFileSync(templatePath, fsReadOptions);
compiledSrc = markoCompiler.compile(
templateSrc,
templatePath,
compilerOptions
);
// Write to a temporary file and move it into place to avoid problems
// assocatiated with multiple processes write to the same file. We only
// write the compiled source code to disk so that stack traces will
// be accurate.
var filename = path.basename(targetFile);
var tempFile = path.join(
targetDir,
"." + process.pid + "." + Date.now() + "." + filename
);
fs.writeFileSync(tempFile, compiledSrc, fsReadOptions);
fs.renameSync(tempFile, targetFile);
}
}
// We attach a path to the compiled template so that hot reloading will work.
return compiledSrc;
}
function getLoadedTemplate(path) {
var cached = require.cache[path];
return cached && cached.exports.render ? cached.exports : undefined;
}
function install(options) {
options = options || {};
var requireExtensions = options.require // options.require introduced for testing
? options.require.extensions
: require.extensions;
var compilerOptions = Object.assign(
{ requireTemplates: true },
options.compilerOptions
);
require("../compiler").configure(compilerOptions);
var extensions = [];
if (options.extension) {
extensions.push(options.extension);
}
if (options.extensions) {
extensions = extensions.concat(options.extensions);
}
if (extensions.length === 0) {
extensions.push(".marko");
}
function markoRequireExtension(module, filename) {
var targetFile = filename + ".js";
var cachedTemplate =
getLoadedTemplate(targetFile) || getLoadedTemplate(filename);
if (cachedTemplate) {
// The template has already been loaded so use the exports of the already loaded template
module.exports = cachedTemplate;
return;
}
// Resolve the appropriate compiler relative to the location of the
// marko template file on disk using the "resolve-from" module.
var dirname = path.dirname(filename);
var markoCompilerModulePath = resolveFrom(dirname, "marko/compiler");
var markoCompiler = require(markoCompilerModulePath);
// Now use the appropriate Marko compiler to compile the Marko template
// file to JavaScript source code:
var compiledSrc = compile(filename, markoCompiler, compilerOptions);
// Append ".js" to the filename since that is where we write the compiled
// source code that is being loaded. This allows stack traces to match up.
module._compile(compiledSrc, targetFile);
}
requireExtensions[MARKO_EXTENSIONS] =
requireExtensions[MARKO_EXTENSIONS] ||
(requireExtensions[MARKO_EXTENSIONS] = []);
extensions.forEach(extension => {
extension = normalizeExtension(extension);
requireExtensions[extension] = markoRequireExtension;
requireExtensions[MARKO_EXTENSIONS].push(extension);
});
}
install();
exports.install = install;
exports.getExtensions = function() {
return require.extensions[MARKO_EXTENSIONS];
};