solarite 0.2.4 → 0.3.0
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/dist/Solarite-debug.js +1671 -1492
- package/dist/Solarite.js +1536 -1259
- package/dist/Solarite.min.js +2 -2
- package/package.json +1 -1
- package/readme.md +1 -3
- package/src/solarite/ExprPath.js +426 -210
- package/src/solarite/Globals.js +77 -52
- package/src/solarite/HtmlParser.js +91 -0
- package/src/solarite/NodeGroup.js +275 -219
- package/src/solarite/Shell.js +117 -91
- package/src/solarite/Solarite.js +7 -3
- package/src/solarite/Template.js +21 -18
- package/src/solarite/Util.js +117 -179
- package/src/solarite/createSolarite.js +16 -138
- package/src/solarite/getArg.js +17 -12
- package/src/solarite/{r.js → h.js} +56 -18
- package/src/solarite/hash.js +12 -9
- package/src/solarite/watch.js +546 -0
- package/src/util/Errors.js +1 -0
- package/src/util/MultiValueMap.js +42 -15
- package/src/util/Util.js +5 -17
- package/src/util/delve.js +5 -4
- package/src/solarite/watch3.js +0 -189
- package/src/util/WeakArray.js +0 -33
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import Template from "./Template.js";
|
|
2
2
|
import Util from "./Util.js";
|
|
3
3
|
import Globals from "./Globals.js";
|
|
4
|
+
import {assert} from "../util/Errors.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Convert strings to HTMLNodes.
|
|
7
|
-
* Using
|
|
8
|
-
* Using
|
|
8
|
+
* Using h`...` as a tag will always create a Template.
|
|
9
|
+
* Using h() as a function() will always create a DOM element.
|
|
9
10
|
*
|
|
10
11
|
* Features beyond what standard js tagged template strings do:
|
|
11
12
|
* 1. r`` sub-expressions
|
|
@@ -15,24 +16,25 @@ import Globals from "./Globals.js";
|
|
|
15
16
|
* 5. TODO: list more
|
|
16
17
|
*
|
|
17
18
|
* Currently supported:
|
|
18
|
-
* 1.
|
|
19
|
-
* 2.
|
|
19
|
+
* 1. h(el, options)`<b>${'Hi'}</b>` // Create template and render its nodes to el.
|
|
20
|
+
* 2. h(el, template, ?options) // Render the Template created by #1 to element.
|
|
20
21
|
*
|
|
21
|
-
* 3.
|
|
22
|
+
* 3. h`<b>Hello</b> ${'World'}!` // Create Template that can later be used to create nodes.
|
|
22
23
|
*
|
|
23
|
-
* 4.
|
|
24
|
-
* 5.
|
|
25
|
-
* 6.
|
|
26
|
-
* 7.
|
|
24
|
+
* 4. h('Hello'); // Create single text node.
|
|
25
|
+
* 5. h('<b>Hello</b>'); // Create single HTMLElement
|
|
26
|
+
* 6. h('<b>Hello</b><u>Goodbye</u>'); // Create document fragment because there's more than one node.
|
|
27
|
+
* 7. h()`Hello<b>${'World'}!</b>` // Same as 4-6, but evaluates the string as a Solarite template, which
|
|
27
28
|
* // includes properly handling nested components and r`` sub-expressions.
|
|
28
|
-
* 8.
|
|
29
|
-
*
|
|
30
|
-
* 9. r({render(){...}}) // Pass an object with a render method, and optionally other props/methods.
|
|
29
|
+
* 8. h(template) // Render Template created by #1.
|
|
31
30
|
*
|
|
31
|
+
* 9. h({render(){...}}) // Pass an object with a render method, and optionally other props/methods.
|
|
32
|
+
* 10. h(string, object, ...) // JSX TODO
|
|
32
33
|
* @param htmlStrings {?HTMLElement|string|string[]|function():Template|{render:function()}}
|
|
33
34
|
* @param exprs {*[]|string|Template|Object}
|
|
34
35
|
* @return {Node|HTMLElement|Template} */
|
|
35
|
-
export default function
|
|
36
|
+
export default function h(htmlStrings=undefined, ...exprs) {
|
|
37
|
+
|
|
36
38
|
|
|
37
39
|
// TODO: Make this a more flat if/else and call other functions for the logic.
|
|
38
40
|
if (htmlStrings instanceof Node) {
|
|
@@ -84,6 +86,23 @@ export default function r(htmlStrings=undefined, ...exprs) {
|
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
else if (typeof htmlStrings === 'string' || htmlStrings instanceof String) {
|
|
89
|
+
// 10. JSX
|
|
90
|
+
if (typeof exprs[0] === 'object') {
|
|
91
|
+
let tag = htmlStrings;
|
|
92
|
+
let props = exprs[0] || {};
|
|
93
|
+
let children = exprs.slice(1);
|
|
94
|
+
|
|
95
|
+
let templateHtmlStrings = [];
|
|
96
|
+
let templateExprs = [];
|
|
97
|
+
|
|
98
|
+
// TODO How to know which children are static html and which are expression placeholders?
|
|
99
|
+
// Perhaps we have to treat every text child as a string?
|
|
100
|
+
|
|
101
|
+
assert(templateHtmlStrings.length === templateExprs.length+1);
|
|
102
|
+
return new Template(templateHtmlStrings, templateExprs);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
87
106
|
// If it starts with a string, trim both ends.
|
|
88
107
|
// TODO: Also trim if it ends with whitespace?
|
|
89
108
|
if (htmlStrings.match(/^\s^</))
|
|
@@ -107,7 +126,7 @@ export default function r(htmlStrings=undefined, ...exprs) {
|
|
|
107
126
|
else if (htmlStrings === undefined) {
|
|
108
127
|
return (htmlStrings, ...exprs) => {
|
|
109
128
|
//Globals.rendered.add(parent)
|
|
110
|
-
let template =
|
|
129
|
+
let template = h(htmlStrings, ...exprs);
|
|
111
130
|
return template.render();
|
|
112
131
|
}
|
|
113
132
|
}
|
|
@@ -119,13 +138,19 @@ export default function r(htmlStrings=undefined, ...exprs) {
|
|
|
119
138
|
|
|
120
139
|
|
|
121
140
|
// 9. Create dynamic element with render() function.
|
|
141
|
+
// TODO: This path doesn't handle embeds like data-id="..."
|
|
122
142
|
else if (typeof htmlStrings === 'object') {
|
|
123
143
|
let obj = htmlStrings;
|
|
124
144
|
|
|
145
|
+
if (obj.constructor.name !== 'Object')
|
|
146
|
+
throw new Error(`Solarate Web Component class ${obj.constructor?.name} must extend HTMLElement.`);
|
|
147
|
+
|
|
148
|
+
|
|
125
149
|
// Special rebound render path, called by normal path.
|
|
150
|
+
// Intercepts the main r`...` function call inside render().
|
|
126
151
|
if (Globals.objToEl.has(obj)) {
|
|
127
152
|
return function(...args) {
|
|
128
|
-
let template =
|
|
153
|
+
let template = h(...args);
|
|
129
154
|
let el = template.render();
|
|
130
155
|
Globals.objToEl.set(obj, el);
|
|
131
156
|
}.bind(obj);
|
|
@@ -134,20 +159,33 @@ export default function r(htmlStrings=undefined, ...exprs) {
|
|
|
134
159
|
// Normal path
|
|
135
160
|
else {
|
|
136
161
|
Globals.objToEl.set(obj, null);
|
|
137
|
-
obj
|
|
162
|
+
obj[renderF](); // Calls the Special rebound render path above, when the render function calls r(this)
|
|
138
163
|
let el = Globals.objToEl.get(obj);
|
|
139
164
|
Globals.objToEl.delete(obj);
|
|
140
165
|
|
|
141
166
|
for (let name in obj)
|
|
142
167
|
if (typeof obj[name] === 'function')
|
|
143
|
-
el[name] = obj[name].bind(el);
|
|
168
|
+
el[name] = obj[name].bind(el); // Make the "this" of functions be el.
|
|
169
|
+
// TODO: But this doesn't work for passing an object with functions as a constructor arg via an attribute:
|
|
170
|
+
// <my-element arg=${{myFunc() { return this }}}
|
|
144
171
|
else
|
|
145
172
|
el[name] = obj[name];
|
|
146
173
|
|
|
174
|
+
// Bind id's
|
|
175
|
+
// This doesn't work for id's referenced by attributes.
|
|
176
|
+
// for (let idEl of el.querySelectorAll('[id],[data-id]')) {
|
|
177
|
+
// Util.bindId(el, idEl);
|
|
178
|
+
// Util.bindId(obj, idEl);
|
|
179
|
+
// }
|
|
180
|
+
// TODO: Bind styles
|
|
181
|
+
|
|
147
182
|
return el;
|
|
148
183
|
}
|
|
149
184
|
}
|
|
150
185
|
|
|
151
186
|
else
|
|
152
187
|
throw new Error('Unsupported arguments.')
|
|
153
|
-
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Trick to prevent minifier from renaming this function.
|
|
191
|
+
let renderF = 'render';
|
package/src/solarite/hash.js
CHANGED
|
@@ -10,7 +10,7 @@ export function getObjectId(obj) {
|
|
|
10
10
|
|
|
11
11
|
let result = objectIds.get(obj);
|
|
12
12
|
if (!result) { // convert to string, store in result, then add 1 to lastObjectId.
|
|
13
|
-
result = (lastObjectId++); // We use a unique prefix to ensure it doesn't collide w/ strings not from getObjectId()
|
|
13
|
+
result = '~\f' + (lastObjectId++); // We use a unique, 2-byte prefix to ensure it doesn't collide w/ strings not from getObjectId()
|
|
14
14
|
objectIds.set(obj, result)
|
|
15
15
|
}
|
|
16
16
|
return result;
|
|
@@ -29,14 +29,7 @@ function toJSON() {
|
|
|
29
29
|
|
|
30
30
|
// Node.prototype.toJSON = toJSON;
|
|
31
31
|
// Function.prototype.toJSON = toJSON;
|
|
32
|
-
|
|
33
|
-
// The same tests sometimes pass, sometimes fail, even after browser and OS restarts.
|
|
34
|
-
// So we check the assignments on every run of getObjectHash()
|
|
35
|
-
if (Node.prototype.toJSON !== toJSON) {
|
|
36
|
-
Node.prototype.toJSON = toJSON;
|
|
37
|
-
if (Function.prototype.toJSON !== toJSON) // Will it only unmap one but not the other?
|
|
38
|
-
Function.prototype.toJSON = toJSON;
|
|
39
|
-
}
|
|
32
|
+
|
|
40
33
|
|
|
41
34
|
/**
|
|
42
35
|
* Get a string that uniquely maps to the values of the given object.
|
|
@@ -51,6 +44,16 @@ if (Node.prototype.toJSON !== toJSON) {
|
|
|
51
44
|
* @param obj {*}
|
|
52
45
|
* @returns {string} */
|
|
53
46
|
export function getObjectHash(obj) {
|
|
47
|
+
|
|
48
|
+
// Sometimes these get unassigned by Chrome and Brave 119, as well as Firefox, seemingly randomly!
|
|
49
|
+
// The same tests sometimes pass, sometimes fail, even after browser and OS restarts.
|
|
50
|
+
// So we check the assignments on every run of getObjectHash()
|
|
51
|
+
if (Node.prototype.toJSON !== toJSON) {
|
|
52
|
+
Node.prototype.toJSON = toJSON;
|
|
53
|
+
if (Function.prototype.toJSON !== toJSON) // Will it only unmap one but not the other?
|
|
54
|
+
Function.prototype.toJSON = toJSON;
|
|
55
|
+
}
|
|
56
|
+
|
|
54
57
|
let result;
|
|
55
58
|
isHashing = true;
|
|
56
59
|
try {
|