1 | "use strict";
|
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 | module.exports = function ( def, moduleName, path ) {
|
36 | try {
|
37 | const
|
38 | context = { vars: {}, moduleName, path },
|
39 | preprocessedDef = process( context, def );
|
40 | return preprocessedDef;
|
41 | } catch ( ex ) {
|
42 | throw Error( `...in boilerplate.preprocessor( ${moduleName}, ${path} )\n${ex}` );
|
43 | }
|
44 | };
|
45 |
|
46 | const
|
47 | RX_VAR_NAME = /^%[a-zA-Z]+%$/,
|
48 | RX_VAR_NAME_CONCAT = /^%[a-zA-Z]+%(\+%[a-zA-Z]+%)+$/;
|
49 |
|
50 |
|
51 |
|
52 |
|
53 | function process( ctx, obj ) {
|
54 | try {
|
55 | if ( Array.isArray( obj ) ) return processArray( ctx, obj );
|
56 | switch ( typeof obj ) {
|
57 | case "string":
|
58 | return processString( ctx, obj );
|
59 | case "object":
|
60 | return processObject( ctx, obj );
|
61 | default:
|
62 | return obj;
|
63 | }
|
64 | } catch ( ex ) {
|
65 | fatal( ctx, ex );
|
66 | }
|
67 | }
|
68 |
|
69 |
|
70 | function processArray( ctx, arr ) {
|
71 | try {
|
72 | const preprocessedArray = arr.map( process.bind( null, ctx ) );
|
73 | return preprocessedArray.filter( x => x !== undefined );
|
74 | } catch ( ex ) {
|
75 | throw Error( `...in processArray\n${ex}` );
|
76 | }
|
77 | }
|
78 |
|
79 |
|
80 | function processString( ctx, str ) {
|
81 | try {
|
82 | if ( RX_VAR_NAME.test( str ) ) {
|
83 | var value = ctx.vars[ str ];
|
84 | if ( typeof value === 'undefined' )
|
85 | throw "Undefined variable " + str + "!";
|
86 | return value;
|
87 | }
|
88 | if ( RX_VAR_NAME_CONCAT.test( str ) ) {
|
89 | var variables = str.split( "+" );
|
90 | return variables.map( varName => {
|
91 | var value = ctx.vars[ varName ];
|
92 | if ( typeof value === 'undefined' )
|
93 | throw "Undefined variable " + str + "!";
|
94 | return value;
|
95 | } ).join( "" );
|
96 | } else {
|
97 | return str;
|
98 | }
|
99 | } catch ( ex ) {
|
100 | throw Error( `...in processString(${JSON.stringify( str )})\n${ex}` );
|
101 | }
|
102 | }
|
103 |
|
104 |
|
105 | function processObject( ctx, obj ) {
|
106 | try {
|
107 | if ( obj === null ) return null;
|
108 |
|
109 | if ( typeof obj[ 0 ] === 'string' && RX_VAR_NAME.test( obj[ 0 ] ) )
|
110 | return processExtension( ctx, obj );
|
111 | const preprocessedObject = {};
|
112 |
|
113 | for ( let key in obj ) {
|
114 | if ( RX_VAR_NAME.test( key ) ) {
|
115 | ctx.vars[ key ] = obj[ key ];
|
116 | }
|
117 | }
|
118 |
|
119 | for ( let key in obj ) {
|
120 | if ( RX_VAR_NAME.test( key ) ) continue;
|
121 | const val = process( ctx, obj[ key ] );
|
122 | preprocessedObject[ key ] = val;
|
123 | }
|
124 | return preprocessedObject;
|
125 | } catch ( ex ) {
|
126 | throw Error( `...in processObject()\n${ex}` );
|
127 | }
|
128 | }
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 | function processExtension( ctx, obj ) {
|
136 | try {
|
137 | const
|
138 | varName = obj[ 0 ],
|
139 | baseObject = makeCopyOf( ctx.vars[ varName ] );
|
140 | if ( typeof baseObject === 'undefined' ) {
|
141 | throw Error( `Undefined variable for extension {${varName}}!` );
|
142 | }
|
143 |
|
144 | for ( const key in obj ) {
|
145 | if ( RX_VAR_NAME.test( key ) ) {
|
146 | ctx.vars[ key ] = obj[ key ];
|
147 | }
|
148 | }
|
149 |
|
150 | for ( const key in obj ) {
|
151 | if ( key === "0" ) continue;
|
152 | if ( RX_VAR_NAME.test( key ) ) continue;
|
153 | const val = process( ctx, obj[ key ] );
|
154 | baseObject[ key ] = val;
|
155 | }
|
156 | return processObject( ctx, baseObject );
|
157 | } catch ( ex ) {
|
158 | throw Error( `...in processExtension()\n${ex}` );
|
159 | }
|
160 | }
|
161 |
|
162 |
|
163 | function fatal( ctx, message ) {
|
164 | throw "Error while preprocessig module " + ctx.module + ":\n" +
|
165 | message + "\n" +
|
166 | "Defined variables at this point:\n" +
|
167 | Object.keys( ctx.vars )
|
168 | .map( k => " " + k + ": " + JSON.stringify( ctx.vars[ k ] ) )
|
169 | .join( "\n" );
|
170 | }
|
171 |
|
172 |
|
173 | function makeCopyOf( obj ) {
|
174 | return JSON.parse( JSON.stringify( obj ) );
|
175 | } |
\ | No newline at end of file |