svg-ast-kit
v0.1.1
Published
Parse SVG strings into typed JSON trees with readable errors.
Downloads
219
Maintainers
Readme
svg-ast-kit
Convert SVG strings into typed JSON trees with readable errors.
svg-ast-kit is a small clean-room SVG-to-JSON parser for tooling, previews, audits and browser demos. It does not render SVG and it does not execute scripts. It turns SVG markup into a predictable object tree that can be inspected, transformed or serialized to JSON.
Package quality
- TypeScript types are generated from the source.
- ESM-only package with no runtime dependencies.
- Marked as side-effect free for bundlers.
- Tested on Node.js 20 and 22 with GitHub Actions.
- Works in Node.js, browsers, Vite apps and static docs tooling.
Install
npm install svg-ast-kitQuick Start
import { findSvgElements, getSvgElementNames, getSvgRootElement, getSvgStats, parseSvg, svgToJson } from "svg-ast-kit";
const tree = parseSvg(`
<svg viewBox="0 0 10 10">
<circle cx="5" cy="5" r="4" />
</svg>
`);
findSvgElements(tree, "circle");
// [{ type: "element", name: "circle", attributes: { cx: "5", cy: "5", r: "4" }, ... }]
getSvgRootElement(tree)?.attributes.viewBox;
// "0 0 10 10"
getSvgStats(tree);
// { elements: 2, attributes: 4, maxDepth: 2, ... }
getSvgElementNames(tree);
// ["svg", "circle"]
svgToJson(`<svg><path d="M0 0" /></svg>`);
// "{ ... }"API
parseSvg(source, options?)
Returns a SvgRootNode.
import { parseSvg } from "svg-ast-kit";
const root = parseSvg(`<svg><title>Logo</title></svg>`, {
includePositions: true
});The tree shape is intentionally JSON-friendly:
type SvgRootNode = {
type: "root";
children: SvgNode[];
};
type SvgElementNode = {
type: "element";
name: string;
attributes: Record<string, string>;
children: SvgNode[];
selfClosing: boolean;
};Supported node types:
| Type | Example |
| --- | --- |
| element | <path d="M0 0" /> |
| text | <title>Logo</title> |
| comment | <!-- note --> |
| cdata | <![CDATA[a > b]]> |
| instruction | <?xml version="1.0"?> |
| doctype | <!DOCTYPE svg> |
Options:
| Option | Default | Description |
| --- | --- | --- |
| includeComments | true | Keep comment nodes. |
| includeInstructions | true | Keep processing instructions. |
| includeDoctype | true | Keep doctype declarations. |
| includeWhitespaceText | false | Keep whitespace-only text nodes. |
| decodeEntities | true | Decode common XML entities. |
| includePositions | false | Attach offset, line and column metadata. |
tryParseSvg(source, options?)
Returns a result object instead of throwing. This is useful for editors, playgrounds and upload flows.
import { tryParseSvg } from "svg-ast-kit";
const result = tryParseSvg(userInput);
if (result.ok) {
console.log(result.root);
} else {
console.error(result.error.message);
}svgToJson(source, options?, space?)
Parses SVG and returns a JSON string. This is a convenience wrapper around parseSvg.
import { svgToJson } from "svg-ast-kit";
const json = svgToJson(`<svg><path d="M0 0" /></svg>`);findSvgElements(root, predicate, options?)
Finds SVG element nodes by tag name or predicate.
import { findSvgElements } from "svg-ast-kit";
findSvgElements(root, "path");
findSvgElements(root, "svg", { caseSensitive: false });
findSvgElements(root, (node) => node.attributes.id === "logo");findFirstSvgElement(root, predicate, options?)
Returns the first matching element, or undefined.
import { findFirstSvgElement } from "svg-ast-kit";
const logo = findFirstSvgElement(root, (node) => node.attributes.id === "logo");getSvgRootElement(root)
Returns the first <svg> element in the tree. The lookup is case-insensitive because snippets copied from tools are not always normalized.
import { getSvgRootElement } from "svg-ast-kit";
const svg = getSvgRootElement(root);getSvgElementNames(root, options?)
Returns element names in document order. Use { unique: true } to keep only the first occurrence of each name.
import { getSvgElementNames } from "svg-ast-kit";
getSvgElementNames(root);
// ["svg", "g", "path", "g", "circle"]
getSvgElementNames(root, { unique: true });
// ["svg", "g", "path", "circle"]walkSvg(root, visitor)
Walks the tree depth-first. Return false to skip a node's children.
import { walkSvg } from "svg-ast-kit";
walkSvg(root, ({ node, depth }) => {
if (node.type === "element") {
console.log(depth, node.name);
}
});getSvgStats(root)
Returns basic inventory data for demos, audits and tooling.
import { getSvgStats } from "svg-ast-kit";
getSvgStats(root);Result:
type SvgStats = {
elements: number;
attributes: number;
textNodes: number;
comments: number;
cdata: number;
instructions: number;
doctypes: number;
maxDepth: number;
elementsByName: Record<string, number>;
};Errors
Invalid markup throws SvgParseError, which includes offset, line and column.
import { SvgParseError, parseSvg } from "svg-ast-kit";
try {
parseSvg("<svg><g></svg>");
} catch (error) {
if (error instanceof SvgParseError) {
console.log(error.message);
console.log(error.line, error.column);
}
}Notes
- This package is for SVG/XML-like tooling, not for HTML parsing.
- Attribute values must be quoted.
- SVG fragments are allowed; a document does not have to contain exactly one root element.
findSvgElements()is case-sensitive by default. Use{ caseSensitive: false }for loose inspection.- The parser does not execute scripts, load external resources or render SVG.
- The implementation is clean-room and does not copy code from the existing
svg-parserpackage.
License
MPL-2.0
