@weasel-js/svg 1.10.1 → 1.11.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 +10 -0
- package/dist/index.d.ts +63 -13
- package/dist/index.js +286 -74
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -37,6 +37,16 @@ answer, and the alternative is unrepresentable anyway (see above). It only
|
|
|
37
37
|
shows up on foreign SVG that sets decoration on a group and cancels it on a
|
|
38
38
|
child.
|
|
39
39
|
|
|
40
|
+
**SVG text does not wrap.** By default a `<text>` is written one line per
|
|
41
|
+
hard break, pitched at the node's font size times its line height, and a
|
|
42
|
+
wrapping or justified node keeps that only in `data-weasel-*` attributes for
|
|
43
|
+
weasel's own reader. Pass `serializeSvg(nodes, { textLayout: layoutTextPose })`
|
|
44
|
+
to write the lines the renderer draws instead: each line is a `<tspan>` at the
|
|
45
|
+
layout's `x` and baseline `y`, each word of a line the layout justified gets
|
|
46
|
+
its own `x`, and a line holding a larger run sits where the renderer puts it.
|
|
47
|
+
The layout measures with the registered fonts, so `await warmSvg(nodes, {
|
|
48
|
+
textLayout })` first; a node no face could measure is written the default way.
|
|
49
|
+
|
|
40
50
|
## Paints SVG cannot express
|
|
41
51
|
|
|
42
52
|
SVG has `<linearGradient>`, `<radialGradient>` and `<pattern>` and nothing
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Affine } from '@weasel-js/geom';
|
|
2
|
-
import { Path, Paint, ScreenLength, StrokeAlign, MarkerRef, StyledRun, TextStyle, TextVerticalAlign, Fill, Stroke, PoseLinear, MarkerEntry, RenderNeeds, TilePatternSpec, ImageNodeData, IngestCtx } from '@weasel-js/core';
|
|
2
|
+
import { Path, Paint, ScreenLength, StrokeAlign, MarkerRef, VertexWidth, StrokeNib, StyledRun, TextStyle, TextVerticalAlign, Fill, Stroke, PoseLinear, MarkerEntry, TextPoseLayout, RenderNeeds, TilePatternSpec, ImageNodeData, IngestCtx } from '@weasel-js/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Media Queries 4 evaluation against a fixed environment.
|
|
@@ -125,6 +125,13 @@ interface SvgStroke {
|
|
|
125
125
|
markerStart?: MarkerRef;
|
|
126
126
|
markerMid?: MarkerRef;
|
|
127
127
|
markerEnd?: MarkerRef;
|
|
128
|
+
/** The kit stroke's `vertexWidths` and `nib`. SVG has no variable width, so
|
|
129
|
+
* the serializer writes such a stroke's outline as a filled shape after the
|
|
130
|
+
* path, and keeps these in the private namespace for the parser. An entry
|
|
131
|
+
* of `vertexWidths`, or one side of a pair, that is not a number of zero or
|
|
132
|
+
* more takes `width`. */
|
|
133
|
+
vertexWidths?: VertexWidth[];
|
|
134
|
+
nib?: StrokeNib;
|
|
128
135
|
}
|
|
129
136
|
/**
|
|
130
137
|
* Leaf node: a path geometry plus fill/stroke. Other shapes (`<rect>`,
|
|
@@ -372,6 +379,18 @@ interface SerializeOptions {
|
|
|
372
379
|
* line, since whitespace inside it is content.
|
|
373
380
|
*/
|
|
374
381
|
pretty?: boolean;
|
|
382
|
+
/**
|
|
383
|
+
* The lines a text node lays out into — pass core's `layoutTextPose`, the
|
|
384
|
+
* layout the renderer draws with. With it, each line is written as a
|
|
385
|
+
* `<tspan>` at the layout's own `x` and baseline `y`, a justified line
|
|
386
|
+
* gives each word its own `x`, and a line holding a larger run is pitched
|
|
387
|
+
* as the renderer pitches it, so a reader that cannot wrap draws the lines
|
|
388
|
+
* where weasel does. A node it returns nothing for, or lays out to zero
|
|
389
|
+
* width because no face could measure it, is written without it: one line
|
|
390
|
+
* per hard break, at the node's own pitch. Fonts it reads must have loaded;
|
|
391
|
+
* `warmSvg(nodes, { textLayout })` loads them.
|
|
392
|
+
*/
|
|
393
|
+
textLayout?: (node: SvgTextNode) => TextPoseLayout | null | undefined;
|
|
375
394
|
}
|
|
376
395
|
|
|
377
396
|
/**
|
|
@@ -421,22 +440,37 @@ declare function nativeSvgSpace(space: string | null | undefined): boolean;
|
|
|
421
440
|
*/
|
|
422
441
|
declare function serializeSvg(nodes: SvgNode[], opts?: SerializeOptions): string;
|
|
423
442
|
|
|
443
|
+
/**
|
|
444
|
+
* Serialize a weasel `Path` to an SVG `d=` attribute string. `RectPath`
|
|
445
|
+
* lowers to `M h v h Z`; `PolygonPath` walks the (commands, coords)
|
|
446
|
+
* arrays, emitting one SVG command per kit command, with corner shapes
|
|
447
|
+
* expanded into the geometry they draw.
|
|
448
|
+
*
|
|
449
|
+
* Output uses absolute commands only and a small amount of whitespace
|
|
450
|
+
* compression (no leading zeros stripped beyond what `Number.toString`
|
|
451
|
+
* already does). Numbers are rounded to ~6 decimals via `trimNumber`.
|
|
452
|
+
*/
|
|
453
|
+
|
|
454
|
+
/** Serialize a weasel `Path` to an SVG `d=` attribute string. */
|
|
455
|
+
declare function serializePathD(given: Path): string;
|
|
456
|
+
|
|
424
457
|
/**
|
|
425
458
|
* What `serializeSvg(nodes)` reads that loads on demand: the paint kind of
|
|
426
459
|
* every fill and stroke it writes as a paint server, and the face of every
|
|
427
460
|
* run whose script size it takes from font metrics. The kinds come from the
|
|
428
461
|
* serializer's own paint pre-pass, so the two cannot disagree. Registered
|
|
429
|
-
* kinds are included.
|
|
462
|
+
* kinds are included. Given the `textLayout` the export will run, every face
|
|
463
|
+
* a text node is set in, which that layout measures with.
|
|
430
464
|
*/
|
|
431
|
-
declare function svgNeeds(nodes: readonly SvgNode[]): RenderNeeds;
|
|
465
|
+
declare function svgNeeds(nodes: readonly SvgNode[], opts?: Pick<SerializeOptions, 'textLayout'>): RenderNeeds;
|
|
432
466
|
/**
|
|
433
|
-
* Load what {@link svgNeeds} lists, so a `serializeSvg(nodes)` issued
|
|
434
|
-
* resolves writes every paint server's def and every script size
|
|
435
|
-
* face it renders in. Only those load: a lazily registered kind or font the
|
|
467
|
+
* Load what {@link svgNeeds} lists, so a `serializeSvg(nodes, opts)` issued
|
|
468
|
+
* after it resolves writes every paint server's def, and every script size and
|
|
469
|
+
* laid-out line from the face it renders in. Only those load: a lazily registered kind or font the
|
|
436
470
|
* nodes do not use is never fetched, and cannot fail the export. A kind
|
|
437
471
|
* nothing registered is passed over; the export warns about it instead.
|
|
438
472
|
*/
|
|
439
|
-
declare function warmSvg(nodes: readonly SvgNode[]): Promise<void>;
|
|
473
|
+
declare function warmSvg(nodes: readonly SvgNode[], opts?: Pick<SerializeOptions, 'textLayout'>): Promise<void>;
|
|
440
474
|
|
|
441
475
|
/**
|
|
442
476
|
* Map between SVG `<pattern>` elements and weasel's pattern paints.
|
|
@@ -502,6 +536,12 @@ interface SvgKitLeafData {
|
|
|
502
536
|
style?: TextStyle;
|
|
503
537
|
runs?: readonly StyledRun[];
|
|
504
538
|
verticalAlign?: TextVerticalAlign;
|
|
539
|
+
/** A text node's paint over its whole box, under the glyphs. */
|
|
540
|
+
background?: Fill | null;
|
|
541
|
+
/** A text node's inset from its box to its text, on every side. */
|
|
542
|
+
padding?: number;
|
|
543
|
+
/** `'clip'` cuts a text node's text at its box. */
|
|
544
|
+
overflow?: 'visible' | 'clip';
|
|
505
545
|
image?: ImageNodeData['image'];
|
|
506
546
|
}
|
|
507
547
|
/** A kit paint as an `SvgPaint`. `null` is `fill="none"`; a box-relative
|
|
@@ -517,19 +557,23 @@ declare function svgImageFromKit(image: ImageNodeData['image'], pose: SvgKitPose
|
|
|
517
557
|
/**
|
|
518
558
|
* Write one leaf as the `SvgNode` its built-in painter draws — image, text or
|
|
519
559
|
* path, in the order the painters claim a node. `null` for data none of them
|
|
520
|
-
* draws.
|
|
560
|
+
* draws. A text node with a `background` is a group: the box, then the text.
|
|
561
|
+
* One that clips is a group clipped to its box as it is drawn, turned with it.
|
|
521
562
|
*
|
|
522
563
|
* A path with no `fill` takes `kit:path`'s fallback: the default shape fill
|
|
523
564
|
* when it has no stroke, and no fill when it has one. Under a pose `transform`
|
|
524
565
|
* its stroke width takes the uniform part of the stretch, as `parseSvg` reads
|
|
525
566
|
* a stroke under a skewed element.
|
|
526
567
|
*/
|
|
527
|
-
declare function svgLeafFromKit(data: SvgKitLeafData, pose: SvgKitPose): SvgPathNode | SvgTextNode | SvgImageNode | null;
|
|
568
|
+
declare function svgLeafFromKit(data: SvgKitLeafData, pose: SvgKitPose): SvgPathNode | SvgTextNode | SvgImageNode | SvgGroupNode | null;
|
|
528
569
|
/** One node as {@link svgNodesFromKit} reads it. */
|
|
529
570
|
interface SvgKitTreeNode {
|
|
530
571
|
kind: string;
|
|
531
572
|
data: unknown;
|
|
532
573
|
pose: SvgKitPose;
|
|
574
|
+
/** The kit's `SceneNode.hidden`: written with `display="none"`, which
|
|
575
|
+
* `parseSvg(…, { keepHidden: true })` reads back as `hidden`. */
|
|
576
|
+
hidden?: boolean;
|
|
533
577
|
/** A container's copies, as the kit's `ContainerNode.copiesFromPose`
|
|
534
578
|
* draws them: each is written as a transformed group of its children. */
|
|
535
579
|
copiesFromPose?(pose: SvgKitPose, node: never): readonly Matrix[] | null;
|
|
@@ -556,7 +600,7 @@ interface SvgNodesFromKitOptions<TId extends string = string> {
|
|
|
556
600
|
* Walk a scene's container tree into `SvgNode`s ready for `serializeSvg`:
|
|
557
601
|
* every `container` becomes a group of its children, in z-order, and every
|
|
558
602
|
* leaf goes through {@link svgLeafFromKit} unless `options.leaf` says
|
|
559
|
-
* otherwise.
|
|
603
|
+
* otherwise. A hidden node is written hidden, with its subtree as it is.
|
|
560
604
|
*/
|
|
561
605
|
declare function svgNodesFromKit<TId extends string>(tree: SvgKitTree<TId>, options?: SvgNodesFromKitOptions<TId>): SvgNode[];
|
|
562
606
|
|
|
@@ -611,6 +655,10 @@ interface SvgNodesToKitDraftsOptions<TData> {
|
|
|
611
655
|
pose: SvgDraftPose;
|
|
612
656
|
data: SvgKitLeafData;
|
|
613
657
|
}, source: SvgLeafNode): TData | null;
|
|
658
|
+
/** Keep a group that draws nothing, which is otherwise dropped — for one
|
|
659
|
+
* whose metadata means something with no children under it. It is drafted
|
|
660
|
+
* with its clip's box, or a zero box at the origin. */
|
|
661
|
+
keepEmpty?(source: SvgGroupNode): boolean;
|
|
614
662
|
}
|
|
615
663
|
/** Lower an `SvgPaint` onto the paint of the `kit:path` painter's
|
|
616
664
|
* `data.fill` — a `Paint`, or `null` for SVG's `fill="none"` (the painter
|
|
@@ -628,7 +676,8 @@ declare function strokeDataFromSvg(stroke: SvgStroke | undefined, box: SvgDraftB
|
|
|
628
676
|
* Walk an `SvgNode[]` tree and emit a flat, parent-before-child list of
|
|
629
677
|
* {@link SvgSceneDraft}s. Each `<g>` becomes a container whose pose is the
|
|
630
678
|
* union AABB of its descendants, or its clip's box when it has one; leaves
|
|
631
|
-
* carry kit-painter-native data. Empty groups are dropped
|
|
679
|
+
* carry kit-painter-native data. Empty groups are dropped unless
|
|
680
|
+
* `options.keepEmpty` keeps them, and so is a group holding only those.
|
|
632
681
|
*
|
|
633
682
|
* Handed a whole `ParseResult`, it also registers the document's markers
|
|
634
683
|
* (`parsed.markers`), without which the strokes naming them draw bare.
|
|
@@ -646,9 +695,10 @@ declare function svgNodesToKitDrafts<TData = Record<string, unknown>>(input: Par
|
|
|
646
695
|
* Each file is fit-clamped to 90% of the visible viewport and centered on the
|
|
647
696
|
* drop point (or the viewport center), with later files cascading by a fixed
|
|
648
697
|
* offset. A multi-root file is wrapped in one container so it arrives as a
|
|
649
|
-
* single selectable unit.
|
|
698
|
+
* single selectable unit. Content the file hides arrives hidden
|
|
699
|
+
* (`SceneNode.hidden`) rather than being left out. A file that fails to parse, or parses to nothing,
|
|
650
700
|
* is skipped with a `console.warn`.
|
|
651
701
|
*/
|
|
652
702
|
declare function unpackSvgFiles(files: File[], ctx: IngestCtx): Promise<void>;
|
|
653
703
|
|
|
654
|
-
export { DEFAULT_MEDIA_ENVIRONMENT, IDENTITY_MATRIX, type Matrix, type NamespaceMeta, type NamespacedElement, type ParseOptions, type ParseResult, type SerializeOptions, type SupportsOptions, type SvgDraftBounds, type SvgDraftPose, type SvgGroupNode, type SvgImageNode, type SvgKitLeafData, type SvgKitPose, type SvgKitTree, type SvgKitTreeNode, type SvgLeafNode, type SvgMediaEnvironment, type SvgNode, type SvgNodesFromKitOptions, type SvgNodesToKitDraftsOptions, type SvgPaint, type SvgPathNode, type SvgSceneDraft, type SvgStroke, type SvgTextNode, evaluateMediaQuery, evaluateSupports, fillDataFromSvg, nativeSvgKind, nativeSvgSpace, parseSvg, serializeSvg, strokeDataFromSvg, svgImageFromKit, svgLeafFromKit, svgNeeds, svgNodesFromKit, svgNodesToKitDrafts, svgPaintFromKit, svgStrokeFromKit, tilePreviewCssUrl, tilePreviewSvg, unpackSvgFiles, warmSvg };
|
|
704
|
+
export { DEFAULT_MEDIA_ENVIRONMENT, IDENTITY_MATRIX, type Matrix, type NamespaceMeta, type NamespacedElement, type ParseOptions, type ParseResult, type SerializeOptions, type SupportsOptions, type SvgDraftBounds, type SvgDraftPose, type SvgGroupNode, type SvgImageNode, type SvgKitLeafData, type SvgKitPose, type SvgKitTree, type SvgKitTreeNode, type SvgLeafNode, type SvgMediaEnvironment, type SvgNode, type SvgNodesFromKitOptions, type SvgNodesToKitDraftsOptions, type SvgPaint, type SvgPathNode, type SvgSceneDraft, type SvgStroke, type SvgTextNode, evaluateMediaQuery, evaluateSupports, fillDataFromSvg, nativeSvgKind, nativeSvgSpace, parseSvg, serializePathD, serializeSvg, strokeDataFromSvg, svgImageFromKit, svgLeafFromKit, svgNeeds, svgNodesFromKit, svgNodesToKitDrafts, svgPaintFromKit, svgStrokeFromKit, tilePreviewCssUrl, tilePreviewSvg, unpackSvgFiles, warmSvg };
|