feat: browser-side annotation screenshots for web preview

Capture the preview/browser iframe DOM with snapDOM (html-to-image
fallback) so web annotation screenshots match the visible viewport,
without a headless Chromium dependency.

- Preserve document scroll via viewport crop and re-bake nested scroll
  (e.g. the Starlight sidebar) deterministically on the clone
- Pin position:fixed elements to their measured viewport rect so headers
  and sidebars land correctly in the crop
- Extract preview capture/proxy helpers into
  lib/preview/screenshot-capture.ts to slim down ContextPanel
- Guard the external preview proxy against SSRF to private, loopback and
  reserved/link-local addresses (incl. cloud metadata)
- Fully validate preview bridge messages before formatting/use
- Warn on the empty browser tab that pages run with full access, so
  users browse untrusted sites knowingly
This commit is contained in:
Bohdan Triapitsyn
2026-05-30 02:04:32 +03:00
parent 49ed0b52c9
commit 7f90ffb878
15 changed files with 1591 additions and 210 deletions
+4 -3
View File
@@ -11,6 +11,7 @@
"lint": "eslint \"./src/**/*.{ts,tsx}\" --config ../../eslint.config.js"
},
"dependencies": {
"@base-ui/react": "^1.4.0",
"@codemirror/autocomplete": "^6.20.0",
"@codemirror/commands": "^6.10.1",
"@codemirror/lang-cpp": "^6.0.3",
@@ -41,11 +42,11 @@
"@lezer/highlight": "^1.2.3",
"@opencode-ai/sdk": "^1.15.10",
"@pierre/diffs": "1.1.0-beta.13",
"@base-ui/react": "^1.4.0",
"@simplewebauthn/browser": "13.3.0",
"@tanstack/react-virtual": "^3.13.18",
"@types/react-syntax-highlighter": "^15.5.13",
"@xenova/transformers": "^2.17.2",
"@zumer/snapdom": "^2.12.0",
"beautiful-mermaid": "^1.1.3",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
@@ -61,8 +62,6 @@
"katex": "^0.16.21",
"marked": "^17.0.3",
"morphdom": "^2.7.7",
"rehype-katex": "^7.0.1",
"remark-math": "^6.0.0",
"motion": "^12.23.24",
"next-themes": "^0.4.6",
"prismjs": "^1.30.0",
@@ -70,6 +69,8 @@
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-syntax-highlighter": "^15.6.6",
"rehype-katex": "^7.0.1",
"remark-math": "^6.0.0",
"remend": "^1.2.1",
"simple-git": "^3.28.0",
"sonner": "^2.0.7",