181 lines
8.6 KiB
Markdown
181 lines
8.6 KiB
Markdown
# SVG Tools
|
|
|
|
SVG Tools is a static, local-first SVG workbench. It keeps the original SVG
|
|
source as the persistent document, then derives a semantic tree, a sanitized
|
|
editing projection, a canvas overlay and inspectors from that source. Files are
|
|
processed in the browser; the app has no backend, upload endpoint, telemetry or
|
|
runtime CDN dependency.
|
|
|
|
Version 0.2.0 delivers the structured viewer/editor milestone (MVP 1) and
|
|
tested vertical slices of the path, transform, reference, optimization,
|
|
security, accessibility, animation and export milestones. The later milestone
|
|
lists below remain a roadmap, not a claim of complete vector-editor coverage.
|
|
|
|
## Working model
|
|
|
|
- The CodeMirror XML document is canonical. Visual changes create exact source
|
|
patches and one application-level undo transaction.
|
|
- The semantic model records element and attribute source ranges, stable
|
|
in-memory keys, source preferences, metrics and diagnostics.
|
|
- Tree, source cursor and canvas selection are synchronized.
|
|
- Invalid edits remain visible in the source editor while the tree and canvas
|
|
retain the last valid revision. Visual editing is disabled until parsing
|
|
succeeds again.
|
|
- Comments, whitespace and unrelated source remain unchanged for targeted
|
|
edits. Prettify, sanitize and optimize are explicit whole-document previews.
|
|
- No editor namespace or persistent editor attribute is added to normal SVG
|
|
exports.
|
|
|
|
## Implemented in 0.2.0
|
|
|
|
- open, drop and paste SVG; magic-byte SVGZ import; new-document templates;
|
|
- XML editor, ranged diagnostics, structure tree, filtering and synchronized
|
|
selection;
|
|
- safe canvas, zoom, pan, grid, selected bounds and last-valid state;
|
|
- document dimensions, `viewBox`, `preserveAspectRatio`, arbitrary attributes,
|
|
fill, stroke, opacity, rotate, flip, translate, scale and skew;
|
|
- undoable subtree duplicate/delete for ID-free nodes, with duplicate-ID and
|
|
external-reference guards rather than silently breaking the document;
|
|
- exact undo/redo and explicit source-diff previews;
|
|
- parsing of `M L H V C S Q T A Z`, absolute/relative and repeated groups;
|
|
- anchors, cubic and quadratic controls, derived smooth controls, arc controls,
|
|
nested-transform coordinate mapping, keyboard nudging, 50% segment splitting
|
|
and path reversal;
|
|
- transform-list parsing, ancestor matrices, invertibility diagnostics, preview
|
|
overlay, and atomic baking for paths, lines, polylines, polygons, rectangles,
|
|
circles and ellipses with disclosed conversion/stroke warnings;
|
|
- ID/reference indexing, broken/ambiguous/cyclic reference diagnostics and
|
|
atomic ID rename for local URL, href and ARIA references;
|
|
- SVGO 4.0.2 in a cancelable worker with conservative, balanced and aggressive
|
|
profiles, explicit optional plugins, sizes and source diff;
|
|
- non-destructive sanitization, geometry diagnostics, accessible-name audit and
|
|
undoable root title/description fixes;
|
|
- app-owned, validated CSS opacity animation preview in the isolated canvas and
|
|
explicit source application;
|
|
- exact SVG, deterministic SVGZ, sanitized SVG, optimized SVG, selected-object
|
|
SVG, symbol sprite, PNG, WebP, JPEG and deterministic project export.
|
|
|
|
Well-formed SVG/XML content that the semantic model does not understand is
|
|
preserved in canonical source. The editing projection deliberately excludes
|
|
active or externally loading content. Standard rendering still follows the
|
|
browser's SVG implementation, so font, filter and text layout can differ across
|
|
browsers.
|
|
|
|
## Path controls
|
|
|
|
Explicit cubic controls are solid; controls reflected by `S` are dashed and
|
|
labelled derived. Quadratic commands show their single control, while `T`
|
|
derives the reflection of the preceding quadratic control. Arcs expose endpoint,
|
|
center and radius controls plus their flags in the command table. Moving a
|
|
derived control intentionally expands shorthand to explicit normalized geometry.
|
|
Visual path edits currently serialize the selected `d` attribute in normalized
|
|
absolute form; surrounding source is untouched.
|
|
|
|
Not yet implemented: multi-node modes, path join/break/combine,
|
|
subpath-start changes, a pen tool, snapping, simplification, boolean operations,
|
|
round corners and stroke-to-path.
|
|
|
|
## Transform model and limits
|
|
|
|
Transform drafts never change source. SVG Tools shows the local/ancestor chain,
|
|
candidate matrix, diagnostics, before/after overlay and source diff before one
|
|
atomic Apply. General rectangle and ellipse cases may convert to a path. Baking
|
|
is refused for unsupported elements rather than partially rewriting them.
|
|
|
|
Stroke widths are not silently rewritten for non-conformal transforms; the
|
|
preview reports the consequence. Paint servers, markers, filters, clips, masks,
|
|
text and shared definitions are not flattened or cloned. Group flattening,
|
|
text-to-path and complete paint-server coordinate remapping remain future work.
|
|
|
|
## Security and privacy
|
|
|
|
Imported source is never inserted into the application DOM. DOMPurify plus an
|
|
application policy produces a separate editing projection. Scripts,
|
|
`foreignObject`, event handlers, native SVG animation, navigation and unsafe
|
|
namespaces are removed; external/executable URLs and unsafe CSS resource forms
|
|
are neutralized. Only unique local fragments and bounded raster data URLs are
|
|
eligible for rendering.
|
|
|
|
The projection runs in an opaque-origin iframe (`sandbox="allow-scripts"`) with
|
|
a restrictive child CSP. Its small self-hosted controller accepts a random
|
|
channel and messages from the parent window only, then removes its own script
|
|
element. Production servers must return the two documented cross-origin headers
|
|
for `canvas-frame-controller.js`; see [docs/SECURITY.md](docs/SECURITY.md).
|
|
Original source always remains available. Sanitization and optimization require
|
|
an explicit preview and Apply. These controls reduce the documented threat
|
|
surface; they are not a universal SVG sanitizer for every embedding context.
|
|
|
|
Resource limits cover source bytes, decompressed SVGZ output, elements, depth,
|
|
attributes, text, path commands, CSS, references, animation/filter counts,
|
|
embedded data, history, optimization time and raster pixels.
|
|
|
|
## Accessibility
|
|
|
|
The current evidence-based audit checks the root accessible name (`title`,
|
|
`aria-label` or `aria-labelledby`), missing description, invalid/ambiguous ARIA
|
|
references, focusable elements without names and selected contrast evidence.
|
|
Safe root title/description fixes are undoable. This is not a complete browser
|
|
accessible-name computation and does not establish WCAG conformance.
|
|
|
|
## Projects and persistence
|
|
|
|
Normal work is memory-only. SVG Tools does not write source or recent-file data
|
|
to browser storage. A `.svgtools.json` project is explicit, deterministic JSON
|
|
containing canonical source, selection/expanded state, active panel, zoom, pan,
|
|
grid and app-owned animation definitions. Import validates schema, sizes,
|
|
numbers, arrays and every animation field before use.
|
|
|
|
## Development
|
|
|
|
Node.js 22 or newer and npm are required.
|
|
|
|
```sh
|
|
npm ci
|
|
npm run dev
|
|
npm run typecheck
|
|
npm run lint
|
|
npm run format:check
|
|
npm test
|
|
npm run test:security
|
|
npm run test:browser
|
|
npm run build
|
|
npm run toolbox:check
|
|
```
|
|
|
|
`vite.config.ts` uses `base: './'`; the same build works standalone, in Toolbox
|
|
context and below a nested path. `npm run release:artifact` performs the complete
|
|
quality gate, creates a deterministic ZIP plus SHA-256 sidecar, and exercises a
|
|
temporary Toolbox Portal assembly. Portal consumes that immutable ZIP; it does
|
|
not build this repository.
|
|
|
|
For the opaque canvas controller, a production server must return:
|
|
|
|
```text
|
|
Access-Control-Allow-Origin: *
|
|
Cross-Origin-Resource-Policy: cross-origin
|
|
```
|
|
|
|
only for the app-relative `canvas-frame-controller.js`. All other app resources
|
|
should keep `Cross-Origin-Resource-Policy: same-origin`. The Toolbox Portal
|
|
0.10.0 Nginx policy contains this URI-scoped exception.
|
|
|
|
## Source and licence
|
|
|
|
Corresponding source and inspected revisions are recorded in [SOURCE.md](SOURCE.md)
|
|
and [docs/REFERENCE_IMPLEMENTATIONS.md](docs/REFERENCE_IMPLEMENTATIONS.md).
|
|
Third-party packages and adoption decisions are recorded in
|
|
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) and [LICENSES](LICENSES/README.md).
|
|
Project-authored fixtures contain no third-party artwork or text.
|
|
|
|
SVG Tools is licensed under `GPL-3.0-or-later`. See [LICENSE](LICENSE).
|
|
|
|
## Roadmap
|
|
|
|
The smallest next slice is multi-node path editing: node selection and modes,
|
|
shape-preserving deletion/insertion, segment conversion and open/join/break
|
|
operations under nested transforms. Later slices add drawing tools, grouping,
|
|
alignment/snapping, gradients/markers/filters, symbol management, advanced
|
|
geometry and broader isolated SMIL/CSS animation inspection.
|
|
|
|
Detailed models and limitations live in [docs](docs/ARCHITECTURE.md).
|