1
1
import Block from './Block.js' ;
2
2
import { trimStart , trimEnd } from '../../utils/trim.js' ;
3
+ import { assign } from '../../shared/index.js' ;
3
4
4
5
function isElseIf ( node ) {
5
6
return node && node . children . length === 1 && node . children [ 0 ] . type === 'IfBlock' ;
6
7
}
7
8
9
+ function getChildState ( parent , child ) {
10
+ return assign ( { } , parent , { name : null , parentNode : null } , child || { } ) ;
11
+ }
12
+
13
+ // Whitespace inside one of these elements will not result in
14
+ // a whitespace node being created in any circumstances. (This
15
+ // list is almost certainly very incomplete)
16
+ const elementsWithoutText = new Set ( [
17
+ 'audio' ,
18
+ 'datalist' ,
19
+ 'dl' ,
20
+ 'ol' ,
21
+ 'optgroup' ,
22
+ 'select' ,
23
+ 'ul' ,
24
+ 'video'
25
+ ] ) ;
26
+
8
27
const preprocessors = {
9
- MustacheTag : ( generator , block , node ) => {
28
+ MustacheTag : ( generator , block , state , node ) => {
29
+ const dependencies = block . findDependencies ( node . expression ) ;
30
+ block . addDependencies ( dependencies ) ;
31
+
32
+ node . _state = getChildState ( state , {
33
+ name : block . getUniqueName ( 'text' )
34
+ } ) ;
35
+ } ,
36
+
37
+ RawMustacheTag : ( generator , block , state , node ) => {
10
38
const dependencies = block . findDependencies ( node . expression ) ;
11
39
block . addDependencies ( dependencies ) ;
40
+
41
+ const basename = block . getUniqueName ( 'raw' ) ;
42
+ const name = block . getUniqueName ( `${ basename } _before` ) ;
43
+
44
+ node . _state = getChildState ( state , { basename, name } ) ;
45
+ } ,
46
+
47
+ Text : ( generator , block , state , node ) => {
48
+ node . _state = getChildState ( state ) ;
49
+
50
+ if ( ! / \S / . test ( node . data ) ) {
51
+ if ( state . namespace ) return ;
52
+ if ( elementsWithoutText . has ( state . parentNodeName ) ) return ;
53
+ }
54
+
55
+ node . _state . shouldCreate = true ;
56
+ node . _state . name = block . getUniqueName ( `text` ) ;
12
57
} ,
13
58
14
- IfBlock : ( generator , block , node ) => {
59
+ IfBlock : ( generator , block , state , node ) => {
15
60
const blocks = [ ] ;
16
61
let dynamic = false ;
17
62
@@ -23,8 +68,10 @@ const preprocessors = {
23
68
name : generator . getUniqueName ( `create_if_block` )
24
69
} ) ;
25
70
71
+ node . _state = getChildState ( state ) ;
72
+
26
73
blocks . push ( node . _block ) ;
27
- preprocessChildren ( generator , node . _block , node ) ;
74
+ preprocessChildren ( generator , node . _block , node . _state , node ) ;
28
75
29
76
if ( node . _block . dependencies . size > 0 ) {
30
77
dynamic = true ;
@@ -38,8 +85,10 @@ const preprocessors = {
38
85
name : generator . getUniqueName ( `create_if_block` )
39
86
} ) ;
40
87
88
+ node . else . _state = getChildState ( state ) ;
89
+
41
90
blocks . push ( node . else . _block ) ;
42
- preprocessChildren ( generator , node . else . _block , node . else ) ;
91
+ preprocessChildren ( generator , node . else . _block , node . else . _state , node . else ) ;
43
92
44
93
if ( node . else . _block . dependencies . size > 0 ) {
45
94
dynamic = true ;
@@ -57,7 +106,7 @@ const preprocessors = {
57
106
generator . blocks . push ( ...blocks ) ;
58
107
} ,
59
108
60
- EachBlock : ( generator , block , node ) => {
109
+ EachBlock : ( generator , block , state , node ) => {
61
110
const dependencies = block . findDependencies ( node . expression ) ;
62
111
block . addDependencies ( dependencies ) ;
63
112
@@ -97,8 +146,12 @@ const preprocessors = {
97
146
params : block . params . concat ( listName , context , indexName )
98
147
} ) ;
99
148
149
+ node . _state = getChildState ( state , {
150
+ inEachBlock : true
151
+ } ) ;
152
+
100
153
generator . blocks . push ( node . _block ) ;
101
- preprocessChildren ( generator , node . _block , node ) ;
154
+ preprocessChildren ( generator , node . _block , node . _state , node ) ;
102
155
block . addDependencies ( node . _block . dependencies ) ;
103
156
node . _block . hasUpdateMethod = node . _block . dependencies . size > 0 ;
104
157
@@ -107,13 +160,32 @@ const preprocessors = {
107
160
name : generator . getUniqueName ( `${ node . _block . name } _else` )
108
161
} ) ;
109
162
163
+ node . else . _state = getChildState ( state ) ;
164
+
110
165
generator . blocks . push ( node . else . _block ) ;
111
- preprocessChildren ( generator , node . else . _block , node . else ) ;
166
+ preprocessChildren ( generator , node . else . _block , node . else . _state , node . else ) ;
112
167
node . else . _block . hasUpdateMethod = node . else . _block . dependencies . size > 0 ;
113
168
}
114
169
} ,
115
170
116
- Element : ( generator , block , node ) => {
171
+ Element : ( generator , block , state , node ) => {
172
+ const isComponent = generator . components . has ( node . name ) || node . name === ':Self' ;
173
+
174
+ if ( isComponent ) {
175
+ node . _state = getChildState ( state ) ;
176
+ } else {
177
+ const name = block . getUniqueName ( node . name . replace ( / [ ^ a - z A - Z 0 - 9 _ $ ] / g, '_' ) ) ;
178
+
179
+ node . _state = getChildState ( state , {
180
+ isTopLevel : false ,
181
+ name,
182
+ parentNode : name ,
183
+ parentNodeName : node . name ,
184
+ namespace : node . name === 'svg' ? 'http://www.w3.org/2000/svg' : state . namespace ,
185
+ allUsedContexts : [ ]
186
+ } ) ;
187
+ }
188
+
117
189
node . attributes . forEach ( attribute => {
118
190
if ( attribute . type === 'Attribute' && attribute . value !== true ) {
119
191
attribute . value . forEach ( chunk => {
@@ -130,8 +202,6 @@ const preprocessors = {
130
202
}
131
203
} ) ;
132
204
133
- const isComponent = generator . components . has ( node . name ) || node . name === ':Self' ;
134
-
135
205
if ( node . children . length ) {
136
206
if ( isComponent ) {
137
207
const name = block . getUniqueName ( ( node . name === ':Self' ? generator . name : node . name ) . toLowerCase ( ) ) ;
@@ -141,21 +211,19 @@ const preprocessors = {
141
211
} ) ;
142
212
143
213
generator . blocks . push ( node . _block ) ;
144
- preprocessChildren ( generator , node . _block , node ) ;
214
+ preprocessChildren ( generator , node . _block , node . _state , node ) ;
145
215
block . addDependencies ( node . _block . dependencies ) ;
146
216
node . _block . hasUpdateMethod = node . _block . dependencies . size > 0 ;
147
217
}
148
218
149
219
else {
150
- preprocessChildren ( generator , block , node ) ;
220
+ preprocessChildren ( generator , block , node . _state , node ) ;
151
221
}
152
222
}
153
223
}
154
224
} ;
155
225
156
- preprocessors . RawMustacheTag = preprocessors . MustacheTag ;
157
-
158
- function preprocessChildren ( generator , block , node ) {
226
+ function preprocessChildren ( generator , block , state , node , isTopLevel ) {
159
227
// glue text nodes together
160
228
const cleaned = [ ] ;
161
229
let lastChild ;
@@ -173,15 +241,43 @@ function preprocessChildren ( generator, block, node ) {
173
241
lastChild = child ;
174
242
} ) ;
175
243
176
- node . children = cleaned ;
244
+ if ( isTopLevel ) {
245
+ // trim leading and trailing whitespace from the top level
246
+ const firstChild = cleaned [ 0 ] ;
247
+ if ( firstChild && firstChild . type === 'Text' ) {
248
+ firstChild . data = trimStart ( firstChild . data ) ;
249
+ if ( ! firstChild . data ) cleaned . shift ( ) ;
250
+ }
251
+
252
+ const lastChild = cleaned [ cleaned . length - 1 ] ;
253
+ if ( lastChild && lastChild . type === 'Text' ) {
254
+ lastChild . data = trimEnd ( lastChild . data ) ;
255
+ if ( ! lastChild . data ) cleaned . pop ( ) ;
256
+ }
257
+ }
258
+
259
+ lastChild = null ;
177
260
178
261
cleaned . forEach ( child => {
179
262
const preprocess = preprocessors [ child . type ] ;
180
- if ( preprocess ) preprocess ( generator , block , child ) ;
263
+ if ( preprocess ) preprocess ( generator , block , state , child ) ;
264
+
265
+ if ( lastChild ) {
266
+ lastChild . next = child ;
267
+ lastChild . needsAnchor = ! child . _state . name ;
268
+ }
269
+
270
+ lastChild = child ;
181
271
} ) ;
272
+
273
+ if ( lastChild ) {
274
+ lastChild . needsAnchor = ! state . parentNode ;
275
+ }
276
+
277
+ node . children = cleaned ;
182
278
}
183
279
184
- export default function preprocess ( generator , node ) {
280
+ export default function preprocess ( generator , state , node ) {
185
281
const block = new Block ( {
186
282
generator,
187
283
name : generator . alias ( 'create_main_fragment' ) ,
@@ -199,21 +295,8 @@ export default function preprocess ( generator, node ) {
199
295
} ) ;
200
296
201
297
generator . blocks . push ( block ) ;
202
- preprocessChildren ( generator , block , node ) ;
298
+ preprocessChildren ( generator , block , state , node , true ) ;
203
299
block . hasUpdateMethod = block . dependencies . size > 0 ;
204
300
205
- // trim leading and trailing whitespace from the top level
206
- const firstChild = node . children [ 0 ] ;
207
- if ( firstChild && firstChild . type === 'Text' ) {
208
- firstChild . data = trimStart ( firstChild . data ) ;
209
- if ( ! firstChild . data ) node . children . shift ( ) ;
210
- }
211
-
212
- const lastChild = node . children [ node . children . length - 1 ] ;
213
- if ( lastChild && lastChild . type === 'Text' ) {
214
- lastChild . data = trimEnd ( lastChild . data ) ;
215
- if ( ! lastChild . data ) node . children . pop ( ) ;
216
- }
217
-
218
301
return block ;
219
302
}
0 commit comments