Skip to content

feat: add --node flag to scope conversion to a single node#3

Open
tommymorgan wants to merge 1 commit into
kreako:mainfrom
tommymorgan:node-targeting
Open

feat: add --node flag to scope conversion to a single node#3
tommymorgan wants to merge 1 commit into
kreako:mainfrom
tommymorgan:node-targeting

Conversation

@tommymorgan
Copy link
Copy Markdown

@tommymorgan tommymorgan commented May 24, 2026

Why

Large Figma files convert to hundreds of MB of optimized JSON, the entire
document, even when only one frame is needed. This adds a --node flag that
scopes conversion to a single node, given by its sessionID:localID (the id
Figma puts in file URLs; dash or colon form accepted). On a real 23MB .fig file this
turns a 313MB JSON export into ~1.5MB for one frame.

What

  • --node <ID> on the CLI. Works for plain .fig and ZIP archives; for an
    archive it converts only the inner file containing the node, skips the rest,
    and errors clearly if no file matches. Rejected together with --raw.
  • New convert_node(bytes, base_dir, target); convert() becomes a no-target
    wrapper, so existing callers are unchanged.
  • The node is matched by its guid right after build_tree, before the
    transformation passes run, so only the targeted subtree is processed.
  • NodeId is a u64 sessionID/localID pair that parses from either form via
    FromStr; a miss is reported as FigError::NodeNotFound(NodeId).

Usage

fig2json --help (the --node option is the addition):

Options:
  -o, --output <OUTPUT>   Output JSON file path (default: stdout) - Cannot be used with extract_dir
      --compact           Compact JSON output (default is pretty-printed with indentation)
  -v, --verbose           Verbose output for debugging
      --raw               Generate both transformed .json and raw .raw.json files (without transformations)
      --node <ID>         Extract only this node and its subtree (Figma node id, e.g. 6886:48774 or 6886-48774)
  -h, --help              Print help (see a summary with '-h')
  -V, --version           Print version

Example, pulling a single frame out of a locally-saved .fig (here a ZIP that
extracts to out/):

fig2json "design.fig" out/ --node 6886:48774
# writes out/<canvas>.json scoped to that node's subtree

Tests

  • New schema::node_filter unit tests (id parsing: colon/dash/whitespace and
    rejected forms; subtree finding incl. sibling exclusion, first-match, and
    guarding against matching non-guid id keys), written test-first.
  • CLI integration tests (tests/cli.rs) for --node and --raw validation.
  • Full suite green (623 unit + 2 CLI + 67 doc), cargo clippy clean.

Large .fig files convert to the entire document, hundreds of MB of JSON,
even when only one frame is needed. --node <ID> scopes conversion to a
single node and its subtree, matched by its guid {sessionID, localID}.

The id accepts both forms Figma provides: 6886:48774 (REST) and
6886-48774 (the node-id in a figma.com URL). Matching runs right after
build_tree and before the transform passes, so only the targeted subtree
is processed. In ZIP mode it converts the archived file containing the
node and skips the rest, erroring only if no file has it. Rejected
together with --raw.

convert_node(bytes, base_dir, target) carries the optional target;
convert() stays as a no-target wrapper, so existing callers are
unchanged. A miss is reported as FigError::NodeNotFound(NodeId).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant