@agent-native/core 0.147.0 → 0.148.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 (197) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +115 -68
  3. package/corpus/templates/analytics/DEVELOPING.md +50 -3
  4. package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
  5. package/corpus/templates/analytics/app/i18n/index.ts +14 -29
  6. package/corpus/templates/analytics/app/i18n-data.ts +10 -10
  7. package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
  8. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
  9. package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +197 -18
  10. package/corpus/templates/analytics/server/db/schema.ts +23 -0
  11. package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
  12. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
  13. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
  14. package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
  15. package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
  16. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
  17. package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
  18. package/corpus/templates/analytics/server/plugins/db.ts +42 -0
  19. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
  20. package/corpus/templates/assets/app/i18n/index.ts +14 -29
  21. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
  22. package/corpus/templates/brain/app/i18n/index.ts +14 -29
  23. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
  24. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  25. package/corpus/templates/chat/app/i18n/index.ts +14 -29
  26. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
  27. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
  28. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
  29. package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
  30. package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
  31. package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
  32. package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
  33. package/corpus/templates/clips/desktop/src/app.tsx +1 -1
  34. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
  35. package/corpus/templates/content/app/i18n/index.ts +14 -29
  36. package/corpus/templates/crm/app/i18n/index.ts +14 -29
  37. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
  38. package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
  39. package/corpus/templates/design/actions/import-code.ts +2 -43
  40. package/corpus/templates/design/app/i18n/index.ts +14 -29
  41. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
  42. package/corpus/templates/dispatch/app/i18n-data.ts +1 -1
  43. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
  44. package/corpus/templates/factory/AGENTS.md +40 -49
  45. package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
  46. package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
  47. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
  48. package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
  49. package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
  50. package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
  51. package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
  52. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  53. package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
  54. package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
  55. package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
  56. package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
  57. package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
  58. package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
  59. package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
  60. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
  61. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
  62. package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
  63. package/corpus/templates/factory/app/routes/factory.tsx +95 -42
  64. package/corpus/templates/factory/server/db/schema.ts +37 -0
  65. package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
  66. package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
  67. package/corpus/templates/factory/server/triage/audit.ts +79 -0
  68. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
  69. package/corpus/templates/forms/app/i18n/index.ts +14 -29
  70. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
  71. package/corpus/templates/macros/app/i18n/index.ts +14 -29
  72. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
  73. package/corpus/templates/mail/app/i18n/index.ts +14 -29
  74. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
  75. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
  76. package/corpus/templates/plan/app/i18n/index.ts +14 -29
  77. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
  78. package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
  79. package/corpus/templates/slides/actions/import-code.ts +2 -43
  80. package/corpus/templates/slides/app/i18n/index.ts +14 -29
  81. package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
  82. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
  83. package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
  84. package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
  85. package/corpus/templates/tasks/app/i18n/index.ts +14 -29
  86. package/dist/agent/engine/ai-sdk-engine.js +2 -1
  87. package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
  88. package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
  89. package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
  90. package/dist/agent/engine/provider-endpoint-validation.js +26 -0
  91. package/dist/agent/engine/provider-env-vars.d.ts +1 -1
  92. package/dist/agent/engine/provider-env-vars.js +1 -1
  93. package/dist/agent/engine/registry.d.ts +8 -6
  94. package/dist/agent/engine/registry.js +37 -24
  95. package/dist/agent/tool-search.d.ts +1 -0
  96. package/dist/agent/tool-search.js +17 -1
  97. package/dist/automations/service.js +4 -10
  98. package/dist/brand-kit/brand-signals.d.ts +13 -0
  99. package/dist/brand-kit/brand-signals.js +15 -0
  100. package/dist/brand-kit/index.d.ts +2 -2
  101. package/dist/brand-kit/index.js +1 -1
  102. package/dist/cli/plan-blocks.d.ts +3 -18
  103. package/dist/cli/plan-blocks.js +2 -95
  104. package/dist/cli/plan-publish-store.d.ts +2 -61
  105. package/dist/cli/plan-publish-store.js +2 -127
  106. package/dist/cli/skills-content/connection.d.ts +1 -1
  107. package/dist/cli/skills-content/connection.js +1 -52
  108. package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
  109. package/dist/cli/skills-content/visual-recap-skill.js +1 -553
  110. package/dist/client/agent-engine-key.d.ts +14 -4
  111. package/dist/client/agent-engine-key.js +51 -5
  112. package/dist/client/agent-provider-catalog.d.ts +20 -0
  113. package/dist/client/agent-provider-catalog.js +100 -0
  114. package/dist/client/blocks/index.d.ts +1 -0
  115. package/dist/client/blocks/index.js +1 -0
  116. package/dist/client/blocks/library/diagram.js +1 -1
  117. package/dist/client/blocks/library/sanitize-html.js +66 -2
  118. package/dist/client/blocks/library/wireframe-kit.js +69 -0
  119. package/dist/client/chat/run-recovery.js +4 -48
  120. package/dist/client/chat-first/apps-rail.d.ts +1 -1
  121. package/dist/client/chat-first/apps-rail.js +4 -4
  122. package/dist/client/chat-first/copy.js +1 -0
  123. package/dist/client/chat-first/types.d.ts +1 -0
  124. package/dist/client/chat-first.js +4 -3
  125. package/dist/client/i18n.d.ts +14 -0
  126. package/dist/client/i18n.js +18 -0
  127. package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
  128. package/dist/client/settings/ProviderSetupForm.js +145 -0
  129. package/dist/client/settings/SettingsPanel.js +52 -49
  130. package/dist/client/settings/index.d.ts +2 -0
  131. package/dist/client/settings/index.js +2 -0
  132. package/dist/coding-tools/run-code.d.ts +5 -0
  133. package/dist/coding-tools/run-code.js +196 -36
  134. package/dist/coding-tools/tool-orchestration.d.ts +10 -0
  135. package/dist/coding-tools/tool-orchestration.js +107 -0
  136. package/dist/collab/routes.d.ts +1 -1
  137. package/dist/jobs/frontmatter.d.ts +9 -0
  138. package/dist/jobs/frontmatter.js +16 -0
  139. package/dist/jobs/scheduler.js +8 -8
  140. package/dist/jobs/tools.d.ts +1 -1
  141. package/dist/jobs/tools.js +2 -7
  142. package/dist/localization/default-messages.d.ts +20 -0
  143. package/dist/localization/default-messages.js +25 -5
  144. package/dist/notifications/routes.d.ts +3 -3
  145. package/dist/observability/routes.d.ts +2 -2
  146. package/dist/onboarding/app-profile.js +1 -1
  147. package/dist/progress/routes.d.ts +1 -1
  148. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  149. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  150. package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
  151. package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
  152. package/dist/server/agent-chat/run-code-tools.js +3 -1
  153. package/dist/server/agent-chat-plugin.js +6 -6
  154. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  155. package/dist/server/agent-engine-api-key-route.js +43 -12
  156. package/dist/server/agents-bundle.js +2 -1
  157. package/dist/server/auth.js +21 -5
  158. package/dist/server/credential-provider.js +1 -0
  159. package/dist/server/design-token-utils.d.ts +18 -0
  160. package/dist/server/design-token-utils.js +31 -0
  161. package/dist/server/onboarding-html.js +22 -2
  162. package/dist/server/realtime-token.d.ts +1 -1
  163. package/dist/styles/blocks.css +132 -0
  164. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  165. package/dist/templates/chat/app/i18n/index.ts +14 -29
  166. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  167. package/dist/templates/default/app/i18n/index.ts +14 -29
  168. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  169. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  170. package/dist/triggers/dispatcher.js +1 -8
  171. package/docs/content/actions.mdx +4 -1
  172. package/docs/content/agent-surfaces.mdx +8 -6
  173. package/docs/content/automations.mdx +1 -1
  174. package/docs/content/database.mdx +6 -1
  175. package/docs/content/docs-components.mdx +22 -14
  176. package/docs/content/drop-in-agent.mdx +1 -1
  177. package/docs/content/environment-variables.mdx +39 -38
  178. package/docs/content/getting-started-actions.mdx +5 -4
  179. package/docs/content/getting-started-pages.mdx +7 -6
  180. package/docs/content/getting-started.mdx +4 -3
  181. package/docs/content/notifications.mdx +6 -6
  182. package/docs/content/progress.mdx +5 -5
  183. package/docs/content/routing.mdx +3 -1
  184. package/docs/content/server-database.mdx +13 -4
  185. package/docs/content/server-overview.mdx +9 -9
  186. package/docs/content/server-plugins.mdx +10 -4
  187. package/docs/content/server-routes.mdx +7 -2
  188. package/docs/content/tracking.mdx +4 -4
  189. package/docs/content/what-is-agent-native.mdx +4 -4
  190. package/package.json +4 -4
  191. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  192. package/src/templates/chat/app/i18n/index.ts +14 -29
  193. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  194. package/src/templates/default/app/i18n/index.ts +14 -29
  195. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  196. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  197. package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
