@vyaz/core 0.0.4 → 0.0.6

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 (42) hide show
  1. package/README.md +156 -0
  2. package/dist/compile/DocumentCompiler.d.ts +40 -0
  3. package/dist/index.browser.d.ts +28 -0
  4. package/dist/index.browser.js +18 -0
  5. package/dist/index.d.ts +30 -0
  6. package/dist/index.js +11 -147930
  7. package/dist/layout/AutoFitEngine.d.ts +44 -0
  8. package/dist/layout/LineBoxValidator.d.ts +25 -0
  9. package/dist/layout/ParagraphLayoutEngine.d.ts +46 -0
  10. package/dist/layout/PositioningEngine.d.ts +68 -0
  11. package/dist/layout/TextFrameLayoutEngine.d.ts +50 -0
  12. package/dist/layout/estimateWidth.d.ts +36 -0
  13. package/dist/measure/FontEngine.d.ts +47 -0
  14. package/dist/measure/FontMetricsProvider.d.ts +49 -0
  15. package/dist/measure/FontNotFoundError.d.ts +6 -0
  16. package/dist/measure/SystemFontRegistry.d.ts +46 -0
  17. package/dist/measure/canvas-polyfill.d.ts +30 -0
  18. package/dist/types/Document.d.ts +593 -0
  19. package/dist/types/FontTypes.d.ts +61 -0
  20. package/dist/types/LayoutTypes.d.ts +128 -0
  21. package/dist/utils/env.d.ts +11 -0
  22. package/dist/utils/font.d.ts +16 -0
  23. package/dist/utils/groupLinesByParagraph.d.ts +44 -0
  24. package/dist/utils/list.d.ts +41 -0
  25. package/dist/utils/textTransform.d.ts +32 -0
  26. package/package.json +30 -13
  27. package/src/compile/DocumentCompiler.ts +0 -136
  28. package/src/index.ts +0 -80
  29. package/src/layout/AutoFitEngine.ts +0 -101
  30. package/src/layout/LineBoxValidator.ts +0 -162
  31. package/src/layout/ParagraphLayoutEngine.ts +0 -202
  32. package/src/layout/PositioningEngine.ts +0 -401
  33. package/src/layout/TextFrameLayoutEngine.ts +0 -91
  34. package/src/measure/FontMetricsProvider.ts +0 -226
  35. package/src/measure/FontNotFoundError.ts +0 -16
  36. package/src/measure/SystemFontRegistry.ts +0 -151
  37. package/src/measure/canvas-polyfill.d.ts +0 -6
  38. package/src/measure/canvas-polyfill.ts +0 -235
  39. package/src/measure/fontkit.d.ts +0 -44
  40. package/src/types/Document.ts +0 -540
  41. package/src/types/FontTypes.ts +0 -74
  42. package/src/types/LayoutTypes.ts +0 -141
