@domql/utils 0.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.
- package/package.json +6 -0
- package/src/index.js +6 -0
- package/src/node.js +10 -0
- package/src/object.js +193 -0
- package/src/protoUtils.js +119 -0
- package/src/report.js +62 -0
package/package.json
ADDED
package/src/index.js
ADDED
package/src/node.js
ADDED
package/src/object.js
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import nodes from '../element/nodes'
|
|
4
|
+
|
|
5
|
+
export const isTagRegistered = arg => nodes.body.indexOf(arg)
|
|
6
|
+
|
|
7
|
+
export const isObject = arg => {
|
|
8
|
+
if (arg === null) return false
|
|
9
|
+
return (typeof arg === 'object') && (arg.constructor === Object)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const isString = arg => typeof arg === 'string'
|
|
13
|
+
|
|
14
|
+
export const isNumber = arg => typeof arg === 'number'
|
|
15
|
+
|
|
16
|
+
export const isFunction = arg => typeof arg === 'function'
|
|
17
|
+
|
|
18
|
+
export const isArray = arg => Array.isArray(arg)
|
|
19
|
+
|
|
20
|
+
export const isObjectLike = arg => {
|
|
21
|
+
if (arg === null) return false
|
|
22
|
+
// if (isArray(arg)) return false
|
|
23
|
+
return (typeof arg === 'object')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const isNode = obj => {
|
|
27
|
+
return (
|
|
28
|
+
typeof window.Node === 'object'
|
|
29
|
+
? obj instanceof window.Node
|
|
30
|
+
: obj && typeof obj === 'object' && typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string'
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const isHtmlElement = obj => {
|
|
35
|
+
return (
|
|
36
|
+
typeof window.HTMLElement === 'object'
|
|
37
|
+
? obj instanceof window.HTMLElement // DOM2
|
|
38
|
+
: obj && typeof obj === 'object' && obj !== null && obj.nodeType === 1 && typeof obj.nodeName === 'string'
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const isDefined = arg => {
|
|
43
|
+
return isObject(arg) ||
|
|
44
|
+
isObjectLike(arg) ||
|
|
45
|
+
isString(arg) ||
|
|
46
|
+
isNumber(arg) ||
|
|
47
|
+
isFunction(arg) ||
|
|
48
|
+
isArray(arg) ||
|
|
49
|
+
isObjectLike(arg)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const exec = (param, element, state) => {
|
|
53
|
+
if (isFunction(param)) return param(element, state || element.state)
|
|
54
|
+
return param
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const map = (obj, extention, element) => {
|
|
58
|
+
for (const e in extention) {
|
|
59
|
+
obj[e] = exec(extention[e], element)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const merge = (element, obj) => {
|
|
64
|
+
for (const e in obj) {
|
|
65
|
+
const elementProp = element[e]
|
|
66
|
+
const objProp = obj[e]
|
|
67
|
+
if (elementProp === undefined) {
|
|
68
|
+
element[e] = objProp
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return element
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const deepMerge = (element, proto) => {
|
|
75
|
+
// console.groupCollapsed('deepMerge:')
|
|
76
|
+
for (const e in proto) {
|
|
77
|
+
const elementProp = element[e]
|
|
78
|
+
const protoProp = proto[e]
|
|
79
|
+
// const cachedProps = cache.props
|
|
80
|
+
if (e === 'parent' || e === 'props') continue
|
|
81
|
+
if (elementProp === undefined) {
|
|
82
|
+
element[e] = protoProp
|
|
83
|
+
} else if (isObjectLike(elementProp) && isObject(protoProp)) {
|
|
84
|
+
deepMerge(elementProp, protoProp)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// console.groupEnd('deepMerge:')
|
|
88
|
+
return element
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const clone = obj => {
|
|
92
|
+
const o = {}
|
|
93
|
+
for (const prop in obj) {
|
|
94
|
+
if (prop === 'node') continue
|
|
95
|
+
o[prop] = obj[prop]
|
|
96
|
+
}
|
|
97
|
+
return o
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Deep cloning of object
|
|
102
|
+
*/
|
|
103
|
+
export const deepClone = (obj, excluding = ['parent', 'node', '__element', '__root']) => {
|
|
104
|
+
const o = {}
|
|
105
|
+
for (const prop in obj) {
|
|
106
|
+
if (excluding.indexOf(prop) > -1) continue
|
|
107
|
+
let objProp = obj[prop]
|
|
108
|
+
if (prop === 'proto' && isArray(objProp)) {
|
|
109
|
+
objProp = mergeArray(objProp)
|
|
110
|
+
}
|
|
111
|
+
if (isObjectLike(objProp)) {
|
|
112
|
+
o[prop] = deepClone(objProp)
|
|
113
|
+
} else o[prop] = objProp
|
|
114
|
+
}
|
|
115
|
+
return o
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Overwrites object properties with another
|
|
120
|
+
*/
|
|
121
|
+
export const overwrite = (element, params, options) => {
|
|
122
|
+
const changes = {}
|
|
123
|
+
|
|
124
|
+
for (const e in params) {
|
|
125
|
+
if (e === 'props') continue
|
|
126
|
+
|
|
127
|
+
const elementProp = element[e]
|
|
128
|
+
const paramsProp = params[e]
|
|
129
|
+
|
|
130
|
+
if (paramsProp) {
|
|
131
|
+
element.__cached[e] = changes[e] = elementProp
|
|
132
|
+
element[e] = paramsProp
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (options.cleanExec) delete element.__exec[e]
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return changes
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Overwrites DEEPly object properties with another
|
|
143
|
+
*/
|
|
144
|
+
export const overwriteDeep = (obj, params, excluding = ['node', '__root']) => {
|
|
145
|
+
for (const e in params) {
|
|
146
|
+
if (excluding.indexOf(e) > -1) continue
|
|
147
|
+
const objProp = obj[e]
|
|
148
|
+
const paramsProp = params[e]
|
|
149
|
+
if (isObjectLike(objProp) && isObjectLike(paramsProp)) {
|
|
150
|
+
overwriteDeep(objProp, paramsProp)
|
|
151
|
+
} else if (paramsProp !== undefined) {
|
|
152
|
+
obj[e] = paramsProp
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return obj
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Overwrites object properties with another
|
|
160
|
+
*/
|
|
161
|
+
export const mergeIfExisted = (a, b) => {
|
|
162
|
+
if (isObjectLike(a) && isObjectLike(b)) return deepMerge(a, b)
|
|
163
|
+
return a || b
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Merges array prototypes
|
|
168
|
+
*/
|
|
169
|
+
export const mergeArray = (arr) => {
|
|
170
|
+
return arr.reduce((a, c) => deepMerge(a, deepClone(c)), {})
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Merges array prototypes
|
|
175
|
+
*/
|
|
176
|
+
export const mergeAndCloneIfArray = obj => {
|
|
177
|
+
return isArray(obj) ? mergeArray(obj) : deepClone(obj)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Overwrites object properties with another
|
|
182
|
+
*/
|
|
183
|
+
export const flattenRecursive = (param, prop, stack = []) => {
|
|
184
|
+
const objectized = mergeAndCloneIfArray(param)
|
|
185
|
+
stack.push(objectized)
|
|
186
|
+
|
|
187
|
+
const protoOfProto = objectized[prop]
|
|
188
|
+
if (protoOfProto) flattenRecursive(protoOfProto, prop, stack)
|
|
189
|
+
|
|
190
|
+
delete objectized[prop]
|
|
191
|
+
|
|
192
|
+
return stack
|
|
193
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { isArray, isFunction, isObject } from './object'
|
|
4
|
+
|
|
5
|
+
export const generateHash = () => Math.random().toString(36).substring(2)
|
|
6
|
+
|
|
7
|
+
// hashing
|
|
8
|
+
export const protoStackRegistry = {}
|
|
9
|
+
export const protoCachedRegistry = {}
|
|
10
|
+
|
|
11
|
+
window.protoStackRegistry = protoStackRegistry
|
|
12
|
+
window.protoCachedRegistry = protoCachedRegistry
|
|
13
|
+
|
|
14
|
+
export const getHashedProto = proto => {
|
|
15
|
+
return protoStackRegistry[proto.__hash]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const setHashedProto = (proto, stack) => {
|
|
19
|
+
const hash = generateHash()
|
|
20
|
+
proto.__hash = hash
|
|
21
|
+
protoStackRegistry[hash] = stack
|
|
22
|
+
return protoStackRegistry[hash]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const getProtoStackRegistry = (proto, stack) => {
|
|
26
|
+
if (proto.__hash) {
|
|
27
|
+
return stack.concat(getHashedProto(proto))
|
|
28
|
+
} else {
|
|
29
|
+
setHashedProto(proto, stack)
|
|
30
|
+
}
|
|
31
|
+
return stack // .concat(hashedProto)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// stacking
|
|
35
|
+
export const extractArrayProto = (proto, stack) => {
|
|
36
|
+
proto.forEach(each => flattenProto(each, stack))
|
|
37
|
+
return stack
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const deepProto = (proto, stack) => {
|
|
41
|
+
const protoOflattenProto = proto.proto
|
|
42
|
+
if (protoOflattenProto) {
|
|
43
|
+
flattenProto(protoOflattenProto, stack)
|
|
44
|
+
}
|
|
45
|
+
return stack
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const flattenProto = (proto, stack) => {
|
|
49
|
+
if (!proto) return stack
|
|
50
|
+
if (isArray(proto)) return extractArrayProto(proto, stack)
|
|
51
|
+
stack.push(proto)
|
|
52
|
+
if (proto.proto) deepProto(proto, stack)
|
|
53
|
+
return stack
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// merging
|
|
57
|
+
export const deepCloneProto = obj => {
|
|
58
|
+
const o = {}
|
|
59
|
+
for (const prop in obj) {
|
|
60
|
+
if (['parent', 'node', '__element', '__root', '__key'].indexOf(prop) > -1) continue
|
|
61
|
+
const objProp = obj[prop]
|
|
62
|
+
if (isObject(objProp)) {
|
|
63
|
+
o[prop] = deepCloneProto(objProp)
|
|
64
|
+
} else if (isArray(objProp)) {
|
|
65
|
+
o[prop] = objProp.map(x => x)
|
|
66
|
+
} else o[prop] = objProp
|
|
67
|
+
}
|
|
68
|
+
return o
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const deepMergeProto = (element, proto) => {
|
|
72
|
+
for (const e in proto) {
|
|
73
|
+
if (['parent', 'node', '__element', '__root'].indexOf(e) > -1) continue
|
|
74
|
+
const elementProp = element[e]
|
|
75
|
+
const protoProp = proto[e]
|
|
76
|
+
if (elementProp === undefined) {
|
|
77
|
+
element[e] = protoProp
|
|
78
|
+
} else if (isObject(elementProp) && isObject(protoProp)) {
|
|
79
|
+
deepMergeProto(elementProp, protoProp)
|
|
80
|
+
} else if (isArray(elementProp) && isArray(protoProp)) {
|
|
81
|
+
element[e] = elementProp.concat(protoProp)
|
|
82
|
+
} else if (isArray(elementProp) && isObject(protoProp)) {
|
|
83
|
+
const obj = deepMergeProto({}, elementProp)
|
|
84
|
+
element[e] = deepMergeProto(obj, protoProp)
|
|
85
|
+
} else if (elementProp === undefined && isFunction(protoProp)) {
|
|
86
|
+
element[e] = protoProp
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return element
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const cloneAndMergeArrayProto = stack => {
|
|
93
|
+
return stack.reduce((a, c) => {
|
|
94
|
+
return deepMergeProto(a, deepCloneProto(c))
|
|
95
|
+
}, {})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// joint stacks
|
|
99
|
+
export const jointStacks = (protoStack, childProtoStack) => {
|
|
100
|
+
return []
|
|
101
|
+
.concat(protoStack.slice(0, 1))
|
|
102
|
+
.concat(childProtoStack.slice(0, 1))
|
|
103
|
+
.concat(protoStack.slice(1))
|
|
104
|
+
.concat(childProtoStack.slice(1))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// init
|
|
108
|
+
export const getProtoStack = proto => {
|
|
109
|
+
if (!proto) return []
|
|
110
|
+
if (proto.__hash) return getHashedProto(proto)
|
|
111
|
+
const stack = flattenProto(proto, [])
|
|
112
|
+
// console.log(stack)
|
|
113
|
+
return getProtoStackRegistry(proto, stack)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export const getProtoMerged = proto => {
|
|
117
|
+
const stack = getProtoStack(proto)
|
|
118
|
+
return cloneAndMergeArrayProto(stack)
|
|
119
|
+
}
|
package/src/report.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
export const errors = {
|
|
4
|
+
en: {
|
|
5
|
+
DocumentNotDefined: {
|
|
6
|
+
title: 'Document is undefined',
|
|
7
|
+
description: 'To tweak with DOM, you should use browser.'
|
|
8
|
+
},
|
|
9
|
+
OverwriteToBuiltin: {
|
|
10
|
+
title: 'Overwriting to builtin method',
|
|
11
|
+
description: 'Overwriting a builtin method in the global define is not possible, please choose different name'
|
|
12
|
+
},
|
|
13
|
+
BrowserNotDefined: {
|
|
14
|
+
title: 'Can\'t recognize environment',
|
|
15
|
+
description: 'Environment should be browser application, that can run Javascript'
|
|
16
|
+
},
|
|
17
|
+
SetQuickPreferancesIsNotObject: {
|
|
18
|
+
title: 'Quick preferances object is required',
|
|
19
|
+
description: 'Please pass a plain object with "lang", "culture" and "area" properties'
|
|
20
|
+
},
|
|
21
|
+
InvalidParams: {
|
|
22
|
+
title: 'Params are invalid',
|
|
23
|
+
description: 'Please pass a plain object with "lang", "culture" and "area" properties'
|
|
24
|
+
},
|
|
25
|
+
CantCreateWithoutNode: {
|
|
26
|
+
title: 'You must provide node',
|
|
27
|
+
description: 'Can\'t create DOM element without setting node or text'
|
|
28
|
+
},
|
|
29
|
+
HTMLInvalidTag: {
|
|
30
|
+
title: 'Element tag name (or DOM nodeName) is invalid',
|
|
31
|
+
description: 'To create element, you must provide valid DOM node. See full list of them at here: http://www.w3schools.com/tags/'
|
|
32
|
+
},
|
|
33
|
+
HTMLInvalidAttr: {
|
|
34
|
+
title: 'Attibutes object is invalid',
|
|
35
|
+
description: 'Please pass a valid plain object to apply as an attributes for a DOM node'
|
|
36
|
+
},
|
|
37
|
+
HTMLInvalidData: {
|
|
38
|
+
title: 'Data object is invalid',
|
|
39
|
+
description: 'Please pass a valid plain object to apply as an dataset for a DOM node'
|
|
40
|
+
},
|
|
41
|
+
HTMLInvalidStyles: {
|
|
42
|
+
title: 'Styles object is invalid',
|
|
43
|
+
description: 'Please pass a valid plain object to apply as an style for a DOM node'
|
|
44
|
+
},
|
|
45
|
+
HTMLInvalidText: {
|
|
46
|
+
title: 'Text string is invalid',
|
|
47
|
+
description: 'Please pass a valid string to apply text to DOM node'
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const report = (err, arg, element) => {
|
|
53
|
+
const currentLang = 'en'
|
|
54
|
+
let errObj
|
|
55
|
+
if (err && typeof err === 'string') errObj = errors[currentLang][err]
|
|
56
|
+
|
|
57
|
+
return new Error(
|
|
58
|
+
`"${err}", "${arg}"\n\n`,
|
|
59
|
+
`${errObj.description}`,
|
|
60
|
+
element ? `\n\n${element}` : ''
|
|
61
|
+
)
|
|
62
|
+
}
|