@syntrologie/adapt-content 2.16.0 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/dist/runtime.js +425 -366
  2. package/dist/runtime.js.map +7 -0
  3. package/dist/schema.d.ts +55 -16
  4. package/dist/schema.d.ts.map +1 -1
  5. package/dist/schema.js +316 -62
  6. package/dist/schema.js.map +7 -0
  7. package/package.json +2 -20
  8. package/dist/cdn.d.ts +0 -35
  9. package/dist/cdn.d.ts.map +0 -1
  10. package/dist/cdn.js +0 -39
  11. package/dist/components/AnchorPicker.d.ts +0 -8
  12. package/dist/components/AnchorPicker.d.ts.map +0 -1
  13. package/dist/components/AnchorPicker.js +0 -6
  14. package/dist/content-editor-state.d.ts +0 -45
  15. package/dist/content-editor-state.d.ts.map +0 -1
  16. package/dist/content-editor-state.js +0 -123
  17. package/dist/content-editor-ui.d.ts +0 -26
  18. package/dist/content-editor-ui.d.ts.map +0 -1
  19. package/dist/content-editor-ui.js +0 -291
  20. package/dist/editor.d.ts +0 -9
  21. package/dist/editor.d.ts.map +0 -1
  22. package/dist/editor.js +0 -8
  23. package/dist/reconciliation-guard.js +0 -80
  24. package/dist/sanitizer.js +0 -95
  25. package/dist/summarize.js +0 -88
  26. package/dist/types.js +0 -7
  27. package/dist/utils/selectorGenerator.d.ts +0 -6
  28. package/dist/utils/selectorGenerator.d.ts.map +0 -1
  29. package/dist/utils/selectorGenerator.js +0 -4
  30. package/node_modules/@syntrologie/shared-editor-ui/dist/cn.d.ts +0 -2
  31. package/node_modules/@syntrologie/shared-editor-ui/dist/cn.d.ts.map +0 -1
  32. package/node_modules/@syntrologie/shared-editor-ui/dist/cn.js +0 -3
  33. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.d.ts +0 -34
  34. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.d.ts.map +0 -1
  35. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPicker.js +0 -161
  36. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPickerLit.d.ts +0 -84
  37. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPickerLit.d.ts.map +0 -1
  38. package/node_modules/@syntrologie/shared-editor-ui/dist/components/AnchorPickerLit.js +0 -323
  39. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.d.ts +0 -7
  40. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.d.ts.map +0 -1
  41. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggle.js +0 -9
  42. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggleLit.d.ts +0 -25
  43. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggleLit.d.ts.map +0 -1
  44. package/node_modules/@syntrologie/shared-editor-ui/dist/components/BeforeAfterToggleLit.js +0 -55
  45. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.d.ts +0 -23
  46. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.d.ts.map +0 -1
  47. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLine.js +0 -40
  48. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLineLit.d.ts +0 -33
  49. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLineLit.d.ts.map +0 -1
  50. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ConditionStatusLineLit.js +0 -118
  51. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.d.ts +0 -7
  52. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.d.ts.map +0 -1
  53. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadge.js +0 -22
  54. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadgeLit.d.ts +0 -32
  55. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadgeLit.d.ts.map +0 -1
  56. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DetectionBadgeLit.js +0 -68
  57. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.d.ts +0 -8
  58. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.d.ts.map +0 -1
  59. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSection.js +0 -9
  60. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSectionLit.d.ts +0 -34
  61. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSectionLit.d.ts.map +0 -1
  62. package/node_modules/@syntrologie/shared-editor-ui/dist/components/DismissedSectionLit.js +0 -57
  63. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.d.ts +0 -7
  64. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.d.ts.map +0 -1
  65. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButton.js +0 -4
  66. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButtonLit.d.ts +0 -13
  67. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButtonLit.d.ts.map +0 -1
  68. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditBackButtonLit.js +0 -31
  69. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.d.ts +0 -7
  70. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.d.ts.map +0 -1
  71. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBody.js +0 -4
  72. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBodyLit.d.ts +0 -7
  73. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBodyLit.d.ts.map +0 -1
  74. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorBodyLit.js +0 -15
  75. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.d.ts +0 -13
  76. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.d.ts.map +0 -1
  77. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCard.js +0 -15
  78. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCardLit.d.ts +0 -36
  79. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCardLit.d.ts.map +0 -1
  80. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorCardLit.js +0 -102
  81. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.d.ts +0 -7
  82. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.d.ts.map +0 -1
  83. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooter.js +0 -4
  84. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooterLit.d.ts +0 -20
  85. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooterLit.d.ts.map +0 -1
  86. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorFooterLit.js +0 -48
  87. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.d.ts +0 -9
  88. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.d.ts.map +0 -1
  89. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeader.js +0 -4
  90. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeaderLit.d.ts +0 -16
  91. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeaderLit.d.ts.map +0 -1
  92. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorHeaderLit.js +0 -25
  93. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.d.ts +0 -8
  94. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.d.ts.map +0 -1
  95. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInput.js +0 -8
  96. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInputLit.d.ts +0 -66
  97. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInputLit.d.ts.map +0 -1
  98. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorInputLit.js +0 -87
  99. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.d.ts +0 -7
  100. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.d.ts.map +0 -1
  101. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayout.js +0 -4
  102. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayoutLit.d.ts +0 -7
  103. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayoutLit.d.ts.map +0 -1
  104. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorLayoutLit.js +0 -15
  105. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.d.ts +0 -25
  106. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.d.ts.map +0 -1
  107. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShell.js +0 -390
  108. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShellLit.d.ts +0 -66
  109. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShellLit.d.ts.map +0 -1
  110. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorPanelShellLit.js +0 -528
  111. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.d.ts +0 -8
  112. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.d.ts.map +0 -1
  113. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelect.js +0 -8
  114. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelectLit.d.ts +0 -41
  115. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelectLit.d.ts.map +0 -1
  116. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorSelectLit.js +0 -63
  117. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.d.ts +0 -8
  118. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.d.ts.map +0 -1
  119. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextarea.js +0 -17
  120. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextareaLit.d.ts +0 -55
  121. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextareaLit.d.ts.map +0 -1
  122. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EditorTextareaLit.js +0 -92
  123. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.d.ts +0 -32
  124. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.d.ts.map +0 -1
  125. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlight.js +0 -85
  126. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlightLit.d.ts +0 -90
  127. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlightLit.d.ts.map +0 -1
  128. package/node_modules/@syntrologie/shared-editor-ui/dist/components/ElementHighlightLit.js +0 -242
  129. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.d.ts +0 -6
  130. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.d.ts.map +0 -1
  131. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyState.js +0 -4
  132. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyStateLit.d.ts +0 -12
  133. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyStateLit.d.ts.map +0 -1
  134. package/node_modules/@syntrologie/shared-editor-ui/dist/components/EmptyStateLit.js +0 -21
  135. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.d.ts +0 -8
  136. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.d.ts.map +0 -1
  137. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeader.js +0 -5
  138. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeaderLit.d.ts +0 -21
  139. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeaderLit.d.ts.map +0 -1
  140. package/node_modules/@syntrologie/shared-editor-ui/dist/components/GroupHeaderLit.js +0 -33
  141. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.d.ts +0 -12
  142. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.d.ts.map +0 -1
  143. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourney.js +0 -40
  144. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourneyLit.d.ts +0 -28
  145. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourneyLit.d.ts.map +0 -1
  146. package/node_modules/@syntrologie/shared-editor-ui/dist/components/TriggerJourneyLit.js +0 -121
  147. package/node_modules/@syntrologie/shared-editor-ui/dist/controllers/PanelShellController.d.ts +0 -110
  148. package/node_modules/@syntrologie/shared-editor-ui/dist/controllers/PanelShellController.d.ts.map +0 -1
  149. package/node_modules/@syntrologie/shared-editor-ui/dist/controllers/PanelShellController.js +0 -481
  150. package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.d.ts +0 -26
  151. package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.d.ts.map +0 -1
  152. package/node_modules/@syntrologie/shared-editor-ui/dist/formatConditionLabel.js +0 -202
  153. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.d.ts +0 -8
  154. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.d.ts.map +0 -1
  155. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useElementRect.js +0 -46
  156. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.d.ts +0 -24
  157. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.d.ts.map +0 -1
  158. package/node_modules/@syntrologie/shared-editor-ui/dist/hooks/useTriggerWhenStatus.js +0 -86
  159. package/node_modules/@syntrologie/shared-editor-ui/dist/index.d.ts +0 -36
  160. package/node_modules/@syntrologie/shared-editor-ui/dist/index.d.ts.map +0 -1
  161. package/node_modules/@syntrologie/shared-editor-ui/dist/index.js +0 -26
  162. package/node_modules/@syntrologie/shared-editor-ui/dist/lit-elements.d.ts +0 -15
  163. package/node_modules/@syntrologie/shared-editor-ui/dist/lit-elements.d.ts.map +0 -1
  164. package/node_modules/@syntrologie/shared-editor-ui/dist/lit-elements.js +0 -14
  165. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.d.ts +0 -33
  166. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.d.ts.map +0 -1
  167. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/elementChainRecommender.js +0 -68
  168. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.d.ts +0 -22
  169. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.d.ts.map +0 -1
  170. package/node_modules/@syntrologie/shared-editor-ui/dist/utils/selectorGenerator.js +0 -143
  171. package/node_modules/@syntrologie/shared-editor-ui/package.json +0 -55