@@ -1,343 +0,0 @@
1
- /*
2
- * Render-layer sanitizer for model-authored wireframe HTML.
3
- *
4
- * The HTML artboard injects model HTML via dangerouslySetInnerHTML into the LIVE
5
- * page DOM (it can't be iframe-sandboxed because the rough overlay must measure
6
- * the laid-out elements). The schema's regex guard is necessary but not
7
- * sufficient — obfuscated schemes (java\tscript:, javascript:) slip past
8
- * string matching. This neutralizes the html at the render point using the
9
- * browser's OWN parser/URL normalization, which decodes entities and collapses
10
- * whitespace, so obfuscation can't survive:
11
- * - drops dangerous elements (script/style/iframe/object/embed/...);
12
- * - strips every on* event-handler attribute;
13
- * - removes url attributes whose RESOLVED scheme isn't safe;
14
- * - removes inline styles carrying expression()/javascript:/data:text/html.
15
- * Defense-in-depth: stored content should also be sanitized server-side, but
16
- * this guarantees the live DOM never carries an executable payload.
17
- */
18
-
19
- const BLOCKED_TAGS =
20
- "script,style,iframe,object,embed,link,meta,base,form,noscript,frame,frameset,applet,marquee,portal";
21
- const DIAGRAM_BLOCKED_TAGS = `${BLOCKED_TAGS},math,foreignObject,foreignobject`;
22
-
23
- const URL_ATTRS = new Set([
24
- "href",
25
- "src",
26
- "xlink:href",
27
- "srcdoc",
28
- "action",
29
- "formaction",
30
- "background",
31
- "poster",
32
- "data",
33
- "ping",
34
- ]);
35
-
36
- const SAFE_SCHEMES = new Set(["http:", "https:", "mailto:", "tel:", "ftp:"]);
37
-
38
- const WHITESPACE = /\s+/g;
39
- const HAS_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
40
- const SAFE_DATA_IMAGE = /^data:image\/(png|jpe?g|gif|webp);/i;
41
-
42
- function isSafeUrl(value: string): boolean {
43
- // Strip whitespace for scheme detection ONLY (the browser collapses these when
44
- // resolving too, so obfuscated schemes like "java\tscript:" can't hide). The
45
- // original attribute is left untouched unless we decide to drop it.
46
- const v = (value || "").replace(WHITESPACE, "");
47
- if (
48
- v === "" ||
49
- v.startsWith("#") ||
50
- v.startsWith("/") ||
51
- v.startsWith("./") ||
52
- v.startsWith("../")
53
- ) {
54
- return true;
55
- }
56
- if (!HAS_SCHEME.test(v)) return true; // no scheme => relative, safe
57
- try {
58
- const a = document.createElement("a");
59
- a.href = v; // browser decodes the scheme + normalizes
60
- const proto = a.protocol.toLowerCase();
61
- // Allow only safe raster data images; block data:image/svg+xml (can script)
62
- // and data:text/html.
63
- if (proto === "data:") return SAFE_DATA_IMAGE.test(a.href);
64
- return SAFE_SCHEMES.has(proto);
65
- } catch {
66
- return false;
67
- }
68
- }
69
-
70
- const DANGEROUS_STYLE =
71
- /(expression\s*\(|javascript:|vbscript:|url\s*\(\s*['"]?\s*(?:javascript|vbscript|data:text\/html))/i;
72
- const DANGEROUS_CSS =
73
- /(@(?:import|font-face|keyframes|page|namespace|charset)\b|expression\s*\(|javascript:|vbscript:|data:text\/html|data:image\/svg\+xml|<\/?\s*(?:script|style)\b)/i;
74
- const DANGEROUS_VIEWPORT_CSS =
75
- /(?:^|[;{\s])position\s*:\s*(?:fixed|sticky)\b|(?:^|[;{\s])z-index\s*:\s*[1-9]\d{4,}\b/i;
76
-
77
- function decodeCssSafetyEscapes(value: string): string {
78
- return value.replace(/\\([0-9a-fA-F]{1,6}\s?|.)/g, (_match, escaped) => {
79
- const hex = String(escaped).match(/^[0-9a-fA-F]{1,6}/)?.[0];
80
- if (hex) {
81
- const point = Number.parseInt(hex, 16);
82
- return Number.isFinite(point) ? String.fromCodePoint(point) : "";
83
- }
84
- return String(escaped)[0] ?? "";
85
- });
86
- }
87
-
88
- function cssSafetyText(value: string): string {
89
- return decodeCssSafetyEscapes(value)
90
- .toLowerCase()
91
- .replace(/[\u0000-\u0020]+/g, "");
92
- }
93
-
94
- type SanitizeElementOptions = {
95
- stripRuntimeDirectives?: boolean;
96
- stripWireframeThemeClasses?: boolean;
97
- };
98
-
99
- const TAILWIND_THEME_COLORS =
100
- /^(?:bg|text|border|ring|outline|divide|placeholder|from|via|to|accent|caret|decoration|fill|stroke)-(?:inherit|current|transparent|black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)(?:-\d{2,3})?(?:\/[\d.]+)?$/;
101
- const TAILWIND_ARBITRARY_THEME_COLOR =
102
- /^(?:bg|text|border|ring|outline|divide|placeholder|from|via|to|accent|caret|decoration|fill|stroke)-\[/;
103
- const TAILWIND_SHADOW = /^shadow(?:$|-)/;
104
-
105
- function baseClassName(className: string): string {
106
- let bracketDepth = 0;
107
- let lastVariantSeparator = -1;
108
- for (let index = 0; index < className.length; index += 1) {
109
- const char = className[index];
110
- if (char === "[") bracketDepth += 1;
111
- if (char === "]") bracketDepth = Math.max(0, bracketDepth - 1);
112
- if (char === ":" && bracketDepth === 0) lastVariantSeparator = index;
113
- }
114
- return className.slice(lastVariantSeparator + 1);
115
- }
116
-
117
- function isWireframeThemeClass(className: string): boolean {
118
- const base = baseClassName(className);
119
- return (
120
- TAILWIND_THEME_COLORS.test(base) ||
121
- TAILWIND_ARBITRARY_THEME_COLOR.test(base) ||
122
- TAILWIND_SHADOW.test(base)
123
- );
124
- }
125
-
126
- function stripWireframeThemeClasses(value: string): string {
127
- return value
128
- .split(/\s+/)
129
- .filter(Boolean)
130
- .filter((className) => !isWireframeThemeClass(className))
131
- .join(" ");
132
- }
133
-
134
- /** Conservative no-DOM fallback for any non-browser code path (SSR). */
135
- function fallbackStrip(html: string, options?: SanitizeElementOptions): string {
136
- // Drop the whole url attribute if its value (whitespace/control-stripped)
137
- // carries a dangerous scheme. Mirrors the DOM path for the rare no-DOMParser
138
- // case; entity-obfuscation isn't decoded here (the live DOM path handles it).
139
- const stripScheme = (m: string, dq?: string, sq?: string, uq?: string) => {
140
- const v = (dq ?? sq ?? uq ?? "").replace(/[\s\u0000-\u001f]+/g, "");
141
- return /^(?:javascript|vbscript):|^data:text\/html/i.test(v) ? "" : m;
142
- };
143
- let out = html
144
- .replace(
145
- /<\/?(?:script|style|iframe|object|embed|link|meta|base|form|noscript|frame|frameset|applet|marquee|portal)\b[^>]*>/gi,
146
- "",
147
- )
148
- .replace(/\son[a-z][\w:-]*\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi, "")
149
- .replace(
150
- /\s(?:href|src|xlink:href|action|formaction|poster|background|data|ping)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi,
151
- stripScheme,
152
- )
153
- .replace(/\sstyle\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, (m) =>
154
- DANGEROUS_STYLE.test(m) ? "" : m,
155
- );
156
- if (options?.stripWireframeThemeClasses) {
157
- out = out.replace(
158
- /\sclass\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi,
159
- (_match, doubleQuoted, singleQuoted, bare) => {
160
- const next = stripWireframeThemeClasses(
161
- doubleQuoted ?? singleQuoted ?? bare ?? "",
162
- );
163
- return next ? ` class="${next}"` : "";
164
- },
165
- );
166
- }
167
- return out;
168
- }
169
-
170
- export function sanitizeWireframeHtml(
171
- html: string | undefined,
172
- options?: { preserveThemeClasses?: boolean },
173
- ): string {
174
- if (!html) return "";
175
- const stripWireframeThemeClasses = !options?.preserveThemeClasses;
176
- if (typeof DOMParser === "undefined" || typeof document === "undefined") {
177
- return fallbackStrip(html, { stripWireframeThemeClasses });
178
- }
179
- const doc = new DOMParser().parseFromString(html, "text/html");
180
- doc.querySelectorAll(BLOCKED_TAGS).forEach((el) => el.remove());
181
- sanitizeElementAttributes(doc.body, { stripWireframeThemeClasses });
182
- return doc.body.innerHTML;
183
- }
184
-
185
- export function sanitizeDiagramHtml(html: string | undefined): string {
186
- if (!html) return "";
187
- if (typeof DOMParser === "undefined" || typeof document === "undefined") {
188
- return fallbackStrip(html)
189
- .replace(/<\/?\s*(?:math|foreignObject|foreignobject)\b[^>]*>/gi, "")
190
- .replace(
191
- /\s(?:@[\w:.-]+|x-on:[\w:.-]+|:on[\w:.-]+|x-bind:on[\w:.-]+|:style|x-bind:style)\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/gi,
192
- "",
193
- );
194
- }
195
- const doc = new DOMParser().parseFromString(html, "text/html");
196
- doc.querySelectorAll(DIAGRAM_BLOCKED_TAGS).forEach((el) => el.remove());
197
- sanitizeElementAttributes(doc.body, { stripRuntimeDirectives: true });
198
- return doc.body.innerHTML;
199
- }
200
-
201
- export function sanitizeWireframeCss(css: string | undefined): string {
202
- if (!css) return "";
203
- return css
204
- .split("\n")
205
- .filter((line) => {
206
- const decoded = decodeCssSafetyEscapes(line);
207
- const compact = cssSafetyText(line);
208
- return !(
209
- DANGEROUS_CSS.test(line) ||
210
- DANGEROUS_CSS.test(decoded) ||
211
- DANGEROUS_VIEWPORT_CSS.test(decoded) ||
212
- /(?:javascript|vbscript):|data:(?:text\/html|image\/svg\+xml)|expression\(|url\(['"]?(?:javascript|vbscript|data:(?:text\/html|image\/svg\+xml))/.test(
213
- compact,
214
- )
215
- );
216
- })
217
- .join("\n")
218
- .replace(/\bjava\s*script\s*:/gi, "")
219
- .replace(/\bvb\s*script\s*:/gi, "")
220
- .replace(/\bdata\s*:\s*(?:text\/html|image\/svg\+xml)/gi, "");
221
- }
222
-
223
- export function scopeDesignCss(css: string, scopeSelector: string): string {
224
- if (!css.trim()) return "";
225
- return css.replace(
226
- /(^|[{}])\s*([^@{}][^{}]*)\{/g,
227
- (_match, boundary: string, selectors: string) => {
228
- const scoped = splitSelectorList(selectors)
229
- .map((selector) => selector.trim())
230
- .filter(Boolean)
231
- .map((selector) => {
232
- if (selector.startsWith(scopeSelector)) return selector;
233
- if (
234
- selector === ":root" ||
235
- selector === "html" ||
236
- selector === "body"
237
- )
238
- return scopeSelector;
239
- return `${scopeSelector} ${selector}`;
240
- })
241
- .join(", ");
242
- return `${boundary} ${scoped} {`;
243
- },
244
- );
245
- }
246
-
247
- function splitSelectorList(selectors: string): string[] {
248
- const parts: string[] = [];
249
- let current = "";
250
- let parenDepth = 0;
251
- let bracketDepth = 0;
252
- let quote: '"' | "'" | null = null;
253
- let escaped = false;
254
-
255
- for (const char of selectors) {
256
- current += char;
257
- if (escaped) {
258
- escaped = false;
259
- continue;
260
- }
261
- if (char === "\\") {
262
- escaped = true;
263
- continue;
264
- }
265
- if (quote) {
266
- if (char === quote) quote = null;
267
- continue;
268
- }
269
- if (char === '"' || char === "'") {
270
- quote = char;
271
- continue;
272
- }
273
- if (char === "[") {
274
- bracketDepth += 1;
275
- continue;
276
- }
277
- if (char === "]") {
278
- bracketDepth = Math.max(0, bracketDepth - 1);
279
- continue;
280
- }
281
- if (char === "(") {
282
- parenDepth += 1;
283
- continue;
284
- }
285
- if (char === ")") {
286
- parenDepth = Math.max(0, parenDepth - 1);
287
- continue;
288
- }
289
- if (char === "," && parenDepth === 0 && bracketDepth === 0) {
290
- parts.push(current.slice(0, -1));
291
- current = "";
292
- }
293
- }
294
-
295
- parts.push(current);
296
- return parts;
297
- }
298
-
299
- function sanitizeElementAttributes(
300
- root: ParentNode,
301
- options?: SanitizeElementOptions,
302
- ) {
303
- root.querySelectorAll<HTMLElement>("*").forEach((el) => {
304
- for (const attr of Array.from(el.attributes)) {
305
- const name = attr.name.toLowerCase();
306
- if (name.startsWith("on")) {
307
- el.removeAttribute(attr.name);
308
- continue;
309
- }
310
- if (
311
- options?.stripRuntimeDirectives &&
312
- (name.startsWith("@") ||
313
- name.startsWith("x-on:") ||
314
- name.startsWith(":on") ||
315
- name.startsWith("x-bind:on") ||
316
- name === ":style" ||
317
- name === "x-bind:style")
318
- ) {
319
- el.removeAttribute(attr.name);
320
- continue;
321
- }
322
- if (URL_ATTRS.has(name) && !isSafeUrl(attr.value)) {
323
- el.removeAttribute(attr.name);
324
- continue;
325
- }
326
- if (name === "style" && DANGEROUS_STYLE.test(attr.value)) {
327
- el.removeAttribute(attr.name);
328
- continue;
329
- }
330
- if (name === "class" && options?.stripWireframeThemeClasses) {
331
- const next = stripWireframeThemeClasses(attr.value);
332
- if (next) {
333
- el.setAttribute(attr.name, next);
334
- } else {
335
- el.removeAttribute(attr.name);
336
- }
337
- }
338
- }
339
- if (el instanceof HTMLTemplateElement) {
340
- sanitizeElementAttributes(el.content, options);
341
- }
342
- });
343
- }