@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.
- package/dist/es/compile/compile.d.ts +8 -1
- package/dist/es/compile/compile.d.ts.map +1 -1
- package/dist/es/compile/compile.js +89 -14
- package/dist/es/compile/node.d.ts +19 -10
- package/dist/es/compile/node.d.ts.map +1 -1
- package/dist/es/compile/node.js +121 -207
- package/dist/es/compile/scope.d.ts.map +1 -1
- package/dist/es/compile/scope.js +3 -1
- package/dist/es/index.d.ts +3 -1
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js +4 -2
- package/dist/es/ir/node.d.ts +45 -12
- package/dist/es/ir/node.d.ts.map +1 -1
- package/dist/es/ir/node.js +10 -3
- package/dist/es/ir/path/path.d.ts +3 -0
- package/dist/es/ir/path/path.d.ts.map +1 -1
- package/dist/es/ir/path/path.js +1 -0
- package/dist/es/ir/scope.d.ts +44 -22
- package/dist/es/ir/scope.d.ts.map +1 -1
- package/dist/es/ir/scope.js +5 -2
- package/dist/es/shapes/_shared.d.ts +7 -0
- package/dist/es/shapes/_shared.d.ts.map +1 -0
- package/dist/es/shapes/_shared.js +11 -0
- package/dist/es/shapes/circle.d.ts +8 -0
- package/dist/es/shapes/circle.d.ts.map +1 -0
- package/dist/es/shapes/circle.js +33 -0
- package/dist/es/shapes/diamond.d.ts +8 -0
- package/dist/es/shapes/diamond.d.ts.map +1 -0
- package/dist/es/shapes/diamond.js +65 -0
- package/dist/es/shapes/ellipse.d.ts +8 -0
- package/dist/es/shapes/ellipse.d.ts.map +1 -0
- package/dist/es/shapes/ellipse.js +45 -0
- package/dist/es/shapes/index.d.ts +14 -0
- package/dist/es/shapes/index.d.ts.map +1 -0
- package/dist/es/shapes/index.js +15 -0
- package/dist/es/shapes/rectangle.d.ts +8 -0
- package/dist/es/shapes/rectangle.d.ts.map +1 -0
- package/dist/es/shapes/rectangle.js +40 -0
- package/dist/es/shapes/types.d.ts +44 -0
- package/dist/es/shapes/types.d.ts.map +1 -0
- package/dist/lib/compile/compile.cjs +91 -16
- package/dist/lib/compile/compile.d.ts +8 -1
- package/dist/lib/compile/compile.d.ts.map +1 -1
- package/dist/lib/compile/node.cjs +121 -207
- package/dist/lib/compile/node.d.ts +19 -10
- package/dist/lib/compile/node.d.ts.map +1 -1
- package/dist/lib/compile/scope.cjs +3 -1
- package/dist/lib/compile/scope.d.ts.map +1 -1
- package/dist/lib/index.cjs +6 -1
- package/dist/lib/index.d.ts +3 -1
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/ir/node.cjs +10 -3
- package/dist/lib/ir/node.d.ts +45 -12
- package/dist/lib/ir/node.d.ts.map +1 -1
- package/dist/lib/ir/path/path.cjs +1 -0
- package/dist/lib/ir/path/path.d.ts +3 -0
- package/dist/lib/ir/path/path.d.ts.map +1 -1
- package/dist/lib/ir/scope.cjs +5 -2
- package/dist/lib/ir/scope.d.ts +44 -22
- package/dist/lib/ir/scope.d.ts.map +1 -1
- package/dist/lib/shapes/_shared.cjs +11 -0
- package/dist/lib/shapes/_shared.d.ts +7 -0
- package/dist/lib/shapes/_shared.d.ts.map +1 -0
- package/dist/lib/shapes/circle.cjs +33 -0
- package/dist/lib/shapes/circle.d.ts +8 -0
- package/dist/lib/shapes/circle.d.ts.map +1 -0
- package/dist/lib/shapes/diamond.cjs +65 -0
- package/dist/lib/shapes/diamond.d.ts +8 -0
- package/dist/lib/shapes/diamond.d.ts.map +1 -0
- package/dist/lib/shapes/ellipse.cjs +45 -0
- package/dist/lib/shapes/ellipse.d.ts +8 -0
- package/dist/lib/shapes/ellipse.d.ts.map +1 -0
- package/dist/lib/shapes/index.cjs +14 -0
- package/dist/lib/shapes/index.d.ts +14 -0
- package/dist/lib/shapes/index.d.ts.map +1 -0
- package/dist/lib/shapes/rectangle.cjs +40 -0
- package/dist/lib/shapes/rectangle.d.ts +8 -0
- package/dist/lib/shapes/rectangle.d.ts.map +1 -0
- package/dist/lib/shapes/types.d.ts +44 -0
- package/dist/lib/shapes/types.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { circle as circle$1 } from "../geometry/circle.js";
|
|
2
|
+
import { asRectAnchor } from "./_shared.js";
|
|
3
|
+
import { ellipse } from "./ellipse.js";
|
|
4
|
+
//#region src/shapes/circle.ts
|
|
5
|
+
/** 外接框 Rect → Circle(radius = 半宽;circle 外接框宽=高) */
|
|
6
|
+
var toCircle = (r) => ({
|
|
7
|
+
x: r.x,
|
|
8
|
+
y: r.y,
|
|
9
|
+
radius: r.width / 2,
|
|
10
|
+
rotate: r.rotate
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* circle 注册项
|
|
14
|
+
* @description circumscribe = 内框对角线/2(两轴相等);几何走 circle 数学层;
|
|
15
|
+
* emit 复用 `ellipse.emit`(circle = rx=ry 的 ellipse),与旧 circle→`emitEllipseShape` 等价
|
|
16
|
+
*/
|
|
17
|
+
var circle = {
|
|
18
|
+
circumscribe: (hw, hh) => {
|
|
19
|
+
const r = Math.sqrt(hw * hw + hh * hh);
|
|
20
|
+
return {
|
|
21
|
+
halfWidth: r,
|
|
22
|
+
halfHeight: r
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
boundaryPoint: (r, toward) => circle$1.boundaryPoint(toCircle(r), toward),
|
|
26
|
+
anchor: (r, name) => {
|
|
27
|
+
const a = asRectAnchor(name);
|
|
28
|
+
return a ? circle$1.anchor(toCircle(r), a) : void 0;
|
|
29
|
+
},
|
|
30
|
+
emit: (r, style, round) => ellipse.emit(r, style, round)
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { circle };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ShapeDefinition } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* diamond 注册项
|
|
4
|
+
* @description circumscribe = 内框 ×2(内框 4 顶点落在菱形 4 边上);几何由外接框半轴派生;
|
|
5
|
+
* emit 在**轴对齐空间**取 4 顶点出 PathPrim(rotate 由外层 group 施加),与旧 `emitDiamondShape(unrotated(...))` 等价
|
|
6
|
+
*/
|
|
7
|
+
export declare const diamond: ShapeDefinition;
|
|
8
|
+
//# sourceMappingURL=diamond.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diamond.d.ts","sourceRoot":"","sources":["../../../src/shapes/diamond.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAW/C;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAAE,eA+BrB,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { asRectAnchor } from "./_shared.js";
|
|
2
|
+
import { diamond as diamond$1 } from "../geometry/diamond.js";
|
|
3
|
+
//#region src/shapes/diamond.ts
|
|
4
|
+
/** 外接框 Rect → Diamond(halfA/halfB = 半宽/半高;顶点在 ±halfA / ±halfB) */
|
|
5
|
+
var toDiamond = (r) => ({
|
|
6
|
+
x: r.x,
|
|
7
|
+
y: r.y,
|
|
8
|
+
halfA: r.width / 2,
|
|
9
|
+
halfB: r.height / 2,
|
|
10
|
+
rotate: r.rotate
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* diamond 注册项
|
|
14
|
+
* @description circumscribe = 内框 ×2(内框 4 顶点落在菱形 4 边上);几何由外接框半轴派生;
|
|
15
|
+
* emit 在**轴对齐空间**取 4 顶点出 PathPrim(rotate 由外层 group 施加),与旧 `emitDiamondShape(unrotated(...))` 等价
|
|
16
|
+
*/
|
|
17
|
+
var diamond = {
|
|
18
|
+
circumscribe: (hw, hh) => ({
|
|
19
|
+
halfWidth: hw * 2,
|
|
20
|
+
halfHeight: hh * 2
|
|
21
|
+
}),
|
|
22
|
+
boundaryPoint: (r, toward) => diamond$1.boundaryPoint(toDiamond(r), toward),
|
|
23
|
+
anchor: (r, name) => {
|
|
24
|
+
const a = asRectAnchor(name);
|
|
25
|
+
return a ? diamond$1.anchor(toDiamond(r), a) : void 0;
|
|
26
|
+
},
|
|
27
|
+
*emit(r, style, round) {
|
|
28
|
+
const d = toDiamond(r);
|
|
29
|
+
const e = diamond$1.anchor(d, "east");
|
|
30
|
+
const n = diamond$1.anchor(d, "north");
|
|
31
|
+
const w = diamond$1.anchor(d, "west");
|
|
32
|
+
const s = diamond$1.anchor(d, "south");
|
|
33
|
+
yield {
|
|
34
|
+
type: "path",
|
|
35
|
+
commands: [
|
|
36
|
+
{
|
|
37
|
+
kind: "move",
|
|
38
|
+
to: [round(e[0]), round(e[1])]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
kind: "line",
|
|
42
|
+
to: [round(n[0]), round(n[1])]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
kind: "line",
|
|
46
|
+
to: [round(w[0]), round(w[1])]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
kind: "line",
|
|
50
|
+
to: [round(s[0]), round(s[1])]
|
|
51
|
+
},
|
|
52
|
+
{ kind: "close" }
|
|
53
|
+
],
|
|
54
|
+
fill: style.fill ?? "transparent",
|
|
55
|
+
fillOpacity: style.fillOpacity,
|
|
56
|
+
stroke: style.stroke ?? "currentColor",
|
|
57
|
+
strokeOpacity: style.strokeOpacity,
|
|
58
|
+
strokeWidth: style.strokeWidth ?? 1,
|
|
59
|
+
dashPattern: style.dashPattern,
|
|
60
|
+
opacity: style.opacity
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
//#endregion
|
|
65
|
+
export { diamond };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ShapeDefinition } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* ellipse 注册项
|
|
4
|
+
* @description circumscribe = 内框 ×√2(内框 4 顶点落在椭圆周上);几何由外接框半轴派生;
|
|
5
|
+
* emit 出 EllipsePrim,与旧 `emitEllipseShape` 逐字段等价
|
|
6
|
+
*/
|
|
7
|
+
export declare const ellipse: ShapeDefinition;
|
|
8
|
+
//# sourceMappingURL=ellipse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ellipse.d.ts","sourceRoot":"","sources":["../../../src/shapes/ellipse.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAW/C;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAAE,eAuBrB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ellipse as ellipse$1 } from "../geometry/ellipse.js";
|
|
2
|
+
import { asRectAnchor } from "./_shared.js";
|
|
3
|
+
//#region src/shapes/ellipse.ts
|
|
4
|
+
/** 外接框 Rect → Ellipse(rx/ry = 半宽/半高) */
|
|
5
|
+
var toEllipse = (r) => ({
|
|
6
|
+
x: r.x,
|
|
7
|
+
y: r.y,
|
|
8
|
+
rx: r.width / 2,
|
|
9
|
+
ry: r.height / 2,
|
|
10
|
+
rotate: r.rotate
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* ellipse 注册项
|
|
14
|
+
* @description circumscribe = 内框 ×√2(内框 4 顶点落在椭圆周上);几何由外接框半轴派生;
|
|
15
|
+
* emit 出 EllipsePrim,与旧 `emitEllipseShape` 逐字段等价
|
|
16
|
+
*/
|
|
17
|
+
var ellipse = {
|
|
18
|
+
circumscribe: (hw, hh) => ({
|
|
19
|
+
halfWidth: hw * Math.SQRT2,
|
|
20
|
+
halfHeight: hh * Math.SQRT2
|
|
21
|
+
}),
|
|
22
|
+
boundaryPoint: (r, toward) => ellipse$1.boundaryPoint(toEllipse(r), toward),
|
|
23
|
+
anchor: (r, name) => {
|
|
24
|
+
const a = asRectAnchor(name);
|
|
25
|
+
return a ? ellipse$1.anchor(toEllipse(r), a) : void 0;
|
|
26
|
+
},
|
|
27
|
+
*emit(r, style, round) {
|
|
28
|
+
yield {
|
|
29
|
+
type: "ellipse",
|
|
30
|
+
cx: round(r.x),
|
|
31
|
+
cy: round(r.y),
|
|
32
|
+
rx: round(r.width / 2),
|
|
33
|
+
ry: round(r.height / 2),
|
|
34
|
+
fill: style.fill ?? "transparent",
|
|
35
|
+
fillOpacity: style.fillOpacity,
|
|
36
|
+
stroke: style.stroke ?? "currentColor",
|
|
37
|
+
strokeOpacity: style.strokeOpacity,
|
|
38
|
+
strokeWidth: style.strokeWidth ?? 1,
|
|
39
|
+
dashPattern: style.dashPattern,
|
|
40
|
+
opacity: style.opacity
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
export { ellipse };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BuiltinShapeName } from '../ir/node';
|
|
2
|
+
import { circle } from './circle';
|
|
3
|
+
import { diamond } from './diamond';
|
|
4
|
+
import { ellipse } from './ellipse';
|
|
5
|
+
import { rectangle } from './rectangle';
|
|
6
|
+
import { ShapeDefinition } from './types';
|
|
7
|
+
/** 内置 4 shape 注册项;与 `CompileOptions.shapes` 合并时被同名注入覆盖 */
|
|
8
|
+
export declare const BUILTIN_SHAPES: Record<BuiltinShapeName, ShapeDefinition>;
|
|
9
|
+
export { rectangle, circle, ellipse, diamond };
|
|
10
|
+
export type { ShapeDefinition, ShapeStyle } from './types';
|
|
11
|
+
export type { Rect } from '../geometry/rect';
|
|
12
|
+
export type { Position } from '../geometry/point';
|
|
13
|
+
export { worldToLocal, localToWorld } from '../geometry/_transform';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shapes/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,0DAA0D;AAC1D,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,gBAAgB,EAAE,eAAe,CAKpE,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC/C,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE3D,YAAY,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,YAAY,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import "../geometry/_transform.js";
|
|
2
|
+
import { ellipse } from "./ellipse.js";
|
|
3
|
+
import { circle } from "./circle.js";
|
|
4
|
+
import { diamond } from "./diamond.js";
|
|
5
|
+
import { rectangle } from "./rectangle.js";
|
|
6
|
+
//#region src/shapes/index.ts
|
|
7
|
+
/** 内置 4 shape 注册项;与 `CompileOptions.shapes` 合并时被同名注入覆盖 */
|
|
8
|
+
var BUILTIN_SHAPES = {
|
|
9
|
+
rectangle,
|
|
10
|
+
circle,
|
|
11
|
+
ellipse,
|
|
12
|
+
diamond
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { BUILTIN_SHAPES };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ShapeDefinition } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* rectangle 注册项
|
|
4
|
+
* @description circumscribe = identity(视觉边界 = 内框);boundaryPoint / anchor 直接走 rect 数学层;
|
|
5
|
+
* emit 出 RectPrim(圆角走 cornerRadius),与旧 `emitRectShape` 逐字段等价
|
|
6
|
+
*/
|
|
7
|
+
export declare const rectangle: ShapeDefinition;
|
|
8
|
+
//# sourceMappingURL=rectangle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rectangle.d.ts","sourceRoot":"","sources":["../../../src/shapes/rectangle.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,SAAS,EAAE,eA0BvB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { rect } from "../geometry/rect.js";
|
|
2
|
+
import { asRectAnchor } from "./_shared.js";
|
|
3
|
+
//#region src/shapes/rectangle.ts
|
|
4
|
+
/**
|
|
5
|
+
* rectangle 注册项
|
|
6
|
+
* @description circumscribe = identity(视觉边界 = 内框);boundaryPoint / anchor 直接走 rect 数学层;
|
|
7
|
+
* emit 出 RectPrim(圆角走 cornerRadius),与旧 `emitRectShape` 逐字段等价
|
|
8
|
+
*/
|
|
9
|
+
var rectangle = {
|
|
10
|
+
circumscribe: (hw, hh) => ({
|
|
11
|
+
halfWidth: hw,
|
|
12
|
+
halfHeight: hh
|
|
13
|
+
}),
|
|
14
|
+
boundaryPoint: (r, toward) => rect.boundaryPoint(r, toward),
|
|
15
|
+
anchor: (r, name) => {
|
|
16
|
+
const a = asRectAnchor(name);
|
|
17
|
+
return a ? rect.anchor(r, a) : void 0;
|
|
18
|
+
},
|
|
19
|
+
*emit(r, style, round) {
|
|
20
|
+
const halfW = r.width / 2;
|
|
21
|
+
const halfH = r.height / 2;
|
|
22
|
+
yield {
|
|
23
|
+
type: "rect",
|
|
24
|
+
x: round(r.x - halfW),
|
|
25
|
+
y: round(r.y - halfH),
|
|
26
|
+
width: round(r.width),
|
|
27
|
+
height: round(r.height),
|
|
28
|
+
fill: style.fill ?? "transparent",
|
|
29
|
+
fillOpacity: style.fillOpacity,
|
|
30
|
+
stroke: style.stroke ?? "currentColor",
|
|
31
|
+
strokeOpacity: style.strokeOpacity,
|
|
32
|
+
strokeWidth: style.strokeWidth ?? 1,
|
|
33
|
+
dashPattern: style.dashPattern,
|
|
34
|
+
cornerRadius: style.roundedCorners,
|
|
35
|
+
opacity: style.opacity
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
40
|
+
export { rectangle };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Position } from '../geometry/point';
|
|
2
|
+
import { Rect } from '../geometry/rect';
|
|
3
|
+
import { ScenePrimitive } from '../primitive';
|
|
4
|
+
/**
|
|
5
|
+
* emit 需要的视觉样式子集
|
|
6
|
+
* @description 从 NodeLayout 的样式字段收敛(不含几何 / 文本);独立 type,不耦合内部 NodeLayout。
|
|
7
|
+
* 字段名与 NodeLayout 样式字段一致(单一词汇表)。
|
|
8
|
+
*/
|
|
9
|
+
export type ShapeStyle = {
|
|
10
|
+
fill?: string;
|
|
11
|
+
fillOpacity?: number;
|
|
12
|
+
stroke?: string;
|
|
13
|
+
strokeOpacity?: number;
|
|
14
|
+
strokeWidth?: number;
|
|
15
|
+
dashPattern?: Array<number>;
|
|
16
|
+
roundedCorners?: number;
|
|
17
|
+
opacity?: number;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* 一个 shape 的可注册定义:外接 / 边界 / anchor / emit 四件事
|
|
21
|
+
* @description plain object(factory 友好:`createPolygonShape(6)` 这类普通函数返回它即可);含函数、
|
|
22
|
+
* **不进 IR**,走 `CompileOptions.shapes` 运行时注入。内置 4 shape 也是注册项(无内置特权)。
|
|
23
|
+
*
|
|
24
|
+
* 坐标语义两套,第三方最易写错:
|
|
25
|
+
* - `boundaryPoint` / `anchor` 收**带 `rotate` 的 Rect**——用 re-export 的 `worldToLocal` / `localToWorld` 写局部系几何。
|
|
26
|
+
* - `emit` 收**轴对齐 Rect(rotate=0)**——旋转由编译器在外层 `GroupPrim` 统一施加。
|
|
27
|
+
*/
|
|
28
|
+
export type ShapeDefinition = {
|
|
29
|
+
/**
|
|
30
|
+
* 外接:内容半轴(text + padding)→ 外接框半轴。
|
|
31
|
+
* @description rectangle: identity;circle: √(hw²+hh²) 两轴相等;ellipse: ×√2;diamond: ×2。
|
|
32
|
+
*/
|
|
33
|
+
circumscribe: (innerHalfWidth: number, innerHalfHeight: number) => {
|
|
34
|
+
halfWidth: number;
|
|
35
|
+
halfHeight: number;
|
|
36
|
+
};
|
|
37
|
+
/** 中心 → toward 射线 ∩ 边界(rect 带 rotate)。 */
|
|
38
|
+
boundaryPoint: (rect: Rect, toward: Position) => Position;
|
|
39
|
+
/** 命名 anchor 世界坐标;shape 不认识的名字返回 `undefined`(调用方据此抛清晰错误)。 */
|
|
40
|
+
anchor: (rect: Rect, name: string) => Position | undefined;
|
|
41
|
+
/** 视觉 primitive,**轴对齐空间**(rotate 由编译器外层 GroupPrim 统一施加)。 */
|
|
42
|
+
emit: (rect: Rect, style: ShapeStyle, round: (n: number) => number) => Iterable<ScenePrimitive>;
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/shapes/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;;OAGG;IACH,YAAY,EAAE,CACZ,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,KACpB;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,0CAA0C;IAC1C,aAAa,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,KAAK,QAAQ,CAAC;IAC1D,6DAA6D;IAC7D,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,CAAC;IAC3D,4DAA4D;IAC5D,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,KAAK,QAAQ,CAAC,cAAc,CAAC,CAAC;CACjG,CAAC"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
const require_rect = require("../geometry/rect.cjs");
|
|
2
|
+
const require_index = require("../shapes/index.cjs");
|
|
2
3
|
const require_name_stack = require("./name-stack.cjs");
|
|
3
4
|
const require_scope = require("./scope.cjs");
|
|
4
5
|
const require_position = require("./position.cjs");
|
|
5
6
|
const require_node = require("./node.cjs");
|
|
6
7
|
const require_text_metrics = require("./text-metrics.cjs");
|
|
7
|
-
const require_index = require("./path/index.cjs");
|
|
8
|
+
const require_index$1 = require("./path/index.cjs");
|
|
8
9
|
const require_precision = require("./precision.cjs");
|
|
9
10
|
const require_style = require("./style.cjs");
|
|
10
11
|
const require_layout = require("./layout.cjs");
|
|
@@ -16,7 +17,8 @@ const require_layout = require("./layout.cjs");
|
|
|
16
17
|
*/
|
|
17
18
|
var zeroSizeRectAt = (id, [cx, cy]) => ({
|
|
18
19
|
id,
|
|
19
|
-
|
|
20
|
+
shapeName: "rectangle",
|
|
21
|
+
shapeDef: require_index.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 = require_precision.makeRound(options.precision ?? 2);
|
|
85
99
|
const nodeDistance = options.nodeDistance;
|
|
86
100
|
const onWarn = options.onWarn ?? defaultWarnDispatcher;
|
|
101
|
+
const effectiveShapes = options.shapes ? {
|
|
102
|
+
...require_index.BUILTIN_SHAPES,
|
|
103
|
+
...options.shapes
|
|
104
|
+
} : require_index.BUILTIN_SHAPES;
|
|
105
|
+
if (options.shapes) {
|
|
106
|
+
for (const name of Object.keys(options.shapes)) if (Object.prototype.hasOwnProperty.call(require_index.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 require_name_stack.NameStack({ onDuplicate: (info) => onWarn(formatDuplicateWarning(info)) });
|
|
89
135
|
const allPoints = [];
|
|
90
136
|
/**
|
|
91
137
|
* 解析一批本层收集的 pending paths(lookup-only 阶段)
|
|
92
|
-
* @description path
|
|
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
|
*/
|
|
@@ -98,15 +144,23 @@ var compileToScene = (ir, options = {}) => {
|
|
|
98
144
|
nameStack.enterLookupPhase();
|
|
99
145
|
try {
|
|
100
146
|
for (const item of pending) {
|
|
101
|
-
const result = require_index.emitPathPrimitive(item.path, nameStack, round, measureText, {
|
|
147
|
+
const result = require_index$1.emitPathPrimitive(item.path, nameStack, round, measureText, {
|
|
102
148
|
onWarn,
|
|
103
149
|
irPath: item.irPath,
|
|
104
150
|
scopeChain: item.scopeChain
|
|
105
151
|
});
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
|
|
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 = require_node.layoutNode(require_style.resolveNodeStyle(child, styleStack), measureText, nameStack, nodeDistance, chain, require_style.resolveLabelDefault(styleStack));
|
|
184
|
+
const layout = require_node.layoutNode(require_style.resolveNodeStyle(child, styleStack), measureText, nameStack, nodeDistance, chain, require_style.resolveLabelDefault(styleStack), effectiveShapes);
|
|
131
185
|
const globalLayout = chain.length === 0 ? layout : require_scope.projectLayoutToGlobal(layout, chain);
|
|
132
186
|
if (child.id) nameStack.register(child.id, globalLayout, `${locatorPrefix}children[${i}].node.id`);
|
|
133
|
-
for (const prim of require_node.emitNodePrimitives(layout, round))
|
|
187
|
+
for (const prim of require_node.emitNodePrimitives(layout, round)) {
|
|
188
|
+
sink.push(prim);
|
|
189
|
+
if (child.zIndex !== void 0) zIndexOf.set(prim, child.zIndex);
|
|
190
|
+
}
|
|
134
191
|
allPoints.push(require_rect.rect.anchor(globalLayout.rect, "north-west"), require_rect.rect.anchor(globalLayout.rect, "north-east"), require_rect.rect.anchor(globalLayout.rect, "south-west"), require_rect.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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
247
|
+
if (child.zIndex !== void 0) zIndexOf.set(group, child.zIndex);
|
|
248
|
+
} else {
|
|
249
|
+
const pending = {
|
|
250
|
+
path: require_style.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: require_layout.computeLayout(allPoints, layoutPadding, round)
|
|
203
278
|
};
|
|
204
279
|
};
|
|
@@ -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;
|
|
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"}
|