@franzenzenhofer/asanakit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -0
  3. package/dist/anatomy/muscles.d.ts +55 -0
  4. package/dist/anatomy/muscles.d.ts.map +1 -0
  5. package/dist/anatomy/muscles.js +79 -0
  6. package/dist/anatomy/muscles.js.map +1 -0
  7. package/dist/anatomy/validate.d.ts +11 -0
  8. package/dist/anatomy/validate.d.ts.map +1 -0
  9. package/dist/anatomy/validate.js +94 -0
  10. package/dist/anatomy/validate.js.map +1 -0
  11. package/dist/cli/commands/export.d.ts +3 -0
  12. package/dist/cli/commands/export.d.ts.map +1 -0
  13. package/dist/cli/commands/export.js +45 -0
  14. package/dist/cli/commands/export.js.map +1 -0
  15. package/dist/cli/commands/info.d.ts +3 -0
  16. package/dist/cli/commands/info.d.ts.map +1 -0
  17. package/dist/cli/commands/info.js +101 -0
  18. package/dist/cli/commands/info.js.map +1 -0
  19. package/dist/cli/commands/render.d.ts +3 -0
  20. package/dist/cli/commands/render.d.ts.map +1 -0
  21. package/dist/cli/commands/render.js +103 -0
  22. package/dist/cli/commands/render.js.map +1 -0
  23. package/dist/cli/index.d.ts +3 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +31 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/cli/resolve.d.ts +12 -0
  28. package/dist/cli/resolve.d.ts.map +1 -0
  29. package/dist/cli/resolve.js +46 -0
  30. package/dist/cli/resolve.js.map +1 -0
  31. package/dist/core/angles.d.ts +12 -0
  32. package/dist/core/angles.d.ts.map +1 -0
  33. package/dist/core/angles.js +27 -0
  34. package/dist/core/angles.js.map +1 -0
  35. package/dist/core/rig.d.ts +8 -0
  36. package/dist/core/rig.d.ts.map +1 -0
  37. package/dist/core/rig.js +97 -0
  38. package/dist/core/rig.js.map +1 -0
  39. package/dist/core/skeleton.d.ts +17 -0
  40. package/dist/core/skeleton.d.ts.map +1 -0
  41. package/dist/core/skeleton.js +144 -0
  42. package/dist/core/skeleton.js.map +1 -0
  43. package/dist/core/types.d.ts +105 -0
  44. package/dist/core/types.d.ts.map +1 -0
  45. package/dist/core/types.js +47 -0
  46. package/dist/core/types.js.map +1 -0
  47. package/dist/core/vec2.d.ts +19 -0
  48. package/dist/core/vec2.d.ts.map +1 -0
  49. package/dist/core/vec2.js +41 -0
  50. package/dist/core/vec2.js.map +1 -0
  51. package/dist/index.d.ts +11 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +11 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/library/index.d.ts +27 -0
  56. package/dist/library/index.d.ts.map +1 -0
  57. package/dist/library/index.js +75 -0
  58. package/dist/library/index.js.map +1 -0
  59. package/dist/model/index.d.ts +4 -0
  60. package/dist/model/index.d.ts.map +1 -0
  61. package/dist/model/index.js +4 -0
  62. package/dist/model/index.js.map +1 -0
  63. package/dist/model/parse.d.ts +12 -0
  64. package/dist/model/parse.d.ts.map +1 -0
  65. package/dist/model/parse.js +43 -0
  66. package/dist/model/parse.js.map +1 -0
  67. package/dist/model/pose.d.ts +11 -0
  68. package/dist/model/pose.d.ts.map +1 -0
  69. package/dist/model/pose.js +26 -0
  70. package/dist/model/pose.js.map +1 -0
  71. package/dist/model/schema.d.ts +1122 -0
  72. package/dist/model/schema.d.ts.map +1 -0
  73. package/dist/model/schema.js +178 -0
  74. package/dist/model/schema.js.map +1 -0
  75. package/dist/render/anatomy.d.ts +10 -0
  76. package/dist/render/anatomy.d.ts.map +1 -0
  77. package/dist/render/anatomy.js +77 -0
  78. package/dist/render/anatomy.js.map +1 -0
  79. package/dist/render/annotations.d.ts +9 -0
  80. package/dist/render/annotations.d.ts.map +1 -0
  81. package/dist/render/annotations.js +185 -0
  82. package/dist/render/annotations.js.map +1 -0
  83. package/dist/render/context.d.ts +16 -0
  84. package/dist/render/context.d.ts.map +1 -0
  85. package/dist/render/context.js +2 -0
  86. package/dist/render/context.js.map +1 -0
  87. package/dist/render/figure.d.ts +8 -0
  88. package/dist/render/figure.d.ts.map +1 -0
  89. package/dist/render/figure.js +138 -0
  90. package/dist/render/figure.js.map +1 -0
  91. package/dist/render/index.d.ts +7 -0
  92. package/dist/render/index.d.ts.map +1 -0
  93. package/dist/render/index.js +7 -0
  94. package/dist/render/index.js.map +1 -0
  95. package/dist/render/project.d.ts +18 -0
  96. package/dist/render/project.d.ts.map +1 -0
  97. package/dist/render/project.js +35 -0
  98. package/dist/render/project.js.map +1 -0
  99. package/dist/render/props.d.ts +9 -0
  100. package/dist/render/props.d.ts.map +1 -0
  101. package/dist/render/props.js +178 -0
  102. package/dist/render/props.js.map +1 -0
  103. package/dist/render/raster.d.ts +19 -0
  104. package/dist/render/raster.d.ts.map +1 -0
  105. package/dist/render/raster.js +39 -0
  106. package/dist/render/raster.js.map +1 -0
  107. package/dist/render/scene.d.ts +26 -0
  108. package/dist/render/scene.d.ts.map +1 -0
  109. package/dist/render/scene.js +144 -0
  110. package/dist/render/scene.js.map +1 -0
  111. package/dist/render/sheet.d.ts +20 -0
  112. package/dist/render/sheet.d.ts.map +1 -0
  113. package/dist/render/sheet.js +74 -0
  114. package/dist/render/sheet.js.map +1 -0
  115. package/dist/render/styles.d.ts +77 -0
  116. package/dist/render/styles.d.ts.map +1 -0
  117. package/dist/render/styles.js +122 -0
  118. package/dist/render/styles.js.map +1 -0
  119. package/dist/render/svg.d.ts +19 -0
  120. package/dist/render/svg.d.ts.map +1 -0
  121. package/dist/render/svg.js +40 -0
  122. package/dist/render/svg.js.map +1 -0
  123. package/dist/standards/keypoints.d.ts +31 -0
  124. package/dist/standards/keypoints.d.ts.map +1 -0
  125. package/dist/standards/keypoints.js +118 -0
  126. package/dist/standards/keypoints.js.map +1 -0
  127. package/docs/AUTHORING.md +144 -0
  128. package/package.json +94 -0
  129. package/poses/surf/bottom-turn.pose.yaml +47 -0
  130. package/poses/surf/cutback.pose.yaml +47 -0
  131. package/poses/surf/duck-dive.pose.yaml +47 -0
  132. package/poses/surf/noseride.pose.yaml +48 -0
  133. package/poses/surf/paddling.pose.yaml +48 -0
  134. package/poses/surf/pop-up.pose.yaml +47 -0
  135. package/poses/surf/takeoff.pose.yaml +47 -0
  136. package/poses/surf/tube-stance.pose.yaml +47 -0
  137. package/poses/yoga/ashtanga/adho-mukha-svanasana.pose.yaml +42 -0
  138. package/poses/yoga/ashtanga/ardha-uttanasana.pose.yaml +42 -0
  139. package/poses/yoga/ashtanga/baddha-konasana.pose.yaml +42 -0
  140. package/poses/yoga/ashtanga/balasana.pose.yaml +43 -0
  141. package/poses/yoga/ashtanga/chaturanga-dandasana.pose.yaml +41 -0
  142. package/poses/yoga/ashtanga/dandasana.pose.yaml +42 -0
  143. package/poses/yoga/ashtanga/halasana.pose.yaml +43 -0
  144. package/poses/yoga/ashtanga/janu-sirsasana-a.pose.yaml +42 -0
  145. package/poses/yoga/ashtanga/karnapidasana.pose.yaml +43 -0
  146. package/poses/yoga/ashtanga/marichyasana-a.pose.yaml +42 -0
  147. package/poses/yoga/ashtanga/marichyasana-c.pose.yaml +42 -0
  148. package/poses/yoga/ashtanga/matsyasana.pose.yaml +43 -0
  149. package/poses/yoga/ashtanga/navasana.pose.yaml +42 -0
  150. package/poses/yoga/ashtanga/padahastasana.pose.yaml +42 -0
  151. package/poses/yoga/ashtanga/padangusthasana.pose.yaml +42 -0
  152. package/poses/yoga/ashtanga/padmasana.pose.yaml +43 -0
  153. package/poses/yoga/ashtanga/parsvottanasana.pose.yaml +42 -0
  154. package/poses/yoga/ashtanga/paschimottanasana.pose.yaml +42 -0
  155. package/poses/yoga/ashtanga/prasarita-padottanasana-a.pose.yaml +46 -0
  156. package/poses/yoga/ashtanga/prasarita-padottanasana-c.pose.yaml +46 -0
  157. package/poses/yoga/ashtanga/primary.seq.yaml +74 -0
  158. package/poses/yoga/ashtanga/purvottanasana.pose.yaml +42 -0
  159. package/poses/yoga/ashtanga/salamba-sarvangasana.pose.yaml +43 -0
  160. package/poses/yoga/ashtanga/samasthiti.pose.yaml +29 -0
  161. package/poses/yoga/ashtanga/savasana.pose.yaml +43 -0
  162. package/poses/yoga/ashtanga/setu-bandhasana.pose.yaml +42 -0
  163. package/poses/yoga/ashtanga/sirsasana.pose.yaml +43 -0
  164. package/poses/yoga/ashtanga/supta-padangusthasana.pose.yaml +42 -0
  165. package/poses/yoga/ashtanga/upavistha-konasana.pose.yaml +42 -0
  166. package/poses/yoga/ashtanga/urdhva-dhanurasana.pose.yaml +43 -0
  167. package/poses/yoga/ashtanga/urdhva-hastasana.pose.yaml +42 -0
  168. package/poses/yoga/ashtanga/urdhva-mukha-svanasana.pose.yaml +42 -0
  169. package/poses/yoga/ashtanga/utkatasana.pose.yaml +42 -0
  170. package/poses/yoga/ashtanga/uttanasana.pose.yaml +42 -0
  171. package/poses/yoga/ashtanga/utthita-parsvakonasana.pose.yaml +44 -0
  172. package/poses/yoga/ashtanga/utthita-trikonasana.pose.yaml +44 -0
  173. package/poses/yoga/ashtanga/virabhadrasana-a.pose.yaml +42 -0
  174. package/poses/yoga/ashtanga/virabhadrasana-b.pose.yaml +42 -0
