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 CHANGED
@@ -40,7 +40,7 @@ var Link = {
40
40
  }
41
41
 
42
42
  var ListItem = {
43
- proto: Link,
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
- childProto: ListItem,
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
- proto: ListItem,
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
- | `proto` | `Object` `Array` | Clones the other element | `undefined` |
93
- | `childProto` | `Object` `Array` | Specifies the `proto` for all child elements | `undefined` |
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
- proto: User,
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
- proto
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
- childProto: {
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.4.21",
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": "^28.1.3",
35
- "esbuild": "^0.14.47",
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": "^27.4.4",
41
+ "jest": "^29.0.0",
42
42
  "jsdom": "^19.0.0",
43
43
  "nodemon": "^2.0.6",
44
44
  "np": "^7.2.0",
@@ -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({ proto: content })
13
+ rootElement.set({ extend: content })
14
14
  .node.scrollIntoView({ behavior: 'smooth' })
15
15
  }
16
16
 
@@ -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 { applyPrototype } from './proto'
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 proto
30
+ // if element is extend
31
31
  if (element.__hash) {
32
- element = { proto: element }
32
+ element = { extend: element }
33
33
  }
34
34
 
35
35
  if (options.components) {
36
36
  const { components } = options
37
- const { proto, component } = element
38
- if (isString(proto))
39
- if (components[proto]) element.proto = components[proto]
40
- else console.warn(proto, 'is not in library', components, element)
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.proto && parent.childProto && parent.childProto.tag) ||
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 PROTOtypal inheritance
59
+ // create EXTENDal inheritance
60
60
 
61
- applyPrototype(element, parent, options)
61
+ applyExtend(element, parent, options)
62
62
 
63
63
  if (Object.keys(options).length) {
64
64
  registry.defaultOptions = options
65
- if (options.ignoreChildProto) delete options.ignoreChildProto
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
- proto: {},
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
- __proto: {},
39
+ __extend: {},
40
40
  __ifFragment: {},
41
41
  __ifFalsy: {},
42
+ __text: {},
42
43
  key: {},
43
44
  tag: {},
44
45
  parent: {},
@@ -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.__proto)) {
41
- element.__proto.map(proto => {
42
- if (proto.props) propsStack.push(proto.props)
43
- return proto.props
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
 
@@ -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 { childProto } = params
29
- if (!childProto && element.childProto) params.childProto = element.childProto
32
+ const { childExtend } = params
33
+ if (!childExtend && element.childExtend) params.childExtend = element.childExtend
30
34
  create(params, element, 'content', {
31
- ignoreChildProto: true,
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
+ }
@@ -3,4 +3,4 @@
3
3
  export * from './report'
4
4
  export * from './object'
5
5
  export * from './node'
6
- export * from './protoUtils'
6
+ export * from './extendUtils'
package/src/utils/node.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- export const cleanWithNode = proto => delete proto.node && proto
3
+ export const cleanWithNode = extend => delete extend.node && extend
4
4
 
5
5
  export const createID = (function * () {
6
6
  let index = 1
@@ -71,17 +71,17 @@ export const merge = (element, obj) => {
71
71
  return element
72
72
  }
73
73
 
74
- export const deepMerge = (element, proto) => {
74
+ export const deepMerge = (element, extend) => {
75
75
  // console.groupCollapsed('deepMerge:')
76
- for (const e in proto) {
76
+ for (const e in extend) {
77
77
  const elementProp = element[e]
78
- const protoProp = proto[e]
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] = protoProp
83
- } else if (isObjectLike(elementProp) && isObject(protoProp)) {
84
- deepMerge(elementProp, protoProp)
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 === 'proto' && isArray(objProp)) {
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 prototypes
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 prototypes
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 protoOfProto = objectized[prop]
188
- if (protoOfProto) flattenRecursive(protoOfProto, prop, stack)
207
+ const extendOfExtend = objectized[prop]
208
+ if (extendOfExtend) flattenRecursive(extendOfExtend, prop, stack)
189
209
 
190
210
  delete objectized[prop]
191
211
 
@@ -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
- }
@@ -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
- }