domql 2.0.3 → 2.0.7
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 +208 -0
- package/package.json +53 -20
- package/packages/cookie/index.js +22 -0
- package/packages/emotion/index.js +35 -0
- package/packages/object/index.js +29 -0
- package/packages/object/package.json +20 -0
- package/packages/routeLink/index.js +23 -0
- package/packages/router/index.js +18 -0
- package/src/element/assign.js +22 -0
- package/src/element/cache.js +52 -0
- package/src/element/create.js +144 -0
- package/src/element/createNode.js +92 -0
- package/src/element/createProps.js +64 -0
- package/src/element/createState.js +51 -0
- package/src/element/define.js +13 -0
- package/src/element/id.js +10 -0
- package/src/element/index.js +34 -0
- package/src/element/iterate.js +80 -0
- package/src/element/methods.js +96 -0
- package/src/element/mixins/attr.js +18 -0
- package/src/element/mixins/classList.js +37 -0
- package/src/element/mixins/content.js +17 -0
- package/src/element/mixins/data.js +21 -0
- package/src/element/mixins/html.js +17 -0
- package/src/element/mixins/index.js +23 -0
- package/src/element/mixins/registry.js +55 -0
- package/src/element/mixins/state.js +16 -0
- package/src/element/mixins/style.js +14 -0
- package/src/element/mixins/text.js +19 -0
- package/src/element/nodes.js +139 -0
- package/src/element/parse.js +17 -0
- package/src/element/proto.js +66 -0
- package/src/element/root.js +10 -0
- package/src/element/set.js +46 -0
- package/src/element/tree.js +5 -0
- package/src/element/update.js +100 -0
- package/src/event/can.js +10 -0
- package/src/event/index.js +11 -0
- package/src/event/is.js +13 -0
- package/src/event/on.js +33 -0
- package/src/event/store.js +6 -0
- package/src/event/wrappers.js +14 -0
- package/src/index.js +16 -0
- package/src/utils/index.js +6 -0
- package/src/utils/node.js +10 -0
- package/src/utils/object.js +193 -0
- package/src/utils/protoUtils.js +119 -0
- package/src/utils/report.js +62 -0
- package/allExports.js +0 -17
- package/index.js +0 -15
package/README.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# DOMQL
|
|
2
|
+
DOM rendering Javascript framework.
|
|
3
|
+
|
|
4
|
+
- Minimalistic
|
|
5
|
+
- No dependencies
|
|
6
|
+
- Extendable
|
|
7
|
+
- No transpilations, simple ES6 code
|
|
8
|
+
- One-time import and subtrees
|
|
9
|
+
|
|
10
|
+
You can start with [starter-kit](https://github.com/rackai/starter-kit) as a boilerplate, or jump into the live editor [playground](https://domql.com/playground/).
|
|
11
|
+
|
|
12
|
+
[](https://badge.fury.io/js/%40rackai%2Fdomql)
|
|
13
|
+
[](https://travis-ci.org/rackai/domql)
|
|
14
|
+
[](https://coveralls.io/github/rackai/domql?branch=main)
|
|
15
|
+
|
|
16
|
+
TODO:
|
|
17
|
+
- [x] error reporting
|
|
18
|
+
- [x] virtual DOM tree
|
|
19
|
+
- [x] create
|
|
20
|
+
- [x] create using prototype class
|
|
21
|
+
- [x] support multiple level prototypes
|
|
22
|
+
- [x] DOM caching
|
|
23
|
+
- [x] state
|
|
24
|
+
- [x] binding
|
|
25
|
+
- [x] with other component
|
|
26
|
+
- [x] with state
|
|
27
|
+
- [x] update
|
|
28
|
+
- [x] set (recreate)
|
|
29
|
+
- [x] only iterate with diff
|
|
30
|
+
- [x] events
|
|
31
|
+
- [x] event handling
|
|
32
|
+
- [ ] bubbling and propogation
|
|
33
|
+
- [ ] run changes inside animationFrame
|
|
34
|
+
|
|
35
|
+
### Getting started
|
|
36
|
+
|
|
37
|
+
To install all dependencies and run dev server, run:
|
|
38
|
+
|
|
39
|
+
```shell
|
|
40
|
+
yarn && yarn start
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Examples
|
|
44
|
+
|
|
45
|
+
Initialization:
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
import DOM from '@rackai/domql'
|
|
49
|
+
|
|
50
|
+
DOM.create({ text: 'Rendered' })
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Attributes:
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
var link = {
|
|
57
|
+
tag: 'a',
|
|
58
|
+
class: 'menu link',
|
|
59
|
+
attr: {
|
|
60
|
+
href: '#'
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
```javascript
|
|
65
|
+
var img = {
|
|
66
|
+
tag: 'img',
|
|
67
|
+
class: 'avatar',
|
|
68
|
+
attr: {
|
|
69
|
+
src: '...'
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Reusing:
|
|
75
|
+
```javascript
|
|
76
|
+
var Link = {
|
|
77
|
+
tag: 'a'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
var ListItem = {
|
|
81
|
+
proto: Link,
|
|
82
|
+
class: 'ui link',
|
|
83
|
+
attr: {
|
|
84
|
+
href: '#'
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
var menu = {
|
|
89
|
+
childProto: ListItem,
|
|
90
|
+
home: 'Home',
|
|
91
|
+
text: 'About'
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
var header = {
|
|
95
|
+
logo: {},
|
|
96
|
+
menu
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Array Support:
|
|
101
|
+
```javascript
|
|
102
|
+
var navItems = ['Home', 'About', 'FAQ', 'Contact']
|
|
103
|
+
|
|
104
|
+
var menu = {
|
|
105
|
+
proto: ListItem,
|
|
106
|
+
...navItems
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Update:
|
|
111
|
+
```javascript
|
|
112
|
+
var val = {
|
|
113
|
+
text: 0
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
var Increment = {
|
|
117
|
+
tag: 'button',
|
|
118
|
+
text: 'Increment',
|
|
119
|
+
on: {
|
|
120
|
+
click: (e) => {
|
|
121
|
+
val.update({ text: val.text++ })
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## API
|
|
128
|
+
|
|
129
|
+
### Properties
|
|
130
|
+
|
|
131
|
+
| Property | Type | Description | Default |
|
|
132
|
+
| --- | --- | --- | --- |
|
|
133
|
+
| `key` | `Number` `String` | Defines the key of the Element | The key of the object, or randomly generated name |
|
|
134
|
+
| `proto` | `Object` `Array` | Clones the other element | `undefined` |
|
|
135
|
+
| `childProto` | `Object` `Array` | Specifies the `proto` for all child elements | `undefined` |
|
|
136
|
+
| `tag` | `String` | Specifis the HTML tag | `div` or related HTML tag if the key matches |
|
|
137
|
+
| `class` | `Any` | Specifies the HTML class | `undefined` |
|
|
138
|
+
| `attr` | `Object` | Specifies the set of HTML attributes | `{}` |
|
|
139
|
+
| `text` | `Any` | Text inside the element | `undefined` |
|
|
140
|
+
| `content` | `Object` `Array` | Fragment wrapper to use dynamic content loading | `undefined`
|
|
141
|
+
|
|
142
|
+
To specify your own property per Element, set the function inside `define` property like:
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
var User = {
|
|
146
|
+
define: {
|
|
147
|
+
username: param => param.toUpperCase()
|
|
148
|
+
},
|
|
149
|
+
text: element => element.username
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
var Contact = {
|
|
153
|
+
proto: User,
|
|
154
|
+
username: 'nikoloza'
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Methods
|
|
159
|
+
| Method | Description | Params |
|
|
160
|
+
| --- | --- | --- |
|
|
161
|
+
| `update` | Updates element by passed object | `properties`: `Object` `Array` |
|
|
162
|
+
| `set` | Sets passed element in the `content` property | `element`: `Object` `Array` |
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
### Events
|
|
166
|
+
All native DOM events are supported and can be specified inside `on` parameter. Additionally, `init` and `render` can be also invoked. All events except these two receive `event` object as a first parameter, following the `element` object itself.
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
### Reserved keywords
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
key
|
|
174
|
+
tag
|
|
175
|
+
node
|
|
176
|
+
proto
|
|
177
|
+
on
|
|
178
|
+
class
|
|
179
|
+
text
|
|
180
|
+
data
|
|
181
|
+
style
|
|
182
|
+
attr
|
|
183
|
+
update
|
|
184
|
+
set
|
|
185
|
+
define
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
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:
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
var layout = { // this will be <div>
|
|
192
|
+
header: {}, // will create <header>
|
|
193
|
+
aside: {}, // will create <aside>
|
|
194
|
+
main: { // will create <main>
|
|
195
|
+
childProto: {
|
|
196
|
+
article: { // will create <article>
|
|
197
|
+
title: {}, // will create <div>
|
|
198
|
+
description: {}, // will create <div>
|
|
199
|
+
_rating: {} // will create <div class="rating">
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
footer: {} // will create <footer>
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Credits
|
|
208
|
+
Inspired by [brisky](https://github.com/vigour-io/brisky)
|
package/package.json
CHANGED
|
@@ -1,25 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "domql",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
3
|
+
"description": "DOM rendering Javascript framework at early stage.",
|
|
4
|
+
"private": false,
|
|
5
|
+
"author": "rackai",
|
|
6
|
+
"version": "2.0.7",
|
|
7
|
+
"repository": "https://github.com/rackai/domql",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"registry": "https://registry.npmjs.org"
|
|
10
|
+
},
|
|
11
|
+
"main": "src/index.js",
|
|
12
|
+
"files": [
|
|
13
|
+
"src",
|
|
14
|
+
"packages"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"start": "parcel examples/index.html --no-cache",
|
|
18
|
+
"build": "parcel build examples/index.html",
|
|
19
|
+
"standard": "npx standard \"src/**/*.js\"",
|
|
20
|
+
"test": "yarn standard && jest --coverage --coverageReporters=text-lcov | coveralls",
|
|
21
|
+
"test-watch": "jest --watch",
|
|
22
|
+
"bump": "npx np"
|
|
23
|
+
},
|
|
24
|
+
"source": true,
|
|
7
25
|
"dependencies": {
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"@
|
|
12
|
-
"@
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
26
|
+
"regenerator-runtime": "^0.13.5"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@babel/core": "^7.10.4",
|
|
30
|
+
"@babel/preset-env": "^7.10.4",
|
|
31
|
+
"babel-eslint": "^10.0.3",
|
|
32
|
+
"babel-jest": "^27.0.2",
|
|
33
|
+
"babel-preset-env": "^1.7.0",
|
|
34
|
+
"coveralls": "^3.0.5",
|
|
35
|
+
"eslint": "^7.12.1",
|
|
36
|
+
"eslint-plugin-jest": "^26.1.0",
|
|
37
|
+
"jest": "^27.0.6",
|
|
38
|
+
"nodemon": "^2.0.6",
|
|
39
|
+
"np": "^7.2.0",
|
|
40
|
+
"parcel-bundler": "^1.12.4",
|
|
41
|
+
"standard": "^16.0.1"
|
|
42
|
+
},
|
|
43
|
+
"jest": {
|
|
44
|
+
"collectCoverageFrom": [
|
|
45
|
+
"src/**/*.js"
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
"standard": {
|
|
49
|
+
"parser": "babel-eslint",
|
|
50
|
+
"env": [
|
|
51
|
+
"jest"
|
|
52
|
+
]
|
|
23
53
|
},
|
|
24
|
-
"
|
|
54
|
+
"browserslist": [
|
|
55
|
+
"> 1%",
|
|
56
|
+
"ie >= 9"
|
|
57
|
+
]
|
|
25
58
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
export const isMobile = (() => /Mobi/.test(navigator.userAgent))()
|
|
4
|
+
|
|
5
|
+
export const setCookie = (cname, cvalue, exdays = 365) => {
|
|
6
|
+
const d = new Date()
|
|
7
|
+
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000))
|
|
8
|
+
const expires = `expires=${d.toUTCString()}`
|
|
9
|
+
document.cookie = `${cname}=${cvalue};${expires};path=/`
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const getCookie = (cname) => {
|
|
13
|
+
const name = `${cname}=`
|
|
14
|
+
const decodedCookie = decodeURIComponent(document.cookie)
|
|
15
|
+
const ca = decodedCookie.split(';')
|
|
16
|
+
for (let i = 0; i < ca.length; i++) {
|
|
17
|
+
let c = ca[i]
|
|
18
|
+
while (c.charAt(0) === ' ') c = c.substring(1)
|
|
19
|
+
if (c.indexOf(name) === 0) return c.substring(name.length, c.length)
|
|
20
|
+
}
|
|
21
|
+
return ''
|
|
22
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import DOM from '../../src'
|
|
4
|
+
import { isObjectLike, exec } from '../../src/utils'
|
|
5
|
+
import { classList } from '../../src/element/mixins'
|
|
6
|
+
|
|
7
|
+
import { css } from '@emotion/css'
|
|
8
|
+
|
|
9
|
+
const style = (params, element, node) => {
|
|
10
|
+
const execPareams = exec(params, element)
|
|
11
|
+
if (params) {
|
|
12
|
+
if (isObjectLike(element.class)) element.class.style = execPareams
|
|
13
|
+
else element.class = { style: execPareams }
|
|
14
|
+
}
|
|
15
|
+
classf(element.class, element, node)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const classf = (params, element, node) => {
|
|
19
|
+
if (isObjectLike(params)) {
|
|
20
|
+
const classObjHelper = {}
|
|
21
|
+
for (const key in params) {
|
|
22
|
+
const prop = exec(params[key], element)
|
|
23
|
+
const CSSed = css(prop)
|
|
24
|
+
classObjHelper[key] = CSSed
|
|
25
|
+
}
|
|
26
|
+
classList(classObjHelper, element, node)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
DOM.define({
|
|
31
|
+
style,
|
|
32
|
+
class: classf
|
|
33
|
+
}, {
|
|
34
|
+
overwrite: true
|
|
35
|
+
})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
export const isObject = arg => {
|
|
4
|
+
if (arg === null) return false
|
|
5
|
+
return (typeof arg === 'object') && (arg.constructor === Object)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const isString = arg => typeof arg === 'string'
|
|
9
|
+
|
|
10
|
+
export const isNumber = arg => typeof arg === 'number'
|
|
11
|
+
|
|
12
|
+
export const isFunction = arg => typeof arg === 'function'
|
|
13
|
+
|
|
14
|
+
export const isArray = arg => Array.isArray(arg)
|
|
15
|
+
|
|
16
|
+
export const isObjectLike = arg => {
|
|
17
|
+
if (arg === null) return false
|
|
18
|
+
return (typeof arg === 'object')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const isDefined = arg => {
|
|
22
|
+
return isObject(arg) ||
|
|
23
|
+
isObjectLike(arg) ||
|
|
24
|
+
isString(arg) ||
|
|
25
|
+
isNumber(arg) ||
|
|
26
|
+
isFunction(arg) ||
|
|
27
|
+
isArray(arg) ||
|
|
28
|
+
isObjectLike(arg)
|
|
29
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@domql/object",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/domql/domql.git"
|
|
13
|
+
},
|
|
14
|
+
"author": "Rackai",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/domql/domql/issues"
|
|
18
|
+
},
|
|
19
|
+
"homepage": "https://github.com/domql/domql#readme"
|
|
20
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { Link } from '@rackai/symbols'
|
|
4
|
+
import { deepMerge } from '../../src/utils'
|
|
5
|
+
import route from './router'
|
|
6
|
+
|
|
7
|
+
const RouteLink = {
|
|
8
|
+
on: {
|
|
9
|
+
click: (event, element, state) => {
|
|
10
|
+
const root = element.lookup('app')
|
|
11
|
+
const { href } = element.props
|
|
12
|
+
const firstThree = href[0] + href[1] + href[2]
|
|
13
|
+
if (href && firstThree !== 'htt' && firstThree !== 'ske') {
|
|
14
|
+
route(root, href, {})
|
|
15
|
+
event.preventDefault()
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
deepMerge(Link, RouteLink)
|
|
22
|
+
|
|
23
|
+
export default RouteLink
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
export const splitRoute = (route = window.location.pathname) => route.slice(1).split('/')
|
|
4
|
+
|
|
5
|
+
export default (rootElement, path, state = {}, level = 0, pushState = true) => {
|
|
6
|
+
const route = path || window.location.pathname
|
|
7
|
+
const routes = splitRoute(route)
|
|
8
|
+
|
|
9
|
+
const content = rootElement.routes[`/${routes[level]}`]
|
|
10
|
+
|
|
11
|
+
if (content) {
|
|
12
|
+
if (pushState) window.history.pushState(state, null, route)
|
|
13
|
+
rootElement.set({ proto: content })
|
|
14
|
+
.node.scrollIntoView({ behavior: 'smooth' })
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (level === 0) rootElement.state.update({ activePage: routes[level] })
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Receives child and parent nodes as parametes
|
|
5
|
+
* and assigns them into real DOM tree
|
|
6
|
+
*/
|
|
7
|
+
export const appendNode = (node, parentNode) => {
|
|
8
|
+
parentNode.appendChild(node)
|
|
9
|
+
return node
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Receives elements and assigns the first
|
|
14
|
+
* parameter as a child of the second one
|
|
15
|
+
*/
|
|
16
|
+
export const assignNode = (element, parent, key) => {
|
|
17
|
+
parent[key || element.key] = element
|
|
18
|
+
if (element.tag !== 'shadow') {
|
|
19
|
+
appendNode(element.node, parent.node)
|
|
20
|
+
}
|
|
21
|
+
return element
|
|
22
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import { can } from '../event'
|
|
4
|
+
import { exec, isString, isTagRegistered, report } from '../utils'
|
|
5
|
+
|
|
6
|
+
const cachedElements = {}
|
|
7
|
+
|
|
8
|
+
const createNode = (element) => {
|
|
9
|
+
const { tag } = element
|
|
10
|
+
if (tag) {
|
|
11
|
+
if (tag === 'string') return document.createTextNode(element.text)
|
|
12
|
+
else if (tag === 'fragment') {
|
|
13
|
+
return document.createDocumentFragment()
|
|
14
|
+
} else if (tag === 'svg' || tag === 'path') { // change that
|
|
15
|
+
return document.createElementNS('http://www.w3.org/2000/svg', tag)
|
|
16
|
+
} else return document.createElement(tag)
|
|
17
|
+
} else {
|
|
18
|
+
return document.createElement('div')
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const detectTag = element => {
|
|
23
|
+
let { tag, key } = element
|
|
24
|
+
tag = exec(tag, element)
|
|
25
|
+
|
|
26
|
+
if (tag === true) tag = key
|
|
27
|
+
|
|
28
|
+
if (isString(tag)) {
|
|
29
|
+
const tagExists = isTagRegistered(tag) > -1
|
|
30
|
+
if (tagExists) return tag
|
|
31
|
+
} else {
|
|
32
|
+
const isKeyATag = isTagRegistered(key) > -1
|
|
33
|
+
if (isKeyATag) return key
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return 'div'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default (element) => {
|
|
40
|
+
const tag = element.tag = detectTag(element)
|
|
41
|
+
|
|
42
|
+
if (!can.render(element)) {
|
|
43
|
+
return report('HTMLInvalidTag')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let cachedTag = cachedElements[tag]
|
|
47
|
+
if (!cachedTag) cachedTag = cachedElements[tag] = createNode(element)
|
|
48
|
+
|
|
49
|
+
const clonedNode = cachedTag.cloneNode(true)
|
|
50
|
+
if (tag === 'string') clonedNode.nodeValue = element.text
|
|
51
|
+
return clonedNode
|
|
52
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
import root from './root'
|
|
4
|
+
import createNode from './createNode'
|
|
5
|
+
import { appendNode, assignNode } from './assign'
|
|
6
|
+
import { applyPrototype } from './proto'
|
|
7
|
+
import nodes from './nodes'
|
|
8
|
+
import set from './set'
|
|
9
|
+
import createState from './createState'
|
|
10
|
+
import createProps from './createProps'
|
|
11
|
+
import update from './update'
|
|
12
|
+
import * as on from '../event/on'
|
|
13
|
+
import { assignClass } from './mixins/classList'
|
|
14
|
+
import { isFunction, isNumber, isString, createID, isNode } from '../utils'
|
|
15
|
+
import { remove, lookup, log, keys, parse, parseDeep } from './methods'
|
|
16
|
+
import cacheNode from './cache'
|
|
17
|
+
// import { overwrite, clone, fillTheRest } from '../utils'
|
|
18
|
+
|
|
19
|
+
const ENV = process.env.NODE_ENV
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Creating a domQL element using passed parameters
|
|
23
|
+
*/
|
|
24
|
+
const create = (element, parent, key, options = {}) => {
|
|
25
|
+
// if ELEMENT is not given
|
|
26
|
+
if (element === undefined) element = {}
|
|
27
|
+
if (element === null) return
|
|
28
|
+
|
|
29
|
+
// define KEY
|
|
30
|
+
const assignedKey = element.key || key || createID.next().value
|
|
31
|
+
|
|
32
|
+
// if PARENT is not given
|
|
33
|
+
// if (parent === null) parent = root
|
|
34
|
+
// if (parent === undefined) parent = root
|
|
35
|
+
if (!parent) parent = root
|
|
36
|
+
if (isNode(parent)) parent = root[`${key}_parent`] = { node: parent }
|
|
37
|
+
|
|
38
|
+
// if (assignedKey === 'all') debugger
|
|
39
|
+
|
|
40
|
+
// if element is STRING
|
|
41
|
+
if (isString(element) || isNumber(element)) {
|
|
42
|
+
element = {
|
|
43
|
+
text: element,
|
|
44
|
+
tag: (!element.proto && parent.childProto && parent.childProto.tag) ||
|
|
45
|
+
((nodes.body.indexOf(key) > -1) && key) || 'string'
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// enable STATE
|
|
50
|
+
element.state = createState(element, parent)
|
|
51
|
+
|
|
52
|
+
// create PROTOtypal inheritance
|
|
53
|
+
applyPrototype(element, parent, options)
|
|
54
|
+
|
|
55
|
+
// console.groupCollapsed('Create:', assignedKey)
|
|
56
|
+
// console.log(element)
|
|
57
|
+
|
|
58
|
+
// create and assign a KEY
|
|
59
|
+
element.key = assignedKey
|
|
60
|
+
|
|
61
|
+
// set the PATH
|
|
62
|
+
if (ENV === 'test' || ENV === 'development') {
|
|
63
|
+
if (!parent.path) parent.path = []
|
|
64
|
+
element.path = parent.path.concat(assignedKey)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// if it already HAS A NODE
|
|
68
|
+
if (element.node) {
|
|
69
|
+
// console.log('hasNode!')
|
|
70
|
+
// console.groupEnd('Create:')
|
|
71
|
+
return assignNode(element, parent, assignedKey)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// generate a CLASS name
|
|
75
|
+
assignClass(element)
|
|
76
|
+
|
|
77
|
+
// assign METHODS
|
|
78
|
+
element.set = set
|
|
79
|
+
element.update = update
|
|
80
|
+
element.remove = remove
|
|
81
|
+
element.lookup = lookup
|
|
82
|
+
if (ENV === 'test' || ENV === 'development') {
|
|
83
|
+
element.keys = keys
|
|
84
|
+
element.parse = parse
|
|
85
|
+
element.parseDeep = parseDeep
|
|
86
|
+
element.log = log
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// run `on.init`
|
|
90
|
+
if (element.on && isFunction(element.on.init)) {
|
|
91
|
+
on.init(element.on.init, element, element.state)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// enable TRANSFORM in data
|
|
95
|
+
if (!element.transform) element.transform = {}
|
|
96
|
+
|
|
97
|
+
// enable CACHING
|
|
98
|
+
if (!element.__cached) element.__cached = {}
|
|
99
|
+
|
|
100
|
+
// enable EXEC
|
|
101
|
+
if (!element.__exec) element.__exec = {}
|
|
102
|
+
|
|
103
|
+
// enable CHANGES storing
|
|
104
|
+
if (!element.__changes) element.__changes = []
|
|
105
|
+
|
|
106
|
+
// enable CHANGES storing
|
|
107
|
+
const hasRoot = parent.parent && parent.parent.key === ':root'
|
|
108
|
+
if (!element.__root) element.__root = hasRoot ? parent : parent.__root
|
|
109
|
+
|
|
110
|
+
// apply props settings
|
|
111
|
+
createProps(element, parent)
|
|
112
|
+
|
|
113
|
+
// console.log('cache.props:')
|
|
114
|
+
// console.log(cache.props)
|
|
115
|
+
// console.log('applied props:')
|
|
116
|
+
// console.log(element.props)
|
|
117
|
+
// console.log('element:')
|
|
118
|
+
// console.log(element)
|
|
119
|
+
// console.groupEnd('Create:')
|
|
120
|
+
|
|
121
|
+
// don't render IF in condition
|
|
122
|
+
if (isFunction(element.if) && !element.if(element, element.state)) {
|
|
123
|
+
// TODO: move as fragment
|
|
124
|
+
const ifFragment = cacheNode({ tag: 'fragment' })
|
|
125
|
+
element.__ifFragment = appendNode(ifFragment, parent.node)
|
|
126
|
+
element.__ifFalsy = true
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// CREATE a real NODE
|
|
131
|
+
createNode(element)
|
|
132
|
+
|
|
133
|
+
// assign NODE
|
|
134
|
+
assignNode(element, parent, key)
|
|
135
|
+
|
|
136
|
+
// run `on.render`
|
|
137
|
+
if (element.on && isFunction(element.on.render)) {
|
|
138
|
+
on.render(element.on.render, element, element.state)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return element
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export default create
|