Skip to content

Commit

Permalink
Merge 7d98c34 into 27ecbdd
Browse files Browse the repository at this point in the history
  • Loading branch information
ogonkov committed Dec 11, 2019
2 parents 27ecbdd + 7d98c34 commit b198777
Show file tree
Hide file tree
Showing 16 changed files with 227 additions and 17 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/.idea/
/node_modules/
node_modules

/lib/
/test/.coverage/
/test/bundles/

.DS_Store
64 changes: 61 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ module.exports = {
```

**template-example.njk**
```
```nunjucks
<p>Hello, {{ username }}!</p>
```

**app.js**
```
```js
import template from './template-example.njk'

document.body.innerHTML = template({
Expand Down Expand Up @@ -100,7 +100,7 @@ module.exports = {
```

**src/page.njk**
```
```nunjucks
<p>Hello, {{ username }}!</p>
```

Expand Down Expand Up @@ -136,6 +136,7 @@ All other options get passed to Nunjunks `Environment` during files loading.
|**[`searchPaths`](#searchpaths)**|`{String}` or `{Array.<string>}`|`.`|One or more paths to resolve templates paths|
|**[`globals`](#globals)**|`Object.<string, string>`|`{}`|Map global function to corresponding module|
|**[`extensions`](#extensions)**|`Object.<string, string>`|`{}`|Map extension to corresponding module|
|**[`filters`](#filters)**|`Object.<string, string>`|`{}`|Map filters to corresponding module|
|<!-- Add custom options above -->**`autoescape`**|`{Boolean}`|`true`|See [Nunjuncks options][nunjucks-docs-configure] for description of options below|
|**`throwOnUndefined`**|`{Boolean}`|`false`||
|**`trimBlocks`**|`{Boolean}`|`false`||
Expand Down Expand Up @@ -263,6 +264,62 @@ module.exports = new CustomExtension();
Loader trying to guess which extensions are really used, and keep only required
imports.

### filters

Map of filters, that would be imported before each template render.
Filter should return instance, that would be added via
[`env.addFilter`][nunjucks-docs-addfilter].

**webpack.config.js**

```js
module.exports = {
module: {
rules: [
{
test: /\.njk$/,
use: [{
loader: 'simple-nunjucks-loader',
options: {
filters: {
foo: path.join(__dirname, 'foo.js')
}
}
}]
}
]
}
};
```

**foo.js**

```js
module.exports = function(val, param) {
return `${val + param}`;
};
```

**template.njk**

```nunjucks
{{ foo_var | foo(3) }}
```

To mark filter as async, filter module should export `async` flag:

**async-filter.js**

```js
module.exports = function(val, param, callback) {
setTimeout(function() {
callback(null, val + param);
}, 1000);
};

module.exports.async = true;
```

[nunjucks-github]:https://github.com/mozilla/nunjucks
[html-webpack-plugin-github]:https://github.com/jantimon/html-webpack-plugin
[html-webpack-plugin-options]:https://github.com/jantimon/html-webpack-plugin/#options
Expand All @@ -271,6 +328,7 @@ imports.
[nunjucks-docs-configure]:https://mozilla.github.io/nunjucks/api.html#configure
[nunjucks-docs-addglobal]:https://mozilla.github.io/nunjucks/api.html#addglobal
[nunjucks-docs-addextension]:https://mozilla.github.io/nunjucks/api.html#addextension
[nunjucks-docs-addfilter]:https://mozilla.github.io/nunjucks/api.html#addfilter

[npm-image]:https://img.shields.io/npm/v/simple-nunjucks-loader.svg
[npm-url]:http://npmjs.org/package/simple-nunjucks-loader
Expand Down
6 changes: 4 additions & 2 deletions src/get-loader-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export function getLoaderOptions(loader, callback) {
jinjaCompat = false,
searchPaths = '.',
globals = {},
extensions = {}
extensions = {},
filters = {}
} = loaderOptions || {};

const options = {
Expand All @@ -31,7 +32,8 @@ export function getLoaderOptions(loader, callback) {
tags,
searchPaths,
globals,
extensions
extensions,
filters
};

try {
Expand Down
11 changes: 7 additions & 4 deletions src/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {getRuntimeImport} from './output/get-runtime-import';
import {getTemplateDependenciesImport} from './output/get-template-dependencies-import';
import {getGlobals} from './output/get-globals';
import {getExtensions} from './output/get-extensions';
import {getFilters} from './output/get-filters';

export default function nunjucksLoader(source) {
const callback = this.async();
Expand All @@ -20,13 +21,16 @@ export default function nunjucksLoader(source) {
withDependencies(resourcePathImport, source, {
...options,
searchPaths: normalizedSearchPaths
}).then(({dependencies, precompiled, globals, extensions}) => {
}).then(({dependencies, precompiled, globals, extensions, filters}) => {
const {
imports: globalsImports
} = getGlobals(globals);
const {
imports: extensionsImports
} = getExtensions(extensions);
const {
imports: filtersImports
} = getFilters(filters);

const resourcePathString = JSON.stringify(resourcePathImport);
// Only required options
Expand All @@ -44,14 +48,13 @@ export default function nunjucksLoader(source) {
${getTemplateDependenciesImport(dependencies)}
${globalsImports()}
${extensionsImports()}
${filtersImports()}
${precompiled}
exports = module.exports = function nunjucksTemplate(ctx) {
var nunjucks = runtime(
${envOptions},
__nunjucks_module_dependencies__.globals,
__nunjucks_module_dependencies__.extensions,
__nunjucks_module_dependencies__.templates
__nunjucks_module_dependencies__
);
return nunjucks.render(${resourcePathString}, ctx);
Expand Down
15 changes: 15 additions & 0 deletions src/output/get-filters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export function getFilters(filters) {
function imports() {
return filters.map(([filterName, importPath, filterInstance]) => (`
var _filter_${filterName} = require('${importPath}');
__nunjucks_module_dependencies__.filters['${filterName}'] = {
module: _filter_${filterName},
async: ${JSON.stringify(filterInstance.async === true)}
};
`));
}

return {
imports
};
}
9 changes: 7 additions & 2 deletions src/output/get-template-dependencies-import.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ function getImports(imports, assignments) {
__nunjucks_module_dependencies__.extensions = Object.assign(
${assignments.extensions}
);
__nunjucks_module_dependencies__.filters = Object.assign(
${assignments.filters}
);
`;
}

Expand All @@ -23,7 +26,8 @@ function foldDependenciesToImports([imports, assignment], [, fullPath], i) {
{
templates: [`${assignment.templates}`, `${importVar}.templates`].join(),
globals: [`${assignment.globals}`, `${importVar}.globals`].join(),
extensions: [`${assignment.extensions}`, `${importVar}.extensions`].join()
extensions: [`${assignment.extensions}`, `${importVar}.extensions`].join(),
filters: [`${assignment.filters}`, `${importVar}.filters`].join()
}
];
}
Expand All @@ -33,7 +37,8 @@ export function getTemplateDependenciesImport(dependencies) {
...dependencies.reduce(foldDependenciesToImports, ['', {
templates: '{}',
globals: '{}',
extensions: '{}'
extensions: '{}',
filters: '{}'
}])
);
}
32 changes: 28 additions & 4 deletions src/precompile/with-dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function getDependenciesGlobals(nodes, globals) {
* @returns {Promise<string>} Source of precompiled template with wrapper
*/
export function withDependencies(resourcePath, source, options) {
const {searchPaths, globals, extensions, ...opts} = options;
const {searchPaths, globals, extensions, filters, ...opts} = options;
const env = nunjucks.configure(searchPaths, opts);
const extensionsInstances =
Object.entries(extensions).map(([name, importPath]) => {
Expand All @@ -90,8 +90,31 @@ export function withDependencies(resourcePath, source, options) {
}).filter(Boolean);

// For proper precompilation of parent templates
extensionsInstances.forEach(function([name, importPath]) {
env.addExtension(name, require(importPath));
extensionsInstances.forEach(function([name,, extensionInstance]) {
env.addExtension(name, extensionInstance);
});

const filtersInstances = Object.entries(
filters
).map(([filterName, importPath]) => (
[filterName, importPath, require(importPath)]
));

filtersInstances.forEach(function([filterName,, filterInstance]) {
env.addFilter(
filterName,
filterInstance,
filterInstance.async === true
);
});

const filtersCalls = nodes.findAll(nunjucks.nodes.Filter).map(({name}) => (
filtersInstances.find(([filterName]) => filterName === name.value)
)).filter(Boolean).filter(([filterName], i, filters) => {
const filter = filters.find(([name]) => name === filterName);
const filterIndex = filters.indexOf(filter);

return i === filterIndex;
});

return Promise.all([
Expand All @@ -102,7 +125,8 @@ export function withDependencies(resourcePath, source, options) {
precompiled,
dependencies,
globals: getDependenciesGlobals(nodes, globals),
extensions: extensionCalls
extensions: extensionCalls,
filters: filtersCalls
};
});
}
19 changes: 18 additions & 1 deletion src/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ const {WebpackPrecompiledLoader} = require('./WebpackPrecompiledLoader');

const nunjucks = require('nunjucks/browser/nunjucks-slim');

module.exports = function runtime(options, globals, extensions, precompiled) {
module.exports = function runtime(options, {
globals,
extensions,
filters,
templates: precompiled
}) {
if (options.jinjaCompat === true) {
nunjucks.installJinjaCompat();
}
Expand All @@ -28,6 +33,18 @@ module.exports = function runtime(options, globals, extensions, precompiled) {
env.addExtension(extensionName, extensions[extensionName].module);
}

for (const filterName in filters) {
if (!Object.prototype.hasOwnProperty.call(filters, filterName)) {
continue;
}

env.addFilter(
filterName,
filters[filterName].module,
filters[filterName].async === true
);
}

return {
render(name, ctx, cb) {
return env.render(name, ctx, cb);
Expand Down
8 changes: 8 additions & 0 deletions src/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@
"type": "string"
}
}
},
"filters": {
"type": "object",
"patternProperties": {
".+": {
"type": "string"
}
}
}
},
"additionalProperties": false
Expand Down
27 changes: 27 additions & 0 deletions test/__snapshots__/loader.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Advanced compilation filters should compile filters in inherited templates 1`] = `
"<!DOCTYPE html>
<html lang=\\"en\\">
<head>
<meta charset=\\"utf-8\\">
<title>Foobar 52</title>
</head>
<body>
<p>48</p>
</body>
</html>
"
`;
exports[`Advanced compilation filters should compile multiple instances of same filter 1`] = `
"15
8
"
`;
exports[`Advanced compilation filters should compile single filter instance 1`] = `
"15
"
`;
exports[`Advanced compilation should compile custom tags 1`] = `
"<div id=\\"el100500\\">
This content will be replaced with the content from /stuff
Expand Down
10 changes: 10 additions & 0 deletions test/fixtures/filters/base.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ title }} {{ foo_var | foo(1, 2) }}</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
5 changes: 5 additions & 0 deletions test/fixtures/filters/children.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% extends 'test/fixtures/filters/base.njk' %}

{% block body %}
<p>{{ foo_var | foo(1, 2, bar=6) }}</p>
{% endblock %}
3 changes: 3 additions & 0 deletions test/fixtures/filters/foo-filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = function(num, x, y, kwargs) {
return num + (kwargs && kwargs.bar || 10);
};
2 changes: 2 additions & 0 deletions test/fixtures/filters/multiple.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{{ 5 | foo(1, 2) }}
{{ 5 | foo(1, 2, bar=3) }}
1 change: 1 addition & 0 deletions test/fixtures/filters/single.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{ 5 | foo(1, 2) }}

0 comments on commit b198777

Please sign in to comment.