@pyreon/connector-document 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +102 -4
  2. package/package.json +9 -9
package/README.md CHANGED
@@ -1,16 +1,114 @@
1
1
  # @pyreon/connector-document
2
2
 
3
- Bridge between `@pyreon/ui-system` components and `@pyreon/document` for multi-format document export.
3
+ Bridge between `@pyreon/ui-system` JSX trees and `@pyreon/document` for multi-format export.
4
+
5
+ `@pyreon/connector-document` walks a Pyreon JSX tree of document-primitive components (`DocDocument`, `DocHeading`, `DocText`, …) and produces a serializable `DocNode` tree that `@pyreon/document` can render to PDF, DOCX, XLSX, PPTX, email, Markdown, HTML, and 10+ other formats. Components carry `_documentType` markers (set via `attrs().statics()` on rocketstyle primitives, or directly on user components); the extractor finds them, resolves `_documentProps` and `$rocketstyle` styles, and recursively walks children. The hot path is fast — for real rocketstyle primitives it runs the accumulated `.attrs()` chain directly instead of invoking the full component (no JSX tree creation, no dimension resolution).
4
6
 
5
7
  ## Install
6
8
 
7
9
  ```bash
8
- bun add @pyreon/connector-document
10
+ bun add @pyreon/connector-document @pyreon/document @pyreon/core
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ ```tsx
16
+ import { extractDocumentTree } from '@pyreon/connector-document'
17
+ import { render } from '@pyreon/document'
18
+ import { DocDocument, DocHeading, DocText } from '@pyreon/document-primitives'
19
+
20
+ const vnode = (
21
+ <DocDocument title="Q4 Report" author="Acme Inc.">
22
+ <DocHeading level={1}>Summary</DocHeading>
23
+ <DocText>Revenue was up 12%.</DocText>
24
+ </DocDocument>
25
+ )
26
+
27
+ const docTree = extractDocumentTree(vnode)
28
+ const pdf = await render(docTree, 'pdf') // Buffer
29
+ const docx = await render(docTree, 'docx') // Buffer
30
+ const md = await render(docTree, 'markdown') // string
31
+ ```
32
+
33
+ In practice, you'll usually call `extractDocNode` from `@pyreon/document-primitives` — a one-step alias that wraps a template function in an extraction-friendly shape — rather than `extractDocumentTree` directly. Use `extractDocumentTree` when you already have a vnode in hand (a captured render result, a test fixture).
34
+
35
+ ## API
36
+
37
+ ### `extractDocumentTree(vnode, options?)`
38
+
39
+ Walk a JSX vnode and produce a `DocNode` tree.
40
+
41
+ ```ts
42
+ const tree = extractDocumentTree(vnode, {
43
+ rootSize: 16, // base font size for rem→px (default 16)
44
+ includeStyles: true, // resolve $rocketstyle into the DocNode.styles field (default true)
45
+ })
46
+ ```
47
+
48
+ Returns `DocNode | DocChild[] | null` (re-exported from `@pyreon/document`). String/number children are inlined as text; reactive accessors (`() => signal()`) are resolved at extraction time, so calling `extractDocumentTree` again after a signal change produces a fresh tree reflecting the live values.
49
+
50
+ **Extraction resolution order for `_documentProps`** (per primitive):
51
+
52
+ 1. **Pre-resolved on the vnode** — for test fixtures that hand-attach `_documentProps` directly.
53
+ 2. **Hoisted-attrs fast path** — real rocketstyle primitives expose `__rs_attrs` (the accumulated `.attrs()` callback chain) as a typed static. The extractor runs the chain directly: `chain.reduce((acc, fn) => Object.assign(acc, fn(props)), {})`. No styled-wrapper invocation, no dimension resolution. Production path for every Pyreon doc primitive.
54
+ 3. **Full component invocation** — legacy fallback for hand-rolled `_documentType`-marked components that don't go through rocketstyle.
55
+
56
+ ### `resolveStyles(rocketstyle, rootSize?)`
57
+
58
+ Convert a `$rocketstyle` theme object into a `ResolvedStyles` (typography, color, spacing, borders) compatible with `@pyreon/document`. Properties the document renderer doesn't support (transitions, cursor, display) are silently dropped.
59
+
60
+ ```ts
61
+ import { resolveStyles } from '@pyreon/connector-document'
62
+
63
+ const styles = resolveStyles({
64
+ fontSize: '1.5rem',
65
+ fontWeight: 'bold',
66
+ color: '#222',
67
+ padding: '12px 16px',
68
+ }, 16)
69
+ // → { fontSize: 24, fontWeight: 700, color: '#222', paddingTop: 12, paddingRight: 16, ... }
9
70
  ```
10
71
 
11
- ## Overview
72
+ ### CSS value parsers
73
+
74
+ Low-level helpers that `resolveStyles` uses internally. Useful when you need to bridge values from elsewhere into the document model.
75
+
76
+ ```ts
77
+ import {
78
+ parseCssDimension, // '1.5rem' → 24 (with rootSize=16)
79
+ parseBoxModel, // '12px 16px' → { top: 12, right: 16, bottom: 12, left: 16 }
80
+ parseFontWeight, // 'bold' → 700; 'normal' → 400; numeric strings → number
81
+ parseLineHeight, // '1.5' → { ratio: 1.5 }; '24px' → { px: 24 }
82
+ } from '@pyreon/connector-document'
83
+ ```
84
+
85
+ ### Marker contract
86
+
87
+ A component is extractable when one of these holds:
88
+
89
+ - It's a rocketstyle primitive with `_documentType` in `.meta` (set via `.statics({ _documentType: 'document' | 'heading' | ... })`).
90
+ - It's a plain function with `_documentType` as a direct static property.
91
+
92
+ `@pyreon/document-primitives` ships 18 such primitives ready to use; you can add your own following the same marker convention.
93
+
94
+ ## Types
95
+
96
+ `DocNode`, `DocChild`, `NodeType`, `ResolvedStyles` are re-exported from `@pyreon/document` — your trees stay assignment-compatible across the boundary.
97
+
98
+ ```ts
99
+ import type { DocNode, DocChild, NodeType, ResolvedStyles } from '@pyreon/connector-document'
100
+ ```
101
+
102
+ ## Gotchas
103
+
104
+ - **Reactive accessor children are resolved at extraction time, not subscribed.** Each `extractDocumentTree(vnode)` call reads the live value once. To produce a document that reflects later signal changes, call extract again.
105
+ - **`$rocketstyle` is keyed by object identity.** A theme that was constructed fresh on every render won't share the same resolved-styles bundle across extractions — minor perf concern only.
106
+ - **Unsupported CSS is silently dropped** in `resolveStyles`. `transition`, `cursor`, `display`, animations, and any non-document property fall away. The same primitive will render correctly in the browser and produce a clean PDF without modification.
107
+ - **Function values in `_documentProps` are resolved on every extraction.** `DocDocument`'s `title?: string | (() => string)` reads the LIVE accessor value at extraction time — perfect for "export current state" buttons.
108
+
109
+ ## Documentation
12
110
 
13
- Connects the Pyreon UI component system (elements, rocketstyle) with the document rendering engine, enabling components to be exported to PDF, DOCX, HTML email, and 14+ other formats.
111
+ Full docs: [docs.pyreon.dev/docs/connector-document](https://docs.pyreon.dev/docs/connector-document) (or `docs/docs/connector-document.md` in this repo).
14
112
 
15
113
  ## License
16
114
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyreon/connector-document",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Bridge between @pyreon/pyreon styled components and @pyreon/document rendering",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -42,19 +42,19 @@
42
42
  "typecheck": "tsc --noEmit"
43
43
  },
44
44
  "devDependencies": {
45
- "@pyreon/core": "^0.22.0",
46
- "@pyreon/document": "^0.22.0",
47
- "@pyreon/reactivity": "^0.22.0",
48
- "@pyreon/test-utils": "^0.13.9",
49
- "@pyreon/typescript": "^0.22.0",
45
+ "@pyreon/core": "^0.23.0",
46
+ "@pyreon/document": "^0.23.0",
47
+ "@pyreon/reactivity": "^0.23.0",
48
+ "@pyreon/test-utils": "^0.13.10",
49
+ "@pyreon/typescript": "^0.23.0",
50
50
  "@vitest/browser-playwright": "^4.1.4",
51
- "@vitus-labs/tools-rolldown": "^2.3.0"
51
+ "@vitus-labs/tools-rolldown": "^2.4.0"
52
52
  },
53
53
  "engines": {
54
54
  "node": ">= 22"
55
55
  },
56
56
  "dependencies": {
57
- "@pyreon/core": "^0.22.0",
58
- "@pyreon/document": "^0.22.0"
57
+ "@pyreon/core": "^0.23.0",
58
+ "@pyreon/document": "^0.23.0"
59
59
  }
60
60
  }