@openelement/core 0.41.0-alpha.1

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 (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/package.json +124 -0
  4. package/src/binding-activation.d.ts +2 -0
  5. package/src/binding-activation.js +254 -0
  6. package/src/binding-descriptor.d.ts +79 -0
  7. package/src/binding-descriptor.js +9 -0
  8. package/src/context.d.ts +32 -0
  9. package/src/context.js +76 -0
  10. package/src/csr.d.ts +13 -0
  11. package/src/csr.js +14 -0
  12. package/src/dsd-hydration-events.d.ts +2 -0
  13. package/src/dsd-hydration-events.js +13 -0
  14. package/src/dsd-hydration.d.ts +40 -0
  15. package/src/dsd-hydration.js +48 -0
  16. package/src/errors.d.ts +54 -0
  17. package/src/errors.js +113 -0
  18. package/src/event-hydration.d.ts +12 -0
  19. package/src/event-hydration.js +118 -0
  20. package/src/event-marker.d.ts +7 -0
  21. package/src/event-marker.js +54 -0
  22. package/src/html-escape.d.ts +29 -0
  23. package/src/html-escape.js +126 -0
  24. package/src/hydrate.d.ts +15 -0
  25. package/src/hydrate.js +15 -0
  26. package/src/index.d.ts +58 -0
  27. package/src/index.js +46 -0
  28. package/src/island-transform.d.ts +14 -0
  29. package/src/island-transform.js +60 -0
  30. package/src/island.d.ts +59 -0
  31. package/src/island.js +342 -0
  32. package/src/isr-runtime.d.ts +28 -0
  33. package/src/isr-runtime.js +99 -0
  34. package/src/isr.d.ts +22 -0
  35. package/src/isr.js +41 -0
  36. package/src/jsx-render-dom.d.ts +22 -0
  37. package/src/jsx-render-dom.js +376 -0
  38. package/src/jsx-runtime.d.ts +58 -0
  39. package/src/jsx-runtime.js +99 -0
  40. package/src/jsx-types.d.ts +46 -0
  41. package/src/logger.d.ts +15 -0
  42. package/src/logger.js +24 -0
  43. package/src/prop.d.ts +24 -0
  44. package/src/prop.js +160 -0
  45. package/src/registry.d.ts +17 -0
  46. package/src/registry.js +219 -0
  47. package/src/render-dsd-stream.d.ts +46 -0
  48. package/src/render-dsd-stream.js +86 -0
  49. package/src/render-dsd.d.ts +27 -0
  50. package/src/render-dsd.js +315 -0
  51. package/src/render-ir.d.ts +32 -0
  52. package/src/render-ir.js +245 -0
  53. package/src/runtime.d.ts +9 -0
  54. package/src/runtime.js +16 -0
  55. package/src/security.d.ts +1 -0
  56. package/src/security.js +40 -0
  57. package/src/signal-context.d.ts +15 -0
  58. package/src/signal-context.js +59 -0
  59. package/src/static.d.ts +35 -0
  60. package/src/static.js +34 -0
  61. package/src/style-sheet.d.ts +9 -0
  62. package/src/style-sheet.js +56 -0
  63. package/src/tag-utils.d.ts +11 -0
  64. package/src/tag-utils.js +28 -0
  65. package/src/vnode.d.ts +15 -0
  66. package/src/vnode.js +31 -0
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Internal structured render IR.
3
+ *
4
+ * v0.29.1: Unified attribute serialization and single async render path.
5
+ * `renderDsdTree` is the only public rendering API. All internal rendering
6
+ * flows through `renderToNode`.
7
+ */ import { escapeAttr, escapeHtml } from './html-escape.js';
8
+ import { createEventMarkerContext, serializeEventMarkers } from './event-marker.js';
9
+ import { FOR_TAG, Fragment, HTML_TAG, SHOW_TAG } from './jsx-runtime.js';
10
+ import { DANGEROUS_KEYS, trustRenderHtml } from './security.js';
11
+ import { isSignalLike, unwrapSignalLike } from '@openelement/signal';
12
+ import { isComponentCtor, isComponentFn, isVNode } from './vnode.js';
13
+ import { renderDsd } from './render-dsd.js';
14
+ import { createLogger } from './logger.js';
15
+ import { formatError } from './errors.js';
16
+ export const VOID_ELEMENTS = new Set([
17
+ 'area',
18
+ 'base',
19
+ 'br',
20
+ 'col',
21
+ 'embed',
22
+ 'hr',
23
+ 'img',
24
+ 'input',
25
+ 'link',
26
+ 'meta',
27
+ 'param',
28
+ 'source',
29
+ 'track',
30
+ 'wbr'
31
+ ]);
32
+ export function textNode(value) {
33
+ return {
34
+ kind: 'text',
35
+ value: String(value)
36
+ };
37
+ }
38
+ export function trustedHtmlNode(value) {
39
+ return {
40
+ kind: 'trusted-html',
41
+ value: trustRenderHtml(String(value))
42
+ };
43
+ }
44
+ export function fragmentNode(children) {
45
+ return {
46
+ kind: 'fragment',
47
+ children
48
+ };
49
+ }
50
+ export function dsdHostNode(params) {
51
+ return {
52
+ kind: 'dsd-host',
53
+ ...params
54
+ };
55
+ }
56
+ export function camelToKebab(str) {
57
+ return str.replace(/([A-Z])/g, '-$1').toLowerCase();
58
+ }
59
+ // ─── Unified Attribute Serialization ────────────────────────────
60
+ const SKIP_ATTR_KEYS = new Set([
61
+ 'children',
62
+ 'ref',
63
+ 'key',
64
+ 'trustedHtml',
65
+ 'innerHTML',
66
+ 'textContent'
67
+ ]);
68
+ export function serializeAttrs(tag, props) {
69
+ const isCustomElement = tag.includes('-');
70
+ let result = '';
71
+ for (const [key, value] of Object.entries(props)){
72
+ if (SKIP_ATTR_KEYS.has(key)) continue;
73
+ if (key.startsWith('on') && typeof value === 'function') continue;
74
+ if (typeof value === 'function') continue;
75
+ if (value == null) continue;
76
+ let attrName = key === 'className' ? 'class' : key === 'htmlFor' ? 'for' : key;
77
+ if (isCustomElement && attrName === key) {
78
+ attrName = camelToKebab(attrName);
79
+ }
80
+ const resolved = unwrapSignalLike(value);
81
+ if (typeof resolved === 'boolean') {
82
+ if (resolved) result += ` ${attrName}`;
83
+ continue;
84
+ }
85
+ if (key === 'style' && typeof resolved === 'object' && resolved !== null) {
86
+ const styleObj = {};
87
+ for (const [sk, sv] of Object.entries(resolved)){
88
+ styleObj[sk] = unwrapSignalLike(sv);
89
+ }
90
+ const css = styleObjectToString(styleObj);
91
+ if (css) result += ` style="${escapeAttr(css)}"`;
92
+ continue;
93
+ }
94
+ if (typeof resolved === 'object') {
95
+ result += ` ${attrName}="${escapeAttr(JSON.stringify(resolved))}"`;
96
+ } else {
97
+ result += ` ${attrName}="${escapeAttr(String(resolved))}"`;
98
+ }
99
+ }
100
+ return result;
101
+ }
102
+ // ─── Serialization ──────────────────────────────────────────────
103
+ export function serializeRenderNode(node) {
104
+ switch(node.kind){
105
+ case 'text':
106
+ return escapeHtml(node.value);
107
+ case 'trusted-html':
108
+ return node.value;
109
+ case 'fragment':
110
+ return node.children.map(serializeRenderNode).join('');
111
+ case 'element':
112
+ {
113
+ const attrs = serializeAttrs(node.tag, node.attrs);
114
+ const events = node.eventAttrs ?? '';
115
+ if (node.voidElement || VOID_ELEMENTS.has(node.tag)) {
116
+ return `<${node.tag}${attrs}${events}>`;
117
+ }
118
+ return `<${node.tag}${attrs}${events}>${node.children.map(serializeRenderNode).join('')}</${node.tag}>`;
119
+ }
120
+ case 'dsd-host':
121
+ {
122
+ const attrs = serializeAttrs(node.tag, node.attrs);
123
+ if (node.layer === 'pure-island' || node.layer === 'light-dom') {
124
+ return `<${node.tag}${attrs}${node.ssrPropsAttr}${node.source}>${[
125
+ ...node.shadow,
126
+ ...node.light
127
+ ].map(serializeRenderNode).join('')}</${node.tag}>`;
128
+ }
129
+ const style = node.styleCss ? `\n <style>${node.styleCss}</style>` : '';
130
+ return `<${node.tag}${attrs}${node.ssrPropsAttr}${node.source}>
131
+ <template shadowrootmode="open"${node.templateAttrs}>${style}
132
+ ${node.shadow.map(serializeRenderNode).join('')}
133
+ </template>
134
+ ${node.light.map(serializeRenderNode).join('')}</${node.tag}>`;
135
+ }
136
+ }
137
+ }
138
+ // ─── Single async render path ───────────────────────────────────
139
+ export async function renderToNode(node, eventContext = createEventMarkerContext()) {
140
+ if (node == null || node === false || typeof node === 'boolean') return fragmentNode([]);
141
+ if (typeof node === 'string' || typeof node === 'number') return textNode(node);
142
+ if (isSignalLike(node)) {
143
+ return await renderToNode(node.value, eventContext);
144
+ }
145
+ if (!isVNode(node)) return textNode(String(node));
146
+ const { tag, props, children } = node;
147
+ // Fragment
148
+ if (tag === Fragment || typeof tag === 'symbol' && String(tag) === 'Symbol(openelement.fragment)') {
149
+ const parts = [];
150
+ for (const child of children)parts.push(await renderToNode(child, eventContext));
151
+ return fragmentNode(parts);
152
+ }
153
+ // Trusted HTML (raw HTML insertion, no wrapping tag)
154
+ if (tag === HTML_TAG) {
155
+ return trustedHtmlNode(props?.html ?? '');
156
+ }
157
+ // Show
158
+ if (tag === SHOW_TAG || tag === 'show') {
159
+ const whenVal = isSignalLike(props?.when) ? props.when.value : props?.when;
160
+ const target = whenVal ? children[0] : children[1];
161
+ return target ? await renderToNode(target, eventContext) : fragmentNode([]);
162
+ }
163
+ // For
164
+ if (tag === FOR_TAG || tag === 'fore') {
165
+ const items = isSignalLike(props?.each) ? props.each.value : props?.each;
166
+ const renderFn = children[0];
167
+ if (!Array.isArray(items) || typeof renderFn !== 'function') {
168
+ return fragmentNode([]);
169
+ }
170
+ const parts = [];
171
+ for(let index = 0; index < items.length; index++){
172
+ parts.push(await renderToNode(renderFn(items[index], index), eventContext));
173
+ }
174
+ return fragmentNode(parts);
175
+ }
176
+ // Component function/class
177
+ if (isComponentCtor(tag) || isComponentFn(tag)) {
178
+ try {
179
+ return await renderToNode(callComponent(tag, props, children), eventContext);
180
+ } catch (err) {
181
+ createLogger('render').error(`render failed for <${String(tag)}>:` + ` ${formatError(err)}`);
182
+ return fragmentNode([]);
183
+ }
184
+ }
185
+ // HTML / SVG element
186
+ const tagName = String(tag);
187
+ const childNodes = [];
188
+ if (props?.innerHTML !== undefined) {
189
+ const value = unwrapSignalLike(props.innerHTML);
190
+ childNodes.push(props.trustedHtml === true ? trustedHtmlNode(value) : textNode(value));
191
+ } else if (props?.textContent !== undefined) {
192
+ childNodes.push(textNode(unwrapSignalLike(props.textContent)));
193
+ } else {
194
+ for (const child of children)childNodes.push(await renderToNode(child, eventContext));
195
+ }
196
+ if (typeof customElements !== 'undefined' && customElements.get && customElements.get(tagName)) {
197
+ try {
198
+ const dsdResult = await renderDsd(tagName, {
199
+ componentClass: customElements.get(tagName),
200
+ props,
201
+ lightDom: childNodes
202
+ });
203
+ return trustedHtmlNode(dsdResult.html);
204
+ } catch (err) {
205
+ createLogger('render').error(`renderDsd failed for registered CE <${tagName}>:` + ` ${formatError(err)}`);
206
+ }
207
+ }
208
+ return {
209
+ kind: 'element',
210
+ tag: tagName,
211
+ attrs: props,
212
+ eventAttrs: serializeEventMarkers(props, eventContext),
213
+ children: childNodes,
214
+ voidElement: VOID_ELEMENTS.has(tagName)
215
+ };
216
+ }
217
+ // ─── Public API ─────────────────────────────────────────────────
218
+ export async function renderDsdTree(node, eventContext = createEventMarkerContext()) {
219
+ return serializeRenderNode(await renderToNode(node, eventContext));
220
+ }
221
+ // ─── Helpers ────────────────────────────────────────────────────
222
+ function callComponent(tag, props, children) {
223
+ if (isComponentCtor(tag)) {
224
+ const instance = new tag();
225
+ for (const [key, value] of Object.entries(props)){
226
+ if (DANGEROUS_KEYS.has(key)) continue;
227
+ instance[key] = value;
228
+ }
229
+ return instance.render();
230
+ }
231
+ if (isComponentFn(tag)) {
232
+ return tag({
233
+ ...props,
234
+ children
235
+ });
236
+ }
237
+ return null;
238
+ }
239
+ function styleObjectToString(obj) {
240
+ return Object.entries(obj).filter(([, value])=>value != null).map(([key, value])=>{
241
+ const prop = key.replace(/([A-Z])/g, (match)=>`-${match.toLowerCase()}`);
242
+ return `${prop}: ${value}`;
243
+ }).join('; ');
244
+ }
245
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jb3JlL3NyYy9yZW5kZXItaXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBJbnRlcm5hbCBzdHJ1Y3R1cmVkIHJlbmRlciBJUi5cbiAqXG4gKiB2MC4yOS4xOiBVbmlmaWVkIGF0dHJpYnV0ZSBzZXJpYWxpemF0aW9uIGFuZCBzaW5nbGUgYXN5bmMgcmVuZGVyIHBhdGguXG4gKiBgcmVuZGVyRHNkVHJlZWAgaXMgdGhlIG9ubHkgcHVibGljIHJlbmRlcmluZyBBUEkuIEFsbCBpbnRlcm5hbCByZW5kZXJpbmdcbiAqIGZsb3dzIHRocm91Z2ggYHJlbmRlclRvTm9kZWAuXG4gKi9cblxuaW1wb3J0IHsgZXNjYXBlQXR0ciwgZXNjYXBlSHRtbCB9IGZyb20gJy4vaHRtbC1lc2NhcGUuanMnO1xuaW1wb3J0IHtcbiAgY3JlYXRlRXZlbnRNYXJrZXJDb250ZXh0LFxuICB0eXBlIEV2ZW50TWFya2VyQ29udGV4dCxcbiAgc2VyaWFsaXplRXZlbnRNYXJrZXJzLFxufSBmcm9tICcuL2V2ZW50LW1hcmtlci5qcyc7XG5pbXBvcnQgeyBGT1JfVEFHLCBGcmFnbWVudCwgSFRNTF9UQUcsIFNIT1dfVEFHIH0gZnJvbSAnLi9qc3gtcnVudGltZS5qcyc7XG5pbXBvcnQgeyBEQU5HRVJPVVNfS0VZUywgdHJ1c3RSZW5kZXJIdG1sIH0gZnJvbSAnLi9zZWN1cml0eS5qcyc7XG5pbXBvcnQgeyBpc1NpZ25hbExpa2UsIHVud3JhcFNpZ25hbExpa2UgfSBmcm9tICdAb3BlbmVsZW1lbnQvc2lnbmFsJztcbmltcG9ydCB7IGlzQ29tcG9uZW50Q3RvciwgaXNDb21wb25lbnRGbiwgaXNWTm9kZSB9IGZyb20gJy4vdm5vZGUuanMnO1xuaW1wb3J0IHR5cGUgeyBSZW5kZXJGbiwgVk5vZGUgfSBmcm9tICdAb3BlbmVsZW1lbnQvcHJvdG9jb2wvdm5vZGUnO1xuaW1wb3J0IHsgcmVuZGVyRHNkIH0gZnJvbSAnLi9yZW5kZXItZHNkLmpzJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyLmpzJztcbmltcG9ydCB7IGZvcm1hdEVycm9yIH0gZnJvbSAnLi9lcnJvcnMuanMnO1xuXG5leHBvcnQgdHlwZSBSZW5kZXJOb2RlID1cbiAgfCB7IGtpbmQ6ICd0ZXh0JzsgdmFsdWU6IHN0cmluZyB9XG4gIHwgeyBraW5kOiAndHJ1c3RlZC1odG1sJzsgdmFsdWU6IHN0cmluZyB9XG4gIHwgeyBraW5kOiAnZnJhZ21lbnQnOyBjaGlsZHJlbjogUmVuZGVyTm9kZVtdIH1cbiAgfCB7XG4gICAga2luZDogJ2VsZW1lbnQnO1xuICAgIHRhZzogc3RyaW5nO1xuICAgIGF0dHJzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICBldmVudEF0dHJzPzogc3RyaW5nO1xuICAgIGNoaWxkcmVuOiBSZW5kZXJOb2RlW107XG4gICAgdm9pZEVsZW1lbnQ/OiBib29sZWFuO1xuICB9XG4gIHwge1xuICAgIGtpbmQ6ICdkc2QtaG9zdCc7XG4gICAgdGFnOiBzdHJpbmc7XG4gICAgYXR0cnM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIHNzclByb3BzQXR0cjogc3RyaW5nO1xuICAgIHNvdXJjZTogc3RyaW5nO1xuICAgIHRlbXBsYXRlQXR0cnM6IHN0cmluZztcbiAgICBzdHlsZUNzczogc3RyaW5nO1xuICAgIHNoYWRvdzogUmVuZGVyTm9kZVtdO1xuICAgIGxpZ2h0OiBSZW5kZXJOb2RlW107XG4gICAgbGF5ZXI6IHN0cmluZztcbiAgfTtcblxuZXhwb3J0IGNvbnN0IFZPSURfRUxFTUVOVFMgPSBuZXcgU2V0KFtcbiAgJ2FyZWEnLFxuICAnYmFzZScsXG4gICdicicsXG4gICdjb2wnLFxuICAnZW1iZWQnLFxuICAnaHInLFxuICAnaW1nJyxcbiAgJ2lucHV0JyxcbiAgJ2xpbmsnLFxuICAnbWV0YScsXG4gICdwYXJhbScsXG4gICdzb3VyY2UnLFxuICAndHJhY2snLFxuICAnd2JyJyxcbl0pO1xuXG5leHBvcnQgZnVuY3Rpb24gdGV4dE5vZGUodmFsdWU6IHVua25vd24pOiBSZW5kZXJOb2RlIHtcbiAgcmV0dXJuIHsga2luZDogJ3RleHQnLCB2YWx1ZTogU3RyaW5nKHZhbHVlKSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJ1c3RlZEh0bWxOb2RlKHZhbHVlOiB1bmtub3duKTogUmVuZGVyTm9kZSB7XG4gIHJldHVybiB7IGtpbmQ6ICd0cnVzdGVkLWh0bWwnLCB2YWx1ZTogdHJ1c3RSZW5kZXJIdG1sKFN0cmluZyh2YWx1ZSkpIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmcmFnbWVudE5vZGUoY2hpbGRyZW46IFJlbmRlck5vZGVbXSk6IFJlbmRlck5vZGUge1xuICByZXR1cm4geyBraW5kOiAnZnJhZ21lbnQnLCBjaGlsZHJlbiB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZHNkSG9zdE5vZGUocGFyYW1zOiBPbWl0PEV4dHJhY3Q8UmVuZGVyTm9kZSwgeyBraW5kOiAnZHNkLWhvc3QnIH0+LCAna2luZCc+KSB7XG4gIHJldHVybiB7IGtpbmQ6ICdkc2QtaG9zdCcsIC4uLnBhcmFtcyB9IHNhdGlzZmllcyBSZW5kZXJOb2RlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FtZWxUb0tlYmFiKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHN0ci5yZXBsYWNlKC8oW0EtWl0pL2csICctJDEnKS50b0xvd2VyQ2FzZSgpO1xufVxuXG4vLyDilIDilIDilIAgVW5pZmllZCBBdHRyaWJ1dGUgU2VyaWFsaXphdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuY29uc3QgU0tJUF9BVFRSX0tFWVMgPSBuZXcgU2V0KFtcbiAgJ2NoaWxkcmVuJyxcbiAgJ3JlZicsXG4gICdrZXknLFxuICAndHJ1c3RlZEh0bWwnLFxuICAnaW5uZXJIVE1MJyxcbiAgJ3RleHRDb250ZW50Jyxcbl0pO1xuXG5leHBvcnQgZnVuY3Rpb24gc2VyaWFsaXplQXR0cnModGFnOiBzdHJpbmcsIHByb3BzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHN0cmluZyB7XG4gIGNvbnN0IGlzQ3VzdG9tRWxlbWVudCA9IHRhZy5pbmNsdWRlcygnLScpO1xuICBsZXQgcmVzdWx0ID0gJyc7XG5cbiAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMocHJvcHMpKSB7XG4gICAgaWYgKFNLSVBfQVRUUl9LRVlTLmhhcyhrZXkpKSBjb250aW51ZTtcbiAgICBpZiAoa2V5LnN0YXJ0c1dpdGgoJ29uJykgJiYgdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSBjb250aW51ZTtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSBjb250aW51ZTtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkgY29udGludWU7XG5cbiAgICBsZXQgYXR0ck5hbWUgPSBrZXkgPT09ICdjbGFzc05hbWUnID8gJ2NsYXNzJyA6IGtleSA9PT0gJ2h0bWxGb3InID8gJ2ZvcicgOiBrZXk7XG4gICAgaWYgKGlzQ3VzdG9tRWxlbWVudCAmJiBhdHRyTmFtZSA9PT0ga2V5KSB7XG4gICAgICBhdHRyTmFtZSA9IGNhbWVsVG9LZWJhYihhdHRyTmFtZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzb2x2ZWQgPSB1bndyYXBTaWduYWxMaWtlKHZhbHVlKTtcblxuICAgIGlmICh0eXBlb2YgcmVzb2x2ZWQgPT09ICdib29sZWFuJykge1xuICAgICAgaWYgKHJlc29sdmVkKSByZXN1bHQgKz0gYCAke2F0dHJOYW1lfWA7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBpZiAoa2V5ID09PSAnc3R5bGUnICYmIHR5cGVvZiByZXNvbHZlZCA9PT0gJ29iamVjdCcgJiYgcmVzb2x2ZWQgIT09IG51bGwpIHtcbiAgICAgIGNvbnN0IHN0eWxlT2JqOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuICAgICAgZm9yIChjb25zdCBbc2ssIHN2XSBvZiBPYmplY3QuZW50cmllcyhyZXNvbHZlZCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikpIHtcbiAgICAgICAgc3R5bGVPYmpbc2tdID0gdW53cmFwU2lnbmFsTGlrZShzdik7XG4gICAgICB9XG4gICAgICBjb25zdCBjc3MgPSBzdHlsZU9iamVjdFRvU3RyaW5nKHN0eWxlT2JqKTtcbiAgICAgIGlmIChjc3MpIHJlc3VsdCArPSBgIHN0eWxlPVwiJHtlc2NhcGVBdHRyKGNzcyl9XCJgO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiByZXNvbHZlZCA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHJlc3VsdCArPSBgICR7YXR0ck5hbWV9PVwiJHtlc2NhcGVBdHRyKEpTT04uc3RyaW5naWZ5KHJlc29sdmVkKSl9XCJgO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQgKz0gYCAke2F0dHJOYW1lfT1cIiR7ZXNjYXBlQXR0cihTdHJpbmcocmVzb2x2ZWQpKX1cImA7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLy8g4pSA4pSA4pSAIFNlcmlhbGl6YXRpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmV4cG9ydCBmdW5jdGlvbiBzZXJpYWxpemVSZW5kZXJOb2RlKG5vZGU6IFJlbmRlck5vZGUpOiBzdHJpbmcge1xuICBzd2l0Y2ggKG5vZGUua2luZCkge1xuICAgIGNhc2UgJ3RleHQnOlxuICAgICAgcmV0dXJuIGVzY2FwZUh0bWwobm9kZS52YWx1ZSk7XG4gICAgY2FzZSAndHJ1c3RlZC1odG1sJzpcbiAgICAgIHJldHVybiBub2RlLnZhbHVlO1xuICAgIGNhc2UgJ2ZyYWdtZW50JzpcbiAgICAgIHJldHVybiBub2RlLmNoaWxkcmVuLm1hcChzZXJpYWxpemVSZW5kZXJOb2RlKS5qb2luKCcnKTtcbiAgICBjYXNlICdlbGVtZW50Jzoge1xuICAgICAgY29uc3QgYXR0cnMgPSBzZXJpYWxpemVBdHRycyhub2RlLnRhZywgbm9kZS5hdHRycyk7XG4gICAgICBjb25zdCBldmVudHMgPSBub2RlLmV2ZW50QXR0cnMgPz8gJyc7XG4gICAgICBpZiAobm9kZS52b2lkRWxlbWVudCB8fCBWT0lEX0VMRU1FTlRTLmhhcyhub2RlLnRhZykpIHtcbiAgICAgICAgcmV0dXJuIGA8JHtub2RlLnRhZ30ke2F0dHJzfSR7ZXZlbnRzfT5gO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGA8JHtub2RlLnRhZ30ke2F0dHJzfSR7ZXZlbnRzfT4ke1xuICAgICAgICBub2RlLmNoaWxkcmVuLm1hcChzZXJpYWxpemVSZW5kZXJOb2RlKS5qb2luKCcnKVxuICAgICAgfTwvJHtub2RlLnRhZ30+YDtcbiAgICB9XG4gICAgY2FzZSAnZHNkLWhvc3QnOiB7XG4gICAgICBjb25zdCBhdHRycyA9IHNlcmlhbGl6ZUF0dHJzKG5vZGUudGFnLCBub2RlLmF0dHJzKTtcbiAgICAgIGlmIChub2RlLmxheWVyID09PSAncHVyZS1pc2xhbmQnIHx8IG5vZGUubGF5ZXIgPT09ICdsaWdodC1kb20nKSB7XG4gICAgICAgIHJldHVybiBgPCR7bm9kZS50YWd9JHthdHRyc30ke25vZGUuc3NyUHJvcHNBdHRyfSR7bm9kZS5zb3VyY2V9PiR7XG4gICAgICAgICAgWy4uLm5vZGUuc2hhZG93LCAuLi5ub2RlLmxpZ2h0XS5tYXAoc2VyaWFsaXplUmVuZGVyTm9kZSkuam9pbignJylcbiAgICAgICAgfTwvJHtub2RlLnRhZ30+YDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHN0eWxlID0gbm9kZS5zdHlsZUNzcyA/IGBcXG4gICAgPHN0eWxlPiR7bm9kZS5zdHlsZUNzc308L3N0eWxlPmAgOiAnJztcbiAgICAgIHJldHVybiBgPCR7bm9kZS50YWd9JHthdHRyc30ke25vZGUuc3NyUHJvcHNBdHRyfSR7bm9kZS5zb3VyY2V9PlxuICA8dGVtcGxhdGUgc2hhZG93cm9vdG1vZGU9XCJvcGVuXCIke25vZGUudGVtcGxhdGVBdHRyc30+JHtzdHlsZX1cbiAgICAke25vZGUuc2hhZG93Lm1hcChzZXJpYWxpemVSZW5kZXJOb2RlKS5qb2luKCcnKX1cbiAgPC90ZW1wbGF0ZT5cbiR7bm9kZS5saWdodC5tYXAoc2VyaWFsaXplUmVuZGVyTm9kZSkuam9pbignJyl9PC8ke25vZGUudGFnfT5gO1xuICAgIH1cbiAgfVxufVxuXG4vLyDilIDilIDilIAgU2luZ2xlIGFzeW5jIHJlbmRlciBwYXRoIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVuZGVyVG9Ob2RlKFxuICBub2RlOiB1bmtub3duLFxuICBldmVudENvbnRleHQ6IEV2ZW50TWFya2VyQ29udGV4dCA9IGNyZWF0ZUV2ZW50TWFya2VyQ29udGV4dCgpLFxuKTogUHJvbWlzZTxSZW5kZXJOb2RlPiB7XG4gIGlmIChub2RlID09IG51bGwgfHwgbm9kZSA9PT0gZmFsc2UgfHwgdHlwZW9mIG5vZGUgPT09ICdib29sZWFuJykgcmV0dXJuIGZyYWdtZW50Tm9kZShbXSk7XG4gIGlmICh0eXBlb2Ygbm9kZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIG5vZGUgPT09ICdudW1iZXInKSByZXR1cm4gdGV4dE5vZGUobm9kZSk7XG4gIGlmIChpc1NpZ25hbExpa2Uobm9kZSkpIHtcbiAgICByZXR1cm4gYXdhaXQgcmVuZGVyVG9Ob2RlKChub2RlIGFzIHsgdmFsdWU6IHVua25vd24gfSkudmFsdWUsIGV2ZW50Q29udGV4dCk7XG4gIH1cbiAgaWYgKCFpc1ZOb2RlKG5vZGUpKSByZXR1cm4gdGV4dE5vZGUoU3RyaW5nKG5vZGUpKTtcblxuICBjb25zdCB7IHRhZywgcHJvcHMsIGNoaWxkcmVuIH0gPSBub2RlO1xuXG4gIC8vIEZyYWdtZW50XG4gIGlmIChcbiAgICB0YWcgPT09IEZyYWdtZW50IHx8ICh0eXBlb2YgdGFnID09PSAnc3ltYm9sJyAmJiBTdHJpbmcodGFnKSA9PT0gJ1N5bWJvbChvcGVuZWxlbWVudC5mcmFnbWVudCknKVxuICApIHtcbiAgICBjb25zdCBwYXJ0czogUmVuZGVyTm9kZVtdID0gW107XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBjaGlsZHJlbikgcGFydHMucHVzaChhd2FpdCByZW5kZXJUb05vZGUoY2hpbGQsIGV2ZW50Q29udGV4dCkpO1xuICAgIHJldHVybiBmcmFnbWVudE5vZGUocGFydHMpO1xuICB9XG5cbiAgLy8gVHJ1c3RlZCBIVE1MIChyYXcgSFRNTCBpbnNlcnRpb24sIG5vIHdyYXBwaW5nIHRhZylcbiAgaWYgKHRhZyA9PT0gSFRNTF9UQUcpIHtcbiAgICByZXR1cm4gdHJ1c3RlZEh0bWxOb2RlKHByb3BzPy5odG1sID8/ICcnKTtcbiAgfVxuXG4gIC8vIFNob3dcbiAgaWYgKHRhZyA9PT0gU0hPV19UQUcgfHwgdGFnID09PSAnc2hvdycpIHtcbiAgICBjb25zdCB3aGVuVmFsID0gaXNTaWduYWxMaWtlKHByb3BzPy53aGVuKVxuICAgICAgPyAocHJvcHMhLndoZW4gYXMgeyB2YWx1ZTogdW5rbm93biB9KS52YWx1ZVxuICAgICAgOiBwcm9wcz8ud2hlbjtcbiAgICBjb25zdCB0YXJnZXQgPSB3aGVuVmFsID8gY2hpbGRyZW5bMF0gOiBjaGlsZHJlblsxXTtcbiAgICByZXR1cm4gdGFyZ2V0ID8gYXdhaXQgcmVuZGVyVG9Ob2RlKHRhcmdldCwgZXZlbnRDb250ZXh0KSA6IGZyYWdtZW50Tm9kZShbXSk7XG4gIH1cblxuICAvLyBGb3JcbiAgaWYgKHRhZyA9PT0gRk9SX1RBRyB8fCB0YWcgPT09ICdmb3JlJykge1xuICAgIGNvbnN0IGl0ZW1zID0gKGlzU2lnbmFsTGlrZShwcm9wcz8uZWFjaClcbiAgICAgID8gKHByb3BzIS5lYWNoIGFzIHsgdmFsdWU6IHVua25vd24gfSkudmFsdWVcbiAgICAgIDogcHJvcHM/LmVhY2gpIGFzIHVua25vd25bXTtcbiAgICBjb25zdCByZW5kZXJGbiA9IGNoaWxkcmVuWzBdIGFzIFJlbmRlckZuO1xuICAgIGlmICghQXJyYXkuaXNBcnJheShpdGVtcykgfHwgdHlwZW9mIHJlbmRlckZuICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXR1cm4gZnJhZ21lbnROb2RlKFtdKTtcbiAgICB9XG4gICAgY29uc3QgcGFydHM6IFJlbmRlck5vZGVbXSA9IFtdO1xuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBpdGVtcy5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgIHBhcnRzLnB1c2goYXdhaXQgcmVuZGVyVG9Ob2RlKHJlbmRlckZuKGl0ZW1zW2luZGV4XSwgaW5kZXgpLCBldmVudENvbnRleHQpKTtcbiAgICB9XG4gICAgcmV0dXJuIGZyYWdtZW50Tm9kZShwYXJ0cyk7XG4gIH1cblxuICAvLyBDb21wb25lbnQgZnVuY3Rpb24vY2xhc3NcbiAgaWYgKGlzQ29tcG9uZW50Q3Rvcih0YWcpIHx8IGlzQ29tcG9uZW50Rm4odGFnKSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgcmVuZGVyVG9Ob2RlKGNhbGxDb21wb25lbnQodGFnLCBwcm9wcywgY2hpbGRyZW4pLCBldmVudENvbnRleHQpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY3JlYXRlTG9nZ2VyKCdyZW5kZXInKS5lcnJvcihcbiAgICAgICAgYHJlbmRlciBmYWlsZWQgZm9yIDwke1N0cmluZyh0YWcpfT46YCArXG4gICAgICAgICAgYCAke2Zvcm1hdEVycm9yKGVycil9YCxcbiAgICAgICk7XG4gICAgICByZXR1cm4gZnJhZ21lbnROb2RlKFtdKTtcbiAgICB9XG4gIH1cblxuICAvLyBIVE1MIC8gU1ZHIGVsZW1lbnRcbiAgY29uc3QgdGFnTmFtZSA9IFN0cmluZyh0YWcpO1xuICBjb25zdCBjaGlsZE5vZGVzOiBSZW5kZXJOb2RlW10gPSBbXTtcblxuICBpZiAocHJvcHM/LmlubmVySFRNTCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgdmFsdWUgPSB1bndyYXBTaWduYWxMaWtlKHByb3BzLmlubmVySFRNTCk7XG4gICAgY2hpbGROb2Rlcy5wdXNoKHByb3BzLnRydXN0ZWRIdG1sID09PSB0cnVlID8gdHJ1c3RlZEh0bWxOb2RlKHZhbHVlKSA6IHRleHROb2RlKHZhbHVlKSk7XG4gIH0gZWxzZSBpZiAocHJvcHM/LnRleHRDb250ZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICBjaGlsZE5vZGVzLnB1c2godGV4dE5vZGUodW53cmFwU2lnbmFsTGlrZShwcm9wcy50ZXh0Q29udGVudCkpKTtcbiAgfSBlbHNlIHtcbiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIGNoaWxkcmVuKSBjaGlsZE5vZGVzLnB1c2goYXdhaXQgcmVuZGVyVG9Ob2RlKGNoaWxkLCBldmVudENvbnRleHQpKTtcbiAgfVxuXG4gIGlmIChcbiAgICB0eXBlb2YgY3VzdG9tRWxlbWVudHMgIT09ICd1bmRlZmluZWQnICYmXG4gICAgY3VzdG9tRWxlbWVudHMuZ2V0ICYmXG4gICAgY3VzdG9tRWxlbWVudHMuZ2V0KHRhZ05hbWUpXG4gICkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkc2RSZXN1bHQgPSBhd2FpdCByZW5kZXJEc2QodGFnTmFtZSwge1xuICAgICAgICBjb21wb25lbnRDbGFzczogY3VzdG9tRWxlbWVudHMuZ2V0KHRhZ05hbWUpIGFzIEN1c3RvbUVsZW1lbnRDb25zdHJ1Y3RvcixcbiAgICAgICAgcHJvcHMsXG4gICAgICAgIGxpZ2h0RG9tOiBjaGlsZE5vZGVzLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gdHJ1c3RlZEh0bWxOb2RlKGRzZFJlc3VsdC5odG1sKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNyZWF0ZUxvZ2dlcigncmVuZGVyJykuZXJyb3IoXG4gICAgICAgIGByZW5kZXJEc2QgZmFpbGVkIGZvciByZWdpc3RlcmVkIENFIDwke3RhZ05hbWV9PjpgICtcbiAgICAgICAgICBgICR7Zm9ybWF0RXJyb3IoZXJyKX1gLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGtpbmQ6ICdlbGVtZW50JyxcbiAgICB0YWc6IHRhZ05hbWUsXG4gICAgYXR0cnM6IHByb3BzLFxuICAgIGV2ZW50QXR0cnM6IHNlcmlhbGl6ZUV2ZW50TWFya2Vycyhwcm9wcywgZXZlbnRDb250ZXh0KSxcbiAgICBjaGlsZHJlbjogY2hpbGROb2RlcyxcbiAgICB2b2lkRWxlbWVudDogVk9JRF9FTEVNRU5UUy5oYXModGFnTmFtZSksXG4gIH07XG59XG5cbi8vIOKUgOKUgOKUgCBQdWJsaWMgQVBJIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVuZGVyRHNkVHJlZShcbiAgbm9kZTogdW5rbm93bixcbiAgZXZlbnRDb250ZXh0OiBFdmVudE1hcmtlckNvbnRleHQgPSBjcmVhdGVFdmVudE1hcmtlckNvbnRleHQoKSxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiBzZXJpYWxpemVSZW5kZXJOb2RlKGF3YWl0IHJlbmRlclRvTm9kZShub2RlLCBldmVudENvbnRleHQpKTtcbn1cblxuLy8g4pSA4pSA4pSAIEhlbHBlcnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmZ1bmN0aW9uIGNhbGxDb21wb25lbnQoXG4gIHRhZzogVk5vZGVbJ3RhZyddLFxuICBwcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIGNoaWxkcmVuOiAoVk5vZGUgfCBzdHJpbmcgfCBSZW5kZXJGbilbXSxcbik6IHVua25vd24ge1xuICBpZiAoaXNDb21wb25lbnRDdG9yKHRhZykpIHtcbiAgICBjb25zdCBpbnN0YW5jZSA9IG5ldyB0YWcoKTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhwcm9wcykpIHtcbiAgICAgIGlmIChEQU5HRVJPVVNfS0VZUy5oYXMoa2V5KSkgY29udGludWU7XG4gICAgICAoaW5zdGFuY2UgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW2tleV0gPSB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGluc3RhbmNlLnJlbmRlcigpO1xuICB9XG4gIGlmIChpc0NvbXBvbmVudEZuKHRhZykpIHtcbiAgICByZXR1cm4gdGFnKHsgLi4ucHJvcHMsIGNoaWxkcmVuIH0pO1xuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBzdHlsZU9iamVjdFRvU3RyaW5nKG9iajogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBzdHJpbmcge1xuICByZXR1cm4gT2JqZWN0LmVudHJpZXMob2JqKVxuICAgIC5maWx0ZXIoKFssIHZhbHVlXSkgPT4gdmFsdWUgIT0gbnVsbClcbiAgICAubWFwKChba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgIGNvbnN0IHByb3AgPSBrZXkucmVwbGFjZSgvKFtBLVpdKS9nLCAobWF0Y2gpID0+IGAtJHttYXRjaC50b0xvd2VyQ2FzZSgpfWApO1xuICAgICAgcmV0dXJuIGAke3Byb3B9OiAke3ZhbHVlfWA7XG4gICAgfSlcbiAgICAuam9pbignOyAnKTtcbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFB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
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Runtime adapter protocol.
3
+ *
4
+ * Replacement boundary for Nitro, Workers, Node, Deno, or future
5
+ * fetch-compatible runtimes. Preserves openElement semantics while leaving
6
+ * concrete server engines outside this package.
7
+ */ import type { OpenElementRequestHandler, RuntimeAdapter, RuntimeAdapterOptions, RuntimeContext, RuntimePrerenderResult } from '@openelement/protocol/runtime';
8
+ export type { OpenElementRequestHandler, RuntimeAdapter, RuntimeAdapterOptions, RuntimeContext, RuntimePrerenderResult };
9
+ export declare function createRuntimeAdapter<Env extends Record<string, unknown> = Record<string, unknown>>(options: RuntimeAdapterOptions<Env>): RuntimeAdapter<Env>;
package/src/runtime.js ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Runtime adapter protocol.
3
+ *
4
+ * Replacement boundary for Nitro, Workers, Node, Deno, or future
5
+ * fetch-compatible runtimes. Preserves openElement semantics while leaving
6
+ * concrete server engines outside this package.
7
+ */ export function createRuntimeAdapter(options) {
8
+ return {
9
+ name: options.name,
10
+ fetch: options.fetch,
11
+ ...options.prerender ? {
12
+ prerender: options.prerender
13
+ } : {}
14
+ };
15
+ }
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jb3JlL3NyYy9ydW50aW1lLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUnVudGltZSBhZGFwdGVyIHByb3RvY29sLlxuICpcbiAqIFJlcGxhY2VtZW50IGJvdW5kYXJ5IGZvciBOaXRybywgV29ya2VycywgTm9kZSwgRGVubywgb3IgZnV0dXJlXG4gKiBmZXRjaC1jb21wYXRpYmxlIHJ1bnRpbWVzLiBQcmVzZXJ2ZXMgb3BlbkVsZW1lbnQgc2VtYW50aWNzIHdoaWxlIGxlYXZpbmdcbiAqIGNvbmNyZXRlIHNlcnZlciBlbmdpbmVzIG91dHNpZGUgdGhpcyBwYWNrYWdlLlxuICovXG5cbmltcG9ydCB0eXBlIHtcbiAgT3BlbkVsZW1lbnRSZXF1ZXN0SGFuZGxlcixcbiAgUnVudGltZUFkYXB0ZXIsXG4gIFJ1bnRpbWVBZGFwdGVyT3B0aW9ucyxcbiAgUnVudGltZUNvbnRleHQsXG4gIFJ1bnRpbWVQcmVyZW5kZXJSZXN1bHQsXG59IGZyb20gJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9ydW50aW1lJztcbmV4cG9ydCB0eXBlIHtcbiAgT3BlbkVsZW1lbnRSZXF1ZXN0SGFuZGxlcixcbiAgUnVudGltZUFkYXB0ZXIsXG4gIFJ1bnRpbWVBZGFwdGVyT3B0aW9ucyxcbiAgUnVudGltZUNvbnRleHQsXG4gIFJ1bnRpbWVQcmVyZW5kZXJSZXN1bHQsXG59O1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUnVudGltZUFkYXB0ZXI8XG4gIEVudiBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4+KG9wdGlvbnM6IFJ1bnRpbWVBZGFwdGVyT3B0aW9uczxFbnY+KTogUnVudGltZUFkYXB0ZXI8RW52PiB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogb3B0aW9ucy5uYW1lLFxuICAgIGZldGNoOiBvcHRpb25zLmZldGNoLFxuICAgIC4uLihvcHRpb25zLnByZXJlbmRlciA/IHsgcHJlcmVuZGVyOiBvcHRpb25zLnByZXJlbmRlciB9IDoge30pLFxuICB9O1xufVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Q0FNQyxHQWlCRCxPQUFPLFNBQVMscUJBRWQsT0FBbUM7RUFDbkMsT0FBTztJQUNMLE1BQU0sUUFBUSxJQUFJO0lBQ2xCLE9BQU8sUUFBUSxLQUFLO0lBQ3BCLEdBQUksUUFBUSxTQUFTLEdBQUc7TUFBRSxXQUFXLFFBQVEsU0FBUztJQUFDLElBQUksQ0FBQyxDQUFDO0VBQy9EO0FBQ0YifQ==
@@ -0,0 +1 @@
1
+ /** Object prototype keys that must never be injected as SSR props. */ export declare const DANGEROUS_KEYS: ReadonlySet<string>;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @openelement/core - SSR Security Guards.
3
+ *
4
+ * Properties that MUST NOT be injected from untrusted SSR props.
5
+ * These are Object.prototype internals and dangerous overrides that
6
+ * could be exploited via arbitrary property assignment.
7
+ *
8
+ * Shared by island.ts (client-side SSR prop restoration) and render-dsd.ts
9
+ * (SSR injectProps). Previously defined in island.ts and imported by
10
+ * render-instantiate.ts (v0.29.1: merged into render-dsd.ts).
11
+ *
12
+ * @module @openelement/core/security
13
+ */ import { createLogger, warnOnce } from './logger.js';
14
+ /** Object prototype keys that must never be injected as SSR props. */ export const DANGEROUS_KEYS = new Set([
15
+ '__proto__',
16
+ 'constructor',
17
+ 'prototype',
18
+ '__defineGetter__',
19
+ '__defineSetter__',
20
+ '__lookupGetter__',
21
+ '__lookupSetter__',
22
+ 'hasOwnProperty',
23
+ 'isPrototypeOf',
24
+ 'propertyIsEnumerable',
25
+ 'toString',
26
+ 'toLocaleString',
27
+ 'valueOf'
28
+ ]);
29
+ /**
30
+ * Mark caller-supplied HTML as trusted before injection into a DOM/string render path.
31
+ *
32
+ * `trustedHtml` is an explicit trust boundary, not a sanitizer. Core escapes
33
+ * untrusted text by default; callers that cross this boundary must sanitize or
34
+ * otherwise trust the HTML before passing it to openElement.
35
+ */ const _securityLog = createLogger('security');
36
+ export function trustRenderHtml(html) {
37
+ warnOnce('trustedHtml', _securityLog, 'trustRenderHtml is a trust boundary, not a sanitizer. ' + 'Caller must ensure HTML content is safe before passing to openElement.');
38
+ return html;
39
+ }
40
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jb3JlL3NyYy9zZWN1cml0eS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBvcGVuZWxlbWVudC9jb3JlIC0gU1NSIFNlY3VyaXR5IEd1YXJkcy5cbiAqXG4gKiBQcm9wZXJ0aWVzIHRoYXQgTVVTVCBOT1QgYmUgaW5qZWN0ZWQgZnJvbSB1bnRydXN0ZWQgU1NSIHByb3BzLlxuICogVGhlc2UgYXJlIE9iamVjdC5wcm90b3R5cGUgaW50ZXJuYWxzIGFuZCBkYW5nZXJvdXMgb3ZlcnJpZGVzIHRoYXRcbiAqIGNvdWxkIGJlIGV4cGxvaXRlZCB2aWEgYXJiaXRyYXJ5IHByb3BlcnR5IGFzc2lnbm1lbnQuXG4gKlxuICogU2hhcmVkIGJ5IGlzbGFuZC50cyAoY2xpZW50LXNpZGUgU1NSIHByb3AgcmVzdG9yYXRpb24pIGFuZCByZW5kZXItZHNkLnRzXG4gKiAoU1NSIGluamVjdFByb3BzKS4gUHJldmlvdXNseSBkZWZpbmVkIGluIGlzbGFuZC50cyBhbmQgaW1wb3J0ZWQgYnlcbiAqIHJlbmRlci1pbnN0YW50aWF0ZS50cyAodjAuMjkuMTogbWVyZ2VkIGludG8gcmVuZGVyLWRzZC50cykuXG4gKlxuICogQG1vZHVsZSBAb3BlbmVsZW1lbnQvY29yZS9zZWN1cml0eVxuICovXG5cbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciwgd2Fybk9uY2UgfSBmcm9tICcuL2xvZ2dlci5qcyc7XG5cbi8qKiBPYmplY3QgcHJvdG90eXBlIGtleXMgdGhhdCBtdXN0IG5ldmVyIGJlIGluamVjdGVkIGFzIFNTUiBwcm9wcy4gKi9cbmV4cG9ydCBjb25zdCBEQU5HRVJPVVNfS0VZUzogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoW1xuICAnX19wcm90b19fJyxcbiAgJ2NvbnN0cnVjdG9yJyxcbiAgJ3Byb3RvdHlwZScsXG4gICdfX2RlZmluZUdldHRlcl9fJyxcbiAgJ19fZGVmaW5lU2V0dGVyX18nLFxuICAnX19sb29rdXBHZXR0ZXJfXycsXG4gICdfX2xvb2t1cFNldHRlcl9fJyxcbiAgJ2hhc093blByb3BlcnR5JyxcbiAgJ2lzUHJvdG90eXBlT2YnLFxuICAncHJvcGVydHlJc0VudW1lcmFibGUnLFxuICAndG9TdHJpbmcnLFxuICAndG9Mb2NhbGVTdHJpbmcnLFxuICAndmFsdWVPZicsXG5dKTtcblxuLyoqXG4gKiBNYXJrIGNhbGxlci1zdXBwbGllZCBIVE1MIGFzIHRydXN0ZWQgYmVmb3JlIGluamVjdGlvbiBpbnRvIGEgRE9NL3N0cmluZyByZW5kZXIgcGF0aC5cbiAqXG4gKiBgdHJ1c3RlZEh0bWxgIGlzIGFuIGV4cGxpY2l0IHRydXN0IGJvdW5kYXJ5LCBub3QgYSBzYW5pdGl6ZXIuIENvcmUgZXNjYXBlc1xuICogdW50cnVzdGVkIHRleHQgYnkgZGVmYXVsdDsgY2FsbGVycyB0aGF0IGNyb3NzIHRoaXMgYm91bmRhcnkgbXVzdCBzYW5pdGl6ZSBvclxuICogb3RoZXJ3aXNlIHRydXN0IHRoZSBIVE1MIGJlZm9yZSBwYXNzaW5nIGl0IHRvIG9wZW5FbGVtZW50LlxuICovXG5jb25zdCBfc2VjdXJpdHlMb2cgPSBjcmVhdGVMb2dnZXIoJ3NlY3VyaXR5Jyk7XG5cbmV4cG9ydCBmdW5jdGlvbiB0cnVzdFJlbmRlckh0bWwoaHRtbDogc3RyaW5nKTogc3RyaW5nIHtcbiAgd2Fybk9uY2UoXG4gICAgJ3RydXN0ZWRIdG1sJyxcbiAgICBfc2VjdXJpdHlMb2csXG4gICAgJ3RydXN0UmVuZGVySHRtbCBpcyBhIHRydXN0IGJvdW5kYXJ5LCBub3QgYSBzYW5pdGl6ZXIuICcgK1xuICAgICAgJ0NhbGxlciBtdXN0IGVuc3VyZSBIVE1MIGNvbnRlbnQgaXMgc2FmZSBiZWZvcmUgcGFzc2luZyB0byBvcGVuRWxlbWVudC4nLFxuICApO1xuICByZXR1cm4gaHRtbDtcbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7O0NBWUMsR0FFRCxTQUFTLFlBQVksRUFBRSxRQUFRLFFBQVEsY0FBYztBQUVyRCxvRUFBb0UsR0FDcEUsT0FBTyxNQUFNLGlCQUFzQyxJQUFJLElBQUk7RUFDekQ7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7Q0FDRCxFQUFFO0FBRUg7Ozs7OztDQU1DLEdBQ0QsTUFBTSxlQUFlLGFBQWE7QUFFbEMsT0FBTyxTQUFTLGdCQUFnQixJQUFZO0VBQzFDLFNBQ0UsZUFDQSxjQUNBLDJEQUNFO0VBRUosT0FBTztBQUNUIn0=
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @openelement/core - SignalContext DOM-tree-based cross-component signal sharing.
3
+ *
4
+ * v0.29.6: WeakMap replaces symbol-keyed DOM property stamping.
5
+ * Consumer walks parentElement / shadowRoot.host upward to find signals.
6
+ *
7
+ * @module @openelement/core/signal-context
8
+ */ import type { WritableSignal } from '@openelement/signal';
9
+ export interface Context<T> {
10
+ key: symbol;
11
+ defaultValue: T;
12
+ }
13
+ export declare function createContext<T>(key: symbol, defaultValue: T): Context<T>;
14
+ export declare function provideContext<T>(host: HTMLElement, ctx: Context<T>, value: T): void;
15
+ export declare function consumeContext<T>(ctx: Context<T>, host?: HTMLElement): WritableSignal<T>;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @openelement/core - SignalContext DOM-tree-based cross-component signal sharing.
3
+ *
4
+ * v0.29.6: WeakMap replaces symbol-keyed DOM property stamping.
5
+ * Consumer walks parentElement / shadowRoot.host upward to find signals.
6
+ *
7
+ * @module @openelement/core/signal-context
8
+ */ import { signal } from '@openelement/signal';
9
+ const defaultSignals = new Map();
10
+ const hostSignals = new WeakMap();
11
+ export function createContext(key, defaultValue) {
12
+ const s = signal(defaultValue);
13
+ defaultSignals.set(key, s);
14
+ return {
15
+ key,
16
+ defaultValue
17
+ };
18
+ }
19
+ function getOrCreateHostSignal(host, ctx, initialValue) {
20
+ let map = hostSignals.get(host);
21
+ if (!map) {
22
+ map = new Map();
23
+ hostSignals.set(host, map);
24
+ }
25
+ let scoped = map.get(ctx.key);
26
+ if (!scoped) {
27
+ scoped = signal(initialValue);
28
+ map.set(ctx.key, scoped);
29
+ }
30
+ return scoped;
31
+ }
32
+ export function provideContext(host, ctx, value) {
33
+ const scoped = getOrCreateHostSignal(host, ctx, value);
34
+ scoped.value = value;
35
+ }
36
+ function findProvidedSignal(host, ctx) {
37
+ let current = host;
38
+ while(current){
39
+ const store = hostSignals.get(current);
40
+ if (store) {
41
+ const candidate = store.get(ctx.key);
42
+ if (candidate) return candidate;
43
+ }
44
+ current = current.parentNode;
45
+ if (!current) {
46
+ const root = host?.getRootNode?.();
47
+ current = root instanceof ShadowRoot ? root.host : null;
48
+ }
49
+ }
50
+ return undefined;
51
+ }
52
+ export function consumeContext(ctx, host) {
53
+ const scoped = findProvidedSignal(host, ctx);
54
+ if (scoped) return scoped;
55
+ const s = defaultSignals.get(ctx.key);
56
+ if (s) return s;
57
+ return signal(ctx.defaultValue);
58
+ }
59
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jb3JlL3NyYy9zaWduYWwtY29udGV4dC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBvcGVuZWxlbWVudC9jb3JlIC0gU2lnbmFsQ29udGV4dCBET00tdHJlZS1iYXNlZCBjcm9zcy1jb21wb25lbnQgc2lnbmFsIHNoYXJpbmcuXG4gKlxuICogdjAuMjkuNjogV2Vha01hcCByZXBsYWNlcyBzeW1ib2wta2V5ZWQgRE9NIHByb3BlcnR5IHN0YW1waW5nLlxuICogQ29uc3VtZXIgd2Fsa3MgcGFyZW50RWxlbWVudCAvIHNoYWRvd1Jvb3QuaG9zdCB1cHdhcmQgdG8gZmluZCBzaWduYWxzLlxuICpcbiAqIEBtb2R1bGUgQG9wZW5lbGVtZW50L2NvcmUvc2lnbmFsLWNvbnRleHRcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFdyaXRhYmxlU2lnbmFsIH0gZnJvbSAnQG9wZW5lbGVtZW50L3NpZ25hbCc7XG5pbXBvcnQgeyBzaWduYWwgfSBmcm9tICdAb3BlbmVsZW1lbnQvc2lnbmFsJztcblxuZXhwb3J0IGludGVyZmFjZSBDb250ZXh0PFQ+IHtcbiAga2V5OiBzeW1ib2w7XG4gIGRlZmF1bHRWYWx1ZTogVDtcbn1cblxuY29uc3QgZGVmYXVsdFNpZ25hbHMgPSBuZXcgTWFwPHN5bWJvbCwgV3JpdGFibGVTaWduYWw8dW5rbm93bj4+KCk7XG5jb25zdCBob3N0U2lnbmFscyA9IG5ldyBXZWFrTWFwPG9iamVjdCwgTWFwPHN5bWJvbCwgV3JpdGFibGVTaWduYWw8dW5rbm93bj4+PigpO1xuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29udGV4dDxUPihrZXk6IHN5bWJvbCwgZGVmYXVsdFZhbHVlOiBUKTogQ29udGV4dDxUPiB7XG4gIGNvbnN0IHMgPSBzaWduYWw8VD4oZGVmYXVsdFZhbHVlKTtcbiAgZGVmYXVsdFNpZ25hbHMuc2V0KGtleSwgcyk7XG4gIHJldHVybiB7IGtleSwgZGVmYXVsdFZhbHVlIH07XG59XG5cbmZ1bmN0aW9uIGdldE9yQ3JlYXRlSG9zdFNpZ25hbDxUPihcbiAgaG9zdDogb2JqZWN0LFxuICBjdHg6IENvbnRleHQ8VD4sXG4gIGluaXRpYWxWYWx1ZTogVCxcbik6IFdyaXRhYmxlU2lnbmFsPFQ+IHtcbiAgbGV0IG1hcCA9IGhvc3RTaWduYWxzLmdldChob3N0KTtcbiAgaWYgKCFtYXApIHtcbiAgICBtYXAgPSBuZXcgTWFwKCk7XG4gICAgaG9zdFNpZ25hbHMuc2V0KGhvc3QsIG1hcCk7XG4gIH1cbiAgbGV0IHNjb3BlZCA9IG1hcC5nZXQoY3R4LmtleSkgYXMgV3JpdGFibGVTaWduYWw8VD4gfCB1bmRlZmluZWQ7XG4gIGlmICghc2NvcGVkKSB7XG4gICAgc2NvcGVkID0gc2lnbmFsPFQ+KGluaXRpYWxWYWx1ZSk7XG4gICAgbWFwLnNldChjdHgua2V5LCBzY29wZWQgYXMgV3JpdGFibGVTaWduYWw8dW5rbm93bj4pO1xuICB9XG4gIHJldHVybiBzY29wZWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwcm92aWRlQ29udGV4dDxUPihcbiAgaG9zdDogSFRNTEVsZW1lbnQsXG4gIGN0eDogQ29udGV4dDxUPixcbiAgdmFsdWU6IFQsXG4pOiB2b2lkIHtcbiAgY29uc3Qgc2NvcGVkID0gZ2V0T3JDcmVhdGVIb3N0U2lnbmFsKGhvc3QsIGN0eCwgdmFsdWUpO1xuICBzY29wZWQudmFsdWUgPSB2YWx1ZTtcbn1cblxuZnVuY3Rpb24gZmluZFByb3ZpZGVkU2lnbmFsPFQ+KFxuICBob3N0OiBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZCxcbiAgY3R4OiBDb250ZXh0PFQ+LFxuKTogV3JpdGFibGVTaWduYWw8VD4gfCB1bmRlZmluZWQge1xuICBsZXQgY3VycmVudDogTm9kZSB8IG51bGwgfCB1bmRlZmluZWQgPSBob3N0O1xuICB3aGlsZSAoY3VycmVudCkge1xuICAgIGNvbnN0IHN0b3JlID0gaG9zdFNpZ25hbHMuZ2V0KGN1cnJlbnQgYXMgb2JqZWN0KTtcbiAgICBpZiAoc3RvcmUpIHtcbiAgICAgIGNvbnN0IGNhbmRpZGF0ZSA9IHN0b3JlLmdldChjdHgua2V5KTtcbiAgICAgIGlmIChjYW5kaWRhdGUpIHJldHVybiBjYW5kaWRhdGUgYXMgV3JpdGFibGVTaWduYWw8VD47XG4gICAgfVxuICAgIGN1cnJlbnQgPSBjdXJyZW50LnBhcmVudE5vZGU7XG4gICAgaWYgKCFjdXJyZW50KSB7XG4gICAgICBjb25zdCByb290ID0gaG9zdD8uZ2V0Um9vdE5vZGU/LigpO1xuICAgICAgY3VycmVudCA9IHJvb3QgaW5zdGFuY2VvZiBTaGFkb3dSb290ID8gcm9vdC5ob3N0IDogbnVsbDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnN1bWVDb250ZXh0PFQ+KFxuICBjdHg6IENvbnRleHQ8VD4sXG4gIGhvc3Q/OiBIVE1MRWxlbWVudCxcbik6IFdyaXRhYmxlU2lnbmFsPFQ+IHtcbiAgY29uc3Qgc2NvcGVkID0gZmluZFByb3ZpZGVkU2lnbmFsKGhvc3QsIGN0eCk7XG4gIGlmIChzY29wZWQpIHJldHVybiBzY29wZWQ7XG4gIGNvbnN0IHMgPSBkZWZhdWx0U2lnbmFscy5nZXQoY3R4LmtleSk7XG4gIGlmIChzKSByZXR1cm4gcyBhcyBXcml0YWJsZVNpZ25hbDxUPjtcbiAgcmV0dXJuIHNpZ25hbChjdHguZGVmYXVsdFZhbHVlKTtcbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7OztDQU9DLEdBR0QsU0FBUyxNQUFNLFFBQVEsc0JBQXNCO0FBTzdDLE1BQU0saUJBQWlCLElBQUk7QUFDM0IsTUFBTSxjQUFjLElBQUk7QUFFeEIsT0FBTyxTQUFTLGNBQWlCLEdBQVcsRUFBRSxZQUFlO0VBQzNELE1BQU0sSUFBSSxPQUFVO0VBQ3BCLGVBQWUsR0FBRyxDQUFDLEtBQUs7RUFDeEIsT0FBTztJQUFFO0lBQUs7RUFBYTtBQUM3QjtBQUVBLFNBQVMsc0JBQ1AsSUFBWSxFQUNaLEdBQWUsRUFDZixZQUFlO0VBRWYsSUFBSSxNQUFNLFlBQVksR0FBRyxDQUFDO0VBQzFCLElBQUksQ0FBQyxLQUFLO0lBQ1IsTUFBTSxJQUFJO0lBQ1YsWUFBWSxHQUFHLENBQUMsTUFBTTtFQUN4QjtFQUNBLElBQUksU0FBUyxJQUFJLEdBQUcsQ0FBQyxJQUFJLEdBQUc7RUFDNUIsSUFBSSxDQUFDLFFBQVE7SUFDWCxTQUFTLE9BQVU7SUFDbkIsSUFBSSxHQUFHLENBQUMsSUFBSSxHQUFHLEVBQUU7RUFDbkI7RUFDQSxPQUFPO0FBQ1Q7QUFFQSxPQUFPLFNBQVMsZUFDZCxJQUFpQixFQUNqQixHQUFlLEVBQ2YsS0FBUTtFQUVSLE1BQU0sU0FBUyxzQkFBc0IsTUFBTSxLQUFLO0VBQ2hELE9BQU8sS0FBSyxHQUFHO0FBQ2pCO0FBRUEsU0FBUyxtQkFDUCxJQUE2QixFQUM3QixHQUFlO0VBRWYsSUFBSSxVQUFtQztFQUN2QyxNQUFPLFFBQVM7SUFDZCxNQUFNLFFBQVEsWUFBWSxHQUFHLENBQUM7SUFDOUIsSUFBSSxPQUFPO01BQ1QsTUFBTSxZQUFZLE1BQU0sR0FBRyxDQUFDLElBQUksR0FBRztNQUNuQyxJQUFJLFdBQVcsT0FBTztJQUN4QjtJQUNBLFVBQVUsUUFBUSxVQUFVO0lBQzVCLElBQUksQ0FBQyxTQUFTO01BQ1osTUFBTSxPQUFPLE1BQU07TUFDbkIsVUFBVSxnQkFBZ0IsYUFBYSxLQUFLLElBQUksR0FBRztJQUNyRDtFQUNGO0VBQ0EsT0FBTztBQUNUO0FBRUEsT0FBTyxTQUFTLGVBQ2QsR0FBZSxFQUNmLElBQWtCO0VBRWxCLE1BQU0sU0FBUyxtQkFBbUIsTUFBTTtFQUN4QyxJQUFJLFFBQVEsT0FBTztFQUNuQixNQUFNLElBQUksZUFBZSxHQUFHLENBQUMsSUFBSSxHQUFHO0VBQ3BDLElBQUksR0FBRyxPQUFPO0VBQ2QsT0FBTyxPQUFPLElBQUksWUFBWTtBQUNoQyJ9
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @openelement/core/static - SSR/SSG runtime surface.
3
+ *
4
+ * Pure static rendering entry point. Contains everything needed to create
5
+ * VNodes and render them to DSD/HTML strings, without pulling in any DOM
6
+ * binding, effect, or hydration code.
7
+ *
8
+ * ADR-0109 Phase 1: split @openelement/core into static, hydrate, and csr.
9
+ */ export type { VNode } from '@openelement/protocol/vnode';
10
+ export { isVNode } from "./vnode.js";
11
+ export { For, Fragment, jsx, jsxDEV, jsxs, Show, trustedHtml } from "./jsx-runtime.js";
12
+ export { camelToKebab, renderDsdTree, serializeAttrs } from "./render-ir.js";
13
+ export { renderDsd } from "./render-dsd.js";
14
+ export { createRenderDsdStreamMetrics, renderDsdStream } from "./render-dsd-stream.js";
15
+ export type { RenderDsdStreamChunk, RenderDsdStreamComponent, RenderDsdStreamMetrics, RenderDsdStreamOptions } from "./render-dsd-stream.js";
16
+ export type { RenderDsdOptions } from "./render-dsd.js";
17
+ export { escapeAttr, escapeAttrValue, escapeHtml, renderSsrError, wrapInDocument } from "./html-escape.js";
18
+ export type { SafeHtml, UnsafeHtml } from '@openelement/protocol/framework';
19
+ export { DANGEROUS_KEYS } from "./security.js";
20
+ export { ERROR_PREFIX, ErrorCode, formatError, OpenElementError, PropValidationError, RenderError, reportError, setErrorTelemetryHook, SsrRenderError } from "./errors.js";
21
+ export type { ErrorPhase, ErrorSeverity, ErrorTelemetryHook } from '@openelement/protocol/errors';
22
+ export { createLogger } from "./logger.js";
23
+ export { disposeStaticProps, handleStaticPropAttributeChange, initializeStaticProps, normalizePropDecl, registerStaticObservedAttributes, syncStaticPropsFromAttributes, unwrap } from "./prop.js";
24
+ export type { NormalizedPropDecl, PropDecl, PropDeclFull, PropDeclShorthand, PropsFrom, PropType } from '@openelement/protocol/prop';
25
+ export { isSignalLike, unwrapSignalLike } from '@openelement/signal';
26
+ export type { SignalLike, Unsubscribe } from '@openelement/protocol/signal';
27
+ export { createSsrContext, extractParams, parseQuery } from "./context.js";
28
+ export type { IslandDescriptor, SsrContext } from '@openelement/protocol/context';
29
+ export { consumeContext, createContext, provideContext } from "./signal-context.js";
30
+ export type { Context } from "./signal-context.js";
31
+ export { isValidTagName } from "./tag-utils.js";
32
+ export { StyleSheet } from "./style-sheet.js";
33
+ export type { StyleSheetLike, StyleSheetRule } from '@openelement/protocol/style-sheet';
34
+ export { createEventMarkerContext, eventMarkerId, eventTypeFromProp, serializeEventMarkers } from "./event-marker.js";
35
+ export type { EventMarkerContext } from "./event-marker.js";
package/src/static.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @openelement/core/static - SSR/SSG runtime surface.
3
+ *
4
+ * Pure static rendering entry point. Contains everything needed to create
5
+ * VNodes and render them to DSD/HTML strings, without pulling in any DOM
6
+ * binding, effect, or hydration code.
7
+ *
8
+ * ADR-0109 Phase 1: split @openelement/core into static, hydrate, and csr.
9
+ */ // VNode / JSX runtime
10
+ export { isVNode } from './vnode.js';
11
+ export { For, Fragment, jsx, jsxDEV, jsxs, Show, trustedHtml } from './jsx-runtime.js';
12
+ // Static rendering (IR + DSD)
13
+ export { camelToKebab, renderDsdTree, serializeAttrs } from './render-ir.js';
14
+ export { renderDsd } from './render-dsd.js';
15
+ export { createRenderDsdStreamMetrics, renderDsdStream } from './render-dsd-stream.js';
16
+ // HTML escaping / document wrapping
17
+ export { escapeAttr, escapeAttrValue, escapeHtml, renderSsrError, wrapInDocument } from './html-escape.js';
18
+ // Security / errors / logging
19
+ export { DANGEROUS_KEYS } from './security.js';
20
+ export { ERROR_PREFIX, ErrorCode, formatError, OpenElementError, PropValidationError, RenderError, reportError, setErrorTelemetryHook, SsrRenderError } from './errors.js';
21
+ export { createLogger } from './logger.js';
22
+ // Static props runtime
23
+ export { disposeStaticProps, handleStaticPropAttributeChange, initializeStaticProps, normalizePropDecl, registerStaticObservedAttributes, syncStaticPropsFromAttributes, unwrap } from './prop.js';
24
+ // Signal utilities (neutral, no DOM)
25
+ export { isSignalLike, unwrapSignalLike } from '@openelement/signal';
26
+ // Context / request helpers
27
+ export { createSsrContext, extractParams, parseQuery } from './context.js';
28
+ export { consumeContext, createContext, provideContext } from './signal-context.js';
29
+ // Misc static utilities
30
+ export { isValidTagName } from './tag-utils.js';
31
+ export { StyleSheet } from './style-sheet.js';
32
+ // Event marker serialization (used by SSR; hydration lives in hydrate.ts)
33
+ export { createEventMarkerContext, eventMarkerId, eventTypeFromProp, serializeEventMarkers } from './event-marker.js';
34
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jb3JlL3NyYy9zdGF0aWMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAb3BlbmVsZW1lbnQvY29yZS9zdGF0aWMgLSBTU1IvU1NHIHJ1bnRpbWUgc3VyZmFjZS5cbiAqXG4gKiBQdXJlIHN0YXRpYyByZW5kZXJpbmcgZW50cnkgcG9pbnQuIENvbnRhaW5zIGV2ZXJ5dGhpbmcgbmVlZGVkIHRvIGNyZWF0ZVxuICogVk5vZGVzIGFuZCByZW5kZXIgdGhlbSB0byBEU0QvSFRNTCBzdHJpbmdzLCB3aXRob3V0IHB1bGxpbmcgaW4gYW55IERPTVxuICogYmluZGluZywgZWZmZWN0LCBvciBoeWRyYXRpb24gY29kZS5cbiAqXG4gKiBBRFItMDEwOSBQaGFzZSAxOiBzcGxpdCBAb3BlbmVsZW1lbnQvY29yZSBpbnRvIHN0YXRpYywgaHlkcmF0ZSwgYW5kIGNzci5cbiAqL1xuXG4vLyBWTm9kZSAvIEpTWCBydW50aW1lXG5leHBvcnQgdHlwZSB7IFZOb2RlIH0gZnJvbSAnQG9wZW5lbGVtZW50L3Byb3RvY29sL3Zub2RlJztcbmV4cG9ydCB7IGlzVk5vZGUgfSBmcm9tICcuL3Zub2RlLmpzJztcbmV4cG9ydCB7IEZvciwgRnJhZ21lbnQsIGpzeCwganN4REVWLCBqc3hzLCBTaG93LCB0cnVzdGVkSHRtbCB9IGZyb20gJy4vanN4LXJ1bnRpbWUuanMnO1xuXG4vLyBTdGF0aWMgcmVuZGVyaW5nIChJUiArIERTRClcbmV4cG9ydCB7IGNhbWVsVG9LZWJhYiwgcmVuZGVyRHNkVHJlZSwgc2VyaWFsaXplQXR0cnMgfSBmcm9tICcuL3JlbmRlci1pci5qcyc7XG5leHBvcnQgeyByZW5kZXJEc2QgfSBmcm9tICcuL3JlbmRlci1kc2QuanMnO1xuZXhwb3J0IHsgY3JlYXRlUmVuZGVyRHNkU3RyZWFtTWV0cmljcywgcmVuZGVyRHNkU3RyZWFtIH0gZnJvbSAnLi9yZW5kZXItZHNkLXN0cmVhbS5qcyc7XG5leHBvcnQgdHlwZSB7XG4gIFJlbmRlckRzZFN0cmVhbUNodW5rLFxuICBSZW5kZXJEc2RTdHJlYW1Db21wb25lbnQsXG4gIFJlbmRlckRzZFN0cmVhbU1ldHJpY3MsXG4gIFJlbmRlckRzZFN0cmVhbU9wdGlvbnMsXG59IGZyb20gJy4vcmVuZGVyLWRzZC1zdHJlYW0uanMnO1xuZXhwb3J0IHR5cGUgeyBSZW5kZXJEc2RPcHRpb25zIH0gZnJvbSAnLi9yZW5kZXItZHNkLmpzJztcblxuLy8gSFRNTCBlc2NhcGluZyAvIGRvY3VtZW50IHdyYXBwaW5nXG5leHBvcnQge1xuICBlc2NhcGVBdHRyLFxuICBlc2NhcGVBdHRyVmFsdWUsXG4gIGVzY2FwZUh0bWwsXG4gIHJlbmRlclNzckVycm9yLFxuICB3cmFwSW5Eb2N1bWVudCxcbn0gZnJvbSAnLi9odG1sLWVzY2FwZS5qcyc7XG5leHBvcnQgdHlwZSB7IFNhZmVIdG1sLCBVbnNhZmVIdG1sIH0gZnJvbSAnQG9wZW5lbGVtZW50L3Byb3RvY29sL2ZyYW1ld29yayc7XG5cbi8vIFNlY3VyaXR5IC8gZXJyb3JzIC8gbG9nZ2luZ1xuZXhwb3J0IHsgREFOR0VST1VTX0tFWVMgfSBmcm9tICcuL3NlY3VyaXR5LmpzJztcbmV4cG9ydCB7XG4gIEVSUk9SX1BSRUZJWCxcbiAgRXJyb3JDb2RlLFxuICBmb3JtYXRFcnJvcixcbiAgT3BlbkVsZW1lbnRFcnJvcixcbiAgUHJvcFZhbGlkYXRpb25FcnJvcixcbiAgUmVuZGVyRXJyb3IsXG4gIHJlcG9ydEVycm9yLFxuICBzZXRFcnJvclRlbGVtZXRyeUhvb2ssXG4gIFNzclJlbmRlckVycm9yLFxufSBmcm9tICcuL2Vycm9ycy5qcyc7XG5leHBvcnQgdHlwZSB7IEVycm9yUGhhc2UsIEVycm9yU2V2ZXJpdHksIEVycm9yVGVsZW1ldHJ5SG9vayB9IGZyb20gJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9lcnJvcnMnO1xuZXhwb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi9sb2dnZXIuanMnO1xuXG4vLyBTdGF0aWMgcHJvcHMgcnVudGltZVxuZXhwb3J0IHtcbiAgZGlzcG9zZVN0YXRpY1Byb3BzLFxuICBoYW5kbGVTdGF0aWNQcm9wQXR0cmlidXRlQ2hhbmdlLFxuICBpbml0aWFsaXplU3RhdGljUHJvcHMsXG4gIG5vcm1hbGl6ZVByb3BEZWNsLFxuICByZWdpc3RlclN0YXRpY09ic2VydmVkQXR0cmlidXRlcyxcbiAgc3luY1N0YXRpY1Byb3BzRnJvbUF0dHJpYnV0ZXMsXG4gIHVud3JhcCxcbn0gZnJvbSAnLi9wcm9wLmpzJztcbmV4cG9ydCB0eXBlIHtcbiAgTm9ybWFsaXplZFByb3BEZWNsLFxuICBQcm9wRGVjbCxcbiAgUHJvcERlY2xGdWxsLFxuICBQcm9wRGVjbFNob3J0aGFuZCxcbiAgUHJvcHNGcm9tLFxuICBQcm9wVHlwZSxcbn0gZnJvbSAnQG9wZW5lbGVtZW50L3Byb3RvY29sL3Byb3AnO1xuXG4vLyBTaWduYWwgdXRpbGl0aWVzIChuZXV0cmFsLCBubyBET00pXG5leHBvcnQgeyBpc1NpZ25hbExpa2UsIHVud3JhcFNpZ25hbExpa2UgfSBmcm9tICdAb3BlbmVsZW1lbnQvc2lnbmFsJztcbmV4cG9ydCB0eXBlIHsgU2lnbmFsTGlrZSwgVW5zdWJzY3JpYmUgfSBmcm9tICdAb3BlbmVsZW1lbnQvcHJvdG9jb2wvc2lnbmFsJztcblxuLy8gQ29udGV4dCAvIHJlcXVlc3QgaGVscGVyc1xuZXhwb3J0IHsgY3JlYXRlU3NyQ29udGV4dCwgZXh0cmFjdFBhcmFtcywgcGFyc2VRdWVyeSB9IGZyb20gJy4vY29udGV4dC5qcyc7XG5leHBvcnQgdHlwZSB7IElzbGFuZERlc2NyaXB0b3IsIFNzckNvbnRleHQgfSBmcm9tICdAb3BlbmVsZW1lbnQvcHJvdG9jb2wvY29udGV4dCc7XG5leHBvcnQgeyBjb25zdW1lQ29udGV4dCwgY3JlYXRlQ29udGV4dCwgcHJvdmlkZUNvbnRleHQgfSBmcm9tICcuL3NpZ25hbC1jb250ZXh0LmpzJztcbmV4cG9ydCB0eXBlIHsgQ29udGV4dCB9IGZyb20gJy4vc2lnbmFsLWNvbnRleHQuanMnO1xuXG4vLyBNaXNjIHN0YXRpYyB1dGlsaXRpZXNcbmV4cG9ydCB7IGlzVmFsaWRUYWdOYW1lIH0gZnJvbSAnLi90YWctdXRpbHMuanMnO1xuZXhwb3J0IHsgU3R5bGVTaGVldCB9IGZyb20gJy4vc3R5bGUtc2hlZXQuanMnO1xuZXhwb3J0IHR5cGUgeyBTdHlsZVNoZWV0TGlrZSwgU3R5bGVTaGVldFJ1bGUgfSBmcm9tICdAb3BlbmVsZW1lbnQvcHJvdG9jb2wvc3R5bGUtc2hlZXQnO1xuXG4vLyBFdmVudCBtYXJrZXIgc2VyaWFsaXphdGlvbiAodXNlZCBieSBTU1I7IGh5ZHJhdGlvbiBsaXZlcyBpbiBoeWRyYXRlLnRzKVxuZXhwb3J0IHtcbiAgY3JlYXRlRXZlbnRNYXJrZXJDb250ZXh0LFxuICBldmVudE1hcmtlcklkLFxuICBldmVudFR5cGVGcm9tUHJvcCxcbiAgc2VyaWFsaXplRXZlbnRNYXJrZXJzLFxufSBmcm9tICcuL2V2ZW50LW1hcmtlci5qcyc7XG5leHBvcnQgdHlwZSB7IEV2ZW50TWFya2VyQ29udGV4dCB9IGZyb20gJy4vZXZlbnQtbWFya2VyLmpzJztcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Q0FRQyxHQUVELHNCQUFzQjtBQUV0QixTQUFTLE9BQU8sUUFBUSxhQUFhO0FBQ3JDLFNBQVMsR0FBRyxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsV0FBVyxRQUFRLG1CQUFtQjtBQUV2Riw4QkFBOEI7QUFDOUIsU0FBUyxZQUFZLEVBQUUsYUFBYSxFQUFFLGNBQWMsUUFBUSxpQkFBaUI7QUFDN0UsU0FBUyxTQUFTLFFBQVEsa0JBQWtCO0FBQzVDLFNBQVMsNEJBQTRCLEVBQUUsZUFBZSxRQUFRLHlCQUF5QjtBQVN2RixvQ0FBb0M7QUFDcEMsU0FDRSxVQUFVLEVBQ1YsZUFBZSxFQUNmLFVBQVUsRUFDVixjQUFjLEVBQ2QsY0FBYyxRQUNULG1CQUFtQjtBQUcxQiw4QkFBOEI7QUFDOUIsU0FBUyxjQUFjLFFBQVEsZ0JBQWdCO0FBQy9DLFNBQ0UsWUFBWSxFQUNaLFNBQVMsRUFDVCxXQUFXLEVBQ1gsZ0JBQWdCLEVBQ2hCLG1CQUFtQixFQUNuQixXQUFXLEVBQ1gsV0FBVyxFQUNYLHFCQUFxQixFQUNyQixjQUFjLFFBQ1QsY0FBYztBQUVyQixTQUFTLFlBQVksUUFBUSxjQUFjO0FBRTNDLHVCQUF1QjtBQUN2QixTQUNFLGtCQUFrQixFQUNsQiwrQkFBK0IsRUFDL0IscUJBQXFCLEVBQ3JCLGlCQUFpQixFQUNqQixnQ0FBZ0MsRUFDaEMsNkJBQTZCLEVBQzdCLE1BQU0sUUFDRCxZQUFZO0FBVW5CLHFDQUFxQztBQUNyQyxTQUFTLFlBQVksRUFBRSxnQkFBZ0IsUUFBUSxzQkFBc0I7QUFHckUsNEJBQTRCO0FBQzVCLFNBQVMsZ0JBQWdCLEVBQUUsYUFBYSxFQUFFLFVBQVUsUUFBUSxlQUFlO0FBRTNFLFNBQVMsY0FBYyxFQUFFLGFBQWEsRUFBRSxjQUFjLFFBQVEsc0JBQXNCO0FBR3BGLHdCQUF3QjtBQUN4QixTQUFTLGNBQWMsUUFBUSxpQkFBaUI7QUFDaEQsU0FBUyxVQUFVLFFBQVEsbUJBQW1CO0FBRzlDLDBFQUEwRTtBQUMxRSxTQUNFLHdCQUF3QixFQUN4QixhQUFhLEVBQ2IsaUJBQWlCLEVBQ2pCLHFCQUFxQixRQUNoQixvQkFBb0IifQ==
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Cross-environment CSSStyleSheet abstraction.
3
+ *
4
+ * In browsers this delegates to the native CSSStyleSheet API. In SSR runtimes
5
+ * it falls back to a minimal in-memory implementation that exposes the subset
6
+ * used by OpenElement and renderDsd().
7
+ */ import type { StyleSheetLike, StyleSheetRule } from '@openelement/protocol/style-sheet';
8
+ export type { StyleSheetLike, StyleSheetRule };
9
+ export declare const StyleSheet: new() => StyleSheetLike;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Cross-environment CSSStyleSheet abstraction.
3
+ *
4
+ * In browsers this delegates to the native CSSStyleSheet API. In SSR runtimes
5
+ * it falls back to a minimal in-memory implementation that exposes the subset
6
+ * used by OpenElement and renderDsd().
7
+ */ function parseRules(css) {
8
+ const rules = [];
9
+ let i = 0;
10
+ const len = css.length;
11
+ while(i < len){
12
+ while(i < len && /\s/.test(css[i]))i++;
13
+ if (i >= len) break;
14
+ if (css[i] === '/' && css[i + 1] === '*') {
15
+ const end = css.indexOf('*/', i + 2);
16
+ if (end === -1) break;
17
+ i = end + 2;
18
+ continue;
19
+ }
20
+ const openBrace = css.indexOf('{', i);
21
+ if (openBrace === -1) break;
22
+ let depth = 0;
23
+ let j = openBrace;
24
+ while(j < len){
25
+ if (css[j] === '{') depth++;
26
+ else if (css[j] === '}') {
27
+ depth--;
28
+ if (depth === 0) break;
29
+ }
30
+ j++;
31
+ }
32
+ if (depth !== 0) break;
33
+ const ruleText = css.substring(i, j + 1).trim();
34
+ if (ruleText) rules.push({
35
+ cssText: ruleText
36
+ });
37
+ i = j + 1;
38
+ }
39
+ if (rules.length === 0 && css.trim()) {
40
+ rules.push({
41
+ cssText: css.trim()
42
+ });
43
+ }
44
+ return rules;
45
+ }
46
+ class ShimStyleSheet {
47
+ #rules = [];
48
+ get cssRules() {
49
+ return this.#rules;
50
+ }
51
+ replaceSync(text) {
52
+ this.#rules = parseRules(text);
53
+ }
54
+ }
55
+ export const StyleSheet = typeof globalThis.CSSStyleSheet === 'function' ? globalThis.CSSStyleSheet : ShimStyleSheet;
56
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jb3JlL3NyYy9zdHlsZS1zaGVldC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENyb3NzLWVudmlyb25tZW50IENTU1N0eWxlU2hlZXQgYWJzdHJhY3Rpb24uXG4gKlxuICogSW4gYnJvd3NlcnMgdGhpcyBkZWxlZ2F0ZXMgdG8gdGhlIG5hdGl2ZSBDU1NTdHlsZVNoZWV0IEFQSS4gSW4gU1NSIHJ1bnRpbWVzXG4gKiBpdCBmYWxscyBiYWNrIHRvIGEgbWluaW1hbCBpbi1tZW1vcnkgaW1wbGVtZW50YXRpb24gdGhhdCBleHBvc2VzIHRoZSBzdWJzZXRcbiAqIHVzZWQgYnkgT3BlbkVsZW1lbnQgYW5kIHJlbmRlckRzZCgpLlxuICovXG5cbmltcG9ydCB0eXBlIHsgU3R5bGVTaGVldExpa2UsIFN0eWxlU2hlZXRSdWxlIH0gZnJvbSAnQG9wZW5lbGVtZW50L3Byb3RvY29sL3N0eWxlLXNoZWV0JztcbmV4cG9ydCB0eXBlIHsgU3R5bGVTaGVldExpa2UsIFN0eWxlU2hlZXRSdWxlIH07XG5cbmZ1bmN0aW9uIHBhcnNlUnVsZXMoY3NzOiBzdHJpbmcpOiBTdHlsZVNoZWV0UnVsZVtdIHtcbiAgY29uc3QgcnVsZXM6IFN0eWxlU2hlZXRSdWxlW10gPSBbXTtcbiAgbGV0IGkgPSAwO1xuICBjb25zdCBsZW4gPSBjc3MubGVuZ3RoO1xuXG4gIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgd2hpbGUgKGkgPCBsZW4gJiYgL1xccy8udGVzdChjc3NbaV0pKSBpKys7XG4gICAgaWYgKGkgPj0gbGVuKSBicmVhaztcblxuICAgIGlmIChjc3NbaV0gPT09ICcvJyAmJiBjc3NbaSArIDFdID09PSAnKicpIHtcbiAgICAgIGNvbnN0IGVuZCA9IGNzcy5pbmRleE9mKCcqLycsIGkgKyAyKTtcbiAgICAgIGlmIChlbmQgPT09IC0xKSBicmVhaztcbiAgICAgIGkgPSBlbmQgKyAyO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3Qgb3BlbkJyYWNlID0gY3NzLmluZGV4T2YoJ3snLCBpKTtcbiAgICBpZiAob3BlbkJyYWNlID09PSAtMSkgYnJlYWs7XG5cbiAgICBsZXQgZGVwdGggPSAwO1xuICAgIGxldCBqID0gb3BlbkJyYWNlO1xuICAgIHdoaWxlIChqIDwgbGVuKSB7XG4gICAgICBpZiAoY3NzW2pdID09PSAneycpIGRlcHRoKys7XG4gICAgICBlbHNlIGlmIChjc3Nbal0gPT09ICd9Jykge1xuICAgICAgICBkZXB0aC0tO1xuICAgICAgICBpZiAoZGVwdGggPT09IDApIGJyZWFrO1xuICAgICAgfVxuICAgICAgaisrO1xuICAgIH1cbiAgICBpZiAoZGVwdGggIT09IDApIGJyZWFrO1xuXG4gICAgY29uc3QgcnVsZVRleHQgPSBjc3Muc3Vic3RyaW5nKGksIGogKyAxKS50cmltKCk7XG4gICAgaWYgKHJ1bGVUZXh0KSBydWxlcy5wdXNoKHsgY3NzVGV4dDogcnVsZVRleHQgfSk7XG4gICAgaSA9IGogKyAxO1xuICB9XG5cbiAgaWYgKHJ1bGVzLmxlbmd0aCA9PT0gMCAmJiBjc3MudHJpbSgpKSB7XG4gICAgcnVsZXMucHVzaCh7IGNzc1RleHQ6IGNzcy50cmltKCkgfSk7XG4gIH1cbiAgcmV0dXJuIHJ1bGVzO1xufVxuXG5jbGFzcyBTaGltU3R5bGVTaGVldCBpbXBsZW1lbnRzIFN0eWxlU2hlZXRMaWtlIHtcbiAgI3J1bGVzOiBTdHlsZVNoZWV0UnVsZVtdID0gW107XG5cbiAgZ2V0IGNzc1J1bGVzKCk6IFN0eWxlU2hlZXRSdWxlW10ge1xuICAgIHJldHVybiB0aGlzLiNydWxlcztcbiAgfVxuXG4gIHJlcGxhY2VTeW5jKHRleHQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuI3J1bGVzID0gcGFyc2VSdWxlcyh0ZXh0KTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgU3R5bGVTaGVldDogbmV3ICgpID0+IFN0eWxlU2hlZXRMaWtlID0gdHlwZW9mIGdsb2JhbFRoaXMuQ1NTU3R5bGVTaGVldCA9PT0gJ2Z1bmN0aW9uJ1xuICA/IGdsb2JhbFRoaXMuQ1NTU3R5bGVTaGVldCBhcyB1bmtub3duIGFzIG5ldyAoKSA9PiBTdHlsZVNoZWV0TGlrZVxuICA6IFNoaW1TdHlsZVNoZWV0O1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Q0FNQyxHQUtELFNBQVMsV0FBVyxHQUFXO0VBQzdCLE1BQU0sUUFBMEIsRUFBRTtFQUNsQyxJQUFJLElBQUk7RUFDUixNQUFNLE1BQU0sSUFBSSxNQUFNO0VBRXRCLE1BQU8sSUFBSSxJQUFLO0lBQ2QsTUFBTyxJQUFJLE9BQU8sS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRztJQUNyQyxJQUFJLEtBQUssS0FBSztJQUVkLElBQUksR0FBRyxDQUFDLEVBQUUsS0FBSyxPQUFPLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxLQUFLO01BQ3hDLE1BQU0sTUFBTSxJQUFJLE9BQU8sQ0FBQyxNQUFNLElBQUk7TUFDbEMsSUFBSSxRQUFRLENBQUMsR0FBRztNQUNoQixJQUFJLE1BQU07TUFDVjtJQUNGO0lBRUEsTUFBTSxZQUFZLElBQUksT0FBTyxDQUFDLEtBQUs7SUFDbkMsSUFBSSxjQUFjLENBQUMsR0FBRztJQUV0QixJQUFJLFFBQVE7SUFDWixJQUFJLElBQUk7SUFDUixNQUFPLElBQUksSUFBSztNQUNkLElBQUksR0FBRyxDQUFDLEVBQUUsS0FBSyxLQUFLO1dBQ2YsSUFBSSxHQUFHLENBQUMsRUFBRSxLQUFLLEtBQUs7UUFDdkI7UUFDQSxJQUFJLFVBQVUsR0FBRztNQUNuQjtNQUNBO0lBQ0Y7SUFDQSxJQUFJLFVBQVUsR0FBRztJQUVqQixNQUFNLFdBQVcsSUFBSSxTQUFTLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSTtJQUM3QyxJQUFJLFVBQVUsTUFBTSxJQUFJLENBQUM7TUFBRSxTQUFTO0lBQVM7SUFDN0MsSUFBSSxJQUFJO0VBQ1Y7RUFFQSxJQUFJLE1BQU0sTUFBTSxLQUFLLEtBQUssSUFBSSxJQUFJLElBQUk7SUFDcEMsTUFBTSxJQUFJLENBQUM7TUFBRSxTQUFTLElBQUksSUFBSTtJQUFHO0VBQ25DO0VBQ0EsT0FBTztBQUNUO0FBRUEsTUFBTTtFQUNKLENBQUEsS0FBTSxHQUFxQixFQUFFLENBQUM7RUFFOUIsSUFBSSxXQUE2QjtJQUMvQixPQUFPLElBQUksQ0FBQyxDQUFBLEtBQU07RUFDcEI7RUFFQSxZQUFZLElBQVksRUFBUTtJQUM5QixJQUFJLENBQUMsQ0FBQSxLQUFNLEdBQUcsV0FBVztFQUMzQjtBQUNGO0FBRUEsT0FBTyxNQUFNLGFBQXVDLE9BQU8sV0FBVyxhQUFhLEtBQUssYUFDcEYsV0FBVyxhQUFhLEdBQ3hCLGVBQWUifQ==
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @openelement/core — Tag name validation utility.
3
+ *
4
+ * Validates custom element tag names per HTML spec:
5
+ * - Must contain at least one hyphen
6
+ * - Must start with a lowercase letter
7
+ * - Only lowercase letters, digits, and hyphens allowed
8
+ * - Must not be a reserved name
9
+ *
10
+ * @module @openelement/core/tag-utils
11
+ */ /** Check if a tag name is a valid custom element name per HTML spec. */ export declare function isValidTagName(tagName: string): boolean;