package/dist/runtime.js CHANGED
@@ -1,390 +1,449 @@
1
- /**
2
- * Adaptive Content - Runtime Module
3
- *
4
- * DOM manipulation actions: insertHtml, setText, setAttr, addClass, removeClass, setStyle.
5
- * These follow the hostPatcher snapshot pattern for safe reversibility.
6
- */
7
- import { guardAgainstReconciliation } from './reconciliation-guard';
8
- import { sanitizeHtml } from './sanitizer';
9
- // ============================================================================
10
- // Executors
11
- // ============================================================================
12
- /**
13
- * Execute an insertHtml action
14
- */
15
- export const executeInsertHtml = async (action, context) => {
16
- let anchorEl = context.resolveAnchor(action.anchorId);
17
- if (!anchorEl && context.waitForAnchor) {
18
- anchorEl = await context.waitForAnchor(action.anchorId, 3000);
1
+ // src/reconciliation-guard.ts
2
+ function guardAgainstReconciliation(container, anchor, reinsertFn, opts) {
3
+ const maxRetries = opts?.maxRetries ?? 3;
4
+ const debounceMs = opts?.debounceMs ?? 50;
5
+ const observeTarget = container.parentElement ?? anchor.parentElement;
6
+ if (!observeTarget) return () => {
7
+ };
8
+ let retries = 0;
9
+ let debounceTimer = null;
10
+ let disconnected = false;
11
+ const observer = new MutationObserver((mutations) => {
12
+ if (disconnected) return;
13
+ for (const mutation of mutations) {
14
+ for (const removed of mutation.removedNodes) {
15
+ if (removed !== container) continue;
16
+ if (retries >= maxRetries) {
17
+ observer.disconnect();
18
+ disconnected = true;
19
+ return;
20
+ }
21
+ if (debounceTimer) clearTimeout(debounceTimer);
22
+ debounceTimer = setTimeout(() => {
23
+ if (disconnected) return;
24
+ if (!anchor.isConnected) {
25
+ observer.disconnect();
26
+ disconnected = true;
27
+ return;
28
+ }
29
+ retries++;
30
+ try {
31
+ reinsertFn();
32
+ } catch {
33
+ observer.disconnect();
34
+ disconnected = true;
35
+ }
36
+ }, debounceMs);
37
+ return;
38
+ }
19
39
  }
20
- if (!anchorEl) {
21
- console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
22
- return { cleanup: () => { } };
40
+ });
41
+ observer.observe(observeTarget, { childList: true, subtree: true });
42
+ return () => {
43
+ disconnected = true;
44
+ observer.disconnect();
45
+ if (debounceTimer) clearTimeout(debounceTimer);
46
+ };
47
+ }
48
+
49
+ // src/sanitizer.ts
50
+ var ALLOWED_TAGS = /* @__PURE__ */ new Set([
51
+ "b",
52
+ "strong",
53
+ "i",
54
+ "em",
55
+ "u",
56
+ "span",
57
+ "div",
58
+ "p",
59
+ "br",
60
+ "ul",
61
+ "ol",
62
+ "li",
63
+ "code",
64
+ "pre",
65
+ "small",
66
+ "sup",
67
+ "sub",
68
+ "a",
69
+ "button",
70
+ // SVG elements (for inline Lucide icons in config HTML)
71
+ "svg",
72
+ "path",
73
+ "circle",
74
+ "line",
75
+ "polyline",
76
+ "polygon",
77
+ "rect",
78
+ "g"
79
+ ]);
80
+ function sanitizeHtml(html) {
81
+ const hasNative = typeof window.Sanitizer === "function";
82
+ if (hasNative) {
83
+ try {
84
+ const s = new window.Sanitizer({});
85
+ const frag = s.sanitizeToFragment(html);
86
+ const div = document.createElement("div");
87
+ div.append(frag);
88
+ return div.innerHTML;
89
+ } catch {
23
90
  }
24
- // Sanitize HTML content using context utility
25
- const sanitizedHtml = sanitizeHtml(action.html);
26
- // Dedup: if a container for this action already exists, remove it first.
27
- // Uses the action label as a stable identifier across re-applications.
28
- // Check both inside the anchor (prepend/append) and in the parent (before/after).
29
- const dedupAttr = 'data-syntro-insert-label';
30
- const label = action.label;
31
- if (label) {
32
- const escapedLabel = CSS.escape(label);
33
- const searchRoot = anchorEl.parentElement ?? anchorEl;
34
- const existing = searchRoot.querySelector(`[${dedupAttr}="${escapedLabel}"]`);
35
- if (existing)
36
- existing.remove();
91
+ }
92
+ const tpl = document.createElement("template");
93
+ tpl.innerHTML = html;
94
+ const root = tpl.content;
95
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, null);
96
+ const toRemove = [];
97
+ while (walker.nextNode()) {
98
+ const el = walker.currentNode;
99
+ const tag = el.tagName.toLowerCase();
100
+ if (!ALLOWED_TAGS.has(tag)) {
101
+ toRemove.push(el);
102
+ continue;
37
103
  }
38
- // Create container for inserted content
39
- const container = document.createElement('div');
40
- container.setAttribute('data-syntro-action-id', context.generateId());
41
- if (label)
42
- container.setAttribute(dedupAttr, label);
43
- container.innerHTML = sanitizedHtml;
44
- // Keep track of original state for replace position
45
- let originalContent = null;
46
- switch (action.position) {
47
- case 'before':
48
- anchorEl.insertAdjacentElement('beforebegin', container);
49
- break;
50
- case 'after':
51
- anchorEl.insertAdjacentElement('afterend', container);
52
- break;
53
- case 'prepend':
54
- anchorEl.insertBefore(container, anchorEl.firstChild);
55
- break;
56
- case 'append':
57
- anchorEl.appendChild(container);
58
- break;
59
- case 'replace':
60
- originalContent = anchorEl.innerHTML;
61
- anchorEl.replaceWith(container);
62
- break;
104
+ for (const attr of Array.from(el.attributes)) {
105
+ const name = attr.name.toLowerCase();
106
+ const value = attr.value.trim().toLowerCase();
107
+ const isEvent = name.startsWith("on");
108
+ const isUrlAttr = name === "href" || name === "src" || name === "formaction";
109
+ const isDangerousUrl = isUrlAttr && (value.startsWith("javascript:") || value.startsWith("vbscript:") || value.startsWith("data:text/html"));
110
+ if (isEvent || isDangerousUrl) {
111
+ el.removeAttribute(attr.name);
112
+ }
63
113
  }
64
- // Deep-link click handler — opens canvas + publishes deep-link event
65
- let deepLinkHandler = null;
66
- if (action.deepLink) {
67
- const { tileId, itemId } = action.deepLink;
68
- deepLinkHandler = () => {
69
- const handle = window.SynOS?.handle;
70
- if (handle) {
71
- handle.open();
72
- handle.runtime?.events?.publish('notification.deep_link', { tileId, itemId });
73
- }
74
- };
75
- container.style.cursor = 'pointer';
76
- container.addEventListener('click', deepLinkHandler);
114
+ }
115
+ const svgs = Array.from(root.querySelectorAll("svg"));
116
+ for (const svg of svgs) {
117
+ if (toRemove.some((el) => svg.contains(el) && el.tagName.toLowerCase() === "script")) {
118
+ toRemove.push(svg);
77
119
  }
78
- context.publishEvent('action.applied', {
79
- id: context.generateId(),
80
- kind: 'content:insertHtml',
81
- anchorId: action.anchorId,
82
- position: action.position,
83
- });
84
- // Guard against React reconciliation removing our container.
85
- // The reinsert function re-applies the same insertion strategy.
86
- const reinsertFn = () => {
87
- switch (action.position) {
88
- case 'before':
89
- anchorEl.insertAdjacentElement('beforebegin', container);
90
- break;
91
- case 'after':
92
- anchorEl.insertAdjacentElement('afterend', container);
93
- break;
94
- case 'prepend':
95
- anchorEl.insertBefore(container, anchorEl.firstChild);
96
- break;
97
- case 'append':
98
- anchorEl.appendChild(container);
99
- break;
100
- case 'replace':
101
- // Cannot re-insert for replace — anchor was already replaced
102
- break;
103
- }
104
- };
105
- const guardCleanup = guardAgainstReconciliation(container, anchorEl, reinsertFn);
106
- return {
107
- cleanup: () => {
108
- if (deepLinkHandler) {
109
- container.removeEventListener('click', deepLinkHandler);
110
- }
111
- guardCleanup();
112
- // Skip DOM mutations if nodes are already detached (SPA navigation)
113
- if (!container.isConnected)
114
- return;
115
- try {
116
- if (action.position === 'replace' && originalContent !== null) {
117
- // Restore original element
118
- const restoredEl = document.createElement(anchorEl.tagName);
119
- restoredEl.innerHTML = originalContent;
120
- // Copy attributes
121
- Array.from(anchorEl.attributes).forEach((attr) => {
122
- restoredEl.setAttribute(attr.name, attr.value);
123
- });
124
- container.replaceWith(restoredEl);
125
- }
126
- else {
127
- container.remove();
128
- }
129
- }
130
- catch {
131
- // DOM nodes already removed by host framework — safe to ignore
132
- }
133
- },
134
- updateFn: (changes) => {
135
- if ('html' in changes && typeof changes.html === 'string') {
136
- container.innerHTML = sanitizeHtml(changes.html);
137
- }
138
- },
139
- };
140
- };
141
- /**
142
- * Walk the DOM to find the deepest descendant that uniquely carries
143
- * text content. Avoids destroying sibling elements (icons, images)
144
- * when setting text on a container like a button.
145
- */
146
- function findTextTarget(el) {
147
- if (el.children.length === 0)
148
- return el;
149
- const textChildren = Array.from(el.children).filter((child) => child.textContent?.trim());
150
- if (textChildren.length === 1) {
151
- const child = textChildren[0];
152
- if (child.textContent?.trim() === el.textContent?.trim()) {
153
- return findTextTarget(child);
154
- }
120
+ }
121
+ for (const el of toRemove) {
122
+ while (el.firstChild) {
123
+ el.parentNode?.insertBefore(el.firstChild, el);
155
124
  }
156
- return el;
125
+ el.remove();
126
+ }
127
+ return tpl.innerHTML;
157
128
  }
158
- /**
159
- * Execute a setText action
160
- */
161
- export const executeSetText = async (action, context) => {
162
- let anchorEl = context.resolveAnchor(action.anchorId);
163
- if (!anchorEl && context.waitForAnchor) {
164
- anchorEl = await context.waitForAnchor(action.anchorId, 3000);
165
- }
166
- if (!anchorEl) {
167
- console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
168
- return { cleanup: () => { } };
169
- }
170
- const textTarget = findTextTarget(anchorEl);
171
- // Snapshot original text
172
- const originalText = textTarget.textContent ?? '';
173
- // Set new text
174
- textTarget.textContent = action.text;
175
- context.publishEvent('action.applied', {
176
- id: context.generateId(),
177
- kind: 'content:setText',
178
- anchorId: action.anchorId,
179
- });
180
- return {
181
- cleanup: () => {
182
- if (!anchorEl.isConnected)
183
- return;
184
- textTarget.textContent = originalText;
185
- },
186
- updateFn: (changes) => {
187
- if ('text' in changes && typeof changes.text === 'string') {
188
- textTarget.textContent = changes.text;
189
- }
190
- },
129
+
130
+ // src/runtime.ts
131
+ var executeInsertHtml = async (action, context) => {
132
+ let anchorEl = context.resolveAnchor(action.anchorId);
133
+ if (!anchorEl && context.waitForAnchor) {
134
+ anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
135
+ }
136
+ if (!anchorEl) {
137
+ console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
138
+ return { cleanup: () => {
139
+ } };
140
+ }
141
+ const sanitizedHtml = sanitizeHtml(action.html);
142
+ const dedupAttr = "data-syntro-insert-label";
143
+ const label = action.label;
144
+ if (label) {
145
+ const escapedLabel = CSS.escape(label);
146
+ const searchRoot = anchorEl.parentElement ?? anchorEl;
147
+ const existing = searchRoot.querySelector(`[${dedupAttr}="${escapedLabel}"]`);
148
+ if (existing) existing.remove();
149
+ }
150
+ const container = document.createElement("div");
151
+ container.setAttribute("data-syntro-action-id", context.generateId());
152
+ if (label) container.setAttribute(dedupAttr, label);
153
+ container.innerHTML = sanitizedHtml;
154
+ let originalContent = null;
155
+ switch (action.position) {
156
+ case "before":
157
+ anchorEl.insertAdjacentElement("beforebegin", container);
158
+ break;
159
+ case "after":
160
+ anchorEl.insertAdjacentElement("afterend", container);
161
+ break;
162
+ case "prepend":
163
+ anchorEl.insertBefore(container, anchorEl.firstChild);
164
+ break;
165
+ case "append":
166
+ anchorEl.appendChild(container);
167
+ break;
168
+ case "replace":
169
+ originalContent = anchorEl.innerHTML;
170
+ anchorEl.replaceWith(container);
171
+ break;
172
+ }
173
+ let deepLinkHandler = null;
174
+ if (action.deepLink) {
175
+ const { tileId, itemId } = action.deepLink;
176
+ deepLinkHandler = () => {
177
+ const handle = window.SynOS?.handle;
178
+ if (handle) {
179
+ handle.open();
180
+ handle.runtime?.events?.publish("notification.deep_link", { tileId, itemId });
181
+ }
191
182
  };
192
- };
193
- /**
194
- * Execute a setAttr action
195
- */
196
- export const executeSetAttr = async (action, context) => {
197
- let anchorEl = context.resolveAnchor(action.anchorId);
198
- if (!anchorEl && context.waitForAnchor) {
199
- anchorEl = await context.waitForAnchor(action.anchorId, 3000);
200
- }
201
- if (!anchorEl) {
202
- console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
203
- return { cleanup: () => { } };
204
- }
205
- // Block dangerous attributes (case-insensitive)
206
- const lowerAttr = action.attr.toLowerCase();
207
- if (lowerAttr.startsWith('on')) {
208
- throw new Error(`Dangerous attribute not allowed: ${action.attr}`);
183
+ container.style.cursor = "pointer";
184
+ container.addEventListener("click", deepLinkHandler);
185
+ }
186
+ context.publishEvent("action.applied", {
187
+ id: context.generateId(),
188
+ kind: "content:insertHtml",
189
+ anchorId: action.anchorId,
190
+ position: action.position
191
+ });
192
+ const reinsertFn = () => {
193
+ switch (action.position) {
194
+ case "before":
195
+ anchorEl.insertAdjacentElement("beforebegin", container);
196
+ break;
197
+ case "after":
198
+ anchorEl.insertAdjacentElement("afterend", container);
199
+ break;
200
+ case "prepend":
201
+ anchorEl.insertBefore(container, anchorEl.firstChild);
202
+ break;
203
+ case "append":
204
+ anchorEl.appendChild(container);
205
+ break;
206
+ case "replace":
207
+ break;
209
208
  }
210
- // Block dangerous URIs in URL-bearing attributes
211
- const isUrlAttr = lowerAttr === 'href' || lowerAttr === 'src' || lowerAttr === 'formaction';
212
- if (isUrlAttr) {
213
- const lowerValue = action.value.trim().toLowerCase();
214
- if (lowerValue.startsWith('javascript:') ||
215
- lowerValue.startsWith('vbscript:') ||
216
- lowerValue.startsWith('data:text/html')) {
217
- throw new Error(`Dangerous URL not allowed in ${action.attr}: ${action.value}`);
209
+ };
210
+ const guardCleanup = guardAgainstReconciliation(container, anchorEl, reinsertFn);
211
+ return {
212
+ cleanup: () => {
213
+ if (deepLinkHandler) {
214
+ container.removeEventListener("click", deepLinkHandler);
215
+ }
216
+ guardCleanup();
217
+ if (!container.isConnected) return;
218
+ try {
219
+ if (action.position === "replace" && originalContent !== null) {
220
+ const restoredEl = document.createElement(anchorEl.tagName);
221
+ restoredEl.innerHTML = originalContent;
222
+ Array.from(anchorEl.attributes).forEach((attr) => {
223
+ restoredEl.setAttribute(attr.name, attr.value);
224
+ });
225
+ container.replaceWith(restoredEl);
226
+ } else {
227
+ container.remove();
218
228
  }
229
+ } catch {
230
+ }
231
+ },
232
+ updateFn: (changes) => {
233
+ if ("html" in changes && typeof changes.html === "string") {
234
+ container.innerHTML = sanitizeHtml(changes.html);
235
+ }
219
236
  }
220
- // Snapshot original attribute value
221
- const originalValue = anchorEl.getAttribute(action.attr);
222
- const hadAttribute = anchorEl.hasAttribute(action.attr);
223
- // Set new attribute
224
- anchorEl.setAttribute(action.attr, action.value);
225
- context.publishEvent('action.applied', {
226
- id: context.generateId(),
227
- kind: 'content:setAttr',
228
- anchorId: action.anchorId,
229
- attr: action.attr,
230
- });
231
- return {
232
- cleanup: () => {
233
- if (!anchorEl.isConnected)
234
- return;
235
- if (hadAttribute && originalValue !== null) {
236
- anchorEl.setAttribute(action.attr, originalValue);
237
- }
238
- else {
239
- anchorEl.removeAttribute(action.attr);
240
- }
241
- },
242
- updateFn: (changes) => {
243
- if ('value' in changes && typeof changes.value === 'string') {
244
- anchorEl.setAttribute(action.attr, changes.value);
245
- }
246
- },
247
- };
237
+ };
248
238
  };
249
- /**
250
- * Execute an addClass action
251
- */
252
- export const executeAddClass = async (action, context) => {
253
- let anchorEl = context.resolveAnchor(action.anchorId);
254
- if (!anchorEl && context.waitForAnchor) {
255
- anchorEl = await context.waitForAnchor(action.anchorId, 3000);
239
+ function findTextTarget(el) {
240
+ if (el.children.length === 0) return el;
241
+ const textChildren = Array.from(el.children).filter((child) => child.textContent?.trim());
242
+ if (textChildren.length === 1) {
243
+ const child = textChildren[0];
244
+ if (child.textContent?.trim() === el.textContent?.trim()) {
245
+ return findTextTarget(child);
256
246
  }
257
- if (!anchorEl) {
258
- console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
259
- return { cleanup: () => { } };
247
+ }
248
+ return el;
249
+ }
250
+ var executeSetText = async (action, context) => {
251
+ let anchorEl = context.resolveAnchor(action.anchorId);
252
+ if (!anchorEl && context.waitForAnchor) {
253
+ anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
254
+ }
255
+ if (!anchorEl) {
256
+ console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
257
+ return { cleanup: () => {
258
+ } };
259
+ }
260
+ const textTarget = findTextTarget(anchorEl);
261
+ const originalText = textTarget.textContent ?? "";
262
+ textTarget.textContent = action.text;
263
+ context.publishEvent("action.applied", {
264
+ id: context.generateId(),
265
+ kind: "content:setText",
266
+ anchorId: action.anchorId
267
+ });
268
+ return {
269
+ cleanup: () => {
270
+ if (!anchorEl.isConnected) return;
271
+ textTarget.textContent = originalText;
272
+ },
273
+ updateFn: (changes) => {
274
+ if ("text" in changes && typeof changes.text === "string") {
275
+ textTarget.textContent = changes.text;
276
+ }
260
277
  }
261
- // Check if class was already present
262
- const hadClass = anchorEl.classList.contains(action.className);
263
- // Add class
264
- anchorEl.classList.add(action.className);
265
- context.publishEvent('action.applied', {
266
- id: context.generateId(),
267
- kind: 'content:addClass',
268
- anchorId: action.anchorId,
269
- className: action.className,
270
- });
271
- return {
272
- cleanup: () => {
273
- if (!anchorEl.isConnected)
274
- return;
275
- // Only remove if we added it
276
- if (!hadClass) {
277
- anchorEl.classList.remove(action.className);
278
- }
279
- },
280
- };
278
+ };
281
279
  };
282
- /**
283
- * Execute a removeClass action
284
- */
285
- export const executeRemoveClass = async (action, context) => {
286
- let anchorEl = context.resolveAnchor(action.anchorId);
287
- if (!anchorEl && context.waitForAnchor) {
288
- anchorEl = await context.waitForAnchor(action.anchorId, 3000);
280
+ var executeSetAttr = async (action, context) => {
281
+ let anchorEl = context.resolveAnchor(action.anchorId);
282
+ if (!anchorEl && context.waitForAnchor) {
283
+ anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
284
+ }
285
+ if (!anchorEl) {
286
+ console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
287
+ return { cleanup: () => {
288
+ } };
289
+ }
290
+ const lowerAttr = action.attr.toLowerCase();
291
+ if (lowerAttr.startsWith("on")) {
292
+ throw new Error(`Dangerous attribute not allowed: ${action.attr}`);
293
+ }
294
+ const isUrlAttr = lowerAttr === "href" || lowerAttr === "src" || lowerAttr === "formaction";
295
+ if (isUrlAttr) {
296
+ const lowerValue = action.value.trim().toLowerCase();
297
+ if (lowerValue.startsWith("javascript:") || lowerValue.startsWith("vbscript:") || lowerValue.startsWith("data:text/html")) {
298
+ throw new Error(`Dangerous URL not allowed in ${action.attr}: ${action.value}`);
289
299
  }
290
- if (!anchorEl) {
291
- console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
292
- return { cleanup: () => { } };
300
+ }
301
+ const originalValue = anchorEl.getAttribute(action.attr);
302
+ const hadAttribute = anchorEl.hasAttribute(action.attr);
303
+ anchorEl.setAttribute(action.attr, action.value);
304
+ context.publishEvent("action.applied", {
305
+ id: context.generateId(),
306
+ kind: "content:setAttr",
307
+ anchorId: action.anchorId,
308
+ attr: action.attr
309
+ });
310
+ return {
311
+ cleanup: () => {
312
+ if (!anchorEl.isConnected) return;
313
+ if (hadAttribute && originalValue !== null) {
314
+ anchorEl.setAttribute(action.attr, originalValue);
315
+ } else {
316
+ anchorEl.removeAttribute(action.attr);
317
+ }
318
+ },
319
+ updateFn: (changes) => {
320
+ if ("value" in changes && typeof changes.value === "string") {
321
+ anchorEl.setAttribute(action.attr, changes.value);
322
+ }
293
323
  }
294
- // Check if class was present
295
- const hadClass = anchorEl.classList.contains(action.className);
296
- // Remove class
297
- anchorEl.classList.remove(action.className);
298
- context.publishEvent('action.applied', {
299
- id: context.generateId(),
300
- kind: 'content:removeClass',
301
- anchorId: action.anchorId,
302
- className: action.className,
303
- });
304
- return {
305
- cleanup: () => {
306
- if (!anchorEl.isConnected)
307
- return;
308
- // Only re-add if we removed it
309
- if (hadClass) {
310
- anchorEl.classList.add(action.className);
311
- }
312
- },
313
- };
324
+ };
314
325
  };
315
- /**
316
- * Execute a setStyle action
317
- */
318
- export const executeSetStyle = async (action, context) => {
319
- let anchorEl = context.resolveAnchor(action.anchorId);
320
- if (!anchorEl && context.waitForAnchor) {
321
- anchorEl = await context.waitForAnchor(action.anchorId, 3000);
322
- }
323
- if (!anchorEl) {
324
- console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
325
- return { cleanup: () => { } };
326
+ var executeAddClass = async (action, context) => {
327
+ let anchorEl = context.resolveAnchor(action.anchorId);
328
+ if (!anchorEl && context.waitForAnchor) {
329
+ anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
330
+ }
331
+ if (!anchorEl) {
332
+ console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
333
+ return { cleanup: () => {
334
+ } };
335
+ }
336
+ const hadClass = anchorEl.classList.contains(action.className);
337
+ anchorEl.classList.add(action.className);
338
+ context.publishEvent("action.applied", {
339
+ id: context.generateId(),
340
+ kind: "content:addClass",
341
+ anchorId: action.anchorId,
342
+ className: action.className
343
+ });
344
+ return {
345
+ cleanup: () => {
346
+ if (!anchorEl.isConnected) return;
347
+ if (!hadClass) {
348
+ anchorEl.classList.remove(action.className);
349
+ }
326
350
  }
327
- // Snapshot original styles
328
- const originalStyles = new Map();
329
- for (const prop of Object.keys(action.styles)) {
330
- const current = anchorEl.style.getPropertyValue(prop);
331
- originalStyles.set(prop, current);
351
+ };
352
+ };
353
+ var executeRemoveClass = async (action, context) => {
354
+ let anchorEl = context.resolveAnchor(action.anchorId);
355
+ if (!anchorEl && context.waitForAnchor) {
356
+ anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
357
+ }
358
+ if (!anchorEl) {
359
+ console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
360
+ return { cleanup: () => {
361
+ } };
362
+ }
363
+ const hadClass = anchorEl.classList.contains(action.className);
364
+ anchorEl.classList.remove(action.className);
365
+ context.publishEvent("action.applied", {
366
+ id: context.generateId(),
367
+ kind: "content:removeClass",
368
+ anchorId: action.anchorId,
369
+ className: action.className
370
+ });
371
+ return {
372
+ cleanup: () => {
373
+ if (!anchorEl.isConnected) return;
374
+ if (hadClass) {
375
+ anchorEl.classList.add(action.className);
376
+ }
332
377
  }
333
- // Apply new styles
334
- for (const [prop, value] of Object.entries(action.styles)) {
335
- anchorEl.style.setProperty(prop, value);
378
+ };
379
+ };
380
+ var executeSetStyle = async (action, context) => {
381
+ let anchorEl = context.resolveAnchor(action.anchorId);
382
+ if (!anchorEl && context.waitForAnchor) {
383
+ anchorEl = await context.waitForAnchor(action.anchorId, 3e3);
384
+ }
385
+ if (!anchorEl) {
386
+ console.warn(`[adaptive-content] Anchor not found after waiting: ${action.anchorId.selector}`);
387
+ return { cleanup: () => {
388
+ } };
389
+ }
390
+ const originalStyles = /* @__PURE__ */ new Map();
391
+ for (const prop of Object.keys(action.styles)) {
392
+ const current = anchorEl.style.getPropertyValue(prop);
393
+ originalStyles.set(prop, current);
394
+ }
395
+ for (const [prop, value] of Object.entries(action.styles)) {
396
+ anchorEl.style.setProperty(prop, value);
397
+ }
398
+ context.publishEvent("action.applied", {
399
+ id: context.generateId(),
400
+ kind: "content:setStyle",
401
+ anchorId: action.anchorId,
402
+ styles: Object.keys(action.styles)
403
+ });
404
+ return {
405
+ cleanup: () => {
406
+ if (!anchorEl.isConnected) return;
407
+ for (const [prop, originalValue] of originalStyles) {
408
+ if (originalValue) {
409
+ anchorEl.style.setProperty(prop, originalValue);
410
+ } else {
411
+ anchorEl.style.removeProperty(prop);
412
+ }
413
+ }
414
+ },
415
+ updateFn: (changes) => {
416
+ if ("styles" in changes && typeof changes.styles === "object" && changes.styles) {
417
+ for (const [prop, value] of Object.entries(changes.styles)) {
418
+ anchorEl.style.setProperty(prop, value);
419
+ }
420
+ }
336
421
  }
337
- context.publishEvent('action.applied', {
338
- id: context.generateId(),
339
- kind: 'content:setStyle',
340
- anchorId: action.anchorId,
341
- styles: Object.keys(action.styles),
342
- });
343
- return {
344
- cleanup: () => {
345
- if (!anchorEl.isConnected)
346
- return;
347
- // Restore original styles
348
- for (const [prop, originalValue] of originalStyles) {
349
- if (originalValue) {
350
- anchorEl.style.setProperty(prop, originalValue);
351
- }
352
- else {
353
- anchorEl.style.removeProperty(prop);
354
- }
355
- }
356
- },
357
- updateFn: (changes) => {
358
- if ('styles' in changes && typeof changes.styles === 'object' && changes.styles) {
359
- for (const [prop, value] of Object.entries(changes.styles)) {
360
- anchorEl.style.setProperty(prop, value);
361
- }
362
- }
363
- },
364
- };
422
+ };
365
423
  };
366
- // ============================================================================
367
- // Executor Definitions for Registration
368
- // ============================================================================
369
- /**
370
- * All executors provided by this app.
371
- * These are registered with the runtime's ExecutorRegistry.
372
- */
373
- export const executors = [
374
- { kind: 'content:insertHtml', executor: executeInsertHtml },
375
- { kind: 'content:setText', executor: executeSetText },
376
- { kind: 'content:setAttr', executor: executeSetAttr },
377
- { kind: 'content:addClass', executor: executeAddClass },
378
- { kind: 'content:removeClass', executor: executeRemoveClass },
379
- { kind: 'content:setStyle', executor: executeSetStyle },
424
+ var executors = [
425
+ { kind: "content:insertHtml", executor: executeInsertHtml },
426
+ { kind: "content:setText", executor: executeSetText },
427
+ { kind: "content:setAttr", executor: executeSetAttr },
428
+ { kind: "content:addClass", executor: executeAddClass },
429
+ { kind: "content:removeClass", executor: executeRemoveClass },
430
+ { kind: "content:setStyle", executor: executeSetStyle }
380
431
  ];
381
- /**
382
- * App runtime manifest.
383
- */
384
- export const runtime = {
385
- id: 'adaptive-content',
386
- version: '1.0.0',
387
- name: 'Content',
388
- description: 'DOM manipulation for text, attributes, and styles',
389
- executors,
432
+ var runtime = {
433
+ id: "adaptive-content",
434
+ version: "1.0.0",
435
+ name: "Content",
436
+ description: "DOM manipulation for text, attributes, and styles",
437
+ executors
438
+ };
439
+ export {
440
+ executeAddClass,
441
+ executeInsertHtml,
442
+ executeRemoveClass,
443
+ executeSetAttr,
444
+ executeSetStyle,
445
+ executeSetText,
446
+ executors,
447
+ runtime
390
448
  };
449
+ //# sourceMappingURL=runtime.js.map