feat(scene): add SVG file import#33
Open
willytop8 wants to merge 2 commits into
Open
Conversation
Introduces a first-class `svg` scene object that stores raw SVG markup and renders it via a data-URL `<img>` tag (browser-sandboxed, no script execution). Adds an SVG file picker to the uploads panel that was previously a "Coming soon" stub. - `avnac-scene.ts`: new `SceneSvg` type, `'svg'` in `SceneObjectType` and `SceneObject` union, parse / clone / displayName cases - `avnac-document.ts`: re-exports `SceneSvg` - `avnac-scene-render.ts`: `svgMarkupToDataUrl` helper + `case 'svg'` in `drawSceneObject` — export pipeline works without further changes - `object-view.tsx`: live editor renders SVG objects via `<img>` data URL - `editor-uploads-panel.tsx`: SVG file picker with DOMParser-based size detection, parseerror guard, and regex sanitizer (strips `<script>`, `<foreignObject>`, `on*` attrs, external `<use href>`) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@willytop8 is attempting to deploy a commit to the Akinkunmi Team on Vercel. A member of the Team first needs to authorize it. |
Contributor
There was a problem hiding this comment.
3 issues found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="frontend/src/components/editor-uploads-panel.tsx">
<violation number="1" location="frontend/src/components/editor-uploads-panel.tsx:33">
P2: `parseSvgNaturalSize` accepts any well-formed XML as SVG because it never checks that the parsed root element is `<svg>`, so non-SVG XML can be imported and stored as an SVG object.</violation>
<violation number="2" location="frontend/src/components/editor-uploads-panel.tsx:76">
P1: File read errors are not handled, causing unhandled promise rejections and aborting processing of remaining files</violation>
<violation number="3" location="frontend/src/components/editor-uploads-panel.tsx:90">
P2: Imported SVG dimensions should be clamped to at least 1; rounding can otherwise create zero-sized objects for tiny SVGs.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
- parseSvgNaturalSize: reject non-SVG XML by checking root tag name - handleSvgFiles: catch FileReader errors per-file so one failure does not abort remaining files in a multi-file upload - clamp display dimensions to at least 1px to prevent zero-sized objects when rounding tiny SVG natural dimensions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="frontend/src/components/editor-uploads-panel.tsx">
<violation number="1" location="frontend/src/components/editor-uploads-panel.tsx:36">
P3: Strictly comparing `tagName` to `'svg'` rejects valid namespace-prefixed SVG roots (e.g. `svg:svg`), causing imported SVGs to be silently skipped.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| if (doc.querySelector('parsererror')) return null | ||
|
|
||
| const root = doc.documentElement | ||
| if (root.tagName.toLowerCase() !== 'svg') return null |
Contributor
There was a problem hiding this comment.
P3: Strictly comparing tagName to 'svg' rejects valid namespace-prefixed SVG roots (e.g. svg:svg), causing imported SVGs to be silently skipped.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frontend/src/components/editor-uploads-panel.tsx, line 36:
<comment>Strictly comparing `tagName` to `'svg'` rejects valid namespace-prefixed SVG roots (e.g. `svg:svg`), causing imported SVGs to be silently skipped.</comment>
<file context>
@@ -33,6 +33,7 @@ function parseSvgNaturalSize(markup: string): { width: number; height: number }
if (doc.querySelector('parsererror')) return null
const root = doc.documentElement
+ if (root.tagName.toLowerCase() !== 'svg') return null
const wAttr = root.getAttribute('width')
const hAttr = root.getAttribute('height')
</file context>
Suggested change
| if (root.tagName.toLowerCase() !== 'svg') return null | |
| if (root.localName.toLowerCase() !== 'svg' || root.namespaceURI !== 'http://www.w3.org/2000/svg') return null |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SceneSvgscene object type that stores raw SVG markup and renders it via adata:image/svg+xml<img>tag (browser-sandboxed — scripts and event handlers do not execute)case 'svg'branch indrawSceneObjectChanges
avnac-scene.tsSceneSvgtype;'svg'added toSceneObjectTypeandSceneObjectunion; parse, clone, and display-name casesavnac-document.tsSceneSvgavnac-scene-render.tssvgMarkupToDataUrlhelper;case 'svg'indrawSceneObjectobject-view.tsx<img>data URLeditor-uploads-panel.tsxparseerrorguard, and sanitizerSafety
SVGs are rendered exclusively via
<img>with a data URL — the browser sandboxes the SVG document so scripts and event handlers are inert. A regex sanitizer runs before storage as defense-in-depth: strips<script>,<foreignObject>,on*event attributes, and external<use href="https://...">references.Out of scope
add_svgtoolNeed help on this PR? Tag
@codesmithwith what you need.Summary by cubic
Adds SVG import as a first-class scene object so users can upload SVGs, place them on the artboard, and export without changing the pipeline. Renders SVGs safely via a data-URL
.
New Features
SceneSvgandsvghandling across parse/clone/display-name and canvas renderer; export works as-is.<img>; sanitizer strips<script>,<foreignObject>,on*attributes, and external<use href>.Bug Fixes
Written for commit 67650d8. Summary will update on new commits.