pirulug-pug-loader
Version:
188 lines (165 loc) • 5.24 kB
JavaScript
var path = require("path");
var dirname = path.dirname;
var loaderUtils = require("loader-utils");
var nodeResolve = require("resolve").sync;
var walk = require("pug-walk");
module.exports = function (source) {
this.cacheable && this.cacheable();
var modulePaths = {};
modulePaths.pug = require.resolve("pug");
modulePaths.load = nodeResolve("pug-load", {
basedir: dirname(modulePaths.pug),
});
modulePaths.runtime = nodeResolve("pug-runtime", {
basedir: dirname(modulePaths.pug),
});
var pug = require(modulePaths.pug);
var load = require(modulePaths.load);
var req = loaderUtils.getRemainingRequest(this).replace(/^!/, "");
var query = loaderUtils.getOptions(this) || {};
var loadModule = this.loadModule;
var resolve = this.resolve;
var loaderContext = this;
var callback;
var fileContents = {};
var filePaths = {};
var missingFileMode = false;
function getFileContent(context, request) {
request = loaderUtils.urlToRequest(request, query.root);
var baseRequest = request;
var filePath;
filePath = filePaths[context + " " + request];
if (filePath) return filePath;
var isSync = true;
resolve(context, request, function (err, _request) {
if (err) {
resolve(context, request, function (err2, _request) {
if (err2) return callback(err2);
request = _request;
next();
});
return;
}
request = _request;
next();
function next() {
loadModule(
"-!" + path.join(__dirname, "stringify.loader.js") + "!" + request,
function (err, source) {
if (err) return callback(err);
filePaths[context + " " + baseRequest] = request;
fileContents[request] = JSON.parse(source);
if (!isSync) {
run();
}
}
);
}
});
filePath = filePaths[context + " " + baseRequest];
if (filePath) return filePath;
isSync = false;
missingFileMode = true;
throw "continue";
}
var plugin = loadModule
? {
postParse: function (ast) {
return walk(ast, function (node) {
if (
["Mixin", "MixinBlock", "NamedBlock"].indexOf(node.type) !== -1
) {
ast._mustBeInlined = true;
}
});
},
resolve: function (request, source) {
if (!callback) {
callback = loaderContext.async();
}
if (!callback) {
return load.resolve(request, source);
}
var context = dirname(source.split("!").pop());
return getFileContent(context, request);
},
read: function (path) {
if (!callback) {
return load.read(path);
}
return fileContents[path];
},
postLoad: function postLoad(ast) {
return walk(
ast,
function (node, replace) {
if (node.file && node.file.ast) {
postLoad(node.file.ast);
}
if (node.type === "Include") {
if (node.file.ast._mustBeInlined) {
ast._mustBeInlined = true;
}
}
},
function (node, replace) {
if (
node.type === "Include" &&
!(node.block && node.block.nodes.length) &&
!node.file.ast._mustBeInlined
) {
replace({
type: "Code",
val:
"require(" +
loaderUtils.stringifyRequest(
loaderContext,
node.file.fullPath
) +
").call(this, locals)",
buffer: true,
mustEscape: false,
isInline: false,
line: node.line,
filename: node.filename,
});
}
}
);
},
}
: {};
run();
function run() {
try {
var tmplFunc = pug.compileClient(source, {
filename: req,
doctype: query.doctype || "html",
pretty: query.pretty,
self: query.self,
compileDebug: loaderContext.debug || false,
globals: ["require"].concat(query.globals || []),
name: "template",
inlineRuntimeFunctions: false,
filters: query.filters,
plugins: [plugin].concat(query.plugins || []),
});
} catch (e) {
if (missingFileMode) {
// Ignore, it'll continue after async action
missingFileMode = false;
return;
}
loaderContext.callback(e);
return;
}
var runtime =
"var pug = require(" +
loaderUtils.stringifyRequest(loaderContext, "!" + modulePaths.runtime) +
");\n\n";
loaderContext.callback(
null,
runtime + tmplFunc.toString() + ";\nmodule.exports = template;"
);
}
};