@vyaz/renderer 0.1.0 → 0.3.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.
- package/README.md +121 -0
- package/dist/SVGRenderer.d.ts +20 -1
- package/dist/SVGRenderer.d.ts.map +1 -1
- package/dist/TableRenderer.d.ts +59 -0
- package/dist/TableRenderer.d.ts.map +1 -0
- package/dist/index.browser.d.ts +4 -0
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +296 -63
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +141788 -63
- package/dist/register-font.d.ts +28 -0
- package/dist/register-font.d.ts.map +1 -0
- package/package.json +11 -2
- package/dist/tsconfig.tsbuildinfo +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# @vyaz/renderer
|
|
2
|
+
|
|
3
|
+
SVG renderer for [`@vyaz/core`](https://www.npmjs.com/package/@vyaz/core) layout
|
|
4
|
+
output — both a plain `TextFrame` and a `TableFrame` grid.
|
|
5
|
+
|
|
6
|
+
Part of the [Vyaz](https://github.com/sedrew/vyaz) project.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
bun add @vyaz/core @vyaz/renderer
|
|
10
|
+
# or
|
|
11
|
+
npm install @vyaz/core @vyaz/renderer
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Quick start — text
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { layoutTextFrame } from '@vyaz/core'
|
|
18
|
+
import { renderToSVG } from '@vyaz/renderer'
|
|
19
|
+
import type { TextFrame } from '@vyaz/core'
|
|
20
|
+
|
|
21
|
+
const frame: TextFrame = {
|
|
22
|
+
width: 400,
|
|
23
|
+
wrap: true,
|
|
24
|
+
paragraphs: [
|
|
25
|
+
{
|
|
26
|
+
style: { alignment: 'left', lineHeight: 1.4, spaceBefore: 0, spaceAfter: 0 },
|
|
27
|
+
children: [
|
|
28
|
+
{ type: 'text', text: 'Hello, ', fontFamily: 'Inter', fontSize: 16, fontWeight: 'normal', fontStyle: 'normal', color: '#111' },
|
|
29
|
+
{ type: 'text', text: 'Vyaz!', fontFamily: 'Inter', fontSize: 16, fontWeight: 'bold', fontStyle: 'normal', color: '#111' },
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const svg = renderToSVG(layoutTextFrame(frame), { preset: 'browser' })
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick start — tables
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import { layoutTableFrame } from '@vyaz/core'
|
|
42
|
+
import { renderTableToSVG } from '@vyaz/renderer'
|
|
43
|
+
import type { TableFrame } from '@vyaz/core'
|
|
44
|
+
|
|
45
|
+
const cell = (text: string) => ({
|
|
46
|
+
content: {
|
|
47
|
+
wrap: true,
|
|
48
|
+
paragraphs: [{
|
|
49
|
+
style: { alignment: 'left', lineHeight: 1.3, spaceBefore: 0, spaceAfter: 0 },
|
|
50
|
+
children: [{ type: 'text', text, fontFamily: 'Inter', fontSize: 14, fontWeight: 'normal', fontStyle: 'normal', color: '#111' }],
|
|
51
|
+
}],
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const table: TableFrame = {
|
|
56
|
+
defaultCellStyle: { paddings: 8, borderWidths: 1, borderColors: '#ccc' },
|
|
57
|
+
rows: [
|
|
58
|
+
{ style: { bgColor: '#eee' }, cells: [cell('Name'), cell('Qty')] },
|
|
59
|
+
{ cells: [cell('Widget'), cell('3')] },
|
|
60
|
+
],
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const svg = renderTableToSVG(layoutTableFrame(table), { preset: 'browser' })
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`renderTableToSVG` paints table/row/cell backgrounds and borders (solid,
|
|
67
|
+
dashed, rounded corners), each cell's text content, `colSpan`/`rowSpan`,
|
|
68
|
+
`before`/`after` decorative slots, and tables nested inside a cell — see the
|
|
69
|
+
[Tables guide](https://sedrew.github.io/vyaz/guide/tables) for the full style
|
|
70
|
+
surface.
|
|
71
|
+
|
|
72
|
+
## Text presets
|
|
73
|
+
|
|
74
|
+
| Preset | Structure | Use case |
|
|
75
|
+
|--------|-----------|----------|
|
|
76
|
+
| `flat` | Single `<text>` with concatenated text | PowerPoint / OOXML export |
|
|
77
|
+
| `browser` | `<text>` + `<tspan>` per run | Web / browser display |
|
|
78
|
+
| `preserve` | `<text>` + `<tspan>` + `textLength` | Pixel-perfect rendering |
|
|
79
|
+
| `glyph` | `<tspan x="x0 x1 ...">` per glyph | Selection / cursor positioning |
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
renderToSVG(result, { preset: 'preserve', style: 'css' })
|
|
83
|
+
|
|
84
|
+
// low-level — supply width/height/sizing yourself instead of deriving from the result
|
|
85
|
+
renderToSVG(result.lines, { sizing: { horizontal: 'frame', vertical: 'content' }, width: 400, preset: 'flat' })
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Pass `{ debug: { frameBox, contentBox, baseline, … } }` for overlay boxes.
|
|
89
|
+
|
|
90
|
+
## `registerFont(family, source, opts?)`
|
|
91
|
+
|
|
92
|
+
Registers a font with **both** `@vyaz/core`'s measurement engine and the
|
|
93
|
+
browser's `document.fonts` in one call — the single most common source of
|
|
94
|
+
drift between measured and painted text is registering only one of the two.
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { registerFont } from '@vyaz/renderer'
|
|
98
|
+
|
|
99
|
+
await registerFont('Inter', 'https://example.com/Inter.woff2')
|
|
100
|
+
// or a local buffer (Node.js)
|
|
101
|
+
import { readFileSync } from 'node:fs'
|
|
102
|
+
await registerFont('Inter', readFileSync('./Inter.woff2'), { weight: 'normal', style: 'normal' })
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## `TableRenderOptions`
|
|
106
|
+
|
|
107
|
+
| option | default | |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| `preset` | `'browser'` | forwarded to every cell's own text render |
|
|
110
|
+
| `style` | `'xml'` | how cell text style properties are expressed |
|
|
111
|
+
| `className` | – | CSS class on the root `<svg>`/`<g>` |
|
|
112
|
+
| `fragment` | `false` | emit a bare `<g>` instead of `<svg xmlns… viewBox…>`, for splicing into a document that already has one |
|
|
113
|
+
|
|
114
|
+
## Requirements
|
|
115
|
+
|
|
116
|
+
- **Runtime**: Bun 1.x, Node.js 18+, or a modern browser
|
|
117
|
+
- **Peer**: `@vyaz/core` (matching major/minor)
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT
|
package/dist/SVGRenderer.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* const svg = renderToSVG(lines, { preset: 'browser' })
|
|
18
18
|
* const svg = renderToSVG(lines, { preset: 'preserve', style: 'css', fit: 'frag' })
|
|
19
19
|
*/
|
|
20
|
-
import type { Line, ParagraphLayoutResult, TextFrameLayoutResult, MultiColumnConfig } from '@vyaz/core';
|
|
20
|
+
import type { Line, ParagraphLayoutResult, TextFrameLayoutResult, MultiColumnConfig, FrameTransform } from '@vyaz/core';
|
|
21
21
|
import type { DebugFlags } from './types.js';
|
|
22
22
|
export type SvgPreset = 'flat' | 'browser' | 'preserve' | 'glyph';
|
|
23
23
|
export type SvgStyle = 'css' | 'xml';
|
|
@@ -63,6 +63,17 @@ export interface SVGRenderOptions {
|
|
|
63
63
|
columns?: MultiColumnConfig;
|
|
64
64
|
/** Left padding from frame (needed for column debug rendering). */
|
|
65
65
|
paddingLeft?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Post-layout rigid transform (writing-mode `sideways-*` / frame `rotation`).
|
|
68
|
+
* When the input is a {@link TextFrameLayoutResult} its own `transform` is used
|
|
69
|
+
* automatically; pass this to supply one for the bare `Line[]` form or to
|
|
70
|
+
* override. A net rotation that is a multiple of 360° is ignored.
|
|
71
|
+
*
|
|
72
|
+
* The lines are rendered into `layoutBox` (pre-rotation space) and the whole
|
|
73
|
+
* output is wrapped in one `<g transform>`; the `<svg>` canvas becomes the
|
|
74
|
+
* rotated visual box.
|
|
75
|
+
*/
|
|
76
|
+
transform?: FrameTransform;
|
|
66
77
|
/**
|
|
67
78
|
* glyph preset only: draw `underline` / `strikethrough` as explicit `<line>`
|
|
68
79
|
* geometry. The glyph path positions each character with its own `x`, so it
|
|
@@ -70,6 +81,14 @@ export interface SVGRenderOptions {
|
|
|
70
81
|
* Ignored by every other preset. Default `true`.
|
|
71
82
|
*/
|
|
72
83
|
glyphDecorations?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Content for inline-box spans, keyed by `span.inlineWidget.id`. Each value is
|
|
86
|
+
* an SVG fragment already sized to the widget's `width` × `height`; it is
|
|
87
|
+
* spliced into a `<g>` translated to the box the layout reserved. A span whose
|
|
88
|
+
* id has no entry gets a light placeholder `<rect>`. Produced by `@vyaz/html`
|
|
89
|
+
* for `<img>` / `<svg>` / `<progress>` / … ; irrelevant without inline boxes.
|
|
90
|
+
*/
|
|
91
|
+
inlineBoxes?: Record<string, string>;
|
|
73
92
|
}
|
|
74
93
|
/**
|
|
75
94
|
* Render a layout to an SVG string.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SVGRenderer.d.ts","sourceRoot":"","sources":["../src/SVGRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAQ,qBAAqB,EAAE,qBAAqB,EAAkB,iBAAiB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"SVGRenderer.d.ts","sourceRoot":"","sources":["../src/SVGRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAQ,qBAAqB,EAAE,qBAAqB,EAAkB,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE9I,OAAO,KAAK,EAAE,UAAU,EAAuB,MAAM,YAAY,CAAC;AAKlE,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;AAElE,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,KAAK,CAAC;AAErC,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAE5C,MAAM,MAAM,aAAa,GAAG;IAAE,UAAU,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,CAAC;AAE3E,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,sGAAsG;IACtG,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;IACnC,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB;IACtB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAu2BD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,IAAI,EAAE,GAAG,qBAAqB,EACrC,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAwTR;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,IAAI,EAAE,EACb,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,EACvB,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAMR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,qBAAqB,EAC7B,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAMR"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TableRenderer.ts — TableLayoutResult → SVG string.
|
|
3
|
+
*
|
|
4
|
+
* Paint order (back to front): table bg → row bg → cell bg → row borders →
|
|
5
|
+
* cell borders → table border → cell content (before slot → main content →
|
|
6
|
+
* after slot, per cell). Each of those three is a complete nested `<svg>`
|
|
7
|
+
* (from `renderToSVG`), positioned with a `<g transform="translate(…)">` —
|
|
8
|
+
* the same "paint a self-contained SVG fragment into a box" pattern
|
|
9
|
+
* `SVGRenderOptions.inlineBoxes` uses for `<img>`/`<svg>` boxes from
|
|
10
|
+
* `@vyaz/html`. `before`/`after` (`paintSlot`) paint at the absolute
|
|
11
|
+
* position `TableLayoutEngine` already resolved for them — no extra
|
|
12
|
+
* padding/border math here, unlike main content.
|
|
13
|
+
*
|
|
14
|
+
* A cell's content is rendered at `sizing: 'frame'` with the *exact* width
|
|
15
|
+
* TableLayoutEngine measured it at (not `sizing: 'content'`): trimming to the
|
|
16
|
+
* ink bounding box would discard the alignment offset for centered/
|
|
17
|
+
* right-aligned paragraphs — the nested `<svg>`'s viewBox has to start at
|
|
18
|
+
* (0, 0) so `line.x` stays the true position within the cell.
|
|
19
|
+
*
|
|
20
|
+
* `cell.cx`/`cy` are an extra px nudge added straight onto the content
|
|
21
|
+
* origin. `cell.allowOverflow` forces `overflow: visible` on the cell's own
|
|
22
|
+
* nested `<svg>` (default clips at the padding box, same as `svg-table-core`
|
|
23
|
+
* — see `withOverflowVisible`). `opts.fragment` swaps the outer `<svg
|
|
24
|
+
* xmlns… viewBox…>` for a bare `<g>`, for splicing this table into a
|
|
25
|
+
* document that already has one (composing tables, nested-table cells).
|
|
26
|
+
*
|
|
27
|
+
* `cell.nestedTable` (`TableCell.content` was itself a `TableFrame`) paints
|
|
28
|
+
* via a *recursive* `renderTableToSVG(cell.nestedTable, { fragment: true })`
|
|
29
|
+
* call at the cell's content origin instead of the normal `renderToSVG` text
|
|
30
|
+
* path — `fragment: true` is exactly what makes this splice in as a `<g>`
|
|
31
|
+
* rather than nesting `<svg>` inside `<svg>` inside `<svg>`.
|
|
32
|
+
*
|
|
33
|
+
* Border dash patterns (`stroke-dasharray`) and per-side `stroke-linecap`
|
|
34
|
+
* (T3, `dashAttrs`/`dashUniform`) paint on both border shapes: a uniform
|
|
35
|
+
* `<rect stroke>` needs its pattern+linecap to also match on all four sides
|
|
36
|
+
* to stay a single rect (SVG has one dasharray per shape); otherwise (or
|
|
37
|
+
* when width/color already differ) it falls back to four `<line>`s, each
|
|
38
|
+
* with its own dasharray/linecap. Asymmetric corner radii remain a possible
|
|
39
|
+
* future addition — only a uniform `rx`/`ry` today.
|
|
40
|
+
*/
|
|
41
|
+
import type { TableLayoutResult } from '@vyaz/core';
|
|
42
|
+
import type { SvgPreset, SvgStyle } from './SVGRenderer.js';
|
|
43
|
+
export interface TableRenderOptions {
|
|
44
|
+
/** Preset used for every cell's own text render. Default `'browser'`. */
|
|
45
|
+
preset?: SvgPreset;
|
|
46
|
+
/** How cell text style properties are expressed. Default `'xml'`. */
|
|
47
|
+
style?: SvgStyle;
|
|
48
|
+
/** CSS class for the root `<svg>`/`<g>`. */
|
|
49
|
+
className?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Emit a bare `<g>` (no `<svg>`/`viewBox`/`xmlns` wrapper) for splicing
|
|
52
|
+
* into a document that already has an outer `<svg>` — e.g. composing
|
|
53
|
+
* several tables, or embedding as a nested-table cell's content. Default
|
|
54
|
+
* `false`.
|
|
55
|
+
*/
|
|
56
|
+
fragment?: boolean;
|
|
57
|
+
}
|
|
58
|
+
export declare function renderTableToSVG(result: TableLayoutResult, opts?: TableRenderOptions): string;
|
|
59
|
+
//# sourceMappingURL=TableRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TableRenderer.d.ts","sourceRoot":"","sources":["../src/TableRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAyC,MAAM,YAAY,CAAC;AAE3F,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5D,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,qEAAqE;IACrE,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAiFD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,EAAE,IAAI,GAAE,kBAAuB,GAAG,MAAM,CAgEjG"}
|
package/dist/index.browser.d.ts
CHANGED
|
@@ -9,9 +9,13 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export { renderToSVG, renderParagraphToSVG, renderResultToSVG } from './SVGRenderer.js';
|
|
11
11
|
export type { SVGRenderOptions, SvgPreset, SvgStyle, SvgFit, SvgSizing } from './SVGRenderer.js';
|
|
12
|
+
export { renderTableToSVG } from './TableRenderer.js';
|
|
13
|
+
export type { TableRenderOptions } from './TableRenderer.js';
|
|
12
14
|
export { renderToCanvas, renderDebugToCanvas, renderSelection, renderCursor } from './CanvasRenderer.js';
|
|
13
15
|
export type { CanvasRenderOptions, CursorOptions } from './CanvasRenderer.js';
|
|
14
16
|
export { charAtPoint, charIndexToPos, posToCharIndex } from './interactive.js';
|
|
15
17
|
export type { CharPos } from './interactive.js';
|
|
18
|
+
export { registerFont } from './register-font.js';
|
|
19
|
+
export type { RegisterFontOptions, RegisterFontResult } from './register-font.js';
|
|
16
20
|
export type { DebugFlags } from './types.js';
|
|
17
21
|
//# sourceMappingURL=index.browser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACxF,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEjG,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACzG,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC/E,YAAY,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACxF,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEjG,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACzG,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC/E,YAAY,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAElF,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|