Skip to content
This repository was archived by the owner on May 7, 2024. It is now read-only.

Commit 139a2c6

Browse files
committed
Compatibility with Twing@5
1 parent eab9dd8 commit 139a2c6

File tree

9 files changed

+142
-110
lines changed

9 files changed

+142
-110
lines changed

.travis.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
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"
1010
jobs:
1111
include:
1212
- stage: cover
1313
node_js: "12"
1414
script:
1515
- npm run cover
16-
- npm run coverage
16+
- npm run coverage

package.json

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "twing-loader",
3-
"version": "3.0.1",
3+
"version": "5.0.0",
44
"main": "dist/index.js",
55
"scripts": {
66
"build": "npm run clean && tsc",
@@ -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",
@@ -45,8 +45,8 @@
4545
"homepage": "https://github.com/NightlyCommit/twing-loader#readme",
4646
"description": "Webpack loader for Twig templates, based on Twing.",
4747
"dependencies": {
48-
"crypto-js": "^3.1.9-1",
49-
"loader-utils": "^1.2.3",
48+
"crypto-js": "^4.0.0",
49+
"loader-utils": "^2.0.0",
5050
"schema-utils": "^2.2.0",
5151
"slash": "^3.0.0"
5252
},
@@ -60,16 +60,16 @@
6060
"@types/webpack": "^4.39.1",
6161
"coveralls": "^3.0.6",
6262
"html-webpack-plugin": "^3.2.0",
63-
"memory-fs": "^0.4.1",
63+
"memory-fs": "^0.5.0",
6464
"module-alias": "^2.2.1",
6565
"nyc": "^14.1.1",
66-
"rimraf": "^2.7.1",
67-
"sinon": "^7.5.0",
66+
"rimraf": "^3.0.2",
67+
"sinon": "^9.0.2",
6868
"tap-bail": "^1.0.0",
6969
"tap-spec": "^5.0.0",
70-
"tape": "^4.11.0",
70+
"tape": "^5.0.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

+17-13
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
TwingNodeModule,
88
TwingSource, TwingTokenStream
99
} from 'twing';
10-
import {Visitor} from "./visitor";
10+
import {Visitor} from './visitor';
1111

1212
const sha256 = require('crypto-js/sha256');
1313
const hex = require('crypto-js/enc-hex');
@@ -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

