Skip to content

Refactor to pure functions: remove state registries from core API#3

Open
gerchowl wants to merge 14 commits into
masterfrom
claude/add-claude-documentation-Nh6H8
Open

Refactor to pure functions: remove state registries from core API#3
gerchowl wants to merge 14 commits into
masterfrom
claude/add-claude-documentation-Nh6H8

Conversation

@gerchowl
Copy link
Copy Markdown
Owner

@gerchowl gerchowl commented Mar 4, 2026

Summary

This PR refactors Blueprint's core API from a state-based architecture to pure functions, eliminating global registries and making components, connectors, edges, and styles plain data structures. This improves composability, testability, and eliminates context-dependent errors.

Key Changes

Core API Refactoring:

  • component() now returns a plain dictionary instead of registering to component-registry
  • component-extend() takes a component object directly (not a name string) and returns a new component
  • place-component() now takes a component object and returns an updated component with new position
  • connector() returns a plain dictionary; removed connector-registry state
  • edge-style() returns a plain dictionary; removed edge-style-registry state
  • Removed style() function and style-registry state (styles are now inline dictionaries)
  • Removed canvas-registry and object-registry states
  • create-canvas() is now a pure function returning canvas info without state updates

Layout & Positioning:

  • relative() now takes a reference object dictionary directly instead of looking up by name
  • Removed register-object() and get-object() functions
  • Positioning is now explicit via function parameters rather than implicit state

Edge Rendering:

  • edge-style() is now a pure function
  • Removed get-edge-style() lookup function
  • Edge routing functions (route-direct, route-rectangular, route-manhattan) remain pure

Test Updates:

  • Updated all test files to work with the new pure function API
  • Tests now pass component objects directly to place-component() instead of component names
  • Added comprehensive new tests: component-connectors, component-inheritance, edge-routing, render-modes, styles-and-themes, computer-architecture, datacenter-architecture
  • Added visual regression test reference images for all test suites

Documentation & Tooling:

  • Added CLAUDE.md with project overview and development commands
  • Added .claude/ directory with Claude Code settings, skills, rules, and agents for development workflow
  • Updated tests/README.md with current test structure
  • Updated examples/simple.typ to demonstrate new API
  • Updated .gitignore to protect test reference images

Implementation Details

  • Components are now immutable data structures; modifications return new components
  • The position parameter was added to component() to support initial positioning
  • component-extend() now recalculates bounds after merging properties
  • All state-dependent lookups have been replaced with direct object passing
  • The unified model for primitives (as minimal components) is preserved and working correctly

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K

claude added 9 commits March 2, 2026 23:42
- Streamline CLAUDE.md with @path imports for PRD and test README
- Add .claude/settings.json with project permissions (just, typst, tt)
- Add .claude/rules/ with path-scoped rules for source, tests, examples
- Add .claude/skills/ for test, build, docs, and new-test workflows

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
- PostToolUse hook: verify src/lib.typ compiles after .typ file edits
- Notification hook: cross-platform desktop alert when Claude needs input

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
- Add typst-explorer subagent (read-only, Haiku) for codebase exploration
- Add PreToolUse hook to protect test reference images from direct edits
- Add SessionStart compact hook to re-inject key project context
- Update .gitignore for Claude Code local files (settings.local, worktrees)

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
…e, example, review

- /add-primitive: scaffold a new primitive type following the unified model
- /add-component: create a reusable component with connectors
- /debug-state: diagnose state registry / context expression issues
- /example: create a new example file with the correct template
- /review: code review against Blueprint conventions (runs in typst-explorer subagent)

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
…ones

Analyzes current code against v0.2.0 milestone checklist from PRD.md,
identifies blockers, and suggests implementation order.

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
The 4 component tests (component-borders-rect, component-borders-circle,
component-borders-ellipse, nested-components) were duplicated in both
tests/ and tests/_component-tests-disabled/ with identical content.
The active copies can't pass because place-component() uses state().get()
which requires context expressions. Remove the active copies; the
canonical versions remain in _component-tests-disabled/.

