cdom 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -2
- package/examples/dashboard.html +1 -1
- package/examples/scratch.html +1 -1
- package/examples/spreadsheet.html +1 -1
- package/index.js +31 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -498,14 +498,22 @@ Converts cDOM object to DOM and optionally inserts it.
|
|
|
498
498
|
**Parameters:**
|
|
499
499
|
- `object`: cDOM object or JSON string
|
|
500
500
|
- `options`: Optional configuration
|
|
501
|
-
- `target`: Element
|
|
501
|
+
- `target`: Element or CSS selector string (default: `document.currentScript`). If a selector matches multiple elements, the component will be instantiated for each.
|
|
502
502
|
- `location`: Where to insert - `'innerHTML'`, `'outerHTML'`, `'beforeend'`, etc.
|
|
503
503
|
- `unsafe`: Allow unsafe eval (default: `false`)
|
|
504
504
|
|
|
505
|
-
**Returns:** DOM element
|
|
505
|
+
**Returns:** The (first) created DOM element
|
|
506
506
|
|
|
507
507
|
If an options object is provided, the default location will be outerHTML on the current script, i.e. replace the script. If you do not want to replace anything and just want the reactive element, DO NOT pass in an options object.
|
|
508
508
|
|
|
509
|
+
```javascript
|
|
510
|
+
// Target a specific element by ID
|
|
511
|
+
cDOM({ h1: "Hello" }, { target: "#header" });
|
|
512
|
+
|
|
513
|
+
// Target all elements with a class
|
|
514
|
+
cDOM({ button: "Click Me" }, { target: ".action-buttons", location: "beforeend" });
|
|
515
|
+
```
|
|
516
|
+
|
|
509
517
|
### `cDOM.state(value, options)` / `cDOM.signal(value, options)`
|
|
510
518
|
|
|
511
519
|
Create reactive state or signals.
|
package/examples/dashboard.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>TechMonitor PRO | Safe & Reactive cDOM</title>
|
|
8
8
|
<!-- We still need expr-eval if cdom.js uses it, but we will avoid operator expressions -->
|
|
9
|
-
<script src="https://
|
|
9
|
+
<script src="https://cdn.jsdelivr.net/npm/expr-eval/dist/bundle.min.js"></script>
|
|
10
10
|
<script src="../index.js"></script>
|
|
11
11
|
|
|
12
12
|
|
package/examples/scratch.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>CryptoSheet | Reactive cDOM Spreadsheet</title>
|
|
8
|
-
<script src="https://
|
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/expr-eval/dist/bundle.min.js"></script>
|
|
9
9
|
<script src="../index.js"></script>
|
|
10
10
|
<link rel="stylesheet" href="spreadsheet.css">
|
|
11
11
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
package/index.js
CHANGED
|
@@ -609,8 +609,12 @@
|
|
|
609
609
|
args[i] = argVal;
|
|
610
610
|
}
|
|
611
611
|
}
|
|
612
|
-
|
|
613
|
-
|
|
612
|
+
try {
|
|
613
|
+
return fn(...args);
|
|
614
|
+
} catch (e) {
|
|
615
|
+
console.error(`[cDOM] Helper error in "${funcName}":`, e, { expression, contextNode: ctx });
|
|
616
|
+
return `_(${expression})`;
|
|
617
|
+
}
|
|
614
618
|
};
|
|
615
619
|
}
|
|
616
620
|
|
|
@@ -632,7 +636,10 @@
|
|
|
632
636
|
return id;
|
|
633
637
|
});
|
|
634
638
|
return mathParser.evaluate(processedExpr, scope);
|
|
635
|
-
} catch (e) {
|
|
639
|
+
} catch (e) {
|
|
640
|
+
console.error(`[cDOM] Math Error in "${expression}":`, e, { contextNode: ctx });
|
|
641
|
+
return `_(${expression})`;
|
|
642
|
+
}
|
|
636
643
|
};
|
|
637
644
|
}
|
|
638
645
|
|
|
@@ -774,6 +781,7 @@
|
|
|
774
781
|
|
|
775
782
|
return { type: 'value', value: elements.map(el => el.textContent || '').join(', ') };
|
|
776
783
|
} catch (e) {
|
|
784
|
+
console.error(`[cDOM] CSS Error: "${selector}"`, e, { contextNode });
|
|
777
785
|
return { type: 'value', value: `[CSS Error: ${selector}]` };
|
|
778
786
|
}
|
|
779
787
|
}
|
|
@@ -809,6 +817,7 @@
|
|
|
809
817
|
default: return { type: 'value', value: '' };
|
|
810
818
|
}
|
|
811
819
|
} catch (e) {
|
|
820
|
+
console.error(`[cDOM] XPath Error: "${expression}"`, e, { contextNode });
|
|
812
821
|
return { type: 'value', value: `[XPath Error: ${expression}]` };
|
|
813
822
|
}
|
|
814
823
|
}
|
|
@@ -945,7 +954,7 @@
|
|
|
945
954
|
continue;
|
|
946
955
|
} else if (key.startsWith('on')) {
|
|
947
956
|
if (typeof val === "string") {
|
|
948
|
-
if (val.startsWith('_(') && val.endsWith(')')) {
|
|
957
|
+
if ((val.startsWith('_(') || val.startsWith('=(')) && val.endsWith(')')) {
|
|
949
958
|
const expr = val.substring(2, val.length - 1);
|
|
950
959
|
el[key] = (event) => evaluateStateExpression(expr, el, event);
|
|
951
960
|
} else if (!wasString || unsafe) {
|
|
@@ -1082,13 +1091,26 @@
|
|
|
1082
1091
|
// call with options to insert into the DOM
|
|
1083
1092
|
const cDOM = (cdom, options, script = document.currentScript) => {
|
|
1084
1093
|
const type = typeof cdom;
|
|
1094
|
+
const wasString = type === 'string' || (options && options._wasString);
|
|
1095
|
+
let cdomObj = cdom;
|
|
1085
1096
|
if (type === 'string') {
|
|
1086
|
-
|
|
1097
|
+
cdomObj = JSON.parse(cdom);
|
|
1087
1098
|
}
|
|
1088
|
-
|
|
1099
|
+
|
|
1089
1100
|
if (options) {
|
|
1090
1101
|
let { target = script, location = 'outerHTML' } = options;
|
|
1091
|
-
|
|
1102
|
+
if (typeof target === 'string') {
|
|
1103
|
+
const targets = Array.from(document.querySelectorAll(target));
|
|
1104
|
+
let firstRes = null;
|
|
1105
|
+
for (let i = 0; i < targets.length; i++) {
|
|
1106
|
+
const res = cDOM(cdomObj, { ...options, target: targets[i], _wasString: wasString }, script);
|
|
1107
|
+
if (i === 0) firstRes = res;
|
|
1108
|
+
}
|
|
1109
|
+
return firstRes;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
const dom = cdomToDOM(cdomObj, wasString, options.unsafe, options.context);
|
|
1113
|
+
location = (location || 'outerHTML').toLowerCase();
|
|
1092
1114
|
if (location === 'outerhtml') target.replaceWith(dom);
|
|
1093
1115
|
else if (location === 'innerhtml') { target.replaceChildren(dom); }
|
|
1094
1116
|
else if (location === 'beforebegin') { target.insertAdjacentElement('beforebegin', dom); }
|
|
@@ -1099,8 +1121,9 @@
|
|
|
1099
1121
|
if (!target.shadowRoot) target.attachShadow({ mode: 'open' });
|
|
1100
1122
|
target.shadowRoot.replaceChildren(dom);
|
|
1101
1123
|
}
|
|
1124
|
+
return dom;
|
|
1102
1125
|
}
|
|
1103
|
-
return
|
|
1126
|
+
return cdomToDOM(cdomObj, wasString);
|
|
1104
1127
|
}
|
|
1105
1128
|
|
|
1106
1129
|
// Standalone src/href handling
|