@@ -0,0 +1,138 @@
1
+ import { curveCatmullRomClosed, line } from 'd3-shape';
2
+ import { el, group } from './svg.js';
3
+ const LIMB_BONES = [
4
+ 'upperArmL',
5
+ 'forearmL',
6
+ 'handL',
7
+ 'thighL',
8
+ 'shinL',
9
+ 'footL',
10
+ 'upperArmR',
11
+ 'forearmR',
12
+ 'handR',
13
+ 'thighR',
14
+ 'shinR',
15
+ 'footR',
16
+ ];
17
+ const TORSO_BONES = ['pelvis', 'spine', 'neck', 'clavicleL', 'clavicleR', 'hipL', 'hipR'];
18
+ const JOINT_LANDMARKS = [
19
+ 'shoulderL',
20
+ 'elbowL',
21
+ 'wristL',
22
+ 'shoulderR',
23
+ 'elbowR',
24
+ 'wristR',
25
+ 'hipJointL',
26
+ 'kneeL',
27
+ 'ankleL',
28
+ 'hipJointR',
29
+ 'kneeR',
30
+ 'ankleR',
31
+ 'chest',
32
+ 'hipCenter',
33
+ ];
34
+ /** In a profile view the far-side limbs sit behind the body and read as lighter. */
35
+ const FAR_SIDE_VIEWS = ['side', 'three-quarter'];
36
+ const isFar = (bone, view) => FAR_SIDE_VIEWS.includes(view) && bone.side === 'right';
37
+ const boneLine = (bone, ctx) => {
38
+ const { proj, style } = ctx;
39
+ const view = ctx.skeleton.view;
40
+ const [x1, y1] = proj.p(bone.start);
41
+ const [x2, y2] = proj.p(bone.end);
42
+ return el('line', {
43
+ 'data-bone': bone.id,
44
+ x1,
45
+ y1,
46
+ x2,
47
+ y2,
48
+ stroke: style.figure.stroke,
49
+ 'stroke-width': style.figure.strokeWidth * proj.s,
50
+ 'stroke-linecap': style.figure.lineCap,
51
+ opacity: isFar(bone, view) ? style.figure.farOpacity : undefined,
52
+ });
53
+ };
54
+ const closedPath = line()
55
+ .x((p) => p[0])
56
+ .y((p) => p[1])
57
+ .curve(curveCatmullRomClosed);
58
+ /** A filled trunk between the shoulders and the hips, for the heavier styles. */
59
+ const torsoShape = ({ skeleton, proj, style }) => {
60
+ if (style.figure.torsoWidth <= 0)
61
+ return null;
62
+ const l = skeleton.landmarks;
63
+ const outline = [l.shoulderL, l.chest, l.shoulderR, l.hipJointR, l.hipCenter, l.hipJointL].map((p) => proj.p(p));
64
+ const d = closedPath(outline);
65
+ if (d === null)
66
+ return null;
67
+ return el('path', {
68
+ 'data-part': 'torso',
69
+ d,
70
+ fill: style.figure.fill === 'none' ? style.figure.stroke : style.figure.fill,
71
+ stroke: style.figure.stroke,
72
+ 'stroke-width': style.figure.torsoWidth * proj.s,
73
+ 'stroke-linejoin': 'round',
74
+ });
75
+ };
76
+ const head = ({ skeleton, proj, style }) => {
77
+ if (style.head.shape === 'none')
78
+ return null;
79
+ const bone = skeleton.bones.head;
80
+ const [cx, cy] = proj.p(skeleton.landmarks.headCenter);
81
+ const rx = style.head.rx * proj.s * skeleton.scale;
82
+ const ry = (style.head.shape === 'circle' ? style.head.rx : style.head.ry) * proj.s * skeleton.scale;
83
+ // SVG rotates clockwise because y points down, so the sign flips against the world angle.
84
+ const rotation = 90 - bone.worldAngle;
85
+ return el('ellipse', {
86
+ 'data-part': 'head',
87
+ cx,
88
+ cy,
89
+ rx,
90
+ ry,
91
+ transform: rotation === 0 ? undefined : `rotate(${rotation.toFixed(3)} ${cx.toFixed(3)} ${cy.toFixed(3)})`,
92
+ fill: style.head.fill,
93
+ stroke: style.head.stroke,
94
+ 'stroke-width': style.head.strokeWidth * proj.s,
95
+ });
96
+ };
97
+ const joints = ({ skeleton, proj, style }) => {
98
+ if (style.figure.joints !== 'dots')
99
+ return null;
100
+ return group({ 'data-part': 'joints' }, JOINT_LANDMARKS.map((id) => {
101
+ const [cx, cy] = proj.p(skeleton.landmarks[id]);
102
+ return el('circle', {
103
+ 'data-joint': id,
104
+ cx,
105
+ cy,
106
+ r: style.figure.jointRadius * proj.s * skeleton.scale,
107
+ fill: style.figure.stroke,
108
+ });
109
+ }));
110
+ };
111
+ const bonesOf = (skeleton, ids, side) => ids
112
+ .map((id) => skeleton.bones[id])
113
+ .filter((bone) => {
114
+ if (side === 'all')
115
+ return true;
116
+ const far = isFar(bone, skeleton.view);
117
+ return side === 'far' ? far : !far;
118
+ });
119
+ /**
120
+ * Draw the figure back-to-front: far limbs, trunk, head, near limbs. That single
121
+ * ordering is what makes a profile pose read as a body rather than a tangle.
122
+ */
123
+ export const renderFigure = (ctx) => {
124
+ const { skeleton } = ctx;
125
+ const draw = (bones) => bones.map((b) => boneLine(b, ctx));
126
+ const optional = (node) => (node === null ? [] : [node]);
127
+ return group({ 'data-layer': 'figure' }, [
128
+ group({ 'data-layer': 'limbs-far' }, draw(bonesOf(skeleton, LIMB_BONES, 'far'))),
129
+ group({ 'data-layer': 'torso' }, [
130
+ ...optional(torsoShape(ctx)),
131
+ ...draw(bonesOf(skeleton, TORSO_BONES, 'all')),
132
+ ]),
133
+ ...optional(head(ctx)),
134
+ group({ 'data-layer': 'limbs-near' }, draw(bonesOf(skeleton, LIMB_BONES, 'near'))),
135
+ ...optional(joints(ctx)),
136
+ ]);
137
+ };
138
+ //# sourceMappingURL=figure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figure.js","sourceRoot":"","sources":["../../src/render/figure.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export * from './scene.js';
2
+ export * from './styles.js';
3
+ export * from './svg.js';
4
+ export * from './project.js';
5
+ export * from './raster.js';
6
+ export * from './sheet.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,7 @@
1
+ export * from './scene.js';
2
+ export * from './styles.js';
3
+ export * from './svg.js';
4
+ export * from './project.js';
5
+ export * from './raster.js';
6
+ export * from './sheet.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/render/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { Bounds } from '../core/types.js';
2
+ import type { Vec2 } from '../core/vec2.js';
3
+ /**
4
+ * Maps math coordinates (y up, origin at the figure's feet) into SVG user units
5
+ * (y down, origin top-left). This is the only place the y-axis flips.
6
+ */
7
+ export interface Projection {
8
+ /** Project a point. */
9
+ readonly p: (v: Vec2) => [number, number];
10
+ /** SVG units per stature unit - use it to scale every stroke width and radius. */
11
+ readonly s: number;
12
+ }
13
+ export declare const unionBounds: (a: Bounds, b: Bounds) => Bounds;
14
+ export declare const boundsOfPoints: (points: readonly Vec2[]) => Bounds;
15
+ export declare const padBounds: (b: Bounds, pad: number) => Bounds;
16
+ /** Fit `content` inside a width x height canvas, preserving aspect ratio and centring. */
17
+ export declare const fitProjection: (content: Bounds, width: number, height: number) => Projection;
18
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/render/project.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,uBAAuB;IACvB,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,kFAAkF;IAClF,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,eAAO,MAAM,WAAW,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAKjD,CAAC;AAEH,eAAO,MAAM,cAAc,GAAI,QAAQ,SAAS,IAAI,EAAE,KAAG,MAKvD,CAAC;AAEH,eAAO,MAAM,SAAS,GAAI,GAAG,MAAM,EAAE,KAAK,MAAM,KAAG,MAKjD,CAAC;AAEH,0FAA0F;AAC1F,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,EAAE,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,UAc9E,CAAC"}
@@ -0,0 +1,35 @@
1
+ const MIN_EXTENT = 1e-6;
2
+ export const unionBounds = (a, b) => ({
3
+ minX: Math.min(a.minX, b.minX),
4
+ minY: Math.min(a.minY, b.minY),
5
+ maxX: Math.max(a.maxX, b.maxX),
6
+ maxY: Math.max(a.maxY, b.maxY),
7
+ });
8
+ export const boundsOfPoints = (points) => ({
9
+ minX: Math.min(...points.map((p) => p[0])),
10
+ maxX: Math.max(...points.map((p) => p[0])),
11
+ minY: Math.min(...points.map((p) => p[1])),
12
+ maxY: Math.max(...points.map((p) => p[1])),
13
+ });
14
+ export const padBounds = (b, pad) => ({
15
+ minX: b.minX - pad,
16
+ minY: b.minY - pad,
17
+ maxX: b.maxX + pad,
18
+ maxY: b.maxY + pad,
19
+ });
20
+ /** Fit `content` inside a width x height canvas, preserving aspect ratio and centring. */
21
+ export const fitProjection = (content, width, height) => {
22
+ const bw = Math.max(content.maxX - content.minX, MIN_EXTENT);
23
+ const bh = Math.max(content.maxY - content.minY, MIN_EXTENT);
24
+ const s = Math.min(width / bw, height / bh);
25
+ const offsetX = (width - bw * s) / 2;
26
+ const offsetY = (height - bh * s) / 2;
27
+ return {
28
+ s,
29
+ p: (v) => [
30
+ offsetX + (v[0] - content.minX) * s,
31
+ height - offsetY - (v[1] - content.minY) * s,
32
+ ],
33
+ };
34
+ };
35
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../../src/render/project.ts"],"names":[],"mappings":"AAcA,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE,CAAC,CAAC;IAC5D,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IAC9B,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IAC9B,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IAC9B,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;CAC/B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAuB,EAAU,EAAE,CAAC,CAAC;IAClE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC3C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAS,EAAE,GAAW,EAAU,EAAE,CAAC,CAAC;IAC5D,IAAI,EAAE,CAAC,CAAC,IAAI,GAAG,GAAG;IAClB,IAAI,EAAE,CAAC,CAAC,IAAI,GAAG,GAAG;IAClB,IAAI,EAAE,CAAC,CAAC,IAAI,GAAG,GAAG;IAClB,IAAI,EAAE,CAAC,CAAC,IAAI,GAAG,GAAG;CACnB,CAAC,CAAC;AAEH,0FAA0F;AAC1F,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAe,EAAE,KAAa,EAAE,MAAc,EAAc,EAAE;IAC1F,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC7D,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC7D,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,CAAC,KAAK,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,CAAC,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAEtC,OAAO;QACL,CAAC;QACD,CAAC,EAAE,CAAC,CAAO,EAAoB,EAAE,CAAC;YAChC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;YACnC,MAAM,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;SAC7C;KACF,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Bounds, Skeleton } from '../core/types.js';
2
+ import { type Vec2 } from '../core/vec2.js';
3
+ import type { Anchor, Prop } from '../model/schema.js';
4
+ import type { RenderContext } from './context.js';
5
+ import { type SvgNode } from './svg.js';
6
+ export declare const resolveAnchor: (anchor: Anchor, skeleton: Skeleton) => Vec2;
7
+ export declare const propsBounds: (props: readonly Prop[], skeleton: Skeleton) => Bounds | null;
8
+ export declare const renderProps: (ctx: RenderContext, props: readonly Prop[]) => SvgNode | null;
9
+ //# sourceMappingURL=props.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../src/render/props.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAc,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAA6C,KAAK,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,UAAU,CAAC;AAExD,eAAO,MAAM,aAAa,GAAI,QAAQ,MAAM,EAAE,UAAU,QAAQ,KAAG,IACe,CAAC;AA+FnF,eAAO,MAAM,WAAW,GAAI,OAAO,SAAS,IAAI,EAAE,EAAE,UAAU,QAAQ,KAAG,MAAM,GAAG,IAGjF,CAAC;AAkFF,eAAO,MAAM,WAAW,GAAI,KAAK,aAAa,EAAE,OAAO,SAAS,IAAI,EAAE,KAAG,OAAO,GAAG,IACiB,CAAC"}
@@ -0,0 +1,178 @@
1
+ import { curveBasis, line } from 'd3-shape';
2
+ import { path } from 'd3-path';
3
+ import { add, fromPolar, rotate, scale as scaleVec } from '../core/vec2.js';
4
+ import { boundsOfPoints } from './project.js';
5
+ import { el, group, num } from './svg.js';
6
+ export const resolveAnchor = (anchor, skeleton) => typeof anchor === 'string' ? skeleton.landmarks[anchor] : [anchor[0], anchor[1]];
7
+ const centreX = (skeleton) => (skeleton.bounds.minX + skeleton.bounds.maxX) / 2;
8
+ const centroid = (ids, skeleton) => {
9
+ if (ids.length === 0)
10
+ return [centreX(skeleton), skeleton.bounds.minY];
11
+ const pts = ids.map((id) => skeleton.landmarks[id]);
12
+ return [
13
+ pts.reduce((sum, p) => sum + p[0], 0) / pts.length,
14
+ pts.reduce((sum, p) => sum + p[1], 0) / pts.length,
15
+ ];
16
+ };
17
+ const smooth = line()
18
+ .x((p) => p[0])
19
+ .y((p) => p[1])
20
+ .curve(curveBasis);
21
+ const WAVE_STEPS = 48;
22
+ const BOARD_WIDTH_RATIO = 0.19;
23
+ const wavePoints = (prop, cx) => {
24
+ const dir = prop.facing === 'right' ? 1 : -1;
25
+ return Array.from({ length: WAVE_STEPS + 1 }, (_, i) => {
26
+ const t = i / WAVE_STEPS;
27
+ const px = cx + (t - 0.5) * prop.length;
28
+ // A breaking wave: a swell that steepens into a crest on the facing side.
29
+ const swell = Math.sin(t * Math.PI * 2 - Math.PI / 2);
30
+ const steepen = prop.breaking ? Math.pow(t, 1.6) : 1;
31
+ return [px * 1, prop.y + prop.amplitude * swell * steepen * dir * dir];
32
+ });
33
+ };
34
+ const boardOutline = (centre, length, rotationDeg) => {
35
+ const half = length / 2;
36
+ const w = length * BOARD_WIDTH_RATIO;
37
+ const local = [
38
+ [half, 0],
39
+ [half * 0.45, w / 2],
40
+ [-half * 0.55, w / 2],
41
+ [-half, w * 0.16],
42
+ [-half, -w * 0.16],
43
+ [-half * 0.55, -w / 2],
44
+ [half * 0.45, -w / 2],
45
+ ];
46
+ return local.map((p) => add(centre, rotate(p, rotationDeg)));
47
+ };
48
+ const polygon = (points, proj) => {
49
+ const p = path();
50
+ points.forEach((pt, i) => {
51
+ const [px, py] = proj.p(pt);
52
+ if (i === 0)
53
+ p.moveTo(num(px), num(py));
54
+ else
55
+ p.lineTo(num(px), num(py));
56
+ });
57
+ p.closePath();
58
+ return p.toString();
59
+ };
60
+ const propPoints = (prop, skeleton) => {
61
+ const cx = centreX(skeleton);
62
+ switch (prop.type) {
63
+ case 'ground':
64
+ return [
65
+ [cx - prop.width / 2, prop.y],
66
+ [cx + prop.width / 2, prop.y],
67
+ ];
68
+ case 'mat':
69
+ return [
70
+ [cx - prop.width / 2, prop.y - prop.thickness],
71
+ [cx + prop.width / 2, prop.y + prop.thickness],
72
+ ];
73
+ case 'block': {
74
+ const at = resolveAnchor(prop.at, skeleton);
75
+ return [
76
+ [at[0] - prop.width, at[1] - prop.height],
77
+ [at[0] + prop.width, at[1] + prop.height],
78
+ ];
79
+ }
80
+ case 'strap':
81
+ return [resolveAnchor(prop.from, skeleton), resolveAnchor(prop.to, skeleton)];
82
+ case 'wall':
83
+ return [
84
+ [prop.x, skeleton.bounds.minY],
85
+ [prop.x, skeleton.bounds.maxY],
86
+ ];
87
+ case 'surfboard': {
88
+ const centre = prop.at ?? add(centroid(prop.under, skeleton), prop.offset);
89
+ return boardOutline(centre, prop.length, prop.rotation);
90
+ }
91
+ case 'wave':
92
+ return wavePoints(prop, cx);
93
+ }
94
+ };
95
+ export const propsBounds = (props, skeleton) => {
96
+ const pts = props.flatMap((prop) => propPoints(prop, skeleton));
97
+ return pts.length === 0 ? null : boundsOfPoints(pts);
98
+ };
99
+ const renderProp = (prop, ctx) => {
100
+ const { skeleton, proj, style } = ctx;
101
+ const cx = centreX(skeleton);
102
+ const attrs = { stroke: style.props.stroke, 'stroke-width': style.props.strokeWidth * proj.s };
103
+ switch (prop.type) {
104
+ case 'ground': {
105
+ const [x1, y1] = proj.p([cx - prop.width / 2, prop.y]);
106
+ const [x2, y2] = proj.p([cx + prop.width / 2, prop.y]);
107
+ return el('line', { 'data-prop': 'ground', x1, y1, x2, y2, ...attrs, 'stroke-linecap': 'round' });
108
+ }
109
+ case 'mat': {
110
+ const [x1, y1] = proj.p([cx - prop.width / 2, prop.y + prop.thickness]);
111
+ const [x2] = proj.p([cx + prop.width / 2, prop.y]);
112
+ return el('rect', {
113
+ 'data-prop': 'mat',
114
+ x: x1,
115
+ y: y1,
116
+ width: x2 - x1,
117
+ height: prop.thickness * 2 * proj.s,
118
+ rx: prop.thickness * proj.s,
119
+ fill: style.props.fill,
120
+ ...attrs,
121
+ });
122
+ }
123
+ case 'block': {
124
+ const at = resolveAnchor(prop.at, skeleton);
125
+ const local = [
126
+ [-prop.width / 2, -prop.height / 2],
127
+ [prop.width / 2, -prop.height / 2],
128
+ [prop.width / 2, prop.height / 2],
129
+ [-prop.width / 2, prop.height / 2],
130
+ ];
131
+ const corners = local.map((p) => add(at, rotate(p, prop.rotation)));
132
+ return el('path', { 'data-prop': 'block', d: polygon(corners, proj), fill: style.props.fill, ...attrs });
133
+ }
134
+ case 'strap': {
135
+ const a = resolveAnchor(prop.from, skeleton);
136
+ const b = resolveAnchor(prop.to, skeleton);
137
+ const mid = add(scaleVec(add(a, b), 0.5), [0, -Math.abs(prop.sag)]);
138
+ const [ax, ay] = proj.p(a);
139
+ const [mx, my] = proj.p(mid);
140
+ const [bx, by] = proj.p(b);
141
+ const p = path();
142
+ p.moveTo(num(ax), num(ay));
143
+ p.quadraticCurveTo(num(mx), num(my), num(bx), num(by));
144
+ return el('path', { 'data-prop': 'strap', d: p.toString(), fill: 'none', ...attrs });
145
+ }
146
+ case 'wall': {
147
+ const [x1, y1] = proj.p([prop.x, skeleton.bounds.minY]);
148
+ const [x2, y2] = proj.p([prop.x, skeleton.bounds.maxY]);
149
+ return el('line', { 'data-prop': 'wall', x1, y1, x2, y2, ...attrs });
150
+ }
151
+ case 'surfboard': {
152
+ const centre = prop.at ?? add(centroid(prop.under, skeleton), prop.offset);
153
+ const outline = boardOutline(centre, prop.length, prop.rotation);
154
+ const stringerEnd = add(centre, fromPolar(prop.rotation, prop.length / 2));
155
+ const stringerStart = add(centre, fromPolar(prop.rotation + 180, prop.length / 2));
156
+ const [sx1, sy1] = proj.p(stringerStart);
157
+ const [sx2, sy2] = proj.p(stringerEnd);
158
+ return group({ 'data-prop': 'surfboard' }, [
159
+ el('path', { d: polygon(outline, proj), fill: style.props.fill, ...attrs, 'stroke-linejoin': 'round' }),
160
+ el('line', { 'data-part': 'stringer', x1: sx1, y1: sy1, x2: sx2, y2: sy2, ...attrs, opacity: 0.5 }),
161
+ ]);
162
+ }
163
+ case 'wave': {
164
+ const pts = wavePoints(prop, cx).map((p) => proj.p(p));
165
+ const d = smooth(pts);
166
+ return el('path', {
167
+ 'data-prop': 'wave',
168
+ d: d ?? '',
169
+ fill: 'none',
170
+ ...attrs,
171
+ 'stroke-width': style.props.strokeWidth * 1.5 * proj.s,
172
+ 'stroke-linecap': 'round',
173
+ });
174
+ }
175
+ }
176
+ };
177
+ export const renderProps = (ctx, props) => props.length === 0 ? null : group({ 'data-layer': 'props' }, props.map((p) => renderProp(p, ctx)));
178
+ //# sourceMappingURL=props.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"props.js","sourceRoot":"","sources":["../../src/render/props.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface PngOptions {
2
+ /** Output width in pixels; height follows the SVG aspect ratio. */
3
+ readonly width?: number;
4
+ /** Uniform scale factor, used when no width is given. */
5
+ readonly scale?: number;
6
+ readonly background?: string;
7
+ }
8
+ /**
9
+ * Rasterise with resvg: a pure-Rust SVG renderer with no system libraries and
10
+ * no browser, so a PNG built on a laptop is byte-identical to one built in CI.
11
+ */
12
+ export declare const renderPng: (svg: string, options?: PngOptions) => Buffer;
13
+ /**
14
+ * Shrink the SVG without losing the `data-*` hooks: those attributes are the
15
+ * contract that lets another program (or a model) find a bone, a muscle or an
16
+ * annotation in the output.
17
+ */
18
+ export declare const optimizeSvg: (svg: string) => string;
19
+ //# sourceMappingURL=raster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raster.d.ts","sourceRoot":"","sources":["../../src/render/raster.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,MAAM,EAAE,UAAS,UAAe,KAAG,MAajE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,MAgBjC,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { Resvg } from '@resvg/resvg-js';
2
+ import { optimize } from 'svgo';
3
+ /**
4
+ * Rasterise with resvg: a pure-Rust SVG renderer with no system libraries and
5
+ * no browser, so a PNG built on a laptop is byte-identical to one built in CI.
6
+ */
7
+ export const renderPng = (svg, options = {}) => {
8
+ const fitTo = options.width === undefined
9
+ ? { mode: 'zoom', value: options.scale ?? 1 }
10
+ : { mode: 'width', value: options.width };
11
+ const resvg = new Resvg(svg, {
12
+ fitTo,
13
+ ...(options.background === undefined ? {} : { background: options.background }),
14
+ font: { loadSystemFonts: true },
15
+ });
16
+ return Buffer.from(resvg.render().asPng());
17
+ };
18
+ /**
19
+ * Shrink the SVG without losing the `data-*` hooks: those attributes are the
20
+ * contract that lets another program (or a model) find a bone, a muscle or an
21
+ * annotation in the output.
22
+ */
23
+ export const optimizeSvg = (svg) => optimize(svg, {
24
+ multipass: true,
25
+ js2svg: { indent: 0, pretty: false },
26
+ plugins: [
27
+ {
28
+ name: 'preset-default',
29
+ params: {
30
+ overrides: {
31
+ removeViewBox: false,
32
+ cleanupIds: false,
33
+ removeUnknownsAndDefaults: { keepDataAttrs: true },
34
+ },
35
+ },
36
+ },
37
+ ],
38
+ }).data;
39
+ //# sourceMappingURL=raster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raster.js","sourceRoot":"","sources":["../../src/render/raster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAUhC;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,UAAsB,EAAE,EAAU,EAAE;IACzE,MAAM,KAAK,GACT,OAAO,CAAC,KAAK,KAAK,SAAS;QACzB,CAAC,CAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC,EAAY;QACxD,CAAC,CAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAY,CAAC;IAEzD,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,EAAE;QAC3B,KAAK;QACL,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;QAC/E,IAAI,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE;KAChC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAW,EAAU,EAAE,CACjD,QAAQ,CAAC,GAAG,EAAE;IACZ,SAAS,EAAE,IAAI;IACf,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE;IACpC,OAAO,EAAE;QACP;YACE,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT,aAAa,EAAE,KAAK;oBACpB,UAAU,EAAE,KAAK;oBACjB,yBAAyB,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE;iBACnD;aACF;SACF;KACF;CACF,CAAC,CAAC,IAAI,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { Bounds, Rig, Skeleton } from '../core/types.js';
2
+ import { type PoseSpec } from '../model/index.js';
3
+ import { type Style, type StyleId, type StyleOverride } from './styles.js';
4
+ import { type SvgNode } from './svg.js';
5
+ export interface RenderOptions {
6
+ readonly width?: number;
7
+ readonly height?: number;
8
+ readonly style?: StyleId;
9
+ readonly styleOverride?: StyleOverride;
10
+ readonly rig?: Rig;
11
+ /** Draw the pose name (and Sanskrit name) above the figure. */
12
+ readonly title?: boolean;
13
+ /** Draw the teaching cues below the figure. */
14
+ readonly caption?: boolean;
15
+ readonly background?: string;
16
+ /** Force the muscle layer on or off, overriding the style. */
17
+ readonly muscles?: boolean;
18
+ }
19
+ export declare const DEFAULT_WIDTH = 600;
20
+ export declare const DEFAULT_HEIGHT = 800;
21
+ /** Everything that must be visible: the figure, its props and its annotations. */
22
+ export declare const contentBounds: (pose: PoseSpec, skeleton: Skeleton, style: Style) => Bounds;
23
+ export declare const renderSvgNode: (pose: PoseSpec, options?: RenderOptions) => SvgNode;
24
+ /** Render a pose to a standalone, deterministic SVG document. */
25
+ export declare const renderSvg: (pose: PoseSpec, options?: RenderOptions) => string;
26
+ //# sourceMappingURL=scene.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../../src/render/scene.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAOjE,OAAO,EAAgB,KAAK,KAAK,EAAE,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAAgC,KAAK,OAAO,EAAE,MAAM,UAAU,CAAC;AAEtE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IACnB,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,cAAc,MAAM,CAAC;AAalC,kFAAkF;AAClF,eAAO,MAAM,aAAa,GAAI,MAAM,QAAQ,EAAE,UAAU,QAAQ,EAAE,OAAO,KAAK,KAAG,MAWhF,CAAC;AAkHF,eAAO,MAAM,aAAa,GAAI,MAAM,QAAQ,EAAE,UAAS,aAAkB,KAAG,OAwC3E,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,SAAS,GAAI,MAAM,QAAQ,EAAE,UAAS,aAAkB,KAAG,MAC/B,CAAC"}