@lightningjs/blits 1.1.0 → 1.3.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 +19 -0
- package/NOTICE +9 -0
- package/docs/_sidebar.md +1 -0
- package/docs/built-in/directives.md +4 -6
- package/docs/built-in/for-loop.md +6 -8
- package/docs/components/component_state.md +3 -5
- package/docs/components/computed_properties.md +3 -5
- package/docs/components/lifecycle_events.md +2 -4
- package/docs/components/methods.md +1 -3
- package/docs/components/props.md +3 -5
- package/docs/components/user_input.md +6 -8
- package/docs/components/utilities.md +1 -2
- package/docs/components/watchers.md +2 -4
- package/docs/essentials/application_root.md +1 -3
- package/docs/essentials/components.md +2 -4
- package/docs/essentials/displaying_images.md +4 -6
- package/docs/essentials/displaying_text.md +4 -6
- package/docs/essentials/element_attributes.md +10 -12
- package/docs/essentials/template_syntax.md +5 -7
- package/docs/getting_started/file_structure.md +9 -11
- package/docs/getting_started/getting_started.md +5 -7
- package/docs/plugins/language.md +172 -0
- package/docs/plugins/text-to-speech-announcer.md +2 -4
- package/docs/sidebar.json +4 -0
- package/docs/transitions_animations/transitions.md +5 -7
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/package.json +3 -2
- package/src/component/base/index.js +4 -1
- package/src/component/base/log.js +1 -1
- package/src/component/base/methods.js +1 -2
- package/src/component/setup/state.js +9 -13
- package/src/component.d.ts +6 -0
- package/src/component.js +30 -10
- package/src/components/FPScounter.js +56 -12
- package/src/components/index.js +0 -2
- package/src/components/index.orig.js +0 -2
- package/src/engines/L3/element.js +56 -66
- package/src/helpers/fetchJson.js +34 -0
- package/src/lib/codegenerator/generator.js +104 -28
- package/src/lib/codegenerator/generator.test.js +184 -0
- package/src/lib/colors/colors.js +6 -7
- package/src/lib/reactivity/reactive.js +3 -5
- package/src/lib/symbols.js +1 -0
- package/src/lib/templateparser/parser.js +1 -1
- package/src/plugin.d.ts +71 -0
- package/src/plugin.js +23 -0
- package/src/{components/Image.orig.js → plugins/index.js} +2 -17
- package/src/plugins/language.js +122 -0
- package/src/components/Image.js +0 -52
|
@@ -70,7 +70,7 @@ const generateElementCode = function (
|
|
|
70
70
|
renderCode.push(`const elementConfig${counter} = {}`)
|
|
71
71
|
|
|
72
72
|
if (options.forloop) {
|
|
73
|
-
renderCode.push(`if(
|
|
73
|
+
renderCode.push(`if(${elm} === undefined) {`)
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
renderCode.push(`
|
|
@@ -99,9 +99,20 @@ const generateElementCode = function (
|
|
|
99
99
|
|
|
100
100
|
if (isReactiveKey(key)) {
|
|
101
101
|
if (options.holder && key === ':color') return
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
if (options.holder) {
|
|
103
|
+
this.effectsCode.push(`
|
|
104
|
+
if(typeof skip${counter} === 'undefined' ||
|
|
105
|
+
skip${counter}.indexOf('${key.substring(1)}') === -1)
|
|
106
|
+
${elm}.set('${key.substring(1)}', ${interpolate(templateObject[key], options.component)})
|
|
107
|
+
`)
|
|
108
|
+
} else {
|
|
109
|
+
this.effectsCode.push(`
|
|
110
|
+
${elm}.set('${key.substring(1)}', ${interpolate(
|
|
111
|
+
templateObject[key],
|
|
112
|
+
options.component
|
|
113
|
+
)})
|
|
114
|
+
`)
|
|
115
|
+
}
|
|
105
116
|
renderCode.push(
|
|
106
117
|
`elementConfig${counter}['${key.substring(1)}'] = ${interpolate(
|
|
107
118
|
templateObject[key],
|
|
@@ -117,16 +128,18 @@ const generateElementCode = function (
|
|
|
117
128
|
|
|
118
129
|
if (options.holder === true) {
|
|
119
130
|
renderCode.push(`
|
|
131
|
+
const skip${counter} = []
|
|
120
132
|
if(typeof cmp${counter} !== 'undefined') {
|
|
121
133
|
for(let key in cmp${counter}.config.props) {
|
|
122
134
|
delete elementConfig${counter}[cmp${counter}.config.props[key]]
|
|
135
|
+
skip${counter}.push(cmp${counter}.config.props[key])
|
|
123
136
|
}
|
|
124
137
|
}
|
|
125
138
|
`)
|
|
126
139
|
}
|
|
127
140
|
|
|
128
141
|
if (options.forloop) {
|
|
129
|
-
renderCode.push(`if(
|
|
142
|
+
renderCode.push(`if(${elm}.nodeId === undefined) {`)
|
|
130
143
|
}
|
|
131
144
|
|
|
132
145
|
renderCode.push(`${elm}.populate(elementConfig${counter})`)
|
|
@@ -187,6 +200,11 @@ const generateComponentCode = function (
|
|
|
187
200
|
}
|
|
188
201
|
|
|
189
202
|
renderCode.push(`const props${counter} = {}`)
|
|
203
|
+
|
|
204
|
+
if (options.forloop) {
|
|
205
|
+
renderCode.push(`if(${elm} === undefined) {`)
|
|
206
|
+
}
|
|
207
|
+
|
|
190
208
|
Object.keys(templateObject).forEach((key) => {
|
|
191
209
|
if (isReactiveKey(key)) {
|
|
192
210
|
this.effectsCode.push(`
|
|
@@ -207,10 +225,6 @@ const generateComponentCode = function (
|
|
|
207
225
|
}
|
|
208
226
|
})
|
|
209
227
|
|
|
210
|
-
if (options.forloop) {
|
|
211
|
-
renderCode.push(`if(!${elm}) {`)
|
|
212
|
-
}
|
|
213
|
-
|
|
214
228
|
renderCode.push(`
|
|
215
229
|
componentType = props${counter}['is'] || '${templateObject[Symbol.for('componentType')]}'
|
|
216
230
|
|
|
@@ -256,6 +270,11 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
256
270
|
const key = templateObject['key']
|
|
257
271
|
const forKey = interpolate(key, 'scope.')
|
|
258
272
|
|
|
273
|
+
const shallow = !!!(
|
|
274
|
+
templateObject['$shallow'] && templateObject['$shallow'].toLowerCase() === 'false'
|
|
275
|
+
)
|
|
276
|
+
delete templateObject['$shallow']
|
|
277
|
+
|
|
259
278
|
delete templateObject['key']
|
|
260
279
|
const regex = /(.+)\s+in\s+(.+)/gi
|
|
261
280
|
// const regex = /(:?\(*)(.+)\s+in\s+(.+)/gi
|
|
@@ -287,7 +306,12 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
287
306
|
const created${forStartCounter} = []
|
|
288
307
|
const forloop${forStartCounter} = (collection = [], elms, created) => {
|
|
289
308
|
const rawCollection = getRaw(collection)
|
|
290
|
-
const keys = new Set(
|
|
309
|
+
const keys = new Set()
|
|
310
|
+
let l = rawCollection.length
|
|
311
|
+
while(l--) {
|
|
312
|
+
const ${item} = rawCollection[l]
|
|
313
|
+
keys.add('' + ${interpolate(key, '') || 'l'})
|
|
314
|
+
}
|
|
291
315
|
`)
|
|
292
316
|
|
|
293
317
|
// keep track of the index in the render code so we can inject
|
|
@@ -297,13 +321,13 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
297
321
|
|
|
298
322
|
ctx.renderCode.push(`
|
|
299
323
|
created.length = 0
|
|
300
|
-
const length =
|
|
324
|
+
const length = rawCollection.length
|
|
301
325
|
for(let __index = 0; __index < length; __index++) {
|
|
302
326
|
const scope = Object.create(component)
|
|
303
327
|
parent = ${parent}
|
|
304
328
|
scope['${index}'] = __index
|
|
305
329
|
scope['${item}'] = rawCollection[__index]
|
|
306
|
-
scope['key'] = ${forKey || '__index'}
|
|
330
|
+
scope['key'] = '' + ${forKey || '__index'}
|
|
307
331
|
`)
|
|
308
332
|
if ('ref' in templateObject && templateObject.ref.indexOf('$') === -1) {
|
|
309
333
|
// automatically map the ref for each item in the loop based on the given ref key
|
|
@@ -347,24 +371,33 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
347
371
|
(effect) => [...effect.matchAll(scopeRegex)].length !== 0
|
|
348
372
|
)
|
|
349
373
|
|
|
350
|
-
|
|
351
|
-
|
|
374
|
+
if (shallow === false) {
|
|
375
|
+
ctx.renderCode.push(`
|
|
376
|
+
scope['${item}'] = null
|
|
377
|
+
scope['${item}'] = collection[__index]
|
|
352
378
|
`)
|
|
379
|
+
}
|
|
353
380
|
|
|
354
381
|
// inner scope variables are part of the main forloop
|
|
355
382
|
innerScopeEffects.forEach((effect) => {
|
|
356
383
|
const key = effect.indexOf(`scope.${index}`) > -1 ? `'${interpolate(result[2], '')}'` : null
|
|
357
|
-
|
|
358
|
-
|
|
384
|
+
if (effect.indexOf("Symbol.for('props')") === -1) {
|
|
385
|
+
ctx.renderCode.push(`
|
|
386
|
+
effect(() => {
|
|
387
|
+
${effect}
|
|
388
|
+
}, ${key})
|
|
389
|
+
`)
|
|
390
|
+
} else {
|
|
391
|
+
// props shouldn't be wrapped in an effect, but simply passed on
|
|
392
|
+
ctx.renderCode.push(`
|
|
359
393
|
${effect}
|
|
360
|
-
|
|
361
|
-
|
|
394
|
+
`)
|
|
395
|
+
}
|
|
362
396
|
})
|
|
363
|
-
|
|
397
|
+
// if(elms[${forStartCounter}][0] && elms[${forStartCounter}][0].forComponent && elms[${forStartCounter}][0].forComponent.___layout) {
|
|
398
|
+
// elms[${forStartCounter}][0].forComponent.___layout()
|
|
399
|
+
// }
|
|
364
400
|
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
401
|
}
|
|
369
402
|
}`)
|
|
370
403
|
|
|
@@ -374,8 +407,8 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
374
407
|
let i = created.length
|
|
375
408
|
|
|
376
409
|
while (i--) {
|
|
377
|
-
|
|
378
|
-
|
|
410
|
+
if (keys.has(created[i]) === false) {
|
|
411
|
+
const key = created[i]
|
|
379
412
|
`)
|
|
380
413
|
const forEndCounter = counter
|
|
381
414
|
|
|
@@ -458,7 +491,7 @@ const generateCode = function (templateObject, parent = false, options = {}) {
|
|
|
458
491
|
const interpolate = (val, component = 'component.') => {
|
|
459
492
|
if (val === undefined) return val
|
|
460
493
|
const replaceString = /('.*?')+/gi
|
|
461
|
-
const replaceDollar =
|
|
494
|
+
const replaceDollar = /\$(\$(?=\$)|\$?)/g
|
|
462
495
|
const matches = val.matchAll(replaceString)
|
|
463
496
|
const restore = []
|
|
464
497
|
|
|
@@ -471,10 +504,19 @@ const interpolate = (val, component = 'component.') => {
|
|
|
471
504
|
i++
|
|
472
505
|
}
|
|
473
506
|
|
|
474
|
-
// replace
|
|
475
|
-
val = val.replace(replaceDollar,
|
|
507
|
+
// replace dollar signs using the regex and function
|
|
508
|
+
val = val.replace(replaceDollar, (match, group1) => {
|
|
509
|
+
// single dollar sign
|
|
510
|
+
if (group1 === '') {
|
|
511
|
+
return component
|
|
512
|
+
}
|
|
513
|
+
// consecutive dollar sign, replace only the first $
|
|
514
|
+
else if (group1 === '$') {
|
|
515
|
+
return component + '$'
|
|
516
|
+
}
|
|
517
|
+
})
|
|
476
518
|
|
|
477
|
-
// restore string
|
|
519
|
+
// restore string replacement
|
|
478
520
|
restore.forEach((el, idx) => {
|
|
479
521
|
val = val.replace(`[@@REPLACEMENT${idx}@@]`, el)
|
|
480
522
|
})
|
|
@@ -483,6 +525,7 @@ const interpolate = (val, component = 'component.') => {
|
|
|
483
525
|
}
|
|
484
526
|
|
|
485
527
|
const cast = (val = '', key = false, component = 'component.') => {
|
|
528
|
+
const dynamicArgumentRegex = /\$\w+/gi
|
|
486
529
|
let castedValue
|
|
487
530
|
|
|
488
531
|
// inline content
|
|
@@ -533,6 +576,21 @@ const cast = (val = '', key = false, component = 'component.') => {
|
|
|
533
576
|
else if (val.startsWith('$')) {
|
|
534
577
|
castedValue = `${component}${val.replace('$', '')}`
|
|
535
578
|
}
|
|
579
|
+
// dynamic value in object
|
|
580
|
+
else if (dynamicArgumentRegex.exec(val)) {
|
|
581
|
+
const rex = /\w+\s*:\s*(?:[^\s,}]+|".*?"|'.*?')/g
|
|
582
|
+
const results = val.match(rex)
|
|
583
|
+
castedValue = {}
|
|
584
|
+
if (results) {
|
|
585
|
+
for (let i = 0; i < results.length; i++) {
|
|
586
|
+
const members = results[i].split(/\s*:\s*/)
|
|
587
|
+
if (members) {
|
|
588
|
+
populateFields(members[0], members[1], component, castedValue)
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
return interpolateObject(castedValue)
|
|
593
|
+
}
|
|
536
594
|
// static string
|
|
537
595
|
else {
|
|
538
596
|
castedValue = `"${val}"`
|
|
@@ -554,3 +612,21 @@ const parseInlineContent = (val, component) => {
|
|
|
554
612
|
}
|
|
555
613
|
return val
|
|
556
614
|
}
|
|
615
|
+
|
|
616
|
+
// Populate value into target's prop
|
|
617
|
+
const populateFields = (prop, val, component, target) => {
|
|
618
|
+
if (val.startsWith('$')) {
|
|
619
|
+
target[prop] = `${component}${val.replace('$', '')}`
|
|
620
|
+
} else {
|
|
621
|
+
target[prop] = val
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
const interpolateObject = (input) => {
|
|
626
|
+
const interpolatedResults = []
|
|
627
|
+
Object.keys(input).forEach((key) => {
|
|
628
|
+
interpolatedResults.push(`${key}: ${input[key]}`)
|
|
629
|
+
})
|
|
630
|
+
|
|
631
|
+
return ` { ${interpolatedResults.join(', ')} }`
|
|
632
|
+
}
|
|
@@ -684,6 +684,138 @@ test('Generate code for a template with dynamic attributes with code to be evalu
|
|
|
684
684
|
assert.end()
|
|
685
685
|
})
|
|
686
686
|
|
|
687
|
+
test('Generate code for a template with attribute (object)', (assert) => {
|
|
688
|
+
const templateObject = {
|
|
689
|
+
children: [
|
|
690
|
+
{
|
|
691
|
+
[Symbol.for('componentType')]: 'Element',
|
|
692
|
+
w: '100',
|
|
693
|
+
h: '100',
|
|
694
|
+
color: '{top: 0xff0000ff, bottom: 0x008000ff, left: 0xffff00ff }',
|
|
695
|
+
},
|
|
696
|
+
],
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
const expectedRender = `
|
|
700
|
+
function anonymous(parent,component,context,components,effect,getRaw) {
|
|
701
|
+
const elms = []
|
|
702
|
+
let componentType
|
|
703
|
+
const rootComponent = component
|
|
704
|
+
const elementConfig0 = {}
|
|
705
|
+
|
|
706
|
+
elms[0] = this.element({parent: parent || 'root'}, component)
|
|
707
|
+
elementConfig0['w'] = 100
|
|
708
|
+
elementConfig0['h'] = 100
|
|
709
|
+
elementConfig0['color'] = "{top: 0xff0000ff, bottom: 0x008000ff, left: 0xffff00ff}"
|
|
710
|
+
elms[0].populate(elementConfig0)
|
|
711
|
+
|
|
712
|
+
return elms
|
|
713
|
+
}
|
|
714
|
+
`
|
|
715
|
+
|
|
716
|
+
const actual = generator.call(scope, templateObject)
|
|
717
|
+
console.log(actual.render.toString())
|
|
718
|
+
assert.equal(
|
|
719
|
+
normalize(actual.render.toString()),
|
|
720
|
+
normalize(expectedRender),
|
|
721
|
+
'Generator should return a render function with the correct code'
|
|
722
|
+
)
|
|
723
|
+
assert.ok(
|
|
724
|
+
Array.isArray(actual.effects) && actual.effects.length === 0,
|
|
725
|
+
'Generator should return an empty effects array'
|
|
726
|
+
)
|
|
727
|
+
|
|
728
|
+
assert.end()
|
|
729
|
+
})
|
|
730
|
+
|
|
731
|
+
test('Generate code for a template with dynamic attribute (object)', (assert) => {
|
|
732
|
+
const templateObject = {
|
|
733
|
+
children: [
|
|
734
|
+
{
|
|
735
|
+
[Symbol.for('componentType')]: 'Element',
|
|
736
|
+
w: '100',
|
|
737
|
+
h: '100',
|
|
738
|
+
color: '{top: $colorT, bottom: $colorB, left:$colorL}',
|
|
739
|
+
},
|
|
740
|
+
],
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
const expectedRender = `
|
|
744
|
+
function anonymous(parent,component,context,components,effect,getRaw) {
|
|
745
|
+
const elms = []
|
|
746
|
+
let componentType
|
|
747
|
+
const rootComponent = component
|
|
748
|
+
const elementConfig0 = {}
|
|
749
|
+
|
|
750
|
+
elms[0] = this.element({parent: parent || 'root'}, component)
|
|
751
|
+
elementConfig0['w'] = 100
|
|
752
|
+
elementConfig0['h'] = 100
|
|
753
|
+
elementConfig0['color'] = { top: component.colorT, bottom: component.colorB, left: component.colorL }
|
|
754
|
+
elms[0].populate(elementConfig0)
|
|
755
|
+
|
|
756
|
+
return elms
|
|
757
|
+
}
|
|
758
|
+
`
|
|
759
|
+
|
|
760
|
+
const actual = generator.call(scope, templateObject)
|
|
761
|
+
|
|
762
|
+
assert.equal(
|
|
763
|
+
normalize(actual.render.toString()),
|
|
764
|
+
normalize(expectedRender),
|
|
765
|
+
'Generator should return a render function with the correct code'
|
|
766
|
+
)
|
|
767
|
+
assert.ok(
|
|
768
|
+
Array.isArray(actual.effects) && actual.effects.length === 0,
|
|
769
|
+
'Generator should return an empty effects array'
|
|
770
|
+
)
|
|
771
|
+
|
|
772
|
+
assert.end()
|
|
773
|
+
})
|
|
774
|
+
|
|
775
|
+
test('Generate code for a template with attribute (object) with mixed dynamic & static value', (assert) => {
|
|
776
|
+
const templateObject = {
|
|
777
|
+
children: [
|
|
778
|
+
{
|
|
779
|
+
[Symbol.for('componentType')]: 'Element',
|
|
780
|
+
w: '100',
|
|
781
|
+
h: '100',
|
|
782
|
+
color: '{top: 0xff0000ff, bottom: $colorB, left: $colorL}',
|
|
783
|
+
},
|
|
784
|
+
],
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
const expectedRender = `
|
|
788
|
+
function anonymous(parent,component,context,components,effect,getRaw) {
|
|
789
|
+
const elms = []
|
|
790
|
+
let componentType
|
|
791
|
+
const rootComponent = component
|
|
792
|
+
const elementConfig0 = {}
|
|
793
|
+
|
|
794
|
+
elms[0] = this.element({parent: parent || 'root'}, component)
|
|
795
|
+
elementConfig0['w'] = 100
|
|
796
|
+
elementConfig0['h'] = 100
|
|
797
|
+
elementConfig0['color'] = { top: 0xff0000ff, bottom: component.colorB, left: component.colorL }
|
|
798
|
+
elms[0].populate(elementConfig0)
|
|
799
|
+
|
|
800
|
+
return elms
|
|
801
|
+
}
|
|
802
|
+
`
|
|
803
|
+
|
|
804
|
+
const actual = generator.call(scope, templateObject)
|
|
805
|
+
|
|
806
|
+
assert.equal(
|
|
807
|
+
normalize(actual.render.toString()),
|
|
808
|
+
normalize(expectedRender),
|
|
809
|
+
'Generator should return a render function with the correct code'
|
|
810
|
+
)
|
|
811
|
+
assert.ok(
|
|
812
|
+
Array.isArray(actual.effects) && actual.effects.length === 0,
|
|
813
|
+
'Generator should return an empty effects array'
|
|
814
|
+
)
|
|
815
|
+
|
|
816
|
+
assert.end()
|
|
817
|
+
})
|
|
818
|
+
|
|
687
819
|
test('Generate code for a template with @-listeners', (assert) => {
|
|
688
820
|
const templateObject = {
|
|
689
821
|
children: [
|
|
@@ -2290,3 +2422,55 @@ test('Generate code for a template with a simple for-loop on an Element with an
|
|
|
2290
2422
|
|
|
2291
2423
|
assert.end()
|
|
2292
2424
|
})
|
|
2425
|
+
|
|
2426
|
+
test('Generate code for a template with double $$ (i.e. referencing a Blits plugin)', (assert) => {
|
|
2427
|
+
const templateObject = {
|
|
2428
|
+
children: [
|
|
2429
|
+
{
|
|
2430
|
+
[Symbol.for('componentType')]: 'Text',
|
|
2431
|
+
':content': "$$language.translate('hello')",
|
|
2432
|
+
},
|
|
2433
|
+
],
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
const expectedRender = `
|
|
2437
|
+
function anonymous(parent, component, context, components, effect, getRaw) {
|
|
2438
|
+
const elms = []
|
|
2439
|
+
let componentType
|
|
2440
|
+
const rootComponent = component
|
|
2441
|
+
const elementConfig0 = {}
|
|
2442
|
+
|
|
2443
|
+
elms[0] = this.element({ parent: parent || 'root' }, component)
|
|
2444
|
+
elementConfig0['content'] = component.$language.translate('hello')
|
|
2445
|
+
elementConfig0['__textnode'] = true
|
|
2446
|
+
elms[0].populate(elementConfig0)
|
|
2447
|
+
|
|
2448
|
+
return elms
|
|
2449
|
+
}
|
|
2450
|
+
`
|
|
2451
|
+
|
|
2452
|
+
const expectedEffect1 = `
|
|
2453
|
+
function anonymous(component, elms, context, components, rootComponent, effect) {
|
|
2454
|
+
elms[0].set('content', component.$language.translate('hello'))
|
|
2455
|
+
}
|
|
2456
|
+
`
|
|
2457
|
+
|
|
2458
|
+
const actual = generator.call(scope, templateObject)
|
|
2459
|
+
|
|
2460
|
+
assert.equal(
|
|
2461
|
+
normalize(actual.render.toString()),
|
|
2462
|
+
normalize(expectedRender),
|
|
2463
|
+
'Generator should return a render function with the correct code'
|
|
2464
|
+
)
|
|
2465
|
+
assert.ok(
|
|
2466
|
+
Array.isArray(actual.effects) && actual.effects.length === 1,
|
|
2467
|
+
'Generator should return an effects array with 1 item'
|
|
2468
|
+
)
|
|
2469
|
+
assert.equal(
|
|
2470
|
+
normalize(actual.effects[0].toString()),
|
|
2471
|
+
normalize(expectedEffect1),
|
|
2472
|
+
'Generator should return first render function with the correct code'
|
|
2473
|
+
)
|
|
2474
|
+
|
|
2475
|
+
assert.end()
|
|
2476
|
+
})
|
package/src/lib/colors/colors.js
CHANGED
|
@@ -39,17 +39,16 @@ export default {
|
|
|
39
39
|
normalize: (color = '', defaultColor = '0xffffffff') => {
|
|
40
40
|
color = color.toString()
|
|
41
41
|
|
|
42
|
-
//
|
|
43
|
-
if (colorsMap[color] !== undefined) {
|
|
44
|
-
return colorsMap[color]
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// its a 0xRRGGBBAA color, store it and return it
|
|
42
|
+
// it is a 0xRRGGBBAA color, return it
|
|
48
43
|
if (color.startsWith('0x') && color.length === 10) {
|
|
49
|
-
colorsMap[color] = color
|
|
50
44
|
return color
|
|
51
45
|
}
|
|
52
46
|
|
|
47
|
+
// it is a previously mapped color, return it
|
|
48
|
+
if (colorsMap[color] !== undefined) {
|
|
49
|
+
return colorsMap[color]
|
|
50
|
+
}
|
|
51
|
+
|
|
53
52
|
// check for hex color
|
|
54
53
|
if (hex.test(color)) {
|
|
55
54
|
color = color.replace('#', '').toLowerCase()
|
|
@@ -30,11 +30,9 @@ export const getRaw = (value) => {
|
|
|
30
30
|
const reactiveProxy = (original, _parent = null, _key) => {
|
|
31
31
|
// don't create a proxy when a Blits component or an Image Texture
|
|
32
32
|
// is assigned to a state variable
|
|
33
|
-
if (
|
|
34
|
-
(
|
|
35
|
-
original.constructor.name === '_ImageTexture'
|
|
36
|
-
) {
|
|
37
|
-
return original
|
|
33
|
+
if (typeof original === 'object') {
|
|
34
|
+
if (original[symbols.id] !== undefined) return original
|
|
35
|
+
if (original.constructor.name === '_ImageTexture') return original
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
// if original object is already a proxy, don't create a new one but return the existing one instead
|
package/src/lib/symbols.js
CHANGED
|
@@ -28,7 +28,7 @@ export default (template = '', componentName, parentComponent, filePath = null)
|
|
|
28
28
|
// regular expressions
|
|
29
29
|
const tagStartRegex = /^<\/?([a-zA-Z0-9_\-.]+)\s*/
|
|
30
30
|
const tagEndRegex = /^\s*(\/?>)\s*/
|
|
31
|
-
const attrNameRegex = /^([A-Za-z0-9:.\-_
|
|
31
|
+
const attrNameRegex = /^([A-Za-z0-9:.\-_@$]+)=\s*(["'])/
|
|
32
32
|
const emptyTagStartRegex = /^<>\s*/
|
|
33
33
|
const emptyTagEndRegex = /^\s*(<\/>)\s*/
|
|
34
34
|
|
package/src/plugin.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2024 Comcast Cable Communications Management, LLC
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
declare namespace Plugin {
|
|
20
|
+
|
|
21
|
+
interface Plugin {
|
|
22
|
+
/**
|
|
23
|
+
* Name of the plugin. The plugin will be accessible on each Component's
|
|
24
|
+
* `this` scope under this name, prefixed with a `$` (i.e. myplugin => `this.$myplugin`)
|
|
25
|
+
*/
|
|
26
|
+
name: string,
|
|
27
|
+
/**
|
|
28
|
+
* Singleton function that will be used to instantiate the plugin.
|
|
29
|
+
* Should do all necessary setup and ideally return an object with
|
|
30
|
+
* properties or methods that can be used in the App
|
|
31
|
+
*/
|
|
32
|
+
plugin: () => any
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Blits.Plugin()
|
|
40
|
+
*
|
|
41
|
+
* Method to register a plugin
|
|
42
|
+
*/
|
|
43
|
+
declare function Plugin(
|
|
44
|
+
/**
|
|
45
|
+
* Plugin object or singleton function that will be used to instantiate the
|
|
46
|
+
* plugin. Should do all necessary setup and ideally return an object with
|
|
47
|
+
* properties or methods that can be used in the App
|
|
48
|
+
*/
|
|
49
|
+
plugin: Plugin.Plugin | (() => any),
|
|
50
|
+
/**
|
|
51
|
+
* Name of the plugin or options object, to be passed into the plugin instantiation.
|
|
52
|
+
*
|
|
53
|
+
* When passing a string, the value will be used as **name** of the plugin. The plugin
|
|
54
|
+
* will be accessible on each Component's `this` scope under this name, prefixed with a `$`
|
|
55
|
+
* (i.e. myplugin => `this.$myplugin`)
|
|
56
|
+
*
|
|
57
|
+
* Passing a name is **required** when `plugin` argument is a singleton function
|
|
58
|
+
*
|
|
59
|
+
* When passing an object, the value will be considered to be an `options` object.
|
|
60
|
+
* The options object will be passed into the plugin instantiation method. Can
|
|
61
|
+
* be used to set default values
|
|
62
|
+
*/
|
|
63
|
+
nameOrOptions?: string | object,
|
|
64
|
+
/**
|
|
65
|
+
* Object with options to be passed into the plugin instantiation method.
|
|
66
|
+
* Can be used to set default values
|
|
67
|
+
*/
|
|
68
|
+
options?: object
|
|
69
|
+
) : void
|
|
70
|
+
|
|
71
|
+
export default Plugin;
|
package/src/plugin.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const plugins = {}
|
|
2
|
+
|
|
3
|
+
const registerPlugin = (plugin, nameOrOptions = '', options = {}) => {
|
|
4
|
+
// map name and options depending on the arguments provided
|
|
5
|
+
let name
|
|
6
|
+
if (typeof nameOrOptions === 'object') {
|
|
7
|
+
options = nameOrOptions
|
|
8
|
+
name = ''
|
|
9
|
+
} else {
|
|
10
|
+
name = nameOrOptions
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (typeof plugin === 'function') {
|
|
14
|
+
if (name === '') {
|
|
15
|
+
throw Error('Error registering plugin: name is required for plugin')
|
|
16
|
+
}
|
|
17
|
+
plugins[name] = { plugin, options }
|
|
18
|
+
} else if (plugin.plugin) {
|
|
19
|
+
registerPlugin(plugin.plugin, plugin.name, options)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default registerPlugin
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright
|
|
2
|
+
* Copyright 2024 Comcast Cable Communications Management, LLC
|
|
3
3
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
* you may not use this file except in compliance with the License.
|
|
5
5
|
* You may obtain a copy of the License at
|
|
@@ -15,19 +15,4 @@
|
|
|
15
15
|
* SPDX-License-Identifier: Apache-2.0
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
export default () =>
|
|
21
|
-
Component('Image', {
|
|
22
|
-
template: `
|
|
23
|
-
<Element :imageSource="$imageSource" />`,
|
|
24
|
-
props: ['src'],
|
|
25
|
-
computed: {
|
|
26
|
-
imageSource() {
|
|
27
|
-
if (/^(?:https?:)?\/\//i.test(this.src)) {
|
|
28
|
-
return this.src
|
|
29
|
-
}
|
|
30
|
-
return `${window.location.protocol}//${window.location.host}/${this.src}`
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
})
|
|
18
|
+
export { default as language } from './language.js'
|