@domql/utils 2.5.200 → 3.0.1

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.
Files changed (58) hide show
  1. package/array.js +26 -13
  2. package/cache.js +4 -0
  3. package/component.js +10 -227
  4. package/cookie.js +27 -24
  5. package/dist/cjs/array.js +27 -10
  6. package/dist/cjs/cache.js +26 -0
  7. package/dist/cjs/component.js +15 -206
  8. package/dist/cjs/cookie.js +14 -14
  9. package/dist/cjs/element.js +136 -0
  10. package/dist/cjs/events.js +37 -0
  11. package/dist/cjs/extends.js +351 -0
  12. package/dist/cjs/if.js +30 -0
  13. package/dist/cjs/index.js +10 -0
  14. package/dist/cjs/key.js +5 -0
  15. package/dist/cjs/keys.js +178 -0
  16. package/dist/cjs/methods.js +305 -0
  17. package/dist/cjs/object.js +78 -191
  18. package/dist/cjs/props.js +220 -0
  19. package/dist/cjs/scope.js +28 -0
  20. package/dist/cjs/state.js +175 -0
  21. package/dist/cjs/string.js +27 -15
  22. package/dist/cjs/update.js +42 -0
  23. package/dist/esm/array.js +27 -10
  24. package/dist/esm/cache.js +6 -0
  25. package/dist/esm/component.js +16 -225
  26. package/dist/esm/cookie.js +14 -14
  27. package/dist/esm/element.js +134 -0
  28. package/dist/esm/events.js +17 -0
  29. package/dist/esm/extends.js +349 -0
  30. package/dist/esm/if.js +10 -0
  31. package/dist/esm/index.js +10 -0
  32. package/dist/esm/key.js +5 -0
  33. package/dist/esm/keys.js +158 -0
  34. package/dist/esm/methods.js +285 -0
  35. package/dist/esm/object.js +79 -193
  36. package/dist/esm/props.js +216 -0
  37. package/dist/esm/scope.js +8 -0
  38. package/dist/esm/state.js +185 -0
  39. package/dist/esm/string.js +27 -15
  40. package/dist/esm/update.js +22 -0
  41. package/element.js +148 -0
  42. package/env.js +5 -2
  43. package/events.js +17 -0
  44. package/extends.js +425 -0
  45. package/if.js +14 -0
  46. package/index.js +10 -0
  47. package/key.js +6 -0
  48. package/keys.js +157 -0
  49. package/log.js +4 -1
  50. package/methods.js +315 -0
  51. package/node.js +21 -13
  52. package/object.js +122 -236
  53. package/package.json +3 -3
  54. package/props.js +249 -0
  55. package/scope.js +8 -0
  56. package/state.js +208 -0
  57. package/string.js +66 -30
  58. package/update.js +27 -0
