@symbo.ls/utils 3.2.3 → 3.14.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/LICENSE +25 -12
- package/README.md +106 -0
- package/array.js +162 -0
- package/cache.js +7 -0
- package/cdn.js +83 -0
- package/component.js +25 -0
- package/cookie.js +71 -0
- package/{src/detectHeight.js → detectHeight.js} +3 -3
- package/dist/cjs/array.js +168 -0
- package/dist/cjs/browser.js +0 -2
- package/dist/cjs/cache.js +26 -0
- package/dist/cjs/cdn.js +85 -0
- package/dist/cjs/component.js +45 -0
- package/dist/cjs/cookie.js +75 -0
- package/dist/cjs/date.js +1 -3
- package/dist/cjs/detectHeight.js +4 -6
- package/dist/cjs/element.js +136 -0
- package/dist/cjs/env.js +43 -0
- package/dist/cjs/events.js +39 -0
- package/dist/cjs/extends.js +434 -0
- package/dist/cjs/fibonacci.js +1 -3
- package/dist/cjs/files.js +1 -3
- package/dist/cjs/function.js +114 -0
- package/dist/cjs/globals.js +30 -0
- package/dist/cjs/if.js +48 -0
- package/dist/cjs/index.js +38 -425
- package/dist/cjs/key.js +38 -0
- package/dist/cjs/keys.js +201 -0
- package/dist/cjs/load.js +5 -7
- package/dist/cjs/log.js +34 -0
- package/dist/cjs/metadata.js +310 -0
- package/dist/cjs/methods.js +599 -0
- package/dist/cjs/node.js +35 -0
- package/dist/cjs/object.js +634 -0
- package/dist/cjs/projectKeys.js +35 -0
- package/dist/cjs/props.js +282 -0
- package/dist/cjs/scaling.js +5 -169
- package/dist/cjs/scope.js +44 -0
- package/dist/cjs/sharedLibraries.js +146 -0
- package/dist/cjs/state.js +173 -0
- package/dist/cjs/string-extra.js +72 -0
- package/dist/cjs/string.js +183 -0
- package/dist/cjs/style.js +1 -3
- package/dist/cjs/tags.js +220 -0
- package/dist/cjs/triggerEvent.js +112 -0
- package/dist/cjs/types.js +74 -0
- package/dist/cjs/update.js +42 -0
- package/dist/esm/array.js +148 -0
- package/dist/esm/browser.js +14 -0
- package/dist/esm/cache.js +6 -0
- package/dist/esm/cdn.js +65 -0
- package/dist/esm/component.js +25 -0
- package/dist/esm/cookie.js +55 -0
- package/dist/esm/date.js +11 -0
- package/dist/esm/detectHeight.js +42 -0
- package/dist/esm/element.js +116 -0
- package/dist/esm/env.js +23 -0
- package/dist/esm/events.js +19 -0
- package/dist/esm/extends.js +414 -0
- package/dist/esm/fibonacci.js +10 -0
- package/dist/esm/files.js +4 -0
- package/dist/esm/function.js +94 -0
- package/dist/esm/globals.js +10 -0
- package/dist/esm/if.js +28 -0
- package/dist/esm/index.js +37 -0
- package/dist/esm/key.js +18 -0
- package/dist/esm/keys.js +181 -0
- package/dist/esm/load.js +151 -0
- package/dist/esm/log.js +14 -0
- package/dist/esm/metadata.js +290 -0
- package/dist/esm/methods.js +569 -0
- package/dist/esm/node.js +15 -0
- package/dist/esm/object.js +621 -0
- package/dist/esm/projectKeys.js +16 -0
- package/dist/esm/props.js +262 -0
- package/dist/esm/scaling.js +15 -0
- package/dist/esm/scope.js +24 -0
- package/dist/esm/sharedLibraries.js +126 -0
- package/dist/esm/state.js +163 -0
- package/dist/esm/string-extra.js +52 -0
- package/dist/esm/string.js +163 -0
- package/dist/esm/style.js +20 -0
- package/dist/esm/tags.js +200 -0
- package/dist/esm/triggerEvent.js +92 -0
- package/dist/esm/types.js +54 -0
- package/dist/esm/update.js +22 -0
- package/dist/iife/index.js +5818 -0
- package/element.js +148 -0
- package/env.js +15 -0
- package/events.js +19 -0
- package/extends.js +519 -0
- package/function.js +145 -0
- package/globals.js +8 -0
- package/if.js +30 -0
- package/index.js +41 -0
- package/key.js +20 -0
- package/keys.js +176 -0
- package/log.js +12 -0
- package/metadata.js +392 -0
- package/methods.js +636 -0
- package/node.js +37 -0
- package/object.js +803 -0
- package/package.json +38 -22
- package/projectKeys.js +30 -0
- package/props.js +327 -0
- package/{src/scaling.js → scaling.js} +1 -1
- package/scope.js +32 -0
- package/sharedLibraries.js +184 -0
- package/state.js +203 -0
- package/{src/index.js → string-extra.js} +11 -17
- package/string.js +206 -0
- package/tags.js +176 -0
- package/triggerEvent.js +102 -0
- package/types.js +55 -0
- package/update.js +27 -0
- package/dist/cjs/package.json +0 -4
- /package/{src/browser.js → browser.js} +0 -0
- /package/{src/date.js → date.js} +0 -0
- /package/{src/fibonacci.js → fibonacci.js} +0 -0
- /package/{src/files.js → files.js} +0 -0
- /package/{src/load.js → load.js} +0 -0
- /package/{src/style.js → style.js} +0 -0
package/state.js
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { addProtoToArray } from './array.js'
|
|
4
|
+
import { STATE_METHODS } from './keys.js'
|
|
5
|
+
import {
|
|
6
|
+
deepClone,
|
|
7
|
+
deepMerge,
|
|
8
|
+
overwriteDeep,
|
|
9
|
+
overwriteShallow
|
|
10
|
+
} from './object.js'
|
|
11
|
+
import {
|
|
12
|
+
is,
|
|
13
|
+
isObject,
|
|
14
|
+
isObjectLike,
|
|
15
|
+
isString
|
|
16
|
+
} from './types.js'
|
|
17
|
+
|
|
18
|
+
export const checkForStateTypes = element => {
|
|
19
|
+
const { state: orig, props, __ref: ref } = element
|
|
20
|
+
const state = props?.state || orig
|
|
21
|
+
if (is(state)('string', 'number')) {
|
|
22
|
+
ref.__state = state
|
|
23
|
+
return { value: state }
|
|
24
|
+
} else if (state === true) {
|
|
25
|
+
ref.__state = element.key
|
|
26
|
+
return {}
|
|
27
|
+
} else if (state) {
|
|
28
|
+
ref.__hasRootState = true
|
|
29
|
+
return state
|
|
30
|
+
} else {
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const getRootStateInKey = (stateKey, parentState) => {
|
|
36
|
+
if (!stateKey.includes('~/')) return
|
|
37
|
+
const arr = stateKey.split('~/')
|
|
38
|
+
if (arr.length > 1) return parentState.root
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const getParentStateInKey = (stateKey, parentState) => {
|
|
42
|
+
if (!stateKey.includes('../')) return
|
|
43
|
+
const arr = stateKey.split('../')
|
|
44
|
+
const arrLength = arr.length - 1
|
|
45
|
+
for (let i = 0; i < arrLength; i++) {
|
|
46
|
+
if (!parentState.parent) return null
|
|
47
|
+
parentState = parentState.parent
|
|
48
|
+
}
|
|
49
|
+
return parentState
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const getChildStateInKey = (stateKey, parentState, options = {}) => {
|
|
53
|
+
const arr = isString(stateKey) ? stateKey.split('/') : [stateKey]
|
|
54
|
+
const arrLength = arr.length - 1
|
|
55
|
+
for (let i = 0; i < arrLength; i++) {
|
|
56
|
+
const childKey = arr[i]
|
|
57
|
+
const grandChildKey = arr[i + 1]
|
|
58
|
+
|
|
59
|
+
if (childKey === '__proto__' || grandChildKey === '__proto__') return
|
|
60
|
+
|
|
61
|
+
let childInParent = parentState[childKey]
|
|
62
|
+
if (!childInParent) childInParent = parentState[childKey] = {} // check for array
|
|
63
|
+
if (!childInParent[grandChildKey]) childInParent[grandChildKey] = {} // check for array
|
|
64
|
+
|
|
65
|
+
stateKey = grandChildKey
|
|
66
|
+
parentState = childInParent
|
|
67
|
+
}
|
|
68
|
+
if (options.returnParent) return parentState
|
|
69
|
+
return parentState[stateKey]
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const findInheritedState = (element, parent, options = {}) => {
|
|
73
|
+
const ref = element.__ref
|
|
74
|
+
let stateKey = ref.__state
|
|
75
|
+
if (!checkIfInherits(element)) return
|
|
76
|
+
|
|
77
|
+
const rootState = getRootStateInKey(stateKey, parent.state)
|
|
78
|
+
let parentState = parent.state
|
|
79
|
+
|
|
80
|
+
if (rootState) {
|
|
81
|
+
parentState = rootState
|
|
82
|
+
stateKey = stateKey.replaceAll('~/', '')
|
|
83
|
+
} else {
|
|
84
|
+
const findGrandParentState = getParentStateInKey(stateKey, parent.state)
|
|
85
|
+
if (findGrandParentState) {
|
|
86
|
+
parentState = findGrandParentState
|
|
87
|
+
stateKey = stateKey.replaceAll('../', '')
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!parentState) return
|
|
92
|
+
return getChildStateInKey(stateKey, parentState, options)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const createInheritedState = (element, parent) => {
|
|
96
|
+
const ref = element.__ref
|
|
97
|
+
const inheritedState = findInheritedState(element, parent)
|
|
98
|
+
if (inheritedState === undefined) return element.state
|
|
99
|
+
|
|
100
|
+
if (is(inheritedState)('object', 'array')) {
|
|
101
|
+
return deepClone(inheritedState)
|
|
102
|
+
} else if (is(inheritedState)('string', 'number', 'boolean')) {
|
|
103
|
+
ref.__stateType = typeof inheritedState
|
|
104
|
+
return { value: inheritedState }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
console.warn(ref.__state, 'is not present. Replacing with', {})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const checkIfInherits = element => {
|
|
111
|
+
const { __ref: ref } = element
|
|
112
|
+
const stateKey = ref?.__state
|
|
113
|
+
if (stateKey && is(stateKey)('number', 'string', 'boolean')) return true
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const isState = function (state) {
|
|
118
|
+
if (!isObjectLike(state)) return false
|
|
119
|
+
return Boolean(
|
|
120
|
+
state.update &&
|
|
121
|
+
state.parse &&
|
|
122
|
+
state.clean &&
|
|
123
|
+
state.create &&
|
|
124
|
+
state.parent &&
|
|
125
|
+
state.destroy &&
|
|
126
|
+
state.rootUpdate &&
|
|
127
|
+
state.parentUpdate &&
|
|
128
|
+
state.keys &&
|
|
129
|
+
state.values &&
|
|
130
|
+
state.toggle &&
|
|
131
|
+
state.replace &&
|
|
132
|
+
state.quietUpdate &&
|
|
133
|
+
state.quietReplace &&
|
|
134
|
+
state.add &&
|
|
135
|
+
state.apply &&
|
|
136
|
+
state.applyReplace &&
|
|
137
|
+
state.setByPath &&
|
|
138
|
+
state.setPathCollection &&
|
|
139
|
+
state.removeByPath &&
|
|
140
|
+
state.removePathCollection &&
|
|
141
|
+
state.getByPath &&
|
|
142
|
+
state.applyFunction &&
|
|
143
|
+
state.__element &&
|
|
144
|
+
state.__children
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export const createNestedObjectByKeyPath = (path, value) => {
|
|
149
|
+
if (!path) {
|
|
150
|
+
return value || {}
|
|
151
|
+
}
|
|
152
|
+
const keys = path.split('/')
|
|
153
|
+
const obj = {}
|
|
154
|
+
let ref = obj
|
|
155
|
+
const lastIdx = keys.length - 1
|
|
156
|
+
for (let i = 0; i <= lastIdx; i++) {
|
|
157
|
+
ref[keys[i]] = i === lastIdx ? value || {} : {}
|
|
158
|
+
ref = ref[keys[i]]
|
|
159
|
+
}
|
|
160
|
+
return obj
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export const applyDependentState = (element, state) => {
|
|
164
|
+
const { __element } = state
|
|
165
|
+
const origState = __element?.state
|
|
166
|
+
if (!origState) return
|
|
167
|
+
const dependentState = deepClone(origState, STATE_METHODS)
|
|
168
|
+
const newDepends = { [element.key]: dependentState }
|
|
169
|
+
|
|
170
|
+
const __depends = isObject(origState.__depends)
|
|
171
|
+
? { ...origState.__depends, ...newDepends }
|
|
172
|
+
: newDepends
|
|
173
|
+
|
|
174
|
+
if (Array.isArray(origState)) {
|
|
175
|
+
addProtoToArray(origState, {
|
|
176
|
+
...Object.getPrototypeOf(origState),
|
|
177
|
+
__depends
|
|
178
|
+
})
|
|
179
|
+
} else {
|
|
180
|
+
Object.setPrototypeOf(origState, {
|
|
181
|
+
...Object.getPrototypeOf(origState),
|
|
182
|
+
__depends
|
|
183
|
+
})
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return dependentState
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export const overwriteState = (state, obj, options = {}) => {
|
|
190
|
+
const { overwrite } = options
|
|
191
|
+
if (!overwrite) return
|
|
192
|
+
|
|
193
|
+
const shallow = overwrite === 'shallow'
|
|
194
|
+
const merge = overwrite === 'merge'
|
|
195
|
+
|
|
196
|
+
if (merge) {
|
|
197
|
+
deepMerge(state, obj, STATE_METHODS)
|
|
198
|
+
return
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const overwriteFunc = shallow ? overwriteShallow : overwriteDeep
|
|
202
|
+
overwriteFunc(state, obj, STATE_METHODS)
|
|
203
|
+
}
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
import { isString, isObject, isArray, isNumber } from '
|
|
3
|
+
import { isString, isObject, isArray, isNumber } from './types.js'
|
|
4
4
|
|
|
5
|
-
export
|
|
6
|
-
export * from './scaling.js'
|
|
7
|
-
export * from './date.js'
|
|
8
|
-
export * from './fibonacci.js'
|
|
9
|
-
export * from './load.js'
|
|
10
|
-
export * from './files.js'
|
|
11
|
-
|
|
12
|
-
export const copyStringToClipboard = async str => {
|
|
5
|
+
export const copyStringToClipboard = async (str) => {
|
|
13
6
|
try {
|
|
14
7
|
await navigator.clipboard.writeText(str)
|
|
15
8
|
} catch (err) {
|
|
@@ -17,7 +10,7 @@ export const copyStringToClipboard = async str => {
|
|
|
17
10
|
}
|
|
18
11
|
}
|
|
19
12
|
|
|
20
|
-
export const copyJavaScriptToClipboard = async jsCode => {
|
|
13
|
+
export const copyJavaScriptToClipboard = async (jsCode) => {
|
|
21
14
|
try {
|
|
22
15
|
// Create a Blob for the JavaScript code with the 'text/javascript' MIME type
|
|
23
16
|
const blob = new Blob([jsCode], { type: 'text/javascript' })
|
|
@@ -34,25 +27,26 @@ export const copyJavaScriptToClipboard = async jsCode => {
|
|
|
34
27
|
}
|
|
35
28
|
}
|
|
36
29
|
|
|
37
|
-
export const removeChars = str => {
|
|
30
|
+
export const removeChars = (str) => {
|
|
38
31
|
return str.replace(/[^a-zA-Z0-9_]/g, '')
|
|
39
32
|
}
|
|
40
33
|
|
|
41
|
-
export const toCamelCase = str => {
|
|
34
|
+
export const toCamelCase = (str) => {
|
|
35
|
+
if (typeof str !== 'string') str = String(str || '')
|
|
42
36
|
return str
|
|
43
37
|
.replace(/(?:^\w|[A-Z]|\b\w)/g, function (word, index) {
|
|
44
38
|
return index === 0 ? word.toLowerCase() : word.toUpperCase()
|
|
45
39
|
})
|
|
46
|
-
.
|
|
40
|
+
.replace(/\s+/g, '')
|
|
47
41
|
}
|
|
48
42
|
|
|
49
|
-
export const toTitleCase = str =>
|
|
43
|
+
export const toTitleCase = (str) =>
|
|
50
44
|
str &&
|
|
51
|
-
str.replace(/\w\S*/g, txt => {
|
|
45
|
+
str.replace(/\w\S*/g, (txt) => {
|
|
52
46
|
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
|
|
53
47
|
})
|
|
54
48
|
|
|
55
|
-
export const toDashCase = val =>
|
|
49
|
+
export const toDashCase = (val) =>
|
|
56
50
|
val
|
|
57
51
|
.replace(/[^a-zA-Z0-9]/g, ' ') // Replace non-alphanumeric characters with spaces
|
|
58
52
|
.trim() // Remove leading and trailing spaces
|
|
@@ -67,7 +61,7 @@ export const toDescriptionCase = (str = '') => {
|
|
|
67
61
|
return result.charAt(0).toUpperCase() + result.slice(1)
|
|
68
62
|
}
|
|
69
63
|
|
|
70
|
-
export const arrayzeValue = val => {
|
|
64
|
+
export const arrayzeValue = (val) => {
|
|
71
65
|
if (isArray(val)) return val
|
|
72
66
|
if (isString(val)) return val.split(' ')
|
|
73
67
|
if (isObject(val)) return Object.values(val)
|
package/string.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
export const stringIncludesAny = (str, characters) => {
|
|
4
|
+
for (const char of characters) {
|
|
5
|
+
if (str.includes(char)) {
|
|
6
|
+
return true
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return false
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const trimStringFromSymbols = (str, characters) => {
|
|
13
|
+
// Create a regular expression pattern to match the specified symbols
|
|
14
|
+
const pattern = new RegExp(`[${characters.join('\\')}]`, 'g')
|
|
15
|
+
|
|
16
|
+
// Replace matched symbols with an empty string
|
|
17
|
+
return str.replace(pattern, '')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Replaces placeholders in a string with corresponding {{ }} values from an object.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} str - The string containing placeholders to replace.
|
|
24
|
+
* @param {object} state - The object containing the values to substitute.
|
|
25
|
+
* @returns {string} The modified string with placeholders replaced by values from the object.
|
|
26
|
+
*/
|
|
27
|
+
const brackRegex = {
|
|
28
|
+
2: /{{\s*((?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}/g,
|
|
29
|
+
3: /{{{(\s*(?:\.\.\/)*)([\w\d.]+)\s*(?:\|\s*([\w\d.]+))?\s*}}}/g
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const getNestedValue = (obj, path) => {
|
|
33
|
+
return path.split('.').reduce((acc, part) => {
|
|
34
|
+
return acc?.[part]
|
|
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 || this.state || {}
|
|
45
|
+
|
|
46
|
+
const element = this
|
|
47
|
+
|
|
48
|
+
return str.replace(reg, (_, parentPath, variable, filter) => {
|
|
49
|
+
const key = variable.trim()
|
|
50
|
+
|
|
51
|
+
// Pipe filter: {{ key | filterName }}
|
|
52
|
+
// Always passes the raw key to the filter — the filter is responsible for resolution
|
|
53
|
+
if (filter) {
|
|
54
|
+
const ctx = element?.context
|
|
55
|
+
const filterFn = ctx?.functions?.[filter] || ctx?.utils?.[filter] || ctx?.methods?.[filter] || ctx?.snippets?.[filter] || element?.[filter]
|
|
56
|
+
if (filterFn && typeof filterFn === 'function') {
|
|
57
|
+
try {
|
|
58
|
+
return String(filterFn.call(element, key) ?? '')
|
|
59
|
+
} catch (e) { return '' }
|
|
60
|
+
}
|
|
61
|
+
return ''
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (parentPath) {
|
|
65
|
+
const parentLevels = (parentPath.match(/\.\.\//g) || []).length
|
|
66
|
+
let parentState = obj
|
|
67
|
+
|
|
68
|
+
for (let i = 0; i < parentLevels; i++) {
|
|
69
|
+
if (!parentState || !parentState.parent) return ''
|
|
70
|
+
parentState = parentState.parent
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// If the variable is 'parent', return the value property
|
|
74
|
+
if (key === 'parent') {
|
|
75
|
+
return String(parentState.value ?? '')
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const value = getNestedValue(parentState, key)
|
|
79
|
+
return String(value ?? '')
|
|
80
|
+
} else {
|
|
81
|
+
// Check state value first
|
|
82
|
+
const value = getNestedValue(obj, key)
|
|
83
|
+
if (value != null) return String(value)
|
|
84
|
+
|
|
85
|
+
// Fall back to polyglot translations for current language
|
|
86
|
+
const poly = element?.context?.polyglot
|
|
87
|
+
if (poly?.translations) {
|
|
88
|
+
const lang = obj?.root?.lang || obj?.lang || element?.context?.state?.lang || poly.defaultLang || 'en'
|
|
89
|
+
const langT = poly.translations[lang]
|
|
90
|
+
if (langT) {
|
|
91
|
+
const tValue = getNestedValue(langT, key)
|
|
92
|
+
if (tValue != null && typeof tValue !== 'object') return String(tValue)
|
|
93
|
+
// Search nested sections (e.g. ka.nav.about for key 'about')
|
|
94
|
+
for (const section in langT) {
|
|
95
|
+
const sectionData = langT[section]
|
|
96
|
+
if (sectionData && typeof sectionData === 'object' && !Array.isArray(sectionData)) {
|
|
97
|
+
const nested = getNestedValue(sectionData, key)
|
|
98
|
+
if (nested != null && typeof nested !== 'object') return String(nested)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Check top-level translations
|
|
103
|
+
const topValue = getNestedValue(poly.translations, key)
|
|
104
|
+
if (topValue != null && typeof topValue !== 'object') return String(topValue)
|
|
105
|
+
}
|
|
106
|
+
return ''
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export const lowercaseFirstLetter = inputString => {
|
|
112
|
+
return `${inputString.charAt(0).toLowerCase()}${inputString.slice(1)}`
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export const findKeyPosition = (str, key) => {
|
|
116
|
+
const lines = str.split('\n')
|
|
117
|
+
let startLineNumber = -1
|
|
118
|
+
let endLineNumber = -1
|
|
119
|
+
let startColumn = -1
|
|
120
|
+
let endColumn = -1
|
|
121
|
+
|
|
122
|
+
const keyPattern = new RegExp(`\\b${key}\\b\\s*:\\s*`)
|
|
123
|
+
let braceCount = 0
|
|
124
|
+
let foundKey = false
|
|
125
|
+
|
|
126
|
+
for (let i = 0; i < lines.length; i++) {
|
|
127
|
+
if (keyPattern.test(lines[i]) && !foundKey) {
|
|
128
|
+
foundKey = true
|
|
129
|
+
startLineNumber = i + 1
|
|
130
|
+
startColumn = lines[i].indexOf(key) + 1
|
|
131
|
+
|
|
132
|
+
// Check if the value is an empty object
|
|
133
|
+
if (lines[i].includes('{}')) {
|
|
134
|
+
endLineNumber = startLineNumber
|
|
135
|
+
endColumn = lines[i].indexOf('{}') + 3
|
|
136
|
+
break
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Check if the value starts with '{' (object) or '[' (array)
|
|
140
|
+
const line = lines[i].slice(startColumn + key.length)
|
|
141
|
+
if (line.includes('{') || line.includes('[')) {
|
|
142
|
+
braceCount = 1
|
|
143
|
+
} else {
|
|
144
|
+
endLineNumber = i + 1
|
|
145
|
+
endColumn = lines[i].length + 1
|
|
146
|
+
break
|
|
147
|
+
}
|
|
148
|
+
} else if (foundKey) {
|
|
149
|
+
braceCount += (lines[i].match(/{/g) || []).length
|
|
150
|
+
braceCount += (lines[i].match(/\[/g) || []).length
|
|
151
|
+
braceCount -= (lines[i].match(/}/g) || []).length
|
|
152
|
+
braceCount -= (lines[i].match(/]/g) || []).length
|
|
153
|
+
|
|
154
|
+
// If braceCount is 0 and we find the end of the object/array
|
|
155
|
+
if (braceCount === 0) {
|
|
156
|
+
endLineNumber = i + 1
|
|
157
|
+
endColumn =
|
|
158
|
+
lines[i].lastIndexOf('}') !== -1
|
|
159
|
+
? lines[i].lastIndexOf('}') + 2
|
|
160
|
+
: lines[i].length + 1
|
|
161
|
+
break
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
startColumn,
|
|
168
|
+
endColumn,
|
|
169
|
+
startLineNumber,
|
|
170
|
+
endLineNumber
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const RE_OCTAL = /\\([0-7]{1,3})/g
|
|
175
|
+
|
|
176
|
+
export const replaceOctalEscapeSequences = str => {
|
|
177
|
+
return str.replace(RE_OCTAL, (_, p1) => String.fromCharCode(parseInt(p1, 8)))
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export const encodeNewlines = str => {
|
|
181
|
+
return str
|
|
182
|
+
.replace(/\n/g, '/////n')
|
|
183
|
+
.replace(/`/g, '/////tilde')
|
|
184
|
+
.replace(/\$/g, '/////dlrsgn')
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export const decodeNewlines = encodedStr => {
|
|
188
|
+
return encodedStr
|
|
189
|
+
.replace(/\/\/\/\/\/n/g, '\n')
|
|
190
|
+
.replace(/\/\/\/\/\/tilde/g, '`')
|
|
191
|
+
.replace(/\/\/\/\/\/dlrsgn/g, '$')
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const RE_NON_ALNUM = /[^a-zA-Z0-9\s]/g
|
|
195
|
+
|
|
196
|
+
export const customEncodeURIComponent = str => {
|
|
197
|
+
return str.replace(RE_NON_ALNUM, char =>
|
|
198
|
+
'%' + char.charCodeAt(0).toString(16).toUpperCase()
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export const customDecodeURIComponent = encodedStr => {
|
|
203
|
+
return encodedStr.replace(/%[0-9A-Fa-f]{2}/g, match =>
|
|
204
|
+
String.fromCharCode(parseInt(match.slice(1), 16))
|
|
205
|
+
)
|
|
206
|
+
}
|
package/tags.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
export const HTML_TAGS = {
|
|
4
|
+
root: ['body', 'html'],
|
|
5
|
+
|
|
6
|
+
head: ['title', 'base', 'meta', 'style', 'noscript', 'script'],
|
|
7
|
+
|
|
8
|
+
body: new Set([
|
|
9
|
+
'string',
|
|
10
|
+
'style',
|
|
11
|
+
'fragment',
|
|
12
|
+
'a',
|
|
13
|
+
'abbr',
|
|
14
|
+
'acronym',
|
|
15
|
+
'address',
|
|
16
|
+
'applet',
|
|
17
|
+
'area',
|
|
18
|
+
'article',
|
|
19
|
+
'aside',
|
|
20
|
+
'audio',
|
|
21
|
+
'b',
|
|
22
|
+
'basefont',
|
|
23
|
+
'bdi',
|
|
24
|
+
'bdo',
|
|
25
|
+
'big',
|
|
26
|
+
'blockquote',
|
|
27
|
+
'br',
|
|
28
|
+
'button',
|
|
29
|
+
'canvas',
|
|
30
|
+
'caption',
|
|
31
|
+
'center',
|
|
32
|
+
'cite',
|
|
33
|
+
'code',
|
|
34
|
+
'search',
|
|
35
|
+
'col',
|
|
36
|
+
'colgroup',
|
|
37
|
+
'data',
|
|
38
|
+
'datalist',
|
|
39
|
+
'dd',
|
|
40
|
+
'del',
|
|
41
|
+
'details',
|
|
42
|
+
'dfn',
|
|
43
|
+
'dialog',
|
|
44
|
+
'dir',
|
|
45
|
+
'div',
|
|
46
|
+
'dl',
|
|
47
|
+
'dt',
|
|
48
|
+
'em',
|
|
49
|
+
'embed',
|
|
50
|
+
'fieldset',
|
|
51
|
+
'figcaption',
|
|
52
|
+
'figure',
|
|
53
|
+
'font',
|
|
54
|
+
'footer',
|
|
55
|
+
'form',
|
|
56
|
+
'frame',
|
|
57
|
+
'frameset',
|
|
58
|
+
'h1',
|
|
59
|
+
'h2',
|
|
60
|
+
'h3',
|
|
61
|
+
'h4',
|
|
62
|
+
'h5',
|
|
63
|
+
'h6',
|
|
64
|
+
'head',
|
|
65
|
+
'header',
|
|
66
|
+
'hr',
|
|
67
|
+
'i',
|
|
68
|
+
'iframe',
|
|
69
|
+
'img',
|
|
70
|
+
'input',
|
|
71
|
+
'ins',
|
|
72
|
+
'kbd',
|
|
73
|
+
'label',
|
|
74
|
+
'legend',
|
|
75
|
+
'li',
|
|
76
|
+
'link',
|
|
77
|
+
'main',
|
|
78
|
+
'map',
|
|
79
|
+
'mark',
|
|
80
|
+
'meter',
|
|
81
|
+
'nav',
|
|
82
|
+
'noframes',
|
|
83
|
+
'noscript',
|
|
84
|
+
'object',
|
|
85
|
+
'ol',
|
|
86
|
+
'optgroup',
|
|
87
|
+
'option',
|
|
88
|
+
'output',
|
|
89
|
+
'p',
|
|
90
|
+
'param',
|
|
91
|
+
'picture',
|
|
92
|
+
'pre',
|
|
93
|
+
'progress',
|
|
94
|
+
'hgroup',
|
|
95
|
+
'q',
|
|
96
|
+
'rp',
|
|
97
|
+
'rt',
|
|
98
|
+
'ruby',
|
|
99
|
+
's',
|
|
100
|
+
'samp',
|
|
101
|
+
'script',
|
|
102
|
+
'section',
|
|
103
|
+
'select',
|
|
104
|
+
'small',
|
|
105
|
+
'source',
|
|
106
|
+
'span',
|
|
107
|
+
'strike',
|
|
108
|
+
'strong',
|
|
109
|
+
'sub',
|
|
110
|
+
'summary',
|
|
111
|
+
'sup',
|
|
112
|
+
'table',
|
|
113
|
+
'tbody',
|
|
114
|
+
'td',
|
|
115
|
+
'template',
|
|
116
|
+
'hgroup',
|
|
117
|
+
'textarea',
|
|
118
|
+
'tfoot',
|
|
119
|
+
'th',
|
|
120
|
+
'thead',
|
|
121
|
+
'time',
|
|
122
|
+
'tr',
|
|
123
|
+
'track',
|
|
124
|
+
'tt',
|
|
125
|
+
'u',
|
|
126
|
+
'ul',
|
|
127
|
+
'var',
|
|
128
|
+
'video',
|
|
129
|
+
'wbr',
|
|
130
|
+
|
|
131
|
+
// SVG
|
|
132
|
+
'svg',
|
|
133
|
+
'path',
|
|
134
|
+
'circle',
|
|
135
|
+
'ellipse',
|
|
136
|
+
'line',
|
|
137
|
+
'polygon',
|
|
138
|
+
'polyline',
|
|
139
|
+
'rect',
|
|
140
|
+
'g',
|
|
141
|
+
'defs',
|
|
142
|
+
'symbol',
|
|
143
|
+
'use',
|
|
144
|
+
'text',
|
|
145
|
+
'tspan',
|
|
146
|
+
'image',
|
|
147
|
+
'clipPath',
|
|
148
|
+
'mask',
|
|
149
|
+
'pattern',
|
|
150
|
+
'marker',
|
|
151
|
+
'linearGradient',
|
|
152
|
+
'radialGradient',
|
|
153
|
+
'stop',
|
|
154
|
+
'filter',
|
|
155
|
+
'feGaussianBlur',
|
|
156
|
+
'feOffset',
|
|
157
|
+
'feMerge',
|
|
158
|
+
'feMergeNode',
|
|
159
|
+
'feBlend',
|
|
160
|
+
'feColorMatrix',
|
|
161
|
+
'feFlood',
|
|
162
|
+
'feComposite',
|
|
163
|
+
'foreignObject'
|
|
164
|
+
])
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export const SVG_TAGS = new Set([
|
|
168
|
+
'svg', 'path', 'circle', 'ellipse', 'line', 'polygon', 'polyline',
|
|
169
|
+
'rect', 'g', 'defs', 'symbol', 'use', 'text', 'tspan', 'image',
|
|
170
|
+
'clipPath', 'mask', 'pattern', 'marker', 'linearGradient',
|
|
171
|
+
'radialGradient', 'stop', 'filter', 'feGaussianBlur', 'feOffset',
|
|
172
|
+
'feMerge', 'feMergeNode', 'feBlend', 'feColorMatrix', 'feFlood',
|
|
173
|
+
'feComposite', 'foreignObject'
|
|
174
|
+
])
|
|
175
|
+
|
|
176
|
+
export const isValidHtmlTag = arg => HTML_TAGS.body.has(arg)
|