Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
bcb58bf
packages: extract framework-neutral serialization core into @formepdf…
cmjoseph07 Jul 3, 2026
7b3aec3
packages/svelte: add Svelte adapter walking skeleton
cmjoseph07 Jul 3, 2026
3e6e185
feat(svelte): add text runs, Fixed, and page-number constants
cmjoseph07 Jul 19, 2026
3dfb6b5
feat(svelte): add Table, Row, and Cell components
cmjoseph07 Jul 19, 2026
0137ead
feat(svelte): add Image, Svg, QrCode, and Barcode components
cmjoseph07 Jul 19, 2026
91ead56
feat(svelte): add Canvas, Watermark, and PageBreak components
cmjoseph07 Jul 19, 2026
c7f2890
feat(svelte): add chart components via shared kind builders
cmjoseph07 Jul 19, 2026
72606d4
feat(svelte): add form field components for fillable PDFs
cmjoseph07 Jul 19, 2026
a7d63d8
style(svelte): replace em dashes with plain dashes
cmjoseph07 Jul 19, 2026
bb5de07
feat(svelte): add font registration, StyleSheet parity, and tw() support
cmjoseph07 Jul 19, 2026
d797d7e
feat(svelte): add renderDocument wrapper over optional @formepdf/core
cmjoseph07 Jul 19, 2026
d6f5e11
feat(svelte): add SvelteKit preview route helper
cmjoseph07 Jul 19, 2026
8b79436
docs(svelte): add adapter docs page, package README, and changelog en…
cmjoseph07 Jul 19, 2026
14d50a3
chore(svelte): align package versions with 0.10.5 monorepo line
cmjoseph07 Jul 19, 2026
1aeedc6
feat(svelte): add headings, lists, and inline formatting components
cmjoseph07 Jul 19, 2026
886bda6
fix(svelte): review fixes - Page style prop, preview 503 hygiene, CI …
cmjoseph07 Jul 19, 2026
e7f67b2
chore: refresh package-lock for shared and svelte workspaces
cmjoseph07 Jul 19, 2026
ed1cc8a
fix(svelte): type PDF bytes as ArrayBuffer-backed for BodyInit
cmjoseph07 Jul 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,18 @@ jobs:
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Install dependencies
run: npm install
- name: Build Shared package
working-directory: packages/shared
run: npm run build
- name: Build React package
working-directory: packages/react
run: npm run build
- name: Build Svelte package
working-directory: packages/svelte
run: npm run build
- name: Check Svelte package (svelte-check)
working-directory: packages/svelte
run: npm run check
- name: Build Templates
working-directory: packages/templates
run: npm run build
Expand All @@ -65,6 +74,11 @@ jobs:
- name: Test React
working-directory: packages/react
run: npm test
- name: Test Svelte
# After Build Core: the WASM smoke + renderDocument tests render
# through @formepdf/core (devDependency).
working-directory: packages/svelte
run: npm test
- name: Test Core
working-directory: packages/core
run: npm test
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ packages/vscode/pkg/
# Node
node_modules/
dist/
.svelte-kit/

# OS
.DS_Store
Expand Down Expand Up @@ -44,3 +45,6 @@ test-*.tsx
test-*.json
/tmp/
*.pdf

