Skill Tracer
Skills › Archify › archify › README.md

README.md

96 lines · archify/renderers/tree/README.md at a406594

Open on GitHub
1# Hierarchy and Tree Renderer
2
3Render `diagram_type: "tree"` JSON files into the standard Archify HTML template.
4
5```bash
6node archify/renderers/tree/render-tree.mjs input.tree.json output.html
7```
8
9The renderer validates input against `archify/schemas/tree.schema.json` with the
10bundled standalone validator. If `output.html` is omitted, it uses
11`meta.output` or falls back to `tree.html`. `--layout-json` prints the placed
12nodes and links instead of writing HTML.

Hierarchy and Tree Renderer

Render diagram_type: "tree" JSON files into the standard Archify HTML template.

node archify/renderers/tree/render-tree.mjs input.tree.json output.html

The renderer validates input against archify/schemas/tree.schema.json with the bundled standalone validator. If output.html is omitted, it uses meta.output or falls back to tree.html. --layout-json prints the placed nodes and links instead of writing HTML.

Raw lines 1 to 13
14## Input
16```json
18 "schema_version": 1,
19 "diagram_type": "tree",
20 "meta": { "title": "Payment platform capabilities" },
21 "nodes": [
22 { "id": "platform", "label": "Payment platform" },
23 { "id": "orders", "label": "Orders", "parent": "platform" }
24 ]
26```
28A node has `id`, `label`, and optional `parent`, `sublabel`, `collapsed`, and
29`sources`. Children are read in declaration order. Links are containment only;
30the first slice has no cross-branch relationships.

Input

{
  "schema_version": 1,
  "diagram_type": "tree",
  "meta": { "title": "Payment platform capabilities" },
  "nodes": [
    { "id": "platform", "label": "Payment platform" },
    { "id": "orders", "label": "Orders", "parent": "platform" }
  ]
}

A node has id, label, and optional parent, sublabel, collapsed, and sources. Children are read in declaration order. Links are containment only; the first slice has no cross-branch relationships.

Raw lines 14 to 31
32## Structure checks
34The hierarchy is exactly what the author declared; nothing is attached or
35inferred.
37| Code | Refused input |
38| --- | --- |
39| `tree/missing-parent` | `parent` names an undeclared node |
40| `tree/root-count` | zero or more than one node without `parent` |
41| `tree/cycle` | a parent chain that loops; every node beneath the loop is unreachable, so this one diagnostic covers them |
42| `tree/duplicate-id` | an id declared twice |

Structure checks

The hierarchy is exactly what the author declared; nothing is attached or inferred.

CodeRefused input
tree/missing-parentparent names an undeclared node
tree/root-countzero or more than one node without parent
tree/cyclea parent chain that loops; every node beneath the loop is unreachable, so this one diagnostic covers them
tree/duplicate-idan id declared twice
Raw lines 32 to 43
44## Layout
46Each generation shares one band: a row for `layout.direction: "down"` (the
47default) and a column for `"right"`. Along the other axis every subtree owns a
48contiguous span, so unequal branch widths and depths never overlap. A parent is
49centred over its first and last child (exactly over a middle child that sits
50within a few pixels of that midpoint, so the stem never jogs; edge drawing also snaps stems aligned within 2px after rounding); going right,
51nodes are left-aligned in their column.
53Going down, a run of three or more consecutive leaf siblings is stacked as an
54indented list under its parent, sharing one width and reached along a spine,
55instead of fanning out across the row. This keeps a real hierarchy such as a
56repository readable at one screen's scale; shorter runs and every branch keep
57the row layout. Leaves are quiet cards; the root and branches carry the tone.
59Nodes size to their label between `layout.nodeW` (140) and `layout.nodeMaxW`
60(220 down, 200 right). Labels and sublabels wrap between words (CJK at any
61character), at the narrowest width that keeps the same number of lines, so a
62long label becomes a balanced box; a single word may widen a node to 1.5 × `nodeMaxW` before it is
63split, so nothing is truncated. `gapX`/`gapY` set the sibling and generation
64gaps.
66An automatic canvas declares `data-reader-fit="intrinsic-height"` and a 7.5px
67reader text floor, so a deep rightward tree scrolls instead of shrinking.

