@domql/element 2.4.0 → 2.4.2
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/cache/index.js +3 -0
- package/cache/options.js +3 -0
- package/dist/cjs/cache/index.js +24 -0
- package/dist/cjs/cache/options.js +24 -0
- package/dist/cjs/methods/index.js +186 -0
- package/dist/cjs/{set.js → methods/set.js} +24 -24
- package/dist/cjs/methods/v2.js +109 -0
- package/dist/cjs/mixins/attr.js +42 -0
- package/dist/cjs/mixins/classList.js +73 -0
- package/dist/cjs/mixins/content.js +75 -0
- package/dist/cjs/{define.js → mixins/data.js} +14 -12
- package/dist/cjs/mixins/html.js +35 -0
- package/dist/cjs/{index.js → mixins/index.js} +23 -15
- package/dist/cjs/mixins/registry.js +89 -0
- package/dist/cjs/mixins/state.js +40 -0
- package/dist/cjs/{tree.js → mixins/style.js} +11 -9
- package/dist/cjs/mixins/text.js +60 -0
- package/dist/cjs/props/create.js +77 -0
- package/dist/cjs/props/ignore.js +24 -0
- package/dist/cjs/props/index.js +21 -0
- package/dist/cjs/props/inherit.js +52 -0
- package/dist/cjs/props/update.js +37 -0
- package/dist/cjs/test/create.test.js +51 -0
- package/dist/cjs/test/set.test.js +9 -0
- package/dist/cjs/test/update.test.js +8 -0
- package/dist/cjs/utils/component.js +133 -0
- package/dist/cjs/utils/extendUtils.js +144 -0
- package/dist/cjs/utils/index.js +20 -0
- package/dist/cjs/utils/object.js +142 -0
- package/methods/index.js +165 -0
- package/methods/set.js +41 -0
- package/methods/v2.js +82 -0
- package/mixins/attr.js +23 -0
- package/mixins/classList.js +48 -0
- package/mixins/content.js +47 -0
- package/mixins/data.js +21 -0
- package/mixins/html.js +20 -0
- package/mixins/index.js +23 -0
- package/mixins/registry.js +66 -0
- package/mixins/state.js +20 -0
- package/mixins/style.js +14 -0
- package/mixins/text.js +41 -0
- package/package.json +5 -4
- package/props/create.js +60 -0
- package/props/ignore.js +3 -0
- package/props/index.js +6 -0
- package/props/inherit.js +34 -0
- package/props/update.js +17 -0
- package/test/create.test.js +61 -0
- package/test/set.test.js +13 -0
- package/test/update.test.js +13 -0
- package/utils/component.js +112 -0
- package/utils/extendUtils.js +118 -0
- package/utils/index.js +5 -0
- package/utils/object.js +141 -0
- package/dist/cjs/applyParam.js +0 -41
- package/dist/cjs/create.js +0 -262
- package/dist/cjs/extend.js +0 -87
- package/dist/cjs/iterate.js +0 -108
- package/dist/cjs/node.js +0 -85
- package/dist/cjs/update.js +0 -223
package/methods/v2.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { isDefined, isFunction, isObjectLike } from '@domql/utils'
|
|
4
|
+
import { parseFilters, registry } from '../mixins'
|
|
5
|
+
|
|
6
|
+
export const defineSetter = (element, key, get, set) =>
|
|
7
|
+
Object.defineProperty(element, key, { get, set })
|
|
8
|
+
|
|
9
|
+
export const keys = function () {
|
|
10
|
+
const element = this
|
|
11
|
+
const keys = []
|
|
12
|
+
for (const param in element) {
|
|
13
|
+
if (registry[param] && !parseFilters.elementKeys.includes(param)) { continue }
|
|
14
|
+
keys.push(param)
|
|
15
|
+
}
|
|
16
|
+
return keys
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const parse = function (excl = []) {
|
|
20
|
+
const element = this
|
|
21
|
+
const obj = {}
|
|
22
|
+
const keyList = keys.call(element)
|
|
23
|
+
keyList.forEach(v => {
|
|
24
|
+
if (excl.includes(v)) return
|
|
25
|
+
let val = element[v]
|
|
26
|
+
if (v === 'state') {
|
|
27
|
+
if (element.__ref && element.__ref.__hasRootState) return
|
|
28
|
+
if (isFunction(val && val.parse)) val = val.parse()
|
|
29
|
+
} else if (v === 'props') {
|
|
30
|
+
const { __element, update, ...props } = element[v]
|
|
31
|
+
obj[v] = props
|
|
32
|
+
} else if (isDefined(val)) obj[v] = val
|
|
33
|
+
})
|
|
34
|
+
return obj
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const parseDeep = function (excl = []) {
|
|
38
|
+
const element = this
|
|
39
|
+
const obj = parse.call(element, excl)
|
|
40
|
+
for (const v in obj) {
|
|
41
|
+
if (excl.includes(v)) return
|
|
42
|
+
if (isObjectLike(obj[v])) { obj[v] = parseDeep.call(obj[v], excl) }
|
|
43
|
+
}
|
|
44
|
+
return obj
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const log = function (...args) {
|
|
48
|
+
const element = this
|
|
49
|
+
const { __ref } = element
|
|
50
|
+
console.group(element.key)
|
|
51
|
+
if (args.length) {
|
|
52
|
+
args.forEach(v => console.log(`%c${v}:\n`, 'font-weight: bold', element[v]))
|
|
53
|
+
} else {
|
|
54
|
+
console.log(__ref.path)
|
|
55
|
+
const keys = element.keys()
|
|
56
|
+
keys.forEach(v => console.log(`%c${v}:\n`, 'font-weight: bold', element[v]))
|
|
57
|
+
}
|
|
58
|
+
console.groupEnd(element.key)
|
|
59
|
+
return element
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const nextElement = function () {
|
|
63
|
+
const element = this
|
|
64
|
+
const { key, parent } = element
|
|
65
|
+
const { __children } = parent.__ref
|
|
66
|
+
|
|
67
|
+
const currentIndex = __children.indexOf(key)
|
|
68
|
+
const nextChild = __children[currentIndex + 1]
|
|
69
|
+
|
|
70
|
+
return parent[nextChild]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const previousElement = function (el) {
|
|
74
|
+
const element = el || this
|
|
75
|
+
const { key, parent } = element
|
|
76
|
+
const { __children } = parent.__ref
|
|
77
|
+
|
|
78
|
+
if (!__children) return
|
|
79
|
+
|
|
80
|
+
const currentIndex = __children.indexOf(key)
|
|
81
|
+
return parent[__children[currentIndex - 1]]
|
|
82
|
+
}
|
package/mixins/attr.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { exec, isNot } from '@domql/utils'
|
|
4
|
+
import { report } from '@domql/report'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Recursively add attributes to a DOM node
|
|
8
|
+
*/
|
|
9
|
+
export default (params, element, node) => {
|
|
10
|
+
const { __ref } = element
|
|
11
|
+
const { __attr } = __ref
|
|
12
|
+
if (isNot('object')) report('HTMLInvalidAttr', params)
|
|
13
|
+
if (params) {
|
|
14
|
+
for (const attr in params) {
|
|
15
|
+
const val = exec(params[attr], element)
|
|
16
|
+
// if (__attr[attr] === val) return
|
|
17
|
+
if (val && node.setAttribute) node.setAttribute(attr, val)
|
|
18
|
+
else if (node.removeAttribute) node.removeAttribute(attr)
|
|
19
|
+
__attr[attr] = val
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
console.groupEnd(params, __attr)
|
|
23
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { exec, isObject, isString } from '@domql/utils'
|
|
4
|
+
|
|
5
|
+
export const assignClass = (element) => {
|
|
6
|
+
const { key } = element
|
|
7
|
+
if (element.class === true) element.class = key
|
|
8
|
+
else if (!element.class && typeof key === 'string' && key.charAt(0) === '_' && key.charAt(1) !== '_') {
|
|
9
|
+
element.class = key.slice(1)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// stringifies class object
|
|
14
|
+
export const classify = (obj, element) => {
|
|
15
|
+
let className = ''
|
|
16
|
+
for (const item in obj) {
|
|
17
|
+
const param = obj[item]
|
|
18
|
+
if (typeof param === 'boolean' && param) className += ` ${item}`
|
|
19
|
+
else if (typeof param === 'string') className += ` ${param}`
|
|
20
|
+
else if (typeof param === 'function') {
|
|
21
|
+
className += ` ${exec(param, element)}`
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return className
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const classList = (params, element) => {
|
|
28
|
+
if (!params) return
|
|
29
|
+
const { key } = element
|
|
30
|
+
if (params === true) params = element.class = { key }
|
|
31
|
+
if (isString(params)) params = element.class = { default: params }
|
|
32
|
+
if (isObject(params)) params = classify(params, element)
|
|
33
|
+
// TODO: fails on string
|
|
34
|
+
const className = params.replace(/\s+/g, ' ').trim()
|
|
35
|
+
if (element.ref) element.ref.class = className // TODO: this check is NOT needed in new DOMQL
|
|
36
|
+
return className
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// LEGACY (still needed in old domql)
|
|
40
|
+
export const applyClassListOnNode = (params, element, node) => {
|
|
41
|
+
const className = classList(params, element)
|
|
42
|
+
node.classList = className
|
|
43
|
+
return className
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default (params, element, node) => {
|
|
47
|
+
applyClassListOnNode(params, element, node)
|
|
48
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { isFunction } from '@domql/utils'
|
|
4
|
+
import set from '../set'
|
|
5
|
+
|
|
6
|
+
export const updateContent = function (params, options) {
|
|
7
|
+
const element = this
|
|
8
|
+
|
|
9
|
+
if (!element.content) return
|
|
10
|
+
if (element.content.update) element.content.update(params, options)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const removeContent = function (el) {
|
|
14
|
+
const element = el || this
|
|
15
|
+
const { __ref } = element
|
|
16
|
+
|
|
17
|
+
if (element.content) {
|
|
18
|
+
if (element.content.node) {
|
|
19
|
+
if (element.content.tag === 'fragment') element.node.innerHTML = ''
|
|
20
|
+
else element.node.removeChild(element.content.node)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const { __cached } = __ref
|
|
24
|
+
if (__cached && __cached.content) {
|
|
25
|
+
if (__cached.content.tag === 'fragment') __cached.content.parent.node.innerHTML = ''
|
|
26
|
+
else if (__cached.content && isFunction(__cached.content.remove)) __cached.content.remove()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
delete element.content
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Appends anything as content
|
|
35
|
+
* an original one as a child
|
|
36
|
+
*/
|
|
37
|
+
export const setContent = (param, element, node, options) => {
|
|
38
|
+
if (param && element) {
|
|
39
|
+
if (element.content.update) {
|
|
40
|
+
element.content.update({}, options)
|
|
41
|
+
} else {
|
|
42
|
+
set.call(element, param, options)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default setContent
|
package/mixins/data.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { exec, isObject } from '@domql/utils'
|
|
4
|
+
import { report } from '@domql/report'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Apply data parameters on the DOM nodes
|
|
8
|
+
* this should only work if `showOnNode: true` is passed
|
|
9
|
+
*/
|
|
10
|
+
export default (params, element, node) => {
|
|
11
|
+
if (params && params.showOnNode) {
|
|
12
|
+
if (!isObject(params)) report('HTMLInvalidData', params)
|
|
13
|
+
|
|
14
|
+
// Apply data params on node
|
|
15
|
+
for (const dataset in params) {
|
|
16
|
+
if (dataset !== 'showOnNode') {
|
|
17
|
+
node.dataset[dataset] = exec(params[dataset], element)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
package/mixins/html.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { exec } from '@domql/utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Appends raw HTML as content
|
|
7
|
+
* an original one as a child
|
|
8
|
+
*/
|
|
9
|
+
export default (param, element, node) => {
|
|
10
|
+
const prop = exec(param, element)
|
|
11
|
+
const { __ref } = element
|
|
12
|
+
if (prop !== __ref.__html) {
|
|
13
|
+
// const parser = new window.DOMParser()
|
|
14
|
+
// param = parser.parseFromString(param, 'text/html')
|
|
15
|
+
if (node.nodeName === 'SVG') node.textContent = prop
|
|
16
|
+
else node.innerHTML = prop
|
|
17
|
+
|
|
18
|
+
__ref.__html = prop
|
|
19
|
+
}
|
|
20
|
+
}
|
package/mixins/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import attr from './attr'
|
|
4
|
+
import classList from './classList'
|
|
5
|
+
import content from './content'
|
|
6
|
+
import data from './data'
|
|
7
|
+
import html from './html'
|
|
8
|
+
import style from './style'
|
|
9
|
+
import text from './text'
|
|
10
|
+
import state from './state'
|
|
11
|
+
import registry from './registry'
|
|
12
|
+
export {
|
|
13
|
+
attr,
|
|
14
|
+
classList,
|
|
15
|
+
content,
|
|
16
|
+
data,
|
|
17
|
+
style,
|
|
18
|
+
text,
|
|
19
|
+
html,
|
|
20
|
+
state,
|
|
21
|
+
registry
|
|
22
|
+
}
|
|
23
|
+
export * from './registry'
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
attr, classList, content,
|
|
5
|
+
data, html, state, style,
|
|
6
|
+
text
|
|
7
|
+
} from '.'
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
attr,
|
|
11
|
+
style,
|
|
12
|
+
text,
|
|
13
|
+
html,
|
|
14
|
+
content,
|
|
15
|
+
data,
|
|
16
|
+
class: classList,
|
|
17
|
+
state,
|
|
18
|
+
|
|
19
|
+
extend: {},
|
|
20
|
+
childExtend: {},
|
|
21
|
+
childExtendRecursive: {},
|
|
22
|
+
props: {},
|
|
23
|
+
path: {},
|
|
24
|
+
if: {},
|
|
25
|
+
define: {},
|
|
26
|
+
transform: {},
|
|
27
|
+
__ref: {},
|
|
28
|
+
__hash: {},
|
|
29
|
+
__text: {},
|
|
30
|
+
nextElement: {},
|
|
31
|
+
previousElement: {},
|
|
32
|
+
key: {},
|
|
33
|
+
tag: {},
|
|
34
|
+
query: {},
|
|
35
|
+
parent: {},
|
|
36
|
+
node: {},
|
|
37
|
+
set: {},
|
|
38
|
+
update: {},
|
|
39
|
+
setProps: {},
|
|
40
|
+
remove: {},
|
|
41
|
+
updateContent: {},
|
|
42
|
+
removeContent: {},
|
|
43
|
+
lookup: {},
|
|
44
|
+
spotByPath: {},
|
|
45
|
+
keys: {},
|
|
46
|
+
log: {},
|
|
47
|
+
parse: {},
|
|
48
|
+
parseDeep: {},
|
|
49
|
+
on: {},
|
|
50
|
+
component: {},
|
|
51
|
+
context: {},
|
|
52
|
+
$setStateCollection: {},
|
|
53
|
+
$setCollection: {},
|
|
54
|
+
$setPropsCollection: {}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// List of keys for .parse() and .parseDeep() to include in the result.
|
|
58
|
+
// Keys not in the array are excluded.
|
|
59
|
+
export const parseFilters = {
|
|
60
|
+
elementKeys: [
|
|
61
|
+
'tag', 'text', 'style', 'attr', 'class', 'state', 'props',
|
|
62
|
+
'data', 'content', 'html', 'on', 'key'
|
|
63
|
+
],
|
|
64
|
+
propsKeys: ['__element', 'update'],
|
|
65
|
+
stateKeys: []
|
|
66
|
+
}
|
package/mixins/state.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { IGNORE_STATE_PARAMS } from '@domql/state'
|
|
4
|
+
import { exec, isObject } from '@domql/utils'
|
|
5
|
+
|
|
6
|
+
export const state = (params, element, node) => {
|
|
7
|
+
const state = exec(params, element)
|
|
8
|
+
|
|
9
|
+
if (isObject(state)) {
|
|
10
|
+
for (const param in state) {
|
|
11
|
+
if (IGNORE_STATE_PARAMS.includes(param)) continue
|
|
12
|
+
if (!state.hasOwnProperty(param)) continue
|
|
13
|
+
element.state[param] = exec(state[param], element)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return element
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default state
|
package/mixins/style.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { isObject, map } from '@domql/utils'
|
|
4
|
+
import { report } from '@domql/report'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Recursively add styles to a DOM node
|
|
8
|
+
*/
|
|
9
|
+
export default (params, element, node) => {
|
|
10
|
+
if (params) {
|
|
11
|
+
if (isObject(params)) map(node.style, params, element)
|
|
12
|
+
else report('HTMLInvalidStyles', params)
|
|
13
|
+
}
|
|
14
|
+
}
|
package/mixins/text.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { create } from '..'
|
|
4
|
+
import {
|
|
5
|
+
exec,
|
|
6
|
+
isString,
|
|
7
|
+
replaceLiteralsWithObjectFields
|
|
8
|
+
} from '@domql/utils'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Creates a text node and appends into
|
|
12
|
+
* an original one as a child
|
|
13
|
+
*/
|
|
14
|
+
export const asd = (param, element, node) => {
|
|
15
|
+
const prop = exec(param, element)
|
|
16
|
+
if (element.tag === 'string') {
|
|
17
|
+
node.nodeValue = prop
|
|
18
|
+
} else if (param !== undefined || param !== null) {
|
|
19
|
+
if (element.__text && element.__text.text !== prop) return
|
|
20
|
+
element.__text.text = prop
|
|
21
|
+
if (element.__text.node) element.__text.node.nodeValue = prop
|
|
22
|
+
else create({ tag: 'string', text: prop }, element, '__text')
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default (param, element, node) => {
|
|
27
|
+
let prop = exec(param, element)
|
|
28
|
+
if (isString(prop) && prop.includes('{{')) {
|
|
29
|
+
prop = replaceLiteralsWithObjectFields(prop, element.state)
|
|
30
|
+
}
|
|
31
|
+
if (element.tag === 'string') {
|
|
32
|
+
if (element.text === prop) return
|
|
33
|
+
node.nodeValue = prop
|
|
34
|
+
} else if (param !== undefined || param !== null) {
|
|
35
|
+
if (element.__text) {
|
|
36
|
+
if (element.__text.text === prop) return
|
|
37
|
+
element.__text.text = prop
|
|
38
|
+
if (element.__text.node) element.__text.node.nodeValue = prop
|
|
39
|
+
} else create({ tag: 'string', text: prop }, element, '__text')
|
|
40
|
+
}
|
|
41
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@domql/element",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "index.js",
|
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
},
|
|
14
14
|
"source": "index.js",
|
|
15
15
|
"files": [
|
|
16
|
+
"*/**.js",
|
|
16
17
|
"*.js",
|
|
17
18
|
"dist"
|
|
18
19
|
],
|
|
19
20
|
"scripts": {
|
|
20
21
|
"copy:package:cjs": "cp ../../build/package-cjs.json dist/cjs/package.json",
|
|
21
|
-
"build:esm": "npx esbuild
|
|
22
|
-
"build:cjs": "npx esbuild
|
|
22
|
+
"build:esm": "npx esbuild **/*.js --target=es2019 --format=esm --outdir=dist/esm",
|
|
23
|
+
"build:cjs": "npx esbuild **/*.js --target=node16 --format=cjs --outdir=dist/cjs",
|
|
23
24
|
"build": "yarn build:cjs",
|
|
24
25
|
"prepublish": "rimraf -I dist && yarn build && yarn copy:package:cjs"
|
|
25
26
|
},
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
"@domql/state": "latest",
|
|
31
32
|
"@domql/utils": "latest"
|
|
32
33
|
},
|
|
33
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "6def1dc6574a649c0bdc8a3ba6eb171ad79649ea",
|
|
34
35
|
"devDependencies": {
|
|
35
36
|
"@babel/core": "^7.12.0"
|
|
36
37
|
}
|
package/props/create.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { exec, isArray, isObject, deepClone, deepMerge } from '@domql/utils'
|
|
4
|
+
import { IGNORE_PROPS_PARAMS } from './ignore'
|
|
5
|
+
|
|
6
|
+
import { inheritParentProps } from './inherit'
|
|
7
|
+
|
|
8
|
+
const createPropsStack = (element, parent) => {
|
|
9
|
+
const { props, __ref } = element
|
|
10
|
+
const propsStack = __ref.__props = inheritParentProps(element, parent)
|
|
11
|
+
|
|
12
|
+
if (isObject(props)) propsStack.push(props)
|
|
13
|
+
else if (props === 'inherit' && parent.props) propsStack.push(parent.props)
|
|
14
|
+
else if (props) propsStack.push(props)
|
|
15
|
+
|
|
16
|
+
if (isArray(__ref.__extend)) {
|
|
17
|
+
__ref.__extend.forEach(extend => {
|
|
18
|
+
if (extend.props) propsStack.push(extend.props)
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
__ref.__props = propsStack
|
|
23
|
+
|
|
24
|
+
return propsStack
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const syncProps = (props, element) => {
|
|
28
|
+
element.props = {}
|
|
29
|
+
const mergedProps = { update, __element: element }
|
|
30
|
+
props.forEach(v => {
|
|
31
|
+
if (IGNORE_PROPS_PARAMS.includes(v)) return
|
|
32
|
+
const execProps = exec(v, element)
|
|
33
|
+
if (isObject(execProps) && execProps.__element) return
|
|
34
|
+
element.props = deepMerge(
|
|
35
|
+
mergedProps,
|
|
36
|
+
deepClone(execProps, IGNORE_PROPS_PARAMS),
|
|
37
|
+
IGNORE_PROPS_PARAMS
|
|
38
|
+
)
|
|
39
|
+
})
|
|
40
|
+
element.props = mergedProps
|
|
41
|
+
return element.props
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const createProps = function (element, parent, cached) {
|
|
45
|
+
const propsStack = cached || createPropsStack(element, parent)
|
|
46
|
+
const { __ref } = element
|
|
47
|
+
|
|
48
|
+
if (propsStack.length) {
|
|
49
|
+
__ref.__props = propsStack
|
|
50
|
+
syncProps(propsStack, element)
|
|
51
|
+
element.props.update = update
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return element
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function update (props, options) {
|
|
58
|
+
const element = this.__element
|
|
59
|
+
element.update({ props }, options)
|
|
60
|
+
}
|
package/props/ignore.js
ADDED
package/props/index.js
ADDED
package/props/inherit.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { exec, is, isString } from '@domql/utils'
|
|
4
|
+
|
|
5
|
+
const objectizeStringProperty = propValue => {
|
|
6
|
+
if (is(propValue)('string', 'number')) {
|
|
7
|
+
return { inheritedString: propValue }
|
|
8
|
+
}
|
|
9
|
+
return propValue
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const inheritParentProps = (element, parent) => {
|
|
13
|
+
let propsStack = []
|
|
14
|
+
const parentProps = exec(parent, parent.state).props
|
|
15
|
+
|
|
16
|
+
const matchParent = parent.props && parentProps[element.key]
|
|
17
|
+
const matchParentIsString = isString(matchParent)
|
|
18
|
+
const matchParentChildProps = parentProps && parentProps.childProps
|
|
19
|
+
|
|
20
|
+
if (matchParent) {
|
|
21
|
+
if (matchParentIsString) {
|
|
22
|
+
const inheritedStringExists = propsStack.filter(v => v.inheritedString)[0]
|
|
23
|
+
if (inheritedStringExists) inheritedStringExists.inheritedString = matchParent
|
|
24
|
+
else {
|
|
25
|
+
propsStack = [].concat(objectizeStringProperty(matchParent), propsStack)
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
propsStack.push(objectizeStringProperty(matchParent))
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (matchParentChildProps) propsStack.push(matchParentChildProps)
|
|
32
|
+
|
|
33
|
+
return propsStack
|
|
34
|
+
}
|
package/props/update.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { syncProps } from './create'
|
|
4
|
+
import { inheritParentProps } from './inherit'
|
|
5
|
+
|
|
6
|
+
export const updateProps = (newProps, element, parent) => {
|
|
7
|
+
const { __ref } = element
|
|
8
|
+
let propsStack = __ref.__props
|
|
9
|
+
|
|
10
|
+
const parentProps = inheritParentProps(element, parent)
|
|
11
|
+
if (parentProps) propsStack = __ref.__props = [].concat(parentProps, propsStack)
|
|
12
|
+
if (newProps) propsStack = __ref.__props = [].concat(newProps, propsStack)
|
|
13
|
+
|
|
14
|
+
if (propsStack) syncProps(propsStack, element)
|
|
15
|
+
|
|
16
|
+
return element
|
|
17
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { create } from '../../src/element'
|
|
4
|
+
|
|
5
|
+
const dom = create({})
|
|
6
|
+
|
|
7
|
+
test('should create EMPTY element', () => {
|
|
8
|
+
expect(dom).toHaveProperty('key')
|
|
9
|
+
expect(dom).toHaveProperty('state')
|
|
10
|
+
expect(dom).toHaveProperty('parent')
|
|
11
|
+
expect(dom).toHaveProperty('node')
|
|
12
|
+
expect(dom).toHaveProperty('set')
|
|
13
|
+
expect(dom).toHaveProperty('update')
|
|
14
|
+
expect(dom).toHaveProperty('__ref')
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test('should create valid DOM node', () => {
|
|
18
|
+
expect(dom.node).toBeInstanceOf(window.HTMLDivElement)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('must be able to create valid PATH', () => {
|
|
22
|
+
expect(dom.__ref.__path).toStrictEqual([dom.key])
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
test('if it HAS a NODE, don\'t recreate', () => {
|
|
26
|
+
const node = document.createElement('div')
|
|
27
|
+
const dom2 = create({ node })
|
|
28
|
+
expect(dom2.node.parentElement).toBe(document.body)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('create with number', () => {
|
|
32
|
+
const numb = create(0)
|
|
33
|
+
expect(numb.text).toBe(0)
|
|
34
|
+
expect(numb.tag).toBe('string')
|
|
35
|
+
expect(numb.node.nodeType).toBe(3) // #text
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('create with string', () => {
|
|
39
|
+
const str = create('hello')
|
|
40
|
+
expect(str.text).toBe('hello')
|
|
41
|
+
expect(str.tag).toBe('string')
|
|
42
|
+
expect(str.node.nodeType).toBe(3) // #text
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('creating conditions', () => {
|
|
46
|
+
const element = create({
|
|
47
|
+
data: { visible: true },
|
|
48
|
+
if: element => element.data.visible
|
|
49
|
+
})
|
|
50
|
+
expect(element.tag).toBe('div')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('creating nesting', () => {
|
|
54
|
+
const element = create({
|
|
55
|
+
header: {
|
|
56
|
+
h1: {}
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
expect(element.header.tag).toBe('header')
|
|
60
|
+
expect(element.header.h1.tag).toBe('h1')
|
|
61
|
+
})
|
package/test/set.test.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { create } from '../../src/element'
|
|
4
|
+
|
|
5
|
+
const element = create({})
|
|
6
|
+
|
|
7
|
+
test('should SET element', () => {
|
|
8
|
+
element.set({ text: 'test' })
|
|
9
|
+
expect(element.content.text).toBe('test')
|
|
10
|
+
|
|
11
|
+
element.set({ text: 'test2' })
|
|
12
|
+
expect(element.content.text).toBe('test2')
|
|
13
|
+
})
|