@@ -3,7 +3,7 @@ const merge = require('lodash.merge')
3
3
const cloneDeep = require ( 'lodash.clonedeep' )
4
4
const parseAndReplace = require ( './expression_parser' )
5
5
6
- let delimiters , unescapeDelimiters , delimiterRegex , unescapeDelimiterRegex , conditionals , loops , options
6
+ let delimiters , unescapeDelimiters , delimiterRegex , unescapeDelimiterRegex , conditionals , loops , scopes , options
7
7
8
8
module . exports = function PostHTMLExpressions ( _options = { } ) {
9
9
options = _options
@@ -19,6 +19,7 @@ module.exports = function PostHTMLExpressions (_options = {}) {
19
19
20
20
// conditional and loop options
21
21
conditionals = options . conditionalTags || [ 'if' , 'elseif' , 'else' ]
22
+ scopes = options . scopeTags || [ 'scope' ]
22
23
loops = options . loopTags || [ 'each' ]
23
24
24
25
// kick off the parsing
@@ -60,7 +61,7 @@ function walk (opts, nodes) {
60
61
}
61
62
62
63
// if the node has content, recurse (unless it's a loop, handled later)
63
- if ( node . content && node . tag !== loops [ 0 ] ) {
64
+ if ( node . content && node . tag !== loops [ 0 ] && node . tag !== scopes [ 0 ] ) {
64
65
node . content = walk ( opts , node . content )
65
66
}
66
67
@@ -159,6 +160,27 @@ function walk (opts, nodes) {
159
160
return m
160
161
}
161
162
163
+ // parse scopes
164
+ if ( node . tag === scopes [ 0 ] ) {
165
+ console . log ( 'scopes found' )
166
+ // handle syntax error
167
+ if ( ! ( node . attrs && node . attrs . with ) ) {
168
+ throw new Error ( `the "${ scopes [ 0 ] } " tag must have a "with" attribute` )
169
+ }
170
+
171
+ const target = vm . runInContext ( node . attrs . with , ctx )
172
+
173
+ // handle additional syntax errors
174
+ if ( typeof target !== 'object' || Array . isArray ( target ) ) {
175
+ throw new Error ( 'You must provide an object to make scope' )
176
+ }
177
+
178
+ m . push ( executeScoped ( target , node ) )
179
+
180
+ // return directly out of the loop, which will skip the "each" tag
181
+ return m
182
+ }
183
+
162
184
// return the node
163
185
m . push ( node )
164
186
return m
@@ -248,10 +270,19 @@ function executeLoop (loopParams, p1, p2, node) {
248
270
const scopedLocals = { }
249
271
scopedLocals [ loopParams [ 0 ] ] = p1
250
272
if ( loopParams [ 1 ] ) scopedLocals [ loopParams [ 1 ] ] = p2
273
+
274
+ return executeScoped ( scopedLocals , node )
275
+ }
276
+
277
+ /**
278
+ * Runs walk function with arbitrary set of local variables
279
+ */
280
+ function executeScoped ( scopedLocals , node ) {
251
281
// merge nondestructively into existing locals
252
282
const scopedOptions = merge ( cloneDeep ( options ) , { locals : scopedLocals } )
253
283
// walk through the contents and run replacements with modified options
254
284
// we need to clone the node because the normal operation modifies
255
285
// the node directly
256
286
return walk ( scopedOptions , cloneDeep ( node . content ) )
257
287
}
288
+
0 commit comments