Layout

Each generation shares one band: a row for layout.direction: "down" (the default) and a column for "right". Along the other axis every subtree owns a contiguous span, so unequal branch widths and depths never overlap. A parent is centred over its first and last child (exactly over a middle child that sits within a few pixels of that midpoint, so the stem never jogs; edge drawing also snaps stems aligned within 2px after rounding); going right, nodes are left-aligned in their column.

Going down, a run of three or more consecutive leaf siblings is stacked as an indented list under its parent, sharing one width and reached along a spine, instead of fanning out across the row. This keeps a real hierarchy such as a repository readable at one screen's scale; shorter runs and every branch keep the row layout. Leaves are quiet cards; the root and branches carry the tone.

Nodes size to their label between layout.nodeW (140) and layout.nodeMaxW (220 down, 200 right). Labels and sublabels wrap between words (CJK at any character), at the narrowest width that keeps the same number of lines, so a long label becomes a balanced box; a single word may widen a node to 1.5 × nodeMaxW before it is split, so nothing is truncated. gapX/gapY set the sibling and generation gaps.

An automatic canvas declares data-reader-fit="intrinsic-height" and a 7.5px reader text floor, so a deep rightward tree scrolls instead of shrinking.

Raw lines 44 to 68
69## Expand and collapse
71Every node with children gets a toggle on its outgoing side, a separate
72focusable button after the node, with `aria-expanded` and a localized label
73that states how many descendants it hides. The Viewer module
74`viewer/tree-branches.js` owns the state:
76- Collapsing hides descendants and their links only. Positions are computed
77 once for the complete tree, so nothing visible moves and the reader keeps
78 their place. A collapsed node shows a stacked card and its hidden count.
79- Keyboard: Enter/Space on a toggle; ArrowLeft collapses and ArrowRight expands
80 the focused branch node. Focus stays on the control that was used.
81- **Expand all** appears at the top-left while any branch is collapsed and
82 restores the authored hierarchy.
83- Selecting a hidden node through Finder, Node Outline, guided views, or a
84 shared link expands its ancestors first.
85- `collapsed: true` only sets the initial Viewer state. The SVG always contains
86 the complete tree.
88Export scope is explicit: every SVG/PNG/JPEG/WebP export is the complete tree,
89whatever is collapsed on screen. Export Cleanup removes the collapsed state from
90the clone and leaves the live view unchanged.

Expand and collapse

Every node with children gets a toggle on its outgoing side, a separate focusable button after the node, with aria-expanded and a localized label that states how many descendants it hides. The Viewer module viewer/tree-branches.js owns the state:

  • Collapsing hides descendants and their links only. Positions are computed once for the complete tree, so nothing visible moves and the reader keeps their place. A collapsed node shows a stacked card and its hidden count.
  • Keyboard: Enter/Space on a toggle; ArrowLeft collapses and ArrowRight expands the focused branch node. Focus stays on the control that was used.
  • Expand all appears at the top-left while any branch is collapsed and restores the authored hierarchy.
  • Selecting a hidden node through Finder, Node Outline, guided views, or a shared link expands its ancestors first.
  • collapsed: true only sets the initial Viewer state. The SVG always contains the complete tree.

Export scope is explicit: every SVG/PNG/JPEG/WebP export is the complete tree, whatever is collapsed on screen. Export Cleanup removes the collapsed state from the clone and leaves the live view unchanged.

Raw lines 69 to 91
92## Tested size
94`examples/archify-repository.tree.json` (31 nodes, depth 4, unbalanced, four
95stacked lists) renders in about 0.2s and passes the showcase gates;
96a toggle updates the DOM in under a few milliseconds.

Tested size

examples/archify-repository.tree.json (31 nodes, depth 4, unbalanced, four stacked lists) renders in about 0.2s and passes the showcase gates; a toggle updates the DOM in under a few milliseconds.

Raw lines 92 to 96