package/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # @vyaz/core
2
+
3
+ Rich text layout engine — TypeScript, isomorphic (browser + Bun/Node.js), pixel-perfect typography.
4
+
5
+ Part of the [Vyaz](https://github.com/sedrew/vyaz) project. Parses styled text into positioned lines with precise font metrics, supporting both CSS Text and Office (PowerPoint/DrawingML) rendering modes.
6
+
7
+ The engine operates on a **TextFrame → Paragraph → TextRun** hierarchy, following W3C CSS Text, CSS Writing Modes, and CSS Inline Layout specifications.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ bun add @vyaz/core
13
+ # or
14
+ npm install @vyaz/core
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```ts
20
+ import { layoutTextFrame } from '@vyaz/core';
21
+ import type { TextFrame } from '@vyaz/core';
22
+
23
+ const frame: TextFrame = {
24
+ width: 400,
25
+ wrap: true,
26
+ paragraphs: [
27
+ {
28
+ style: { alignment: 'left', lineHeight: 1.4, spaceBefore: 0, spaceAfter: 0 },
29
+ children: [
30
+ { text: 'Hello, Vyaz!', fontFamily: 'Arial', fontSize: 16, fontWeight: 'bold', fontStyle: 'normal', color: '#000' },
31
+ ],
32
+ },
33
+ ],
34
+ };
35
+
36
+ const result = layoutTextFrame(frame);
37
+ console.log(result.lines);
38
+ ```
39
+
40
+ ## Features
41
+
42
+ - **Text frame layout** — multi-paragraph frames with padding, wrapping, and vertical alignment
43
+ - **Multi-font, multi-style text** — bold, italic, size, color, subscript/superscript, letter-spacing
44
+ - **Text alignment** — left, center, right, justify
45
+ - **Line wrapping** — soft/hard breaks, `white-space` control (normal, nowrap, pre)
46
+ - **Writing modes** — `horizontal-tb`, `vertical-rl`, `vertical-lr` with text orientation
47
+ - **Auto-fit** — scale text proportionally to fit the container (`AutofitConfig`)
48
+ - **Inline widgets** — embedded objects (icons, images) inside the text flow
49
+ - **Office-compatible mode** — `mode: 'office'` for PowerPoint/DrawingML rendering
50
+ - **Font metrics** — system font registry with fontkit-based metric extraction
51
+ - **Compiler** — paragraph compilation with token preparation for external renderers
52
+
53
+ ## API Overview
54
+
55
+ ### Text Frame Layout
56
+
57
+ ```ts
58
+ import { layoutTextFrame } from '@vyaz/core';
59
+ import type { TextFrame, TextFrameLayoutResult } from '@vyaz/core';
60
+
61
+ const frame: TextFrame = {
62
+ width: 600,
63
+ height: 400,
64
+ wrap: true,
65
+ padding: { top: 20, right: 20, bottom: 20, left: 20 },
66
+ verticalAlignment: 'top',
67
+ paragraphs: [
68
+ {
69
+ style: { alignment: 'left', lineHeight: 1.4, spaceBefore: 0, spaceAfter: 12 },
70
+ children: [
71
+ { text: 'First paragraph', fontFamily: 'Arial', fontSize: 16, fontWeight: 'normal', fontStyle: 'normal', color: '#000' },
72
+ ],
73
+ },
74
+ ],
75
+ };
76
+
77
+ const result: TextFrameLayoutResult = layoutTextFrame(frame);
78
+ // → { lines: Line[], frameWidth?, frameHeight?, contentWidth, contentHeight, fitHorizontal, fitVertical }
79
+ ```
80
+
81
+ ### Autofit
82
+
83
+ ```ts
84
+ import { applyScale, findScale } from '@vyaz/core';
85
+ import type { AutoFitOptions, AutoFitResult } from '@vyaz/core';
86
+
87
+ const scale: AutoFitResult = findScale(contentWidth, contentHeight, frameWidth, frameHeight);
88
+ const scaledLines = applyScale(result.lines, scale);
89
+ ```
90
+
91
+ ### Font Registration & Metrics
92
+
93
+ ```ts
94
+ import {
95
+ FontMetricsProvider,
96
+ SystemFontRegistry,
97
+ createFontFace,
98
+ getFontBuffer,
99
+ } from '@vyaz/core';
100
+ import type { FontMetrics, IFontMetricsProvider, FontFace } from '@vyaz/core';
101
+
102
+ const provider = new FontMetricsProvider();
103
+
104
+ // Node.js — register from a local file
105
+ import { readFileSync } from 'node:fs';
106
+ const buffer = readFileSync('/path/to/font.ttf');
107
+ await provider.registerFont('MyFont', { weight: 'bold', style: 'normal' }, buffer);
108
+
109
+ // Browser — register from a URL
110
+ await provider.registerFont('MyFont', {}, 'https://example.com/font.woff2');
111
+
112
+ // Get pixel metrics
113
+ const metrics: FontMetrics = provider.getMetrics('MyFont', 16);
114
+ // → { ascent, descent, capHeight, unitsPerEm, sourceTable }
115
+ ```
116
+
117
+ ### Compiler
118
+
119
+ ```ts
120
+ import { compileParagraph, getParagraphText, makeFontToken } from '@vyaz/core';
121
+ import type { PreparedRichInlineItem } from '@vyaz/core';
122
+
123
+ const items: PreparedRichInlineItem[] = compileParagraph(paragraph, defaultStyle);
124
+ const text: string = getParagraphText(paragraph);
125
+ const token: string = makeFontToken(fontFamily, fontSize, fontWeight, fontStyle);
126
+ ```
127
+
128
+ ### Paragraph Layout Engine (low-level)
129
+
130
+ ```ts
131
+ import { ParagraphLayoutEngine, paragraphLayoutEngine } from '@vyaz/core';
132
+
133
+ const engine = new ParagraphLayoutEngine();
134
+ const result = engine.layout(paragraph, maxWidth, yOffset);
135
+ // → ParagraphLayoutResult { lines: Line[], width, height, contentWidth, contentHeight }
136
+ ```
137
+
138
+ ## Package Structure
139
+
140
+ ```
141
+ src/
142
+ ├── compile/ — DocumentCompiler, paragraph→token compilation
143
+ ├── layout/ — Layout engines (Paragraph, TextFrame, Positioning, AutoFit)
144
+ ├── measure/ — Font metrics, fontkit integration, system font registry
145
+ ├── types/ — TypeScript type definitions (Document, Font, Layout)
146
+ └── utils/ — Helpers (font, list, text transform, env detection)
147
+ ```
148
+
149
+ ## Requirements
150
+
151
+ - **Runtime**: Bun 1.x, Node.js 18+, or modern browser
152
+ - **Optional**: `@napi-rs/canvas`, `fontkit`, `get-system-fonts` for Node.js font metrics
153
+
154
+ ## License
155
+
156
+ MIT
@@ -0,0 +1,40 @@
1
+ /**
2
+ * DocumentCompiler.ts — compile Paragraph → PreparedRichInlineItem[].
3
+ *
4
+ * Each TextRun becomes a RichInlineItem for pretext.
5
+ * inline-box: text → \uFFFC, dimensions in metadata.inlineWidget.
6
+ * super/sub: fontSize *= 0.65, baselineOffset in metadata.
7
+ *
8
+ * Simple JSON-serialisable format — does not depend on pretext directly.
9
+ */
10
+ import type { Paragraph, TextRun } from '../types/Document.js';
11
+ export declare const FONT_WEIGHTS: Record<string, number>;
12
+ /** Normalize fontWeight to a numeric value (400 by default). */
13
+ export declare function normalizeFontWeight(weight: number | string | undefined): number;
14
+ /** Font token for pretext: "${style}_${weight}_${fontSize}_${family}" */
15
+ export declare function makeFontToken(run: TextRun, effectiveFontSize: number): string;
16
+ /** Compilation context (passed to pretext) */
17
+ export interface PreparedRichInlineItem {
18
+ text: string;
19
+ font: string;
20
+ letterSpacing?: number;
21
+ extraWidth?: number;
22
+ break?: 'normal' | 'never';
23
+ /** Original text before text-transform (if transform was applied). Used for copy-paste / round-trip. */
24
+ originalText?: string;
25
+ metadata: {
26
+ originalRunIndex: number;
27
+ baselineOffset: number;
28
+ effectiveFontSize: number;
29
+ style: TextRun;
30
+ inlineWidget?: TextRun['inlineWidget'];
31
+ };
32
+ }
33
+ /**
34
+ * Compile a paragraph into PreparedRichInlineItem[].
35
+ */
36
+ export declare function compileParagraph(paragraph: Paragraph): PreparedRichInlineItem[];
37
+ /**
38
+ * Get the full text of a paragraph (for INDEX_CONSIST checks).
39
+ */
40
+ export declare function getParagraphText(paragraph: Paragraph): string;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @vyaz/core — Browser entry point.
3
+ *
4
+ * Re-exports everything from the main index **except** `SystemFontRegistry`
5
+ * and `systemFontRegistry`, which require Node.js built-in modules
6
+ * (`node:fs`, `get-system-fonts`).
7
+ *
8
+ * All server-only code paths are guarded by runtime checks (`isNodeLike`)
9
+ * so tree-shakers can safely eliminate dead branches.
10
+ *
11
+ * ✅ Safe for Vite / webpack / Rollup / esbuild browser builds.
12
+ */
13
+ export type { TextFrame, Paragraph, ParagraphStyle, TextRun, InlineWidget, AutofitConfig, TextAlignment, WritingMode, TextOrientation, VerticalAlignment, ScriptType, WhiteSpace, MultiColumnConfig, DominantBaseline, LineFitEdge, TextAlignLast, WordBreak, LineBreak, OverflowWrap, TextDecorationStyle, TextTransform, ListType, NumberFormat, ListStylePosition, ListStyle, } from './types/Document.js';
14
+ export { DEFAULT_PARAGRAPH_STYLE, DEFAULT_TEXT_STYLE, } from './types/Document.js';
15
+ export type { ParagraphLayoutResult, Line, Span, SpanFontMetrics, SemanticParagraph, SemanticLine, SemanticFragment, } from './types/LayoutTypes.js';
16
+ export type { FontMetrics, IFontMetricsProvider, GlyphData, } from './types/FontTypes.js';
17
+ export { ParagraphLayoutEngine, paragraphLayoutEngine } from './layout/ParagraphLayoutEngine.js';
18
+ export { positionLines } from './layout/PositioningEngine.js';
19
+ export { assertLineInvariants, linesToYAML } from './layout/LineBoxValidator.js';
20
+ export type { InvariantError } from './layout/LineBoxValidator.js';
21
+ export { layoutTextFrame } from './layout/TextFrameLayoutEngine.js';
22
+ export type { TextFrameLayoutResult } from './layout/TextFrameLayoutEngine.js';
23
+ export { applyScale, findScale } from './layout/AutoFitEngine.js';
24
+ export type { AutoFitOptions, AutoFitResult } from './layout/AutoFitEngine.js';
25
+ export { compileParagraph, getParagraphText, makeFontToken } from './compile/DocumentCompiler.js';
26
+ export type { PreparedRichInlineItem } from './compile/DocumentCompiler.js';
27
+ export { FontMetricsProvider, fontMetricsProvider } from './measure/FontMetricsProvider.js';
28
+ export { FontNotFoundError } from './measure/FontNotFoundError.js';
@@ -0,0 +1,18 @@
1
+ export {
2
+ positionLines,
3
+ paragraphLayoutEngine,
4
+ makeFontToken,
5
+ linesToYAML,
6
+ layoutTextFrame,
7
+ getParagraphText,
8
+ fontMetricsProvider,
9
+ findScale,
10
+ compileParagraph,
11
+ assertLineInvariants,
12
+ applyScale,
13
+ ParagraphLayoutEngine,
14
+ FontNotFoundError,
15
+ FontMetricsProvider,
16
+ DEFAULT_TEXT_STYLE,
17
+ DEFAULT_PARAGRAPH_STYLE
18
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @vyaz/core — Public API.
3
+ *
4
+ * Exports input types (Logical level), output types (Physical Box Model),
5
+ * layout engines, font metric providers, renderers, and utilities.
6
+ */
7
+ export type { TextFrame, Paragraph, ParagraphStyle, TextRun, InlineWidget, AutofitConfig, TextAlignment, WritingMode, TextOrientation, VerticalAlignment, ScriptType, WhiteSpace, MultiColumnConfig, DominantBaseline, LineFitEdge, TextAlignLast, WordBreak, LineBreak, OverflowWrap, TextDecorationStyle, TextTransform, ListType, NumberFormat, ListStylePosition, ListStyle, } from './types/Document.js';
8
+ export { DEFAULT_PARAGRAPH_STYLE, DEFAULT_TEXT_STYLE, } from './types/Document.js';
9
+ export type { ParagraphLayoutResult, Line, Span, SpanFontMetrics, SemanticParagraph, SemanticLine, SemanticFragment, } from './types/LayoutTypes.js';
10
+ export type { FontMetrics, IFontMetricsProvider, GlyphData, } from './types/FontTypes.js';
11
+ export { ParagraphLayoutEngine, paragraphLayoutEngine } from './layout/ParagraphLayoutEngine.js';
12
+ export { positionLines } from './layout/PositioningEngine.js';
13
+ export { assertLineInvariants, linesToYAML } from './layout/LineBoxValidator.js';
14
+ export type { InvariantError } from './layout/LineBoxValidator.js';
15
+ export { layoutTextFrame } from './layout/TextFrameLayoutEngine.js';
16
+ export type { TextFrameLayoutResult } from './layout/TextFrameLayoutEngine.js';
17
+ export { applyScale, findScale } from './layout/AutoFitEngine.js';
18
+ export type { AutoFitOptions, AutoFitResult } from './layout/AutoFitEngine.js';
19
+ export { groupLinesByParagraph } from './utils/groupLinesByParagraph.js';
20
+ export type { ParagraphGroup } from './utils/groupLinesByParagraph.js';
21
+ export { transformText } from './utils/textTransform.js';
22
+ export { formatListNumber, defaultBulletChar, BULLET_CHARACTERS } from './utils/list.js';
23
+ export { compileParagraph, getParagraphText, makeFontToken } from './compile/DocumentCompiler.js';
24
+ export type { PreparedRichInlineItem } from './compile/DocumentCompiler.js';
25
+ export type { FontFace } from './measure/FontEngine.js';
26
+ export { createFontFace, getGlyphAdvance, computePixelMetrics, isFontEngineAvailable } from './measure/FontEngine.js';
27
+ export { FontMetricsProvider, fontMetricsProvider } from './measure/FontMetricsProvider.js';
28
+ export { SystemFontRegistry, systemFontRegistry } from './measure/SystemFontRegistry.js';
29
+ export { getFontBuffer } from './utils/font.js';
30
+ export { FontNotFoundError } from './measure/FontNotFoundError.js';