@retikz/core 0.2.0-alpha.2 → 0.2.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.
Files changed (81) hide show
  1. package/dist/es/compile/compile.d.ts +8 -1
  2. package/dist/es/compile/compile.d.ts.map +1 -1
  3. package/dist/es/compile/compile.js +89 -14
  4. package/dist/es/compile/node.d.ts +19 -10
  5. package/dist/es/compile/node.d.ts.map +1 -1
  6. package/dist/es/compile/node.js +121 -207
  7. package/dist/es/compile/scope.d.ts.map +1 -1
  8. package/dist/es/compile/scope.js +3 -1
  9. package/dist/es/index.d.ts +3 -1
  10. package/dist/es/index.d.ts.map +1 -1
  11. package/dist/es/index.js +4 -2
  12. package/dist/es/ir/node.d.ts +45 -12
  13. package/dist/es/ir/node.d.ts.map +1 -1
  14. package/dist/es/ir/node.js +10 -3
  15. package/dist/es/ir/path/path.d.ts +3 -0
  16. package/dist/es/ir/path/path.d.ts.map +1 -1
  17. package/dist/es/ir/path/path.js +1 -0
  18. package/dist/es/ir/scope.d.ts +44 -22
  19. package/dist/es/ir/scope.d.ts.map +1 -1
  20. package/dist/es/ir/scope.js +5 -2
  21. package/dist/es/shapes/_shared.d.ts +7 -0
  22. package/dist/es/shapes/_shared.d.ts.map +1 -0
  23. package/dist/es/shapes/_shared.js +11 -0
  24. package/dist/es/shapes/circle.d.ts +8 -0
  25. package/dist/es/shapes/circle.d.ts.map +1 -0
  26. package/dist/es/shapes/circle.js +33 -0
  27. package/dist/es/shapes/diamond.d.ts +8 -0
  28. package/dist/es/shapes/diamond.d.ts.map +1 -0
  29. package/dist/es/shapes/diamond.js +65 -0
  30. package/dist/es/shapes/ellipse.d.ts +8 -0
  31. package/dist/es/shapes/ellipse.d.ts.map +1 -0
  32. package/dist/es/shapes/ellipse.js +45 -0
  33. package/dist/es/shapes/index.d.ts +14 -0
  34. package/dist/es/shapes/index.d.ts.map +1 -0
  35. package/dist/es/shapes/index.js +15 -0
  36. package/dist/es/shapes/rectangle.d.ts +8 -0
  37. package/dist/es/shapes/rectangle.d.ts.map +1 -0
  38. package/dist/es/shapes/rectangle.js +40 -0
  39. package/dist/es/shapes/types.d.ts +44 -0
  40. package/dist/es/shapes/types.d.ts.map +1 -0
  41. package/dist/lib/compile/compile.cjs +91 -16
  42. package/dist/lib/compile/compile.d.ts +8 -1
  43. package/dist/lib/compile/compile.d.ts.map +1 -1
  44. package/dist/lib/compile/node.cjs +121 -207
  45. package/dist/lib/compile/node.d.ts +19 -10
  46. package/dist/lib/compile/node.d.ts.map +1 -1
  47. package/dist/lib/compile/scope.cjs +3 -1
  48. package/dist/lib/compile/scope.d.ts.map +1 -1
  49. package/dist/lib/index.cjs +6 -1
  50. package/dist/lib/index.d.ts +3 -1
  51. package/dist/lib/index.d.ts.map +1 -1
  52. package/dist/lib/ir/node.cjs +10 -3
  53. package/dist/lib/ir/node.d.ts +45 -12
  54. package/dist/lib/ir/node.d.ts.map +1 -1
  55. package/dist/lib/ir/path/path.cjs +1 -0
  56. package/dist/lib/ir/path/path.d.ts +3 -0
  57. package/dist/lib/ir/path/path.d.ts.map +1 -1
  58. package/dist/lib/ir/scope.cjs +5 -2
  59. package/dist/lib/ir/scope.d.ts +44 -22
  60. package/dist/lib/ir/scope.d.ts.map +1 -1
  61. package/dist/lib/shapes/_shared.cjs +11 -0
  62. package/dist/lib/shapes/_shared.d.ts +7 -0
  63. package/dist/lib/shapes/_shared.d.ts.map +1 -0
  64. package/dist/lib/shapes/circle.cjs +33 -0
  65. package/dist/lib/shapes/circle.d.ts +8 -0
  66. package/dist/lib/shapes/circle.d.ts.map +1 -0
  67. package/dist/lib/shapes/diamond.cjs +65 -0
  68. package/dist/lib/shapes/diamond.d.ts +8 -0
  69. package/dist/lib/shapes/diamond.d.ts.map +1 -0
  70. package/dist/lib/shapes/ellipse.cjs +45 -0
  71. package/dist/lib/shapes/ellipse.d.ts +8 -0
  72. package/dist/lib/shapes/ellipse.d.ts.map +1 -0
  73. package/dist/lib/shapes/index.cjs +14 -0
  74. package/dist/lib/shapes/index.d.ts +14 -0
  75. package/dist/lib/shapes/index.d.ts.map +1 -0
  76. package/dist/lib/shapes/rectangle.cjs +40 -0
  77. package/dist/lib/shapes/rectangle.d.ts +8 -0
  78. package/dist/lib/shapes/rectangle.d.ts.map +1 -0
  79. package/dist/lib/shapes/types.d.ts +44 -0
  80. package/dist/lib/shapes/types.d.ts.map +1 -0
  81. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  import { IR } from '../ir';
