@lightningjs/blits 0.9.9 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/boilerplate/common/public/fonts/Lato-Regular.ttf +0 -0
- package/boilerplate/common/public/fonts/Raleway-ExtraBold.ttf +0 -0
- package/docs/essentials/displaying_text.md +1 -1
- package/package.json +3 -4
- package/src/component/base/events.js +1 -1
- package/src/component/base/utils.js +34 -1
- package/src/component/setup/props.js +3 -1
- package/src/component/setup/props.test.js +51 -19
- package/src/component.d.ts +2 -1
- package/src/component.js +20 -13
- package/src/components/Circle.js +13 -12
- package/src/components/FPScounter.js +413 -465
- package/src/components/Image.js +7 -9
- package/src/components/Layout.js +49 -0
- package/src/components/Layout.orig.js +34 -0
- package/src/components/RouterView.js +6 -10
- package/src/components/Sprite.js +10 -12
- package/src/components/index.js +2 -2
- package/src/components/index.orig.js +2 -2
- package/src/engine.js +1 -1
- package/src/engines/L3/element.js +193 -180
- package/src/engines/L3/element.test.js +170 -0
- package/src/engines/L3/fontLoader.js +20 -7
- package/src/engines/L3/index.js +2 -2
- package/src/engines/L3/launch.js +7 -13
- package/src/engines/L3/shaderLoader.js +12 -0
- package/src/engines/index.js +1 -1
- package/src/launch.d.ts +19 -2
- package/src/lib/codegenerator/generator.js +214 -77
- package/src/lib/codegenerator/generator.test.js +657 -942
- package/src/lib/colors/colors.js +59 -46
- package/src/lib/precompiler/precompiler.js +2 -1
- package/src/lib/reactivity/effect.js +10 -13
- package/src/lib/reactivity/reactive.js +24 -14
- package/src/lib/symbols.js +1 -0
- package/src/router/router.js +17 -3
- package/vite/msdfGenerator.js +52 -53
- package/boilerplate/common/public/fonts/Lato-Regular.msdf.json +0 -5383
- package/boilerplate/common/public/fonts/Lato-Regular.msdf.png +0 -0
- package/boilerplate/common/public/fonts/Raleway-ExtraBold.msdf.json +0 -10838
- package/boilerplate/common/public/fonts/Raleway-ExtraBold.msdf.png +0 -0
- package/boilerplate/js/default/src/renderer.js +0 -4
- package/src/components/Text.js +0 -119
- package/src/components/Text.orig.js +0 -81
|
@@ -19,7 +19,7 @@ let counter
|
|
|
19
19
|
|
|
20
20
|
export default function (templateObject = { children: [] }) {
|
|
21
21
|
const ctx = {
|
|
22
|
-
renderCode: ['const elms = []'],
|
|
22
|
+
renderCode: ['const elms = []', 'let componentType', 'const rootComponent = component'],
|
|
23
23
|
effectsCode: [],
|
|
24
24
|
context: { props: [], components: this.components },
|
|
25
25
|
}
|
|
@@ -29,9 +29,18 @@ export default function (templateObject = { children: [] }) {
|
|
|
29
29
|
ctx.renderCode.push('return elms')
|
|
30
30
|
|
|
31
31
|
return {
|
|
32
|
-
render: new Function(
|
|
32
|
+
render: new Function(
|
|
33
|
+
'parent',
|
|
34
|
+
'component',
|
|
35
|
+
'context',
|
|
36
|
+
'components',
|
|
37
|
+
'effect',
|
|
38
|
+
'getRaw',
|
|
39
|
+
ctx.renderCode.join('\n')
|
|
40
|
+
),
|
|
33
41
|
effects: ctx.effectsCode.map(
|
|
34
|
-
(code) =>
|
|
42
|
+
(code) =>
|
|
43
|
+
new Function('component', 'elms', 'context', 'components', 'rootComponent', 'effect', code)
|
|
35
44
|
),
|
|
36
45
|
context: ctx.context,
|
|
37
46
|
}
|
|
@@ -40,7 +49,7 @@ export default function (templateObject = { children: [] }) {
|
|
|
40
49
|
const generateElementCode = function (
|
|
41
50
|
templateObject,
|
|
42
51
|
parent = false,
|
|
43
|
-
options = { key: false, component: 'component.', forceEffect: false }
|
|
52
|
+
options = { key: false, component: 'component.', forceEffect: false, forloop: false }
|
|
44
53
|
) {
|
|
45
54
|
const renderCode = options.forceEffect ? this.effectsCode : this.renderCode
|
|
46
55
|
if (parent) {
|
|
@@ -52,17 +61,26 @@ const generateElementCode = function (
|
|
|
52
61
|
|
|
53
62
|
if (options.key) {
|
|
54
63
|
renderCode.push(`
|
|
55
|
-
elms[${counter}]
|
|
64
|
+
if(elms[${counter}] === undefined) {
|
|
65
|
+
elms[${counter}] = {}
|
|
66
|
+
}
|
|
56
67
|
`)
|
|
57
68
|
}
|
|
58
69
|
|
|
70
|
+
renderCode.push(`const elementConfig${counter} = {}`)
|
|
71
|
+
|
|
72
|
+
if (options.forloop) {
|
|
73
|
+
renderCode.push(`if(!${elm}) {`)
|
|
74
|
+
}
|
|
75
|
+
|
|
59
76
|
renderCode.push(`
|
|
60
|
-
|
|
61
|
-
${elm} = this.element({parent: parent || 'root'}, component)
|
|
62
|
-
}
|
|
63
|
-
const elementConfig${counter} = {}
|
|
77
|
+
${elm} = this.element({parent: parent || 'root'}, component)
|
|
64
78
|
`)
|
|
65
79
|
|
|
80
|
+
if (options.forloop) {
|
|
81
|
+
renderCode.push('}')
|
|
82
|
+
}
|
|
83
|
+
|
|
66
84
|
const children = templateObject['children']
|
|
67
85
|
delete templateObject['children']
|
|
68
86
|
|
|
@@ -77,11 +95,19 @@ const generateElementCode = function (
|
|
|
77
95
|
`)
|
|
78
96
|
}
|
|
79
97
|
|
|
98
|
+
if (key === 'key') return
|
|
99
|
+
|
|
80
100
|
if (isReactiveKey(key)) {
|
|
81
101
|
if (options.holder && key === ':color') return
|
|
82
102
|
this.effectsCode.push(
|
|
83
103
|
`${elm}.set('${key.substring(1)}', ${interpolate(templateObject[key], options.component)})`
|
|
84
104
|
)
|
|
105
|
+
renderCode.push(
|
|
106
|
+
`elementConfig${counter}['${key.substring(1)}'] = ${interpolate(
|
|
107
|
+
templateObject[key],
|
|
108
|
+
options.component
|
|
109
|
+
)}`
|
|
110
|
+
)
|
|
85
111
|
} else {
|
|
86
112
|
renderCode.push(
|
|
87
113
|
`elementConfig${counter}['${key}'] = ${cast(templateObject[key], key, options.component)}`
|
|
@@ -99,11 +125,15 @@ const generateElementCode = function (
|
|
|
99
125
|
`)
|
|
100
126
|
}
|
|
101
127
|
|
|
102
|
-
|
|
103
|
-
if(!${elm}.nodeId) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
`)
|
|
128
|
+
if (options.forloop) {
|
|
129
|
+
renderCode.push(`if(!${elm}.nodeId) {`)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
renderCode.push(`${elm}.populate(elementConfig${counter})`)
|
|
133
|
+
|
|
134
|
+
if (options.forloop) {
|
|
135
|
+
renderCode.push('}')
|
|
136
|
+
}
|
|
107
137
|
|
|
108
138
|
if (children) {
|
|
109
139
|
generateCode.call(this, { children }, `${elm}`, options)
|
|
@@ -113,7 +143,13 @@ const generateElementCode = function (
|
|
|
113
143
|
const generateComponentCode = function (
|
|
114
144
|
templateObject,
|
|
115
145
|
parent = false,
|
|
116
|
-
options = {
|
|
146
|
+
options = {
|
|
147
|
+
key: false,
|
|
148
|
+
component: 'component.',
|
|
149
|
+
forceEffect: false,
|
|
150
|
+
holder: false,
|
|
151
|
+
forloop: false,
|
|
152
|
+
}
|
|
117
153
|
) {
|
|
118
154
|
const renderCode = options.forceEffect ? this.effectsCode : this.renderCode
|
|
119
155
|
|
|
@@ -140,7 +176,9 @@ const generateComponentCode = function (
|
|
|
140
176
|
|
|
141
177
|
if (options.key) {
|
|
142
178
|
renderCode.push(`
|
|
143
|
-
elms[${counter}]
|
|
179
|
+
if(elms[${counter}] === undefined) {
|
|
180
|
+
elms[${counter}] = {}
|
|
181
|
+
}
|
|
144
182
|
`)
|
|
145
183
|
}
|
|
146
184
|
|
|
@@ -169,34 +207,56 @@ const generateComponentCode = function (
|
|
|
169
207
|
}
|
|
170
208
|
})
|
|
171
209
|
|
|
210
|
+
if (options.forloop) {
|
|
211
|
+
renderCode.push(`if(!${elm}) {`)
|
|
212
|
+
}
|
|
213
|
+
|
|
172
214
|
renderCode.push(`
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
} not found')})).call(null, {props: props${counter}}, ${parent}, component)
|
|
181
|
-
if (${elm}[Symbol.for('slots')][0]) {
|
|
182
|
-
parent = ${elm}[Symbol.for('slots')][0]
|
|
183
|
-
component = ${elm}
|
|
184
|
-
} else {
|
|
185
|
-
parent = ${elm}[Symbol.for('children')][0]
|
|
215
|
+
componentType = props${counter}['is'] || '${templateObject[Symbol.for('componentType')]}'
|
|
216
|
+
|
|
217
|
+
let component${counter}
|
|
218
|
+
if(typeof componentType === 'string') {
|
|
219
|
+
component${counter} = context.components && context.components[componentType] || components[componentType]
|
|
220
|
+
if(!component${counter}) {
|
|
221
|
+
throw new Error('Component "${templateObject[Symbol.for('componentType')]}" not found')
|
|
186
222
|
}
|
|
223
|
+
} else if(typeof componentType === 'function' && componentType.name === 'factory') {
|
|
224
|
+
component${counter} = componentType
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
${elm} = component${counter}.call(null, {props: props${counter}}, ${parent}, component)
|
|
228
|
+
|
|
229
|
+
if (${elm}[Symbol.for('slots')][0]) {
|
|
230
|
+
parent = ${elm}[Symbol.for('slots')][0]
|
|
231
|
+
component = ${elm}
|
|
232
|
+
} else {
|
|
233
|
+
parent = ${elm}[Symbol.for('children')][0]
|
|
187
234
|
}
|
|
188
235
|
`)
|
|
189
236
|
|
|
237
|
+
if (options.forloop) {
|
|
238
|
+
renderCode.push('}')
|
|
239
|
+
}
|
|
240
|
+
|
|
190
241
|
if (children) {
|
|
191
242
|
counter++
|
|
192
243
|
generateElementCode.call(this, { children }, false, { ...options })
|
|
193
244
|
}
|
|
245
|
+
// if (!options.forloop) {
|
|
246
|
+
// renderCode.push(`
|
|
247
|
+
// component = rootComponent
|
|
248
|
+
// `)
|
|
249
|
+
// }
|
|
194
250
|
}
|
|
195
251
|
|
|
196
252
|
const generateForLoopCode = function (templateObject, parent) {
|
|
197
253
|
const forLoop = templateObject[':for']
|
|
198
254
|
delete templateObject[':for']
|
|
199
255
|
|
|
256
|
+
const key = templateObject['key']
|
|
257
|
+
const forKey = interpolate(key, 'scope.')
|
|
258
|
+
|
|
259
|
+
delete templateObject['key']
|
|
200
260
|
const regex = /(.+)\s+in\s+(.+)/gi
|
|
201
261
|
// const regex = /(:?\(*)(.+)\s+in\s+(.+)/gi
|
|
202
262
|
|
|
@@ -208,6 +268,8 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
208
268
|
.replace(')', '')
|
|
209
269
|
.split(/\s*,\s*/)
|
|
210
270
|
|
|
271
|
+
const scopeRegex = new RegExp(`(scope\\.(?!${item}\\.|${index}|key)(\\w+))`, 'gi')
|
|
272
|
+
|
|
211
273
|
// local context
|
|
212
274
|
const ctx = {
|
|
213
275
|
renderCode: [],
|
|
@@ -216,87 +278,157 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
216
278
|
}
|
|
217
279
|
|
|
218
280
|
if (parent) {
|
|
219
|
-
ctx.renderCode.push(`
|
|
281
|
+
ctx.renderCode.push(`parent = ${parent}`)
|
|
220
282
|
}
|
|
221
283
|
|
|
222
284
|
const forStartCounter = counter
|
|
223
285
|
|
|
224
|
-
// reference all reactive attributes (except those referencing the iterator item),
|
|
225
|
-
// to ensure that reactivity is registered, even when the initial array is empty
|
|
226
|
-
Object.keys(templateObject).forEach((k) => {
|
|
227
|
-
if (isReactiveKey(k) && templateObject[k].indexOf('$' + item) === -1) {
|
|
228
|
-
ctx.renderCode.push(`
|
|
229
|
-
void ${interpolate(templateObject[k], 'component.')}
|
|
230
|
-
`)
|
|
231
|
-
}
|
|
232
|
-
})
|
|
233
|
-
|
|
234
286
|
ctx.renderCode.push(`
|
|
235
|
-
const
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
287
|
+
const created${forStartCounter} = []
|
|
288
|
+
const forloop${forStartCounter} = (collection = [], elms, created) => {
|
|
289
|
+
const rawCollection = getRaw(collection)
|
|
290
|
+
const keys = new Set(rawCollection.map((${item}) => '' + ${interpolate(key, '')}))
|
|
291
|
+
`)
|
|
292
|
+
|
|
293
|
+
// keep track of the index in the render code so we can inject
|
|
294
|
+
// the code that takes care of destroying elements (generated later on)
|
|
295
|
+
// in the right spot
|
|
296
|
+
const indexToInjectDestroyCode = ctx.renderCode.length
|
|
245
297
|
|
|
298
|
+
ctx.renderCode.push(`
|
|
299
|
+
created.length = 0
|
|
300
|
+
const length = collection.length
|
|
301
|
+
for(let __index = 0; __index < length; __index++) {
|
|
302
|
+
const scope = Object.create(component)
|
|
303
|
+
parent = ${parent}
|
|
304
|
+
scope['${index}'] = __index
|
|
305
|
+
scope['${item}'] = rawCollection[__index]
|
|
306
|
+
scope['key'] = ${forKey || '__index'}
|
|
307
|
+
`)
|
|
246
308
|
if ('ref' in templateObject && templateObject.ref.indexOf('$') === -1) {
|
|
247
309
|
// automatically map the ref for each item in the loop based on the given ref key
|
|
248
310
|
ctx.renderCode.push(`
|
|
249
|
-
|
|
311
|
+
scope['__ref'] = '${templateObject.ref}' + __index
|
|
250
312
|
`)
|
|
251
313
|
templateObject.ref = '$__ref'
|
|
252
314
|
}
|
|
315
|
+
|
|
253
316
|
ctx.renderCode.push(`
|
|
254
|
-
|
|
317
|
+
created.push(scope.key)
|
|
255
318
|
`)
|
|
256
319
|
|
|
257
|
-
if ('key' in templateObject) {
|
|
258
|
-
ctx.renderCode.push(`
|
|
259
|
-
keys.push(${interpolate(templateObject.key, 'scope.')}.toString())
|
|
260
|
-
`)
|
|
261
|
-
} else {
|
|
262
|
-
ctx.renderCode.push(`
|
|
263
|
-
keys.push(scope.key.toString())
|
|
264
|
-
`)
|
|
265
|
-
}
|
|
266
|
-
|
|
267
320
|
if (
|
|
268
321
|
templateObject[Symbol.for('componentType')] === 'Element' ||
|
|
269
|
-
templateObject[Symbol.for('componentType')] === 'Slot'
|
|
322
|
+
templateObject[Symbol.for('componentType')] === 'Slot' ||
|
|
323
|
+
templateObject[Symbol.for('componentType')] === 'Text'
|
|
270
324
|
) {
|
|
271
325
|
generateElementCode.call(ctx, templateObject, parent, {
|
|
272
326
|
key: 'scope.key',
|
|
273
327
|
component: 'scope.',
|
|
274
328
|
forceEffect: false,
|
|
329
|
+
forloop: true,
|
|
275
330
|
})
|
|
276
331
|
} else {
|
|
277
332
|
generateComponentCode.call(ctx, templateObject, false, {
|
|
278
333
|
key: 'scope.key',
|
|
279
334
|
component: 'scope.',
|
|
280
335
|
forceEffect: false,
|
|
336
|
+
forloop: true,
|
|
281
337
|
})
|
|
282
338
|
}
|
|
283
|
-
ctx.renderCode = ctx.renderCode.concat(ctx.effectsCode)
|
|
284
|
-
ctx.renderCode.push('}')
|
|
285
339
|
|
|
340
|
+
// separate effects that only rely on variables in the itteration
|
|
341
|
+
const innerScopeEffects = ctx.effectsCode.filter(
|
|
342
|
+
(effect) => [...effect.matchAll(scopeRegex)].length === 0
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
// separate effects that (also) rely on variables in the outer scope
|
|
346
|
+
const outerScopeEffects = ctx.effectsCode.filter(
|
|
347
|
+
(effect) => [...effect.matchAll(scopeRegex)].length !== 0
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
ctx.renderCode.push(`
|
|
351
|
+
scope['${item}'] = collection[__index]
|
|
352
|
+
`)
|
|
353
|
+
|
|
354
|
+
// inner scope variables are part of the main forloop
|
|
355
|
+
innerScopeEffects.forEach((effect) => {
|
|
356
|
+
const key = effect.indexOf(`scope.${index}`) > -1 ? `'${interpolate(result[2], '')}'` : null
|
|
357
|
+
ctx.renderCode.push(`
|
|
358
|
+
effect(() => {
|
|
359
|
+
${effect}
|
|
360
|
+
}, ${key})
|
|
361
|
+
`)
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
ctx.renderCode.push(`
|
|
365
|
+
if(elms[${forStartCounter}][0] && elms[${forStartCounter}][0].forComponent && elms[${forStartCounter}][0].forComponent.___layout) {
|
|
366
|
+
elms[${forStartCounter}][0].forComponent.___layout()
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}`)
|
|
370
|
+
|
|
371
|
+
// generate code that destroys items
|
|
372
|
+
const destroyCode = []
|
|
373
|
+
destroyCode.push(`
|
|
374
|
+
let i = created.length
|
|
375
|
+
|
|
376
|
+
while (i--) {
|
|
377
|
+
const key = created[i]
|
|
378
|
+
if (!keys.has(key)) {
|
|
379
|
+
`)
|
|
286
380
|
const forEndCounter = counter
|
|
381
|
+
|
|
382
|
+
for (let i = forStartCounter; i <= forEndCounter; i++) {
|
|
383
|
+
destroyCode.push(`
|
|
384
|
+
elms[${i}][key] && elms[${i}][key].destroy()
|
|
385
|
+
delete elms[${i}][key]
|
|
386
|
+
`)
|
|
387
|
+
}
|
|
388
|
+
destroyCode.push(`
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
`)
|
|
392
|
+
|
|
393
|
+
// inject the destroy code in the correct spot
|
|
394
|
+
ctx.renderCode.splice(indexToInjectDestroyCode, 0, ...destroyCode)
|
|
287
395
|
ctx.renderCode.push(`
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
396
|
+
effect(() => {
|
|
397
|
+
forloop${forStartCounter}(${cast(result[2], ':for')}, elms, created${forStartCounter})
|
|
398
|
+
}, '${interpolate(result[2], '')}')
|
|
399
|
+
`)
|
|
400
|
+
|
|
401
|
+
outerScopeEffects.forEach((effect) => {
|
|
402
|
+
const matches = [...effect.matchAll(scopeRegex)]
|
|
403
|
+
|
|
404
|
+
let l = matches.length
|
|
405
|
+
const refs = []
|
|
406
|
+
while (l--) {
|
|
407
|
+
const match = matches[l]
|
|
408
|
+
const ref = `component.${match[2]}`
|
|
409
|
+
refs.indexOf(ref) === -1 && refs.push(ref)
|
|
410
|
+
effect =
|
|
411
|
+
effect.substring(0, match.index) + ref + effect.substring(match.index + match[1].length)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
ctx.renderCode.push(`
|
|
415
|
+
effect(() => {
|
|
416
|
+
void ${refs.join(', ')}
|
|
417
|
+
for(let __index = 0; __index < ${interpolate(result[2])}.length; __index++) {
|
|
418
|
+
const scope = {}
|
|
419
|
+
scope['${index}'] = __index
|
|
420
|
+
scope['${item}'] = ${interpolate(result[2])}[__index]
|
|
421
|
+
scope['key'] = ${forKey || '__index'}
|
|
422
|
+
`)
|
|
423
|
+
|
|
424
|
+
ctx.renderCode.push(`
|
|
425
|
+
${effect}
|
|
295
426
|
}
|
|
296
427
|
})
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
428
|
+
`)
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
this.renderCode.push(ctx.renderCode.join('\n'))
|
|
300
432
|
}
|
|
301
433
|
|
|
302
434
|
const generateCode = function (templateObject, parent = false, options = {}) {
|
|
@@ -309,8 +441,12 @@ const generateCode = function (templateObject, parent = false, options = {}) {
|
|
|
309
441
|
} else {
|
|
310
442
|
if (
|
|
311
443
|
childTemplateObject[Symbol.for('componentType')] === 'Element' ||
|
|
312
|
-
childTemplateObject[Symbol.for('componentType')] === 'Slot'
|
|
444
|
+
childTemplateObject[Symbol.for('componentType')] === 'Slot' ||
|
|
445
|
+
childTemplateObject[Symbol.for('componentType')] === 'Text'
|
|
313
446
|
) {
|
|
447
|
+
if (childTemplateObject[Symbol.for('componentType')] === 'Text') {
|
|
448
|
+
childTemplateObject.__textnode = 'true'
|
|
449
|
+
}
|
|
314
450
|
generateElementCode.call(this, childTemplateObject, parent, options)
|
|
315
451
|
} else {
|
|
316
452
|
generateComponentCode.call(this, childTemplateObject, parent, options)
|
|
@@ -320,6 +456,7 @@ const generateCode = function (templateObject, parent = false, options = {}) {
|
|
|
320
456
|
}
|
|
321
457
|
|
|
322
458
|
const interpolate = (val, component = 'component.') => {
|
|
459
|
+
if (val === undefined) return val
|
|
323
460
|
const replaceString = /('.*?')+/gi
|
|
324
461
|
const replaceDollar = /\$/gi
|
|
325
462
|
const matches = val.matchAll(replaceString)
|
|
@@ -335,7 +472,7 @@ const interpolate = (val, component = 'component.') => {
|
|
|
335
472
|
}
|
|
336
473
|
|
|
337
474
|
// replace remaining dollar signs
|
|
338
|
-
val = val.replace(replaceDollar, component)
|
|
475
|
+
val = val.replace(replaceDollar, component || '')
|
|
339
476
|
|
|
340
477
|
// restore string replacemenet
|
|
341
478
|
restore.forEach((el, idx) => {
|