@retikz/core 0.3.0-alpha.3 → 0.3.0-alpha.4
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 +41 -41
- package/dist/es/compile/anchor-cache.d.ts +5 -3
- package/dist/es/compile/anchor-cache.d.ts.map +1 -1
- package/dist/es/compile/anchor-cache.js +14 -10
- package/dist/es/compile/boundary.d.ts +19 -0
- package/dist/es/compile/boundary.d.ts.map +1 -0
- package/dist/es/compile/boundary.js +64 -0
- package/dist/es/compile/compile.d.ts.map +1 -1
- package/dist/es/compile/compile.js +14 -2
- package/dist/es/compile/node.d.ts +24 -8
- package/dist/es/compile/node.d.ts.map +1 -1
- package/dist/es/compile/node.js +100 -16
- package/dist/es/compile/path/anchor.d.ts.map +1 -1
- package/dist/es/compile/path/anchor.js +7 -6
- package/dist/es/compile/path/index.d.ts.map +1 -1
- package/dist/es/compile/path/index.js +5 -3
- package/dist/es/compile/path/relative.js +1 -1
- package/dist/es/compile/scope.d.ts.map +1 -1
- package/dist/es/compile/scope.js +2 -1
- package/dist/es/geometry/arc.d.ts +14 -0
- package/dist/es/geometry/arc.d.ts.map +1 -1
- package/dist/es/geometry/arc.js +65 -9
- package/dist/es/geometry/index.d.ts +1 -0
- package/dist/es/geometry/index.d.ts.map +1 -1
- package/dist/es/geometry/rect.d.ts +2 -2
- package/dist/es/geometry/rect.d.ts.map +1 -1
- package/dist/es/geometry/rect.js +3 -3
- package/dist/es/geometry/roundedContour.d.ts +88 -0
- package/dist/es/geometry/roundedContour.d.ts.map +1 -0
- package/dist/es/geometry/roundedContour.js +417 -0
- package/dist/es/index.d.ts +6 -5
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js +9 -6
- package/dist/es/ir/boundary.d.ts +25 -0
- package/dist/es/ir/boundary.d.ts.map +1 -0
- package/dist/es/ir/boundary.js +14 -0
- package/dist/es/ir/index.d.ts +2 -0
- package/dist/es/ir/index.d.ts.map +1 -1
- package/dist/es/ir/node.d.ts +43 -7
- package/dist/es/ir/node.d.ts.map +1 -1
- package/dist/es/ir/node.js +8 -3
- package/dist/es/ir/path/arrow.d.ts +12 -12
- package/dist/es/ir/path/path.d.ts +490 -147
- package/dist/es/ir/path/path.d.ts.map +1 -1
- package/dist/es/ir/path/path.js +2 -0
- package/dist/es/ir/path/step.d.ts +674 -154
- package/dist/es/ir/path/step.d.ts.map +1 -1
- package/dist/es/ir/path/step.js +2 -2
- package/dist/es/ir/path/target.d.ts +43 -8
- package/dist/es/ir/path/target.d.ts.map +1 -1
- package/dist/es/ir/path/target.js +4 -5
- package/dist/es/ir/scope.d.ts +843 -234
- package/dist/es/ir/scope.d.ts.map +1 -1
- package/dist/es/ir/scope.js +6 -2
- package/dist/es/ir/shape.d.ts +14 -0
- package/dist/es/ir/shape.d.ts.map +1 -0
- package/dist/es/ir/shape.js +9 -0
- package/dist/es/parsers/parseNodeTarget.d.ts.map +1 -1
- package/dist/es/parsers/parseNodeTarget.js +4 -2
- package/dist/es/primitive/ellipse.d.ts +3 -0
- package/dist/es/primitive/ellipse.d.ts.map +1 -1
- package/dist/es/primitive/group.d.ts +3 -0
- package/dist/es/primitive/group.d.ts.map +1 -1
- package/dist/es/primitive/path.d.ts +3 -0
- package/dist/es/primitive/path.d.ts.map +1 -1
- package/dist/es/primitive/rect.d.ts +3 -0
- package/dist/es/primitive/rect.d.ts.map +1 -1
- package/dist/es/primitive/text.d.ts +3 -0
- package/dist/es/primitive/text.d.ts.map +1 -1
- package/dist/es/shapes/_contour.d.ts +19 -0
- package/dist/es/shapes/_contour.d.ts.map +1 -0
- package/dist/es/shapes/_contour.js +60 -0
- package/dist/es/shapes/_shared.d.ts +54 -0
- package/dist/es/shapes/_shared.d.ts.map +1 -1
- package/dist/es/shapes/_shared.js +68 -1
- package/dist/es/shapes/arc.d.ts +8 -0
- package/dist/es/shapes/arc.d.ts.map +1 -0
- package/dist/es/shapes/arc.js +104 -0
- package/dist/es/shapes/define.d.ts +13 -0
- package/dist/es/shapes/define.d.ts.map +1 -0
- package/dist/es/shapes/define.js +13 -0
- package/dist/es/shapes/ellipse.d.ts +5 -4
- package/dist/es/shapes/ellipse.d.ts.map +1 -1
- package/dist/es/shapes/ellipse.js +15 -7
- package/dist/es/shapes/index.d.ts +9 -6
- package/dist/es/shapes/index.d.ts.map +1 -1
- package/dist/es/shapes/index.js +10 -5
- package/dist/es/shapes/polygon.d.ts +13 -0
- package/dist/es/shapes/polygon.d.ts.map +1 -0
- package/dist/es/shapes/polygon.js +104 -0
- package/dist/es/shapes/rectangle.d.ts +7 -5
- package/dist/es/shapes/rectangle.d.ts.map +1 -1
- package/dist/es/shapes/rectangle.js +37 -8
- package/dist/es/shapes/sector.d.ts +9 -0
- package/dist/es/shapes/sector.d.ts.map +1 -0
- package/dist/es/shapes/sector.js +143 -0
- package/dist/es/shapes/star.d.ts +15 -0
- package/dist/es/shapes/star.d.ts.map +1 -0
- package/dist/es/shapes/star.js +113 -0
- package/dist/es/shapes/types.d.ts +47 -14
- package/dist/es/shapes/types.d.ts.map +1 -1
- package/dist/lib/compile/anchor-cache.cjs +14 -10
- package/dist/lib/compile/anchor-cache.d.ts +5 -3
- package/dist/lib/compile/anchor-cache.d.ts.map +1 -1
- package/dist/lib/compile/boundary.cjs +65 -0
- package/dist/lib/compile/boundary.d.ts +19 -0
- package/dist/lib/compile/boundary.d.ts.map +1 -0
- package/dist/lib/compile/compile.cjs +14 -2
- package/dist/lib/compile/compile.d.ts.map +1 -1
- package/dist/lib/compile/node.cjs +100 -16
- package/dist/lib/compile/node.d.ts +24 -8
- package/dist/lib/compile/node.d.ts.map +1 -1
- package/dist/lib/compile/path/anchor.cjs +7 -6
- package/dist/lib/compile/path/anchor.d.ts.map +1 -1
- package/dist/lib/compile/path/index.cjs +5 -3
- package/dist/lib/compile/path/index.d.ts.map +1 -1
- package/dist/lib/compile/path/relative.cjs +1 -1
- package/dist/lib/compile/scope.cjs +2 -1
- package/dist/lib/compile/scope.d.ts.map +1 -1
- package/dist/lib/geometry/arc.cjs +66 -8
- package/dist/lib/geometry/arc.d.ts +14 -0
- package/dist/lib/geometry/arc.d.ts.map +1 -1
- package/dist/lib/geometry/index.d.ts +1 -0
- package/dist/lib/geometry/index.d.ts.map +1 -1
- package/dist/lib/geometry/rect.cjs +3 -3
- package/dist/lib/geometry/rect.d.ts +2 -2
- package/dist/lib/geometry/rect.d.ts.map +1 -1
- package/dist/lib/geometry/roundedContour.cjs +418 -0
- package/dist/lib/geometry/roundedContour.d.ts +88 -0
- package/dist/lib/geometry/roundedContour.d.ts.map +1 -0
- package/dist/lib/index.cjs +14 -7
- package/dist/lib/index.d.ts +6 -5
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/ir/boundary.cjs +15 -0
- package/dist/lib/ir/boundary.d.ts +25 -0
- package/dist/lib/ir/boundary.d.ts.map +1 -0
- package/dist/lib/ir/index.d.ts +2 -0
- package/dist/lib/ir/index.d.ts.map +1 -1
- package/dist/lib/ir/node.cjs +8 -3
- package/dist/lib/ir/node.d.ts +43 -7
- package/dist/lib/ir/node.d.ts.map +1 -1
- package/dist/lib/ir/path/arrow.d.ts +12 -12
- package/dist/lib/ir/path/path.cjs +2 -0
- package/dist/lib/ir/path/path.d.ts +490 -147
- package/dist/lib/ir/path/path.d.ts.map +1 -1
- package/dist/lib/ir/path/step.cjs +2 -2
- package/dist/lib/ir/path/step.d.ts +674 -154
- package/dist/lib/ir/path/step.d.ts.map +1 -1
- package/dist/lib/ir/path/target.cjs +4 -5
- package/dist/lib/ir/path/target.d.ts +43 -8
- package/dist/lib/ir/path/target.d.ts.map +1 -1
- package/dist/lib/ir/scope.cjs +6 -2
- package/dist/lib/ir/scope.d.ts +843 -234
- package/dist/lib/ir/scope.d.ts.map +1 -1
- package/dist/lib/ir/shape.cjs +9 -0
- package/dist/lib/ir/shape.d.ts +14 -0
- package/dist/lib/ir/shape.d.ts.map +1 -0
- package/dist/lib/parsers/parseNodeTarget.cjs +4 -2
- package/dist/lib/parsers/parseNodeTarget.d.ts.map +1 -1
- package/dist/lib/primitive/ellipse.d.ts +3 -0
- package/dist/lib/primitive/ellipse.d.ts.map +1 -1
- package/dist/lib/primitive/group.d.ts +3 -0
- package/dist/lib/primitive/group.d.ts.map +1 -1
- package/dist/lib/primitive/path.d.ts +3 -0
- package/dist/lib/primitive/path.d.ts.map +1 -1
- package/dist/lib/primitive/rect.d.ts +3 -0
- package/dist/lib/primitive/rect.d.ts.map +1 -1
- package/dist/lib/primitive/text.d.ts +3 -0
- package/dist/lib/primitive/text.d.ts.map +1 -1
- package/dist/lib/shapes/_contour.cjs +61 -0
- package/dist/lib/shapes/_contour.d.ts +19 -0
- package/dist/lib/shapes/_contour.d.ts.map +1 -0
- package/dist/lib/shapes/_shared.cjs +70 -0
- package/dist/lib/shapes/_shared.d.ts +54 -0
- package/dist/lib/shapes/_shared.d.ts.map +1 -1
- package/dist/lib/shapes/arc.cjs +104 -0
- package/dist/lib/shapes/arc.d.ts +8 -0
- package/dist/lib/shapes/arc.d.ts.map +1 -0
- package/dist/lib/shapes/define.cjs +13 -0
- package/dist/lib/shapes/define.d.ts +13 -0
- package/dist/lib/shapes/define.d.ts.map +1 -0
- package/dist/lib/shapes/ellipse.cjs +15 -7
- package/dist/lib/shapes/ellipse.d.ts +5 -4
- package/dist/lib/shapes/ellipse.d.ts.map +1 -1
- package/dist/lib/shapes/index.cjs +12 -6
- package/dist/lib/shapes/index.d.ts +9 -6
- package/dist/lib/shapes/index.d.ts.map +1 -1
- package/dist/lib/shapes/polygon.cjs +104 -0
- package/dist/lib/shapes/polygon.d.ts +13 -0
- package/dist/lib/shapes/polygon.d.ts.map +1 -0
- package/dist/lib/shapes/rectangle.cjs +37 -8
- package/dist/lib/shapes/rectangle.d.ts +7 -5
- package/dist/lib/shapes/rectangle.d.ts.map +1 -1
- package/dist/lib/shapes/sector.cjs +143 -0
- package/dist/lib/shapes/sector.d.ts +9 -0
- package/dist/lib/shapes/sector.d.ts.map +1 -0
- package/dist/lib/shapes/star.cjs +113 -0
- package/dist/lib/shapes/star.d.ts +15 -0
- package/dist/lib/shapes/star.d.ts.map +1 -0
- package/dist/lib/shapes/types.d.ts +47 -14
- package/dist/lib/shapes/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/es/shapes/circle.d.ts +0 -8
- package/dist/es/shapes/circle.d.ts.map +0 -1
- package/dist/es/shapes/circle.js +0 -34
- package/dist/es/shapes/diamond.d.ts +0 -8
- package/dist/es/shapes/diamond.d.ts.map +0 -1
- package/dist/es/shapes/diamond.js +0 -66
- package/dist/lib/shapes/circle.cjs +0 -34
- package/dist/lib/shapes/circle.d.ts +0 -8
- package/dist/lib/shapes/circle.d.ts.map +0 -1
- package/dist/lib/shapes/diamond.cjs +0 -66
- package/dist/lib/shapes/diamond.d.ts +0 -8
- package/dist/lib/shapes/diamond.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
# @retikz/core
|
|
2
|
-
|
|
3
|
-
Framework-agnostic core of [retikz](https://pionpill.github.io/retikz/) — a TikZ-inspired diagramming library. Provides the zod-typed **IR**, the **`compileToScene`** compiler, pure **parsers**, geometry helpers, and the shape / arrow / pattern / path-generator registries.
|
|
4
|
-
|
|
5
|
-
零框架核心:retikz 的中间表示(IR)、`compileToScene` 编译器、纯解析器、几何工具与形状 / 箭头 / 图案 / 路径生成器注册面。**零 React、零 DOM**,运行时依赖只有 `zod`,IR 100% 可 JSON 序列化。
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
pnpm add @retikz/core
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Usage
|
|
14
|
-
|
|
15
|
-
`@retikz/core` is renderer-agnostic: it turns an IR into a serializable `Scene`. A backend (`@retikz/render`) or runtime (`@retikz/react` / `@retikz/vanilla`) then renders that Scene.
|
|
16
|
-
|
|
17
|
-
```ts
|
|
18
|
-
import { compileToScene } from '@retikz/core';
|
|
19
|
-
|
|
20
|
-
const scene = compileToScene(ir);
|
|
21
|
-
// optional: compileToScene(ir, { measureText, shapes, arrows, padding, ... })
|
|
22
|
-
// hand `scene` to @retikz/render/svg, @retikz/render/canvas, or a runtime
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
Most users consume core indirectly through [`@retikz/react`](https://www.npmjs.com/package/@retikz/react) or [`@retikz/vanilla`](https://www.npmjs.com/package/@retikz/vanilla). Use core directly when you build IR programmatically, persist/transport scenes, or write a custom renderer.
|
|
26
|
-
|
|
27
|
-
## Exports
|
|
28
|
-
|
|
29
|
-
- `compileToScene` / `computeLayout` / `fallbackMeasurer` — IR → `Scene`
|
|
30
|
-
- IR & `Scene` zod schemas + inferred types
|
|
31
|
-
- `parseWay` / `parseNodeTarget` / `parseTargetSugar` — pure parsers
|
|
32
|
-
- `point` / `rect` / `circle` / `ellipse` / `diamond` / `polar` — geometry
|
|
33
|
-
- `BUILTIN_SHAPES` / `BUILTIN_ARROWS` / `BUILTIN_PATTERNS` + `ShapeDefinition` / `ArrowDefinition` / `PatternDefinition` / `definePathGenerator` — registries
|
|
34
|
-
|
|
35
|
-
## Docs
|
|
36
|
-
|
|
37
|
-
<https://pionpill.github.io/retikz/>
|
|
38
|
-
|
|
39
|
-
## License
|
|
40
|
-
|
|
41
|
-
MIT
|
|
1
|
+
# @retikz/core
|
|
2
|
+
|
|
3
|
+
Framework-agnostic core of [retikz](https://pionpill.github.io/retikz/) — a TikZ-inspired diagramming library. Provides the zod-typed **IR**, the **`compileToScene`** compiler, pure **parsers**, geometry helpers, and the shape / arrow / pattern / path-generator registries.
|
|
4
|
+
|
|
5
|
+
零框架核心:retikz 的中间表示(IR)、`compileToScene` 编译器、纯解析器、几何工具与形状 / 箭头 / 图案 / 路径生成器注册面。**零 React、零 DOM**,运行时依赖只有 `zod`,IR 100% 可 JSON 序列化。
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @retikz/core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
`@retikz/core` is renderer-agnostic: it turns an IR into a serializable `Scene`. A backend (`@retikz/render`) or runtime (`@retikz/react` / `@retikz/vanilla`) then renders that Scene.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { compileToScene } from '@retikz/core';
|
|
19
|
+
|
|
20
|
+
const scene = compileToScene(ir);
|
|
21
|
+
// optional: compileToScene(ir, { measureText, shapes, arrows, padding, ... })
|
|
22
|
+
// hand `scene` to @retikz/render/svg, @retikz/render/canvas, or a runtime
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Most users consume core indirectly through [`@retikz/react`](https://www.npmjs.com/package/@retikz/react) or [`@retikz/vanilla`](https://www.npmjs.com/package/@retikz/vanilla). Use core directly when you build IR programmatically, persist/transport scenes, or write a custom renderer.
|
|
26
|
+
|
|
27
|
+
## Exports
|
|
28
|
+
|
|
29
|
+
- `compileToScene` / `computeLayout` / `fallbackMeasurer` — IR → `Scene`
|
|
30
|
+
- IR & `Scene` zod schemas + inferred types
|
|
31
|
+
- `parseWay` / `parseNodeTarget` / `parseTargetSugar` — pure parsers
|
|
32
|
+
- `point` / `rect` / `circle` / `ellipse` / `diamond` / `polar` — geometry
|
|
33
|
+
- `BUILTIN_SHAPES` / `BUILTIN_ARROWS` / `BUILTIN_PATTERNS` + `ShapeDefinition` / `ArrowDefinition` / `PatternDefinition` / `definePathGenerator` — registries
|
|
34
|
+
|
|
35
|
+
## Docs
|
|
36
|
+
|
|
37
|
+
<https://pionpill.github.io/retikz/>
|
|
38
|
+
|
|
39
|
+
## License
|
|
40
|
+
|
|
41
|
+
MIT
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Side } from '../geometry/_edge';
|
|
2
|
-
import { IRPosition } from '../ir';
|
|
2
|
+
import { IRBoundary, IRPosition } from '../ir';
|
|
3
3
|
import { NodeLayout } from './node';
|
|
4
4
|
/**
|
|
5
5
|
* 取节点 anchor 的全局坐标,带 per-layout 缓存
|
|
6
6
|
* @description name 接受 RectAnchor 关键字(如 `'north'` / `'south-west'`)或数字角度字符串(如 `'30'` / `'-45'`);
|
|
7
|
-
*
|
|
7
|
+
* boundary 指定连接面(默认 `'shape'`,即节点自身视觉轮廓);不同 boundary 产生独立缓存条目,互不串扰;
|
|
8
|
+
* 同一 (layout, name, boundary) 组合第二次起返回首调用结果的**同一引用**——上游可用 `===` 判定 cache 命中
|
|
8
9
|
* @param layout 已 Pass 1 完成的 NodeLayout(rect 已是全局坐标)
|
|
9
10
|
* @param anchorName 关键字或数字角度字符串
|
|
11
|
+
* @param boundary 连接面,缺省为 `'shape'`(视觉轮廓)
|
|
10
12
|
* @returns 全局坐标系下的 IRPosition `[x, y]`
|
|
11
13
|
*/
|
|
12
|
-
export declare const resolveAnchor: (layout: NodeLayout, anchorName: string) => IRPosition;
|
|
14
|
+
export declare const resolveAnchor: (layout: NodeLayout, anchorName: string, boundary?: IRBoundary | undefined) => IRPosition;
|
|
13
15
|
/**
|
|
14
16
|
* 取节点边上比例点 `{ side, t }` 的全局坐标,带 per-layout 缓存
|
|
15
17
|
* @description 走 `layout.shapeDef.edgePoint`——shape 未实现(如自定义 shape)抛"does not support side anchors";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor-cache.d.ts","sourceRoot":"","sources":["../../../src/compile/anchor-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"anchor-cache.d.ts","sourceRoot":"","sources":["../../../src/compile/anchor-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAiCzC;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,UAAU,EAClB,YAAY,MAAM,EAClB,WAAU,UAAU,GAAG,SAAmB,KACzC,UAYF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,UAAU,EAClB,MAAM,IAAI,EACV,GAAG,MAAM,KACR,UAuBF,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { boundaryKey } from "./boundary.js";
|
|
1
2
|
import { anchorOf, angleBoundaryOf } from "./node.js";
|
|
2
3
|
//#region src/compile/anchor-cache.ts
|
|
3
4
|
/**
|
|
@@ -9,32 +10,35 @@ var cache = /* @__PURE__ */ new WeakMap();
|
|
|
9
10
|
var ANGLE_RE = /^-?\d+(\.\d+)?$/;
|
|
10
11
|
/**
|
|
11
12
|
* 把 anchorName 解析到对应 shape 的 anchor / boundaryPoint 上
|
|
12
|
-
* @description 数字字符串走 angleBoundaryOf;其余按 RectAnchor 走 anchorOf
|
|
13
|
+
* @description 数字字符串走 angleBoundaryOf;其余按 RectAnchor 走 anchorOf;boundary 透传给两者
|
|
13
14
|
*/
|
|
14
|
-
var computeAnchor = (layout, anchorName) => {
|
|
15
|
-
if (ANGLE_RE.test(anchorName)) return positionToIR(angleBoundaryOf(layout, Number(anchorName)));
|
|
16
|
-
return positionToIR(anchorOf(layout, anchorName));
|
|
15
|
+
var computeAnchor = (layout, anchorName, boundary) => {
|
|
16
|
+
if (ANGLE_RE.test(anchorName)) return positionToIR(angleBoundaryOf(layout, Number(anchorName), boundary));
|
|
17
|
+
return positionToIR(anchorOf(layout, anchorName, boundary));
|
|
17
18
|
};
|
|
18
19
|
/** geometry Position(含 readonly 形态)转 IRPosition 元组(IRPosition === [number, number]) */
|
|
19
20
|
var positionToIR = (p) => [p[0], p[1]];
|
|
20
21
|
/**
|
|
21
22
|
* 取节点 anchor 的全局坐标,带 per-layout 缓存
|
|
22
23
|
* @description name 接受 RectAnchor 关键字(如 `'north'` / `'south-west'`)或数字角度字符串(如 `'30'` / `'-45'`);
|
|
23
|
-
*
|
|
24
|
+
* boundary 指定连接面(默认 `'shape'`,即节点自身视觉轮廓);不同 boundary 产生独立缓存条目,互不串扰;
|
|
25
|
+
* 同一 (layout, name, boundary) 组合第二次起返回首调用结果的**同一引用**——上游可用 `===` 判定 cache 命中
|
|
24
26
|
* @param layout 已 Pass 1 完成的 NodeLayout(rect 已是全局坐标)
|
|
25
27
|
* @param anchorName 关键字或数字角度字符串
|
|
28
|
+
* @param boundary 连接面,缺省为 `'shape'`(视觉轮廓)
|
|
26
29
|
* @returns 全局坐标系下的 IRPosition `[x, y]`
|
|
27
30
|
*/
|
|
28
|
-
var resolveAnchor = (layout, anchorName) => {
|
|
31
|
+
var resolveAnchor = (layout, anchorName, boundary = "shape") => {
|
|
29
32
|
let layoutCache = cache.get(layout);
|
|
30
33
|
if (!layoutCache) {
|
|
31
34
|
layoutCache = /* @__PURE__ */ new Map();
|
|
32
35
|
cache.set(layout, layoutCache);
|
|
33
36
|
}
|
|
34
|
-
const
|
|
37
|
+
const key = `${boundaryKey(boundary)} ${anchorName}`;
|
|
38
|
+
const cached = layoutCache.get(key);
|
|
35
39
|
if (cached !== void 0) return cached;
|
|
36
|
-
const result = computeAnchor(layout, anchorName);
|
|
37
|
-
layoutCache.set(
|
|
40
|
+
const result = computeAnchor(layout, anchorName, boundary);
|
|
41
|
+
layoutCache.set(key, result);
|
|
38
42
|
return result;
|
|
39
43
|
};
|
|
40
44
|
/**
|
|
@@ -57,7 +61,7 @@ var resolveEdgePoint = (layout, side, t) => {
|
|
|
57
61
|
const key = `${side}:${t}`;
|
|
58
62
|
const cached = layoutCache.get(key);
|
|
59
63
|
if (cached !== void 0) return cached;
|
|
60
|
-
const result = positionToIR(edgePoint(layout.rect, side, t));
|
|
64
|
+
const result = positionToIR(edgePoint(layout.rect, side, t, layout.shapeParams ?? {}));
|
|
61
65
|
layoutCache.set(key, result);
|
|
62
66
|
return result;
|
|
63
67
|
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Rect } from '../geometry/rect';
|
|
2
|
+
import { IRBoundary } from '../ir';
|
|
3
|
+
import { IRJsonObject } from '../ir/json';
|
|
4
|
+
import { ShapeDefinition } from '../shapes';
|
|
5
|
+
/**
|
|
6
|
+
* 把连接面取值解析为「计算 boundaryPoint / anchor 所需的 def + rect + params」
|
|
7
|
+
* @description layout-neutral:borrowed/builtin 一律喂目标节点的视觉 AABB rect,绝不调其 circumscribe。
|
|
8
|
+
* 保留字 'shape' → 视觉 def 原样;'circle' → ellipse def + squared-to-max rect;
|
|
9
|
+
* 保留字 'rectangle' / 'ellipse' → 对应内置 def + 视觉 AABB;其余 → registry 查表。
|
|
10
|
+
* 保留字优先于 registry 同名 shape。
|
|
11
|
+
*/
|
|
12
|
+
export declare const resolveBoundary: (boundary: IRBoundary | undefined, visualDef: ShapeDefinition, visualRect: Rect, visualParams: IRJsonObject, registry: Record<string, ShapeDefinition>) => {
|
|
13
|
+
def: ShapeDefinition;
|
|
14
|
+
rect: Rect;
|
|
15
|
+
params: IRJsonObject;
|
|
16
|
+
};
|
|
17
|
+
/** 连接面的稳定字符串判别(anchor cache key 用) */
|
|
18
|
+
export declare const boundaryKey: (boundary: IRBoundary | undefined) => string;
|
|
19
|
+
//# sourceMappingURL=boundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../../src/compile/boundary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAcjD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,UAAU,GAAG,SAAS,EAChC,WAAW,eAAe,EAC1B,YAAY,IAAI,EAChB,cAAc,YAAY,EAC1B,UAAU,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,KACxC;IAAE,GAAG,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAuB1D,CAAC;AAEF,sCAAsC;AACtC,eAAO,MAAM,WAAW,GAAI,UAAU,UAAU,GAAG,SAAS,KAAG,MAI9D,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ellipse } from "../shapes/ellipse.js";
|
|
2
|
+
import { rectangle } from "../shapes/rectangle.js";
|
|
3
|
+
//#region src/compile/boundary.ts
|
|
4
|
+
/** 保留字:连接面 = 节点自身视觉形状 */
|
|
5
|
+
var SELF = "shape";
|
|
6
|
+
/** 保留字:真圆(半径 = AABB 较长半轴) */
|
|
7
|
+
var CIRCLE = "circle";
|
|
8
|
+
/** 把 rect 收成边长 = max(width, height) 的正方(中心 / rotate 不变)——circle 连接面用 */
|
|
9
|
+
var squareToMax = (rect) => {
|
|
10
|
+
const side = Math.max(rect.width, rect.height);
|
|
11
|
+
return {
|
|
12
|
+
x: rect.x,
|
|
13
|
+
y: rect.y,
|
|
14
|
+
width: side,
|
|
15
|
+
height: side,
|
|
16
|
+
rotate: rect.rotate
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* 把连接面取值解析为「计算 boundaryPoint / anchor 所需的 def + rect + params」
|
|
21
|
+
* @description layout-neutral:borrowed/builtin 一律喂目标节点的视觉 AABB rect,绝不调其 circumscribe。
|
|
22
|
+
* 保留字 'shape' → 视觉 def 原样;'circle' → ellipse def + squared-to-max rect;
|
|
23
|
+
* 保留字 'rectangle' / 'ellipse' → 对应内置 def + 视觉 AABB;其余 → registry 查表。
|
|
24
|
+
* 保留字优先于 registry 同名 shape。
|
|
25
|
+
*/
|
|
26
|
+
var resolveBoundary = (boundary, visualDef, visualRect, visualParams, registry) => {
|
|
27
|
+
if (boundary === void 0 || boundary === SELF) return {
|
|
28
|
+
def: visualDef,
|
|
29
|
+
rect: visualRect,
|
|
30
|
+
params: visualParams
|
|
31
|
+
};
|
|
32
|
+
if (boundary === CIRCLE) return {
|
|
33
|
+
def: ellipse,
|
|
34
|
+
rect: squareToMax(visualRect),
|
|
35
|
+
params: {}
|
|
36
|
+
};
|
|
37
|
+
if (boundary === "rectangle") return {
|
|
38
|
+
def: rectangle,
|
|
39
|
+
rect: visualRect,
|
|
40
|
+
params: {}
|
|
41
|
+
};
|
|
42
|
+
if (boundary === "ellipse") return {
|
|
43
|
+
def: ellipse,
|
|
44
|
+
rect: visualRect,
|
|
45
|
+
params: {}
|
|
46
|
+
};
|
|
47
|
+
const type = typeof boundary === "string" ? boundary : boundary.type;
|
|
48
|
+
const rawParams = typeof boundary === "string" ? {} : boundary.params ?? {};
|
|
49
|
+
const def = Object.prototype.hasOwnProperty.call(registry, type) ? registry[type] : void 0;
|
|
50
|
+
if (!def) throw new Error(`Unknown connection surface '${type}'; reserved: shape/circle, registered: ${Object.keys(registry).sort().join(", ")}`);
|
|
51
|
+
return {
|
|
52
|
+
def,
|
|
53
|
+
rect: visualRect,
|
|
54
|
+
params: def.paramsSchema.parse(rawParams)
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
/** 连接面的稳定字符串判别(anchor cache key 用) */
|
|
58
|
+
var boundaryKey = (boundary) => {
|
|
59
|
+
if (boundary === void 0) return SELF;
|
|
60
|
+
if (typeof boundary === "string") return boundary;
|
|
61
|
+
return `${boundary.type}:${JSON.stringify(boundary.params ?? {})}`;
|
|
62
|
+
};
|
|
63
|
+
//#endregion
|
|
64
|
+
export { boundaryKey, resolveBoundary };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/compile/compile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAwC,MAAM,OAAO,CAAC;AACtE,OAAO,KAAK,EAAa,KAAK,EAA6B,MAAM,cAAc,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAwBzD,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/compile/compile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAwC,MAAM,OAAO,CAAC;AACtE,OAAO,KAAK,EAAa,KAAK,EAA6B,MAAM,cAAc,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAwBzD,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AA6CrE,uEAAuE;AACvE,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,IAAI,EACA,2BAA2B,GAC3B,gBAAgB,GAChB,0BAA0B,GAC1B,wBAAwB,GACxB,yBAAyB,GACzB,sBAAsB,GACtB,8BAA8B,GAC9B,oBAAoB,GACpB,mBAAmB,GACnB,yBAAyB,GACzB,yBAAyB,GACzB,2BAA2B,GAC3B,0BAA0B,GAC1B,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClB,iBAAiB;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,2BAA2B;AAC3B,MAAM,MAAM,cAAc,GAAG;IAC3B,oCAAoC;IACpC,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC7C;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IACzD;;;;OAIG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACxC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAwJF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,IAAI,EAAE,EAAE,UAAS,cAAmB,KAAG,KAqWrE,CAAC"}
|
|
@@ -38,7 +38,8 @@ var zeroSizeRectAt = (id, [cx, cy]) => ({
|
|
|
38
38
|
textHeight: 0,
|
|
39
39
|
align: "middle",
|
|
40
40
|
lineHeight: 0,
|
|
41
|
-
fontSize: 0
|
|
41
|
+
fontSize: 0,
|
|
42
|
+
shapes: BUILTIN_SHAPES
|
|
42
43
|
});
|
|
43
44
|
/**
|
|
44
45
|
* 把 coordinate 注册成 0×0 NodeLayout
|
|
@@ -77,6 +78,16 @@ var viewBoxToLayout = (vb, round) => {
|
|
|
77
78
|
};
|
|
78
79
|
};
|
|
79
80
|
/**
|
|
81
|
+
* 自动算 layout 的 finite 守卫:四值非全 finite 即抛清晰错(LLM 可读),不泄漏进 Scene
|
|
82
|
+
* @description computeLayout 由 `center ± halfWidth` 等运算聚合——极端 shape 几何(如 outerRadius:1e308
|
|
83
|
+
* 半轴 finite 但 center+halfWidth 溢出 Infinity)会让运算结果脏。schema 的 `.finite()` 只守单字段输入,
|
|
84
|
+
* 守不住聚合后的溢出;此处复用 viewBoxToLayout 同款 finite 关口,是自动 layout 进 Scene 前的唯一兜底。
|
|
85
|
+
*/
|
|
86
|
+
var assertFiniteLayout = (layout) => {
|
|
87
|
+
if (!Number.isFinite(layout.x) || !Number.isFinite(layout.y) || !Number.isFinite(layout.width) || !Number.isFinite(layout.height)) throw new Error(`Node layout produced non-finite bounds (x=${String(layout.x)}, y=${String(layout.y)}, width=${String(layout.width)}, height=${String(layout.height)}); check shape geometry (e.g. extreme radius).`);
|
|
88
|
+
return layout;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
80
91
|
* 默认 warn dispatcher:dev 模式 console.warn、生产静默
|
|
81
92
|
* @description 用户传 onWarn 时使用用户的;不传走此 fallback
|
|
82
93
|
*/
|
|
@@ -305,6 +316,7 @@ var compileToScene = (ir, options = {}) => {
|
|
|
305
316
|
children: stableSortByZIndex(sealSink(innerSink))
|
|
306
317
|
};
|
|
307
318
|
if (child.id !== void 0) group.id = child.id;
|
|
319
|
+
if (child.meta !== void 0) group.meta = child.meta;
|
|
308
320
|
if (hasOwnTransforms) group.transforms = [...ownTransforms];
|
|
309
321
|
if (child.clip !== void 0) group.clipRef = clip.resolve(child.clip);
|
|
310
322
|
sink.push(group);
|
|
@@ -339,7 +351,7 @@ var compileToScene = (ir, options = {}) => {
|
|
|
339
351
|
const resources = [...paint.resources(), ...clip.resources()];
|
|
340
352
|
return {
|
|
341
353
|
primitives: stableSortByZIndex(sealSink(primitives)),
|
|
342
|
-
layout: loweredIr.viewBox !== void 0 ? viewBoxToLayout(loweredIr.viewBox, round) : computeLayout(allPoints, layoutPadding, round),
|
|
354
|
+
layout: loweredIr.viewBox !== void 0 ? viewBoxToLayout(loweredIr.viewBox, round) : assertFiniteLayout(computeLayout(allPoints, layoutPadding, round)),
|
|
343
355
|
...resources.length > 0 ? { resources } : {}
|
|
344
356
|
};
|
|
345
357
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Position } from '../geometry/point';
|
|
2
2
|
import { Rect } from '../geometry/rect';
|
|
3
|
-
import { AtDirection, IRLabelDefault, IRNode, IRPaintSpec } from '../ir';
|
|
3
|
+
import { AtDirection, IRBoundary, IRJsonObject, IRLabelDefault, IRNode, IRPaintSpec } from '../ir';
|
|
4
4
|
import { PaintResolver } from './paint';
|
|
5
5
|
import { ScenePrimitive, TextLine, Transform } from '../primitive';
|
|
6
6
|
import { ShapeDefinition } from '../shapes';
|
|
@@ -14,6 +14,12 @@ export type NodeLayout = {
|
|
|
14
14
|
shapeName: string;
|
|
15
15
|
/** 已解析的 shape 定义;circumscribe / boundaryPoint / anchor / emit 多点复用,取代旧 switch */
|
|
16
16
|
shapeDef: ShapeDefinition;
|
|
17
|
+
/**
|
|
18
|
+
* 已校验的 per-instance shape 参数(经 `paramsSchema.parse` + `JsonObjectSchema.parse` 双护栏)
|
|
19
|
+
* @description 透传给 `shapeDef` 的 circumscribe / boundaryPoint / anchor / edgePoint / emit;
|
|
20
|
+
* 无参形状(内置 4 个)解析为 `{}`。省略时各调用点以空对象兜底(合成 layout 如 coordinate / scope.id)。
|
|
21
|
+
*/
|
|
22
|
+
shapeParams?: IRJsonObject;
|
|
17
23
|
/**
|
|
18
24
|
* 节点视觉边界框(所有 shape 共享语义)
|
|
19
25
|
* @description rectangle: rect 本身;circle: width=height=2×radius;ellipse: 2×rx,2×ry;diamond: 2×halfA,2×halfB。x,y 是几何中心,rotate 弧度
|
|
@@ -57,7 +63,7 @@ export type NodeLayout = {
|
|
|
57
63
|
/** 描边 dash pattern,已把 dashed/dotted 预设解析为具体 pattern */
|
|
58
64
|
dashPattern?: Array<number>;
|
|
59
65
|
/** rectangle 圆角半径(非 rect shape 无效) */
|
|
60
|
-
|
|
66
|
+
cornerRadius?: number;
|
|
61
67
|
/** 文字颜色,emit 时 'currentColor' 兜底 */
|
|
62
68
|
textColor?: string;
|
|
63
69
|
/** 整节点透明度 0~1(同时挂 shape 与 text primitive) */
|
|
@@ -67,6 +73,12 @@ export type NodeLayout = {
|
|
|
67
73
|
* @description IR 层 `Node.label` 标准化:position 默认 'above'、distance 默认 DEFAULT_LABEL_DISTANCE、font 从 Node 继承
|
|
68
74
|
*/
|
|
69
75
|
labels?: Array<NodeLabelLayout>;
|
|
76
|
+
/** 节点默认连接面(来自 IR `node.boundary`;undefined = 'shape');path 端点 boundary 可覆盖 */
|
|
77
|
+
boundary?: IRBoundary;
|
|
78
|
+
/** provenance 元数据(来自 IR `node.meta`);emit 时原样 stamp 到 node 的 top-level 图元,renderer 忽略 */
|
|
79
|
+
meta?: IRJsonObject;
|
|
80
|
+
/** 构建本 layout 的 shape 注册表引用——借用连接面(borrowed boundary)查表用 */
|
|
81
|
+
shapes: Record<string, ShapeDefinition>;
|
|
70
82
|
};
|
|
71
83
|
/** 节点附属标签 layout(layoutNode 已合并默认值与样式继承) */
|
|
72
84
|
export type NodeLabelLayout = {
|
|
@@ -96,20 +108,24 @@ export type NodeLabelLayout = {
|
|
|
96
108
|
};
|
|
97
109
|
/**
|
|
98
110
|
* 取节点 shape 在 toward 方向的附着点(path 端点贴边用)
|
|
99
|
-
* @description
|
|
111
|
+
* @description 走连接面(boundary)对应的 def.boundaryPoint;margin > 0 时先膨胀外接 Rect,让 path 在 border 外停 margin。
|
|
112
|
+
* boundary 缺省 = 'shape'(视觉形状自身),与改前行为一致。
|
|
100
113
|
*/
|
|
101
|
-
export declare const boundaryPointOf: (layout: NodeLayout, toward: Position) => Position;
|
|
114
|
+
export declare const boundaryPointOf: (layout: NodeLayout, toward: Position, boundary?: IRBoundary | undefined) => Position;
|
|
102
115
|
/**
|
|
103
116
|
* 取节点 shape 命名 anchor(center / north / east / north-east 等)
|
|
104
117
|
* @description 不应用 margin——TikZ 语义中 explicit anchor 取视觉边界点不涉及 outer sep;用于 `'A.north'` 落点。
|
|
105
|
-
*
|
|
118
|
+
* compass(9 个 rect 方位名)走连接面 AABB:'shape' 时归一为 'rectangle'(矩形 AABB),其余按 boundary 解析。
|
|
119
|
+
* 形状专属命名 anchor(tip-N / apex 等非 compass 名)恒走视觉形状自身,boundary 不影响。
|
|
120
|
+
* boundary 缺省 = 'shape',与改前 compass 走 AABB 行为一致(原 shapeDef.anchor 内部也走 rect AABB)。
|
|
106
121
|
*/
|
|
107
|
-
export declare const anchorOf: (layout: NodeLayout, name: string) => Position;
|
|
122
|
+
export declare const anchorOf: (layout: NodeLayout, name: string, boundary?: IRBoundary | undefined) => Position;
|
|
108
123
|
/**
|
|
109
124
|
* 取节点 shape 在指定角度方向的边界点
|
|
110
|
-
* @description 角度是节点**局部坐标系**下的极角(度数:0°=局部 +x,90°=局部 +y)。layout.rect.rotate 把局部基绕中心旋转,得到世界系下的视觉方向;shape boundaryPoint 内部用 rotate-aware 投影,所以这里把局部 (cos, sin) 经 rect.rotate 旋转后加到中心当作世界系 toward 传入。不应用 margin(同 anchorOf);用于 `'A.30'`
|
|
125
|
+
* @description 角度是节点**局部坐标系**下的极角(度数:0°=局部 +x,90°=局部 +y)。layout.rect.rotate 把局部基绕中心旋转,得到世界系下的视觉方向;shape boundaryPoint 内部用 rotate-aware 投影,所以这里把局部 (cos, sin) 经 rect.rotate 旋转后加到中心当作世界系 toward 传入。不应用 margin(同 anchorOf);用于 `'A.30'` 落点。
|
|
126
|
+
* boundary 缺省 = 'shape'(视觉形状自身),与改前行为一致。
|
|
111
127
|
*/
|
|
112
|
-
export declare const angleBoundaryOf: (layout: NodeLayout, angleDeg: number) => Position;
|
|
128
|
+
export declare const angleBoundaryOf: (layout: NodeLayout, angleDeg: number, boundary?: IRBoundary | undefined) => Position;
|
|
113
129
|
/**
|
|
114
130
|
* IR Node → 内部 NodeLayout
|
|
115
131
|
* @description 文本度量 + padding 推内框半轴;按 shape 算外接边界(circle 取半对角线、ellipse ×√2、diamond ×2);解析 position 为几何中心;rotate 度数转弧度。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/compile/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAc,MAAM,EAAe,WAAW,
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/compile/node.ts"],"names":[],"mappings":"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"}
|
package/dist/es/compile/node.js
CHANGED
|
@@ -1,9 +1,62 @@
|
|
|
1
|
+
import { JsonObjectSchema } from "../ir/json.js";
|
|
2
|
+
import { asRectAnchor } from "../shapes/_shared.js";
|
|
1
3
|
import { BUILTIN_SHAPES } from "../shapes/index.js";
|
|
2
4
|
import { resolvePosition } from "./position.js";
|
|
3
5
|
import { toAlphabeticBaselineY } from "./text-baseline.js";
|
|
6
|
+
import { resolveBoundary } from "./boundary.js";
|
|
4
7
|
//#region src/compile/node.ts
|
|
5
8
|
var DEFAULT_FONT_SIZE = 14;
|
|
6
9
|
var DEFAULT_PADDING = 8;
|
|
10
|
+
/** 无参 / 合成 layout 的 shape params 兜底(避免每次调用重建空对象) */
|
|
11
|
+
var EMPTY_SHAPE_PARAMS = {};
|
|
12
|
+
/**
|
|
13
|
+
* 规范化 `Node.shape` 为 `{ type, params }`
|
|
14
|
+
* @description 裸 string → `{ type, params: {} }`;`{ type, params? }` → params 缺省补 `{}`;
|
|
15
|
+
* 缺省(undefined)→ `{ type: 'rectangle', params: {} }`。`'circle'`(裸 string)消解为
|
|
16
|
+
* `{ type: 'ellipse', params: { circumscribe: 'equal' } }`——circle 无独立几何,是 ellipse 等轴 preset 别名。
|
|
17
|
+
* `'diamond'`(裸 string)消解为 `{ type: 'polygon', params: { sides: 4, rotate: 45 } }`——diamond 无独立几何,
|
|
18
|
+
* 是 polygon 4 边形(自旋 45°)preset 别名。仅做形态归一,不查表 / 不校验。
|
|
19
|
+
*/
|
|
20
|
+
var normalizeShape = (shape) => {
|
|
21
|
+
if (shape === void 0) return {
|
|
22
|
+
type: "rectangle",
|
|
23
|
+
params: {}
|
|
24
|
+
};
|
|
25
|
+
if (shape === "circle") return {
|
|
26
|
+
type: "ellipse",
|
|
27
|
+
params: { circumscribe: "equal" }
|
|
28
|
+
};
|
|
29
|
+
if (shape === "diamond") return {
|
|
30
|
+
type: "polygon",
|
|
31
|
+
params: {
|
|
32
|
+
sides: 4,
|
|
33
|
+
rotate: 45
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
if (typeof shape === "string") return {
|
|
37
|
+
type: shape,
|
|
38
|
+
params: {}
|
|
39
|
+
};
|
|
40
|
+
const ref = shape;
|
|
41
|
+
return {
|
|
42
|
+
type: ref.type,
|
|
43
|
+
params: ref.params ?? {}
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* 递归把 JSON 值里所有数值叶子乘以 factor(数组 / 对象深入,string / boolean / null 原样)
|
|
48
|
+
* @description 用于 shape params 随 node scale 协同缩放;输入已是 JSON-safe(双护栏过),输出仍 JSON-safe。
|
|
49
|
+
*/
|
|
50
|
+
var scaleJsonNumbers = (value, factor) => {
|
|
51
|
+
if (typeof value === "number") return value * factor;
|
|
52
|
+
if (Array.isArray(value)) return value.map((v) => scaleJsonNumbers(v, factor));
|
|
53
|
+
if (value !== null && typeof value === "object") {
|
|
54
|
+
const out = {};
|
|
55
|
+
for (const [k, v] of Object.entries(value)) out[k] = scaleJsonNumbers(v, factor);
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
};
|
|
7
60
|
var DEFAULT_LINE_HEIGHT_FACTOR = 1.2;
|
|
8
61
|
var DEG_TO_RAD = Math.PI / 180;
|
|
9
62
|
/** CJK / fullwidth ranges: break per-character (no whitespace needed) */
|
|
@@ -73,16 +126,28 @@ var inflateRect = (r, m) => m === 0 ? r : {
|
|
|
73
126
|
};
|
|
74
127
|
/**
|
|
75
128
|
* 取节点 shape 在 toward 方向的附着点(path 端点贴边用)
|
|
76
|
-
* @description
|
|
129
|
+
* @description 走连接面(boundary)对应的 def.boundaryPoint;margin > 0 时先膨胀外接 Rect,让 path 在 border 外停 margin。
|
|
130
|
+
* boundary 缺省 = 'shape'(视觉形状自身),与改前行为一致。
|
|
77
131
|
*/
|
|
78
|
-
var boundaryPointOf = (layout, toward
|
|
132
|
+
var boundaryPointOf = (layout, toward, boundary = "shape") => {
|
|
133
|
+
const { def, rect, params } = resolveBoundary(boundary, layout.shapeDef, layout.rect, layout.shapeParams ?? EMPTY_SHAPE_PARAMS, layout.shapes);
|
|
134
|
+
return def.boundaryPoint(inflateRect(rect, layout.margin), toward, params);
|
|
135
|
+
};
|
|
79
136
|
/**
|
|
80
137
|
* 取节点 shape 命名 anchor(center / north / east / north-east 等)
|
|
81
138
|
* @description 不应用 margin——TikZ 语义中 explicit anchor 取视觉边界点不涉及 outer sep;用于 `'A.north'` 落点。
|
|
82
|
-
*
|
|
139
|
+
* compass(9 个 rect 方位名)走连接面 AABB:'shape' 时归一为 'rectangle'(矩形 AABB),其余按 boundary 解析。
|
|
140
|
+
* 形状专属命名 anchor(tip-N / apex 等非 compass 名)恒走视觉形状自身,boundary 不影响。
|
|
141
|
+
* boundary 缺省 = 'shape',与改前 compass 走 AABB 行为一致(原 shapeDef.anchor 内部也走 rect AABB)。
|
|
83
142
|
*/
|
|
84
|
-
var anchorOf = (layout, name) => {
|
|
85
|
-
|
|
143
|
+
var anchorOf = (layout, name, boundary = "shape") => {
|
|
144
|
+
if (asRectAnchor(name) !== void 0) {
|
|
145
|
+
const { def, rect, params } = resolveBoundary(boundary === "shape" ? "rectangle" : boundary, layout.shapeDef, layout.rect, layout.shapeParams ?? EMPTY_SHAPE_PARAMS, layout.shapes);
|
|
146
|
+
const p = def.anchor(rect, name, params);
|
|
147
|
+
if (p === void 0) throw new Error(`Unknown anchor '${name}' for shape '${layout.shapeName}'`);
|
|
148
|
+
return p;
|
|
149
|
+
}
|
|
150
|
+
const p = layout.shapeDef.anchor(layout.rect, name, layout.shapeParams ?? EMPTY_SHAPE_PARAMS);
|
|
86
151
|
if (p === void 0) throw new Error(`Unknown anchor '${name}' for shape '${layout.shapeName}'`);
|
|
87
152
|
return p;
|
|
88
153
|
};
|
|
@@ -187,9 +252,10 @@ var resolveLabelRotateDeg = (label, lx, ly, cx, cy) => {
|
|
|
187
252
|
};
|
|
188
253
|
/**
|
|
189
254
|
* 取节点 shape 在指定角度方向的边界点
|
|
190
|
-
* @description 角度是节点**局部坐标系**下的极角(度数:0°=局部 +x,90°=局部 +y)。layout.rect.rotate 把局部基绕中心旋转,得到世界系下的视觉方向;shape boundaryPoint 内部用 rotate-aware 投影,所以这里把局部 (cos, sin) 经 rect.rotate 旋转后加到中心当作世界系 toward 传入。不应用 margin(同 anchorOf);用于 `'A.30'`
|
|
255
|
+
* @description 角度是节点**局部坐标系**下的极角(度数:0°=局部 +x,90°=局部 +y)。layout.rect.rotate 把局部基绕中心旋转,得到世界系下的视觉方向;shape boundaryPoint 内部用 rotate-aware 投影,所以这里把局部 (cos, sin) 经 rect.rotate 旋转后加到中心当作世界系 toward 传入。不应用 margin(同 anchorOf);用于 `'A.30'` 落点。
|
|
256
|
+
* boundary 缺省 = 'shape'(视觉形状自身),与改前行为一致。
|
|
191
257
|
*/
|
|
192
|
-
var angleBoundaryOf = (layout, angleDeg) => {
|
|
258
|
+
var angleBoundaryOf = (layout, angleDeg, boundary = "shape") => {
|
|
193
259
|
const rad = angleDeg * Math.PI / 180;
|
|
194
260
|
const lx = Math.cos(rad);
|
|
195
261
|
const ly = Math.sin(rad);
|
|
@@ -197,7 +263,8 @@ var angleBoundaryOf = (layout, angleDeg) => {
|
|
|
197
263
|
const cosR = Math.cos(rot);
|
|
198
264
|
const sinR = Math.sin(rot);
|
|
199
265
|
const toward = [layout.rect.x + lx * cosR - ly * sinR, layout.rect.y + lx * sinR + ly * cosR];
|
|
200
|
-
|
|
266
|
+
const { def, rect, params } = resolveBoundary(boundary, layout.shapeDef, layout.rect, layout.shapeParams ?? EMPTY_SHAPE_PARAMS, layout.shapes);
|
|
267
|
+
return def.boundaryPoint(rect, toward, params);
|
|
201
268
|
};
|
|
202
269
|
/**
|
|
203
270
|
* IR Node → 内部 NodeLayout
|
|
@@ -207,12 +274,20 @@ var angleBoundaryOf = (layout, angleDeg) => {
|
|
|
207
274
|
* 笛卡尔字面量 `Position` 已在 scope 局部度量,行为延续 v0.1。
|
|
208
275
|
*/
|
|
209
276
|
var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], labelDefault, shapes = BUILTIN_SHAPES, resolveBetweenGlobal) => {
|
|
210
|
-
const shapeName = node.shape
|
|
277
|
+
const { type: shapeName, params: rawShapeParams } = normalizeShape(node.shape);
|
|
211
278
|
const shapeDef = Object.prototype.hasOwnProperty.call(shapes, shapeName) ? shapes[shapeName] : void 0;
|
|
212
279
|
if (!shapeDef) throw new Error(`Unknown shape '${shapeName}'; registered shapes: ${Object.keys(shapes).sort().join(", ")}`);
|
|
280
|
+
JsonObjectSchema.parse(rawShapeParams);
|
|
281
|
+
const parsedShapeParams = shapeDef.paramsSchema.parse(rawShapeParams);
|
|
282
|
+
const mergedShapeParams = shapeName === "rectangle" && node.cornerRadius !== void 0 && !("cornerRadius" in parsedShapeParams) ? {
|
|
283
|
+
...parsedShapeParams,
|
|
284
|
+
cornerRadius: node.cornerRadius
|
|
285
|
+
} : parsedShapeParams;
|
|
213
286
|
const sx = node.xScale ?? node.scale ?? 1;
|
|
214
287
|
const sy = node.yScale ?? node.scale ?? 1;
|
|
215
288
|
const fontScale = Math.min(sx, sy);
|
|
289
|
+
const shapeScale = Math.sqrt(sx * sy);
|
|
290
|
+
const shapeParams = sx === 1 && sy === 1 ? mergedShapeParams : shapeDef.scaleParams ? shapeDef.scaleParams(mergedShapeParams, sx, sy) : scaleJsonNumbers(mergedShapeParams, shapeScale);
|
|
216
291
|
const baseFontSize = node.font?.size ?? DEFAULT_FONT_SIZE;
|
|
217
292
|
const fontSize = baseFontSize * fontScale;
|
|
218
293
|
const fontFamily = node.font?.family;
|
|
@@ -262,10 +337,13 @@ var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], l
|
|
|
262
337
|
const minH = node.minimumHeight ?? node.minimumSize ?? 0;
|
|
263
338
|
const innerHalfW = Math.max(textWidth / 2 + xSep, xSep, minW / 2);
|
|
264
339
|
const innerHalfH = Math.max(textHeight / 2 + ySep, ySep, minH / 2);
|
|
265
|
-
const { halfWidth: boundsHalfW, halfHeight: boundsHalfH } = shapeDef.circumscribe(innerHalfW, innerHalfH);
|
|
340
|
+
const { halfWidth: boundsHalfW, halfHeight: boundsHalfH } = shapeDef.circumscribe(innerHalfW, innerHalfH, shapeParams);
|
|
266
341
|
const rotateDeg = node.rotate ?? 0;
|
|
267
342
|
const center = resolvePosition(node.position, nameStack, nodeDistance, scopeChain, resolveBetweenGlobal);
|
|
268
343
|
if (!center) throw new Error(`Cannot resolve position for node ${node.id ?? "(unnamed)"}; polar.origin / at.of / between endpoint may reference an undefined node`);
|
|
344
|
+
const aabbOffset = shapeDef.circumscribeOffset?.(shapeParams);
|
|
345
|
+
const rectCenterX = center[0] + (aabbOffset?.[0] ?? 0);
|
|
346
|
+
const rectCenterY = center[1] + (aabbOffset?.[1] ?? 0);
|
|
269
347
|
const labels = (node.label === void 0 ? void 0 : Array.isArray(node.label) ? node.label : [node.label])?.map((lab) => {
|
|
270
348
|
const labFont = lab.font;
|
|
271
349
|
const labFontSize = (labFont?.size ?? labelDefault?.font?.size ?? baseFontSize) * fontScale;
|
|
@@ -297,9 +375,10 @@ var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], l
|
|
|
297
375
|
id: node.id,
|
|
298
376
|
shapeName,
|
|
299
377
|
shapeDef,
|
|
378
|
+
shapeParams,
|
|
300
379
|
rect: {
|
|
301
|
-
x:
|
|
302
|
-
y:
|
|
380
|
+
x: rectCenterX,
|
|
381
|
+
y: rectCenterY,
|
|
303
382
|
width: 2 * boundsHalfW,
|
|
304
383
|
height: 2 * boundsHalfH,
|
|
305
384
|
rotate: rotateDeg * DEG_TO_RAD
|
|
@@ -321,10 +400,13 @@ var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], l
|
|
|
321
400
|
strokeOpacity: node.drawOpacity,
|
|
322
401
|
strokeWidth: node.strokeWidth,
|
|
323
402
|
dashPattern: resolveDashArray(node.dashArray, node.dashed, node.dotted),
|
|
324
|
-
|
|
403
|
+
cornerRadius: node.cornerRadius,
|
|
325
404
|
textColor: node.textColor,
|
|
326
405
|
opacity: node.opacity,
|
|
327
|
-
labels
|
|
406
|
+
labels,
|
|
407
|
+
boundary: node.boundary,
|
|
408
|
+
meta: node.meta,
|
|
409
|
+
shapes
|
|
328
410
|
};
|
|
329
411
|
};
|
|
330
412
|
/** 从 NodeLayout 收敛 emit 所需的视觉样式子集(ShapeStyle,不含几何 / 文本);fill 经 resolveFill 转 PaintValue */
|
|
@@ -335,7 +417,7 @@ var toShapeStyle = (layout, resolveFill) => ({
|
|
|
335
417
|
strokeOpacity: layout.strokeOpacity,
|
|
336
418
|
strokeWidth: layout.strokeWidth,
|
|
337
419
|
dashPattern: layout.dashPattern,
|
|
338
|
-
|
|
420
|
+
cornerRadius: layout.cornerRadius,
|
|
339
421
|
opacity: layout.opacity
|
|
340
422
|
});
|
|
341
423
|
/**
|
|
@@ -380,7 +462,7 @@ var emitNodePrimitives = (layout, round, resolveFill) => {
|
|
|
380
462
|
...layout.rect,
|
|
381
463
|
rotate: 0
|
|
382
464
|
};
|
|
383
|
-
const shapePrims = [...layout.shapeDef.emit(axisAlignedRect, toShapeStyle(layout, resolveFill), round)];
|
|
465
|
+
const shapePrims = [...layout.shapeDef.emit(axisAlignedRect, toShapeStyle(layout, resolveFill), round, layout.shapeParams ?? EMPTY_SHAPE_PARAMS)];
|
|
384
466
|
const inner = [...shapePrims];
|
|
385
467
|
if (layout.lines) {
|
|
386
468
|
const halfBlockW = layout.textWidth / 2;
|
|
@@ -463,6 +545,7 @@ var emitNodePrimitives = (layout, round, resolveFill) => {
|
|
|
463
545
|
}
|
|
464
546
|
if (!(layout.rotateDeg !== 0 || layout.lines !== void 0)) {
|
|
465
547
|
if (layout.id !== void 0) for (const prim of shapePrims) prim.id = layout.id;
|
|
548
|
+
if (layout.meta !== void 0) for (const prim of shapePrims) prim.meta = layout.meta;
|
|
466
549
|
return inner;
|
|
467
550
|
}
|
|
468
551
|
const group = {
|
|
@@ -470,6 +553,7 @@ var emitNodePrimitives = (layout, round, resolveFill) => {
|
|
|
470
553
|
children: inner
|
|
471
554
|
};
|
|
472
555
|
if (layout.id !== void 0) group.id = layout.id;
|
|
556
|
+
if (layout.meta !== void 0) group.meta = layout.meta;
|
|
473
557
|
if (layout.rotateDeg !== 0) group.transforms = [{
|
|
474
558
|
kind: "rotate",
|
|
475
559
|
degrees: round(layout.rotateDeg),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/anchor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,UAAU,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/anchor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,UAAU,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEtF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AA6B/C;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,QAAQ,EAChB,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,UAAU,GAAG,IA8Bf,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,QAAQ,GACnB,MAAM,UAAU,EAChB,MAAM,UAAU,EAChB,KAAK,IAAI,GAAG,IAAI,KACf,UACqD,CAAC;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,QAAQ,EAChB,QAAQ,UAAU,EAClB,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,UAAU,GAAG,IAuBf,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,SAAS,GAAI,GAAG,UAAU,GAAG,IAAI,EAAE,GAAG,UAAU,GAAG,IAAI,KAAG,OACzB,CAAC;AAE/C,6BAA6B;AAC7B,eAAO,MAAM,WAAW,GAAI,GAAG,UAAU,EAAE,QAAQ,UAAU,EAAE,MAAM,MAAM,KAAG,UAM7E,CAAC"}
|