solarite 0.5.0 → 0.5.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/dist/Solarite-debug.js +188 -6
- package/dist/Solarite.js +188 -6
- package/dist/Solarite.min.js +2 -2
- package/package.json +1 -1
- package/src/PathToAttribValue.js +3 -0
- package/src/PathToAttribs.js +4 -0
- package/src/PathToComponent.js +22 -2
- package/src/PathToEvent.js +8 -0
- package/src/Shell.js +10 -3
- package/src/Solarite.d.ts +8 -1
- package/src/Solarite.js +138 -0
- package/src/Template.js +3 -0
package/dist/Solarite-debug.js
CHANGED
|
@@ -876,6 +876,9 @@ class PathToAttribValue extends Path {
|
|
|
876
876
|
* @type {?string[]} Used only if type=AttribType.Value. If null, use one expr to set the whole attribute value. */
|
|
877
877
|
attrValue;
|
|
878
878
|
|
|
879
|
+
/** @type {boolean} Provides value for attribute on a component. */
|
|
880
|
+
isComponent;
|
|
881
|
+
|
|
879
882
|
isHtmlProperty;
|
|
880
883
|
|
|
881
884
|
constructor(nodeBefore, nodeMarker, attrName=null, attrValue=null) {
|
|
@@ -1140,6 +1143,14 @@ class PathToEvent extends PathToAttribValue {
|
|
|
1140
1143
|
assert(Array.isArray(exprs));
|
|
1141
1144
|
//#ENDIF
|
|
1142
1145
|
|
|
1146
|
+
// Tested by Solariate.events.classicWithExpr
|
|
1147
|
+
// We have expressions within a string attribute value that's not a Solarite event. E.g.
|
|
1148
|
+
// <div onclick="alert(${1});"
|
|
1149
|
+
if (this.attrValue?.length > 1) {
|
|
1150
|
+
super.apply(exprs);
|
|
1151
|
+
return;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1143
1154
|
// Don't bind events to component placeholders.
|
|
1144
1155
|
// PathToComponent will do the binding later when it instantiates the component.
|
|
1145
1156
|
if (this.isComponentAttrib && this.nodeMarker.tagName.endsWith('-SOLARITE-PLACEHOLDER'))
|
|
@@ -1182,6 +1193,9 @@ class PathToAttribs extends Path {
|
|
|
1182
1193
|
* @type {Set<string>} Used for type=AttribType.Multiple to remember the attributes that were added. */
|
|
1183
1194
|
attrNames;
|
|
1184
1195
|
|
|
1196
|
+
/** @type {boolean} Provides one or more attributes on a component. */
|
|
1197
|
+
isComponent;
|
|
1198
|
+
|
|
1185
1199
|
constructor(nodeBefore, nodeMarker) {
|
|
1186
1200
|
super(null, null);
|
|
1187
1201
|
this.nodeMarker = nodeMarker;
|
|
@@ -1248,6 +1262,7 @@ class PathToAttribs extends Path {
|
|
|
1248
1262
|
|
|
1249
1263
|
|
|
1250
1264
|
getExpressionCount() { return 1 }
|
|
1265
|
+
getValue(exprs) { return exprs[0]; }
|
|
1251
1266
|
}
|
|
1252
1267
|
|
|
1253
1268
|
/**
|
|
@@ -2088,8 +2103,27 @@ class PathToComponent extends Path {
|
|
|
2088
2103
|
// 1. Attributes
|
|
2089
2104
|
let attribs = Util.attribsToObject(el, '_is');
|
|
2090
2105
|
for (let i=0, attribPath; attribPath = this.attribPaths[i]; i++) {
|
|
2091
|
-
|
|
2092
|
-
|
|
2106
|
+
if (attribPath instanceof PathToAttribValue) {
|
|
2107
|
+
let name = Util.dashesToCamel(attribPath.attrName);
|
|
2108
|
+
attribs[name] = attribPath.getValue(exprs[i]);
|
|
2109
|
+
}
|
|
2110
|
+
else { // PathToAttribs
|
|
2111
|
+
let val = attribPath.getValue(exprs[i]);
|
|
2112
|
+
if (typeof val === 'object')
|
|
2113
|
+
for (let name in val)
|
|
2114
|
+
attribs[Util.dashesToCamel(name)] = val[name];
|
|
2115
|
+
else if (typeof val === 'string') {
|
|
2116
|
+
let attrs = val.split(/([\w-]+\s*=\s*(?:"[^"]*"|'[^']*'|\S+))/g)
|
|
2117
|
+
.map(text => text.trim())
|
|
2118
|
+
.filter(text => text.length);
|
|
2119
|
+
|
|
2120
|
+
for (let attr of attrs) {
|
|
2121
|
+
let [name, value] = attr.split(/\s*=\s*/); // split on first equals.
|
|
2122
|
+
value = (value || '').replace(/^(['"])(.*)\1$/, '$2'); // trim value quotes if they match.
|
|
2123
|
+
attribs[Util.dashesToCamel(name)] = value;
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2093
2127
|
}
|
|
2094
2128
|
|
|
2095
2129
|
// 2. Instantiate component on first time.
|
|
@@ -2281,13 +2315,15 @@ class Shell {
|
|
|
2281
2315
|
|
|
2282
2316
|
for (let attr of [...node.attributes]) { // Copy the attributes array b/c we remove attributes with placeholders as we go.
|
|
2283
2317
|
|
|
2284
|
-
//
|
|
2318
|
+
// One or more whole attributes
|
|
2285
2319
|
let matches = attr.name.match(/^[\ue000-\uf8ff]$/);
|
|
2286
2320
|
if (matches) {
|
|
2287
2321
|
let path = new PathToAttribs(null, node);
|
|
2288
2322
|
this.paths.push(path);
|
|
2289
|
-
if (isComponent)
|
|
2323
|
+
if (isComponent) {
|
|
2324
|
+
path.isComponentAttrib = true;
|
|
2290
2325
|
componentAttribPaths.push(path);
|
|
2326
|
+
}
|
|
2291
2327
|
|
|
2292
2328
|
placeholdersUsed ++;
|
|
2293
2329
|
node.removeAttribute(matches[0]); // TODO: Is this necessary?
|
|
@@ -2310,7 +2346,12 @@ class Shell {
|
|
|
2310
2346
|
}
|
|
2311
2347
|
|
|
2312
2348
|
placeholdersUsed += parts.length - 1;
|
|
2313
|
-
|
|
2349
|
+
try {
|
|
2350
|
+
node.setAttribute(attr.name, parts.join(''));
|
|
2351
|
+
}
|
|
2352
|
+
catch (e) {
|
|
2353
|
+
throw new Error(`Error setting attribute "${attr.name}" on node <${node.tagName}>: ${e.message}`);
|
|
2354
|
+
}
|
|
2314
2355
|
}
|
|
2315
2356
|
}
|
|
2316
2357
|
}
|
|
@@ -3018,6 +3059,9 @@ class Template {
|
|
|
3018
3059
|
/** @type {Array} Used for toJSON() and getObjectHash(). Stores values used to quickly create a string hash of this template. */
|
|
3019
3060
|
hashedFields;
|
|
3020
3061
|
|
|
3062
|
+
closeKey;
|
|
3063
|
+
exactKey;
|
|
3064
|
+
|
|
3021
3065
|
isText;
|
|
3022
3066
|
|
|
3023
3067
|
/**
|
|
@@ -3730,7 +3774,145 @@ class Solarite extends HTMLElementAutoDefine {
|
|
|
3730
3774
|
}
|
|
3731
3775
|
return result;
|
|
3732
3776
|
}
|
|
3777
|
+
|
|
3778
|
+
|
|
3779
|
+
// TODO: Do we want to use this to get the tag name from the render() function, instead of having the user define it?
|
|
3780
|
+
/**
|
|
3781
|
+
* Get the tag name for a class, as defined by the tag used in render().
|
|
3782
|
+
*
|
|
3783
|
+
* This will parse the JavaScript code of the render() function to find the tag name.
|
|
3784
|
+
* It will itarage every character, keeping track of quotes and comments so it can
|
|
3785
|
+
* skip them until it finds the tag name passed to h(this)`<tagname>` inside the render() function.
|
|
3786
|
+
*
|
|
3787
|
+
* */
|
|
3788
|
+
/*
|
|
3789
|
+
static getTagName(Class) {
|
|
3790
|
+
let code = Class.prototype.render.toString();
|
|
3791
|
+
let i = 0;
|
|
3792
|
+
while (i < code.length) {
|
|
3793
|
+
let char = code[i];
|
|
3794
|
+
let next = code[i + 1];
|
|
3795
|
+
|
|
3796
|
+
// Skip single line comments
|
|
3797
|
+
if (char === '/' && next === '/') {
|
|
3798
|
+
i = code.indexOf('\n', i);
|
|
3799
|
+
if (i === -1) break;
|
|
3800
|
+
continue;
|
|
3801
|
+
}
|
|
3802
|
+
// Skip multi-line comments
|
|
3803
|
+
if (char === '/' && next === '*') {
|
|
3804
|
+
i = code.indexOf('*'+'/', i + 2);
|
|
3805
|
+
if (i === -1) break;
|
|
3806
|
+
i += 2;
|
|
3807
|
+
continue;
|
|
3808
|
+
}
|
|
3809
|
+
// Skip strings and template literals
|
|
3810
|
+
if (char === "'" || char === '"' || char === '`') {
|
|
3811
|
+
let quote = char;
|
|
3812
|
+
i++;
|
|
3813
|
+
while (i < code.length) {
|
|
3814
|
+
if (code[i] === '\\') i += 2;
|
|
3815
|
+
else if (code[i] === quote) { i++; break; }
|
|
3816
|
+
else i++;
|
|
3817
|
+
}
|
|
3818
|
+
continue;
|
|
3819
|
+
}
|
|
3820
|
+
// Skip regex literals (simple heuristic)
|
|
3821
|
+
if (char === '/') {
|
|
3822
|
+
let prev = code.slice(Math.max(0, i - 10), i).trim();
|
|
3823
|
+
// If / is preceded by something that indicates an operator or start of expression
|
|
3824
|
+
if (/[=(,;:[!&|?]$|return$|yield$|case$/.test(prev)) {
|
|
3825
|
+
i++;
|
|
3826
|
+
while (i < code.length) {
|
|
3827
|
+
if (code[i] === '\\') i += 2;
|
|
3828
|
+
else if (code[i] === '[') { // Skip character classes
|
|
3829
|
+
i++;
|
|
3830
|
+
while (i < code.length && code[i] !== ']') {
|
|
3831
|
+
if (code[i] === '\\') i += 2;
|
|
3832
|
+
else i++;
|
|
3833
|
+
}
|
|
3834
|
+
i++;
|
|
3835
|
+
}
|
|
3836
|
+
else if (code[i] === '/') { i++; break; }
|
|
3837
|
+
else i++;
|
|
3838
|
+
}
|
|
3839
|
+
continue;
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
// Check for h(this)`
|
|
3843
|
+
if (char === 'h' && code.slice(i, i + 8) === 'h(this)`') {
|
|
3844
|
+
i += 8;
|
|
3845
|
+
// We are now inside the template literal.
|
|
3846
|
+
// Skip whitespace and HTML comments
|
|
3847
|
+
while (i < code.length) {
|
|
3848
|
+
// Skip JS template literal end (shouldn't happen before tag, but for safety)
|
|
3849
|
+
if (code[i] === '`') return null;
|
|
3850
|
+
|
|
3851
|
+
// Skip whitespace
|
|
3852
|
+
if (/\s/.test(code[i])) { i++; continue; }
|
|
3853
|
+
|
|
3854
|
+
// Skip HTML comments <!-- ... -->
|
|
3855
|
+
if (code.slice(i, i + 4) === '<!--') {
|
|
3856
|
+
i = code.indexOf('-->', i + 4);
|
|
3857
|
+
if (i === -1) return null;
|
|
3858
|
+
i += 3;
|
|
3859
|
+
continue;
|
|
3860
|
+
}
|
|
3861
|
+
|
|
3862
|
+
// Find the first tag
|
|
3863
|
+
if (code[i] === '<') {
|
|
3864
|
+
let start = ++i;
|
|
3865
|
+
while (i < code.length && /[a-zA-Z0-9-]/.test(code[i])) i++;
|
|
3866
|
+
return code.slice(start, i);
|
|
3867
|
+
}
|
|
3868
|
+
|
|
3869
|
+
// If we encounter anything else (like text before a tag),
|
|
3870
|
+
// we can keep looking or return null depending on how strict we want to be.
|
|
3871
|
+
// For now, let's just skip non-tag characters.
|
|
3872
|
+
i++;
|
|
3873
|
+
}
|
|
3874
|
+
}
|
|
3875
|
+
i++;
|
|
3876
|
+
}
|
|
3877
|
+
return null;
|
|
3878
|
+
}
|
|
3879
|
+
*/
|
|
3880
|
+
}
|
|
3881
|
+
|
|
3882
|
+
|
|
3883
|
+
/**
|
|
3884
|
+
* Assign fields from `src` to `dest` if they exist in `dest` and their names are not in the `ignore` list.
|
|
3885
|
+
* When a value in `src` is a string and the existing value in `dest` is a boolean, number, or Date,
|
|
3886
|
+
* it will be converted to that type.
|
|
3887
|
+
* This is often used in class constructors that accept an object of arguments.
|
|
3888
|
+
* @param {object} dest
|
|
3889
|
+
* @param {?object} src
|
|
3890
|
+
* @param {string[]} [ignore=[]] */
|
|
3891
|
+
function assignFields(dest, src, ignore=[]) {
|
|
3892
|
+
for (let name in src || {}) {
|
|
3893
|
+
if (name in dest && !ignore.includes(name)) {
|
|
3894
|
+
const descriptor = Object.getOwnPropertyDescriptor(dest, name)
|
|
3895
|
+
|| Object.getOwnPropertyDescriptor(Object.getPrototypeOf(dest), name); // Also find (parent?) setters. Is this necssary?
|
|
3896
|
+
if (!descriptor || descriptor.writable || descriptor.set) {
|
|
3897
|
+
let srcVal = src[name];
|
|
3898
|
+
let destVal = dest[name];
|
|
3899
|
+
if (typeof src[name] === 'string') {
|
|
3900
|
+
if (typeof destVal === 'boolean') // empty string (when an attribute is present with no value) is true
|
|
3901
|
+
dest[name] = ![false, 'false', 0, '0'].includes(srcVal);
|
|
3902
|
+
else if (typeof destVal === 'number')
|
|
3903
|
+
dest[name] = Number(srcVal);
|
|
3904
|
+
else if (destVal instanceof Date) {
|
|
3905
|
+
dest[name] = new Date(srcVal); // TODO: read it as UTC 0 by default.
|
|
3906
|
+
}
|
|
3907
|
+
else
|
|
3908
|
+
dest[name] = srcVal;
|
|
3909
|
+
}
|
|
3910
|
+
else
|
|
3911
|
+
dest[name] = srcVal;
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
}
|
|
3733
3915
|
}
|
|
3734
3916
|
|
|
3735
3917
|
export default h;
|
|
3736
|
-
export { ArgType, Globals$1 as Globals, HtmlParser, NodeGroup, Shell, Solarite, Util as SolariteUtil, Template, delve, getArg, h, h as r, setArgs, t, toEl };
|
|
3918
|
+
export { ArgType, Globals$1 as Globals, HtmlParser, NodeGroup, Shell, Solarite, Util as SolariteUtil, Template, assignFields, delve, getArg, h, h as r, setArgs, t, toEl };
|
package/dist/Solarite.js
CHANGED
|
@@ -774,6 +774,9 @@ class PathToAttribValue extends Path {
|
|
|
774
774
|
* @type {?string[]} Used only if type=AttribType.Value. If null, use one expr to set the whole attribute value. */
|
|
775
775
|
attrValue;
|
|
776
776
|
|
|
777
|
+
/** @type {boolean} Provides value for attribute on a component. */
|
|
778
|
+
isComponent;
|
|
779
|
+
|
|
777
780
|
isHtmlProperty;
|
|
778
781
|
|
|
779
782
|
constructor(nodeBefore, nodeMarker, attrName=null, attrValue=null) {
|
|
@@ -1030,6 +1033,14 @@ class PathToEvent extends PathToAttribValue {
|
|
|
1030
1033
|
apply(exprs) {
|
|
1031
1034
|
|
|
1032
1035
|
|
|
1036
|
+
// Tested by Solariate.events.classicWithExpr
|
|
1037
|
+
// We have expressions within a string attribute value that's not a Solarite event. E.g.
|
|
1038
|
+
// <div onclick="alert(${1});"
|
|
1039
|
+
if (this.attrValue?.length > 1) {
|
|
1040
|
+
super.apply(exprs);
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1033
1044
|
// Don't bind events to component placeholders.
|
|
1034
1045
|
// PathToComponent will do the binding later when it instantiates the component.
|
|
1035
1046
|
if (this.isComponentAttrib && this.nodeMarker.tagName.endsWith('-SOLARITE-PLACEHOLDER'))
|
|
@@ -1070,6 +1081,9 @@ class PathToAttribs extends Path {
|
|
|
1070
1081
|
* @type {Set<string>} Used for type=AttribType.Multiple to remember the attributes that were added. */
|
|
1071
1082
|
attrNames;
|
|
1072
1083
|
|
|
1084
|
+
/** @type {boolean} Provides one or more attributes on a component. */
|
|
1085
|
+
isComponent;
|
|
1086
|
+
|
|
1073
1087
|
constructor(nodeBefore, nodeMarker) {
|
|
1074
1088
|
super(null, null);
|
|
1075
1089
|
this.nodeMarker = nodeMarker;
|
|
@@ -1134,6 +1148,7 @@ class PathToAttribs extends Path {
|
|
|
1134
1148
|
|
|
1135
1149
|
|
|
1136
1150
|
getExpressionCount() { return 1 }
|
|
1151
|
+
getValue(exprs) { return exprs[0]; }
|
|
1137
1152
|
}
|
|
1138
1153
|
|
|
1139
1154
|
/**
|
|
@@ -1936,8 +1951,27 @@ class PathToComponent extends Path {
|
|
|
1936
1951
|
// 1. Attributes
|
|
1937
1952
|
let attribs = Util.attribsToObject(el, '_is');
|
|
1938
1953
|
for (let i=0, attribPath; attribPath = this.attribPaths[i]; i++) {
|
|
1939
|
-
|
|
1940
|
-
|
|
1954
|
+
if (attribPath instanceof PathToAttribValue) {
|
|
1955
|
+
let name = Util.dashesToCamel(attribPath.attrName);
|
|
1956
|
+
attribs[name] = attribPath.getValue(exprs[i]);
|
|
1957
|
+
}
|
|
1958
|
+
else { // PathToAttribs
|
|
1959
|
+
let val = attribPath.getValue(exprs[i]);
|
|
1960
|
+
if (typeof val === 'object')
|
|
1961
|
+
for (let name in val)
|
|
1962
|
+
attribs[Util.dashesToCamel(name)] = val[name];
|
|
1963
|
+
else if (typeof val === 'string') {
|
|
1964
|
+
let attrs = val.split(/([\w-]+\s*=\s*(?:"[^"]*"|'[^']*'|\S+))/g)
|
|
1965
|
+
.map(text => text.trim())
|
|
1966
|
+
.filter(text => text.length);
|
|
1967
|
+
|
|
1968
|
+
for (let attr of attrs) {
|
|
1969
|
+
let [name, value] = attr.split(/\s*=\s*/); // split on first equals.
|
|
1970
|
+
value = (value || '').replace(/^(['"])(.*)\1$/, '$2'); // trim value quotes if they match.
|
|
1971
|
+
attribs[Util.dashesToCamel(name)] = value;
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1941
1975
|
}
|
|
1942
1976
|
|
|
1943
1977
|
// 2. Instantiate component on first time.
|
|
@@ -2115,13 +2149,15 @@ class Shell {
|
|
|
2115
2149
|
|
|
2116
2150
|
for (let attr of [...node.attributes]) { // Copy the attributes array b/c we remove attributes with placeholders as we go.
|
|
2117
2151
|
|
|
2118
|
-
//
|
|
2152
|
+
// One or more whole attributes
|
|
2119
2153
|
let matches = attr.name.match(/^[\ue000-\uf8ff]$/);
|
|
2120
2154
|
if (matches) {
|
|
2121
2155
|
let path = new PathToAttribs(null, node);
|
|
2122
2156
|
this.paths.push(path);
|
|
2123
|
-
if (isComponent)
|
|
2157
|
+
if (isComponent) {
|
|
2158
|
+
path.isComponentAttrib = true;
|
|
2124
2159
|
componentAttribPaths.push(path);
|
|
2160
|
+
}
|
|
2125
2161
|
|
|
2126
2162
|
placeholdersUsed ++;
|
|
2127
2163
|
node.removeAttribute(matches[0]); // TODO: Is this necessary?
|
|
@@ -2144,7 +2180,12 @@ class Shell {
|
|
|
2144
2180
|
}
|
|
2145
2181
|
|
|
2146
2182
|
placeholdersUsed += parts.length - 1;
|
|
2147
|
-
|
|
2183
|
+
try {
|
|
2184
|
+
node.setAttribute(attr.name, parts.join(''));
|
|
2185
|
+
}
|
|
2186
|
+
catch (e) {
|
|
2187
|
+
throw new Error(`Error setting attribute "${attr.name}" on node <${node.tagName}>: ${e.message}`);
|
|
2188
|
+
}
|
|
2148
2189
|
}
|
|
2149
2190
|
}
|
|
2150
2191
|
}
|
|
@@ -2773,6 +2814,9 @@ class Template {
|
|
|
2773
2814
|
/** @type {Array} Used for toJSON() and getObjectHash(). Stores values used to quickly create a string hash of this template. */
|
|
2774
2815
|
hashedFields;
|
|
2775
2816
|
|
|
2817
|
+
closeKey;
|
|
2818
|
+
exactKey;
|
|
2819
|
+
|
|
2776
2820
|
isText;
|
|
2777
2821
|
|
|
2778
2822
|
/**
|
|
@@ -3476,7 +3520,145 @@ class Solarite extends HTMLElementAutoDefine {
|
|
|
3476
3520
|
}
|
|
3477
3521
|
return result;
|
|
3478
3522
|
}
|
|
3523
|
+
|
|
3524
|
+
|
|
3525
|
+
// TODO: Do we want to use this to get the tag name from the render() function, instead of having the user define it?
|
|
3526
|
+
/**
|
|
3527
|
+
* Get the tag name for a class, as defined by the tag used in render().
|
|
3528
|
+
*
|
|
3529
|
+
* This will parse the JavaScript code of the render() function to find the tag name.
|
|
3530
|
+
* It will itarage every character, keeping track of quotes and comments so it can
|
|
3531
|
+
* skip them until it finds the tag name passed to h(this)`<tagname>` inside the render() function.
|
|
3532
|
+
*
|
|
3533
|
+
* */
|
|
3534
|
+
/*
|
|
3535
|
+
static getTagName(Class) {
|
|
3536
|
+
let code = Class.prototype.render.toString();
|
|
3537
|
+
let i = 0;
|
|
3538
|
+
while (i < code.length) {
|
|
3539
|
+
let char = code[i];
|
|
3540
|
+
let next = code[i + 1];
|
|
3541
|
+
|
|
3542
|
+
// Skip single line comments
|
|
3543
|
+
if (char === '/' && next === '/') {
|
|
3544
|
+
i = code.indexOf('\n', i);
|
|
3545
|
+
if (i === -1) break;
|
|
3546
|
+
continue;
|
|
3547
|
+
}
|
|
3548
|
+
// Skip multi-line comments
|
|
3549
|
+
if (char === '/' && next === '*') {
|
|
3550
|
+
i = code.indexOf('*'+'/', i + 2);
|
|
3551
|
+
if (i === -1) break;
|
|
3552
|
+
i += 2;
|
|
3553
|
+
continue;
|
|
3554
|
+
}
|
|
3555
|
+
// Skip strings and template literals
|
|
3556
|
+
if (char === "'" || char === '"' || char === '`') {
|
|
3557
|
+
let quote = char;
|
|
3558
|
+
i++;
|
|
3559
|
+
while (i < code.length) {
|
|
3560
|
+
if (code[i] === '\\') i += 2;
|
|
3561
|
+
else if (code[i] === quote) { i++; break; }
|
|
3562
|
+
else i++;
|
|
3563
|
+
}
|
|
3564
|
+
continue;
|
|
3565
|
+
}
|
|
3566
|
+
// Skip regex literals (simple heuristic)
|
|
3567
|
+
if (char === '/') {
|
|
3568
|
+
let prev = code.slice(Math.max(0, i - 10), i).trim();
|
|
3569
|
+
// If / is preceded by something that indicates an operator or start of expression
|
|
3570
|
+
if (/[=(,;:[!&|?]$|return$|yield$|case$/.test(prev)) {
|
|
3571
|
+
i++;
|
|
3572
|
+
while (i < code.length) {
|
|
3573
|
+
if (code[i] === '\\') i += 2;
|
|
3574
|
+
else if (code[i] === '[') { // Skip character classes
|
|
3575
|
+
i++;
|
|
3576
|
+
while (i < code.length && code[i] !== ']') {
|
|
3577
|
+
if (code[i] === '\\') i += 2;
|
|
3578
|
+
else i++;
|
|
3579
|
+
}
|
|
3580
|
+
i++;
|
|
3581
|
+
}
|
|
3582
|
+
else if (code[i] === '/') { i++; break; }
|
|
3583
|
+
else i++;
|
|
3584
|
+
}
|
|
3585
|
+
continue;
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
// Check for h(this)`
|
|
3589
|
+
if (char === 'h' && code.slice(i, i + 8) === 'h(this)`') {
|
|
3590
|
+
i += 8;
|
|
3591
|
+
// We are now inside the template literal.
|
|
3592
|
+
// Skip whitespace and HTML comments
|
|
3593
|
+
while (i < code.length) {
|
|
3594
|
+
// Skip JS template literal end (shouldn't happen before tag, but for safety)
|
|
3595
|
+
if (code[i] === '`') return null;
|
|
3596
|
+
|
|
3597
|
+
// Skip whitespace
|
|
3598
|
+
if (/\s/.test(code[i])) { i++; continue; }
|
|
3599
|
+
|
|
3600
|
+
// Skip HTML comments <!-- ... -->
|
|
3601
|
+
if (code.slice(i, i + 4) === '<!--') {
|
|
3602
|
+
i = code.indexOf('-->', i + 4);
|
|
3603
|
+
if (i === -1) return null;
|
|
3604
|
+
i += 3;
|
|
3605
|
+
continue;
|
|
3606
|
+
}
|
|
3607
|
+
|
|
3608
|
+
// Find the first tag
|
|
3609
|
+
if (code[i] === '<') {
|
|
3610
|
+
let start = ++i;
|
|
3611
|
+
while (i < code.length && /[a-zA-Z0-9-]/.test(code[i])) i++;
|
|
3612
|
+
return code.slice(start, i);
|
|
3613
|
+
}
|
|
3614
|
+
|
|
3615
|
+
// If we encounter anything else (like text before a tag),
|
|
3616
|
+
// we can keep looking or return null depending on how strict we want to be.
|
|
3617
|
+
// For now, let's just skip non-tag characters.
|
|
3618
|
+
i++;
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
i++;
|
|
3622
|
+
}
|
|
3623
|
+
return null;
|
|
3624
|
+
}
|
|
3625
|
+
*/
|
|
3626
|
+
}
|
|
3627
|
+
|
|
3628
|
+
|
|
3629
|
+
/**
|
|
3630
|
+
* Assign fields from `src` to `dest` if they exist in `dest` and their names are not in the `ignore` list.
|
|
3631
|
+
* When a value in `src` is a string and the existing value in `dest` is a boolean, number, or Date,
|
|
3632
|
+
* it will be converted to that type.
|
|
3633
|
+
* This is often used in class constructors that accept an object of arguments.
|
|
3634
|
+
* @param {object} dest
|
|
3635
|
+
* @param {?object} src
|
|
3636
|
+
* @param {string[]} [ignore=[]] */
|
|
3637
|
+
function assignFields(dest, src, ignore=[]) {
|
|
3638
|
+
for (let name in src || {}) {
|
|
3639
|
+
if (name in dest && !ignore.includes(name)) {
|
|
3640
|
+
const descriptor = Object.getOwnPropertyDescriptor(dest, name)
|
|
3641
|
+
|| Object.getOwnPropertyDescriptor(Object.getPrototypeOf(dest), name); // Also find (parent?) setters. Is this necssary?
|
|
3642
|
+
if (!descriptor || descriptor.writable || descriptor.set) {
|
|
3643
|
+
let srcVal = src[name];
|
|
3644
|
+
let destVal = dest[name];
|
|
3645
|
+
if (typeof src[name] === 'string') {
|
|
3646
|
+
if (typeof destVal === 'boolean') // empty string (when an attribute is present with no value) is true
|
|
3647
|
+
dest[name] = ![false, 'false', 0, '0'].includes(srcVal);
|
|
3648
|
+
else if (typeof destVal === 'number')
|
|
3649
|
+
dest[name] = Number(srcVal);
|
|
3650
|
+
else if (destVal instanceof Date) {
|
|
3651
|
+
dest[name] = new Date(srcVal); // TODO: read it as UTC 0 by default.
|
|
3652
|
+
}
|
|
3653
|
+
else
|
|
3654
|
+
dest[name] = srcVal;
|
|
3655
|
+
}
|
|
3656
|
+
else
|
|
3657
|
+
dest[name] = srcVal;
|
|
3658
|
+
}
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3479
3661
|
}
|
|
3480
3662
|
|
|
3481
3663
|
export default h;
|
|
3482
|
-
export { ArgType, Globals$1 as Globals, HtmlParser, NodeGroup, Shell, Solarite, Util as SolariteUtil, Template, delve, getArg, h, h as r, setArgs, t, toEl };
|
|
3664
|
+
export { ArgType, Globals$1 as Globals, HtmlParser, NodeGroup, Shell, Solarite, Util as SolariteUtil, Template, assignFields, delve, getArg, h, h as r, setArgs, t, toEl };
|
package/dist/Solarite.min.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Version 0.5.
|
|
1
|
+
// Version 0.5.2
|
|
2
2
|
// License: MIT
|
|
3
3
|
// http://vorticode.github.io/solarite
|
|
4
|
-
function assert(t){}let lastObjectId=1,objectIds=new WeakMap;function getObjectId(t){let e=objectIds.get(t);return void 0===e&&(e="~@"+lastObjectId++,objectIds.set(t,e)),e}let isHashing=!0;function toJSON(){return isHashing?getObjectId(this):this}function getObjectHash(t){Node.prototype.toJSON!==toJSON&&(Node.prototype.toJSON=toJSON,(()=>{}).toJSON!==toJSON&&(Function.prototype.toJSON=toJSON)),isHashing=!0;try{return JSON.stringify(t)}catch(e){return getObjectHashCircular(t)}finally{isHashing=!1}}function getObjectHashCircular(t){const e=new Set;return JSON.stringify(t,((t,l)=>{if("object"==typeof l&&null!==l){if(e.has(l))return getObjectId(l);e.add(l)}return l}))}var Globals;function reset(){Globals={connected:new WeakSet,t:null,l:null,div:document.createElement("div"),i:document,o:{},h:{},u:new WeakMap,p:new WeakMap,m:new WeakMap,$:new WeakSet,v:new WeakMap,reset}}reset();var Globals$1=Globals;function delve(t,e,l=d){let s=l!==d,i=e.length;if(!t&&!s&&i)return;let r=0;for(let o of e){if(void 0===t[o]){if(!s)return;i-1>r&&(t[o]=(e[r+1]+"").match(/^\d+$/)?[]:{})}s&&r===i-1&&(t[o]=l),t=t[o],r++}return t}let d={},Util={T(t,e){let l=t.length;if(l!==e.length)return!1;for(let s=0;l>s;s++)if(t[s]!==e[s])return!1;return!0},P(t,e=null){let l={};for(let s of t.attributes)s.name!==e&&(l[Util.G(s.name)]=s.value);return l},A(t,e){let l=e.getAttribute("data-id")||e.getAttribute("id");if(l){if(t[l]&&!t[l]?.nodeType)throw Error(`${t.constructor.name}.${l} already has a value. Can't set it as a reference to <${e.tagName.toLowerCase()} id="${l}">`);delve(t,l.split(/\./g),e)}},N(t,e){let l,s,i=e.tagName.toLowerCase();if(t.hasAttribute("global")||t.hasAttribute("data-global")){l=i,s="";let r=Globals$1.i||e.ownerDocument||document;r.head.querySelector(`style[data-style="${l}"]`)?t.remove():(r.head.append(t),t.setAttribute("data-style",l))}else{let t=e.getAttribute("data-style");t||(e.constructor.S||(e.constructor.S=1),t=e.constructor.S++,e.setAttribute("data-style",t)),s=`[data-style="${t}"]`}for(let e of t.childNodes)if(3===e.nodeType){let t=e.textContent,l=t.replace(/:host(?=[^a-z0-9_])/gi,`${i}${s}`);t!==l&&(e.textContent=l)}},O:t=>(t=(t=(t=t.replace(/([a-z0-9])([A-Z])/g,"$1-$2")).replace(/([A-Z])([A-Z][a-z])/g,"$1-$2")).replace(/([a-zA-Z])([0-9])/g,"$1-$2")).toLowerCase(),G:t=>t.replace(/-([a-z])/g,(t=>t[1].toUpperCase())),H(t,e){customElements[getName](t)||((e=e||Util.O(t.name)).includes("-")||(e+="-element"),customElements[define](e,t))},C:t=>"checkbox"===t.type||"radio"===t.type?t.checked:"file"===t.type?[...t.files]:"number"===t.type||"range"===t.type?t.valueAsNumber:"date"===t.type||"time"===t.type||"datetime-local"===t.type?t.valueAsDate:"select-multiple"===t.type?[...t.selectedOptions].map((t=>t.value)):t.hasAttribute("contenteditable")?t.innerHTML:t.value,j:t=>t.startsWith("on")&&t in Globals$1.div,U(t,e){let l=t.tagName+"."+e,s=Globals$1.h[l];if(void 0===s){let i=Object.getPrototypeOf(t);for(;i;){const t=i.constructor.name;if(t.startsWith("HTML")&&t.endsWith("Element"))break;i=Object.getPrototypeOf(i)}Globals$1.h[l]=s=!!i&&!!Object.getOwnPropertyDescriptor(i,e)?.set}return s},M:t=>Array.isArray(t)&&t.length>=2&&("object"==typeof t[0]||void 0===t[0])&&!t.slice(1).find((t=>"string"!=typeof t&&"number"!=typeof t)),L:t=>void 0===t||!1===t||null===t,I:t=>"function"==typeof t?Util.I(t()):t instanceof Date?t.toISOString().replace(/T/," "):Array.isArray(t)||"object"==typeof t?"":t,R(t,e,l){let s=t.get(e);s?s.push(l):(s=[l],t.set(e,s))},k(t){Globals$1.i.createDocumentFragment().append(...t)},F(t){const e=t=>t.nodeType!==Node.ELEMENT_NODE&&(t.nodeType!==Node.TEXT_NODE||""===t.textContent.trim()),l=[...t];for(;l.length>0&&e(l[0]);)l.shift();for(;l.length>0&&e(l[l.length-1]);)l.pop();return l}},define="define",getName="getName";class Path{J;V;D;W=[];Z;_;B;K;constructor(t,e){this.J=t,this.V=e}apply(t,e=!0){}q(){return 1}X(t,e){let l=t,s=this.B,i=s.length-e;for(let t=i-1;t>0;t--)l=l.childNodes[s[t]];return i?l.childNodes[s[0]]:t}clone(t,e=0){let l,s,i=t,r=this.B,o=r.length-e;for(let t=o-1;t>0;t--)i=i.childNodes[r[t]];let n=i.childNodes;l=o?n[r[0]]:t,this.J&&(s=n[this._]);let a=new this.constructor(s,l,this.attrName,this.Y);return a.tt=this.tt,a.et=this.et,a}lt(){return[this.V]}static get(t){let e=[];for(;;){let l=t.parentNode;if(!l)break;e.push([].indexOf.call(t.parentNode.childNodes,t)),t=l}return e}static resolve(t,e){for(let l=e.length-1;l>=0;l--)t=t.childNodes[e[l]];return t}}class HtmlParser{constructor(){this.st={context:HtmlParser.Text,quote:null,buffer:"",it:null},this.state={...this.st}}reset(){return this.state={...this.st},this.state.context}parse(t,e=null){if(null===t)return this.reset();for(let l=0;t.length>l;l++){const s=t[l];switch(this.state.context){case HtmlParser.Text:"<"===s&&t[l+1].match(/[/a-z!]/i)&&(e?.(t,l,this.state.context,HtmlParser.rt),this.state.context=HtmlParser.rt,this.state.buffer="");break;case HtmlParser.rt:if(">"===s)e?.(t,l+1,this.state.context,HtmlParser.Text),this.state.context=HtmlParser.Text,this.state.quote=null,this.state.buffer="";else{if(" "===s&&!this.state.buffer)continue;" "===s||"/"===s||"?"===s?this.state.buffer="":'"'===s||"'"===s||"="===s?(e?.(t,l,this.state.context,HtmlParser.ot),this.state.context=HtmlParser.ot,this.state.quote="="===s?null:s,this.state.buffer=""):this.state.buffer+=s}break;case HtmlParser.ot:this.state.quote||this.state.buffer.length||'"'!==s&&"'"!==s?s===this.state.quote||!this.state.quote&&this.state.buffer.length?(e?.(t,l,this.state.context,HtmlParser.rt),this.state.context=HtmlParser.rt,this.state.quote=null,this.state.buffer=""):this.state.quote||">"!==s?" "!==s&&(this.state.buffer+=s):(e?.(t,l+1,this.state.context,HtmlParser.Text),this.state.context=HtmlParser.Text,this.state.quote=null,this.state.buffer=""):this.state.quote=s}}return e?.(t,t.length,this.state.context,null),this.state.context}}HtmlParser.ot="Attribute",HtmlParser.Text="Text",HtmlParser.rt="Tag";class PathToAttribValue extends Path{attrName;Y;et;constructor(t,e,l=null,s=null){super(null,e),this.attrName=l,this.Y=s}apply(t){let e=this.V,l=t[0],s=this.Y;if(!s&&Util.M(l)){if(this.tt&&e.tagName.endsWith("-SOLARITE-PLACEHOLDER"))return;let[t,s]=[l[0],l.slice(1)];if(!t)throw Error(`Solarite cannot bind to <${e.tagName.toLowerCase()} ${this.attrName}=\${[${l.map((t=>t?`'${t}'`:t+"")).join(", ")}]}>.`);let i=delve(t,s);if("value"===this.attrName&&"select-multiple"===e.type&&Array.isArray(i)){let t=i.map((t=>t+""));for(let l of e.options)l.selected=t.includes(l.value)}else{const t=Util.L(i)?"":i;"value"===this.attrName&&e.hasAttribute("contenteditable")?t!==e.innerHTML&&(e.innerHTML=t):t!==e[this.attrName]&&(e[this.attrName]=t)}let r=()=>{let l="value"===this.attrName?Util.C(e):e[this.attrName];delve(t,s,l)};this.nt(e,this.D.getRootNode(),this.attrName,"input",r,[],!0)}else{let i=this.et;if(!s){if(Globals$1.t=this,"function"==typeof l){if(this.tt)return;this.K=l,l=l()}else l=Util.I(l);Globals$1.t=null}if(s||void 0!==l&&!1!==l&&null!==l)if(s||!0!==l){let r=s?this.ht(t):l;(i?e[this.attrName]:e.getAttribute(this.attrName))!==r&&(i?e[this.attrName]=r:"value"===this.attrName&&e.hasAttribute("contenteditable")&&(e.innerHTML=r),e.setAttribute(this.attrName,r))}else i&&(e[this.attrName]=!0),e.setAttribute(this.attrName,"");else i&&(e[this.attrName]=!1),e.removeAttribute(this.attrName)}}q(){return this.Y?this.Y.length-1:1}ht(t){if(!this.Y)return t[0];let e=[],l=this.Y;for(let s=0;l.length>s;s++)if(e.push(l[s]),l.length-1>s){Globals$1.t=this;let l=Util.I(t[s]);Globals$1.t=null,Util.L(l)||e.push(l)}return e.join("")}nt(t,e,l,s,i,r,o=!1){let n=Globals$1.u.get(t);n||(n={[l]:[,,,]},Globals$1.u.set(t,n));let a=n[l];if(a||(n[l]=a=[,,,]),"function"!=typeof i)throw Error(`Solarite cannot bind to <${t.tagName.toLowerCase()} ${this.attrName}=\${${i}}> because it's not a function.`);if(a[0]!==i){let[l,r,n]=a;l&&t.removeEventListener(s,r,o);let h=i,f=l=>h.call(e,...a[2],l,t);a[0]=h,a[1]=f,t.addEventListener(s,f,o)}n[l][2]=r}}class PathToEvent extends PathToAttribValue{constructor(t,e,l=null,s=null){super(null,e,l,s)}apply(t){if(this.tt&&this.V.tagName.endsWith("-SOLARITE-PLACEHOLDER"))return;let e,l=t[0],s=this.D.ft.root,i=this.V,r=this.attrName.slice(2),o=[];if(Array.isArray(l)&&"function"==typeof l[0])e=l[0],o=l.slice(1);else{if("function"!=typeof l)throw Error(`Invalid event binding: <${i.tagName.toLowerCase()} ${this.attrName}=\${${JSON.stringify(l)}}>`);e=l}this.nt(i,s,r,r,e,o)}}class PathToAttribs extends Path{ut;constructor(t,e){super(null,null),this.V=e,this.ut=new Set}apply(t,e){let l=t[0],s=this.V;Array.isArray(l)&&(l=l.flat().join(" "));let i=this.ut;if(this.ut=new Set,l)if("function"==typeof l&&(Globals$1.t=this,this.K=l,l=l(),Globals$1.t=null),"object"==typeof l)for(let t in l){let e=l[t];void 0!==e&&!1!==e&&null!==e&&(s.setAttribute(t,e),this.ut.add(t))}else{let t=(l+"").split(/([\w-]+\s*=\s*(?:"[^"]*"|'[^']*'|\S+))/g).map((t=>t.trim())).filter((t=>t.length));for(let e of t){let[t,l]=e.split(/\s*=\s*/);l=(l||"").replace(/^(['"])(.*)\1$/,"$2"),s.setAttribute(t,l),this.ut.add(t)}}for(let t of i)this.ut.has(t)||s.removeAttribute(t)}q(){return 1}}const udomdiff=(t,e,l,s)=>{const i=l.length;let r=e.length,o=i,n=0,a=0,h=null;for(;r>n||o>a;)if(r===n){const e=i>o?a?l[a-1].nextSibling:l[o-a]:s;for(;o>a;){let s=l[a++];t.insertBefore(s,e)}}else if(o===a)for(;r>n;){let l=e[n];h&&h.has(l)||t.removeChild(l),n++}else if(e[n]===l[a])n++,a++;else if(e[r-1]===l[o-1])r--,o--;else if(e[n]===l[o-1]&&l[a]===e[r-1]){const s=e[--r].nextSibling;let i=l[a++],h=e[n++];t.insertBefore(i,h.nextSibling);let f=l[--o];t.insertBefore(f,s),e[r]=l[o]}else{if(!h){h=new Map;let t=a;for(;o>t;)h.set(l[t],t++)}if(h.has(e[n])){const s=h.get(e[n]);if(s>a&&o>s){let i=n,f=1;for(;++i<r&&o>i&&h.get(e[i])===s+f;)f++;if(f>s-a){const i=e[n];for(;s>a;){let e=l[a++];t.insertBefore(e,i)}}else{let s=e[n++],i=l[a++];t.replaceChild(i,s)}}else n++}else{let l=e[n++];t.removeChild(l)}}return l};class MultiValueMap{data={};add(t,e){let l=this.data,s=l[t];s||(s=new Set,l[t]=s),s.add(e)}ct(){for(let t in this.data)return!0;return!1}getAll(t){return this.data[t]||[]}delete(t,e=void 0){let l,s=this.data,i=s[t];if(i)return void 0===e?([l]=i,i.delete(l)):(i.delete(e),l=e),0===i.size&&delete s[t],l}dt(t){let e,l=this.data,s=l[t];if(s)return[e]=s,s.delete(e),0===s.size&&delete l[t],e}bt(t,e){let l,s=this.data,i=s[t];if(i)return i.delete(e),l=e,0===i.size&&delete s[t],l}yt(t){let e=this.data,l=[];for(let s in e)e[s].has(t)&&l.push(s);return l}}class PathToNodes extends Path{gt;$t=[];Et=new MultiValueMap;vt=new MultiValueMap;constructor(t,e){super(t,e)}apply(t,e=!0){let l=this,s=t[0];e&&l.Tt();let i=[],r=l.W,o=[];l.W=[],l.Pt(s,i,o);let n=!1;if(o.length){for(let[t,e]of o){let s=l.Gt(i[t],!1),r=s.lt();1===r.length?i[t]=r[0]:(i[t]=r,n=!0),l.W[e]=s}n&&(i=i.flat())}let a=l.lt();if(!Util.T(a,i)){l.Z=i,this.D.wt&&this.D.wt.At(),a.length&&!i.length&&l.Nt()||udomdiff(l.V.parentNode,a,i,l.V);for(let t of r)t.St.parentNode||Util.k(t.lt())}}Pt(t,e,l){if(t instanceof Template){let s=this.Gt(t,!0);if(s){let l=s.lt();return e.push(...l),s.Ot(t.exprs,!1,!1),this.W.push(s),s}l.push([e.length,this.W.length]),e.push(t),this.W.push(null)}else t instanceof NodeList?e.push(...t):t?.nodeType?11===t?.nodeType?e.push(...t.childNodes):e.push(t):this.Ht(t,(t=>{this.Pt(t,e,l)}))}Ct(t){let e=Math.min(t.xt,t.items.length),l=t.xt-e;for(let l=0;e>l;l++){let e=this.W[t.index+l],s=(this.gt||this.K)(t.items[l]);this.Ht(s,(s=>{let i=this.Gt(s,!0);if(i&&i===e);else{i||(i=this.Gt(s,!1)),this.W[t.index+l]=i;let r=e.St;for(let t of i.lt())r.parentNode.insertBefore(t,r);i!==e&&Util.k(e.lt())}}))}if(l>0){for(let s=0;l>s;s++)Util.k(this.W[t.index+e+s].lt());this.W.splice(t.index+e,l)}else{let l=t.items.slice(e),s=this.W[t.index+e]?.St||this.V;for(let t=0;l.length>t;t++){let e=this.gt(l[t]),i=this.Gt(e,!0);i||(i=this.Gt(e,!1)),this.W.push(i);for(let t of i.lt())s.parentNode.insertBefore(t,s)}}this.Z=null}At(){let t=this,e=this.V.parentNode;for(;t&&t.V.parentNode===e;)t.Z=null,t=t.D?.wt}Nt(){let t=this.J.parentNode;return this.J===t.firstChild&&this.V===t.lastChild&&(t.innerHTML="",t.append(this.J,this.V),!0)}Ht(t,e){if(Array.isArray(t))for(let l of t)this.Ht(l,e);else if("function"==typeof t)Globals$1.t=this,this.K=t,t=t(),Globals$1.t=null,this.Ht(t,e);else if(t instanceof Template||t?.nodeType)e(t);else{void 0===t||!1===t||null===t?t="":"string"!=typeof t&&(t+="");let l=new Template([t],[]);l.jt=!0,this.Ht(l,e)}}Gt(t,e=!0){let l,s=this.Et;if(e){if(l=s.dt(t.Ut()),l||(s=this.vt,l=s.dt(t.Ut())),!l)return null;s.bt(t.Mt(),l)}else t.exprs.length&&(l=s.dt(t.Mt()),l||(s=this.vt,l=s.dt(t.Mt())),l&&(s.bt(l.Lt,l),l.Ot(t.exprs),l.Lt=t.Ut()));return l||(l=new NodeGroup(t,this),l.Ot(t.exprs),l.Lt=t.Ut()),this.$t.push(l),l}Tt(){let t=this.Et.data,e=this.vt.data;for(let l in t){let s=e[l];if(s)for(let e of t[l])s.add(e);else e[l]=t[l]}this.Et=new MultiValueMap;let l=this.Et;for(let t of this.$t)l.add(t.Lt,t),l.add(t.It,t);this.$t=[]}lt(){let t;if(t=this.Z,t)return t;t=[];let e=this.J.nextSibling,l=this.V;for(;e&&e!==l;)t.push(e),e=e.nextSibling;return this.Z=t,t}}class PathToComponent extends Path{Rt;constructor(t,e){super(null,e)}apply(t,e=!0,l=!0){let s=this.V,i=Util.P(s,"_is");for(let e,l=0;e=this.Rt[l];l++)i[Util.G(e.attrName)]=e.ht(t[l]);let r=s.getAttribute("_is");if(s.tagName.endsWith("-SOLARITE-PLACEHOLDER")||r){let e=(r||s.tagName.slice(0,-21)).toLowerCase(),o=customElements.get(e);if(!o)throw Error(`Must call customElements.define('${e}', Class) before using it.`);Globals$1.l=[...s.childNodes];let n=new o(i);r&&n.setAttribute("is",r);for(let t of s.attributes)"_is"!==t.name&&n.setAttribute(t.name,t.value);for(let t in i){let e=i[t],l=typeof e;"boolean"===l?!1!==e&&null!=e&&n.setAttribute(t,""):"string"!==l&&"number"!==l&&"bigint"!==l||n.setAttribute(t,e)}let a=n.getAttribute("data-id")||n.getAttribute("id");a&&delve(this.D.getRootNode(),a.split(/\./g),n);let h=this.D;this.V=n;for(let t of h.kt)t.V===s&&(t.V=n),t.J===s&&(t.J=n);h.St===s&&(h.St=n),h.Ft===s&&(h.Ft=n),"function"!=typeof n.render||Globals$1.$.has(n)||n.render(i,l);for(let e,l=0;e=this.Rt[l];l++)e.D=this.D,e.V=n,e.apply(t[l]);s.replaceWith(n)}else"function"==typeof s.render&&s.render(i,l);Globals$1.l=null}clone(t,e=0){let l=this.X(t,e),s=new PathToComponent(null,l);return s.Rt=this.Rt.map((l=>l.clone(t,e))),s}q(){return 0}}class Shell{fragment;kt=[];Jt=[];scripts=[];Vt=[];constructor(t=null){if(!t)return;if(1===t.length&&!t[0].match(/[<&]/))return void(this.fragment=Globals$1.i.createTextNode(t[0]));let e,l=Shell.Dt(t),s=Globals$1.i.createElement("template");l?s.innerHTML=l:s.content.append(Globals$1.i.createTextNode("")),this.fragment=s.content;let i=[],r=0;const o=Globals$1.i.createTreeWalker(this.fragment,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_TEXT);for(;e=o.nextNode();)if(i.map((t=>t.remove())),i=[],1===e.nodeType){const t=e.hasAttribute("is"),l=t||e.tagName.includes("-"),s=[];for(let t of[...e.attributes]){let i=t.name.match(/^[\ue000-\uf8ff]$/);if(i){let t=new PathToAttribs(null,e);this.kt.push(t),l&&s.push(t),r++,e.removeAttribute(i[0])}else{let i=t.value.split(/[\ue000-\uf8ff]/g);if(i.length>1){let o=2!==i.length||i[0].length||i[1].length?i:null,n=Util.j(t.name)?new PathToEvent(null,e,t.name,o):new PathToAttribValue(null,e,t.name,o);n.et=Util.U(e,t.name),this.kt.push(n),l&&(n.tt=!0,s.push(n)),r+=i.length-1,e.setAttribute(t.name,i.join(""))}}}if(l){let l=new PathToComponent(null,e);l.Rt=s,this.kt.splice(this.kt.length-s.length,0,l),t&&(e.setAttribute("_is",e.getAttribute("is")),e.removeAttribute("is"))}}else if(8===e.nodeType&&"!✨!"===e.nodeValue){if(e?.parentNode?.closest&&e?.parentNode?.closest("[contenteditable]"))throw Error('Contenteditable can\'t have expressions inside them. Use <div contenteditable value="${...}"> instead.');let t,l=e.previousSibling;l||(l=Globals$1.i.createComment("Path:"+this.kt.length),e.parentNode.insertBefore(l,e)),!e.nextSibling||8===e.nextSibling.nodeType&&"!✨!"===e.nextSibling.textContent?(t=e,t.textContent="PathEnd:"+this.kt.length):(t=e.nextSibling,i.push(e));let s=new PathToNodes(l,t);this.kt.push(s),r++}else{if(3===e.nodeType&&"TEXTAREA"===e.parentNode?.tagName&&e.textContent.includes("\x3c!--!✨!--\x3e"))throw Error('Textarea can\'t have expressions inside them. Use <textarea value="${...}"> instead.');if(8===e.nodeType){let t=e.textContent.split(/[\ue000-\uf8ff]/g);for(let l=0;t.length-1>l;l++){let t=new Path(e.previousSibling,e);this.kt.push(t),r++}}else if(3===e.nodeType&&["SCRIPT","STYLE"].includes(e.parentNode?.nodeName)){let t=e.textContent.split(commentPlaceholder);if(t.length>1){let l=[];for(let s=0;t.length>s;s++){let i=Globals$1.i.createTextNode(t[s]);e.parentNode.insertBefore(i,e),s>0&&l.push(i)}for(let t,e=0;t=l[e];e++){let e=new PathToNodes(t.previousSibling,t);this.kt.push(e),r++}i.push(e)}}}if(i.map((t=>t.remove())),r!==t.length-1)throw Error("Could not parse expressions in template. Check for duplicate attributes or malformed html: "+t.join("${...}"));for(let t of this.kt)t.J&&(t._=[].indexOf.call(t.J.parentNode.childNodes,t.J)),t.B=Path.get(t.V);this.zt()}static Dt(t){let e=[],l=new HtmlParser;for(let s=0;t.length>s;s++){let i=0,r=l.parse(t[s],((t,l,s)=>{if(i!==l){let r=t.slice(i,l);s===HtmlParser.rt&&(r=r.replace(/^<\/?[a-z][a-z0-9]*-[a-z0-9-]+/i,(t=>t+"-SOLARITE-PLACEHOLDER"))),e.push(r)}i=l}));t.length-1>s&&e.push(r===HtmlParser.Text?commentPlaceholder:String.fromCharCode(attribPlaceholder+s))}return e.join("")}zt(){this.scripts=[].map.call(this.fragment.querySelectorAll("scripts"),(t=>Path.get(t))),this.Vt=[].map.call(this.fragment.querySelectorAll("style"),(t=>Path.get(t)));let t=this.fragment.querySelectorAll("[id],[data-id]");for(let e of t){let t=e.getAttribute("data-id")||e.getAttribute("id");if(Globals$1.div.hasOwnProperty(t))throw Error(`<${e.tagName.toLowerCase()} id="${t}"> can't override existing HTMLElement id property.`)}this.Jt=[].map.call(t,(t=>Path.get(t)))}static get(t){let e=Globals$1.v.get(t);return e||(e=new Shell(t),Globals$1.v.set(t,e)),e}}const commentPlaceholder="\x3c!--!✨!--\x3e",attribPlaceholder=57344;class NodeGroup{ft;wt;St;Ft;kt=[];Lt;It;Z;Vt;Wt;root;constructor(t,e=null,l=null,s=null){if(this.ft=e?.D?.ft||this,this.wt=e,this.Wt=t,this.It=t.Mt(),t.jt)this.St=this.Ft=Globals$1.i.createTextNode(t.html[0]);else{const e=Shell.get(t.html),i=e.fragment.cloneNode(!0);if(11===i.nodeType?(this.St=i.firstChild,this.Ft=i.lastChild):this.St=this.Ft=i,this instanceof RootNodeGroup){let t=0;if(this.options=s,i instanceof Text){if(!l)throw Error("Cannot create a standalone text node");this.root=l,i.nodeValue.length&&this.root.append(i)}else{if(l){let e;if(this.root=l,(Globals$1.l||l.childNodes.length)&&(e=Globals$1.i.createDocumentFragment(),e.append(...Globals$1.l||l.childNodes)),isReplaceEl(i,this.root.tagName)){this.root.append(...i.children[0].childNodes);for(let t of i.children[0].attributes)this.root.hasAttribute(t.name)||this.root.setAttribute(t.name,t.value);t=1}else 1===i.childNodes.length&&3===i.childNodes[0].nodeType&&""===i.childNodes[0].textContent||this.root.append(...i.childNodes);if(e){for(let t of l.querySelectorAll("slot[name]")){let l=t.getAttribute("name");if(l){let s=e.querySelectorAll(`[slot='${l}']`);t.append(...s)}}let t=l.querySelector("slot:not([name])");t?t.append(e):l.append(e)}}else{let e=getSingleEl(i);this.root=e||i,e&&(t=1)}this.Zt(this.root,e.kt,t),this._t(this.root,e,t)}this.St=this.Ft=this.root,Globals$1.p.set(this.root,this)}else e&&(e.kt.length&&this.Zt(i,e.kt),this._t(i,e))}}Ot(t,e=!0,l=!0){let s=this.kt,i=t.length,r=Array(s.length);for(let o,n=s.length-1;o=s[n];n--){if(0===n&&o instanceof PathToComponent&&o.V===this.getRootNode())continue;let s=o.q();if(r[n]=t.slice(i-s,i),i-=s,o instanceof PathToComponent){let t=r.slice(n+1,n+1+o.Rt.length);o.apply(t,!0,e)}else l&&o.apply(r[n])}l&&(this.Bt(),this.Z=null)}Kt(t){}lt(){let t=this.Z;if(t)return t;t=[];let e=this.St,l=this.Ft?.nextSibling;for(;e&&e!==l;)t.push(e),e=e.nextSibling;return this.Z=t,t}getRootNode(){return this.ft.root}qt(){return this.ft}Zt(t,e,l=0){let s=e.length;this.kt.length=s;for(let i=0;s>i;i++){let s=e[i].clone(t,l);s.D=this,this.kt[i]=s}}Bt(){if(this.Vt)for(let[t,e]of this.Vt)e!==t.textContent&&Util.N(t,this.qt().root)}_t(root,shell,pathOffset=0){let rootEl=this.ft.root;if(rootEl){let options=this.ft.options;if(!1!==options?.Jt)for(let t of shell.Jt){pathOffset&&(t=t.slice(0,-pathOffset));let e=Path.resolve(root,t);Util.A(rootEl,e)}if(!1!==options?.Vt){shell.Vt.length&&(this.Vt=new Map);for(let t of shell.Vt){pathOffset&&(t=t.slice(0,-pathOffset));let e=Path.resolve(root,t);1===rootEl.nodeType&&(Util.N(e,rootEl),this.Vt.set(e,e.textContent))}}if(!1!==options?.scripts)for(let path of shell.scripts){pathOffset&&(path=path.slice(0,-pathOffset));let script=Path.resolve(root,path);eval(script.textContent)}}}}function getSingleEl(t){let e=[];for(let l of t.childNodes)if(1===l.nodeType||3===l.nodeType&&l.textContent.trim().length){if(e.length)return null;e.push(l)}return e[0]}function isReplaceEl(t,e){return 1===t.children.length&&e.includes("-")&&t.children[0].tagName.replace("-SOLARITE-PLACEHOLDER","")===e}class RootNodeGroup extends NodeGroup{Xt}class Template{exprs=[];html=[];Yt;jt;constructor(t=[""],e=[]){this.html=t,this.exprs=e}toJSON(){return void 0===this.Yt&&(this.Yt=[getObjectId(this.html),this.exprs]),this.Yt}render(t=null,e={}){let l=t&&Globals$1.p.get(t);if(l||(l=new RootNodeGroup(this,null,t,e),t||(t=l.getRootNode()),Globals$1.p.set(t,l)),1!==this.html?.length||this.html[0]){let t=l.Lt,e=this.Ut();l.Ot(this.exprs,t!==e),l.Lt=e}else t.innerHTML="";return l.Xt=new Map,t}Ut(){return void 0===this.Lt&&(this.Lt=this.exprs.length?getObjectHash(this):this.html[0]),this.Lt}Mt(){return void 0===this.It&&(this.It=this.exprs.length?this.toJSON()[0]:this.html[0]),this.It}static Qt(t,e,l){const s=selfClosingTags.has(t.toLowerCase());let i=[],r=[],o="<"+t;if(e&&"object"==typeof e)for(let t in e){let l=e[t];"id"!==t&&"data-id"!==t?(o+=` ${t}=`,i.push(o),r.push(l),o=""):o+=` ${t}="${l}"`}if(!s){i.push(i.length>0?'"'===o?'">':">":o+">");for(let t of l)addChild(t,i,r)}return s?i.push(i.length>0?">":o+">"):i[i.length-1]+=`</${t}>`,new Template(i,r)}}const selfClosingTags=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),addChild=(t,e,l)=>{if(Array.isArray(t))for(let s of t)addChild(s,e,l);else{let s=!1;if(t instanceof Template)if(t.exprs.length>0)s=!0;else{const e=(t.html[0]||"").match(/^<([a-zA-Z][\w:-]*)/),l=e?e[1].toLowerCase():"";s=selfClosingTags.has(l)}if(s){e[e.length-1]+=t.html[0];for(let s=0;t.exprs.length>s;s++)l.push(t.exprs[s]),e.push(t.html[s+1]??"")}else l.push(t),e.push("")}};function toEl(t){if("string"==typeof t){let e=t;(e.match(/^\s^<\S+/)||e.match(/\S+>\s+$/))&&(e=e.trim());let l=Globals$1.i.createElement("template");l.innerHTML=e;let s=Util.F(l.content.childNodes);return 1===s.length?s[0]:l.content}if(t instanceof Template)return t.render();if(t&&"object"==typeof t){let e=t;if("Object"!==e.constructor.name)throw Error(`Solarate Web Component class ${e.constructor?.name} must extend HTMLElement.`);if(!Globals$1.m.has(e)){Globals$1.m.set(e,null),e[renderF]();let t=Globals$1.m.get(e);Globals$1.m.delete(e);for(let l in e)t[l]="function"==typeof e[l]?e[l].bind(t):e[l];return t}}throw Error("toEl() does not support argument of type: "+(t?typeof t:t))}let renderF="render";function h(t=void 0,...e){if(Array.isArray(arguments[0]))return new Template(arguments[0],e);if("string"==typeof arguments[0]||arguments[0]instanceof String){let t=arguments[0];if(!e.length||"object"!=typeof e[0]&&null!==e[0]){let e=t;return e.match(/^\s^</)&&(e=e.trim()),new Template([e],[])}{let l=t+"",s=e[0]||{},i=e.slice(1);return Template.Qt(l,s,i)}}if(arguments[0]instanceof HTMLElement||arguments[0]instanceof DocumentFragment){if(!(arguments[1]instanceof Template)){let t=arguments[0],e=arguments[1];t.shadowRoot&&(t.innerHTML="");let l=(l,...s)=>(Globals$1.$.add(t),new Template(l,s).render(t,e));return l}arguments[1].render(arguments[0],arguments[2])}else{if(!arguments.length)return(t,...e)=>toEl(h(t,...e));if("object"!=typeof arguments[0]||!Globals$1.m.has(arguments[0])){if(Util.L(arguments[0]))return new Template;throw Error("h() does not support argument of type: "+(arguments[0]?typeof arguments[0]:arguments[0]))}{let t=arguments[0];if("Object"!==t.constructor.name)throw Error(`Solarate Web Component class ${t.constructor?.name} must extend HTMLElement.`);if(!(arguments[1]instanceof Template))return((...e)=>{let l=h(...e).render();Globals$1.m.set(t,l)}).bind(t);{let e=arguments[1].render();Globals$1.m.set(t,e)}}}}function getArg(el,attributeName,defaultValue=void 0,type=ArgType.String){let val=defaultValue,attrVal=el.getAttribute(attributeName)||el.getAttribute(Util.O(attributeName));if(null!==attrVal&&(val=attrVal),Array.isArray(type))return type.includes(val)?val:void 0;if("function"==typeof type)return type.constructor?new type(val):type(val);if(type===ArgType.te){let t="string"==typeof val?val.toLowerCase():val;return!["false","0",!1,0,null,void 0,NaN].includes(t)&&(!(!["true",!0].includes(t)&&0===parseFloat(t))||void 0)}switch(type){case ArgType.ee:return parseInt(val);case ArgType.le:return parseFloat(val);case ArgType.String:return[void 0,null,!1].includes(val)?"":val+"";case ArgType.se:case ArgType.ie:if("string"!=typeof val||!val.length)return val;try{return type===ArgType.se?JSON.parse(val):eval(`(${val})`)}catch(t){return val}default:return val}}function setArgs(t,e,l){for(let s in e)this[s]=getArg(t,s,e[s],l[s]||ArgType.String)}var ArgType={te:"Bool",ee:"Int",le:"Float",String:"String",JSON:"Json",se:"Json",ie:"Eval"};function t(t){return new Template([t],[])}let HTMLElementAutoDefine=new Proxy(HTMLElement,{construct:(t,e,l)=>(Util.H(l),Reflect.construct(t,e,l))});class Solarite extends HTMLElementAutoDefine{constructor(t=null){if(super(),t){if("object"!=typeof t)throw Error("First argument to custom element constructor must be an object.");if(t&&!Object.keys(t).length){let e=Solarite.getAttribs(this);for(let l in e)t[l]=e[l]}}}render(){throw Error("render() is not defined for "+this.constructor.name)}renderFirstTime(){if(!Globals$1.$.has(this)){let t=Solarite.getAttribs(this);this.render(t)}}connectedCallback(){this.renderFirstTime()}static define(t=null){Util.H(this,t)}static getAttribs(t){let e=Util.P(t);for(let t in e){let l=e[t];l.startsWith("${")&&l.endsWith("}")&&(e[t]=JSON.parse(l.slice(2,-1)))}return e}}export default h;export{ArgType,Globals$1 as Globals,HtmlParser,NodeGroup,Shell,Solarite,Util as SolariteUtil,Template,delve,getArg,h,h as r,setArgs,t,toEl};
|
|
4
|
+
function assert(t){}let lastObjectId=1,objectIds=new WeakMap;function getObjectId(t){let e=objectIds.get(t);return void 0===e&&(e="~@"+lastObjectId++,objectIds.set(t,e)),e}let isHashing=!0;function toJSON(){return isHashing?getObjectId(this):this}function getObjectHash(t){Node.prototype.toJSON!==toJSON&&(Node.prototype.toJSON=toJSON,(()=>{}).toJSON!==toJSON&&(Function.prototype.toJSON=toJSON)),isHashing=!0;try{return JSON.stringify(t)}catch(e){return getObjectHashCircular(t)}finally{isHashing=!1}}function getObjectHashCircular(t){const e=new Set;return JSON.stringify(t,((t,l)=>{if("object"==typeof l&&null!==l){if(e.has(l))return getObjectId(l);e.add(l)}return l}))}var Globals;function reset(){Globals={connected:new WeakSet,t:null,l:null,div:document.createElement("div"),i:document,o:{},h:{},u:new WeakMap,p:new WeakMap,m:new WeakMap,$:new WeakSet,v:new WeakMap,reset}}reset();var Globals$1=Globals;function delve(t,e,l=d){let s=l!==d,i=e.length;if(!t&&!s&&i)return;let r=0;for(let o of e){if(void 0===t[o]){if(!s)return;i-1>r&&(t[o]=(e[r+1]+"").match(/^\d+$/)?[]:{})}s&&r===i-1&&(t[o]=l),t=t[o],r++}return t}let d={},Util={T(t,e){let l=t.length;if(l!==e.length)return!1;for(let s=0;l>s;s++)if(t[s]!==e[s])return!1;return!0},P(t,e=null){let l={};for(let s of t.attributes)s.name!==e&&(l[Util.G(s.name)]=s.value);return l},A(t,e){let l=e.getAttribute("data-id")||e.getAttribute("id");if(l){if(t[l]&&!t[l]?.nodeType)throw Error(`${t.constructor.name}.${l} already has a value. Can't set it as a reference to <${e.tagName.toLowerCase()} id="${l}">`);delve(t,l.split(/\./g),e)}},N(t,e){let l,s,i=e.tagName.toLowerCase();if(t.hasAttribute("global")||t.hasAttribute("data-global")){l=i,s="";let r=Globals$1.i||e.ownerDocument||document;r.head.querySelector(`style[data-style="${l}"]`)?t.remove():(r.head.append(t),t.setAttribute("data-style",l))}else{let t=e.getAttribute("data-style");t||(e.constructor.S||(e.constructor.S=1),t=e.constructor.S++,e.setAttribute("data-style",t)),s=`[data-style="${t}"]`}for(let e of t.childNodes)if(3===e.nodeType){let t=e.textContent,l=t.replace(/:host(?=[^a-z0-9_])/gi,`${i}${s}`);t!==l&&(e.textContent=l)}},O:t=>(t=(t=(t=t.replace(/([a-z0-9])([A-Z])/g,"$1-$2")).replace(/([A-Z])([A-Z][a-z])/g,"$1-$2")).replace(/([a-zA-Z])([0-9])/g,"$1-$2")).toLowerCase(),G:t=>t.replace(/-([a-z])/g,(t=>t[1].toUpperCase())),C(t,e){customElements[getName](t)||((e=e||Util.O(t.name)).includes("-")||(e+="-element"),customElements[define](e,t))},H:t=>"checkbox"===t.type||"radio"===t.type?t.checked:"file"===t.type?[...t.files]:"number"===t.type||"range"===t.type?t.valueAsNumber:"date"===t.type||"time"===t.type||"datetime-local"===t.type?t.valueAsDate:"select-multiple"===t.type?[...t.selectedOptions].map((t=>t.value)):t.hasAttribute("contenteditable")?t.innerHTML:t.value,j:t=>t.startsWith("on")&&t in Globals$1.div,U(t,e){let l=t.tagName+"."+e,s=Globals$1.h[l];if(void 0===s){let i=Object.getPrototypeOf(t);for(;i;){const t=i.constructor.name;if(t.startsWith("HTML")&&t.endsWith("Element"))break;i=Object.getPrototypeOf(i)}Globals$1.h[l]=s=!!i&&!!Object.getOwnPropertyDescriptor(i,e)?.set}return s},M:t=>Array.isArray(t)&&t.length>=2&&("object"==typeof t[0]||void 0===t[0])&&!t.slice(1).find((t=>"string"!=typeof t&&"number"!=typeof t)),L:t=>void 0===t||!1===t||null===t,I:t=>"function"==typeof t?Util.I(t()):t instanceof Date?t.toISOString().replace(/T/," "):Array.isArray(t)||"object"==typeof t?"":t,R(t,e,l){let s=t.get(e);s?s.push(l):(s=[l],t.set(e,s))},k(t){Globals$1.i.createDocumentFragment().append(...t)},F(t){const e=t=>t.nodeType!==Node.ELEMENT_NODE&&(t.nodeType!==Node.TEXT_NODE||""===t.textContent.trim()),l=[...t];for(;l.length>0&&e(l[0]);)l.shift();for(;l.length>0&&e(l[l.length-1]);)l.pop();return l}},define="define",getName="getName";class Path{V;J;D;W=[];K;Z;_;B;constructor(t,e){this.V=t,this.J=e}apply(t,e=!0){}q(){return 1}X(t,e){let l=t,s=this._,i=s.length-e;for(let t=i-1;t>0;t--)l=l.childNodes[s[t]];return i?l.childNodes[s[0]]:t}clone(t,e=0){let l,s,i=t,r=this._,o=r.length-e;for(let t=o-1;t>0;t--)i=i.childNodes[r[t]];let n=i.childNodes;l=o?n[r[0]]:t,this.V&&(s=n[this.Z]);let a=new this.constructor(s,l,this.attrName,this.Y);return a.tt=this.tt,a.et=this.et,a}lt(){return[this.J]}static get(t){let e=[];for(;;){let l=t.parentNode;if(!l)break;e.push([].indexOf.call(t.parentNode.childNodes,t)),t=l}return e}static resolve(t,e){for(let l=e.length-1;l>=0;l--)t=t.childNodes[e[l]];return t}}class HtmlParser{constructor(){this.st={context:HtmlParser.Text,quote:null,buffer:"",it:null},this.state={...this.st}}reset(){return this.state={...this.st},this.state.context}parse(t,e=null){if(null===t)return this.reset();for(let l=0;t.length>l;l++){const s=t[l];switch(this.state.context){case HtmlParser.Text:"<"===s&&t[l+1].match(/[/a-z!]/i)&&(e?.(t,l,this.state.context,HtmlParser.rt),this.state.context=HtmlParser.rt,this.state.buffer="");break;case HtmlParser.rt:if(">"===s)e?.(t,l+1,this.state.context,HtmlParser.Text),this.state.context=HtmlParser.Text,this.state.quote=null,this.state.buffer="";else{if(" "===s&&!this.state.buffer)continue;" "===s||"/"===s||"?"===s?this.state.buffer="":'"'===s||"'"===s||"="===s?(e?.(t,l,this.state.context,HtmlParser.ot),this.state.context=HtmlParser.ot,this.state.quote="="===s?null:s,this.state.buffer=""):this.state.buffer+=s}break;case HtmlParser.ot:this.state.quote||this.state.buffer.length||'"'!==s&&"'"!==s?s===this.state.quote||!this.state.quote&&this.state.buffer.length?(e?.(t,l,this.state.context,HtmlParser.rt),this.state.context=HtmlParser.rt,this.state.quote=null,this.state.buffer=""):this.state.quote||">"!==s?" "!==s&&(this.state.buffer+=s):(e?.(t,l+1,this.state.context,HtmlParser.Text),this.state.context=HtmlParser.Text,this.state.quote=null,this.state.buffer=""):this.state.quote=s}}return e?.(t,t.length,this.state.context,null),this.state.context}}HtmlParser.ot="Attribute",HtmlParser.Text="Text",HtmlParser.rt="Tag";class PathToAttribValue extends Path{attrName;Y;nt;et;constructor(t,e,l=null,s=null){super(null,e),this.attrName=l,this.Y=s}apply(t){let e=this.J,l=t[0],s=this.Y;if(!s&&Util.M(l)){if(this.tt&&e.tagName.endsWith("-SOLARITE-PLACEHOLDER"))return;let[t,s]=[l[0],l.slice(1)];if(!t)throw Error(`Solarite cannot bind to <${e.tagName.toLowerCase()} ${this.attrName}=\${[${l.map((t=>t?`'${t}'`:t+"")).join(", ")}]}>.`);let i=delve(t,s);if("value"===this.attrName&&"select-multiple"===e.type&&Array.isArray(i)){let t=i.map((t=>t+""));for(let l of e.options)l.selected=t.includes(l.value)}else{const t=Util.L(i)?"":i;"value"===this.attrName&&e.hasAttribute("contenteditable")?t!==e.innerHTML&&(e.innerHTML=t):t!==e[this.attrName]&&(e[this.attrName]=t)}let r=()=>{let l="value"===this.attrName?Util.H(e):e[this.attrName];delve(t,s,l)};this.ht(e,this.D.getRootNode(),this.attrName,"input",r,[],!0)}else{let i=this.et;if(!s){if(Globals$1.t=this,"function"==typeof l){if(this.tt)return;this.B=l,l=l()}else l=Util.I(l);Globals$1.t=null}if(s||void 0!==l&&!1!==l&&null!==l)if(s||!0!==l){let r=s?this.ft(t):l;(i?e[this.attrName]:e.getAttribute(this.attrName))!==r&&(i?e[this.attrName]=r:"value"===this.attrName&&e.hasAttribute("contenteditable")&&(e.innerHTML=r),e.setAttribute(this.attrName,r))}else i&&(e[this.attrName]=!0),e.setAttribute(this.attrName,"");else i&&(e[this.attrName]=!1),e.removeAttribute(this.attrName)}}q(){return this.Y?this.Y.length-1:1}ft(t){if(!this.Y)return t[0];let e=[],l=this.Y;for(let s=0;l.length>s;s++)if(e.push(l[s]),l.length-1>s){Globals$1.t=this;let l=Util.I(t[s]);Globals$1.t=null,Util.L(l)||e.push(l)}return e.join("")}ht(t,e,l,s,i,r,o=!1){let n=Globals$1.u.get(t);n||(n={[l]:[,,,]},Globals$1.u.set(t,n));let a=n[l];if(a||(n[l]=a=[,,,]),"function"!=typeof i)throw Error(`Solarite cannot bind to <${t.tagName.toLowerCase()} ${this.attrName}=\${${i}}> because it's not a function.`);if(a[0]!==i){let[l,r,n]=a;l&&t.removeEventListener(s,r,o);let h=i,f=l=>h.call(e,...a[2],l,t);a[0]=h,a[1]=f,t.addEventListener(s,f,o)}n[l][2]=r}}class PathToEvent extends PathToAttribValue{constructor(t,e,l=null,s=null){super(null,e,l,s)}apply(t){if(this.Y?.length>1)return void super.apply(t);if(this.tt&&this.J.tagName.endsWith("-SOLARITE-PLACEHOLDER"))return;let e,l=t[0],s=this.D.ut.root,i=this.J,r=this.attrName.slice(2),o=[];if(Array.isArray(l)&&"function"==typeof l[0])e=l[0],o=l.slice(1);else{if("function"!=typeof l)throw Error(`Invalid event binding: <${i.tagName.toLowerCase()} ${this.attrName}=\${${JSON.stringify(l)}}>`);e=l}this.ht(i,s,r,r,e,o)}}class PathToAttribs extends Path{ct;nt;constructor(t,e){super(null,null),this.J=e,this.ct=new Set}apply(t,e){let l=t[0],s=this.J;Array.isArray(l)&&(l=l.flat().join(" "));let i=this.ct;if(this.ct=new Set,l)if("function"==typeof l&&(Globals$1.t=this,this.B=l,l=l(),Globals$1.t=null),"object"==typeof l)for(let t in l){let e=l[t];void 0!==e&&!1!==e&&null!==e&&(s.setAttribute(t,e),this.ct.add(t))}else{let t=(l+"").split(/([\w-]+\s*=\s*(?:"[^"]*"|'[^']*'|\S+))/g).map((t=>t.trim())).filter((t=>t.length));for(let e of t){let[t,l]=e.split(/\s*=\s*/);l=(l||"").replace(/^(['"])(.*)\1$/,"$2"),s.setAttribute(t,l),this.ct.add(t)}}for(let t of i)this.ct.has(t)||s.removeAttribute(t)}q(){return 1}ft(t){return t[0]}}const udomdiff=(t,e,l,s)=>{const i=l.length;let r=e.length,o=i,n=0,a=0,h=null;for(;r>n||o>a;)if(r===n){const e=i>o?a?l[a-1].nextSibling:l[o-a]:s;for(;o>a;){let s=l[a++];t.insertBefore(s,e)}}else if(o===a)for(;r>n;){let l=e[n];h&&h.has(l)||t.removeChild(l),n++}else if(e[n]===l[a])n++,a++;else if(e[r-1]===l[o-1])r--,o--;else if(e[n]===l[o-1]&&l[a]===e[r-1]){const s=e[--r].nextSibling;let i=l[a++],h=e[n++];t.insertBefore(i,h.nextSibling);let f=l[--o];t.insertBefore(f,s),e[r]=l[o]}else{if(!h){h=new Map;let t=a;for(;o>t;)h.set(l[t],t++)}if(h.has(e[n])){const s=h.get(e[n]);if(s>a&&o>s){let i=n,f=1;for(;++i<r&&o>i&&h.get(e[i])===s+f;)f++;if(f>s-a){const i=e[n];for(;s>a;){let e=l[a++];t.insertBefore(e,i)}}else{let s=e[n++],i=l[a++];t.replaceChild(i,s)}}else n++}else{let l=e[n++];t.removeChild(l)}}return l};class MultiValueMap{data={};add(t,e){let l=this.data,s=l[t];s||(s=new Set,l[t]=s),s.add(e)}dt(){for(let t in this.data)return!0;return!1}getAll(t){return this.data[t]||[]}delete(t,e=void 0){let l,s=this.data,i=s[t];if(i)return void 0===e?([l]=i,i.delete(l)):(i.delete(e),l=e),0===i.size&&delete s[t],l}bt(t){let e,l=this.data,s=l[t];if(s)return[e]=s,s.delete(e),0===s.size&&delete l[t],e}yt(t,e){let l,s=this.data,i=s[t];if(i)return i.delete(e),l=e,0===i.size&&delete s[t],l}gt(t){let e=this.data,l=[];for(let s in e)e[s].has(t)&&l.push(s);return l}}class PathToNodes extends Path{$t;Et=[];vt=new MultiValueMap;Tt=new MultiValueMap;constructor(t,e){super(t,e)}apply(t,e=!0){let l=this,s=t[0];e&&l.Pt();let i=[],r=l.W,o=[];l.W=[],l.wt(s,i,o);let n=!1;if(o.length){for(let[t,e]of o){let s=l.Gt(i[t],!1),r=s.lt();1===r.length?i[t]=r[0]:(i[t]=r,n=!0),l.W[e]=s}n&&(i=i.flat())}let a=l.lt();if(!Util.T(a,i)){l.K=i,this.D.At&&this.D.At.Nt(),a.length&&!i.length&&l.St()||udomdiff(l.J.parentNode,a,i,l.J);for(let t of r)t.Ot.parentNode||Util.k(t.lt())}}wt(t,e,l){if(t instanceof Template){let s=this.Gt(t,!0);if(s){let l=s.lt();return e.push(...l),s.Ct(t.exprs,!1,!1),this.W.push(s),s}l.push([e.length,this.W.length]),e.push(t),this.W.push(null)}else t instanceof NodeList?e.push(...t):t?.nodeType?11===t?.nodeType?e.push(...t.childNodes):e.push(t):this.Ht(t,(t=>{this.wt(t,e,l)}))}xt(t){let e=Math.min(t.jt,t.items.length),l=t.jt-e;for(let l=0;e>l;l++){let e=this.W[t.index+l],s=(this.$t||this.B)(t.items[l]);this.Ht(s,(s=>{let i=this.Gt(s,!0);if(i&&i===e);else{i||(i=this.Gt(s,!1)),this.W[t.index+l]=i;let r=e.Ot;for(let t of i.lt())r.parentNode.insertBefore(t,r);i!==e&&Util.k(e.lt())}}))}if(l>0){for(let s=0;l>s;s++)Util.k(this.W[t.index+e+s].lt());this.W.splice(t.index+e,l)}else{let l=t.items.slice(e),s=this.W[t.index+e]?.Ot||this.J;for(let t=0;l.length>t;t++){let e=this.$t(l[t]),i=this.Gt(e,!0);i||(i=this.Gt(e,!1)),this.W.push(i);for(let t of i.lt())s.parentNode.insertBefore(t,s)}}this.K=null}Nt(){let t=this,e=this.J.parentNode;for(;t&&t.J.parentNode===e;)t.K=null,t=t.D?.At}St(){let t=this.V.parentNode;return this.V===t.firstChild&&this.J===t.lastChild&&(t.innerHTML="",t.append(this.V,this.J),!0)}Ht(t,e){if(Array.isArray(t))for(let l of t)this.Ht(l,e);else if("function"==typeof t)Globals$1.t=this,this.B=t,t=t(),Globals$1.t=null,this.Ht(t,e);else if(t instanceof Template||t?.nodeType)e(t);else{void 0===t||!1===t||null===t?t="":"string"!=typeof t&&(t+="");let l=new Template([t],[]);l.Ut=!0,this.Ht(l,e)}}Gt(t,e=!0){let l,s=this.vt;if(e){if(l=s.bt(t.Mt()),l||(s=this.Tt,l=s.bt(t.Mt())),!l)return null;s.yt(t.Lt(),l)}else t.exprs.length&&(l=s.bt(t.Lt()),l||(s=this.Tt,l=s.bt(t.Lt())),l&&(s.yt(l.It,l),l.Ct(t.exprs),l.It=t.Mt()));return l||(l=new NodeGroup(t,this),l.Ct(t.exprs),l.It=t.Mt()),this.Et.push(l),l}Pt(){let t=this.vt.data,e=this.Tt.data;for(let l in t){let s=e[l];if(s)for(let e of t[l])s.add(e);else e[l]=t[l]}this.vt=new MultiValueMap;let l=this.vt;for(let t of this.Et)l.add(t.It,t),l.add(t.Rt,t);this.Et=[]}lt(){let t;if(t=this.K,t)return t;t=[];let e=this.V.nextSibling,l=this.J;for(;e&&e!==l;)t.push(e),e=e.nextSibling;return this.K=t,t}}class PathToComponent extends Path{kt;constructor(t,e){super(null,e)}apply(t,e=!0,l=!0){let s=this.J,i=Util.P(s,"_is");for(let e,l=0;e=this.kt[l];l++)if(e instanceof PathToAttribValue)i[Util.G(e.attrName)]=e.ft(t[l]);else{let s=e.ft(t[l]);if("object"==typeof s)for(let t in s)i[Util.G(t)]=s[t];else if("string"==typeof s){let t=s.split(/([\w-]+\s*=\s*(?:"[^"]*"|'[^']*'|\S+))/g).map((t=>t.trim())).filter((t=>t.length));for(let e of t){let[t,l]=e.split(/\s*=\s*/);l=(l||"").replace(/^(['"])(.*)\1$/,"$2"),i[Util.G(t)]=l}}}let r=s.getAttribute("_is");if(s.tagName.endsWith("-SOLARITE-PLACEHOLDER")||r){let e=(r||s.tagName.slice(0,-21)).toLowerCase(),o=customElements.get(e);if(!o)throw Error(`Must call customElements.define('${e}', Class) before using it.`);Globals$1.l=[...s.childNodes];let n=new o(i);r&&n.setAttribute("is",r);for(let t of s.attributes)"_is"!==t.name&&n.setAttribute(t.name,t.value);for(let t in i){let e=i[t],l=typeof e;"boolean"===l?!1!==e&&null!=e&&n.setAttribute(t,""):"string"!==l&&"number"!==l&&"bigint"!==l||n.setAttribute(t,e)}let a=n.getAttribute("data-id")||n.getAttribute("id");a&&delve(this.D.getRootNode(),a.split(/\./g),n);let h=this.D;this.J=n;for(let t of h.Ft)t.J===s&&(t.J=n),t.V===s&&(t.V=n);h.Ot===s&&(h.Ot=n),h.Vt===s&&(h.Vt=n),"function"!=typeof n.render||Globals$1.$.has(n)||n.render(i,l);for(let e,l=0;e=this.kt[l];l++)e.D=this.D,e.J=n,e.apply(t[l]);s.replaceWith(n)}else"function"==typeof s.render&&s.render(i,l);Globals$1.l=null}clone(t,e=0){let l=this.X(t,e),s=new PathToComponent(null,l);return s.kt=this.kt.map((l=>l.clone(t,e))),s}q(){return 0}}class Shell{fragment;Ft=[];Jt=[];scripts=[];Dt=[];constructor(t=null){if(!t)return;if(1===t.length&&!t[0].match(/[<&]/))return void(this.fragment=Globals$1.i.createTextNode(t[0]));let e,l=Shell.zt(t),s=Globals$1.i.createElement("template");l?s.innerHTML=l:s.content.append(Globals$1.i.createTextNode("")),this.fragment=s.content;let i=[],r=0;const o=Globals$1.i.createTreeWalker(this.fragment,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_COMMENT|NodeFilter.SHOW_TEXT);for(;e=o.nextNode();)if(i.map((t=>t.remove())),i=[],1===e.nodeType){const t=e.hasAttribute("is"),l=t||e.tagName.includes("-"),s=[];for(let t of[...e.attributes]){let i=t.name.match(/^[\ue000-\uf8ff]$/);if(i){let t=new PathToAttribs(null,e);this.Ft.push(t),l&&(t.tt=!0,s.push(t)),r++,e.removeAttribute(i[0])}else{let i=t.value.split(/[\ue000-\uf8ff]/g);if(i.length>1){let o=2!==i.length||i[0].length||i[1].length?i:null,n=Util.j(t.name)?new PathToEvent(null,e,t.name,o):new PathToAttribValue(null,e,t.name,o);n.et=Util.U(e,t.name),this.Ft.push(n),l&&(n.tt=!0,s.push(n)),r+=i.length-1;try{e.setAttribute(t.name,i.join(""))}catch(l){throw Error(`Error setting attribute "${t.name}" on node <${e.tagName}>: ${l.message}`)}}}}if(l){let l=new PathToComponent(null,e);l.kt=s,this.Ft.splice(this.Ft.length-s.length,0,l),t&&(e.setAttribute("_is",e.getAttribute("is")),e.removeAttribute("is"))}}else if(8===e.nodeType&&"!✨!"===e.nodeValue){if(e?.parentNode?.closest&&e?.parentNode?.closest("[contenteditable]"))throw Error('Contenteditable can\'t have expressions inside them. Use <div contenteditable value="${...}"> instead.');let t,l=e.previousSibling;l||(l=Globals$1.i.createComment("Path:"+this.Ft.length),e.parentNode.insertBefore(l,e)),!e.nextSibling||8===e.nextSibling.nodeType&&"!✨!"===e.nextSibling.textContent?(t=e,t.textContent="PathEnd:"+this.Ft.length):(t=e.nextSibling,i.push(e));let s=new PathToNodes(l,t);this.Ft.push(s),r++}else{if(3===e.nodeType&&"TEXTAREA"===e.parentNode?.tagName&&e.textContent.includes("\x3c!--!✨!--\x3e"))throw Error('Textarea can\'t have expressions inside them. Use <textarea value="${...}"> instead.');if(8===e.nodeType){let t=e.textContent.split(/[\ue000-\uf8ff]/g);for(let l=0;t.length-1>l;l++){let t=new Path(e.previousSibling,e);this.Ft.push(t),r++}}else if(3===e.nodeType&&["SCRIPT","STYLE"].includes(e.parentNode?.nodeName)){let t=e.textContent.split(commentPlaceholder);if(t.length>1){let l=[];for(let s=0;t.length>s;s++){let i=Globals$1.i.createTextNode(t[s]);e.parentNode.insertBefore(i,e),s>0&&l.push(i)}for(let t,e=0;t=l[e];e++){let e=new PathToNodes(t.previousSibling,t);this.Ft.push(e),r++}i.push(e)}}}if(i.map((t=>t.remove())),r!==t.length-1)throw Error("Could not parse expressions in template. Check for duplicate attributes or malformed html: "+t.join("${...}"));for(let t of this.Ft)t.V&&(t.Z=[].indexOf.call(t.V.parentNode.childNodes,t.V)),t._=Path.get(t.J);this.Wt()}static zt(t){let e=[],l=new HtmlParser;for(let s=0;t.length>s;s++){let i=0,r=l.parse(t[s],((t,l,s)=>{if(i!==l){let r=t.slice(i,l);s===HtmlParser.rt&&(r=r.replace(/^<\/?[a-z][a-z0-9]*-[a-z0-9-]+/i,(t=>t+"-SOLARITE-PLACEHOLDER"))),e.push(r)}i=l}));t.length-1>s&&e.push(r===HtmlParser.Text?commentPlaceholder:String.fromCharCode(attribPlaceholder+s))}return e.join("")}Wt(){this.scripts=[].map.call(this.fragment.querySelectorAll("scripts"),(t=>Path.get(t))),this.Dt=[].map.call(this.fragment.querySelectorAll("style"),(t=>Path.get(t)));let t=this.fragment.querySelectorAll("[id],[data-id]");for(let e of t){let t=e.getAttribute("data-id")||e.getAttribute("id");if(Globals$1.div.hasOwnProperty(t))throw Error(`<${e.tagName.toLowerCase()} id="${t}"> can't override existing HTMLElement id property.`)}this.Jt=[].map.call(t,(t=>Path.get(t)))}static get(t){let e=Globals$1.v.get(t);return e||(e=new Shell(t),Globals$1.v.set(t,e)),e}}const commentPlaceholder="\x3c!--!✨!--\x3e",attribPlaceholder=57344;class NodeGroup{ut;At;Ot;Vt;Ft=[];It;Rt;K;Dt;Kt;root;constructor(t,e=null,l=null,s=null){if(this.ut=e?.D?.ut||this,this.At=e,this.Kt=t,this.Rt=t.Lt(),t.Ut)this.Ot=this.Vt=Globals$1.i.createTextNode(t.html[0]);else{const e=Shell.get(t.html),i=e.fragment.cloneNode(!0);if(11===i.nodeType?(this.Ot=i.firstChild,this.Vt=i.lastChild):this.Ot=this.Vt=i,this instanceof RootNodeGroup){let t=0;if(this.options=s,i instanceof Text){if(!l)throw Error("Cannot create a standalone text node");this.root=l,i.nodeValue.length&&this.root.append(i)}else{if(l){let e;if(this.root=l,(Globals$1.l||l.childNodes.length)&&(e=Globals$1.i.createDocumentFragment(),e.append(...Globals$1.l||l.childNodes)),isReplaceEl(i,this.root.tagName)){this.root.append(...i.children[0].childNodes);for(let t of i.children[0].attributes)this.root.hasAttribute(t.name)||this.root.setAttribute(t.name,t.value);t=1}else 1===i.childNodes.length&&3===i.childNodes[0].nodeType&&""===i.childNodes[0].textContent||this.root.append(...i.childNodes);if(e){for(let t of l.querySelectorAll("slot[name]")){let l=t.getAttribute("name");if(l){let s=e.querySelectorAll(`[slot='${l}']`);t.append(...s)}}let t=l.querySelector("slot:not([name])");t?t.append(e):l.append(e)}}else{let e=getSingleEl(i);this.root=e||i,e&&(t=1)}this.Zt(this.root,e.Ft,t),this._t(this.root,e,t)}this.Ot=this.Vt=this.root,Globals$1.p.set(this.root,this)}else e&&(e.Ft.length&&this.Zt(i,e.Ft),this._t(i,e))}}Ct(t,e=!0,l=!0){let s=this.Ft,i=t.length,r=Array(s.length);for(let o,n=s.length-1;o=s[n];n--){if(0===n&&o instanceof PathToComponent&&o.J===this.getRootNode())continue;let s=o.q();if(r[n]=t.slice(i-s,i),i-=s,o instanceof PathToComponent){let t=r.slice(n+1,n+1+o.kt.length);o.apply(t,!0,e)}else l&&o.apply(r[n])}l&&(this.Bt(),this.K=null)}qt(t){}lt(){let t=this.K;if(t)return t;t=[];let e=this.Ot,l=this.Vt?.nextSibling;for(;e&&e!==l;)t.push(e),e=e.nextSibling;return this.K=t,t}getRootNode(){return this.ut.root}Xt(){return this.ut}Zt(t,e,l=0){let s=e.length;this.Ft.length=s;for(let i=0;s>i;i++){let s=e[i].clone(t,l);s.D=this,this.Ft[i]=s}}Bt(){if(this.Dt)for(let[t,e]of this.Dt)e!==t.textContent&&Util.N(t,this.Xt().root)}_t(root,shell,pathOffset=0){let rootEl=this.ut.root;if(rootEl){let options=this.ut.options;if(!1!==options?.Jt)for(let t of shell.Jt){pathOffset&&(t=t.slice(0,-pathOffset));let e=Path.resolve(root,t);Util.A(rootEl,e)}if(!1!==options?.Dt){shell.Dt.length&&(this.Dt=new Map);for(let t of shell.Dt){pathOffset&&(t=t.slice(0,-pathOffset));let e=Path.resolve(root,t);1===rootEl.nodeType&&(Util.N(e,rootEl),this.Dt.set(e,e.textContent))}}if(!1!==options?.scripts)for(let path of shell.scripts){pathOffset&&(path=path.slice(0,-pathOffset));let script=Path.resolve(root,path);eval(script.textContent)}}}}function getSingleEl(t){let e=[];for(let l of t.childNodes)if(1===l.nodeType||3===l.nodeType&&l.textContent.trim().length){if(e.length)return null;e.push(l)}return e[0]}function isReplaceEl(t,e){return 1===t.children.length&&e.includes("-")&&t.children[0].tagName.replace("-SOLARITE-PLACEHOLDER","")===e}class RootNodeGroup extends NodeGroup{Yt}class Template{exprs=[];html=[];Qt;Rt;It;Ut;constructor(t=[""],e=[]){this.html=t,this.exprs=e}toJSON(){return void 0===this.Qt&&(this.Qt=[getObjectId(this.html),this.exprs]),this.Qt}render(t=null,e={}){let l=t&&Globals$1.p.get(t);if(l||(l=new RootNodeGroup(this,null,t,e),t||(t=l.getRootNode()),Globals$1.p.set(t,l)),1!==this.html?.length||this.html[0]){let t=l.It,e=this.Mt();l.Ct(this.exprs,t!==e),l.It=e}else t.innerHTML="";return l.Yt=new Map,t}Mt(){return void 0===this.It&&(this.It=this.exprs.length?getObjectHash(this):this.html[0]),this.It}Lt(){return void 0===this.Rt&&(this.Rt=this.exprs.length?this.toJSON()[0]:this.html[0]),this.Rt}static te(t,e,l){const s=selfClosingTags.has(t.toLowerCase());let i=[],r=[],o="<"+t;if(e&&"object"==typeof e)for(let t in e){let l=e[t];"id"!==t&&"data-id"!==t?(o+=` ${t}=`,i.push(o),r.push(l),o=""):o+=` ${t}="${l}"`}if(!s){i.push(i.length>0?'"'===o?'">':">":o+">");for(let t of l)addChild(t,i,r)}return s?i.push(i.length>0?">":o+">"):i[i.length-1]+=`</${t}>`,new Template(i,r)}}const selfClosingTags=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),addChild=(t,e,l)=>{if(Array.isArray(t))for(let s of t)addChild(s,e,l);else{let s=!1;if(t instanceof Template)if(t.exprs.length>0)s=!0;else{const e=(t.html[0]||"").match(/^<([a-zA-Z][\w:-]*)/),l=e?e[1].toLowerCase():"";s=selfClosingTags.has(l)}if(s){e[e.length-1]+=t.html[0];for(let s=0;t.exprs.length>s;s++)l.push(t.exprs[s]),e.push(t.html[s+1]??"")}else l.push(t),e.push("")}};function toEl(t){if("string"==typeof t){let e=t;(e.match(/^\s^<\S+/)||e.match(/\S+>\s+$/))&&(e=e.trim());let l=Globals$1.i.createElement("template");l.innerHTML=e;let s=Util.F(l.content.childNodes);return 1===s.length?s[0]:l.content}if(t instanceof Template)return t.render();if(t&&"object"==typeof t){let e=t;if("Object"!==e.constructor.name)throw Error(`Solarate Web Component class ${e.constructor?.name} must extend HTMLElement.`);if(!Globals$1.m.has(e)){Globals$1.m.set(e,null),e[renderF]();let t=Globals$1.m.get(e);Globals$1.m.delete(e);for(let l in e)t[l]="function"==typeof e[l]?e[l].bind(t):e[l];return t}}throw Error("toEl() does not support argument of type: "+(t?typeof t:t))}let renderF="render";function h(t=void 0,...e){if(Array.isArray(arguments[0]))return new Template(arguments[0],e);if("string"==typeof arguments[0]||arguments[0]instanceof String){let t=arguments[0];if(!e.length||"object"!=typeof e[0]&&null!==e[0]){let e=t;return e.match(/^\s^</)&&(e=e.trim()),new Template([e],[])}{let l=t+"",s=e[0]||{},i=e.slice(1);return Template.te(l,s,i)}}if(arguments[0]instanceof HTMLElement||arguments[0]instanceof DocumentFragment){if(!(arguments[1]instanceof Template)){let t=arguments[0],e=arguments[1];t.shadowRoot&&(t.innerHTML="");let l=(l,...s)=>(Globals$1.$.add(t),new Template(l,s).render(t,e));return l}arguments[1].render(arguments[0],arguments[2])}else{if(!arguments.length)return(t,...e)=>toEl(h(t,...e));if("object"!=typeof arguments[0]||!Globals$1.m.has(arguments[0])){if(Util.L(arguments[0]))return new Template;throw Error("h() does not support argument of type: "+(arguments[0]?typeof arguments[0]:arguments[0]))}{let t=arguments[0];if("Object"!==t.constructor.name)throw Error(`Solarate Web Component class ${t.constructor?.name} must extend HTMLElement.`);if(!(arguments[1]instanceof Template))return((...e)=>{let l=h(...e).render();Globals$1.m.set(t,l)}).bind(t);{let e=arguments[1].render();Globals$1.m.set(t,e)}}}}function getArg(el,attributeName,defaultValue=void 0,type=ArgType.String){let val=defaultValue,attrVal=el.getAttribute(attributeName)||el.getAttribute(Util.O(attributeName));if(null!==attrVal&&(val=attrVal),Array.isArray(type))return type.includes(val)?val:void 0;if("function"==typeof type)return type.constructor?new type(val):type(val);if(type===ArgType.ee){let t="string"==typeof val?val.toLowerCase():val;return!["false","0",!1,0,null,void 0,NaN].includes(t)&&(!(!["true",!0].includes(t)&&0===parseFloat(t))||void 0)}switch(type){case ArgType.le:return parseInt(val);case ArgType.se:return parseFloat(val);case ArgType.String:return[void 0,null,!1].includes(val)?"":val+"";case ArgType.ie:case ArgType.re:if("string"!=typeof val||!val.length)return val;try{return type===ArgType.ie?JSON.parse(val):eval(`(${val})`)}catch(t){return val}default:return val}}function setArgs(t,e,l){for(let s in e)this[s]=getArg(t,s,e[s],l[s]||ArgType.String)}var ArgType={ee:"Bool",le:"Int",se:"Float",String:"String",JSON:"Json",ie:"Json",re:"Eval"};function t(t){return new Template([t],[])}let HTMLElementAutoDefine=new Proxy(HTMLElement,{construct:(t,e,l)=>(Util.C(l),Reflect.construct(t,e,l))});class Solarite extends HTMLElementAutoDefine{constructor(t=null){if(super(),t){if("object"!=typeof t)throw Error("First argument to custom element constructor must be an object.");if(t&&!Object.keys(t).length){let e=Solarite.getAttribs(this);for(let l in e)t[l]=e[l]}}}render(){throw Error("render() is not defined for "+this.constructor.name)}renderFirstTime(){if(!Globals$1.$.has(this)){let t=Solarite.getAttribs(this);this.render(t)}}connectedCallback(){this.renderFirstTime()}static define(t=null){Util.C(this,t)}static getAttribs(t){let e=Util.P(t);for(let t in e){let l=e[t];l.startsWith("${")&&l.endsWith("}")&&(e[t]=JSON.parse(l.slice(2,-1)))}return e}}function assignFields(t,e,l=[]){for(let s in e||{})if(s in t&&!l.includes(s)){const l=Object.getOwnPropertyDescriptor(t,s)||Object.getOwnPropertyDescriptor(Object.getPrototypeOf(t),s);if(!l||l.writable||l.set){let l=e[s],i=t[s];t[s]="string"==typeof e[s]?"boolean"==typeof i?![!1,"false",0,"0"].includes(l):"number"==typeof i?+l:i instanceof Date?new Date(l):l:l}}}export default h;export{ArgType,Globals$1 as Globals,HtmlParser,NodeGroup,Shell,Solarite,Util as SolariteUtil,Template,assignFields,delve,getArg,h,h as r,setArgs,t,toEl};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solarite",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Solarite is a small (9KB min+gzip), fast, compilation-free JavaScript library for adding reactivity to native web components, so that updates require minimal re-rendering.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/Solarite.js",
|
package/src/PathToAttribValue.js
CHANGED
|
@@ -13,6 +13,9 @@ export default class PathToAttribValue extends Path {
|
|
|
13
13
|
* @type {?string[]} Used only if type=AttribType.Value. If null, use one expr to set the whole attribute value. */
|
|
14
14
|
attrValue;
|
|
15
15
|
|
|
16
|
+
/** @type {boolean} Provides value for attribute on a component. */
|
|
17
|
+
isComponent;
|
|
18
|
+
|
|
16
19
|
isHtmlProperty;
|
|
17
20
|
|
|
18
21
|
constructor(nodeBefore, nodeMarker, attrName=null, attrValue=null) {
|
package/src/PathToAttribs.js
CHANGED
|
@@ -8,6 +8,9 @@ export default class PathToAttribs extends Path {
|
|
|
8
8
|
* @type {Set<string>} Used for type=AttribType.Multiple to remember the attributes that were added. */
|
|
9
9
|
attrNames;
|
|
10
10
|
|
|
11
|
+
/** @type {boolean} Provides one or more attributes on a component. */
|
|
12
|
+
isComponent;
|
|
13
|
+
|
|
11
14
|
constructor(nodeBefore, nodeMarker) {
|
|
12
15
|
super(null, null);
|
|
13
16
|
this.nodeMarker = nodeMarker;
|
|
@@ -74,4 +77,5 @@ export default class PathToAttribs extends Path {
|
|
|
74
77
|
|
|
75
78
|
|
|
76
79
|
getExpressionCount() { return 1 }
|
|
80
|
+
getValue(exprs) { return exprs[0]; }
|
|
77
81
|
}
|
package/src/PathToComponent.js
CHANGED
|
@@ -2,6 +2,7 @@ import Path from "./Path.js";
|
|
|
2
2
|
import Util from "./Util.js";
|
|
3
3
|
import delve from "./delve.js";
|
|
4
4
|
import assert from "./assert.js";
|
|
5
|
+
import PathToAttribValue from "./PathToAttribValue.js";
|
|
5
6
|
import Globals from "./Globals.js";
|
|
6
7
|
|
|
7
8
|
export default class PathToComponent extends Path {
|
|
@@ -36,8 +37,27 @@ export default class PathToComponent extends Path {
|
|
|
36
37
|
// 1. Attributes
|
|
37
38
|
let attribs = Util.attribsToObject(el, '_is');
|
|
38
39
|
for (let i=0, attribPath; attribPath = this.attribPaths[i]; i++) {
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
if (attribPath instanceof PathToAttribValue) {
|
|
41
|
+
let name = Util.dashesToCamel(attribPath.attrName);
|
|
42
|
+
attribs[name] = attribPath.getValue(exprs[i]);
|
|
43
|
+
}
|
|
44
|
+
else { // PathToAttribs
|
|
45
|
+
let val = attribPath.getValue(exprs[i]);
|
|
46
|
+
if (typeof val === 'object')
|
|
47
|
+
for (let name in val)
|
|
48
|
+
attribs[Util.dashesToCamel(name)] = val[name];
|
|
49
|
+
else if (typeof val === 'string') {
|
|
50
|
+
let attrs = val.split(/([\w-]+\s*=\s*(?:"[^"]*"|'[^']*'|\S+))/g)
|
|
51
|
+
.map(text => text.trim())
|
|
52
|
+
.filter(text => text.length);
|
|
53
|
+
|
|
54
|
+
for (let attr of attrs) {
|
|
55
|
+
let [name, value] = attr.split(/\s*=\s*/); // split on first equals.
|
|
56
|
+
value = (value || '').replace(/^(['"])(.*)\1$/, '$2'); // trim value quotes if they match.
|
|
57
|
+
attribs[Util.dashesToCamel(name)] = value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
41
61
|
}
|
|
42
62
|
|
|
43
63
|
// 2. Instantiate component on first time.
|
package/src/PathToEvent.js
CHANGED
|
@@ -20,6 +20,14 @@ export default class PathToEvent extends PathToAttribValue {
|
|
|
20
20
|
assert(Array.isArray(exprs));
|
|
21
21
|
//#ENDIF
|
|
22
22
|
|
|
23
|
+
// Tested by Solariate.events.classicWithExpr
|
|
24
|
+
// We have expressions within a string attribute value that's not a Solarite event. E.g.
|
|
25
|
+
// <div onclick="alert(${1});"
|
|
26
|
+
if (this.attrValue?.length > 1) {
|
|
27
|
+
super.apply(exprs);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
// Don't bind events to component placeholders.
|
|
24
32
|
// PathToComponent will do the binding later when it instantiates the component.
|
|
25
33
|
if (this.isComponentAttrib && this.nodeMarker.tagName.endsWith('-SOLARITE-PLACEHOLDER'))
|
package/src/Shell.js
CHANGED
|
@@ -85,13 +85,15 @@ export default class Shell {
|
|
|
85
85
|
|
|
86
86
|
for (let attr of [...node.attributes]) { // Copy the attributes array b/c we remove attributes with placeholders as we go.
|
|
87
87
|
|
|
88
|
-
//
|
|
88
|
+
// One or more whole attributes
|
|
89
89
|
let matches = attr.name.match(/^[\ue000-\uf8ff]$/)
|
|
90
90
|
if (matches) {
|
|
91
91
|
let path = new PathToAttribs(null, node);
|
|
92
92
|
this.paths.push(path);
|
|
93
|
-
if (isComponent)
|
|
93
|
+
if (isComponent) {
|
|
94
|
+
path.isComponentAttrib = true;
|
|
94
95
|
componentAttribPaths.push(path);
|
|
96
|
+
}
|
|
95
97
|
|
|
96
98
|
placeholdersUsed ++;
|
|
97
99
|
node.removeAttribute(matches[0]); // TODO: Is this necessary?
|
|
@@ -114,7 +116,12 @@ export default class Shell {
|
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
placeholdersUsed += parts.length - 1;
|
|
117
|
-
|
|
119
|
+
try {
|
|
120
|
+
node.setAttribute(attr.name, parts.join(''));
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
throw new Error(`Error setting attribute "${attr.name}" on node <${node.tagName}>: ${e.message}`);
|
|
124
|
+
}
|
|
118
125
|
}
|
|
119
126
|
}
|
|
120
127
|
}
|
package/src/Solarite.d.ts
CHANGED
|
@@ -19,10 +19,11 @@ declare function h(el: HTMLElement | DocumentFragment, options?: RenderOptions):
|
|
|
19
19
|
declare function h(el: HTMLElement | DocumentFragment, template: Template, options?: RenderOptions): void;
|
|
20
20
|
declare function h(tag: string, props: object, ...children: any[]): Template; // JSX
|
|
21
21
|
declare function h(obj: {render: Function}): (htmlStrings: TemplateStringsArray, ...exprs: any[]) => void; // Rebound render
|
|
22
|
+
declare function h(): (htmlStrings: TemplateStringsArray, ...exprs: any[]) => Node|DocumentFragment;
|
|
22
23
|
|
|
23
24
|
export default h;
|
|
24
25
|
export {h};
|
|
25
|
-
export {h as r};
|
|
26
|
+
export {h as r}; // deprecated
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
29
|
* Solarite provides more features if your web component extends Solarite instead of HTMLElement. */
|
|
@@ -40,6 +41,12 @@ export class Solarite extends HTMLElement {
|
|
|
40
41
|
* Convert a template, string, or object into a DOM Node or Element. */
|
|
41
42
|
export function toEl(arg: string | Template | {render: () => void}): Node | HTMLElement | DocumentFragment;
|
|
42
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Assign fields from `src` to `dest` if they exist in `dest` and don't exist in `ignore`.
|
|
46
|
+
* When a value in `src` is a string and the existing value in `dest` is a boolean, number, or Date,
|
|
47
|
+
* it will be converted to that type. */
|
|
48
|
+
export function assignFields(dest: object, src: object|null, ignore?: string[]): void;
|
|
49
|
+
|
|
43
50
|
/**
|
|
44
51
|
* @deprecated
|
|
45
52
|
* Retrieve and cast an attribute value from an HTMLElement. */
|
package/src/Solarite.js
CHANGED
|
@@ -145,4 +145,142 @@ export class Solarite extends HTMLElementAutoDefine {
|
|
|
145
145
|
}
|
|
146
146
|
return result;
|
|
147
147
|
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
// TODO: Do we want to use this to get the tag name from the render() function, instead of having the user define it?
|
|
151
|
+
/**
|
|
152
|
+
* Get the tag name for a class, as defined by the tag used in render().
|
|
153
|
+
*
|
|
154
|
+
* This will parse the JavaScript code of the render() function to find the tag name.
|
|
155
|
+
* It will itarage every character, keeping track of quotes and comments so it can
|
|
156
|
+
* skip them until it finds the tag name passed to h(this)`<tagname>` inside the render() function.
|
|
157
|
+
*
|
|
158
|
+
* */
|
|
159
|
+
/*
|
|
160
|
+
static getTagName(Class) {
|
|
161
|
+
let code = Class.prototype.render.toString();
|
|
162
|
+
let i = 0;
|
|
163
|
+
while (i < code.length) {
|
|
164
|
+
let char = code[i];
|
|
165
|
+
let next = code[i + 1];
|
|
166
|
+
|
|
167
|
+
// Skip single line comments
|
|
168
|
+
if (char === '/' && next === '/') {
|
|
169
|
+
i = code.indexOf('\n', i);
|
|
170
|
+
if (i === -1) break;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
// Skip multi-line comments
|
|
174
|
+
if (char === '/' && next === '*') {
|
|
175
|
+
i = code.indexOf('*'+'/', i + 2);
|
|
176
|
+
if (i === -1) break;
|
|
177
|
+
i += 2;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
// Skip strings and template literals
|
|
181
|
+
if (char === "'" || char === '"' || char === '`') {
|
|
182
|
+
let quote = char;
|
|
183
|
+
i++;
|
|
184
|
+
while (i < code.length) {
|
|
185
|
+
if (code[i] === '\\') i += 2;
|
|
186
|
+
else if (code[i] === quote) { i++; break; }
|
|
187
|
+
else i++;
|
|
188
|
+
}
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
// Skip regex literals (simple heuristic)
|
|
192
|
+
if (char === '/') {
|
|
193
|
+
let prev = code.slice(Math.max(0, i - 10), i).trim();
|
|
194
|
+
// If / is preceded by something that indicates an operator or start of expression
|
|
195
|
+
if (/[=(,;:[!&|?]$|return$|yield$|case$/.test(prev)) {
|
|
196
|
+
i++;
|
|
197
|
+
while (i < code.length) {
|
|
198
|
+
if (code[i] === '\\') i += 2;
|
|
199
|
+
else if (code[i] === '[') { // Skip character classes
|
|
200
|
+
i++;
|
|
201
|
+
while (i < code.length && code[i] !== ']') {
|
|
202
|
+
if (code[i] === '\\') i += 2;
|
|
203
|
+
else i++;
|
|
204
|
+
}
|
|
205
|
+
i++;
|
|
206
|
+
}
|
|
207
|
+
else if (code[i] === '/') { i++; break; }
|
|
208
|
+
else i++;
|
|
209
|
+
}
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// Check for h(this)`
|
|
214
|
+
if (char === 'h' && code.slice(i, i + 8) === 'h(this)`') {
|
|
215
|
+
i += 8;
|
|
216
|
+
// We are now inside the template literal.
|
|
217
|
+
// Skip whitespace and HTML comments
|
|
218
|
+
while (i < code.length) {
|
|
219
|
+
// Skip JS template literal end (shouldn't happen before tag, but for safety)
|
|
220
|
+
if (code[i] === '`') return null;
|
|
221
|
+
|
|
222
|
+
// Skip whitespace
|
|
223
|
+
if (/\s/.test(code[i])) { i++; continue; }
|
|
224
|
+
|
|
225
|
+
// Skip HTML comments <!-- ... -->
|
|
226
|
+
if (code.slice(i, i + 4) === '<!--') {
|
|
227
|
+
i = code.indexOf('-->', i + 4);
|
|
228
|
+
if (i === -1) return null;
|
|
229
|
+
i += 3;
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Find the first tag
|
|
234
|
+
if (code[i] === '<') {
|
|
235
|
+
let start = ++i;
|
|
236
|
+
while (i < code.length && /[a-zA-Z0-9-]/.test(code[i])) i++;
|
|
237
|
+
return code.slice(start, i);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// If we encounter anything else (like text before a tag),
|
|
241
|
+
// we can keep looking or return null depending on how strict we want to be.
|
|
242
|
+
// For now, let's just skip non-tag characters.
|
|
243
|
+
i++;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
i++;
|
|
247
|
+
}
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
*/
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Assign fields from `src` to `dest` if they exist in `dest` and their names are not in the `ignore` list.
|
|
256
|
+
* When a value in `src` is a string and the existing value in `dest` is a boolean, number, or Date,
|
|
257
|
+
* it will be converted to that type.
|
|
258
|
+
* This is often used in class constructors that accept an object of arguments.
|
|
259
|
+
* @param {object} dest
|
|
260
|
+
* @param {?object} src
|
|
261
|
+
* @param {string[]} [ignore=[]] */
|
|
262
|
+
export function assignFields(dest, src, ignore=[]) {
|
|
263
|
+
for (let name in src || {}) {
|
|
264
|
+
if (name in dest && !ignore.includes(name)) {
|
|
265
|
+
const descriptor = Object.getOwnPropertyDescriptor(dest, name)
|
|
266
|
+
|| Object.getOwnPropertyDescriptor(Object.getPrototypeOf(dest), name); // Also find (parent?) setters. Is this necssary?
|
|
267
|
+
if (!descriptor || descriptor.writable || descriptor.set) {
|
|
268
|
+
let srcVal = src[name];
|
|
269
|
+
let destVal = dest[name];
|
|
270
|
+
if (typeof src[name] === 'string') {
|
|
271
|
+
if (typeof destVal === 'boolean') // empty string (when an attribute is present with no value) is true
|
|
272
|
+
dest[name] = ![false, 'false', 0, '0'].includes(srcVal);
|
|
273
|
+
else if (typeof destVal === 'number')
|
|
274
|
+
dest[name] = Number(srcVal);
|
|
275
|
+
else if (destVal instanceof Date) {
|
|
276
|
+
dest[name] = new Date(srcVal); // TODO: read it as UTC 0 by default.
|
|
277
|
+
}
|
|
278
|
+
else
|
|
279
|
+
dest[name] = srcVal;
|
|
280
|
+
}
|
|
281
|
+
else
|
|
282
|
+
dest[name] = srcVal;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
148
286
|
}
|
package/src/Template.js
CHANGED