Skip to content

Commit 8ad34ac

Browse files
authored
Merge pull request NightlyCommit#29 from ericmorand/issue_21
Fix issue NightlyCommit#21
2 parents eab9dd8 + 2509016 commit 8ad34ac

File tree

10 files changed

+195
-122
lines changed

10 files changed

+195
-122
lines changed

.nycrc.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
],
99
"include": "src",
1010
"reporter": [
11-
"text-summary",
11+
"text",
1212
"html"
1313
]
1414
}

.travis.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
language: node_js
22
node_js:
3-
- "6"
4-
- "7"
53
- "8"
64
- "9"
75
- "10"
86
- "11"
97
- "12"
8+
- "13"
9+
- "14"
10+
- "15"
1011
jobs:
1112
include:
1213
- stage: cover
13-
node_js: "12"
14+
node_js: "15"
1415
script:
1516
- npm run cover
1617
- npm run coverage

README.md

+8-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Webpack loader for Twig templates, based on [Twing](https://www.npmjs.com/packag
66
## Prerequisites
77

88
* Webpack 4
9-
* Twing 3.0.1
9+
* Twing 5.0.2
1010

1111
## Installation
1212

@@ -65,9 +65,11 @@ module.exports = new TwingEnvironment(
6565
```javascript
6666
let template = require('./index.twig');
6767

68-
let renderedTemplate = template({
68+
template({
6969
foo: 'bar'
70-
}); // "bar"
70+
}).then((renderedTemplate) => {
71+
// "bar"
72+
});
7173
```
7274

7375
This behavior, known as _render at runtime_, comes at the cost of having Twing as part of the bundle.
@@ -122,7 +124,9 @@ module.exports = new TwingEnvironment(
122124
<sub>index.js</sub>
123125

124126
```javascript
125-
let renderedTemplate = require('./index.twig'); // "bar"
127+
require('./index.twig').then((renderedTemplate) => {
128+
// "bar"
129+
});
126130
```
127131

128132
This second behavior, known as _render at compile time_, comes with the benefit of not having Twing as part of the bundle.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
],
3434
"license": "ISC",
3535
"peerDependencies": {
36-
"twing": "^3.0.1"
36+
"twing": "^5.0.2"
3737
},
3838
"repository": {
3939
"type": "git",
@@ -69,7 +69,7 @@
6969
"tap-spec": "^5.0.0",
7070
"tape": "^4.11.0",
7171
"ts-node": "^8.4.1",
72-
"twing": "^3.0.1",
72+
"twing": "^5.0.2",
7373
"typescript": "^3.6.3",
7474
"webpack": "^4.41.0",
7575
"webpack-cli": "^3.3.9"

src/index.ts

+28-20
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,16 @@ const optionsSchema = {
3232
};
3333

3434
class PathSupportingArrayLoader extends TwingLoaderArray {
35-
getSourceContext(name: string, from: TwingSource): TwingSource {
36-
let source = super.getSourceContext(name, from);
37-
38-
return new TwingSource(source.getCode(), source.getName(), name);
35+
getSourceContext(name: string, from: TwingSource): Promise<TwingSource> {
36+
return super.getSourceContext(name, from).then((source) => {
37+
return new TwingSource(source.getCode(), source.getName(), name);
38+
});
3939
}
4040
}
4141

4242
export default function (this: loader.LoaderContext, source: string) {
43+
const callback = this.async();
44+
4345
const getTemplateHash = (name: string) => {
4446
return this.mode !== 'production' ? name : hex.stringify(sha256(name));
4547
};
@@ -48,13 +50,15 @@ export default function (this: loader.LoaderContext, source: string) {
4850

4951
validateOptions(optionsSchema, options, 'Twing loader');
5052

53+
delete require.cache[options.environmentModulePath];
54+
5155
let resourcePath: string = slash(this.resourcePath);
5256
let environmentModulePath: string = options.environmentModulePath;
5357
let renderContext: any = options.renderContext;
5458

5559
this.addDependency(slash(environmentModulePath));
5660

57-
// require takes module name separated wicth forward slashes
61+
// require takes module name separated with forward slashes
5862
let environment: TwingEnvironment = require(slash(environmentModulePath));
5963
let loader = environment.getLoader();
6064

@@ -71,11 +75,10 @@ export default function (this: loader.LoaderContext, source: string) {
7175

7276
let visitor = new Visitor(loader, resourcePath, getTemplateHash);
7377

74-
visitor.visit(module);
78+
visitor.visit(module).then(() => {
79+
let precompiledTemplate = environment.compile(module);
7580

76-
let precompiledTemplate = environment.compile(module);
77-
78-
parts.push(`let templatesModule = (() => {
81+
parts.push(`let templatesModule = (() => {
7982
let module = {
8083
exports: undefined
8184
};
@@ -86,21 +89,22 @@ ${precompiledTemplate}
8689
})();
8790
`);
8891

89-
for (let foundTemplateName of visitor.foundTemplateNames) {
90-
// require takes module name separated with forward slashes
91-
parts.push(`require('${slash(foundTemplateName)}');`);
92-
}
92+
for (let foundTemplateName of visitor.foundTemplateNames) {
93+
// require takes module name separated with forward slashes
94+
parts.push(`require('${slash(foundTemplateName)}');`);
95+
}
9396

94-
parts.push(`env.registerTemplatesModule(templatesModule, '${key}');`);
97+
parts.push(`env.registerTemplatesModule(templatesModule, '${key}');`);
9598

96-
parts.push(`
99+
parts.push(`
97100
let template = env.loadTemplate('${key}');
98101
99102
module.exports = (context = {}) => {
100-
return template.render(context);
103+
return template.then((template) => template.render(context));
101104
};`);
102105

103-
return parts.join('\n');
106+
callback(null, parts.join('\n'));
107+
});
104108
} else {
105109
environment.setLoader(new TwingLoaderChain([
106110
new PathSupportingArrayLoader(new Map([
@@ -109,10 +113,14 @@ module.exports = (context = {}) => {
109113
loader
110114
]));
111115

112-
environment.on('template', (name: string, from: TwingSource) => {
113-
this.addDependency(environment.getLoader().resolve(name, from));
116+
environment.on('template', async (name: string, from: TwingSource) => {
117+
this.addDependency(await environment.getLoader().resolve(name, from));
114118
});
115119

116-
return `module.exports = ${JSON.stringify(environment.render(resourcePath, renderContext))};`;
120+
environment.render(resourcePath, renderContext).then((result) => {
121+
callback(null, `module.exports = ${JSON.stringify(result)};`);
122+
}).catch((error) => {
123+
callback(error);
124+
});
117125
}
118126
};

src/visitor.ts

+33-22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
1-
import {TwingLoaderInterface, TwingNode, TwingNodeExpression, TwingNodeType, TwingSource} from "twing";
1+
import {
2+
TwingLoaderInterface,
3+
TwingNode,
4+
TwingNodeExpression,
5+
TwingNodeExpressionArray,
6+
TwingNodeExpressionConditional,
7+
TwingNodeExpressionConstant,
8+
TwingNodeExpressionFunction,
9+
TwingNodeImport,
10+
TwingNodeInclude, TwingNodeModule,
11+
TwingSource
12+
} from "twing";
213
import {existsSync} from "fs";
314

415
const slash = require('slash');
@@ -20,11 +31,11 @@ export class Visitor {
2031
return this._foundTemplateNames;
2132
}
2233

23-
visit(node: TwingNode) {
24-
let processExpressionNode = (node: TwingNodeExpression) => {
25-
let pushValue = (value: string): string => {
26-
if (this._loader.exists(value, this._from)) {
27-
value = this._loader.resolve(value, this._from);
34+
async visit(node: TwingNode): Promise<void> {
35+
let processExpressionNode = async (node: TwingNodeExpression): Promise<void> => {
36+
let pushValue = async (value: string): Promise<string> => {
37+
if (await this._loader.exists(value, this._from)) {
38+
value = await this._loader.resolve(value, this._from);
2839

2940
if (existsSync(value)) {
3041
if (!this._foundTemplateNames.includes(value)) {
@@ -38,52 +49,52 @@ export class Visitor {
3849
return value;
3950
};
4051

41-
if (node.getType() === TwingNodeType.EXPRESSION_ARRAY) {
52+
if (node instanceof TwingNodeExpressionArray) {
4253
for (let [index, constantNode] of node.getNodes()) {
4354
if ((index as number) % 2) {
44-
processExpressionNode(constantNode);
55+
await processExpressionNode(constantNode);
4556
}
4657
}
4758
}
4859

49-
if (node.getType() === TwingNodeType.EXPRESSION_CONDITIONAL) {
60+
if (node instanceof TwingNodeExpressionConditional) {
5061
let expr2: TwingNodeExpression = node.getNode('expr2');
5162
let expr3: TwingNodeExpression = node.getNode('expr3');
5263

53-
processExpressionNode(expr2);
54-
processExpressionNode(expr3);
64+
await processExpressionNode(expr2);
65+
await processExpressionNode(expr3);
5566
}
5667

57-
if (node.getType() === TwingNodeType.EXPRESSION_CONSTANT) {
58-
node.setAttribute('value', pushValue(node.getAttribute('value')));
68+
if (node instanceof TwingNodeExpressionConstant) {
69+
node.setAttribute('value', await pushValue(node.getAttribute('value')));
5970
}
6071
};
6172

6273
// include function
63-
if ((node.getType() === TwingNodeType.EXPRESSION_FUNCTION) && (node.getAttribute('name') === 'include')) {
64-
processExpressionNode(node.getNode('arguments').getNode(0));
74+
if ((node instanceof TwingNodeExpressionFunction) && (node.getAttribute('name') === 'include')) {
75+
await processExpressionNode(node.getNode('arguments').getNode(0));
6576
}
6677

6778
// import and include tags
68-
if ((node.getType() === TwingNodeType.IMPORT) || (node.getType() === TwingNodeType.INCLUDE)) {
79+
if ((node instanceof TwingNodeImport) || (node instanceof TwingNodeInclude)) {
6980
if (node.hasNode('expr')) {
70-
processExpressionNode(node.getNode('expr'));
81+
await processExpressionNode(node.getNode('expr'));
7182
}
7283
}
7384

7485
// extends and embed tags
75-
if ((node.getType() === TwingNodeType.MODULE)) {
86+
if ((node instanceof TwingNodeModule)) {
7687
if (node.hasNode('parent')) {
77-
processExpressionNode(node.getNode('parent'))
88+
await processExpressionNode(node.getNode('parent'))
7889
}
7990

8091
for (let embeddedTemplate of node.getAttribute('embedded_templates')) {
81-
this.visit(embeddedTemplate);
92+
await this.visit(embeddedTemplate);
8293
}
8394
}
8495

85-
for (let [key, subNode] of node.getNodes()) {
86-
this.visit(subNode);
96+
for (let [, subNode] of node.getNodes()) {
97+
await this.visit(subNode);
8798
}
8899
};
89100
}

test/integration/plugin/HtmlWebpackPlugin/test.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ class HtmlWebpackPluginTestCase extends TestCase {
4444
`;
4545
}
4646

47-
protected doTest(test: Test, message: string, memoryFs: MemoryFileSystem): void {
48-
super.doTest(test, message, memoryFs);
47+
protected doTest(test: Test, message: string, memoryFs: MemoryFileSystem): Promise<void> {
48+
return super.doTest(test, message, memoryFs).then(() => {
49+
let actual = memoryFs.readFileSync(resolvePath('dist/index.html'), 'UTF-8');
4950

50-
let actual = memoryFs.readFileSync(resolvePath('dist/index.html'), 'UTF-8');
51-
52-
test.same(actual, this.expectedFromPlugin, 'plugin output is valid');
51+
test.same(actual, this.expectedFromPlugin, 'plugin output is valid');
52+
});
5353
}
5454
}
5555

test/integration/test-case.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {resolve as resolvePath, relative as relativePath} from 'path';
1+
import {resolve as resolvePath} from 'path';
22

33
import {Test} from "tape";
44
import * as webpack from "webpack";
@@ -79,17 +79,17 @@ export abstract class TestCase {
7979

8080
return this.compile(configuration, test)
8181
.then((memoryFs: MemoryFileSystem) => {
82-
this.doTest(test, this.renderContext ? 'using "render at compile time" behavior' : 'using "render at runtime" behavior', memoryFs);
82+
return this.doTest(test, this.renderContext ? 'using "render at compile time" behavior' : 'using "render at runtime" behavior', memoryFs);
8383
})
8484
.catch((err) => {
8585
test.fail(err.message);
8686
});
8787
}
8888

89-
protected doTest(test: Test, message: string, memoryFs: MemoryFileSystem): void {
89+
protected async doTest(test: Test, message: string, memoryFs: MemoryFileSystem): Promise<void> {
9090
let actual: string;
9191

92-
actual = new Function(`return ${memoryFs.readFileSync(resolvePath('dist/main.js'), 'UTF-8')};`)();
92+
actual = await new Function(`return ${memoryFs.readFileSync(resolvePath('dist/main.js'), 'UTF-8')};`)();
9393

9494
test.same(actual, this.expected, message);
9595
}

0 commit comments

Comments
 (0)