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 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 to insert into (default: `document.currentScript`)
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.
@@ -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://unpkg.com/expr-eval@2.0.2/dist/bundle.min.js"></script>
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
 
@@ -1,5 +1,5 @@
1
1
  <html>
2
- <script src="https://unpkg.com/expr-eval@2.0.2/dist/bundle.min.js"></script>
2
+ <script src="https://cdn.jsdelivr.net/npm/expr-eval/dist/bundle.min.js"></script>
3
3
  <script src="../index.js"></script>
4
4
 
5
5
  <body>
@@ -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://unpkg.com/expr-eval@2.0.2/dist/bundle.min.js"></script>
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
- const result = fn(...args);
613
- return result;
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) { return `[Math Error]`; }
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
- cdom = JSON.parse(cdom);
1097
+ cdomObj = JSON.parse(cdom);
1087
1098
  }
1088
- const dom = cdomToDOM(cdom, type === 'string', options?.unsafe, options?.context);
1099
+
1089
1100
  if (options) {
1090
1101
  let { target = script, location = 'outerHTML' } = options;
1091
- location = location.toLowerCase();
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 dom;
1126
+ return cdomToDOM(cdomObj, wasString);
1104
1127
  }
1105
1128
 
1106
1129
  // Standalone src/href handling
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdom",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Safe, reactive UIs based on JSON Pointer, XPath, JSON Schema",
5
5
  "keywords": [
6
6
  "JPRX",