1
1
import { getOptions } from 'loader-utils' ;
2
2
import { loader } from 'webpack' ;
3
- import { TwingEnvironment , TwingLoaderArray , TwingLoaderChain , TwingSource } from 'twing' ;
4
- import { NodeVisitor } from "./node-visitor" ;
3
+ import {
4
+ TwingEnvironment ,
5
+ TwingLoaderArray ,
6
+ TwingLoaderChain ,
7
+ TwingNodeModule ,
8
+ TwingSource , TwingTokenStream
9
+ } from 'twing' ;
10
+ import { Visitor } from "./visitor" ;
5
11
6
12
const sha256 = require ( 'crypto-js/sha256' ) ;
7
13
const hex = require ( 'crypto-js/enc-hex' ) ;
8
- const process = require ( 'process' ) ;
9
14
const slash = require ( 'slash' ) ;
10
15
11
16
const validateOptions = require ( 'schema-utils' ) ;
@@ -27,82 +32,71 @@ const optionsSchema = {
27
32
} ;
28
33
29
34
class PathSupportingArrayLoader extends TwingLoaderArray {
30
- getSourceContext ( name : string ) : TwingSource {
31
- let source = super . getSourceContext ( name ) ;
35
+ getSourceContext ( name : string , from : TwingSource ) : TwingSource {
36
+ let source = super . getSourceContext ( name , from ) ;
32
37
33
38
return new TwingSource ( source . getCode ( ) , source . getName ( ) , name ) ;
34
39
}
35
40
}
36
41
37
42
export default function ( this : loader . LoaderContext , source : string ) {
43
+ const getTemplateHash = ( name : string ) => {
44
+ return this . mode !== 'production' ? name : hex . stringify ( sha256 ( name ) ) ;
45
+ } ;
46
+
38
47
const options = getOptions ( this ) ;
39
48
40
49
validateOptions ( optionsSchema , options , 'Twing loader' ) ;
41
50
42
51
let resourcePath : string = slash ( this . resourcePath ) ;
43
- let environmentModulePath : string = slash ( options . environmentModulePath ) ;
52
+ let environmentModulePath : string = options . environmentModulePath ;
44
53
let renderContext : any = options . renderContext ;
45
54
46
- this . addDependency ( environmentModulePath ) ;
47
-
48
- // we don't want to reuse an eventual initialized environment
49
- delete require . cache [ require . resolve ( environmentModulePath ) ] ;
55
+ this . addDependency ( slash ( environmentModulePath ) ) ;
50
56
51
- let environment : TwingEnvironment = require ( environmentModulePath ) ;
57
+ // require takes module name separated wicth forward slashes
58
+ let environment : TwingEnvironment = require ( slash ( environmentModulePath ) ) ;
59
+ let loader = environment . getLoader ( ) ;
52
60
53
61
if ( renderContext === undefined ) {
54
-
55
62
let parts : string [ ] = [
56
- `const {cache, loader, getEnvironment} = require('${ slash ( require . resolve ( './runtime' ) ) } ');` ,
57
- `const env = getEnvironment(require('${ environmentModulePath } '));`
63
+ `const env = require('${ slash ( environmentModulePath ) } ');`
58
64
] ;
59
65
60
- let nodeVisitor : NodeVisitor ;
61
-
62
- nodeVisitor = new NodeVisitor ( ) ;
63
- nodeVisitor . fromPath = resourcePath ;
66
+ let key = getTemplateHash ( resourcePath ) ;
67
+ let sourceContext : TwingSource = new TwingSource ( source , `${ key } ` ) ;
68
+ let tokenStream : TwingTokenStream = environment . tokenize ( sourceContext ) ;
64
69
65
- environment . addNodeVisitor ( nodeVisitor ) ;
70
+ let module : TwingNodeModule = environment . parse ( tokenStream ) ;
66
71
67
- Reflect . set ( environment , 'getTemplateClass' , function ( name : string , index : number = null , from : TwingSource = null ) {
68
- let hash : string ;
72
+ let visitor = new Visitor ( loader , resourcePath , getTemplateHash ) ;
69
73
70
- const HASH_PREFIX = '__HASHED__' ;
74
+ visitor . visit ( module ) ;
71
75
72
- if ( name . startsWith ( HASH_PREFIX ) ) {
73
- hash = name ;
74
- } else {
75
- hash = `${ HASH_PREFIX } ${ hex . stringify ( sha256 ( name ) ) } ` ;
76
- }
76
+ let precompiledTemplate = environment . compile ( module ) ;
77
77
78
- return hash + ( index === null ? '' : '_' + index ) ;
79
- } ) ;
80
-
81
- let className : string = environment . getTemplateClass ( resourcePath ) ;
82
- let sourceContext : TwingSource = new TwingSource ( source , className ) ;
83
- let precompiledTemplate = environment . compile ( environment . parse ( environment . tokenize ( sourceContext ) ) ) ;
84
-
85
- parts . push ( `cache.write('${ className } ', (() => {let module = {
78
+ parts . push ( `let templatesModule = (() => {
79
+ let module = {
86
80
exports: undefined
87
81
};
88
82
89
83
${ precompiledTemplate }
90
84
91
- return module.exports;})());
85
+ return module.exports;
86
+ })();
92
87
` ) ;
93
- parts . push ( `loader.addTemplateKey('${ className } ', '${ className } ');` ) ;
94
88
95
- for ( let foundTemplateName of nodeVisitor . foundTemplateNames ) {
96
- if ( process . platform === 'win32' ) {
97
- foundTemplateName = slash ( foundTemplateName ) ;
98
- }
99
- parts . push ( `require('${ foundTemplateName } ');` ) ;
89
+ for ( let foundTemplateName of visitor . foundTemplateNames ) {
90
+ // require takes module name separated with forward slashes
91
+ parts . push ( `require('${ slash ( foundTemplateName ) } ');` ) ;
100
92
}
101
93
94
+ parts . push ( `env.registerTemplatesModule(templatesModule, '${ key } ');` ) ;
95
+
102
96
parts . push ( `
103
- let template = env.loadTemplate('${ className } ');
97
+ let template = env.loadTemplate('${ key } ');
104
98
105
- module.exports = function (context = {}) {
99
+ module.exports = (context = {}) => {
106
100
return template.render(context);
107
101
};` ) ;
108
102
@@ -112,7 +106,7 @@ module.exports = function(context = {}) {
112
106
new PathSupportingArrayLoader ( new Map ( [
113
107
[ resourcePath , source ]
114
108
] ) ) ,
115
- environment . getLoader ( )
109
+ loader
116
110
] ) ) ;
117
111
118
112
environment . on ( 'template' , ( name : string , from : TwingSource ) => {
0 commit comments