domql 1.5.16 → 1.5.18

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 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.5.16",
6
+ "version": "1.5.18",
7
7
  "repository": "https://github.com/rackai/domql",
8
8
  "publishConfig": {
9
9
  "registry": "https://registry.npmjs.org"
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  import DOM from '../../src'
4
- import { isObjectLike, exec, isObject } from '../../src/utils'
4
+ import { isObjectLike, exec, isObject, isEqualDeep } from '../../src/utils'
5
5
  import { classList } from '../../src/element/mixins'
6
6
  import createEmotion from '@emotion/css/create-instance'
7
7
  const ENV = process.env.NODE_ENV
@@ -30,11 +30,13 @@ export const initEmotion = (container, options) => {
30
30
  }
31
31
 
32
32
  const classf = (params, element, node) => {
33
+ const { __class } = element
33
34
  if (isObjectLike(params)) {
34
35
  const classObjHelper = {}
35
36
  for (const key in params) {
36
37
  const prop = exec(params[key], element)
37
- if (!prop) continue
38
+ if (!prop && prop === __class[key]) continue
39
+ __class[key] = prop
38
40
  if ((ENV === 'test' || ENV === 'development') && isObject(prop)) prop.label = key || element.key
39
41
  const CSSed = css(prop)
40
42
  classObjHelper[key] = CSSed
@@ -12,7 +12,7 @@ import update from './update'
12
12
  import * as on from '../event/on'
13
13
  import { assignClass } from './mixins/classList'
14
14
  import { isFunction, isNumber, isString, createID, isNode, exec } from '../utils'
15
- import { remove, lookup, setProps, log, keys, parse, parseDeep } from './methods'
15
+ import { remove, lookup, setProps, log, keys, parse, parseDeep, spotByPath } from './methods'
16
16
  import cacheNode from './cache'
17
17
  import { registry } from './mixins'
18
18
  // import { overwrite, clone, fillTheRest } from '../utils'
@@ -83,21 +83,30 @@ const create = (element, parent, key, options = {}) => {
83
83
  if (options.ignoreChildExtend) delete options.ignoreChildExtend
84
84
  }
85
85
 
86
- // enable STATE
87
- element.state = createState(element, parent)
88
-
89
86
  // create and assign a KEY
90
87
  element.key = assignedKey
91
88
 
92
- // don't render IF in condition
93
- if (isFunction(element.if)) {
94
- // TODO: move as fragment
95
- if (!element.if(element, element.state)) {
96
- const ifFragment = cacheNode({ tag: 'fragment' })
97
- element.__ifFragment = appendNode(ifFragment, parent.node)
98
- element.__ifFalsy = true
99
- }
100
- }
89
+ // enable TRANSFORM in data
90
+ if (!element.transform) element.transform = {}
91
+
92
+ // enable CACHING
93
+ if (!element.__cached) element.__cached = {}
94
+
95
+ // enable EXEC
96
+ if (!element.__exec) element.__exec = {}
97
+
98
+ // enable CLASS CACHING
99
+ if (!element.__class) element.__class = {}
100
+
101
+ // enable CHANGES storing
102
+ if (!element.__changes) element.__changes = []
103
+
104
+ // enable CHANGES storing
105
+ if (!element.__children) element.__children = []
106
+
107
+ // Add _root element property
108
+ const hasRoot = parent.parent && parent.parent.key === ':root'
109
+ if (!element.__root) element.__root = hasRoot ? parent : parent.__root
101
110
 
102
111
  // set the PATH array
103
112
  if (ENV === 'test' || ENV === 'development') {
@@ -105,11 +114,6 @@ const create = (element, parent, key, options = {}) => {
105
114
  element.path = parent.path.concat(assignedKey)
106
115
  }
107
116
 
108
- // if it already HAS a NODE
109
- if (element.node && !element.__ifFalsy) { // TODO: check on if
110
- return assignNode(element, parent, assignedKey)
111
- }
112
-
113
117
  // assign METHODS
114
118
  element.set = set
115
119
  element.update = update
@@ -117,6 +121,7 @@ const create = (element, parent, key, options = {}) => {
117
121
  element.removeContent = removeContentElement
118
122
  element.setProps = setProps
119
123
  element.lookup = lookup
124
+ element.spotByPath = spotByPath
120
125
  element.parse = parse
121
126
  element.parseDeep = parseDeep
122
127
  element.keys = keys
@@ -124,24 +129,23 @@ const create = (element, parent, key, options = {}) => {
124
129
  element.log = log
125
130
  }
126
131
 
127
- // enable TRANSFORM in data
128
- if (!element.transform) element.transform = {}
129
-
130
- // enable CACHING
131
- if (!element.__cached) element.__cached = {}
132
-
133
- // enable EXEC
134
- if (!element.__exec) element.__exec = {}
135
-
136
- // enable CHANGES storing
137
- if (!element.__changes) element.__changes = []
132
+ // enable STATE
133
+ element.state = createState(element, parent)
138
134
 
139
- // enable CHANGES storing
140
- if (!element.__children) element.__children = []
135
+ // don't render IF in condition
136
+ if (isFunction(element.if)) {
137
+ // TODO: move as fragment
138
+ if (!element.if(element, element.state)) {
139
+ const ifFragment = cacheNode({ tag: 'fragment' })
140
+ element.__ifFragment = appendNode(ifFragment, parent.node)
141
+ element.__ifFalsy = true
142
+ }
143
+ }
141
144
 
142
- // Add _root element property
143
- const hasRoot = parent.parent && parent.parent.key === ':root'
144
- if (!element.__root) element.__root = hasRoot ? parent : parent.__root
145
+ // if it already HAS a NODE
146
+ if (element.node && !element.__ifFalsy) { // TODO: check on if
147
+ return assignNode(element, parent, assignedKey)
148
+ }
145
149
 
146
150
  // apply props settings
147
151
  if (!element.__ifFalsy) createProps(element, parent)
@@ -173,6 +177,7 @@ const create = (element, parent, key, options = {}) => {
173
177
  }
174
178
 
175
179
  if (parent.__children) parent.__children.push(element.key)
180
+ // console.groupEnd(element.key)
176
181
 
177
182
  return element
178
183
  }
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { isFunction, isObject, isObjectLike } from '../utils'
4
4
  import { registry } from './mixins'
5
+ import root from './root'
5
6
  import { removeContentElement } from './set'
6
7
 
7
8
  const ENV = process.env.NODE_ENV
@@ -20,6 +21,24 @@ export const lookup = function (key) {
20
21
  return parent
21
22
  }
22
23
 
24
+ // TODO: update these files
25
+ export const spotByPath = function (path) {
26
+ const element = this
27
+ const arr = [].concat(path)
28
+ let active = root[arr[0]]
29
+
30
+ if (!arr || !arr.length) return console.log(arr, 'on', element.key, 'is undefined')
31
+
32
+ while (active.key === arr[0]) {
33
+ arr.shift()
34
+ if (!arr.length) break
35
+ active = active[arr[0]]
36
+ if (!active) return
37
+ }
38
+
39
+ return active
40
+ }
41
+
23
42
  export const remove = function (params) {
24
43
  const element = this
25
44
  if (isFunction(element.node.remove)) element.node.remove()
@@ -104,6 +123,7 @@ export const isMethod = function (param) {
104
123
  param === 'remove' ||
105
124
  param === 'removeContent' ||
106
125
  param === 'lookup' ||
126
+ param === 'spotByPath' ||
107
127
  param === 'keys' ||
108
128
  param === 'parse' ||
109
129
  param === 'setProps' ||
@@ -26,12 +26,13 @@ export const classify = (obj, element) => {
26
26
 
27
27
  export default (params, element, node) => {
28
28
  if (!params) return
29
- const { key } = element
29
+ const { key, __className } = element
30
30
  if (params === true) params = element.class = { key }
31
31
  if (isString(params)) params = element.class = { default: params }
32
32
  if (isObject(params)) params = classify(params, element)
33
33
  // TODO: fails on string
34
34
  const className = params.replace(/\s+/g, ' ').trim()
35
- node.classList = className
35
+ if (className && className !== __className) node.classList = className
36
+ element.__className = className
36
37
  return className
37
38
  }
@@ -9,6 +9,8 @@ import set from '../set'
9
9
  export default (param, element, node, options) => {
10
10
  if (param && element) {
11
11
  if (param.__hash === element.content.__hash && element.content.update) {
12
+ const { define } = element
13
+ // if (define && !define.$setStateCollection)
12
14
  element.content.update(param)
13
15
  } else {
14
16
  set.call(element, param, options)
@@ -8,10 +8,12 @@ import { exec } from '../../utils'
8
8
  */
9
9
  export default (param, element, node) => {
10
10
  const prop = exec(param, element)
11
- if (prop) {
11
+ if (prop || prop !== element.__html) {
12
12
  // const parser = new window.DOMParser()
13
13
  // param = parser.parseFromString(param, 'text/html')
14
14
  if (node.nodeName === 'SVG') node.textContent = prop
15
15
  else node.innerHTML = prop
16
+
17
+ element.__html = prop
16
18
  }
17
19
  }
@@ -42,6 +42,9 @@ export default {
42
42
  __ifFalsy: {},
43
43
  __text: {},
44
44
  __element: {},
45
+ __class: {},
46
+ __html: {},
47
+ __className: {},
45
48
  key: {},
46
49
  tag: {},
47
50
  parent: {},
@@ -52,6 +55,7 @@ export default {
52
55
  remove: {},
53
56
  removeContent: {},
54
57
  lookup: {},
58
+ spot: {},
55
59
  keys: {},
56
60
  log: {},
57
61
  parse: {},
@@ -1,13 +1,15 @@
1
1
  'use strict'
2
2
 
3
3
  import { exec, isObject } from '../../utils'
4
+ import { IGNORE_STATE_PARAMS } from '../state'
4
5
 
5
6
  export default (params, element, node) => {
6
7
  const state = exec(params, element)
7
8
 
8
9
  if (isObject(state)) {
9
10
  for (const param in state) {
10
- if (param === 'update' || param === '__element' || param === 'parse') continue
11
+ IGNORE_STATE_PARAMS
12
+ if (IGNORE_STATE_PARAMS.includes(param)) continue
11
13
  element.state[param] = exec(state[param], element)
12
14
  }
13
15
  }
@@ -15,12 +15,14 @@ const initProps = (element, parent) => {
15
15
  return propValue
16
16
  }
17
17
 
18
+ if (isObject(props)) {
19
+ propsStack.push(props)
20
+ }
21
+
18
22
  if (matchParent && props !== 'match') propsStack.push(matchParent)
19
23
  if (matchParentChild) propsStack.push(matchParentChild)
20
24
 
21
- if (isObject(props)) {
22
- propsStack.push(props)
23
- } else if (props === 'inherit') {
25
+ if (props === 'inherit') {
24
26
  if (parent.props) propsStack.push(parent.props)
25
27
  } else if (isMatch) {
26
28
  const hasArg = props.split(' ')
@@ -28,6 +28,8 @@ const set = function (params, options, el) {
28
28
  const isEqual = isEqualDeep(params, element.content)
29
29
  if (isEqual && element.content.__cached) return element
30
30
 
31
+ // console.group(element.key)
32
+ // console.log(isEqual, params, element.content)
31
33
  removeContentElement(element)
32
34
 
33
35
  if (params) {
@@ -38,6 +40,7 @@ const set = function (params, options, el) {
38
40
  ...registry.defaultOptions
39
41
  })
40
42
  }
43
+ // console.groupEnd(element.key)
41
44
 
42
45
  return element
43
46
  }
@@ -1,19 +1,31 @@
1
1
  'use strict'
2
2
 
3
3
  import { on } from '../event'
4
- import { deepClone, exec, isFunction, overwriteDeep } from '../utils'
4
+ import { deepClone, exec, isFunction, isObject, overwriteDeep } from '../utils'
5
+
6
+ export const IGNORE_STATE_PARAMS = ['update', 'parse', 'clean', 'parent', '__element', '__depends', '__ref']
5
7
 
6
8
  export const parseState = function () {
7
9
  const state = this
8
10
  const parseState = {}
9
11
  for (const param in state) {
10
- if (param !== '__element' && param !== 'update' && param !== 'parse') {
12
+ if (!IGNORE_STATE_PARAMS.includes(param)) {
11
13
  parseState[param] = state[param]
12
14
  }
13
15
  }
14
16
  return parseState
15
17
  }
16
18
 
19
+ export const cleanState = function () {
20
+ const state = this
21
+ for (const param in state) {
22
+ if (!IGNORE_STATE_PARAMS.includes(param)) {
23
+ delete state[param]
24
+ }
25
+ }
26
+ return state
27
+ }
28
+
17
29
  export const updateState = function (obj, options = {}) {
18
30
  const state = this
19
31
  const element = state.__element
@@ -23,9 +35,18 @@ export const updateState = function (obj, options = {}) {
23
35
  on.initStateUpdated(element.on.initStateUpdated, element, state)
24
36
  }
25
37
 
26
- overwriteDeep(state, obj, ['update', 'parse', '__element'])
38
+ overwriteDeep(state, obj, IGNORE_STATE_PARAMS)
39
+
27
40
  if (!options.preventUpdate) element.update({}, options)
28
41
 
42
+ if (state.__depends) {
43
+ for (const el in state.__depends) {
44
+ // const findElement = element.spotByPath(state.__depends[el])
45
+ const findElement = state.__depends[el]
46
+ findElement.clean().update(state.parse(), options)
47
+ }
48
+ }
49
+
29
50
  // run `on.stateUpdated`
30
51
  if (element.on && isFunction(element.on.stateUpdated)) {
31
52
  on.stateUpdated(element.on.stateUpdated, element, state)
@@ -34,15 +55,27 @@ export const updateState = function (obj, options = {}) {
34
55
 
35
56
  export default function (element, parent) {
36
57
  let { state } = element
37
- // if (!state) return (parent && parent.state) || {}
58
+
38
59
  if (!state) {
39
60
  if (parent && parent.state) return parent.state
40
61
  return {}
41
62
  }
63
+
42
64
  if (isFunction(state)) state = exec(state, element)
43
65
 
44
- element.state = state = deepClone(state, ['update', 'parse', '__element'])
66
+ const { __ref } = state
67
+ if (__ref) {
68
+ state = deepClone(__ref, IGNORE_STATE_PARAMS)
69
+ if (isObject(__ref.__depends)) {
70
+ __ref.__depends[element.key] = state
71
+ } else __ref.__depends = { [element.key] : state }
72
+ } else {
73
+ state = deepClone(state, IGNORE_STATE_PARAMS)
74
+ }
75
+
76
+ element.state = state
45
77
  state.__element = element
78
+ state.clean = cleanState
46
79
  state.parse = parseState
47
80
  state.update = updateState
48
81
  state.parent = element.parent.state
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- import { overwrite, isFunction, isObject, isString, isNumber } from '../utils'
3
+ import { overwrite, isFunction, isObject, isString, isNumber, isEqualDeep } from '../utils'
4
4
  import { registry } from './mixins'
5
5
  import * as on from '../event/on'
6
6
  import { isMethod } from './methods'
@@ -44,6 +44,8 @@ const update = function (params = {}, options = UPDATE_DEFAULT_OPTIONS) {
44
44
  const overwriteChanges = overwrite(element, params, UPDATE_DEFAULT_OPTIONS)
45
45
  const execChanges = throughUpdatedExec(element, UPDATE_DEFAULT_OPTIONS)
46
46
  const definedChanges = throughUpdatedDefine(element)
47
+ // console.log(execChanges)
48
+ // console.log(definedChanges)
47
49
 
48
50
  if (options.stackChanges && element.__stackChanges) {
49
51
  const stackChanges = merge(definedChanges, merge(execChanges, overwriteChanges))
@@ -60,6 +62,7 @@ const update = function (params = {}, options = UPDATE_DEFAULT_OPTIONS) {
60
62
  on.initUpdate(element.on.initUpdate, element, element.state)
61
63
  }
62
64
 
65
+
63
66
  for (const param in element) {
64
67
  const prop = element[param]
65
68
 
@@ -70,13 +73,16 @@ const update = function (params = {}, options = UPDATE_DEFAULT_OPTIONS) {
70
73
  const hasDefined = define && define[param]
71
74
  const ourParam = registry[param]
72
75
 
73
-
74
76
  if (options.preventContentUpdate && param === 'content') console.log(param)
75
77
 
76
78
  if (ourParam) {
77
- if (isFunction(ourParam)) ourParam(prop, element, node)
79
+ // measure([element.key, param], () => {
80
+ if (isFunction(ourParam)) ourParam(prop, element, node)
81
+ // }, { logLevel: 5 })
78
82
  } else if (prop && isObject(prop) && !hasDefined) {
79
- if (!options.preventRecursive) update.call(prop, params[prop], UPDATE_DEFAULT_OPTIONS)
83
+ if (!options.preventRecursive) {
84
+ update.call(prop, params[prop], UPDATE_DEFAULT_OPTIONS)
85
+ }
80
86
  }
81
87
  }
82
88
 
@@ -2,6 +2,20 @@
2
2
 
3
3
  import nodes from '../element/nodes'
4
4
 
5
+ export const memoize = (fn) => {
6
+ const cache = {}
7
+ return (...args) => {
8
+ const n = args[0]
9
+ if (n in cache) {
10
+ return cache[n]
11
+ } else {
12
+ const result = fn(n)
13
+ cache[n] = result
14
+ return result
15
+ }
16
+ }
17
+ }
18
+
5
19
  export const isTagRegistered = arg => nodes.body.indexOf(arg)
6
20
 
7
21
  export const isObject = arg => {