2
2
  import { Scene } from '../primitive';
3
+ import { ShapeDefinition } from '../shapes';
3
4
  import { TextMeasurer } from './text-metrics';
4
5
  /** 编译期警告:path / position 解析失败时通过 `CompileOptions.onWarn` 发出,不影响编译产物 */
5
6
  export type CompileWarning = {
@@ -7,7 +8,7 @@ export type CompileWarning = {
7
8
  * 警告类型代码(机器可读)
8
9
  * @description 用户可按 code 分支处理;未来 alpha 加新 code 不破坏调用方
9
10
  */
10
- code: 'UNRESOLVED_NODE_REFERENCE' | 'PATH_TOO_SHORT' | 'ANCHOR_RESOLUTION_FAILED' | 'OFFSET_BASE_UNRESOLVED' | 'POLAR_ORIGIN_UNRESOLVED' | 'AT_TARGET_UNRESOLVED' | 'RELATIVE_INITIAL_NO_PREV_END' | 'BBOX_EXTREME_INPUT' | 'DUPLICATE_NODE_ID' | (string & {});
11
+ code: 'UNRESOLVED_NODE_REFERENCE' | 'PATH_TOO_SHORT' | 'ANCHOR_RESOLUTION_FAILED' | 'OFFSET_BASE_UNRESOLVED' | 'POLAR_ORIGIN_UNRESOLVED' | 'AT_TARGET_UNRESOLVED' | 'RELATIVE_INITIAL_NO_PREV_END' | 'BBOX_EXTREME_INPUT' | 'DUPLICATE_NODE_ID' | 'SHAPE_OVERRIDES_BUILTIN' | (string & {});
11
12
  /** 人类可读消息(英文) */
12
13
  message: string;
13
14
  /** IR locator 路径(jq-like,如 `'children[3].path.children[1].to'`) */
@@ -34,6 +35,12 @@ export type CompileOptions = {
34
35
  * @description path / position 解析失败时按 IR locator + code + message 同步触发;不传时 dev 模式(`process.env.NODE_ENV !== 'production'`)默认 `console.warn`、生产静默
35
36
  */
36
37
  onWarn?: (warning: CompileWarning) => void;
38
+ /**
39
+ * 运行时注入的第三方 shape(不进 IR)
40
+ * @description 有效 shape 表 = `{ ...BUILTIN_SHAPES, ...shapes }`——同名 key 覆盖内置,经 `onWarn` 发
41
+ * `SHAPE_OVERRIDES_BUILTIN`。IR 的 `node.shape` 仍是字符串;未注册名在编译期 throw。
42
+ */
43
+ shapes?: Record<string, ShapeDefinition>;
37
44
  };
38
45
  /**
39
46
  * IR → Scene 纯函数转换,所有 adapter 共享
@@ -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;AAoBhF,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AA2CrE,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,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;CAC5C,CAAC;AAsDF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,IAAI,EAAE,EAAE,UAAS,cAAmB,KAAG,KA+MrE,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;AAoBjD,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AA4CrE,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,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;CAC1C,CAAC;AA6FF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,IAAI,EAAE,EAAE,UAAS,cAAmB,KAAG,KA4RrE,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { rect } from "../geometry/rect.js";
2
+ import { BUILTIN_SHAPES } from "../shapes/index.js";
2
3
  import { NameStack } from "./name-stack.js";
3
4
  import { applyTransformChain, computeScopeBoundingBox, lowerScopeTransforms, projectLayoutToGlobal, registerScopeAsLayout } from "./scope.js";
4
5
  import { resolvePosition } from "./position.js";
@@ -16,7 +17,8 @@ import { computeLayout } from "./layout.js";
16
17
  */
17
18
  var zeroSizeRectAt = (id, [cx, cy]) => ({
18
19
  id,
19
- shape: "rectangle",
20
+ shapeName: "rectangle",
21
+ shapeDef: BUILTIN_SHAPES.rectangle,
20
22
  rect: {
21
23
  x: cx,
22
24
  y: cy,
@@ -54,6 +56,18 @@ var defaultWarnDispatcher = (warning) => {
54
56
  if (typeof process !== "undefined" && process.env.NODE_ENV === "production") return;
55
57
  console.warn(`[retikz] ${warning.code} at ${warning.path}: ${warning.message}`);
56
58
  };
59
+ var makePathPlaceholder = () => ({ type: "path-placeholder" });
60
+ /** 把内部 sink 收窄回公开 ScenePrimitive[]:占位已全部回填(compileToScene 末端 placeholderBalance 无条件校验兜底) */
61
+ var sealSink = (sink) => sink;
62
+ /** dev 诊断:递归找出残留占位的 index 路径,供末端无条件校验报错时定位 */
63
+ var collectPlaceholderLocators = (prims, prefix = "primitives") => {
64
+ const locators = [];
65
+ prims.forEach((prim, idx) => {
66
+ if (prim.type === "path-placeholder") locators.push(`${prefix}[${idx}]`);
67
+ else if (prim.type === "group") locators.push(...collectPlaceholderLocators(prim.children, `${prefix}[${idx}].children`));
68
+ });
69
+ return locators;
70
+ };
57
71
  /** scope.transforms 解析失败时根据失败成因映射的 warn code */
58
72
  var scopeTransformWarnCode = (scope) => {
59
73
  for (const t of scope.transforms ?? []) {
@@ -84,12 +98,44 @@ var compileToScene = (ir, options = {}) => {
84
98
  const round = makeRound(options.precision ?? 2);
85
99
  const nodeDistance = options.nodeDistance;
86
100
  const onWarn = options.onWarn ?? defaultWarnDispatcher;
101
+ const effectiveShapes = options.shapes ? {
102
+ ...BUILTIN_SHAPES,
103
+ ...options.shapes
104
+ } : BUILTIN_SHAPES;
105
+ if (options.shapes) {
106
+ for (const name of Object.keys(options.shapes)) if (Object.prototype.hasOwnProperty.call(BUILTIN_SHAPES, name)) onWarn({
107
+ code: "SHAPE_OVERRIDES_BUILTIN",
108
+ message: `Injected shape '${name}' overrides the built-in shape of the same name.`,
109
+ path: `options.shapes.${name}`
110
+ });
111
+ }
87
112
  const primitives = [];
113
+ /** 已 push 但未回填的占位计数;compileToScene 返回前必须归零(无条件守 Scene 公开契约) */
114
+ let placeholderBalance = 0;
115
+ /**
116
+ * primitive → 显式 zIndex 旁路记录(缺省视为 0);sealSink 后按它稳定排序,不写进 primitive 本体(保 Scene 输出纯净)。
117
+ * key 只会是 real ScenePrimitive——占位 PathPlaceholder 永不进此 Map(占位即将被回填替换)。
118
+ */
119
+ const zIndexOf = /* @__PURE__ */ new Map();
120
+ /**
121
+ * 按 zIndex 升序原地稳定排序:同 zIndex 保持原 IR 顺序(decorate-sort 带原始下标)。全 0 键 = 恒等。
122
+ * 仅在 sealSink(占位已回填、类型已收窄回 ScenePrimitive)之后调用。
123
+ */
124
+ const stableSortByZIndex = (arr) => {
125
+ const decorated = arr.map((prim, index) => ({
126
+ prim,
127
+ index,
128
+ z: zIndexOf.get(prim) ?? 0
129
+ }));
130
+ decorated.sort((a, b) => a.z - b.z || a.index - b.index);
131
+ for (let i = 0; i < arr.length; i++) arr[i] = decorated[i].prim;
132
+ return arr;
133
+ };
88
134
  const nameStack = new NameStack({ onDuplicate: (info) => onWarn(formatDuplicateWarning(info)) });
89
135
  const allPoints = [];
90
136
  /**
91
137
  * 解析一批本层收集的 pending paths(lookup-only 阶段)
92
- * @description path primitive 一律 push 到顶层 `primitives` —— 端点已是全局坐标,不能进 GroupPrim 否则被 scope.transform 二次 apply。NameStack 切到 pass2 守门:path 解析中误调 register 抛 internal error;解析完切回 pass1 让上层 scope 子树继续 register 子节点。
138
+ * @description 两种落点:有 `slot`(scopeChain 为空)→ 原位 splice 回填该 path 在本层 sink 占的位(按引用定位免索引漂移),保住与同层 node 的 IR 声明序;无 `slot`(scopeChain 非空)→ hoist 到顶层 `primitives`,因端点已是全局坐标、进 transformed GroupPrim 会被 scope.transform 二次 apply。NameStack 切到 pass2 守门:path 解析中误调 register 抛 internal error;解析完切回 pass1 让上层 scope 子树继续 register 子节点。
93
139
  * `item.scopeChain` 记录该 path 所属 scope 累积 transform 链——传给 emitPathPrimitive,
94
140
  * 让 step.to 内的 polar/at/offset 字面量按"当前 scope 局部度量 + 末端 apply chain"投影回全局。
95
141
  */
@@ -103,10 +149,18 @@ var compileToScene = (ir, options = {}) => {
103
149
  irPath: item.irPath,
104
150
  scopeChain: item.scopeChain
105
151
  });
106
- if (result) {
107
- for (const prim of result.primitives) primitives.push(prim);
108
- for (const p of result.points) allPoints.push(p);
152
+ if (item.slot) {
153
+ const idx = item.slot.sink.indexOf(item.slot.placeholder);
154
+ if (idx === -1) throw new Error("internal: path placeholder missing from its sink");
155
+ const real = result?.primitives ?? [];
156
+ item.slot.sink.splice(idx, 1, ...real);
157
+ if (item.zIndex !== void 0) for (const prim of real) zIndexOf.set(prim, item.zIndex);
158
+ placeholderBalance--;
159
+ } else if (result) for (const prim of result.primitives) {
160
+ primitives.push(prim);
161
+ if (item.zIndex !== void 0) zIndexOf.set(prim, item.zIndex);
109
162
  }
163
+ if (result) for (const p of result.points) allPoints.push(p);
110
164
  }
111
165
  } finally {
112
166
  nameStack.exitLookupPhase();
@@ -127,10 +181,13 @@ var compileToScene = (ir, options = {}) => {
127
181
  for (let i = 0; i < children.length; i++) {
128
182
  const child = children[i];
129
183
  if (child.type === "node") {
130
- const layout = layoutNode(resolveNodeStyle(child, styleStack), measureText, nameStack, nodeDistance, chain, resolveLabelDefault(styleStack));
184
+ const layout = layoutNode(resolveNodeStyle(child, styleStack), measureText, nameStack, nodeDistance, chain, resolveLabelDefault(styleStack), effectiveShapes);
131
185
  const globalLayout = chain.length === 0 ? layout : projectLayoutToGlobal(layout, chain);
132
186
  if (child.id) nameStack.register(child.id, globalLayout, `${locatorPrefix}children[${i}].node.id`);
133
- for (const prim of emitNodePrimitives(layout, round)) sink.push(prim);
187
+ for (const prim of emitNodePrimitives(layout, round)) {
188
+ sink.push(prim);
189
+ if (child.zIndex !== void 0) zIndexOf.set(prim, child.zIndex);
190
+ }
134
191
  allPoints.push(rect.anchor(globalLayout.rect, "north-west"), rect.anchor(globalLayout.rect, "north-east"), rect.anchor(globalLayout.rect, "south-west"), rect.anchor(globalLayout.rect, "south-east"));
135
192
  layoutsAccumulator.push(globalLayout);
136
193
  } else if (child.type === "coordinate") {
@@ -183,22 +240,40 @@ var compileToScene = (ir, options = {}) => {
183
240
  if (innerSink.length === 0 && !hasOwnTransforms && child.id === void 0) continue;
184
241
  const group = {
185
242
  type: "group",
186
- children: innerSink
243
+ children: stableSortByZIndex(sealSink(innerSink))
187
244
  };
188
245
  if (hasOwnTransforms) group.transforms = [...ownTransforms];
189
246
  sink.push(group);
190
- } else pathsAccumulator.push({
191
- path: resolveEffectivePath(child, styleStack),
192
- irPath: `${locatorPrefix}children[${i}].path`,
193
- scopeChain: chain
194
- });
247
+ if (child.zIndex !== void 0) zIndexOf.set(group, child.zIndex);
248
+ } else {
249
+ const pending = {
250
+ path: resolveEffectivePath(child, styleStack),
251
+ irPath: `${locatorPrefix}children[${i}].path`,
252
+ scopeChain: chain,
253
+ zIndex: child.zIndex
254
+ };
255
+ if (chain.length === 0) {
256
+ const placeholder = makePathPlaceholder();
257
+ sink.push(placeholder);
258
+ pending.slot = {
259
+ sink,
260
+ placeholder
261
+ };
262
+ placeholderBalance++;
263
+ }
264
+ pathsAccumulator.push(pending);
265
+ }
195
266
  }
196
267
  };
197
268
  const rootPaths = [];
198
269
  processChildren(ir.children, [], primitives, "", [], rootPaths, []);
199
270
  resolvePendingPaths(rootPaths);
271
+ if (placeholderBalance !== 0) {
272
+ const detail = typeof process !== "undefined" && process.env.NODE_ENV !== "production" ? ` at ${collectPlaceholderLocators(primitives).join(", ")}` : "";
273
+ throw new Error(`internal: ${placeholderBalance} unresolved path placeholder(s) leaked into Scene output${detail}`);
274
+ }
200
275
  return {
201
- primitives,
276
+ primitives: stableSortByZIndex(sealSink(primitives)),
202
277
  layout: computeLayout(allPoints, layoutPadding, round)
203
278
  };
204
279
  };
@@ -1,14 +1,17 @@
1
1
  import { Position } from '../geometry/point';
2
- import { Rect, RectAnchor } from '../geometry/rect';
3
- import { AtDirection, IRLabelDefault, IRNode, NodeShape } from '../ir';
2
+ import { Rect } from '../geometry/rect';
3
+ import { AtDirection, IRLabelDefault, IRNode } from '../ir';
4
4
  import { ScenePrimitive, TextLine, Transform } from '../primitive';
5
+ import { ShapeDefinition } from '../shapes';
5
6
  import { NameStack } from './name-stack';
6
7
  import { TextMeasurer } from './text-metrics';
7
8
  export type NodeLayout = {
8
9
  /** 节点 id(其他位置可引用) */
9
10
  id?: string;
10
- /** 节点形状,所有几何 / boundaryPoint shape 多态 */
11
- shape: NodeShape;
11
+ /** 节点形状名(诊断 / 错误信息用;几何走 shapeDef) */
12
+ shapeName: string;
13
+ /** 已解析的 shape 定义;circumscribe / boundaryPoint / anchor / emit 多点复用,取代旧 switch */
14
+ shapeDef: ShapeDefinition;
12
15
  /**
13
16
  * 节点视觉边界框(所有 shape 共享语义)
14
17
  * @description rectangle: rect 本身;circle: width=height=2×radius;ellipse: 2×rx,2×ry;diamond: 2×halfA,2×halfB。x,y 是几何中心,rotate 弧度
@@ -76,17 +79,22 @@ export type NodeLabelLayout = {
76
79
  fontFamily?: string;
77
80
  fontWeight?: string | number;
78
81
  fontStyle?: 'normal' | 'italic' | 'oblique';
82
+ /** label 文本自旋模式(none / radial / tangent / 数字角度);缺省 = 不旋转 */
83
+ rotate?: 'none' | 'radial' | 'tangent' | number;
84
+ /** 自旋后若文字倒置则翻 180°;缺省 false */
85
+ keepUpright?: boolean;
79
86
  };
80
87
  /**
81
88
  * 取节点 shape 在 toward 方向的附着点(path 端点贴边用)
82
- * @description shape 多态调用各自 boundaryPoint;margin > 0 时形状先外扩,让 path 在 border 外停 margin
89
+ * @description shapeDef.boundaryPoint;margin > 0 时先膨胀外接 Rect,让 path 在 border 外停 margin
83
90
  */
84
91
  export declare const boundaryPointOf: (layout: NodeLayout, toward: Position) => Position;
85
92
  /**
86
- * 取节点 shape 命名 anchor(center / north / east / north-east 等 9 个)
87
- * @description 不应用 margin——TikZ 语义中 explicit anchor 取视觉边界点不涉及 outer sep;用于 `'A.north'` 落点
93
+ * 取节点 shape 命名 anchor(center / north / east / north-east 等)
94
+ * @description 不应用 margin——TikZ 语义中 explicit anchor 取视觉边界点不涉及 outer sep;用于 `'A.north'` 落点。
95
+ * shapeDef.anchor 不认识的名字返回 undefined,此处抛 Unknown anchor(列出 shape 名)
88
96
  */
89
- export declare const anchorOf: (layout: NodeLayout, name: RectAnchor) => Position;
97
+ export declare const anchorOf: (layout: NodeLayout, name: string) => Position;
90
98
  /**
91
99
  * 取节点 shape 在指定角度方向的边界点
92
100
  * @description 角度是节点**局部坐标系**下的极角(度数:0°=局部 +x,90°=局部 +y)。layout.rect.rotate 把局部基绕中心旋转,得到世界系下的视觉方向;shape boundaryPoint 内部用 rotate-aware 投影,所以这里把局部 (cos, sin) 经 rect.rotate 旋转后加到中心当作世界系 toward 传入。不应用 margin(同 anchorOf);用于 `'A.30'` 落点
@@ -99,10 +107,11 @@ export declare const angleBoundaryOf: (layout: NodeLayout, angleDeg: number) =>
99
107
  * scope 局部度量),调用方负责后续 `projectLayoutToGlobal` / `applyTransformChain` 投回全局;
100
108
  * 笛卡尔字面量 `Position` 已在 scope 局部度量,行为延续 v0.1。
101
109
  */
102
- export declare const layoutNode: (node: IRNode, measureText: TextMeasurer, nameStack: NameStack, nodeDistance?: number, scopeChain?: ReadonlyArray<Transform>, labelDefault?: IRLabelDefault) => NodeLayout;
110
+ export declare const layoutNode: (node: IRNode, measureText: TextMeasurer, nameStack: NameStack, nodeDistance?: number, scopeChain?: ReadonlyArray<Transform>, labelDefault?: IRLabelDefault, shapes?: Record<string, ShapeDefinition>) => NodeLayout;
103
111
  /**
104
112
  * NodeLayout → Scene primitives
105
- * @description shape 主体按 shape 分发(rect/ellipse/path);text 始终走 TextPrim;有旋转时外层 GroupPrim 用 `rotate(deg cx cy)` 统一包裹(text 必须靠 group 旋转)
113
+ * @description shape 主体走 `shapeDef.emit`(收轴对齐 rect、可出多 primitive);text 始终走 TextPrim
114
+ * 有旋转时外层 GroupPrim 用 `rotate(deg cx cy)` 统一包裹 shape + text(diamond 顶点 / text 都靠 group 旋转)
106
115
  */
107
116
  export declare const emitNodePrimitives: (layout: NodeLayout, round: (n: number) => number) => Array<ScenePrimitive>;
108
117
  //# sourceMappingURL=node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/compile/node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/compile/node.ts"],"names":[],"mappings":"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"}