cdom 0.0.15 → 0.0.16
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/index.js +137 -10
- package/package.json +1 -1
- package/helpers/add.js +0 -3
- package/helpers/and.js +0 -4
- package/helpers/decrement.js +0 -10
- package/helpers/divide.js +0 -7
- package/helpers/eq.js +0 -4
- package/helpers/gt.js +0 -4
- package/helpers/if.js +0 -4
- package/helpers/ifs.js +0 -7
- package/helpers/increment.js +0 -10
- package/helpers/lt.js +0 -4
- package/helpers/multiply.js +0 -4
- package/helpers/not.js +0 -4
- package/helpers/or.js +0 -4
- package/helpers/set.js +0 -13
- package/helpers/subtract.js +0 -7
- package/helpers/sum.js +0 -4
- package/helpers/switch.js +0 -7
- package/helpers/toggle.js +0 -9
package/index.js
CHANGED
|
@@ -35,20 +35,20 @@
|
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
function tokenize(src) {
|
|
39
|
+
const tokenRegex = /\s*(\d*\.\d+|\d+|"([^"\\]|\\.)*"|'([^'\\]|\\.)*'|=\/|=\$this|=\$event|=\$query|=\$|[a-zA-Z_$][\w$]*|==|!=|<=|>=|&&|\|\||[-+*/%^<>!?:.,(){}[\]])\s*/g;
|
|
40
|
+
const results = [];
|
|
41
|
+
let match;
|
|
42
|
+
while ((match = tokenRegex.exec(src)) !== null) {
|
|
43
|
+
results.push(match[1]);
|
|
44
|
+
}
|
|
45
|
+
return results;
|
|
46
|
+
}
|
|
47
|
+
|
|
38
48
|
function createExpression(text) {
|
|
39
49
|
let at = 0;
|
|
40
50
|
const tokens = tokenize(text);
|
|
41
51
|
|
|
42
|
-
function tokenize(src) {
|
|
43
|
-
const results = [];
|
|
44
|
-
const tokenRegex = /\s*(\d*\.\d+|\d+|"([^"\\]|\\.)*"|'([^'\\]|\\.)*'|=\/|=\$this|=\$event|=\$query|=\$|[a-zA-Z_$][\w$]*|==|!=|<=|>=|&&|\|\||[-+*/%^<>!?:.,(){}[\]])\s*/g;
|
|
45
|
-
let match;
|
|
46
|
-
while ((match = tokenRegex.exec(src)) !== null) {
|
|
47
|
-
results.push(match[1]);
|
|
48
|
-
}
|
|
49
|
-
return results;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
52
|
function peek(offset = 0) { return tokens[at + offset]; }
|
|
53
53
|
function next() { return tokens[at++]; }
|
|
54
54
|
function consume(expected) {
|
|
@@ -852,6 +852,7 @@
|
|
|
852
852
|
}
|
|
853
853
|
|
|
854
854
|
async function loadHelper(name) {
|
|
855
|
+
if (helpers.has(name)) return Promise.resolve(helpers.get(name));
|
|
855
856
|
if (pendingHelpers.has(name)) return pendingHelpers.get(name);
|
|
856
857
|
|
|
857
858
|
const promise = (async () => {
|
|
@@ -906,6 +907,42 @@
|
|
|
906
907
|
set.add(sub);
|
|
907
908
|
}
|
|
908
909
|
|
|
910
|
+
function findNeededHelpers(obj, found = new Set()) {
|
|
911
|
+
if (!obj) return found;
|
|
912
|
+
|
|
913
|
+
if (typeof obj === 'string') {
|
|
914
|
+
if (obj.startsWith('=') && obj.length > 1) {
|
|
915
|
+
const tokens = tokenize(obj);
|
|
916
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
917
|
+
const t = tokens[i];
|
|
918
|
+
if (/^[a-zA-Z_$][\w$]*$/.test(t) && !['true', 'false', 'null', 'undefined'].includes(t)) {
|
|
919
|
+
if (i > 0 && tokens[i - 1] === '.') continue;
|
|
920
|
+
found.add(t);
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return found;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
if (typeof obj !== 'object' || obj.nodeType) return found;
|
|
928
|
+
|
|
929
|
+
if (Array.isArray(obj)) {
|
|
930
|
+
for (const item of obj) findNeededHelpers(item, found);
|
|
931
|
+
return found;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
for (const key in obj) {
|
|
935
|
+
const alias = symbolicOperators.get(key);
|
|
936
|
+
if (key.startsWith('=') && key.length > 1) {
|
|
937
|
+
found.add(key.slice(1));
|
|
938
|
+
} else if (alias) {
|
|
939
|
+
found.add(alias);
|
|
940
|
+
}
|
|
941
|
+
findNeededHelpers(obj[key], found);
|
|
942
|
+
}
|
|
943
|
+
return found;
|
|
944
|
+
}
|
|
945
|
+
|
|
909
946
|
|
|
910
947
|
function evaluateStructural(obj, context, event, unsafe) {
|
|
911
948
|
if (typeof obj !== 'object' || obj === null || obj.nodeType) {
|
|
@@ -1497,6 +1534,13 @@
|
|
|
1497
1534
|
const query = Object.fromEntries(url.searchParams.entries());
|
|
1498
1535
|
element._queryContext = query;
|
|
1499
1536
|
if (!element._macroContext) element._macroContext = query;
|
|
1537
|
+
|
|
1538
|
+
// Pre-load all needed helpers to avoid "suspense" flickering during hypermedia loads
|
|
1539
|
+
const helpersToLoad = findNeededHelpers(cdomData);
|
|
1540
|
+
if (helpersToLoad.size > 0) {
|
|
1541
|
+
await Promise.all(Array.from(helpersToLoad).map(name => loadHelper(name)));
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1500
1544
|
const dom = cdomToDOM(cdomData, true, false, element);
|
|
1501
1545
|
element.replaceChildren(dom);
|
|
1502
1546
|
} else if (isHTML) {
|
|
@@ -1554,6 +1598,65 @@
|
|
|
1554
1598
|
}
|
|
1555
1599
|
}
|
|
1556
1600
|
|
|
1601
|
+
// Core Library Functions (Inlined for performance/reliability)
|
|
1602
|
+
const _sum = (...args) => args.flat(Infinity).reduce((a, b) => a + (Number(b) || 0), 0);
|
|
1603
|
+
const _sub = (...args) => {
|
|
1604
|
+
const flat = args.flat(Infinity).map(v => Number(v) || 0);
|
|
1605
|
+
if (flat.length === 0) return 0;
|
|
1606
|
+
if (flat.length === 1) return -flat[0];
|
|
1607
|
+
return flat.reduce((a, b) => a - b);
|
|
1608
|
+
};
|
|
1609
|
+
const _mul = (...args) => args.flat(Infinity).reduce((a, b) => a * (Number(b) || 1), 1);
|
|
1610
|
+
const _div = (a, b) => (Number(a) || 0) / (Number(b) || 1);
|
|
1611
|
+
|
|
1612
|
+
const _set = function (target, val) {
|
|
1613
|
+
if (target && typeof target === 'object' && 'value' in target) {
|
|
1614
|
+
target.value = val;
|
|
1615
|
+
} else if (target && typeof target === 'function' && 'value' in target) {
|
|
1616
|
+
target.value = val;
|
|
1617
|
+
} else if (target && typeof target === 'object' && val && typeof val === 'object') {
|
|
1618
|
+
Object.assign(target, val);
|
|
1619
|
+
}
|
|
1620
|
+
return val;
|
|
1621
|
+
};
|
|
1622
|
+
_set.mutates = true;
|
|
1623
|
+
|
|
1624
|
+
const _inc = function (target, by = 1) {
|
|
1625
|
+
const hasValue = target && (typeof target === 'object' || typeof target === 'function') && 'value' in target;
|
|
1626
|
+
const current = hasValue ? target.value : 0;
|
|
1627
|
+
return _set(target, Number(current) + Number(by));
|
|
1628
|
+
};
|
|
1629
|
+
_inc.mutates = true;
|
|
1630
|
+
|
|
1631
|
+
const _dec = function (target, by = 1) {
|
|
1632
|
+
const hasValue = target && (typeof target === 'object' || typeof target === 'function') && 'value' in target;
|
|
1633
|
+
const current = hasValue ? target.value : 0;
|
|
1634
|
+
return _set(target, Number(current) - Number(by));
|
|
1635
|
+
};
|
|
1636
|
+
_dec.mutates = true;
|
|
1637
|
+
|
|
1638
|
+
const _toggle = function (target) {
|
|
1639
|
+
const hasValue = target && (typeof target === 'object' || typeof target === 'function') && 'value' in target;
|
|
1640
|
+
const current = hasValue ? target.value : false;
|
|
1641
|
+
return _set(target, !current);
|
|
1642
|
+
};
|
|
1643
|
+
_toggle.mutates = true;
|
|
1644
|
+
|
|
1645
|
+
const _if = (c, t, e) => c ? t : e;
|
|
1646
|
+
const _ifs = (...args) => {
|
|
1647
|
+
for (let i = 0; i < args.length; i += 2) {
|
|
1648
|
+
if (i + 1 >= args.length) return args[i]; // Default case
|
|
1649
|
+
if (args[i]) return args[i + 1];
|
|
1650
|
+
}
|
|
1651
|
+
};
|
|
1652
|
+
|
|
1653
|
+
const _switch = (exp, ...args) => {
|
|
1654
|
+
for (let i = 0; i < args.length - 1; i += 2) {
|
|
1655
|
+
if (exp === args[i]) return args[i + 1];
|
|
1656
|
+
}
|
|
1657
|
+
return args.length % 2 === 1 ? args[args.length - 1] : undefined;
|
|
1658
|
+
};
|
|
1659
|
+
|
|
1557
1660
|
// Export to global scope
|
|
1558
1661
|
cDOM.signal = signal;
|
|
1559
1662
|
cDOM.state = state;
|
|
@@ -1571,6 +1674,27 @@
|
|
|
1571
1674
|
// Register core helpers
|
|
1572
1675
|
helpers.set('state', state);
|
|
1573
1676
|
helpers.set('signal', signal);
|
|
1677
|
+
helpers.set('sum', _sum);
|
|
1678
|
+
helpers.set('add', _sum);
|
|
1679
|
+
helpers.set('subtract', _sub);
|
|
1680
|
+
helpers.set('multiply', _mul);
|
|
1681
|
+
helpers.set('divide', _div);
|
|
1682
|
+
helpers.set('eq', (a, b) => a == b);
|
|
1683
|
+
helpers.set('neq', (a, b) => a != b);
|
|
1684
|
+
helpers.set('gt', (a, b) => a > b);
|
|
1685
|
+
helpers.set('lt', (a, b) => a < b);
|
|
1686
|
+
helpers.set('gte', (a, b) => a >= b);
|
|
1687
|
+
helpers.set('lte', (a, b) => a <= b);
|
|
1688
|
+
helpers.set('and', (...args) => args.every(Boolean));
|
|
1689
|
+
helpers.set('or', (...args) => args.some(Boolean));
|
|
1690
|
+
helpers.set('not', (a) => !a);
|
|
1691
|
+
helpers.set('set', _set);
|
|
1692
|
+
helpers.set('increment', _inc);
|
|
1693
|
+
helpers.set('decrement', _dec);
|
|
1694
|
+
helpers.set('toggle', _toggle);
|
|
1695
|
+
helpers.set('if', _if);
|
|
1696
|
+
helpers.set('ifs', _ifs);
|
|
1697
|
+
helpers.set('switch', _switch);
|
|
1574
1698
|
|
|
1575
1699
|
// Default Operator Mappings
|
|
1576
1700
|
cDOM.operator('+', 'add');
|
|
@@ -1578,8 +1702,11 @@
|
|
|
1578
1702
|
cDOM.operator('*', 'multiply');
|
|
1579
1703
|
cDOM.operator('/', 'divide');
|
|
1580
1704
|
cDOM.operator('==', 'eq');
|
|
1705
|
+
cDOM.operator('!=', 'neq');
|
|
1581
1706
|
cDOM.operator('>', 'gt');
|
|
1582
1707
|
cDOM.operator('<', 'lt');
|
|
1708
|
+
cDOM.operator('>=', 'gte');
|
|
1709
|
+
cDOM.operator('<=', 'lte');
|
|
1583
1710
|
cDOM.operator('&&', 'and');
|
|
1584
1711
|
cDOM.operator('||', 'or');
|
|
1585
1712
|
cDOM.operator('!', 'not');
|
package/package.json
CHANGED
package/helpers/add.js
DELETED
package/helpers/and.js
DELETED
package/helpers/decrement.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Example: { onclick: { "=decrement": ["/counter/count", 1] } }
|
|
2
|
-
import set from './set.js';
|
|
3
|
-
const decrement = function (target, by = 1) {
|
|
4
|
-
const hasValue = target && (typeof target === 'object' || typeof target === 'function') && 'value' in target;
|
|
5
|
-
const current = hasValue ? target.value : 0;
|
|
6
|
-
const next = Number(current) - Number(by);
|
|
7
|
-
return set(target, next);
|
|
8
|
-
}
|
|
9
|
-
decrement.mutates = true;
|
|
10
|
-
export default decrement;
|
package/helpers/divide.js
DELETED
package/helpers/eq.js
DELETED
package/helpers/gt.js
DELETED
package/helpers/if.js
DELETED
package/helpers/ifs.js
DELETED
package/helpers/increment.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Example: { onclick: { "=increment": ["/counter/count", 1] } }
|
|
2
|
-
import set from './set.js';
|
|
3
|
-
const increment = function (target, by = 1) {
|
|
4
|
-
const hasValue = target && (typeof target === 'object' || typeof target === 'function') && 'value' in target;
|
|
5
|
-
const current = hasValue ? target.value : 0;
|
|
6
|
-
const next = Number(current) + Number(by);
|
|
7
|
-
return set(target, next);
|
|
8
|
-
}
|
|
9
|
-
increment.mutates = true;
|
|
10
|
-
export default increment;
|
package/helpers/lt.js
DELETED
package/helpers/multiply.js
DELETED
package/helpers/not.js
DELETED
package/helpers/or.js
DELETED
package/helpers/set.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Example: { onclick: { "=set": ["/app/title", "New Title"] } }
|
|
2
|
-
const set = function (target, val) {
|
|
3
|
-
if (target && typeof target === 'object' && 'value' in target) {
|
|
4
|
-
target.value = val;
|
|
5
|
-
} else if (target && typeof target === 'function' && 'value' in target) {
|
|
6
|
-
target.value = val;
|
|
7
|
-
} else if (target && typeof target === 'object' && val && typeof val === 'object') {
|
|
8
|
-
Object.assign(target, val);
|
|
9
|
-
}
|
|
10
|
-
return val;
|
|
11
|
-
}
|
|
12
|
-
set.mutates = true;
|
|
13
|
-
export default set;
|
package/helpers/subtract.js
DELETED
package/helpers/sum.js
DELETED
package/helpers/switch.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// Example: { p: { "=switch": [2, 1, "One", 2, "Two", "Default"] } }
|
|
2
|
-
export default function (expression, ...args) {
|
|
3
|
-
for (let i = 0; i < args.length - 1; i += 2) {
|
|
4
|
-
if (expression === args[i]) return args[i + 1];
|
|
5
|
-
}
|
|
6
|
-
return args.length % 2 === 1 ? args[args.length - 1] : undefined;
|
|
7
|
-
}
|
package/helpers/toggle.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// Example: { onclick: { "=toggle": ["/user/isActive"] } }
|
|
2
|
-
import set from './set.js';
|
|
3
|
-
const toggle = function (target) {
|
|
4
|
-
const hasValue = target && (typeof target === 'object' || typeof target === 'function') && 'value' in target;
|
|
5
|
-
const current = hasValue ? target.value : false;
|
|
6
|
-
return set(target, !current);
|
|
7
|
-
}
|
|
8
|
-
toggle.mutates = true;
|
|
9
|
-
export default toggle;
|