package/props.js ADDED
@@ -0,0 +1,249 @@
1
+ 'use strict'
2
+
3
+ import { DOMQ_PROPERTIES, PROPS_METHODS } from './keys.js'
4
+ import { addEventFromProps } from './events.js'
5
+ import { deepClone, deepMerge, exec } from './object.js'
6
+ import { is, isArray, isFunction, isObject, isObjectLike } from './types.js'
7
+
8
+ export const createProps = (element, parent, key) => {
9
+ const { props, __ref: ref } = element
10
+ ref.__propsStack = []
11
+ // if (props !== undefined) ref.__initialProps = props
12
+ if (props) ref.__initialProps = props
13
+ else return {}
14
+ if (!isObjectLike(props)) {
15
+ ref.__propsStack.push(props)
16
+ return {}
17
+ }
18
+ return { ...props }
19
+ }
20
+
21
+ export function pickupPropsFromElement (element, opts = {}) {
22
+ const cachedKeys = opts.cachedKeys || []
23
+
24
+ for (const key in element) {
25
+ const value = element[key]
26
+
27
+ const hasDefine = isObject(element.define?.[key])
28
+ const hasGlobalDefine = isObject(element.context?.define?.[key])
29
+ const isElement = /^[A-Z]/.test(key) || /^\d+$/.test(key)
30
+ const isBuiltin = DOMQ_PROPERTIES.includes(key)
31
+
32
+ // If it's not a special case, move to props
33
+ if (!isElement && !isBuiltin && !hasDefine && !hasGlobalDefine) {
34
+ element.props[key] = value
35
+ delete element[key]
36
+ cachedKeys.push(key)
37
+ }
38
+ }
39
+
40
+ return element
41
+ }
42
+
43
+ export function pickupElementFromProps (element, opts) {
44
+ const cachedKeys = opts.cachedKeys || []
45
+
46
+ for (const key in element.props) {
47
+ const value = element.props[key]
48
+
49
+ // Handle event handlers
50
+ const isEvent = key.startsWith('on') && key.length > 2
51
+ const isFn = isFunction(value)
52
+
53
+ if (isEvent && isFn) {
54
+ addEventFromProps(key, element)
55
+ delete element.props[key]
56
+ continue
57
+ }
58
+
59
+ // Skip if key was originally from element
60
+ if (cachedKeys.includes(key)) continue
61
+
62
+ const hasDefine = isObject(element.define?.[key])
63
+ const hasGlobalDefine = isObject(element.context?.define?.[key])
64
+ const isElement = /^[A-Z]/.test(key) || /^\d+$/.test(key)
65
+ const isBuiltin = DOMQ_PROPERTIES.includes(key)
66
+
67
+ // Move qualifying properties back to element root
68
+ if (isElement || isBuiltin || hasDefine || hasGlobalDefine) {
69
+ element[key] = value
70
+ delete element.props[key]
71
+ }
72
+ }
73
+
74
+ return element
75
+ }
76
+
77
+ // Helper function to maintain compatibility with original propertizeElement
78
+ export function propertizeElement (element, opts = {}) {
79
+ const cachedKeys = []
80
+ pickupPropsFromElement(element, { cachedKeys })
81
+ pickupElementFromProps(element, { cachedKeys })
82
+ return element
83
+ }
84
+
85
+ export const objectizeStringProperty = propValue => {
86
+ if (is(propValue)('string', 'number')) {
87
+ return { inheritedString: propValue }
88
+ }
89
+ return propValue
90
+ }
91
+
92
+ export const propExists = (prop, stack) => {
93
+ if (!prop || !stack.length) return false
94
+ const key = isObject(prop) ? JSON.stringify(prop) : prop
95
+ return stack.some(existing => {
96
+ const existingKey = isObject(existing) ? JSON.stringify(existing) : existing
97
+ return existingKey === key
98
+ })
99
+ }
100
+
101
+ export const inheritParentProps = (element, parent) => {
102
+ const { __ref: ref } = element
103
+ const propsStack = ref.__propsStack || []
104
+ const parentProps = parent.props
105
+
106
+ if (!parentProps) return propsStack
107
+
108
+ const matchParentKeyProps = parentProps[element.key]
109
+ const matchParentChildProps = parentProps.childProps
110
+
111
+ // Order matters: key-specific props should be added after childProps
112
+ const ignoreChildProps = element.props?.ignoreChildProps
113
+ if (matchParentChildProps && !ignoreChildProps) {
114
+ const childProps = objectizeStringProperty(matchParentChildProps)
115
+ propsStack.unshift(childProps)
116
+ }
117
+
118
+ if (matchParentKeyProps) {
119
+ const keyProps = objectizeStringProperty(matchParentKeyProps)
120
+ propsStack.unshift(keyProps)
121
+ }
122
+
123
+ return propsStack
124
+ }
125
+
126
+ export async function update (props, options) {
127
+ const element = this.__element
128
+ await element.update({ props }, options)
129
+ }
130
+
131
+ // TODO: check bind with promise
132
+ export function setPropsPrototype (element) {
133
+ const methods = { update: update.bind(element.props), __element: element }
134
+ Object.setPrototypeOf(element.props, methods)
135
+ }
136
+
137
+ export const removeDuplicateProps = propsStack => {
138
+ const seen = new Set()
139
+
140
+ return propsStack.filter(prop => {
141
+ if (!prop || PROPS_METHODS.includes(prop)) return false
142
+ const key = isObject(prop) ? JSON.stringify(prop) : prop
143
+ if (seen.has(key)) return false
144
+ seen.add(key)
145
+ return true
146
+ })
147
+ }
148
+
149
+ export const syncProps = (propsStack, element, opts) => {
150
+ element.props = propsStack.reduce((mergedProps, v) => {
151
+ if (PROPS_METHODS.includes(v)) return mergedProps
152
+ while (isFunction(v)) v = exec(v, element)
153
+ return deepMerge(mergedProps, deepClone(v, { exclude: PROPS_METHODS }))
154
+ }, {})
155
+ setPropsPrototype(element)
156
+ return element.props
157
+ }
158
+
159
+ export const createPropsStack = (element, parent) => {
160
+ const { props, __ref: ref } = element
161
+
162
+ // Start with parent props
163
+ let propsStack = ref.__propsStack || []
164
+
165
+ // Get parent props
166
+ if (parent && parent.props) {
167
+ const parentStack = inheritParentProps(element, parent)
168
+ propsStack = [...parentStack]
169
+ }
170
+
171
+ // Add current props
172
+ if (isObject(props)) propsStack.push(props)
173
+ else if (props === 'inherit' && parent?.props) propsStack.push(parent.props)
174
+ else if (props) propsStack.push(props)
175
+
176
+ // Add extends props
177
+ if (isArray(ref.__extendsStack)) {
178
+ ref.__extendsStack.forEach(_extends => {
179
+ if (_extends.props && _extends.props !== props) {
180
+ propsStack.push(_extends.props)
181
+ }
182
+ })
183
+ }
184
+
185
+ // Remove duplicates and update reference
186
+ ref.__propsStack = removeDuplicateProps(propsStack)
187
+ return ref.__propsStack
188
+ }
189
+
190
+ export const applyProps = (element, parent) => {
191
+ const { __ref: ref } = element
192
+
193
+ // Create a fresh props stack
194
+ const propsStack = createPropsStack(element, parent)
195
+
196
+ // Update the element
197
+ if (propsStack.length) {
198
+ syncProps(propsStack, element)
199
+ } else {
200
+ ref.__propsStack = []
201
+ element.props = {}
202
+ }
203
+ }
204
+
205
+ export const initProps = function (element, parent, options) {
206
+ const { __ref: ref } = element
207
+
208
+ if (ref.__if) applyProps(element, parent)
209
+ else {
210
+ try {
211
+ applyProps(element, parent)
212
+ } catch {
213
+ element.props = {}
214
+ ref.__propsStack = []
215
+ }
216
+ }
217
+
218
+ setPropsPrototype(element)
219
+
220
+ return element
221
+ }
222
+
223
+ export const updateProps = (newProps, element, parent) => {
224
+ const { __ref: ref } = element
225
+ const propsStack = ref.__propsStack || []
226
+
227
+ // Create a new array to avoid mutating the original
228
+ let newStack = [...propsStack]
229
+
230
+ // Add parent props first if they exist
231
+ const parentProps = inheritParentProps(element, parent)
232
+ if (parentProps.length) {
233
+ newStack = [...parentProps, ...newStack]
234
+ }
235
+
236
+ // Add new props if they exist
237
+ if (newProps) {
238
+ newStack = [newProps, ...newStack]
239
+ }
240
+
241
+ // Clean up duplicates
242
+ ref.__propsStack = removeDuplicateProps(newStack)
243
+
244
+ if (ref.__propsStack.length) {
245
+ syncProps(ref.__propsStack, element)
246
+ }
247
+
248
+ return element
249
+ }
package/scope.js ADDED
@@ -0,0 +1,8 @@
1
+ 'use strict'
2
+
3
+ // Create scope - shared object across the elements to the own or the nearest parent
4
+ export const createScope = (element, parent) => {
5
+ const { __ref: ref } = element
6
+ // If the element doesn't have a scope, initialize it using the parent's scope or the root's scope.
7
+ if (!element.scope) element.scope = parent.scope || ref.root?.scope || {}
8
+ }
package/state.js ADDED
@@ -0,0 +1,208 @@
1
+ 'use strict'
2
+
3
+ import { addProtoToArray } from './array.js'
4
+ import { STATE_METHODS } from './keys.js'
5
+ import {
6
+ deepClone,
7
+ deepMerge,
8
+ execPromise,
9
+ overwriteDeep,
10
+ overwriteShallow
11
+ } from './object.js'
12
+ import {
13
+ is,
14
+ isFunction,
15
+ isObject,
16
+ isObjectLike,
17
+ isString,
18
+ isUndefined
19
+ } from './types.js'
20
+
21
+ export const checkForStateTypes = async element => {
22
+ const { state: orig, props, __ref: ref } = element
23
+ const state = props?.state || orig
24
+ if (isFunction(state)) {
25
+ ref.__state = state
26
+ return await execPromise(state, element)
27
+ } else if (is(state)('string', 'number')) {
28
+ ref.__state = state
29
+ return { value: state }
30
+ } else if (state === true) {
31
+ ref.__state = element.key
32
+ return {}
33
+ } else if (state) {
34
+ ref.__hasRootState = true
35
+ return state
36
+ } else {
37
+ return false
38
+ }
39
+ }
40
+
41
+ export const getRootStateInKey = (stateKey, parentState) => {
42
+ if (!stateKey.includes('~/')) return
43
+ const arr = stateKey.split('~/')
44
+ if (arr.length > 1) return parentState.root
45
+ }
46
+
47
+ export const getParentStateInKey = (stateKey, parentState) => {
48
+ if (!stateKey.includes('../')) return
49
+ const arr = stateKey.split('../')
50
+ const arrLength = arr.length - 1
51
+ for (let i = 0; i < arrLength; i++) {
52
+ if (!parentState.parent) return null
53
+ parentState = parentState.parent
54
+ }
55
+ return parentState
56
+ }
57
+
58
+ export const getChildStateInKey = (stateKey, parentState, options = {}) => {
59
+ const arr = isString(stateKey) ? stateKey.split('/') : [stateKey]
60
+ const arrLength = arr.length - 1
61
+ for (let i = 0; i < arrLength; i++) {
62
+ const childKey = arr[i]
63
+ const grandChildKey = arr[i + 1]
64
+
65
+ if (childKey === '__proto__' || grandChildKey === '__proto__') return
66
+
67
+ let childInParent = parentState[childKey]
68
+ if (!childInParent) childInParent = parentState[childKey] = {} // check for array
69
+ if (!childInParent[grandChildKey]) childInParent[grandChildKey] = {} // check for array
70
+
71
+ stateKey = grandChildKey
72
+ parentState = childInParent
73
+ }
74
+ if (options.returnParent) return parentState
75
+ return parentState[stateKey]
76
+ }
77
+
78
+ export const findInheritedState = (element, parent, options = {}) => {
79
+ const ref = element.__ref
80
+ let stateKey = ref.__state
81
+ if (!checkIfInherits(element)) return
82
+
83
+ const rootState = getRootStateInKey(stateKey, parent.state)
84
+ let parentState = parent.state
85
+
86
+ if (rootState) {
87
+ parentState = rootState
88
+ stateKey = stateKey.replaceAll('~/', '')
89
+ } else {
90
+ const findGrandParentState = getParentStateInKey(stateKey, parent.state)
91
+ if (findGrandParentState) {
92
+ parentState = findGrandParentState
93
+ stateKey = stateKey.replaceAll('../', '')
94
+ }
95
+ }
96
+
97
+ if (!parentState) return
98
+ return getChildStateInKey(stateKey, parentState, options)
99
+ }
100
+
101
+ export const createInheritedState = (element, parent) => {
102
+ const ref = element.__ref
103
+ const inheritedState = findInheritedState(element, parent)
104
+ if (isUndefined(inheritedState)) return element.state
105
+
106
+ if (is(inheritedState)('object', 'array')) {
107
+ return deepClone(inheritedState)
108
+ } else if (is(inheritedState)('string', 'number', 'boolean')) {
109
+ ref.__stateType = typeof inheritedState
110
+ return { value: inheritedState }
111
+ }
112
+
113
+ console.warn(ref.__state, 'is not present. Replacing with', {})
114
+ }
115
+
116
+ export const checkIfInherits = element => {
117
+ const { __ref: ref } = element
118
+ const stateKey = ref?.__state
119
+ if (stateKey && is(stateKey)('number', 'string', 'boolean')) return true
120
+ return false
121
+ }
122
+
123
+ export const isState = function (state) {
124
+ if (!isObjectLike(state)) return false
125
+ return Boolean(
126
+ state.update &&
127
+ state.parse &&
128
+ state.clean &&
129
+ state.create &&
130
+ state.parent &&
131
+ state.destroy &&
132
+ state.rootUpdate &&
133
+ state.parentUpdate &&
134
+ state.keys &&
135
+ state.values &&
136
+ state.toggle &&
137
+ state.replace &&
138
+ state.quietUpdate &&
139
+ state.quietReplace &&
140
+ state.add &&
141
+ state.apply &&
142
+ state.applyReplace &&
143
+ state.setByPath &&
144
+ state.setPathCollection &&
145
+ state.removeByPath &&
146
+ state.removePathCollection &&
147
+ state.getByPath &&
148
+ state.applyFunction &&
149
+ state.__element &&
150
+ state.__children
151
+ )
152
+ }
153
+
154
+ export const createNestedObjectByKeyPath = (path, value) => {
155
+ if (!path) {
156
+ return value || {}
157
+ }
158
+ const keys = path.split('/')
159
+ const obj = {}
160
+ let ref = obj
161
+ keys.forEach((key, index) => {
162
+ ref[key] = index === keys.length - 1 ? value || {} : {}
163
+ ref = ref[key]
164
+ })
165
+ return obj
166
+ }
167
+
168
+ export const applyDependentState = async (element, state) => {
169
+ const { __element } = state //
170
+ const origState = await execPromise(__element?.state, element)
171
+ if (!origState) return
172
+ const dependentState = deepClone(origState, STATE_METHODS)
173
+ const newDepends = { [element.key]: dependentState }
174
+
175
+ const __depends = isObject(origState.__depends)
176
+ ? { ...origState.__depends, ...newDepends }
177
+ : newDepends
178
+
179
+ if (Array.isArray(origState)) {
180
+ addProtoToArray(origState, {
181
+ ...Object.getPrototypeOf(origState),
182
+ __depends
183
+ })
184
+ } else {
185
+ Object.setPrototypeOf(origState, {
186
+ ...Object.getPrototypeOf(origState),
187
+ __depends
188
+ })
189
+ }
190
+
191
+ return dependentState
192
+ }
193
+
194
+ export const overwriteState = (state, obj, options = {}) => {
195
+ const { overwrite } = options
196
+ if (!overwrite) return
197
+
198
+ const shallow = overwrite === 'shallow'
199
+ const merge = overwrite === 'merge'
200
+
201
+ if (merge) {
202
+ deepMerge(state, obj, STATE_METHODS)
203
+ return
204
+ }
205
+
206
+ const overwriteFunc = shallow ? overwriteShallow : overwriteDeep
207
+ overwriteFunc(state, obj, STATE_METHODS)
208
+ }
package/string.js CHANGED
@@ -25,34 +25,50 @@ export const trimStringFromSymbols = (str, characters) => {
25
25
  * @returns {string} The modified string with placeholders replaced by values from the object.
26
26
  */
27
27
  const brackRegex = {
28
- 2: /\{\{\s*((?:\.\.\/)+)?([^}\s]+)\s*\}\}/g,
29
- 3: /\{\{\{\s*((?:\.\.\/)+)?([^}\s]+)\s*\}\}\}/g
28
+ 2: /{{\s*((?:\.\.\/)*)([\w\d.]+)\s*}}/g,
29
+ 3: /{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*}}}/g
30
30
  }