42-
export default function (this: loader.LoaderContext, source: string) {
42+
export default async 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
};
@@ -54,7 +56,7 @@ export default function (this: loader.LoaderContext, source: string) {
5456

5557
this.addDependency(slash(environmentModulePath));
5658

57-
// require takes module name separated wicth forward slashes
59+
// require takes module name separated with forward slashes
5860
let environment: TwingEnvironment = require(slash(environmentModulePath));
5961
let loader = environment.getLoader();
6062

@@ -71,7 +73,7 @@ export default function (this: loader.LoaderContext, source: string) {
7173

7274
let visitor = new Visitor(loader, resourcePath, getTemplateHash);
7375

74-
visitor.visit(module);
76+
await visitor.visit(module);
7577

7678
let precompiledTemplate = environment.compile(module);
7779

@@ -94,13 +96,13 @@ ${precompiledTemplate}
9496
parts.push(`env.registerTemplatesModule(templatesModule, '${key}');`);
9597

9698
parts.push(`
97-
let template = env.loadTemplate('${key}');
99+
let loadTemplate = () => env.loadTemplate('${key}');
98100
99101
module.exports = (context = {}) => {
100-
return template.render(context);
102+
return loadTemplate().then((template) => template.render(context));
101103
};`);
102104

103-
return parts.join('\n');
105+
callback(null, parts.join('\n'));
104106
} else {
105107
environment.setLoader(new TwingLoaderChain([
106108
new PathSupportingArrayLoader(new Map([
@@ -110,9 +112,11 @@ module.exports = (context = {}) => {
110112
]));
111113

112114
environment.on('template', (name: string, from: TwingSource) => {
113-
this.addDependency(environment.getLoader().resolve(name, from));
115+
environment.getLoader().resolve(name, from)
116+
.then((path) => this.addDependency(path))
117+
.catch((e) => {});
114118
});
115119

116-
return `module.exports = ${JSON.stringify(environment.render(resourcePath, renderContext))};`;
120+
callback(null, `module.exports = ${JSON.stringify(await environment.render(resourcePath, renderContext))};`);
117121
}
118122
};

src/visitor.ts

+36-31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import {TwingLoaderInterface, TwingNode, TwingNodeExpression, TwingNodeType, TwingSource} from "twing";
2-
import {existsSync} from "fs";
1+
import {TwingLoaderInterface, TwingNode, TwingNodeExpression, TwingSource} from 'twing';
2+
import {existsSync} from 'fs';
33

44
const slash = require('slash');
55

@@ -20,12 +20,15 @@ export class Visitor {
2020
return this._foundTemplateNames;
2121
}
2222

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);
23+
async visit(node: TwingNode) {
24+
const processExpressionNode = async (node: TwingNodeExpression) => {
25+
if (node.type === null) {
26+
return;
27+
}
2828

29+
const pushValue = async (value: string): Promise<string> => {
30+
if (await this._loader.exists(value, this._from)) {
31+
value = await this._loader.resolve(value, this._from);
2932
if (existsSync(value)) {
3033
if (!this._foundTemplateNames.includes(value)) {
3134
this._foundTemplateNames.push(value);
@@ -38,52 +41,54 @@ export class Visitor {
3841
return value;
3942
};
4043

41-
if (node.getType() === TwingNodeType.EXPRESSION_ARRAY) {
44+
if (node.type.toString() === 'expression_array') {
4245
for (let [index, constantNode] of node.getNodes()) {
4346
if ((index as number) % 2) {
44-
processExpressionNode(constantNode);
47+
await processExpressionNode(constantNode);
4548
}
4649
}
4750
}
4851

49-
if (node.getType() === TwingNodeType.EXPRESSION_CONDITIONAL) {
52+
if (node.type.toString() === 'expression_conditional') {
5053
let expr2: TwingNodeExpression = node.getNode('expr2');
5154
let expr3: TwingNodeExpression = node.getNode('expr3');
5255

53-
processExpressionNode(expr2);
54-
processExpressionNode(expr3);
56+
await processExpressionNode(expr2);
57+
await processExpressionNode(expr3);
5558
}
5659

57-
if (node.getType() === TwingNodeType.EXPRESSION_CONSTANT) {
58-
node.setAttribute('value', pushValue(node.getAttribute('value')));
60+
if (node.type.toString() === 'expression_constant') {
61+
node.setAttribute('value', await pushValue(node.getAttribute('value')));
5962
}
6063
};
6164

62-
// include function
63-
if ((node.getType() === TwingNodeType.EXPRESSION_FUNCTION) && (node.getAttribute('name') === 'include')) {
64-
processExpressionNode(node.getNode('arguments').getNode(0));
65-
}
66-
67-
// import and include tags
68-
if ((node.getType() === TwingNodeType.IMPORT) || (node.getType() === TwingNodeType.INCLUDE)) {
69-
if (node.hasNode('expr')) {
70-
processExpressionNode(node.getNode('expr'));
65+
if (node.type !== null) {
66+
// include function
67+
if ((node.type.toString() === 'expression_function') && (node.getAttribute('name') === 'include')) {
68+
await processExpressionNode(node.getNode('arguments').getNode(0));
7169
}
72-
}
7370

74-
// extends and embed tags
75-
if ((node.getType() === TwingNodeType.MODULE)) {
76-
if (node.hasNode('parent')) {
77-
processExpressionNode(node.getNode('parent'))
71+
// import and include tags
72+
if ((node.type.toString() === 'import') || (node.type.toString() === 'include')) {
73+
if (node.hasNode('expr')) {
74+
await processExpressionNode(node.getNode('expr'));
75+
}
7876
}
7977

80-
for (let embeddedTemplate of node.getAttribute('embedded_templates')) {
81-
this.visit(embeddedTemplate);
78+
// extends and embed tags
79+
if ((node.type.toString() === 'module')) {
80+
if (node.hasNode('parent')) {
81+
await processExpressionNode(node.getNode('parent'))
82+
}
83+
84+
for (let embeddedTemplate of node.getAttribute('embedded_templates')) {
85+
await this.visit(embeddedTemplate);
86+
}
8287
}
8388
}
8489

8590
for (let [key, subNode] of node.getNodes()) {
86-
this.visit(subNode);
91+
await this.visit(subNode);
8792
}
8893
};
8994
}

test/integration/array_loader/environment.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ module.exports = new TwingEnvironment(
77
bar: 'BAR FROM THE ARRAY LOADER'
88
})
99
])
10-
);
10+
);

test/integration/extends/environment.js

-5
This file was deleted.

test/integration/test-case.ts

+25-15
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {resolve as resolvePath, relative as relativePath} from 'path';
22

33
import {Test} from "tape";
44
import * as webpack from "webpack";
5-
import {Compiler} from "webpack";
5+
import {Compiler, Stats} from "webpack";
66
import {Configuration} from "webpack";
77
import MemoryFileSystem = require("memory-fs");
88

@@ -59,15 +59,15 @@ export abstract class TestCase {
5959
compiler.outputFileSystem = memoryFs;
6060

6161
compiler.run((err, stats) => {
62-
if (err || stats.hasErrors()) {
63-
if (err) {
64-
reject(err);
65-
} else {
66-
reject(new Error(stats.toJson("errors-only").errors.join('')));
67-
}
68-
} else {
69-
resolve(memoryFs);
62+
if (err) {
63+
return reject(err);
64+
}
65+
66+
if (stats.hasErrors()) {
67+
return reject(new Error(stats.toJson("errors-only").errors.join('')));
7068
}
69+
70+
resolve(memoryFs);
7171
});
7272
});
7373
}
@@ -79,18 +79,28 @@ 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 new Promise<void>((resolve) =>
83+
resolve(this.doTest(
84+
test,
85+
this.renderContext ? 'using "render at compile time" behavior' : 'using "render at runtime" behavior',
86+
memoryFs
87+
))
88+
);
8389
})
8490
.catch((err) => {
8591
test.fail(err.message);
8692
});
8793
}
8894

89-
protected doTest(test: Test, message: string, memoryFs: MemoryFileSystem): void {
90-
let actual: string;
91-
92-
actual = new Function(`return ${memoryFs.readFileSync(resolvePath('dist/main.js'), 'UTF-8')};`)();
95+
protected doTest(test: Test, message: string, memoryFs: MemoryFileSystem): void|Promise<void> {
96+
let result: string|Promise<string>;
97+
const source = memoryFs.readFileSync(resolvePath('dist/main.js'), 'UTF-8');
9398

94-
test.same(actual, this.expected, message);
99+
result = new Function(`return ${source};`)()
100+
if (result instanceof Promise) {
101+
return result.then((code: string) => test.same(code, this.expected, message));
102+
} else {
103+
test.same(result, this.expected, message);
104+
}
95105
}
96106
}

0 commit comments

Comments
 (0)