@shapeshift-labs/frontier-lang-compiler 0.2.174 → 0.2.176

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.
@@ -151,7 +151,7 @@ function duplicateExplicitIdentityKeys(evidence) {
151
151
  }
152
152
 
153
153
  const ScopedCascadeMissingProofReasonCodes = new Set(['css-scoped-cascade-equivalence-unproved', 'css-media-cascade-scope-unproved', 'css-supports-cascade-scope-unproved', 'css-container-cascade-scope-unproved', 'css-layer-cascade-scope-unproved', 'css-scope-cascade-scope-unproved']);
154
- const HtmlRuntimeBoundaryReasonCodes = new Set(['script-runtime-boundary', 'style-runtime-boundary', 'template-runtime-boundary', 'slot-runtime-boundary', 'custom-element-runtime-boundary', 'event-handler-runtime-boundary', 'inline-style-runtime-boundary', 'iframe-runtime-boundary', 'iframe-srcdoc-runtime-boundary']);
154
+ const HtmlRuntimeBoundaryReasonCodes = new Set(['script-runtime-boundary', 'style-runtime-boundary', 'template-runtime-boundary', 'slot-runtime-boundary', 'custom-element-runtime-boundary', 'event-handler-runtime-boundary', 'inline-style-runtime-boundary', 'iframe-runtime-boundary', 'iframe-srcdoc-runtime-boundary', 'form-runtime-boundary', 'form-submitter-runtime-boundary', 'form-control-runtime-boundary', 'document-base-runtime-boundary', 'document-metadata-runtime-boundary', 'resource-loading-runtime-boundary']);
155
155
  const HtmlFrameworkBoundaryReasonCodes = new Set(['framework-directive-boundary', 'custom-element-runtime-boundary']);
156
156
  const CssDependencyMissingProofReasonCodes = new Set(['css-dependency-graph-evidence-missing', 'css-custom-property-dependency-graph-unproved', 'css-var-fallback-dependency-graph-unproved', 'css-animation-name-keyframes-graph-unproved', 'css-font-face-dependency-graph-unproved', 'css-url-asset-dependency-graph-unproved']);
157
157
  const CssDependencyAtRuleNames = new Set(['keyframes', 'font-face']);
@@ -2,6 +2,7 @@ import { safeMergeCssSource } from '@shapeshift-labs/frontier-lang-css';
2
2
  import { safeMergeHtmlSource } from '@shapeshift-labs/frontier-lang-html';
3
3
  import { compactRecord } from './js-ts-safe-merge-context.js';
4
4
  import { hashText, safeId, uniqueStrings } from './js-ts-safe-project-merge-core.js';
5
+ import { htmlRuntimeBoundaryChanges, htmlRuntimeBoundaryProofForChange, htmlRuntimeBoundaryProofRecord, htmlRuntimeBoundaryProvenResult } from './js-ts-safe-project-merge-html-runtime-boundaries.js';
5
6
 
6
7
  function projectFileLanguage(file, input) {
7
8
  return file.language ?? inferLanguageFromPath(file.sourcePath) ?? input.language ?? 'typescript';
@@ -103,140 +104,10 @@ function duplicateHtmlExplicitIdentityKeys(identityEvidence) {
103
104
  });
104
105
  }
105
106
 
