domql 1.4.21 → 1.5.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/README.md +9 -9
- package/package.json +4 -4
- package/packages/router/index.js +1 -1
- package/src/element/create.js +15 -18
- package/src/element/extend.js +55 -0
- package/src/element/mixins/registry.js +4 -3
- package/src/element/props.js +4 -4
- package/src/element/set.js +7 -11
- package/src/utils/extendUtils.js +116 -0
- package/src/utils/index.js +1 -1
- package/src/utils/node.js +1 -1
- package/src/utils/object.js +31 -11
- package/src/element/proto.js +0 -55
- package/src/utils/protoUtils.js +0 -116
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ var Link = {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
var ListItem = {
|
|
43
|
-
|
|
43
|
+
extend: Link,
|
|
44
44
|
class: 'ui link',
|
|
45
45
|
attr: {
|
|
46
46
|
href: '#'
|
|
@@ -48,7 +48,7 @@ var ListItem = {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
var menu = {
|
|
51
|
-
|
|
51
|
+
childExtend: ListItem,
|
|
52
52
|
home: 'Home',
|
|
53
53
|
text: 'About'
|
|
54
54
|
}
|
|
@@ -62,7 +62,7 @@ var header = {
|
|
|
62
62
|
var navItems = ['Home', 'About', 'FAQ', 'Contact']
|
|
63
63
|
|
|
64
64
|
var menu = {
|
|
65
|
-
|
|
65
|
+
extend: ListItem,
|
|
66
66
|
...navItems
|
|
67
67
|
}
|
|
68
68
|
```
|
|
@@ -89,8 +89,8 @@ var Increment = {
|
|
|
89
89
|
| Property | Type | Description | Default |
|
|
90
90
|
| --- | --- | --- | --- |
|
|
91
91
|
| `key` | `Number` `String` | Defines the key of the Element | The key of the object, or randomly generated name |
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
92
|
+
| `extend` | `Object` `Array` | Clones the other element | `undefined` |
|
|
93
|
+
| `childExtend` | `Object` `Array` | Specifies the `extend` for all child elements | `undefined` |
|
|
94
94
|
| `tag` | `String` | Specifis the HTML tag | `div` or related HTML tag if the key matches |
|
|
95
95
|
| `class` | `Any` | Specifies the HTML class | `undefined` |
|
|
96
96
|
| `attr` | `Object` | Specifies the set of HTML attributes | `{}` |
|
|
@@ -108,7 +108,7 @@ var User = {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
var Contact = {
|
|
111
|
-
|
|
111
|
+
extend: User,
|
|
112
112
|
username: 'nikoloza'
|
|
113
113
|
}
|
|
114
114
|
```
|
|
@@ -131,7 +131,7 @@ All native DOM events are supported and can be specified inside `on` parameter.
|
|
|
131
131
|
key
|
|
132
132
|
tag
|
|
133
133
|
node
|
|
134
|
-
|
|
134
|
+
extend
|
|
135
135
|
on
|
|
136
136
|
class
|
|
137
137
|
text
|
|
@@ -143,14 +143,14 @@ set
|
|
|
143
143
|
define
|
|
144
144
|
```
|
|
145
145
|
|
|
146
|
-
Anything except these keywords will create a new nested child element. The easier method to specify HTML tag is to use related nodeName as a key, for example:
|
|
146
|
+
Anything except these keywords will create a new nested child element. The easier method to specify HTML tag is to use related nodeName as a key, for example:
|
|
147
147
|
|
|
148
148
|
```javascript
|
|
149
149
|
var layout = { // this will be <div>
|
|
150
150
|
header: {}, // will create <header>
|
|
151
151
|
aside: {}, // will create <aside>
|
|
152
152
|
main: { // will create <main>
|
|
153
|
-
|
|
153
|
+
childExtend: {
|
|
154
154
|
article: { // will create <article>
|
|
155
155
|
title: {}, // will create <div>
|
|
156
156
|
description: {}, // will create <div>
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "DOM rendering Javascript framework at early stage.",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "rackai",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.5.1",
|
|
7
7
|
"repository": "https://github.com/rackai/domql",
|
|
8
8
|
"publishConfig": {
|
|
9
9
|
"registry": "https://registry.npmjs.org"
|
|
@@ -31,14 +31,14 @@
|
|
|
31
31
|
"@babel/preset-env": "^7.16.4",
|
|
32
32
|
"@emotion/css": "^11.10.0",
|
|
33
33
|
"@parcel/babel-preset-env": "^2.0.1",
|
|
34
|
-
"babel-jest": "^
|
|
35
|
-
"esbuild": "^0.
|
|
34
|
+
"babel-jest": "^29.0.0",
|
|
35
|
+
"esbuild": "^0.15.5",
|
|
36
36
|
"eslint": "^8.4.0",
|
|
37
37
|
"eslint-config-standard": "^17.0.0",
|
|
38
38
|
"eslint-plugin-import": "^2.25.3",
|
|
39
39
|
"eslint-plugin-jest": "^26.8.2",
|
|
40
40
|
"eslint-plugin-node": "^11.1.0",
|
|
41
|
-
"jest": "^
|
|
41
|
+
"jest": "^29.0.0",
|
|
42
42
|
"jsdom": "^19.0.0",
|
|
43
43
|
"nodemon": "^2.0.6",
|
|
44
44
|
"np": "^7.2.0",
|
package/packages/router/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export default (rootElement, path, state = {}, level = 0, pushState = true) => {
|
|
|
10
10
|
|
|
11
11
|
if (content) {
|
|
12
12
|
if (pushState) window.history.pushState(state, null, route)
|
|
13
|
-
rootElement.set({
|
|
13
|
+
rootElement.set({ extend: content })
|
|
14
14
|
.node.scrollIntoView({ behavior: 'smooth' })
|
|
15
15
|
}
|
|
16
16
|
|
package/src/element/create.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import root from './root'
|
|
4
4
|
import createNode from './node'
|
|
5
5
|
import { appendNode, assignNode } from './assign'
|
|
6
|
-
import {
|
|
6
|
+
import { applyExtend } from './extend'
|
|
7
7
|
import nodes from './nodes'
|
|
8
8
|
import set from './set'
|
|
9
9
|
import createState from './state'
|
|
@@ -27,17 +27,17 @@ const create = (element, parent, key, options = {}) => {
|
|
|
27
27
|
if (element === undefined) element = {}
|
|
28
28
|
if (element === null) return
|
|
29
29
|
|
|
30
|
-
// if element is
|
|
30
|
+
// if element is extend
|
|
31
31
|
if (element.__hash) {
|
|
32
|
-
element = {
|
|
32
|
+
element = { extend: element }
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
if (options.components) {
|
|
36
36
|
const { components } = options
|
|
37
|
-
const {
|
|
38
|
-
if (isString(
|
|
39
|
-
if (components[
|
|
40
|
-
else console.warn(
|
|
37
|
+
const { extend, component } = element
|
|
38
|
+
if (isString(extend))
|
|
39
|
+
if (components[extend]) element.extend = components[extend]
|
|
40
|
+
else console.warn(extend, 'is not in library', components, element)
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// define KEY
|
|
@@ -45,24 +45,24 @@ const create = (element, parent, key, options = {}) => {
|
|
|
45
45
|
|
|
46
46
|
// if PARENT is not given
|
|
47
47
|
if (!parent) parent = root
|
|
48
|
-
if (isNode(parent)) parent = root[`${key}_parent`] = { node: parent }
|
|
48
|
+
if (isNode(parent)) parent = root[`${key}_parent`] = { key: ':root', node: parent }
|
|
49
49
|
|
|
50
50
|
// if element is STRING
|
|
51
51
|
if (isString(element) || isNumber(element)) {
|
|
52
52
|
element = {
|
|
53
53
|
text: element,
|
|
54
|
-
tag: (!element.
|
|
54
|
+
tag: (!element.extend && parent.childExtend && parent.childExtend.tag) ||
|
|
55
55
|
((nodes.body.indexOf(key) > -1) && key) || 'string'
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// create
|
|
59
|
+
// create EXTENDal inheritance
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
applyExtend(element, parent, options)
|
|
62
62
|
|
|
63
63
|
if (Object.keys(options).length) {
|
|
64
64
|
registry.defaultOptions = options
|
|
65
|
-
if (options.
|
|
65
|
+
if (options.ignoreChildExtend) delete options.ignoreChildExtend
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
// enable STATE
|
|
@@ -137,12 +137,6 @@ const create = (element, parent, key, options = {}) => {
|
|
|
137
137
|
// generate a CLASS name
|
|
138
138
|
assignClass(element)
|
|
139
139
|
|
|
140
|
-
// console.group('create')
|
|
141
|
-
// console.log(element.path)
|
|
142
|
-
// console.log(element)
|
|
143
|
-
// console.groupEnd('create')
|
|
144
|
-
// if (parent.key === 'footer' && key === '0') debugger
|
|
145
|
-
|
|
146
140
|
// CREATE a real NODE
|
|
147
141
|
createNode(element, options)
|
|
148
142
|
|
|
@@ -151,6 +145,9 @@ const create = (element, parent, key, options = {}) => {
|
|
|
151
145
|
// assign NODE
|
|
152
146
|
assignNode(element, parent, key)
|
|
153
147
|
|
|
148
|
+
console.log(key, element)
|
|
149
|
+
console.log(element.path)
|
|
150
|
+
|
|
154
151
|
// run `on.render`
|
|
155
152
|
if (element.on && isFunction(element.on.render)) {
|
|
156
153
|
on.render(element.on.render, element, element.state)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { isFunction, exec, getExtendStack, jointStacks, cloneAndMergeArrayExtend, deepMergeExtend } from '../utils'
|
|
4
|
+
|
|
5
|
+
const ENV = process.env.NODE_ENV
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Checks whether element has `extend` or is a part
|
|
9
|
+
* of parent's `childExtend` extend
|
|
10
|
+
*/
|
|
11
|
+
export const applyExtend = (element, parent, options = {}) => {
|
|
12
|
+
if (isFunction(element)) element = exec(element, parent)
|
|
13
|
+
|
|
14
|
+
const { extend } = element
|
|
15
|
+
const extendStack = getExtendStack(extend)
|
|
16
|
+
|
|
17
|
+
if (ENV !== 'test' || ENV !== 'development') delete element.extend
|
|
18
|
+
|
|
19
|
+
let childExtendStack = []
|
|
20
|
+
if (parent) {
|
|
21
|
+
// Assign parent attr to the element
|
|
22
|
+
element.parent = parent
|
|
23
|
+
if (!options.ignoreChildExtend) {
|
|
24
|
+
childExtendStack = getExtendStack(parent.childExtend)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const extendLength = extendStack.length
|
|
29
|
+
const childExtendLength = childExtendStack.length
|
|
30
|
+
|
|
31
|
+
let stack = []
|
|
32
|
+
if (extendLength && childExtendLength) {
|
|
33
|
+
stack = jointStacks(extendStack, childExtendStack)
|
|
34
|
+
} else if (extendLength) {
|
|
35
|
+
stack = extendStack
|
|
36
|
+
} else if (childExtendLength) {
|
|
37
|
+
stack = childExtendStack
|
|
38
|
+
} else if (!options.extend) return element
|
|
39
|
+
|
|
40
|
+
if (options.extend) {
|
|
41
|
+
const defaultOptionsExtend = getExtendStack(options.extend)
|
|
42
|
+
stack = [].concat(stack, defaultOptionsExtend)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
element.__extend = stack
|
|
46
|
+
let mergedExtend = cloneAndMergeArrayExtend(stack)
|
|
47
|
+
|
|
48
|
+
const component = exec(element.component || mergedExtend.component, element)
|
|
49
|
+
if (component && options.components && options.components[component]) {
|
|
50
|
+
const componentExtend = cloneAndMergeArrayExtend(getExtendStack(options.components[component]))
|
|
51
|
+
mergedExtend = deepMergeExtend(componentExtend, mergedExtend)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return deepMergeExtend(element, mergedExtend)
|
|
55
|
+
}
|
|
@@ -21,10 +21,10 @@ export default {
|
|
|
21
21
|
class: classList,
|
|
22
22
|
state,
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
extend: {},
|
|
25
|
+
childExtend: {},
|
|
25
26
|
props: {},
|
|
26
27
|
path: {},
|
|
27
|
-
childProto: {},
|
|
28
28
|
if: {},
|
|
29
29
|
define: {},
|
|
30
30
|
transform: {},
|
|
@@ -36,9 +36,10 @@ export default {
|
|
|
36
36
|
__trash: {},
|
|
37
37
|
__root: {},
|
|
38
38
|
__props: {},
|
|
39
|
-
|
|
39
|
+
__extend: {},
|
|
40
40
|
__ifFragment: {},
|
|
41
41
|
__ifFalsy: {},
|
|
42
|
+
__text: {},
|
|
42
43
|
key: {},
|
|
43
44
|
tag: {},
|
|
44
45
|
parent: {},
|
package/src/element/props.js
CHANGED
|
@@ -37,10 +37,10 @@ const initProps = (element, parent) => {
|
|
|
37
37
|
propsStack.push(matchParentValue)
|
|
38
38
|
} else if (props) propsStack.push(props)
|
|
39
39
|
|
|
40
|
-
if (isArray(element.
|
|
41
|
-
element.
|
|
42
|
-
if (
|
|
43
|
-
return
|
|
40
|
+
if (isArray(element.__extend)) {
|
|
41
|
+
element.__extend.map(extend => {
|
|
42
|
+
if (extend.props) propsStack.push(extend.props)
|
|
43
|
+
return extend.props
|
|
44
44
|
})
|
|
45
45
|
}
|
|
46
46
|
|
package/src/element/set.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
import create from './create'
|
|
4
|
+
import { isEqualDeep } from '../utils'
|
|
4
5
|
import { registry } from './mixins'
|
|
5
6
|
|
|
6
7
|
const removeContentElement = (params, element) => {
|
|
@@ -22,13 +23,16 @@ const removeContentElement = (params, element) => {
|
|
|
22
23
|
const set = function (params, options) {
|
|
23
24
|
const element = this
|
|
24
25
|
|
|
26
|
+
const isEqual = isEqualDeep(params, element.content)
|
|
27
|
+
if (isEqual && element.content.__cached) return element
|
|
28
|
+
|
|
25
29
|
removeContentElement(params, element)
|
|
26
30
|
|
|
27
31
|
if (params) {
|
|
28
|
-
const {
|
|
29
|
-
if (!
|
|
32
|
+
const { childExtend } = params
|
|
33
|
+
if (!childExtend && element.childExtend) params.childExtend = element.childExtend
|
|
30
34
|
create(params, element, 'content', {
|
|
31
|
-
|
|
35
|
+
ignoreChildExtend: true,
|
|
32
36
|
...registry.defaultOptions
|
|
33
37
|
})
|
|
34
38
|
}
|
|
@@ -38,11 +42,3 @@ const set = function (params, options) {
|
|
|
38
42
|
|
|
39
43
|
export default set
|
|
40
44
|
|
|
41
|
-
// if (element.content && (isFunction(element.content) || element.content.node)) {
|
|
42
|
-
// // leave(element, () => {
|
|
43
|
-
// // console.log('remove', element.content)
|
|
44
|
-
// // element.content.remove()
|
|
45
|
-
// // element.content.update(params)
|
|
46
|
-
// // element.node.removeChild(element.content.node)
|
|
47
|
-
// // delete element.content
|
|
48
|
-
// }
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { exec, isArray, isFunction, isObject } from './object'
|
|
4
|
+
|
|
5
|
+
export const generateHash = () => Math.random().toString(36).substring(2)
|
|
6
|
+
|
|
7
|
+
// hashing
|
|
8
|
+
export const extendStackRegistry = {}
|
|
9
|
+
export const extendCachedRegistry = {}
|
|
10
|
+
|
|
11
|
+
window.extendStackRegistry = extendStackRegistry
|
|
12
|
+
window.extendCachedRegistry = extendCachedRegistry
|
|
13
|
+
|
|
14
|
+
export const getHashedExtend = extend => {
|
|
15
|
+
return extendStackRegistry[extend.__hash]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const setHashedExtend = (extend, stack) => {
|
|
19
|
+
const hash = generateHash()
|
|
20
|
+
extend.__hash = hash
|
|
21
|
+
extendStackRegistry[hash] = stack
|
|
22
|
+
return stack
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const getExtendStackRegistry = (extend, stack) => {
|
|
26
|
+
if (extend.__hash)
|
|
27
|
+
return stack.concat(getHashedExtend(extend))
|
|
28
|
+
return setHashedExtend(extend, stack) // stack .concat(hashedExtend)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// stacking
|
|
32
|
+
export const extractArrayExtend = (extend, stack) => {
|
|
33
|
+
extend.forEach(each => flattenExtend(each, stack))
|
|
34
|
+
return stack
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const deepExtend = (extend, stack) => {
|
|
38
|
+
const extendOflattenExtend = extend.extend
|
|
39
|
+
if (extendOflattenExtend) {
|
|
40
|
+
flattenExtend(extendOflattenExtend, stack)
|
|
41
|
+
}
|
|
42
|
+
return stack
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const flattenExtend = (extend, stack) => {
|
|
46
|
+
if (!extend) return stack
|
|
47
|
+
if (isArray(extend)) return extractArrayExtend(extend, stack)
|
|
48
|
+
stack.push(extend)
|
|
49
|
+
if (extend.extend) deepExtend(extend, stack)
|
|
50
|
+
return stack
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// merging
|
|
54
|
+
export const deepCloneExtend = obj => {
|
|
55
|
+
const o = {}
|
|
56
|
+
for (const prop in obj) {
|
|
57
|
+
if (['parent', 'node', '__element', '__root', '__key'].indexOf(prop) > -1) continue
|
|
58
|
+
const objProp = obj[prop]
|
|
59
|
+
if (isObject(objProp)) {
|
|
60
|
+
o[prop] = deepCloneExtend(objProp)
|
|
61
|
+
} else if (isArray(objProp)) {
|
|
62
|
+
o[prop] = objProp.map(x => x)
|
|
63
|
+
} else o[prop] = objProp
|
|
64
|
+
}
|
|
65
|
+
return o
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const deepMergeExtend = (element, extend) => {
|
|
69
|
+
for (const e in extend) {
|
|
70
|
+
if (['parent', 'node', '__element', '__root'].indexOf(e) > -1) continue
|
|
71
|
+
const elementProp = element[e]
|
|
72
|
+
const extendProp = extend[e]
|
|
73
|
+
if (elementProp === undefined) {
|
|
74
|
+
element[e] = extendProp
|
|
75
|
+
} else if (isObject(elementProp) && isObject(extendProp)) {
|
|
76
|
+
deepMergeExtend(elementProp, extendProp)
|
|
77
|
+
} else if (isArray(elementProp) && isArray(extendProp)) {
|
|
78
|
+
element[e] = elementProp.concat(extendProp)
|
|
79
|
+
} else if (isArray(elementProp) && isObject(extendProp)) {
|
|
80
|
+
const obj = deepMergeExtend({}, elementProp)
|
|
81
|
+
element[e] = deepMergeExtend(obj, extendProp)
|
|
82
|
+
} else if (elementProp === undefined && isFunction(extendProp)) {
|
|
83
|
+
element[e] = extendProp
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return element
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const cloneAndMergeArrayExtend = stack => {
|
|
90
|
+
return stack.reduce((a, c) => {
|
|
91
|
+
return deepMergeExtend(a, deepCloneExtend(c))
|
|
92
|
+
}, {})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// joint stacks
|
|
96
|
+
export const jointStacks = (extendStack, childExtendStack) => {
|
|
97
|
+
return []
|
|
98
|
+
.concat(extendStack.slice(0, 1))
|
|
99
|
+
.concat(childExtendStack.slice(0, 1))
|
|
100
|
+
.concat(extendStack.slice(1))
|
|
101
|
+
.concat(childExtendStack.slice(1))
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// init
|
|
105
|
+
export const getExtendStack = extend => {
|
|
106
|
+
if (!extend) return []
|
|
107
|
+
if (extend.__hash) return getHashedExtend(extend)
|
|
108
|
+
const stack = flattenExtend(extend, [])
|
|
109
|
+
// console.log(stack)
|
|
110
|
+
return getExtendStackRegistry(extend, stack)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export const getExtendMerged = extend => {
|
|
114
|
+
const stack = getExtendStack(extend)
|
|
115
|
+
return cloneAndMergeArrayExtend(stack)
|
|
116
|
+
}
|
package/src/utils/index.js
CHANGED
package/src/utils/node.js
CHANGED
package/src/utils/object.js
CHANGED
|
@@ -71,17 +71,17 @@ export const merge = (element, obj) => {
|
|
|
71
71
|
return element
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
export const deepMerge = (element,
|
|
74
|
+
export const deepMerge = (element, extend) => {
|
|
75
75
|
// console.groupCollapsed('deepMerge:')
|
|
76
|
-
for (const e in
|
|
76
|
+
for (const e in extend) {
|
|
77
77
|
const elementProp = element[e]
|
|
78
|
-
const
|
|
78
|
+
const extendProp = extend[e]
|
|
79
79
|
// const cachedProps = cache.props
|
|
80
80
|
if (e === 'parent' || e === 'props' || e === 'state') continue
|
|
81
81
|
if (elementProp === undefined) {
|
|
82
|
-
element[e] =
|
|
83
|
-
} else if (isObjectLike(elementProp) && isObject(
|
|
84
|
-
deepMerge(elementProp,
|
|
82
|
+
element[e] = extendProp
|
|
83
|
+
} else if (isObjectLike(elementProp) && isObject(extendProp)) {
|
|
84
|
+
deepMerge(elementProp, extendProp)
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
// console.groupEnd('deepMerge:')
|
|
@@ -105,7 +105,7 @@ export const deepClone = (obj, excluding = ['parent', 'node', '__element', '__ro
|
|
|
105
105
|
for (const prop in obj) {
|
|
106
106
|
if (excluding.indexOf(prop) > -1) continue
|
|
107
107
|
let objProp = obj[prop]
|
|
108
|
-
if (prop === '
|
|
108
|
+
if (prop === 'extend' && isArray(objProp)) {
|
|
109
109
|
objProp = mergeArray(objProp)
|
|
110
110
|
}
|
|
111
111
|
if (isObjectLike(objProp)) {
|
|
@@ -115,6 +115,26 @@ export const deepClone = (obj, excluding = ['parent', 'node', '__element', '__ro
|
|
|
115
115
|
return o
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Overwrites object properties with another
|
|
120
|
+
*/
|
|
121
|
+
export const isEqualDeep = (param, element) => {
|
|
122
|
+
if (param === element) return true
|
|
123
|
+
if (!param || !element) return false
|
|
124
|
+
for (const prop in param) {
|
|
125
|
+
const paramProp = param[prop]
|
|
126
|
+
const elementProp = element[prop]
|
|
127
|
+
if (isObjectLike(paramProp)) {
|
|
128
|
+
const isEqual = isEqualDeep(paramProp, elementProp)
|
|
129
|
+
if (!isEqual) return false
|
|
130
|
+
} else {
|
|
131
|
+
const isEqual = paramProp === elementProp
|
|
132
|
+
if (!isEqual) return false
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return true
|
|
136
|
+
}
|
|
137
|
+
|
|
118
138
|
/**
|
|
119
139
|
* Overwrites object properties with another
|
|
120
140
|
*/
|
|
@@ -164,14 +184,14 @@ export const mergeIfExisted = (a, b) => {
|
|
|
164
184
|
}
|
|
165
185
|
|
|
166
186
|
/**
|
|
167
|
-
* Merges array
|
|
187
|
+
* Merges array extends
|
|
168
188
|
*/
|
|
169
189
|
export const mergeArray = (arr) => {
|
|
170
190
|
return arr.reduce((a, c) => deepMerge(a, deepClone(c)), {})
|
|
171
191
|
}
|
|
172
192
|
|
|
173
193
|
/**
|
|
174
|
-
* Merges array
|
|
194
|
+
* Merges array extends
|
|
175
195
|
*/
|
|
176
196
|
export const mergeAndCloneIfArray = obj => {
|
|
177
197
|
return isArray(obj) ? mergeArray(obj) : deepClone(obj)
|
|
@@ -184,8 +204,8 @@ export const flattenRecursive = (param, prop, stack = []) => {
|
|
|
184
204
|
const objectized = mergeAndCloneIfArray(param)
|
|
185
205
|
stack.push(objectized)
|
|
186
206
|
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
207
|
+
const extendOfExtend = objectized[prop]
|
|
208
|
+
if (extendOfExtend) flattenRecursive(extendOfExtend, prop, stack)
|
|
189
209
|
|
|
190
210
|
delete objectized[prop]
|
|
191
211
|
|
package/src/element/proto.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import { isFunction, exec, getProtoStack, jointStacks, cloneAndMergeArrayProto, deepMergeProto } from '../utils'
|
|
4
|
-
|
|
5
|
-
const ENV = process.env.NODE_ENV
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Checks whether element has `proto` or is a part
|
|
9
|
-
* of parent's `childProto` prototype
|
|
10
|
-
*/
|
|
11
|
-
export const applyPrototype = (element, parent, options = {}) => {
|
|
12
|
-
if (isFunction(element)) element = exec(element, parent)
|
|
13
|
-
|
|
14
|
-
const { proto } = element
|
|
15
|
-
const protoStack = getProtoStack(proto)
|
|
16
|
-
|
|
17
|
-
if (ENV !== 'test' || ENV !== 'development') delete element.proto
|
|
18
|
-
|
|
19
|
-
let childProtoStack = []
|
|
20
|
-
if (parent) {
|
|
21
|
-
// Assign parent attr to the element
|
|
22
|
-
element.parent = parent
|
|
23
|
-
if (!options.ignoreChildProto) {
|
|
24
|
-
childProtoStack = getProtoStack(parent.childProto)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const protoLength = protoStack.length
|
|
29
|
-
const childProtoLength = childProtoStack.length
|
|
30
|
-
|
|
31
|
-
let stack = []
|
|
32
|
-
if (protoLength && childProtoLength) {
|
|
33
|
-
stack = jointStacks(protoStack, childProtoStack)
|
|
34
|
-
} else if (protoLength) {
|
|
35
|
-
stack = protoStack
|
|
36
|
-
} else if (childProtoLength) {
|
|
37
|
-
stack = childProtoStack
|
|
38
|
-
} else if (!options.proto) return element
|
|
39
|
-
|
|
40
|
-
if (options.proto) {
|
|
41
|
-
const defaultOptionsProto = getProtoStack(options.proto)
|
|
42
|
-
stack = [].concat(stack, defaultOptionsProto)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
element.__proto = stack
|
|
46
|
-
let mergedProto = cloneAndMergeArrayProto(stack)
|
|
47
|
-
|
|
48
|
-
const component = exec(element.component || mergedProto.component, element)
|
|
49
|
-
if (component && options.components && options.components[component]) {
|
|
50
|
-
const componentProto = cloneAndMergeArrayProto(getProtoStack(options.components[component]))
|
|
51
|
-
mergedProto = deepMergeProto(componentProto, mergedProto)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return deepMergeProto(element, mergedProto)
|
|
55
|
-
}
|
package/src/utils/protoUtils.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
import { exec, 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 stack
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const getProtoStackRegistry = (proto, stack) => {
|
|
26
|
-
if (proto.__hash)
|
|
27
|
-
return stack.concat(getHashedProto(proto))
|
|
28
|
-
return setHashedProto(proto, stack) // stack .concat(hashedProto)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// stacking
|
|
32
|
-
export const extractArrayProto = (proto, stack) => {
|
|
33
|
-
proto.forEach(each => flattenProto(each, stack))
|
|
34
|
-
return stack
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export const deepProto = (proto, stack) => {
|
|
38
|
-
const protoOflattenProto = proto.proto
|
|
39
|
-
if (protoOflattenProto) {
|
|
40
|
-
flattenProto(protoOflattenProto, stack)
|
|
41
|
-
}
|
|
42
|
-
return stack
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const flattenProto = (proto, stack) => {
|
|
46
|
-
if (!proto) return stack
|
|
47
|
-
if (isArray(proto)) return extractArrayProto(proto, stack)
|
|
48
|
-
stack.push(proto)
|
|
49
|
-
if (proto.proto) deepProto(proto, stack)
|
|
50
|
-
return stack
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// merging
|
|
54
|
-
export const deepCloneProto = obj => {
|
|
55
|
-
const o = {}
|
|
56
|
-
for (const prop in obj) {
|
|
57
|
-
if (['parent', 'node', '__element', '__root', '__key'].indexOf(prop) > -1) continue
|
|
58
|
-
const objProp = obj[prop]
|
|
59
|
-
if (isObject(objProp)) {
|
|
60
|
-
o[prop] = deepCloneProto(objProp)
|
|
61
|
-
} else if (isArray(objProp)) {
|
|
62
|
-
o[prop] = objProp.map(x => x)
|
|
63
|
-
} else o[prop] = objProp
|
|
64
|
-
}
|
|
65
|
-
return o
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export const deepMergeProto = (element, proto) => {
|
|
69
|
-
for (const e in proto) {
|
|
70
|
-
if (['parent', 'node', '__element', '__root'].indexOf(e) > -1) continue
|
|
71
|
-
const elementProp = element[e]
|
|
72
|
-
const protoProp = proto[e]
|
|
73
|
-
if (elementProp === undefined) {
|
|
74
|
-
element[e] = protoProp
|
|
75
|
-
} else if (isObject(elementProp) && isObject(protoProp)) {
|
|
76
|
-
deepMergeProto(elementProp, protoProp)
|
|
77
|
-
} else if (isArray(elementProp) && isArray(protoProp)) {
|
|
78
|
-
element[e] = elementProp.concat(protoProp)
|
|
79
|
-
} else if (isArray(elementProp) && isObject(protoProp)) {
|
|
80
|
-
const obj = deepMergeProto({}, elementProp)
|
|
81
|
-
element[e] = deepMergeProto(obj, protoProp)
|
|
82
|
-
} else if (elementProp === undefined && isFunction(protoProp)) {
|
|
83
|
-
element[e] = protoProp
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return element
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export const cloneAndMergeArrayProto = stack => {
|
|
90
|
-
return stack.reduce((a, c) => {
|
|
91
|
-
return deepMergeProto(a, deepCloneProto(c))
|
|
92
|
-
}, {})
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// joint stacks
|
|
96
|
-
export const jointStacks = (protoStack, childProtoStack) => {
|
|
97
|
-
return []
|
|
98
|
-
.concat(protoStack.slice(0, 1))
|
|
99
|
-
.concat(childProtoStack.slice(0, 1))
|
|
100
|
-
.concat(protoStack.slice(1))
|
|
101
|
-
.concat(childProtoStack.slice(1))
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// init
|
|
105
|
-
export const getProtoStack = proto => {
|
|
106
|
-
if (!proto) return []
|
|
107
|
-
if (proto.__hash) return getHashedProto(proto)
|
|
108
|
-
const stack = flattenProto(proto, [])
|
|
109
|
-
// console.log(stack)
|
|
110
|
-
return getProtoStackRegistry(proto, stack)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export const getProtoMerged = proto => {
|
|
114
|
-
const stack = getProtoStack(proto)
|
|
115
|
-
return cloneAndMergeArrayProto(stack)
|
|
116
|
-
}
|