Also clarifies that no reference images have been generated yet
(ref/ directories don't exist), and that the disabled tests are still
relevant to the current API.

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
…ests

Major architectural change: all factory functions are now pure (return plain
dicts, no state() usage). This eliminates the context expression requirement
that blocked component tests and removes the return-discards-content warning.

Fixes:
- Remove all state() registries from factory functions (component, connector,
  style, canvas, edge-style) — everything is now pure data flow
- Implement calculate-bounds() in utils.typ (was placeholder returning zeros)
- Implement arrow mark rendering in edge.typ with proper arrowhead triangles
- Fix length*length arithmetic in arrowhead math (convert to pt floats)
- Fix relative-with-anchor() to account for target object bounds
- Replace error() calls with panic() (correct Typst function)

New features:
- Arrow marks: ->, <-, <->, -, with colored arrowheads matching stroke
- Dashed edge support via dash parameter
- Style inheritance via base parameter
- Component inheritance via component-extend() (fully working)
- Three render modes (detailed/collapsed/high-level) all functional

Tests (13 total, all passing):
- Re-enabled 4 previously disabled component tests
- Added 5 new tests: edge-routing, component-connectors,
  component-inheritance, render-modes, styles-and-themes
- Generated reference images for all 13 tests

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
Fix two-layer rendering (draw-item/draw-content) to properly translate
nested placed components using CeTZ scope+translate. Fix
calculate-content-bounds to offset item bounds by placement position.

Add computer-architecture test (CPU with nested cache hierarchy, memory
controller, PCIe subsystem, edges in single canvas) and
datacenter-architecture test (rack with ToR switch, servers, storage,
network edges, collapsed/high-level views). All 15 tests passing.

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
Repository owner deleted a comment from cursor Bot Mar 4, 2026
claude added 5 commits March 4, 2026 18:42
…ring

- Primitives: add optional `label` parameter that renders text at center
- Components: auto-render name above border (detailed) or centered (collapsed)
- Connectors: add `side`/`offset` parameters for border-relative positioning
  (e.g., side: "bottom", offset: 0.3 places connector at 30% along bottom edge)
- Rewrite computer-architecture and datacenter-architecture tests with:
  - Labels on all primitives (ALU, Regs, L1$, CPU, RAM, NIC, Disk 1-4, etc.)
  - Border-relative connectors that sit exactly on component edges
  - Edges connecting to actual connector positions via conn-abs helper
  - Internal cache hierarchy edges within CPU package
- Update all 15 test reference images for name label rendering

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
- Fix anchor-to-offset to use Y-up semantics (top=1.0, bottom=0.0)
- Fix relative() and relative-with-anchor() to include bounds.x/y offset
- Fix primitive anchor dicts for Y-up consistency
- Add relative-positioning test: datacenter rack built with relative-with-anchor()
  instead of hardcoded absolute coordinates (16 tests, all passing)

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
- route-manhattan now accepts from-side/to-side parameters for connector
  border awareness. Edges leave/arrive perpendicular to their border.
- Algorithm uses stub segments for clean departure/arrival, then connects
  with minimal turns: L-shape (1 turn) for adjacent sides, bridge (2 turns)
  for opposite/same sides. Collinear points are cleaned up.
- connect-points accepts from-side/to-side hints; connect() auto-detects
  side from connector dicts.
- Edge-routing test rewritten with labeled sections demonstrating all
  routing modes, side combinations, and component integration.

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
- tools/sql_to_blueprint.py: Python script that queries a SQLite database
  (datacenters → racks → switches/servers → NICs/disks → links) and generates
  Blueprint Typst code with relative positioning and Manhattan routing.
- Complex schema: 10 tables (datacenters, racks, switches, servers, nics,
  disks, links, vlans, vlan_assignments), populated with 2 DCs, 4 racks,
  4 switches, 8 servers, 15 NICs, 16 disks, 10 network links.
- Generated diagrams are color-coded by role (compute=blue, storage=orange,
  gpu=pink), with cable-type colored edges (copper=green, DAC=orange, fiber=red).
- New test: sql-generated (17 tests, all passing).

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
- Edge labels: `label:` parameter on `edge-style()` and `connect-points()`,
  rendered at midpoint of longest segment
- Layout combinators: `stack()` for vertical/horizontal placement,
  `grid()` for row-major grid layout with configurable columns and gaps
- Instance badges: `render-name-label()` shows "×N" when component has
  `instance-count > 1`
- SQL generator: updated to use `stack()` combinator and edge labels
  showing link speeds (10G, 25G, 100G) with cable-type coloring

All 17 tests pass.

https://claude.ai/code/session_01LDjYnYKJGMSvxVt7dTEu2K
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.

2 participants