31
31
 
32
- export function replaceLiteralsWithObjectFields (str, options = {}, forcedState) {
33
- if (!str.includes(options.bracketsLength === 3 ? '{{{' : '{{')) return str
34
- const reg = brackRegex[options.bracketsLength || 2]
35
- const obj = forcedState || this?.state || {}
32
+ const getNestedValue = (obj, path) => {
33
+ return path.split('.').reduce((acc, part) => {
34
+ return acc && acc[part] !== undefined ? acc[part] : undefined
35
+ }, obj)
36
+ }
37
+
38
+ export function replaceLiteralsWithObjectFields (str, state = {}, options = {}) {
39
+ const { bracketsLength = 2 } = options
40
+ const bracketPattern = bracketsLength === 3 ? '{{{' : '{{'
41
+ if (!str.includes(bracketPattern)) return str
42
+
43
+ const reg = brackRegex[bracketsLength]
44
+ const obj = state || {}
45
+
36
46
  return str.replace(reg, (_, parentPath, variable) => {
37
47
  if (parentPath) {
38
- const parentLevels = parentPath.match(options.bracketsLength === 3 ? /\.\.\.\//g : /\.\.\//g).length
48
+ const parentLevels = (parentPath.match(/\.\.\//g) || []).length
39
49
  let parentState = obj
50
+
40
51
  for (let i = 0; i < parentLevels; i++) {
52
+ if (!parentState || !parentState.parent) return ''
41
53
  parentState = parentState.parent
42
- if (!parentState) {
43
- return '' // Return an empty string if the parent level doesn't exist
44
- }
45
54
  }
46
- const value = parentState[variable.trim()]
47
- return value !== undefined ? `${value}` : ''
55
+
56
+ // If the variable is 'parent', return the value property
57
+ const key = variable.trim()
58
+ if (key === 'parent') {
59
+ return parentState.value !== undefined ? String(parentState.value) : ''
60
+ }
61
+
62
+ const value = getNestedValue(parentState, key)
63
+ return value !== undefined ? String(value) : ''
48
64
  } else {
49
- const value = obj[variable.trim()]
50
- return value !== undefined ? `${value}` : ''
65
+ const value = getNestedValue(obj, variable.trim())
66
+ return value !== undefined ? String(value) : ''
51
67
  }
52
68
  })
53
69
  }
54
70
 
55
- export const lowercaseFirstLetter = (inputString) => {
71
+ export const lowercaseFirstLetter = inputString => {
56
72
  return `${inputString.charAt(0).toLowerCase()}${inputString.slice(1)}`
57
73
  }
58
74
 
@@ -98,7 +114,10 @@ export const findKeyPosition = (str, key) => {
98
114
  // If braceCount is 0 and we find the end of the object/array
99
115
  if (braceCount === 0) {
100
116
  endLineNumber = i + 1
101
- endColumn = lines[i].lastIndexOf('}') !== -1 ? lines[i].lastIndexOf('}') + 2 : lines[i].length + 1
117
+ endColumn =
118
+ lines[i].lastIndexOf('}') !== -1
119
+ ? lines[i].lastIndexOf('}') + 2
120
+ : lines[i].length + 1
102
121
  break
103
122
  }
104
123
  }
@@ -112,7 +131,7 @@ export const findKeyPosition = (str, key) => {
112
131
  }
113
132
  }
114
133
 
115
- export const replaceOctalEscapeSequences = (str) => {
134
+ export const replaceOctalEscapeSequences = str => {
116
135
  // Regex to match octal escape sequences
117
136
  const octalRegex = /\\([0-7]{1,3})/g
118
137
 
@@ -126,23 +145,40 @@ export const replaceOctalEscapeSequences = (str) => {
126
145
  })
127
146
  }
128
147
 
129
- export const encodeNewlines = (str) => {
130
- return str.split('\n').join('/////n').split('`').join('/////tilde').split('$').join('/////dlrsgn')
148
+ export const encodeNewlines = str => {
149
+ return str
150
+ .split('\n')
151
+ .join('/////n')
152
+ .split('`')
153
+ .join('/////tilde')
154
+ .split('$')
155
+ .join('/////dlrsgn')
131
156
  }
132
157
 
133
- export const decodeNewlines = (encodedStr) => {
134
- return encodedStr.split('/////n').join('\n').split('/////tilde').join('`').split('/////dlrsgn').join('$')
158
+ export const decodeNewlines = encodedStr => {
159
+ return encodedStr
160
+ .split('/////n')
161
+ .join('\n')
162
+ .split('/////tilde')
163
+ .join('`')
164
+ .split('/////dlrsgn')
165
+ .join('$')
135
166
  }
136
167
 
137
- export const customEncodeURIComponent = (str) => {
138
- return str.split('').map(char => {
139
- if (/[^a-zA-Z0-9\s]/.test(char)) {
140
- return '%' + char.charCodeAt(0).toString(16).toUpperCase()
141
- }
142
- return char
143
- }).join('')
168
+ export const customEncodeURIComponent = str => {
169
+ return str
170
+ .split('')
171
+ .map(char => {
172
+ if (/[^a-zA-Z0-9\s]/.test(char)) {
173
+ return '%' + char.charCodeAt(0).toString(16).toUpperCase()
174
+ }
175
+ return char
176
+ })
177
+ .join('')
144
178
  }
145
179
 
146
- export const customDecodeURIComponent = (encodedStr) => {
147
- return encodedStr.replace(/%[0-9A-Fa-f]{2}/g, match => String.fromCharCode(parseInt(match.slice(1), 16)))
180
+ export const customDecodeURIComponent = encodedStr => {
181
+ return encodedStr.replace(/%[0-9A-Fa-f]{2}/g, match =>
182
+ String.fromCharCode(parseInt(match.slice(1), 16))
183
+ )
148
184
  }
package/update.js ADDED
@@ -0,0 +1,27 @@
1
+ 'use strict'
2
+
3
+ import { createSnapshotId } from './key.js'
4
+
5
+ const snapshot = {
6
+ snapshotId: createSnapshotId
7
+ }
8
+
9
+ export const captureSnapshot = (element, options) => {
10
+ const ref = element.__ref
11
+
12
+ const { currentSnapshot, calleeElement } = options
13
+ const isCallee = calleeElement === element
14
+ if (!calleeElement || isCallee) {
15
+ const createdStanpshot = snapshot.snapshotId()
16
+ ref.__currentSnapshot = createdStanpshot
17
+ return [createdStanpshot, element]
18
+ }
19
+
20
+ const snapshotOnCallee = calleeElement.__ref.__currentSnapshot
21
+
22
+ if (currentSnapshot < snapshotOnCallee) {
23
+ return [snapshotOnCallee, calleeElement, true]
24
+ }
25
+
26
+ return [snapshotOnCallee, calleeElement]
27
+ }