106
- function htmlRuntimeBoundaryChanges(base, worker, head) {
107
- const baseEventHandlers = htmlEventHandlerBoundaryFingerprint(base);
108
- return [
109
- htmlRuntimeBoundaryChange('worker', base, worker, baseEventHandlers),
110
- htmlRuntimeBoundaryChange('head', base, head, baseEventHandlers)
111
- ].filter(Boolean);
112
- }
113
-
114
- function htmlRuntimeBoundaryChange(side, base, sourceText, baseEventHandlers) {
115
- if (sourceText === base) return undefined;
116
- const eventHandlers = htmlEventHandlerBoundaryFingerprint(sourceText);
117
- if (eventHandlers === baseEventHandlers) return undefined;
118
- return {
119
- side,
120
- reasonCode: 'event-handler-runtime-boundary',
121
- boundary: 'html-event-handler-attribute',
122
- boundaryAttributes: htmlEventHandlerBoundaryAttributeNames(sourceText)
123
- };
124
- }
125
-
126
- function htmlRuntimeBoundaryProofForChange(proofs, change, binding) {
127
- return proofs.find((proof) => isHtmlRuntimeBoundaryProofForChange(proof, change, binding));
128
- }
129
-
130
- function isHtmlRuntimeBoundaryProofForChange(proof, change, binding) {
131
- return Boolean(proof && typeof proof === 'object') &&
132
- HtmlRuntimeBoundaryProofKinds.has(proof.kind) &&
133
- proof.status === 'passed' &&
134
- proof.sourcePath === binding.sourcePath &&
135
- htmlProofCoversValue(proof.reasonCode, proof.reasonCodes, change.reasonCode) &&
136
- htmlProofCoversValue(proof.side, proof.sides, change.side) &&
137
- proof.boundary === change.boundary &&
138
- sameStringSet(proof.boundaryAttributes ?? proof.changedBoundaryAttributes, change.boundaryAttributes) &&
139
- htmlRuntimeBoundaryProofSourceBound(proof, binding);
140
- }
141
-
142
- function htmlRuntimeBoundaryProofSourceBound(proof, binding) {
143
- return htmlRuntimeBoundaryProofSourceMatches(proof, 'base', binding.base) &&
144
- htmlRuntimeBoundaryProofSourceMatches(proof, 'worker', binding.worker) &&
145
- htmlRuntimeBoundaryProofSourceMatches(proof, 'head', binding.head) &&
146
- htmlRuntimeBoundaryProofSourceMatches(proof, 'output', binding.output);
147
- }
148
-
149
- function htmlRuntimeBoundaryProofSourceMatches(proof, role, sourceText) {
150
- if (typeof sourceText !== 'string') return false;
151
- const hash = hashText(sourceText);
152
- const textFields = role === 'output' ? ['outputSourceText', 'mergedSourceText'] : [`${role}SourceText`];
153
- const hashFields = role === 'output' ? ['outputSourceHash', 'mergedSourceHash'] : [`${role}SourceHash`];
154
- const aliases = role === 'output' ? ['output', 'merged'] : [role];
155
- return textFields.some((field) => proof[field] === sourceText) ||
156
- aliases.some((alias) => proof.sourceTexts?.[alias] === sourceText || proof.sources?.[alias] === sourceText) ||
157
- hashFields.some((field) => proof[field] === hash) ||
158
- aliases.some((alias) => proof.sourceHashes?.[alias] === hash || proof.hashes?.[alias] === hash);
159
- }
160
-
161
- function htmlRuntimeBoundaryProofRecord(proof, change, binding) {
162
- return compactRecord({
163
- id: proof.id,
164
- kind: proof.kind,
165
- status: 'passed',
166
- proofLevel: proof.proofLevel ?? 'html-runtime-boundary-source-bound',
167
- reasonCode: change.reasonCode,
168
- side: change.side,
169
- boundary: change.boundary,
170
- boundaryAttributes: change.boundaryAttributes,
171
- sourcePath: binding.sourcePath,
172
- baseSourceHash: hashText(binding.base),
173
- workerSourceHash: hashText(binding.worker),
174
- headSourceHash: hashText(binding.head),
175
- outputSourceHash: hashText(binding.output)
176
- });
177
- }
178
-
179
- function htmlRuntimeBoundaryProvenResult(result, runtimeBoundaryProofs) {
180
- return compactRecord({
181
- ...result,
182
- runtimeBoundaryProofs,
183
- browserRuntimeEquivalenceClaim: true,
184
- admission: compactRecord({
185
- ...(result.admission ?? {}),
186
- browserRuntimeEquivalenceClaim: true,
187
- htmlRuntimeBoundaryProofs: runtimeBoundaryProofs,
188
- reasonCodes: uniqueStrings([...(result.admission?.reasonCodes ?? []), 'html-runtime-boundary-source-bound'])
189
- })
190
- });
191
- }
192
-
193
- function htmlEventHandlerBoundaryFingerprint(sourceText) {
194
- return htmlEventHandlerBoundaryAttributes(sourceText)
195
- .map((attribute) => `${attribute.tagName}:${attribute.name}=${String(attribute.value)}`)
196
- .sort()
197
- .join('\n');
198
- }
199
-
200
- function htmlEventHandlerBoundaryAttributeNames(sourceText) {
201
- return uniqueStrings(htmlEventHandlerBoundaryAttributes(sourceText).map((attribute) => attribute.name));
202
- }
203
-
204
- function htmlEventHandlerBoundaryAttributes(sourceText) {
205
- const attributes = [];
206
- for (const tag of String(sourceText ?? '').matchAll(/<[A-Za-z][\w:-]*(?:\s+[^<>]*?)?\/?>/g)) {
207
- const parsed = /^<([A-Za-z][\w:-]*)([\s\S]*?)\/?>$/.exec(tag[0]);
208
- if (!parsed) continue;
209
- const tagName = parsed[1].toLowerCase();
210
- for (const attribute of parseHtmlAttributes(parsed[2] ?? '')) {
211
- if (/^on[\w:.-]+$/i.test(attribute.name)) attributes.push({ ...attribute, name: attribute.name.toLowerCase(), tagName });
212
- }
213
- }
214
- return attributes;
215
- }
216
-
217
- function parseHtmlAttributes(text) {
218
- const attributes = [];
219
- const pattern = /([:@A-Za-z_][\w:.-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
220
- for (const match of text.matchAll(pattern)) attributes.push({ name: match[1], value: match[2] ?? match[3] ?? match[4] ?? true });
221
- return attributes;
222
- }
223
-
224
- function htmlProofCoversValue(value, values, expected) {
225
- return value === expected || (Array.isArray(values) && values.includes(expected));
226
- }
227
-
228
- function sameStringSet(actual, expected) {
229
- const actualSet = uniqueStrings(asArray(actual).map((value) => String(value)));
230
- const expectedSet = uniqueStrings(asArray(expected).map((value) => String(value)));
231
- return actualSet.length === expectedSet.length && expectedSet.every((value) => actualSet.includes(value));
232
- }
233
-
234
107
  function asArray(value) {
235
108
  return Array.isArray(value) ? value : value === undefined ? [] : [value];
236
109
  }
237
110
 
238
- const HtmlRuntimeBoundaryProofKinds = new Set(['html-runtime-boundary-proof', 'html-source-bound-runtime-boundary-proof']);
239
-
240
111
  function htmlProofGapConflict(id, sourcePath, reasonCode, details = {}, code = 'html-proof-gap-blocked') {
241
112
  return {
242
113
  code,
@@ -263,6 +134,12 @@ function htmlProofGapSummary(reasonCode) {
263
134
  if (reasonCode === 'event-handler-runtime-boundary') return 'HTML event handler attributes execute in the browser runtime and require source-bound host evidence.';
264
135
  if (reasonCode === 'inline-style-runtime-boundary') return 'HTML inline style attributes affect browser cascade and rendering and require source-bound host evidence.';
265
136
  if (reasonCode === 'iframe-runtime-boundary' || reasonCode === 'iframe-srcdoc-runtime-boundary') return reasonCode === 'iframe-runtime-boundary' ? 'HTML iframe runtime attributes affect nested browsing-context execution and require source-bound host evidence.' : 'HTML iframe srcdoc attributes define nested browsing-context content and require source-bound host evidence.';
137
+ if (reasonCode === 'form-runtime-boundary') return 'HTML form runtime attributes affect submission, navigation, encoding, or validation and require source-bound host evidence.';
138
+ if (reasonCode === 'form-submitter-runtime-boundary') return 'HTML submitter attributes affect form submission behavior and require source-bound host evidence.';
139
+ if (reasonCode === 'form-control-runtime-boundary') return 'HTML form-control attributes affect user input, validation, state, or submission data and require source-bound host evidence.';
140
+ if (reasonCode === 'document-base-runtime-boundary') return 'HTML base attributes affect URL resolution or navigation targets and require source-bound host evidence.';
141
+ if (reasonCode === 'document-metadata-runtime-boundary') return 'HTML metadata attributes can affect document loading, policy, refresh, viewport, or discovery behavior and require source-bound host evidence.';
142
+ if (reasonCode === 'resource-loading-runtime-boundary') return 'HTML resource-loading attributes affect fetched resources, selection, privacy, media behavior, or layout and require source-bound host evidence.';
266
143
  return 'HTML proof gap requires source-bound evidence before structural merge admission.';
267
144
  }
268
145
 
@@ -271,6 +148,8 @@ function htmlProofGapNextProof(reasonCode) {
271
148
  if (reasonCode === 'event-handler-runtime-boundary') return 'Attach htmlRuntimeBoundaryProofsByPath[sourcePath] with kind html-source-bound-runtime-boundary-proof, status passed, sourcePath, reasonCode, side, boundary, boundaryAttributes, and exact base/worker/head/output source text or hashes.';
272
149
  if (reasonCode === 'inline-style-runtime-boundary') return 'Attach htmlRuntimeBoundaryProofsByPath[sourcePath] with kind html-source-bound-runtime-boundary-proof, status passed, sourcePath, reasonCode, side, boundary "html-inline-style-attribute", boundaryAttributes ["style"], and exact base/worker/head/output source text or hashes.';
273
150
  if (reasonCode === 'iframe-runtime-boundary' || reasonCode === 'iframe-srcdoc-runtime-boundary') return 'Attach htmlRuntimeBoundaryProofsByPath[sourcePath] with kind html-source-bound-runtime-boundary-proof, status passed, sourcePath, reasonCode, side, boundary, boundaryAttributes, and exact base/worker/head/output source text or hashes.';
151
+ if (reasonCode === 'form-runtime-boundary' || reasonCode === 'form-submitter-runtime-boundary' || reasonCode === 'form-control-runtime-boundary') return 'Attach htmlRuntimeBoundaryProofsByPath[sourcePath] with kind html-source-bound-runtime-boundary-proof, status passed, sourcePath, reasonCode, side, boundary, boundaryAttributes, and exact base/worker/head/output source text or hashes.';
152
+ if (reasonCode === 'document-base-runtime-boundary' || reasonCode === 'document-metadata-runtime-boundary' || reasonCode === 'resource-loading-runtime-boundary') return 'Attach htmlRuntimeBoundaryProofsByPath[sourcePath] with kind html-source-bound-runtime-boundary-proof, status passed, sourcePath, reasonCode, side, boundary, boundaryAttributes, and exact base/worker/head/output source text or hashes.';
274
153
  return 'Attach source-bound HTML parser, identity, and runtime-boundary evidence for the changed file before structural admission.';
275
154
  }
276
155
 
@@ -0,0 +1,181 @@
1
+ import { compactRecord } from './js-ts-safe-merge-context.js';
2
+ import { hashText, uniqueStrings } from './js-ts-safe-project-merge-core.js';
3
+
4
+ function htmlRuntimeBoundaryChanges(base, worker, head) {
5
+ const baseBoundaries = htmlRuntimeBoundaryAttributeGroups(base);
6
+ return [
7
+ ...htmlRuntimeBoundaryChangesForSide('worker', baseBoundaries, htmlRuntimeBoundaryAttributeGroups(worker)),
8
+ ...htmlRuntimeBoundaryChangesForSide('head', baseBoundaries, htmlRuntimeBoundaryAttributeGroups(head))
9
+ ];
10
+ }
11
+
12
+ function htmlRuntimeBoundaryChangesForSide(side, baseGroups, currentGroups) {
13
+ return uniqueStrings([...baseGroups.keys(), ...currentGroups.keys()]).flatMap((key) => {
14
+ const before = baseGroups.get(key);
15
+ const after = currentGroups.get(key);
16
+ if ((before?.fingerprint ?? '') === (after?.fingerprint ?? '')) return [];
17
+ const sample = after ?? before;
18
+ return [{
19
+ side,
20
+ reasonCode: sample.reasonCode,
21
+ boundary: sample.boundary,
22
+ boundaryAttributes: changedHtmlRuntimeBoundaryAttributes(before?.records ?? [], after?.records ?? [])
23
+ }];
24
+ });
25
+ }
26
+
27
+ function htmlRuntimeBoundaryProofForChange(proofs, change, binding) {
28
+ return proofs.find((proof) => isHtmlRuntimeBoundaryProofForChange(proof, change, binding));
29
+ }
30
+
31
+ function isHtmlRuntimeBoundaryProofForChange(proof, change, binding) {
32
+ return Boolean(proof && typeof proof === 'object') &&
33
+ HtmlRuntimeBoundaryProofKinds.has(proof.kind) &&
34
+ proof.status === 'passed' &&
35
+ proof.sourcePath === binding.sourcePath &&
36
+ htmlProofCoversValue(proof.reasonCode, proof.reasonCodes, change.reasonCode) &&
37
+ htmlProofCoversValue(proof.side, proof.sides, change.side) &&
38
+ proof.boundary === change.boundary &&
39
+ sameStringSet(proof.boundaryAttributes ?? proof.changedBoundaryAttributes, change.boundaryAttributes) &&
40
+ htmlRuntimeBoundaryProofSourceBound(proof, binding);
41
+ }
42
+
43
+ function htmlRuntimeBoundaryProofSourceBound(proof, binding) {
44
+ return htmlRuntimeBoundaryProofSourceMatches(proof, 'base', binding.base) &&
45
+ htmlRuntimeBoundaryProofSourceMatches(proof, 'worker', binding.worker) &&
46
+ htmlRuntimeBoundaryProofSourceMatches(proof, 'head', binding.head) &&
47
+ htmlRuntimeBoundaryProofSourceMatches(proof, 'output', binding.output);
48
+ }
49
+
50
+ function htmlRuntimeBoundaryProofSourceMatches(proof, role, sourceText) {
51
+ if (typeof sourceText !== 'string') return false;
52
+ const hash = hashText(sourceText);
53
+ const textFields = role === 'output' ? ['outputSourceText', 'mergedSourceText'] : [`${role}SourceText`];
54
+ const hashFields = role === 'output' ? ['outputSourceHash', 'mergedSourceHash'] : [`${role}SourceHash`];
55
+ const aliases = role === 'output' ? ['output', 'merged'] : [role];
56
+ return textFields.some((field) => proof[field] === sourceText) ||
57
+ aliases.some((alias) => proof.sourceTexts?.[alias] === sourceText || proof.sources?.[alias] === sourceText) ||
58
+ hashFields.some((field) => proof[field] === hash) ||
59
+ aliases.some((alias) => proof.sourceHashes?.[alias] === hash || proof.hashes?.[alias] === hash);
60
+ }
61
+
62
+ function htmlRuntimeBoundaryProofRecord(proof, change, binding) {
63
+ return compactRecord({
64
+ id: proof.id,
65
+ kind: proof.kind,
66
+ status: 'passed',
67
+ proofLevel: proof.proofLevel ?? 'html-runtime-boundary-source-bound',
68
+ reasonCode: change.reasonCode,
69
+ side: change.side,
70
+ boundary: change.boundary,
71
+ boundaryAttributes: change.boundaryAttributes,
72
+ sourcePath: binding.sourcePath,
73
+ baseSourceHash: hashText(binding.base),
74
+ workerSourceHash: hashText(binding.worker),
75
+ headSourceHash: hashText(binding.head),
76
+ outputSourceHash: hashText(binding.output)
77
+ });
78
+ }
79
+
80
+ function htmlRuntimeBoundaryProvenResult(result, runtimeBoundaryProofs) {
81
+ return compactRecord({
82
+ ...result,
83
+ runtimeBoundaryProofs,
84
+ browserRuntimeEquivalenceClaim: true,
85
+ admission: compactRecord({
86
+ ...(result.admission ?? {}),
87
+ browserRuntimeEquivalenceClaim: true,
88
+ htmlRuntimeBoundaryProofs: runtimeBoundaryProofs,
89
+ reasonCodes: uniqueStrings([...(result.admission?.reasonCodes ?? []), 'html-runtime-boundary-source-bound'])
90
+ })
91
+ });
92
+ }
93
+
94
+ function htmlRuntimeBoundaryAttributeGroups(sourceText) {
95
+ const groups = new Map();
96
+ for (const attribute of htmlRuntimeBoundaryAttributes(sourceText)) {
97
+ const key = `${attribute.reasonCode}\0${attribute.boundary}`;
98
+ const group = groups.get(key) ?? { reasonCode: attribute.reasonCode, boundary: attribute.boundary, records: [] };
99
+ group.records.push(attribute);
100
+ groups.set(key, group);
101
+ }
102
+ for (const group of groups.values()) group.fingerprint = group.records.map((attribute) => `${attribute.elementKey}:${attribute.name}=${String(attribute.value)}`).sort().join('\n');
103
+ return groups;
104
+ }
105
+
106
+ function changedHtmlRuntimeBoundaryAttributes(before, after) {
107
+ const beforeByKey = new Map(before.map((attribute) => [`${attribute.elementKey}:${attribute.name}`, attribute]));
108
+ const afterByKey = new Map(after.map((attribute) => [`${attribute.elementKey}:${attribute.name}`, attribute]));
109
+ const names = uniqueStrings([...beforeByKey.keys(), ...afterByKey.keys()].flatMap((key) => {
110
+ const left = beforeByKey.get(key);
111
+ const right = afterByKey.get(key);
112
+ return String(left?.value) === String(right?.value) ? [] : [right?.name ?? left?.name];
113
+ }));
114
+ return names.length ? names : uniqueStrings([...before, ...after].map((attribute) => attribute.name));
115
+ }
116
+
117
+ function htmlRuntimeBoundaryAttributes(sourceText) {
118
+ const attributes = [];
119
+ let elementIndex = 0;
120
+ for (const tag of String(sourceText ?? '').matchAll(/<[A-Za-z][\w:-]*(?:\s+[^<>]*?)?\/?>/g)) {
121
+ const parsed = /^<([A-Za-z][\w:-]*)([\s\S]*?)\/?>$/.exec(tag[0]);
122
+ if (!parsed) continue;
123
+ const tagName = parsed[1].toLowerCase();
124
+ const elementKey = `${elementIndex++}:${tagName}`;
125
+ for (const attribute of parseHtmlAttributes(parsed[2] ?? '')) {
126
+ const name = attribute.name.toLowerCase();
127
+ const spec = htmlRuntimeAttributeSpec(name, tagName);
128
+ if (spec) attributes.push({ ...attribute, ...spec, name, tagName, elementKey });
129
+ }
130
+ }
131
+ return attributes;
132
+ }
133
+
134
+ function htmlRuntimeAttributeSpec(name, tagName) {
135
+ if (/^on[\w:.-]+$/i.test(name)) return { boundary: 'html-event-handler-attribute', reasonCode: 'event-handler-runtime-boundary' };
136
+ if (name === 'style') return { boundary: 'html-inline-style-attribute', reasonCode: 'inline-style-runtime-boundary' };
137
+ if (tagName === 'iframe' && name === 'srcdoc') return { boundary: 'html-iframe-srcdoc-attribute', reasonCode: 'iframe-srcdoc-runtime-boundary' };
138
+ if (tagName === 'iframe' && IframeRuntimeAttributes.has(name)) return { boundary: 'html-iframe-runtime-attribute', reasonCode: 'iframe-runtime-boundary' };
139
+ if (tagName === 'form' && FormRuntimeAttributes.has(name)) return { boundary: 'html-form-runtime-attribute', reasonCode: 'form-runtime-boundary' };
140
+ if (FormSubmitterTags.has(tagName) && FormSubmitterRuntimeAttributes.has(name)) return { boundary: 'html-form-submitter-runtime-attribute', reasonCode: 'form-submitter-runtime-boundary' };
141
+ if (FormControlTags.has(tagName) && FormControlRuntimeAttributes.has(name)) return { boundary: 'html-form-control-runtime-attribute', reasonCode: 'form-control-runtime-boundary' };
142
+ if (tagName === 'base' && BaseRuntimeAttributes.has(name)) return { boundary: 'html-document-base-runtime-attribute', reasonCode: 'document-base-runtime-boundary' };
143
+ if (tagName === 'meta' && MetaRuntimeAttributes.has(name)) return { boundary: 'html-document-metadata-runtime-attribute', reasonCode: 'document-metadata-runtime-boundary' };
144
+ if (ResourceLoadingTags.has(tagName) && ResourceLoadingAttributes.has(name)) return { boundary: 'html-resource-loading-attribute', reasonCode: 'resource-loading-runtime-boundary' };
145
+ return undefined;
146
+ }
147
+
148
+ function parseHtmlAttributes(text) {
149
+ const attributes = [];
150
+ const pattern = /([:@A-Za-z_][\w:.-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
151
+ for (const match of text.matchAll(pattern)) attributes.push({ name: match[1], value: match[2] ?? match[3] ?? match[4] ?? true });
152
+ return attributes;
153
+ }
154
+
155
+ function htmlProofCoversValue(value, values, expected) {
156
+ return value === expected || (Array.isArray(values) && values.includes(expected));
157
+ }
158
+
159
+ function sameStringSet(actual, expected) {
160
+ const actualSet = uniqueStrings(asArray(actual).map((value) => String(value)));
161
+ const expectedSet = uniqueStrings(asArray(expected).map((value) => String(value)));
162
+ return actualSet.length === expectedSet.length && expectedSet.every((value) => actualSet.includes(value));
163
+ }
164
+
165
+ function asArray(value) {
166
+ return Array.isArray(value) ? value : value === undefined ? [] : [value];
167
+ }
168
+
169
+ const HtmlRuntimeBoundaryProofKinds = new Set(['html-runtime-boundary-proof', 'html-source-bound-runtime-boundary-proof']);
170
+ const IframeRuntimeAttributes = new Set(['allow', 'allowfullscreen', 'allowpaymentrequest', 'credentialless', 'csp', 'fetchpriority', 'loading', 'name', 'referrerpolicy', 'sandbox', 'src']);
171
+ const FormRuntimeAttributes = new Set(['accept-charset', 'action', 'autocomplete', 'enctype', 'method', 'novalidate', 'target']);
172
+ const FormSubmitterTags = new Set(['button', 'input']);
173
+ const FormSubmitterRuntimeAttributes = new Set(['form', 'formaction', 'formenctype', 'formmethod', 'formnovalidate', 'formtarget', 'type']);
174
+ const FormControlTags = new Set(['button', 'fieldset', 'input', 'optgroup', 'option', 'output', 'select', 'textarea']);
175
+ const FormControlRuntimeAttributes = new Set(['accept', 'autocomplete', 'capture', 'checked', 'disabled', 'form', 'list', 'max', 'maxlength', 'min', 'minlength', 'multiple', 'name', 'pattern', 'readonly', 'required', 'selected', 'size', 'step', 'value']);
176
+ const BaseRuntimeAttributes = new Set(['href', 'target']);
177
+ const MetaRuntimeAttributes = new Set(['charset', 'content', 'http-equiv', 'media', 'name', 'property']);
178
+ const ResourceLoadingTags = new Set(['audio', 'embed', 'img', 'link', 'object', 'source', 'track', 'video']);
179
+ const ResourceLoadingAttributes = new Set(['as', 'autoplay', 'blocking', 'color', 'controls', 'controlslist', 'crossorigin', 'data', 'decoding', 'default', 'disablepictureinpicture', 'disableremoteplayback', 'fetchpriority', 'height', 'href', 'imagesizes', 'imagesrcset', 'integrity', 'ismap', 'kind', 'label', 'loading', 'loop', 'media', 'muted', 'poster', 'preload', 'referrerpolicy', 'rel', 'sizes', 'src', 'srcset', 'srclang', 'type', 'usemap', 'width']);
180
+
181
+ export { htmlRuntimeBoundaryChanges, htmlRuntimeBoundaryProofForChange, htmlRuntimeBoundaryProofRecord, htmlRuntimeBoundaryProvenResult };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shapeshift-labs/frontier-lang-compiler",
3
- "version": "0.2.174",
3
+ "version": "0.2.176",
4
4
  "description": "Compiler facade for Frontier Lang source documents and language projection adapters.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -64,7 +64,7 @@
64
64
  "@shapeshift-labs/frontier-lang-c": "0.2.9",
65
65
  "@shapeshift-labs/frontier-lang-checker": "0.3.8",
66
66
  "@shapeshift-labs/frontier-lang-css": "^0.1.15",
67
- "@shapeshift-labs/frontier-lang-html": "^0.1.10",
67
+ "@shapeshift-labs/frontier-lang-html": "^0.1.12",
68
68
  "@shapeshift-labs/frontier-lang-javascript": "0.2.9",
69
69
  "@shapeshift-labs/frontier-lang-kernel": "0.3.12",
70
70
  "@shapeshift-labs/frontier-lang-parser": "0.3.8",