# Generated preview HTML embed (packages/svelte build step)
packages/svelte/src/preview/preview-html.generated.ts
35 changes: 27 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,31 @@ forme/
│ ├── grid-dashboard.tsx # Multi-feature showcase (grid, charts, i18n, RTL)
│ └── grid-dashboard-data.json
└── packages/
├── shared/ # Framework-neutral core shared by authoring adapters
│ └── src/
│ ├── index.ts # Public exports
│ ├── types.ts # Document-model (Forme*) types + Style
│ ├── style.ts # mapStyle + CSS shorthand/color/edge/grid/transform parsing
│ ├── font.ts # Font.register() store + font merging
│ ├── canvas.ts # CanvasContext recorder for <Canvas> draw callbacks
│ ├── charts.ts # Chart kind builders (camelCase to snake_case prop mapping)
│ └── semantics.ts # Heading/inline-formatting defaults + list marker mapping
├── svelte/ # Svelte 5 adapter: same components authored as .svelte files
│ └── src/
│ ├── index.ts # Public exports
│ ├── components/ # One .svelte file per component, emitting placeholder tags
│ ├── serialize.ts # SSR render + parse entry points (serialize/render)
│ ├── parser.ts # Placeholder markup to Forme document model
│ ├── encode.ts # Props JSON round-trip (byte markers for Uint8Array)
│ ├── render-document.ts # One-call PDF rendering over optional @formepdf/core
│ └── preview/ # formePreview() SvelteKit route helper
├── react/ # JSX component library: <Document>, <Page>, <View>, etc.
│ └── src/
│ ├── index.ts # Public exports
│ ├── components.tsx # Component definitions
│ ├── charts.tsx # BarChart, LineChart, PieChart
│ ├── font.ts # Font.register() static API + global font store
│ ├── serialize.ts # JSX → JSON document tree + font merging
│ ├── font.ts # Re-exports the Font store from @formepdf/shared
│ ├── serialize.ts # JSX → JSON document tree
│ ├── template-proxy.ts # Recording proxy for template compilation
│ └── expr.ts # Expression helpers for templates
├── core/ # WASM bridge: compiles engine to WebAssembly
Expand Down Expand Up @@ -90,7 +108,7 @@ forme/
```

### Renderer Package (`@formepdf/renderer`)
Shared render pipeline extracted from the CLI dev server so that VS Code (and future integrations) reuse the same bundling, font/image resolution, and WASM rendering code. Key exports: `bundle()` (esbuild TSX → JS), `resolveFonts()` / `resolveImages()` (file paths → base64), `renderPdf()` / `renderLayout()` (JS → WASM → bytes/JSON). The preview HTML (`src/preview/index.html`) supports dual mode: standalone for CLI dev server, and VS Code webview (receives messages instead of fetching endpoints). Build order: `react` → `core` → `renderer` → `cli` / `vscode`.
Shared render pipeline extracted from the CLI dev server so that VS Code (and future integrations) reuse the same bundling, font/image resolution, and WASM rendering code. Key exports: `bundle()` (esbuild TSX → JS), `resolveFonts()` / `resolveImages()` (file paths → base64), `renderPdf()` / `renderLayout()` (JS → WASM → bytes/JSON). The preview HTML (`src/preview/index.html`) supports dual mode: standalone for CLI dev server, and VS Code webview (receives messages instead of fetching endpoints). Build order: `shared` → `react` → `core` → `renderer` → `cli` / `vscode`.

### VS Code Extension (`forme-pdf`)
Live PDF preview inside VS Code. Architecture: `LayoutStore` is the central event-emitting store — preview panel, component tree, and inspector all subscribe to it, staying decoupled from each other. The preview panel uses the same `index.html` from `@formepdf/renderer` (VS Code mode). Component tree (`TreeView` sidebar) shows the element hierarchy with hover-to-highlight. Inspector (`WebviewView` sidebar) shows box model visualization, computed styles, "Open in Editor" (maps element source locations to editor), and "Copy Style". The extension watches `.tsx` files and re-renders on save.
Expand All @@ -106,9 +124,10 @@ cd engine && cargo fmt && cargo clippy -- -W clippy::all

**TypeScript (if any `packages/` files changed):**
```bash
# Build affected packages (build order: react → core → cli)
# Build affected packages (build order: shared → react → core → cli)
# Run tsc for each changed package, e.g.:
cd packages/react && npm run build
cd packages/svelte && npm run build
cd packages/core && npm run build
cd packages/mcp && npm run build
```
Expand Down Expand Up @@ -221,7 +240,7 @@ Users register custom TrueType fonts via `Font.register()` (global, react-pdf co
2. **Rendering layer** (`core/index.ts` or `cli/dev.ts`): Resolves font sources to base64 before passing JSON to WASM. File paths are read from disk; `Uint8Array` is base64-encoded; data URIs pass through as-is. In the CLI dev server, file paths resolve relative to the template directory.
3. **Engine** (`lib.rs`): `register_document_fonts()` decodes base64 from each `FontEntry` and calls `FontContext.registry_mut().register()` before layout. The existing `FontRegistry`, `CustomFontMetrics`, and PDF subsetting handle everything from there.

Key files: `packages/react/src/font.ts`, `packages/react/src/serialize.ts` (mergeFonts), `packages/core/src/index.ts` (resolveFonts), `packages/cli/src/dev.ts` (resolveFontPaths), `engine/src/lib.rs` (register_document_fonts), `engine/src/model/mod.rs` (FontEntry).
Key files: `packages/shared/src/font.ts` (Font store, mergeFonts), `packages/react/src/serialize.ts`, `packages/core/src/index.ts` (resolveFonts), `packages/cli/src/dev.ts` (resolveFontPaths), `engine/src/lib.rs` (register_document_fonts), `engine/src/model/mod.rs` (FontEntry).

Merge strategy: fonts are keyed by `family:weight:italic`. Document fonts override global fonts on conflict.

Expand All @@ -236,8 +255,8 @@ Templates enable a hosted API workflow: store template JSON + dynamic data → p

Key files: `engine/src/template.rs`, `engine/src/lib.rs` (render_template), `engine/src/wasm.rs` (render_template_pdf), `packages/react/src/template-proxy.ts`, `packages/react/src/expr.ts`, `packages/react/src/serialize.ts` (serializeTemplate), `packages/core/src/index.ts` (renderTemplate), `packages/cli/src/template-build.ts` (buildTemplate), `packages/cli/src/index.ts` (--template flag).

### CSS String Shorthands (React layer only)
Parsed in `mapStyle()` in `serialize.ts` no engine changes needed. Three capabilities:
### CSS String Shorthands (TypeScript layer only)
Parsed in `mapStyle()` in `packages/shared/src/style.ts` - no engine changes needed. Three capabilities:

1. **Border shorthand**: `border: "1px solid #000"` → parses into `borderWidth` + `borderColor`. Per-side variants: `borderTop: "2px solid #f00"` or `borderBottom: 3` (number = width only). `parseBorderString()` tokenizes by whitespace, recognizes CSS border-style keywords (ignored), numeric tokens (width), and color tokens.
2. **Edge strings**: `padding: "8 16"` or `margin: "8 16 24 32"` → CSS 1-4 value shorthand. Optional `px` suffix stripped. `parseCSSEdges()` handles the parsing.
Expand Down Expand Up @@ -277,7 +296,7 @@ Backward-compatible: a single family name (no comma) behaves identically to the
Standard font `char_width()` in `font/metrics.rs` maps Unicode codepoints through `unicode_to_winansi()` before looking up glyph widths. Characters like em-dash (U+2014), en-dash (U+2013), smart quotes, ellipsis, etc. have Unicode code points above 255 but their widths are stored at WinAnsi positions (0x80–0x9F). The shared `unicode_to_winansi()` function in `font/metrics.rs` is also used by `PdfSerializer` for PDF text encoding — single source of truth for the Windows-1252 mapping.

### Grid repeat() Syntax
React-layer only. `expandRepeat()` in `serialize.ts` pre-processes grid template strings, expanding `repeat(N, tracks)` before the existing split-on-whitespace logic. Example: `repeat(3, 1fr)` → `1fr 1fr 1fr`. Supports mixed: `200 repeat(2, 1fr) 200` → `200 1fr 1fr 200`.
TypeScript-layer only. `expandRepeat()` in `packages/shared/src/style.ts` pre-processes grid template strings, expanding `repeat(N, tracks)` before the existing split-on-whitespace logic. Example: `repeat(3, 1fr)` → `1fr 1fr 1fr`. Supports mixed: `200 repeat(2, 1fr) 200` → `200 1fr 1fr 200`.

### Alt Text, Document Language, Clickable Images/SVGs
- **Alt text**: `alt` prop on `<Image>` and `<Svg>` flows through `Node.alt` → `LayoutElement.alt`. Carried through the data model for future tagged PDF support (actual `/Alt` emission requires structure elements — follow-up scope).
Expand Down
2 changes: 1 addition & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
},
{
"group": "Reference",
"pages": ["components", "styles", "tailwind", "fonts", "page-breaks", "charts", "templates", "embedded-data", "self-hosting"]
"pages": ["components", "styles", "tailwind", "svelte", "fonts", "page-breaks", "charts", "templates", "embedded-data", "self-hosting"]
},
{
"group": "API Reference",
Expand Down
Loading