forked from at0g/nunjucks-loader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
154 lines (125 loc) · 5.95 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*******************************************************************
*
* This module was heavily inspired by nunjucksify.
* (https://www.npmjs.com/package/nunjucksify)
*
* Full credit to the original authors.
*
******************************************************************/
var nunjucks = require('nunjucks');
var slash = require('slash');
var path = require('path');
var loaderUtils = require('loader-utils');
var env;
var hasRun = false;
var pathToConfigure;
var jinjaCompatStr;
var root;
module.exports = function (source) {
if (this.target !== 'web') {
throw new Error('[nunjucks-loader] non-web targets are not supported');
}
this.cacheable();
if (!hasRun){
var query = loaderUtils.parseQuery(this.query);
if (query){
env = new nunjucks.Environment([], query.opts || {});
if (query.config){
pathToConfigure = query.config;
try {
var configure = require(query.config);
configure(env);
}
catch (e) {
if (e.code === 'MODULE_NOT_FOUND') {
if (!query.quiet) {
var message = 'Cannot configure nunjucks environment before precompile\n' +
'\t' + e.message + '\n' +
'Async filters and custom extensions are unsupported when the nunjucks\n' +
'environment configuration depends on webpack loaders or custom module\n' +
'resolve rules. If you are not using async filters or custom extensions\n' +
'with nunjucks, you can safely ignore this warning.'
;
this.emitWarning(message);
}
}
else {
this.emitError(e.message);
}
}
}
// Specify the template search path, so we know from what directory
// it should be relative to.
if (query.root) {
root = query.root;
}
// Enable experimental Jinja compatibility to be enabled
if(query.jinjaCompat){
jinjaCompatStr = 'nunjucks.installJinjaCompat();\n';
}
}
else {
env = new nunjucks.Environment([]);
}
hasRun = true;
}
var name = slash(path.relative(root || this.options.context, this.resourcePath));
var nunjucksCompiledStr = nunjucks.precompileString(source, {
env: env,
name: name
});
nunjucksCompiledStr = nunjucksCompiledStr.replace(/window\.nunjucksPrecompiled/g, 'nunjucks.nunjucksPrecompiled');
// ==============================================================================
// replace 'require' filter with a webpack require expression (to resolve assets)
// ==============================================================================
var filterReg = /env\.getFilter\(\"require\"\)\.call\(context, \"(.*?)\"/g;
nunjucksCompiledStr = nunjucksCompiledStr.replace(filterReg, 'require("$1"');
// ================================================================
// Begin to write the compiled template output to return to webpack
// ================================================================
var compiledTemplate = '';
compiledTemplate += 'var nunjucks = require("nunjucks/browser/nunjucks-slim");\n';
if (jinjaCompatStr) {
compiledTemplate += jinjaCompatStr + '\n';
}
compiledTemplate += 'var env;\n';
compiledTemplate += 'if (!nunjucks.currentEnv){\n';
compiledTemplate += '\tenv = nunjucks.currentEnv = new nunjucks.Environment([], { autoescape: true });\n';
compiledTemplate += '} else {\n';
compiledTemplate += '\tenv = nunjucks.currentEnv;\n';
compiledTemplate += '}\n';
if (pathToConfigure) {
compiledTemplate += 'var configure = require("' + slash(path.relative(this.context, pathToConfigure)) + '")(env);\n';
}
// =========================================================================
// Find template dependencies within nunjucks (extends, import, include etc)
// =========================================================================
//
// Create an object on nunjucks to hold the template dependencies so that they persist
// when this loader compiles multiple templates.
compiledTemplate += 'var dependencies = nunjucks.webpackDependencies || (nunjucks.webpackDependencies = {});\n';
var templateReg = /env\.getTemplate\(\"(.*?)\"/g;
var match;
// Create an object to store references to the dependencies that have been included - this ensures that a template
// dependency is only written once per file, even if it is used multiple times.
var required = {};
// Iterate over the template dependencies
while (match = templateReg.exec(nunjucksCompiledStr)) {
var templateRef = match[1];
if (!required[templateRef]) {
// Require the dependency by name, so it gets bundled by webpack
compiledTemplate += 'dependencies["' + templateRef + '"] = require( "' + templateRef + '" );\n';
required[templateRef] = true;
}
}
compiledTemplate += '\n\n\n\n';
// Include a shim module (by reference rather than inline) that modifies the nunjucks runtime to work with the loader.
compiledTemplate += 'var shim = require("' + slash(path.resolve(this.context, __dirname + '/runtime-shim')) + '");\n';
compiledTemplate += '\n\n';
// Write the compiled template string
compiledTemplate += nunjucksCompiledStr + '\n';
compiledTemplate += '\n\n';
// export the shimmed module
compiledTemplate += 'module.exports = shim(nunjucks, env, nunjucks.nunjucksPrecompiled["' + name + '"] , dependencies)';
return compiledTemplate;
};