@lightningjs/blits 1.32.1 → 1.34.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.
@@ -27,28 +27,50 @@ export default () =>
27
27
  code: {
28
28
  render: function anonymous(parent, component, context, components, effect, getRaw, Log) {
29
29
  const elms = []
30
+ const elementConfigs = []
31
+ const forloops = []
32
+ const props = []
33
+ const created = []
34
+ const skips = []
30
35
  let componentType
31
- const rootComponent = component
36
+ let rootComponent = component
32
37
  let propData
33
38
  let slotComponent
34
39
  let inSlot = false
35
40
  let slotChildCounter = 0
36
- const elementConfig0 = {}
41
+ let cmps = []
42
+ elementConfigs[0] = {}
37
43
 
38
44
  elms[0] = this.element(
39
45
  { parent: parent || 'root' },
40
46
  inSlot === true ? slotComponent : component
41
47
  )
42
48
 
43
- elementConfig0['w'] = parent.node.width * (100 / 100)
44
- elementConfig0['height'] = parent.node.height * (100 / 100)
45
- elms[0].populate(elementConfig0)
49
+ elementConfigs[0]['w'] = parent.node.width * (100 / 100)
50
+ elementConfigs[0]['height'] = parent.node.height * (100 / 100)
51
+ elms[0].populate(elementConfigs[0])
46
52
 
47
53
  if (inSlot === true) {
48
54
  slotChildCounter -= 1
49
55
  }
50
56
 
51
- return elms
57
+ return {
58
+ elms,
59
+ cleanup: () => {
60
+ rootComponent = null
61
+ propData = null
62
+ slotComponent = null
63
+ component = null
64
+ parent = null
65
+ cmps.length = 0
66
+ elms.length = 0
67
+ components.length = 0
68
+ elementConfigs.length = 0
69
+ forloops.length = 0
70
+ props.length = 0
71
+ skips.length = 0
72
+ },
73
+ }
52
74
  },
53
75
  effects: [],
54
76
  context: {},
@@ -25,30 +25,52 @@ export default () =>
25
25
  code: {
26
26
  render: function anonymous(parent, component, context, components, effect, getRaw, Log) {
27
27
  const elms = []
28
+ const elementConfigs = []
29
+ const forloops = []
30
+ const props = []
31
+ const created = []
32
+ const skips = []
28
33
  let componentType
29
- const rootComponent = component
34
+ let rootComponent = component
30
35
  let propData
31
36
  let slotComponent
32
37
  let inSlot = false
33
38
  let slotChildCounter = 0
34
- const elementConfig0 = {}
39
+ let cmps = []
40
+ elementConfigs[0] = {}
35
41
 
36
42
  elms[0] = this.element(
37
43
  { parent: parent || 'root' },
38
44
  inSlot === true ? slotComponent : component
39
45
  )
40
46
 
41
- elementConfig0['w'] = parent.node.width * (100 / 100)
42
- elementConfig0['h'] = parent.node.height * (100 / 100)
43
- elementConfig0['texture'] = component.texture
44
- elementConfig0['color'] = component.color
45
- elms[0].populate(elementConfig0)
47
+ elementConfigs[0]['w'] = parent.node.width * (100 / 100)
48
+ elementConfigs[0]['h'] = parent.node.height * (100 / 100)
49
+ elementConfigs[0]['texture'] = component.texture
50
+ elementConfigs[0]['color'] = component.color
51
+ elms[0].populate(elementConfigs[0])
46
52
 
47
53
  if (inSlot === true) {
48
54
  slotChildCounter -= 1
49
55
  }
50
56
 
51
- return elms
57
+ return {
58
+ elms,
59
+ cleanup: () => {
60
+ rootComponent = null
61
+ propData = null
62
+ slotComponent = null
63
+ component = null
64
+ parent = null
65
+ cmps.length = 0
66
+ elms.length = 0
67
+ components.length = 0
68
+ elementConfigs.length = 0
69
+ forloops.length = 0
70
+ props.length = 0
71
+ skips.length = 0
72
+ },
73
+ }
52
74
  },
53
75
  effects: [
54
76
  function anonymous(component, elms, context, components, rootComponent, effect) {
@@ -26,8 +26,8 @@ import colors from '../../lib/colors/colors.js'
26
26
  import fontLoader from './fontLoader.js'
27
27
  import shaderLoader from './shaderLoader.js'
28
28
 
29
- /** @type {RendererMain|null} */
30
- export let renderer = null
29
+ /** @type {RendererMain|{}} */
30
+ export let renderer = {}
31
31
 
32
32
  const renderEngine = (settings) => {
33
33
  const renderMode = 'renderMode' in settings ? settings.renderMode : 'webgl'
@@ -99,6 +99,7 @@ export default (App, target, settings = {}) => {
99
99
  textureProcessingTimeLimit: settings.textureProcessingTimeLimit,
100
100
  textureMemory: textureMemorySettings(settings),
101
101
  createImageBitmapSupport: 'auto',
102
+ targetFPS: 'maxFPS' in settings ? settings.maxFPS : 0,
102
103
  },
103
104
  ...(settings.advanced || {}),
104
105
  },
package/src/launch.js CHANGED
@@ -89,6 +89,7 @@ async function rendererVersion() {
89
89
  * @property {number} [textureProcessingTimeLimit] - Max time renderer can process textures in a frame
90
90
  * @property {Partial<import('@lightningjs/renderer').RendererMainSettings>} [advanced] - Advanced renderer settings
91
91
  * @property {boolean} [announcer] - Whether or not the announcer should be activated on initialization
92
+ * @property {number} [maxFPS] - Maximum FPS
92
93
  */
93
94
 
94
95
  /**
@@ -22,14 +22,27 @@ export default function (templateObject = { children: [] }, devMode = false) {
22
22
  const ctx = {
23
23
  renderCode: [
24
24
  'const elms = []',
25
+ 'const elementConfigs = []',
26
+ 'const forloops = []',
27
+ 'const props = []',
28
+ 'const created = []',
29
+ 'const skips = []',
25
30
  'let componentType',
26
- 'const rootComponent = component',
31
+ 'let rootComponent = component',
27
32
  'let propData',
28
33
  'let slotComponent',
29
34
  'let inSlot = false',
30
35
  'let slotChildCounter = 0',
36
+ 'let cmps = []',
31
37
  ],
32
38
  effectsCode: [],
39
+ cleanupCode: [
40
+ 'rootComponent = null',
41
+ 'propData = null',
42
+ 'slotComponent = null',
43
+ 'component = null',
44
+ 'parent = null',
45
+ ],
33
46
  context: { props: [], components: this.components },
34
47
  }
35
48
 
@@ -57,7 +70,18 @@ export default function (templateObject = { children: [] }, devMode = false) {
57
70
  `)
58
71
  }
59
72
  generateCode.call(ctx, templateObject)
60
- ctx.renderCode.push('return elms')
73
+ ctx.renderCode.push(`
74
+ return { elms, cleanup: () => {
75
+ ${ctx.cleanupCode.join('\n')}
76
+ cmps.length = 0
77
+ elms.length = 0
78
+ components.length = 0
79
+ elementConfigs.length = 0
80
+ forloops.length = 0
81
+ props.length = 0
82
+ skips.length = 0
83
+ }}
84
+ `)
61
85
 
62
86
  return {
63
87
  render: new Function(
@@ -124,7 +148,7 @@ const generateElementCode = function (
124
148
  `)
125
149
  }
126
150
 
127
- renderCode.push(`const elementConfig${counter} = {}`)
151
+ renderCode.push(`elementConfigs[${counter}] = {}`)
128
152
 
129
153
  if (options.forloop) {
130
154
  renderCode.push(`if(${elm} === undefined) {`)
@@ -142,13 +166,13 @@ const generateElementCode = function (
142
166
  delete templateObject['children']
143
167
 
144
168
  if (templateObject[Symbol.for('componentType')] === 'Slot') {
145
- renderCode.push(`elementConfig${counter}[Symbol.for('isSlot')] = true`)
169
+ renderCode.push(`elementConfigs[${counter}][Symbol.for('isSlot')] = true`)
146
170
  }
147
171
 
148
172
  Object.keys(templateObject).forEach((key) => {
149
173
  if (key === 'slot') {
150
174
  renderCode.push(`
151
- elementConfig${counter}['parent'] = slotComponent[Symbol.for('slots')] !== undefined && Array.isArray(slotComponent[Symbol.for('slots')]) === true && slotComponent[Symbol.for('slots')].filter(slot => slot.ref === '${templateObject.slot}').shift() || parent
175
+ elementConfigs[${counter}]['parent'] = slotComponent[Symbol.for('slots')] !== undefined && Array.isArray(slotComponent[Symbol.for('slots')]) === true && slotComponent[Symbol.for('slots')].filter(slot => slot.ref === '${templateObject.slot}').shift() || parent
152
176
  `)
153
177
  }
154
178
 
@@ -160,8 +184,8 @@ const generateElementCode = function (
160
184
  if (options.holder && key === ':color') return
161
185
  if (options.holder) {
162
186
  this.effectsCode.push(`
163
- if(typeof skip${counter} === 'undefined' ||
164
- skip${counter}.indexOf('${key.substring(1)}') === -1)
187
+ if(typeof skips === 'undefined' || (typeof skips[${counter}] === 'undefined' ||
188
+ skips[${counter}].indexOf('${key.substring(1)}') === -1))
165
189
  ${elm}.set('${key.substring(1)}', ${interpolate(templateObject[key], options.component)})
166
190
  `)
167
191
  } else {
@@ -177,23 +201,28 @@ const generateElementCode = function (
177
201
  verifyVariables(value, renderCode, 'reactive')
178
202
  }
179
203
  renderCode.push(
180
- `elementConfig${counter}['${key.substring(1)}'] = ${interpolate(value, options.component)}`
204
+ `elementConfigs[${counter}]['${key.substring(1)}'] = ${interpolate(
205
+ value,
206
+ options.component
207
+ )}`
181
208
  )
182
209
  } else {
183
210
  if (isDev === true && options.component !== 'scope.' && value.includes('$')) {
184
211
  verifyVariables(value, renderCode)
185
212
  }
186
- renderCode.push(`elementConfig${counter}['${key}'] = ${cast(value, key, options.component)}`)
213
+ renderCode.push(
214
+ `elementConfigs[${counter}]['${key}'] = ${cast(value, key, options.component)}`
215
+ )
187
216
  }
188
217
  })
189
218
 
190
219
  if (options.holder === true) {
191
220
  renderCode.push(`
192
- const skip${counter} = []
193
- if(typeof cmp${counter} !== 'undefined') {
194
- for(let key in cmp${counter}[Symbol.for('config')].props) {
195
- delete elementConfig${counter}[cmp${counter}[Symbol.for('config')].props[key]]
196
- skip${counter}.push(cmp${counter}[Symbol.for('config')].props[key])
221
+ skips[${counter}] = []
222
+ if(typeof cmps[${counter}] !== 'undefined') {
223
+ for(let key in cmps[${counter}][Symbol.for('config')].props) {
224
+ delete elementConfigs[${counter}][cmps[${counter}][Symbol.for('config')].props[key]]
225
+ skips[${counter}].push(cmps[${counter}][Symbol.for('config')].props[key])
197
226
  }
198
227
  }
199
228
  `)
@@ -203,7 +232,7 @@ const generateElementCode = function (
203
232
  renderCode.push(`if(${elm}.nodeId === undefined) {`)
204
233
  }
205
234
 
206
- renderCode.push(`${elm}.populate(elementConfig${counter})`)
235
+ renderCode.push(`${elm}.populate(elementConfigs[${counter}])`)
207
236
 
208
237
  renderCode.push(`
209
238
  if(inSlot === true) {
@@ -234,12 +263,16 @@ const generateComponentCode = function (
234
263
  const renderCode = options.forceEffect ? this.effectsCode : this.renderCode
235
264
 
236
265
  renderCode.push(`
237
- const cmp${counter} =
266
+ cmps[${counter}] =
238
267
  (context.components && context.components['${
239
268
  templateObject[Symbol.for('componentType')]
240
269
  }']) || components['${templateObject[Symbol.for('componentType')]}']
241
270
  `)
242
271
 
272
+ this.cleanupCode.push(`
273
+ cmps[${counter}] = null
274
+ `)
275
+
243
276
  if ('key' in templateObject) {
244
277
  options.key = interpolate(templateObject.key, options.component)
245
278
  }
@@ -263,10 +296,11 @@ const generateComponentCode = function (
263
296
  }
264
297
 
265
298
  if (parent) {
266
- renderCode.push(`parent = ${parent}`)
299
+ renderCode.push(`parent = ${parent};`)
267
300
  }
268
301
 
269
- renderCode.push(`const props${counter} = {}`)
302
+ renderCode.push(`props[${counter}] = {}`)
303
+ this.cleanupCode.push(`props[${counter}] = null`)
270
304
 
271
305
  if (options.forloop) {
272
306
  renderCode.push(`if(${elm} === undefined) {`)
@@ -284,28 +318,28 @@ const generateComponentCode = function (
284
318
  if (Array.isArray(propData) === true) {
285
319
  propData = getRaw(propData).slice(0)
286
320
  }
287
- props${counter}['${key.substring(1)}'] = propData`)
321
+ props[${counter}]['${key.substring(1)}'] = propData`)
288
322
  } else {
289
323
  renderCode.push(
290
- `props${counter}['${key}'] = ${cast(templateObject[key], key, options.component)}`
324
+ `props[${counter}]['${key}'] = ${cast(templateObject[key], key, options.component)}`
291
325
  )
292
326
  }
293
327
  })
294
328
 
295
329
  renderCode.push(`
296
- componentType = props${counter}['is'] || '${templateObject[Symbol.for('componentType')]}'
330
+ componentType = props[${counter}]['is'] || '${templateObject[Symbol.for('componentType')]}'
297
331
 
298
- let component${counter}
332
+ components[${counter}]
299
333
  if(typeof componentType === 'string') {
300
- component${counter} = context.components && context.components[componentType] || components[componentType]
301
- if(!component${counter}) {
334
+ components[${counter}] = context.components && context.components[componentType] || components[componentType]
335
+ if(!components[${counter}]) {
302
336
  throw new Error('Component "${templateObject[Symbol.for('componentType')]}" not found')
303
337
  }
304
338
  } else if(typeof componentType === 'function' && componentType[Symbol.for('isComponent')] === true) {
305
- component${counter} = componentType
339
+ components[${counter}] = componentType
306
340
  }
307
341
 
308
- ${elm} = component${counter}.call(null, {props: props${counter}}, ${parent}, component)
342
+ ${elm} = components[${counter}].call(null, {props: props[${counter}]}, ${parent}, component)
309
343
 
310
344
  if (${elm}[Symbol.for('slots')][0]) {
311
345
  parent = ${elm}[Symbol.for('slots')][0]
@@ -316,6 +350,8 @@ const generateComponentCode = function (
316
350
  }
317
351
  `)
318
352
 
353
+ this.cleanupCode.push(`components[${counter}] = null`)
354
+
319
355
  if (options.forloop) {
320
356
  renderCode.push('}')
321
357
  }
@@ -374,6 +410,7 @@ const generateForLoopCode = function (templateObject, parent) {
374
410
  const ctx = {
375
411
  renderCode: [],
376
412
  effectsCode: [],
413
+ cleanupCode: [],
377
414
  context: { props: [], components: this.components },
378
415
  }
379
416
 
@@ -395,12 +432,12 @@ const generateForLoopCode = function (templateObject, parent) {
395
432
  const forStartCounter = counter
396
433
 
397
434
  ctx.renderCode.push(`
398
- const created${forStartCounter} = []
435
+ created[${forStartCounter}] = []
399
436
 
400
437
  let from${forStartCounter}
401
438
  let to${forStartCounter}
402
439
 
403
- const forloop${forStartCounter} = (collection = [], elms, created) => {
440
+ forloops[${forStartCounter}] = (collection = [], elms, created) => {
404
441
  const rawCollection = getRaw(collection)
405
442
  const keys = new Set()
406
443
  let l = rawCollection.length
@@ -412,6 +449,12 @@ const generateForLoopCode = function (templateObject, parent) {
412
449
  while(l--) {
413
450
  const ${item} = rawCollection[l]
414
451
  `)
452
+
453
+ ctx.cleanupCode.push(`
454
+ created[${forStartCounter}].length = 0
455
+ forloops[${forStartCounter}] = null
456
+ `)
457
+
415
458
  // push reference of index variable
416
459
  if (index !== undefined) {
417
460
  ctx.renderCode.push(`
@@ -538,9 +581,10 @@ const generateForLoopCode = function (templateObject, parent) {
538
581
 
539
582
  for (let i = forStartCounter; i <= forEndCounter; i++) {
540
583
  destroyCode.push(`
541
- elms[${i}][key] && elms[${i}][key].destroy()
542
- delete elms[${i}][key]
543
- `)
584
+ elms[${i}][key] && elms[${i}][key].destroy()
585
+ elms[${i}][key] = null
586
+ delete elms[${i}][key]
587
+ `)
544
588
  }
545
589
  destroyCode.push(`
546
590
  }
@@ -562,14 +606,8 @@ const generateForLoopCode = function (templateObject, parent) {
562
606
  const effectKeys = [...range.matchAll(effectKeysRegex)].map((match) => `'${match[1]}'`)
563
607
 
564
608
  ctx.renderCode.push(`
565
- let forEffects${forStartCounter}
566
- const eff${forStartCounter} = () => {
567
- component[Symbol.for('removeGlobalEffects')](forEffects${forStartCounter})
568
- forEffects${forStartCounter} = null
569
- forEffects${forStartCounter} = forloop${forStartCounter}(${cast(
570
- result[2],
571
- ':for'
572
- )}, elms, created${forStartCounter})
609
+ let eff${forStartCounter} = () => {
610
+ forloops[${forStartCounter}](${cast(result[2], ':for')}, elms, created[${forStartCounter}])
573
611
  }
574
612
 
575
613
  component[Symbol.for('effects')].push(eff${forStartCounter})
@@ -577,6 +615,10 @@ const generateForLoopCode = function (templateObject, parent) {
577
615
  effect(eff${forStartCounter}, ['${effectKey}', ${effectKeys.join(',')}] )
578
616
  `)
579
617
 
618
+ ctx.cleanupCode.push(`
619
+ eff${forStartCounter} = null
620
+ `)
621
+
580
622
  outerScopeEffects.forEach((effect, outerScopeEffectsIndex) => {
581
623
  const matches = [...effect.matchAll(scopeRegex)]
582
624
 
@@ -594,7 +636,7 @@ const generateForLoopCode = function (templateObject, parent) {
594
636
  }
595
637
 
596
638
  ctx.renderCode.push(`
597
- const eff${forStartCounter}_${outerScopeEffectsIndex} = () => {
639
+ let eff${forStartCounter}_${outerScopeEffectsIndex} = () => {
598
640
  void ${refs.join(', ')}
599
641
  for(let __index = 0; __index < ${interpolate(result[2])}.length; __index++) {
600
642
  if(__index < from${forStartCounter} || __index >= to${forStartCounter}) continue
@@ -603,6 +645,7 @@ const generateForLoopCode = function (templateObject, parent) {
603
645
  scope['${item}'] = ${interpolate(result[2])}[__index]
604
646
  scope['key'] = ${forKey || '__index'}
605
647
  `)
648
+ ctx.cleanupCode.push(`eff${forStartCounter}_${outerScopeEffectsIndex} = null`)
606
649
 
607
650
  ctx.renderCode.push(`
608
651
  ${effect}
@@ -614,6 +657,7 @@ const generateForLoopCode = function (templateObject, parent) {
614
657
  })
615
658
 
616
659
  this.renderCode.push(ctx.renderCode.join('\n'))
660
+ this.cleanupCode.push(ctx.cleanupCode.join('\n'))
617
661
  }
618
662
 
619
663
  const generateCode = function (templateObject, parent = false, options = {}) {
package/src/lib/log.js CHANGED
@@ -19,16 +19,16 @@ import Settings from '../settings.js'
19
19
 
20
20
  const n = () => {}
21
21
 
22
+ const pad = (n) => String(n).padStart(2, '0')
23
+
22
24
  /**
23
25
  * Returns the current time as a locale time string (hh:mm:ss).
24
26
  * @returns {string} The current time string.
25
27
  */
26
- const time = () =>
27
- new Date().toLocaleTimeString([], {
28
- hour: '2-digit',
29
- minute: '2-digit',
30
- second: '2-digit',
31
- })
28
+ const time = () => {
29
+ const now = new Date()
30
+ return pad(now.getHours()) + ':' + pad(now.getMinutes()) + ':' + pad(now.getSeconds())
31
+ }
32
32
 
33
33
  /**
34
34
  * Returns a logger object for the given context, with info, warn, debug, and error methods.
@@ -2,6 +2,7 @@
2
2
  * Symbol registry for internal framework properties and generated code.
3
3
  *
4
4
  * @typedef {Object} BlitsSymbols
5
+ * @property {symbol} cleanup
5
6
  * @property {symbol} currentView
6
7
  * @property {symbol} cursorTagStart
7
8
  * @property {symbol} computedKeys
@@ -52,6 +53,7 @@
52
53
  * @type {BlitsSymbols}
53
54
  */
54
55
  export default {
56
+ cleanup: Symbol('cleanup'),
55
57
  currentView: Symbol('currentView'),
56
58
  cursorTagStart: Symbol('cursorTagStart'),
57
59
  computedKeys: Symbol('computedKeys'),
@@ -18,3 +18,4 @@
18
18
  export { default as language } from './language.js'
19
19
  export { default as theme } from './theme.js'
20
20
  export { default as appState } from './appstate.js'
21
+ export { default as storage } from './storage/storage.js'
@@ -0,0 +1,133 @@
1
+ /*
2
+ * If not stated otherwise in this file or this component's LICENSE file the
3
+ * following copyright and licenses apply:
4
+ *
5
+ * Copyright 2019 Metrological
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the License);
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ // LocalStorage and Cookie storage library
21
+ class localCookie {
22
+ constructor(options) {
23
+ options = options || {}
24
+ this.forceCookies = options.forceCookies || false
25
+
26
+ if (this._checkIfLocalStorageWorks() === true && options.forceCookies !== true)
27
+ return {
28
+ getItem: this._getItemLocalStorage,
29
+ setItem: this._setItemLocalStorage,
30
+ removeItem: this._removeItemLocalStorage,
31
+ clear: this._clearLocalStorage,
32
+ keys: this._getLocalStorageKeys,
33
+ }
34
+ else
35
+ return {
36
+ getItem: this._getItemCookie,
37
+ setItem: this._setItemCookie,
38
+ removeItem: this._removeItemCookie,
39
+ clear: this._clearCookies,
40
+ keys: this._getCookieKeys,
41
+ }
42
+ }
43
+
44
+ // Checks if local storage is available and works
45
+ _checkIfLocalStorageWorks() {
46
+ if (typeof localStorage !== 'undefined') {
47
+ try {
48
+ localStorage.setItem('feature_test', 'yes')
49
+ if (localStorage.getItem('feature_test') === 'yes') {
50
+ localStorage.removeItem('feature_test')
51
+ // localStorage is enabled
52
+ return true
53
+ } else {
54
+ // localStorage is disabled
55
+ return false
56
+ }
57
+ } catch (e) {
58
+ // localStorage is disabled
59
+ return false
60
+ }
61
+ } else {
62
+ // localStorage is not available
63
+ return false
64
+ }
65
+ }
66
+
67
+ /*
68
+ * Local Storage APIs
69
+ */
70
+ _getItemLocalStorage(key) {
71
+ return window.localStorage.getItem(key)
72
+ }
73
+
74
+ _setItemLocalStorage(key, value) {
75
+ return window.localStorage.setItem(key, value)
76
+ }
77
+
78
+ _removeItemLocalStorage(key) {
79
+ return window.localStorage.removeItem(key)
80
+ }
81
+
82
+ _clearLocalStorage() {
83
+ return window.localStorage.clear()
84
+ }
85
+
86
+ _getLocalStorageKeys() {
87
+ return Object.keys(window.localStorage)
88
+ }
89
+
90
+ /*
91
+ * Cookie APIs
92
+ */
93
+ _getItemCookie(key) {
94
+ /* eslint-disable */
95
+ function escape(s) { return s.replace(/([.*+?\^${}()|\[\]\/\\])/g, '\\$1'); };
96
+ var match = document.cookie.match(RegExp('(?:^|;\\s*)' + escape(key) + '=([^;]*)'));
97
+
98
+ //if value in key of the entire cookie is empty, its deleted
99
+ if (match && match[1] === '')
100
+ match[1] = null
101
+
102
+ return match ? match[1] : null;
103
+ }
104
+
105
+ _setItemCookie(key, value) {
106
+ var now = new Date()
107
+ var expires = new Date(now.getTime() +1000*60*60*24*365*5) // 5 years!
108
+ document.cookie = `${key}=${value}; expires=${expires.toUTCString()};`
109
+ return //return undefined just like localStorage
110
+ }
111
+
112
+ _removeItemCookie(key) {
113
+ // to delete an k/v set the key to empty
114
+ document.cookie = `${key}=;Max-Age=-99999999;`
115
+ return //return undefined just like localStorage
116
+ }
117
+
118
+ _clearCookies() {
119
+ // empty all key/values in cookies
120
+ // What about cookies we got from the server? ¯\_(ツ)_/¯
121
+ // They should have the HttpOnly flag, so we shouldn't be able to delete them
122
+ document.cookie.split(";").forEach( (c) => {
123
+ document.cookie = c.replace(/^ +/, "").replace(/=.*/, "=;expires=Max-Age=-99999999");
124
+ });
125
+
126
+ return //return undefined
127
+ }
128
+ _getCookieKeys() {
129
+ return document.cookie.split(";").map((item)=>item.split("=")[0])
130
+ }
131
+ }
132
+
133
+ export default localCookie
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Copyright 2024 Comcast Cable Communications Management, LLC
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ *
15
+ * SPDX-License-Identifier: Apache-2.0
16
+ */
17
+
18
+ import localCookie from './localCookie.js'
19
+
20
+ let lc = new localCookie()
21
+
22
+ export default {
23
+ name: 'storage',
24
+ plugin() {
25
+ return {
26
+ get(key) {
27
+ try {
28
+ return JSON.parse(lc.getItem(key))
29
+ } catch (e) {
30
+ return null
31
+ }
32
+ },
33
+ set(key, value) {
34
+ try {
35
+ lc.setItem(key, JSON.stringify(value))
36
+ return true
37
+ } catch (e) {
38
+ return false
39
+ }
40
+ },
41
+ remove(key) {
42
+ lc.removeItem(key)
43
+ },
44
+ clear() {
45
+ lc.clear()
46
+ },
47
+ }
48
+ },
49
+ }