schematex 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 (181) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +379 -0
  3. package/dist/chunk-2MQWZ2XY.cjs +453 -0
  4. package/dist/chunk-2MQWZ2XY.cjs.map +1 -0
  5. package/dist/chunk-2UKC6ZCY.cjs +1803 -0
  6. package/dist/chunk-2UKC6ZCY.cjs.map +1 -0
  7. package/dist/chunk-34X3ZJ6E.cjs +783 -0
  8. package/dist/chunk-34X3ZJ6E.cjs.map +1 -0
  9. package/dist/chunk-3FTUWAXK.cjs +1220 -0
  10. package/dist/chunk-3FTUWAXK.cjs.map +1 -0
  11. package/dist/chunk-3J7TFUOC.js +745 -0
  12. package/dist/chunk-3J7TFUOC.js.map +1 -0
  13. package/dist/chunk-47ZC6EMJ.js +1009 -0
  14. package/dist/chunk-47ZC6EMJ.js.map +1 -0
  15. package/dist/chunk-4DBRNOPA.cjs +750 -0
  16. package/dist/chunk-4DBRNOPA.cjs.map +1 -0
  17. package/dist/chunk-4G7ZIBHN.js +778 -0
  18. package/dist/chunk-4G7ZIBHN.js.map +1 -0
  19. package/dist/chunk-5C7DPDHQ.js +1321 -0
  20. package/dist/chunk-5C7DPDHQ.js.map +1 -0
  21. package/dist/chunk-ADOXGKAK.js +1251 -0
  22. package/dist/chunk-ADOXGKAK.js.map +1 -0
  23. package/dist/chunk-BE5HNDA5.cjs +874 -0
  24. package/dist/chunk-BE5HNDA5.cjs.map +1 -0
  25. package/dist/chunk-CZRM7LT7.js +889 -0
  26. package/dist/chunk-CZRM7LT7.js.map +1 -0
  27. package/dist/chunk-D4JTSPOL.js +1795 -0
  28. package/dist/chunk-D4JTSPOL.js.map +1 -0
  29. package/dist/chunk-DS47NTWZ.cjs +1034 -0
  30. package/dist/chunk-DS47NTWZ.cjs.map +1 -0
  31. package/dist/chunk-FDLZEKEB.js +449 -0
  32. package/dist/chunk-FDLZEKEB.js.map +1 -0
  33. package/dist/chunk-FGPTCDUT.cjs +1851 -0
  34. package/dist/chunk-FGPTCDUT.cjs.map +1 -0
  35. package/dist/chunk-HDKDQAEQ.cjs +86 -0
  36. package/dist/chunk-HDKDQAEQ.cjs.map +1 -0
  37. package/dist/chunk-IX554O5K.js +346 -0
  38. package/dist/chunk-IX554O5K.js.map +1 -0
  39. package/dist/chunk-KLJEK547.js +71 -0
  40. package/dist/chunk-KLJEK547.js.map +1 -0
  41. package/dist/chunk-LMFSHK45.js +1028 -0
  42. package/dist/chunk-LMFSHK45.js.map +1 -0
  43. package/dist/chunk-MDICUK6F.cjs +1258 -0
  44. package/dist/chunk-MDICUK6F.cjs.map +1 -0
  45. package/dist/chunk-N7KOXOMX.cjs +363 -0
  46. package/dist/chunk-N7KOXOMX.cjs.map +1 -0
  47. package/dist/chunk-NYCIK4SU.cjs +775 -0
  48. package/dist/chunk-NYCIK4SU.cjs.map +1 -0
  49. package/dist/chunk-PDPHRZZT.js +770 -0
  50. package/dist/chunk-PDPHRZZT.js.map +1 -0
  51. package/dist/chunk-ROFLJ74T.js +1212 -0
  52. package/dist/chunk-ROFLJ74T.js.map +1 -0
  53. package/dist/chunk-S6BK5DB6.cjs +845 -0
  54. package/dist/chunk-S6BK5DB6.cjs.map +1 -0
  55. package/dist/chunk-U4I37IBN.js +874 -0
  56. package/dist/chunk-U4I37IBN.js.map +1 -0
  57. package/dist/chunk-U5GGE6PJ.js +839 -0
  58. package/dist/chunk-U5GGE6PJ.js.map +1 -0
  59. package/dist/chunk-UHLYS3W5.cjs +1015 -0
  60. package/dist/chunk-UHLYS3W5.cjs.map +1 -0
  61. package/dist/chunk-URSKIHSY.cjs +881 -0
  62. package/dist/chunk-URSKIHSY.cjs.map +1 -0
  63. package/dist/chunk-V6WO7RK7.cjs +1056 -0
  64. package/dist/chunk-V6WO7RK7.cjs.map +1 -0
  65. package/dist/chunk-VFQCTXOX.js +869 -0
  66. package/dist/chunk-VFQCTXOX.js.map +1 -0
  67. package/dist/chunk-XQ52ICHU.cjs +895 -0
  68. package/dist/chunk-XQ52ICHU.cjs.map +1 -0
  69. package/dist/chunk-XX4BKS7Y.js +1051 -0
  70. package/dist/chunk-XX4BKS7Y.js.map +1 -0
  71. package/dist/chunk-XXU36667.js +1844 -0
  72. package/dist/chunk-XXU36667.js.map +1 -0
  73. package/dist/chunk-ZX7QKZK2.cjs +1326 -0
  74. package/dist/chunk-ZX7QKZK2.cjs.map +1 -0
  75. package/dist/diagrams/blockdiagram/index.cjs +25 -0
  76. package/dist/diagrams/blockdiagram/index.cjs.map +1 -0
  77. package/dist/diagrams/blockdiagram/index.d.cts +67 -0
  78. package/dist/diagrams/blockdiagram/index.d.ts +67 -0
  79. package/dist/diagrams/blockdiagram/index.js +4 -0
  80. package/dist/diagrams/blockdiagram/index.js.map +1 -0
  81. package/dist/diagrams/circuit/index.cjs +34 -0
  82. package/dist/diagrams/circuit/index.cjs.map +1 -0
  83. package/dist/diagrams/circuit/index.d.cts +138 -0
  84. package/dist/diagrams/circuit/index.d.ts +138 -0
  85. package/dist/diagrams/circuit/index.js +5 -0
  86. package/dist/diagrams/circuit/index.js.map +1 -0
  87. package/dist/diagrams/ecomap/index.cjs +30 -0
  88. package/dist/diagrams/ecomap/index.cjs.map +1 -0
  89. package/dist/diagrams/ecomap/index.d.cts +15 -0
  90. package/dist/diagrams/ecomap/index.d.ts +15 -0
  91. package/dist/diagrams/ecomap/index.js +5 -0
  92. package/dist/diagrams/ecomap/index.js.map +1 -0
  93. package/dist/diagrams/entity/index.cjs +26 -0
  94. package/dist/diagrams/entity/index.cjs.map +1 -0
  95. package/dist/diagrams/entity/index.d.cts +54 -0
  96. package/dist/diagrams/entity/index.d.ts +54 -0
  97. package/dist/diagrams/entity/index.js +5 -0
  98. package/dist/diagrams/entity/index.js.map +1 -0
  99. package/dist/diagrams/fishbone/index.cjs +34 -0
  100. package/dist/diagrams/fishbone/index.cjs.map +1 -0
  101. package/dist/diagrams/fishbone/index.d.cts +185 -0
  102. package/dist/diagrams/fishbone/index.d.ts +185 -0
  103. package/dist/diagrams/fishbone/index.js +5 -0
  104. package/dist/diagrams/fishbone/index.js.map +1 -0
  105. package/dist/diagrams/flowchart/index.cjs +34 -0
  106. package/dist/diagrams/flowchart/index.cjs.map +1 -0
  107. package/dist/diagrams/flowchart/index.d.cts +2 -0
  108. package/dist/diagrams/flowchart/index.d.ts +2 -0
  109. package/dist/diagrams/flowchart/index.js +5 -0
  110. package/dist/diagrams/flowchart/index.js.map +1 -0
  111. package/dist/diagrams/genogram/index.cjs +38 -0
  112. package/dist/diagrams/genogram/index.cjs.map +1 -0
  113. package/dist/diagrams/genogram/index.d.cts +20 -0
  114. package/dist/diagrams/genogram/index.d.ts +20 -0
  115. package/dist/diagrams/genogram/index.js +5 -0
  116. package/dist/diagrams/genogram/index.js.map +1 -0
  117. package/dist/diagrams/ladder/index.cjs +26 -0
  118. package/dist/diagrams/ladder/index.cjs.map +1 -0
  119. package/dist/diagrams/ladder/index.d.cts +49 -0
  120. package/dist/diagrams/ladder/index.d.ts +49 -0
  121. package/dist/diagrams/ladder/index.js +5 -0
  122. package/dist/diagrams/ladder/index.js.map +1 -0
  123. package/dist/diagrams/logic/index.cjs +26 -0
  124. package/dist/diagrams/logic/index.cjs.map +1 -0
  125. package/dist/diagrams/logic/index.d.cts +73 -0
  126. package/dist/diagrams/logic/index.d.ts +73 -0
  127. package/dist/diagrams/logic/index.js +5 -0
  128. package/dist/diagrams/logic/index.js.map +1 -0
  129. package/dist/diagrams/orgchart/index.cjs +30 -0
  130. package/dist/diagrams/orgchart/index.cjs.map +1 -0
  131. package/dist/diagrams/orgchart/index.d.cts +100 -0
  132. package/dist/diagrams/orgchart/index.d.ts +100 -0
  133. package/dist/diagrams/orgchart/index.js +5 -0
  134. package/dist/diagrams/orgchart/index.js.map +1 -0
  135. package/dist/diagrams/pedigree/index.cjs +30 -0
  136. package/dist/diagrams/pedigree/index.cjs.map +1 -0
  137. package/dist/diagrams/pedigree/index.d.cts +15 -0
  138. package/dist/diagrams/pedigree/index.d.ts +15 -0
  139. package/dist/diagrams/pedigree/index.js +5 -0
  140. package/dist/diagrams/pedigree/index.js.map +1 -0
  141. package/dist/diagrams/phylo/index.cjs +30 -0
  142. package/dist/diagrams/phylo/index.cjs.map +1 -0
  143. package/dist/diagrams/phylo/index.d.cts +32 -0
  144. package/dist/diagrams/phylo/index.d.ts +32 -0
  145. package/dist/diagrams/phylo/index.js +5 -0
  146. package/dist/diagrams/phylo/index.js.map +1 -0
  147. package/dist/diagrams/sld/index.cjs +26 -0
  148. package/dist/diagrams/sld/index.cjs.map +1 -0
  149. package/dist/diagrams/sld/index.d.cts +58 -0
  150. package/dist/diagrams/sld/index.d.ts +58 -0
  151. package/dist/diagrams/sld/index.js +5 -0
  152. package/dist/diagrams/sld/index.js.map +1 -0
  153. package/dist/diagrams/sociogram/index.cjs +26 -0
  154. package/dist/diagrams/sociogram/index.cjs.map +1 -0
  155. package/dist/diagrams/sociogram/index.d.cts +76 -0
  156. package/dist/diagrams/sociogram/index.d.ts +76 -0
  157. package/dist/diagrams/sociogram/index.js +5 -0
  158. package/dist/diagrams/sociogram/index.js.map +1 -0
  159. package/dist/diagrams/timing/index.cjs +21 -0
  160. package/dist/diagrams/timing/index.cjs.map +1 -0
  161. package/dist/diagrams/timing/index.d.cts +9 -0
  162. package/dist/diagrams/timing/index.d.ts +9 -0
  163. package/dist/diagrams/timing/index.js +4 -0
  164. package/dist/diagrams/timing/index.js.map +1 -0
  165. package/dist/diagrams/venn/index.cjs +38 -0
  166. package/dist/diagrams/venn/index.cjs.map +1 -0
  167. package/dist/diagrams/venn/index.d.cts +69 -0
  168. package/dist/diagrams/venn/index.d.ts +69 -0
  169. package/dist/diagrams/venn/index.js +5 -0
  170. package/dist/diagrams/venn/index.js.map +1 -0
  171. package/dist/index-BSlza1YY.d.ts +150 -0
  172. package/dist/index-BXefHVce.d.cts +150 -0
  173. package/dist/index.cjs +2033 -0
  174. package/dist/index.cjs.map +1 -0
  175. package/dist/index.d.cts +29 -0
  176. package/dist/index.d.ts +29 -0
  177. package/dist/index.js +1944 -0
  178. package/dist/index.js.map +1 -0
  179. package/dist/types-DqfcYkcY.d.cts +741 -0
  180. package/dist/types-DqfcYkcY.d.ts +741 -0
  181. package/package.json +163 -0
@@ -0,0 +1,845 @@
1
+ 'use strict';
2
+
3
+ var chunkN7KOXOMX_cjs = require('./chunk-N7KOXOMX.cjs');
4
+ var chunkHDKDQAEQ_cjs = require('./chunk-HDKDQAEQ.cjs');
5
+
6
+ // src/diagrams/ecomap/parser.ts
7
+ var EcomapParseError = class extends Error {
8
+ constructor(message, line) {
9
+ super(`Line ${line}: ${message}`);
10
+ this.line = line;
11
+ this.name = "EcomapParseError";
12
+ }
13
+ line;
14
+ };
15
+ var CONNECTION_OPS = {
16
+ "===": { relType: "strong" },
17
+ "==": { relType: "moderate" },
18
+ "---": { relType: "normal" },
19
+ "- -": { relType: "weak" },
20
+ "~~~": { relType: "stressful" },
21
+ "~=~": { relType: "stressful-strong" },
22
+ "~x~": { relType: "conflictual" },
23
+ "-/-": { relType: "broken" },
24
+ "===>": { relType: "strong", energyFlow: "from" },
25
+ "<===": { relType: "strong", energyFlow: "to" },
26
+ "<=>": { relType: "moderate", energyFlow: "mutual" },
27
+ "==>": { relType: "moderate", energyFlow: "from" },
28
+ "<==": { relType: "moderate", energyFlow: "to" },
29
+ "-->": { relType: "normal", energyFlow: "from" },
30
+ "<--": { relType: "normal", energyFlow: "to" },
31
+ "<->": { relType: "normal", energyFlow: "mutual" }
32
+ };
33
+ var OP_PATTERN = "===>|<===|===|<=>|==>|<==|<->|-->|<--|~=~|~x~|~~~|-\\/-|---|==|- -";
34
+ var CONNECTION_RE = new RegExp(
35
+ `^([a-zA-Z][a-zA-Z0-9_-]*)\\s+(${OP_PATTERN})\\s+([a-zA-Z][a-zA-Z0-9_-]*)(.*)$`
36
+ );
37
+ function parseEcomap(text2) {
38
+ const lines = text2.split("\n");
39
+ const individuals = [];
40
+ const knownIds = /* @__PURE__ */ new Set();
41
+ const relationships = [];
42
+ const metadata = {};
43
+ let centerId = null;
44
+ let i = 0;
45
+ while (i < lines.length && lines[i].trim() === "") i++;
46
+ if (i >= lines.length) throw new EcomapParseError("Empty input", 1);
47
+ const header = lines[i].trim();
48
+ const headerMatch = header.match(/^ecomap\s*(?:"([^"]*)")?$/i);
49
+ if (!headerMatch)
50
+ throw new EcomapParseError("Expected 'ecomap' header", i + 1);
51
+ if (headerMatch[1]) metadata.title = headerMatch[1];
52
+ i++;
53
+ while (i < lines.length) {
54
+ const raw = lines[i];
55
+ const trimmed = raw.trim();
56
+ if (trimmed === "" || trimmed.startsWith("#") || trimmed.startsWith("//")) {
57
+ i++;
58
+ continue;
59
+ }
60
+ const centerMatch = trimmed.match(
61
+ /^center:\s*([a-zA-Z][a-zA-Z0-9_-]*)\s*(\[.*\])?\s*$/
62
+ );
63
+ if (centerMatch) {
64
+ const id = centerMatch[1].toLowerCase();
65
+ centerId = id;
66
+ const props = centerMatch[2] ? parseProps(centerMatch[2]) : {};
67
+ individuals.push(buildIndividual(id, props, true));
68
+ knownIds.add(id);
69
+ i++;
70
+ const baseIndent = leadingSpaces(raw);
71
+ while (i < lines.length) {
72
+ if (lines[i].trim() === "") {
73
+ i++;
74
+ continue;
75
+ }
76
+ if (leadingSpaces(lines[i]) > baseIndent + 2) {
77
+ i++;
78
+ } else {
79
+ break;
80
+ }
81
+ }
82
+ continue;
83
+ }
84
+ const connMatch = trimmed.match(CONNECTION_RE);
85
+ if (connMatch) {
86
+ const fromRaw = connMatch[1].toLowerCase();
87
+ const op = connMatch[2];
88
+ const toRaw = connMatch[3].toLowerCase();
89
+ const rest = connMatch[4]?.trim() ?? "";
90
+ const opInfo = CONNECTION_OPS[op];
91
+ if (!opInfo)
92
+ throw new EcomapParseError(`Unknown operator '${op}'`, i + 1);
93
+ let label;
94
+ const lblMatch = rest.match(/\[\s*label:\s*"([^"]*)"\s*\]/);
95
+ if (lblMatch) label = lblMatch[1];
96
+ let from = fromRaw;
97
+ let to = toRaw;
98
+ let flow = opInfo.energyFlow;
99
+ if (to === centerId && from !== centerId) {
100
+ [from, to] = [to, from];
101
+ if (flow === "from") flow = "to";
102
+ else if (flow === "to") flow = "from";
103
+ }
104
+ relationships.push({
105
+ type: opInfo.relType,
106
+ from,
107
+ to,
108
+ label,
109
+ energyFlow: flow
110
+ });
111
+ i++;
112
+ continue;
113
+ }
114
+ const sysMatch = trimmed.match(
115
+ /^([a-zA-Z][a-zA-Z0-9_-]*)\s*(\[.*\])?\s*$/
116
+ );
117
+ if (sysMatch) {
118
+ const id = sysMatch[1].toLowerCase();
119
+ if (!knownIds.has(id)) {
120
+ const props = sysMatch[2] ? parseProps(sysMatch[2]) : {};
121
+ individuals.push(buildIndividual(id, props, false));
122
+ knownIds.add(id);
123
+ }
124
+ i++;
125
+ continue;
126
+ }
127
+ throw new EcomapParseError(`Unexpected: ${trimmed}`, i + 1);
128
+ }
129
+ return { type: "ecomap", individuals, relationships, metadata };
130
+ }
131
+ function leadingSpaces(line) {
132
+ const m = line.match(/^(\s*)/);
133
+ return m ? m[1].length : 0;
134
+ }
135
+ function parseProps(bracketStr) {
136
+ const inner = bracketStr.slice(1, -1).trim();
137
+ if (!inner) return {};
138
+ const props = {};
139
+ for (const part of splitCommas(inner)) {
140
+ const t = part.trim();
141
+ if (!t) continue;
142
+ const kv = t.match(/^([\w][\w-]*)\s*:\s*(?:"([^"]*)"|(\S+))$/);
143
+ if (kv) {
144
+ props[kv[1]] = kv[2] ?? kv[3];
145
+ continue;
146
+ }
147
+ if (t === "male" || t === "female" || t === "unknown") {
148
+ props.sex = t;
149
+ continue;
150
+ }
151
+ props[t] = "true";
152
+ }
153
+ return props;
154
+ }
155
+ function splitCommas(s) {
156
+ const parts = [];
157
+ let cur = "";
158
+ let inQ = false;
159
+ for (const ch of s) {
160
+ if (ch === '"') {
161
+ inQ = !inQ;
162
+ cur += ch;
163
+ } else if (ch === "," && !inQ) {
164
+ parts.push(cur);
165
+ cur = "";
166
+ } else {
167
+ cur += ch;
168
+ }
169
+ }
170
+ if (cur) parts.push(cur);
171
+ return parts;
172
+ }
173
+ function parseSex(s) {
174
+ switch (s) {
175
+ case "male":
176
+ case "female":
177
+ case "unknown":
178
+ case "other":
179
+ case "nonbinary":
180
+ case "intersex":
181
+ return s;
182
+ default:
183
+ return "unknown";
184
+ }
185
+ }
186
+ function buildIndividual(id, props, isCenter) {
187
+ const properties = {};
188
+ if (isCenter) properties.center = "true";
189
+ if (props.category) properties.category = props.category;
190
+ if (props.size) properties.size = props.size;
191
+ if (props.importance) properties.importance = props.importance;
192
+ if (props.sector) properties.sector = props.sector;
193
+ return {
194
+ id,
195
+ label: props.label ?? id,
196
+ sex: parseSex(props.sex),
197
+ status: "alive",
198
+ age: props.age ? parseInt(props.age, 10) : void 0,
199
+ properties
200
+ };
201
+ }
202
+
203
+ // src/diagrams/ecomap/layout.ts
204
+ var CENTER_R = 50;
205
+ var SYS_R = 30;
206
+ var SYS_R_LARGE = 40;
207
+ var SYS_R_SMALL = 20;
208
+ var PADDING = 40;
209
+ var LABEL_CLEARANCE = 60;
210
+ function layoutEcomap(ast, _config) {
211
+ const center = ast.individuals.find(
212
+ (ind) => ind.properties?.center === "true"
213
+ );
214
+ if (!center) throw new Error("Ecomap requires a center element");
215
+ const systems = ast.individuals.filter(
216
+ (ind) => ind.properties?.center !== "true"
217
+ );
218
+ const n = systems.length;
219
+ if (n === 0) {
220
+ const size = (CENTER_R + PADDING + LABEL_CLEARANCE) * 2;
221
+ return {
222
+ width: size,
223
+ height: size,
224
+ nodes: [
225
+ {
226
+ id: center.id,
227
+ x: size / 2 - CENTER_R,
228
+ y: size / 2 - CENTER_R,
229
+ width: CENTER_R * 2,
230
+ height: CENTER_R * 2,
231
+ generation: 0,
232
+ individual: center
233
+ }
234
+ ],
235
+ edges: []
236
+ };
237
+ }
238
+ const ringRadii = getRingRadii(n);
239
+ const ringAssignment = assignToRings(
240
+ center.id,
241
+ systems,
242
+ ast.relationships,
243
+ ringRadii.length
244
+ );
245
+ const systemPositions = placeOnRings(systems, ringAssignment, ringRadii);
246
+ const maxRing = ringRadii[ringRadii.length - 1] ?? 180;
247
+ const canvasSize = (maxRing + SYS_R_LARGE + LABEL_CLEARANCE + PADDING) * 2;
248
+ const cx = canvasSize / 2;
249
+ const cy = canvasSize / 2;
250
+ const nodes = [];
251
+ nodes.push({
252
+ id: center.id,
253
+ x: cx - CENTER_R,
254
+ y: cy - CENTER_R,
255
+ width: CENTER_R * 2,
256
+ height: CENTER_R * 2,
257
+ generation: 0,
258
+ individual: center
259
+ });
260
+ for (const sys of systems) {
261
+ const pos = systemPositions.get(sys.id);
262
+ if (!pos) continue;
263
+ const r = getSystemRadius(sys);
264
+ nodes.push({
265
+ id: sys.id,
266
+ x: cx + pos.x - r,
267
+ y: cy + pos.y - r,
268
+ width: r * 2,
269
+ height: r * 2,
270
+ generation: pos.ring + 1,
271
+ individual: sys
272
+ });
273
+ }
274
+ const edges = computeEdges(nodes, ast.relationships);
275
+ return { width: canvasSize, height: canvasSize, nodes, edges };
276
+ }
277
+ function getRingRadii(n) {
278
+ if (n === 0) return [];
279
+ if (n <= 6) return [180];
280
+ if (n <= 12) return [150, 270];
281
+ return [140, 230, 320];
282
+ }
283
+ function assignToRings(_centerId, systems, rels, ringCount) {
284
+ const relBySys = /* @__PURE__ */ new Map();
285
+ for (const r of rels) {
286
+ const sysId = r.from === _centerId ? r.to : r.from === _centerId ? r.to : r.to;
287
+ if (!relBySys.has(sysId)) relBySys.set(sysId, r);
288
+ const otherId = r.from === _centerId ? r.to : r.from;
289
+ if (!relBySys.has(otherId)) relBySys.set(otherId, r);
290
+ }
291
+ const result = /* @__PURE__ */ new Map();
292
+ if (ringCount <= 1) {
293
+ for (const s of systems) result.set(s.id, 0);
294
+ return result;
295
+ }
296
+ for (const s of systems) {
297
+ const rel = relBySys.get(s.id);
298
+ if (!rel) {
299
+ result.set(s.id, ringCount - 1);
300
+ continue;
301
+ }
302
+ if (rel.type === "strong" || rel.type === "stressful-strong") {
303
+ result.set(s.id, 0);
304
+ } else if (rel.type === "weak" || rel.type === "broken") {
305
+ result.set(s.id, ringCount - 1);
306
+ } else {
307
+ result.set(s.id, Math.min(1, ringCount - 1));
308
+ }
309
+ }
310
+ return result;
311
+ }
312
+ function placeOnRings(systems, ringAssignment, ringRadii) {
313
+ const ringGroups = /* @__PURE__ */ new Map();
314
+ for (const s of systems) {
315
+ const ring = ringAssignment.get(s.id) ?? 0;
316
+ const grp = ringGroups.get(ring) ?? [];
317
+ grp.push(s);
318
+ ringGroups.set(ring, grp);
319
+ }
320
+ const positions = /* @__PURE__ */ new Map();
321
+ for (const [ring, grp] of ringGroups) {
322
+ const radius = ringRadii[ring] ?? ringRadii[ringRadii.length - 1] ?? 180;
323
+ const n = grp.length;
324
+ const startAngle = -Math.PI / 2;
325
+ for (let idx = 0; idx < n; idx++) {
326
+ const angle = startAngle + 2 * Math.PI * idx / n;
327
+ positions.set(grp[idx].id, {
328
+ x: radius * Math.cos(angle),
329
+ y: radius * Math.sin(angle),
330
+ ring
331
+ });
332
+ }
333
+ }
334
+ return positions;
335
+ }
336
+ function computeEdges(nodes, rels) {
337
+ const nodeMap = /* @__PURE__ */ new Map();
338
+ for (const n of nodes) nodeMap.set(n.id, n);
339
+ const edges = [];
340
+ for (const rel of rels) {
341
+ const fromNode = nodeMap.get(rel.from);
342
+ const toNode = nodeMap.get(rel.to);
343
+ if (!fromNode || !toNode) continue;
344
+ const fcx = fromNode.x + fromNode.width / 2;
345
+ const fcy = fromNode.y + fromNode.height / 2;
346
+ const tcx = toNode.x + toNode.width / 2;
347
+ const tcy = toNode.y + toNode.height / 2;
348
+ const dx = tcx - fcx;
349
+ const dy = tcy - fcy;
350
+ const dist = Math.sqrt(dx * dx + dy * dy);
351
+ if (dist < 1) continue;
352
+ const ux = dx / dist;
353
+ const uy = dy / dist;
354
+ const fromR = fromNode.width / 2;
355
+ const toR = toNode.width / 2;
356
+ const x1 = fcx + ux * fromR;
357
+ const y1 = fcy + uy * fromR;
358
+ const x2 = tcx - ux * toR;
359
+ const y2 = tcy - uy * toR;
360
+ edges.push({
361
+ from: rel.from,
362
+ to: rel.to,
363
+ relationship: rel,
364
+ path: `M ${x1} ${y1} L ${x2} ${y2}`
365
+ });
366
+ }
367
+ return edges;
368
+ }
369
+ function getSystemRadius(ind) {
370
+ const imp = ind.properties?.importance ?? ind.properties?.size;
371
+ switch (imp) {
372
+ case "major":
373
+ case "large":
374
+ return SYS_R_LARGE;
375
+ case "minor":
376
+ case "small":
377
+ return SYS_R_SMALL;
378
+ default:
379
+ return SYS_R;
380
+ }
381
+ }
382
+
383
+ // src/diagrams/ecomap/renderer.ts
384
+ var CATEGORY_COLORS = {
385
+ family: "#8D6E63",
386
+ friends: "#42A5F5",
387
+ work: "#66BB6A",
388
+ education: "#FFA726",
389
+ health: "#EF5350",
390
+ "mental-health": "#AB47BC",
391
+ religion: "#CCBB33",
392
+ recreation: "#26C6DA",
393
+ legal: "#78909C",
394
+ government: "#8D6E63",
395
+ financial: "#66BB6A",
396
+ community: "#29B6F6",
397
+ cultural: "#FFA726",
398
+ substance: "#EF5350",
399
+ technology: "#42A5F5",
400
+ pet: "#8D6E63"
401
+ };
402
+ function renderEcomap(layout, config) {
403
+ const centerNode = layout.nodes.find(
404
+ (n) => n.individual.properties?.center === "true"
405
+ );
406
+ const systemNodes = layout.nodes.filter(
407
+ (n) => n.individual.properties?.center !== "true"
408
+ );
409
+ const t = chunkN7KOXOMX_cjs.resolveBaseTheme(config.theme);
410
+ const defsStr = buildDefs(t);
411
+ const styleStr = buildStyles(config, t);
412
+ const connectionsStr = renderConnections(layout.edges);
413
+ const centerStr = centerNode ? renderCenter(centerNode, config) : "";
414
+ const systemsStr = renderSystems(systemNodes, config);
415
+ const labelsStr = renderConnectionLabels(layout.edges, t);
416
+ return chunkHDKDQAEQ_cjs.svgRoot(
417
+ {
418
+ viewBox: `0 0 ${layout.width} ${layout.height}`,
419
+ class: "schematex-diagram schematex-ecomap",
420
+ width: layout.width,
421
+ height: layout.height
422
+ },
423
+ [
424
+ chunkHDKDQAEQ_cjs.title("Ecomap"),
425
+ chunkHDKDQAEQ_cjs.desc(
426
+ `Ecomap diagram with ${systemNodes.length} external systems`
427
+ ),
428
+ defsStr,
429
+ styleStr,
430
+ connectionsStr,
431
+ centerStr,
432
+ systemsStr,
433
+ labelsStr
434
+ ]
435
+ );
436
+ }
437
+ function buildDefs(t) {
438
+ const arrowMarker = chunkHDKDQAEQ_cjs.el(
439
+ "marker",
440
+ {
441
+ id: "schematex-ecomap-eco-arrow",
442
+ viewBox: "0 0 10 10",
443
+ refX: "10",
444
+ refY: "5",
445
+ markerWidth: "8",
446
+ markerHeight: "8",
447
+ orient: "auto-start-reverse"
448
+ },
449
+ [chunkHDKDQAEQ_cjs.el("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: t.neutral })]
450
+ );
451
+ return chunkHDKDQAEQ_cjs.el("defs", {}, [arrowMarker]);
452
+ }
453
+ function buildStyles(config, t) {
454
+ let css = `
455
+ .schematex-ecomap {${chunkN7KOXOMX_cjs.cssCustomProperties(t)}
456
+ background: ${t.bg};
457
+ }
458
+ .schematex-ecomap-center-shape { fill: ${t.fill}; stroke: ${t.stroke}; stroke-width: ${chunkN7KOXOMX_cjs.STROKE_WIDTH.thick}; }
459
+ .schematex-ecomap-center-label { font-family: ${config.fontFamily}; font-size: ${config.fontSize + 2}px; text-anchor: middle; dominant-baseline: central; fill: ${t.text}; font-weight: 600; }
460
+ .schematex-ecomap-system-shape { fill: ${t.fillMuted}; stroke: ${t.neutral}; stroke-width: ${chunkN7KOXOMX_cjs.STROKE_WIDTH.normal}; }
461
+ .schematex-ecomap-system-label { font-family: ${config.fontFamily}; font-size: ${config.fontSize - 1}px; text-anchor: middle; fill: ${t.text}; }
462
+ .schematex-ecomap-eco-line { stroke: ${t.neutral}; stroke-width: ${chunkN7KOXOMX_cjs.STROKE_WIDTH.normal}; fill: none; stroke-linecap: round; }
463
+ .schematex-ecomap-eco-line-parallel { stroke: ${t.neutral}; stroke-width: ${chunkN7KOXOMX_cjs.STROKE_WIDTH.normal}; fill: none; stroke-linecap: round; }
464
+ .schematex-ecomap-eco-line-weak { stroke: ${t.neutral}; stroke-width: ${chunkN7KOXOMX_cjs.STROKE_WIDTH.normal}; stroke-dasharray: 6,4; fill: none; stroke-linecap: round; }
465
+ .schematex-ecomap-eco-line-broken { stroke: ${t.neutral}; stroke-width: ${chunkN7KOXOMX_cjs.STROKE_WIDTH.normal}; stroke-dasharray: 3,8; fill: none; stroke-linecap: round; }
466
+ .schematex-ecomap-eco-line-stressful { stroke: ${t.neutral}; stroke-width: ${chunkN7KOXOMX_cjs.STROKE_WIDTH.normal}; fill: none; stroke-linecap: round; }
467
+ .schematex-ecomap-eco-conn-label { font-family: ${config.fontFamily}; font-size: ${config.fontSize - 2}px; text-anchor: middle; fill: ${t.textMuted}; }
468
+ .schematex-ecomap-eco-arrow { fill: ${t.neutral}; }
469
+ `;
470
+ for (const [cat, color] of Object.entries(CATEGORY_COLORS)) {
471
+ css += `.schematex-ecomap-system-${cat} .schematex-ecomap-system-shape { fill: ${color}18; stroke: ${color}; }
472
+ `;
473
+ }
474
+ return chunkHDKDQAEQ_cjs.el("style", {}, css);
475
+ }
476
+ function renderCenter(node, config) {
477
+ const cx = node.x + node.width / 2;
478
+ const cy = node.y + node.height / 2;
479
+ const r = node.width / 2;
480
+ const ind = node.individual;
481
+ const label = ind.label !== ind.id ? ind.label : capitalize(ind.id);
482
+ const elements = [
483
+ chunkHDKDQAEQ_cjs.el("circle", {
484
+ cx,
485
+ cy,
486
+ r,
487
+ class: "schematex-ecomap-center-shape"
488
+ }),
489
+ chunkHDKDQAEQ_cjs.text(
490
+ {
491
+ x: cx,
492
+ y: cy,
493
+ class: "schematex-ecomap-center-label"
494
+ },
495
+ label
496
+ )
497
+ ];
498
+ if (ind.age) {
499
+ elements.push(
500
+ chunkHDKDQAEQ_cjs.text(
501
+ {
502
+ x: cx,
503
+ y: cy + config.fontSize + 4,
504
+ class: "schematex-ecomap-center-label",
505
+ "font-size": `${config.fontSize}px`,
506
+ "font-weight": "normal"
507
+ },
508
+ `Age ${ind.age}`
509
+ )
510
+ );
511
+ }
512
+ return chunkHDKDQAEQ_cjs.group(
513
+ { class: "schematex-ecomap-center", "data-id": ind.id },
514
+ elements
515
+ );
516
+ }
517
+ function renderSystems(nodes, config) {
518
+ const elements = [];
519
+ for (const node of nodes) {
520
+ const cx = node.x + node.width / 2;
521
+ const cy = node.y + node.height / 2;
522
+ const r = node.width / 2;
523
+ const ind = node.individual;
524
+ const cat = ind.properties?.category ?? "other";
525
+ const label = ind.label !== ind.id ? ind.label : capitalize(ind.id);
526
+ const labelLines = wrapLabel(label, 12);
527
+ const labelElements = [];
528
+ const labelStartY = cy + r + config.fontSize + 2;
529
+ for (let li = 0; li < labelLines.length; li++) {
530
+ labelElements.push(
531
+ chunkHDKDQAEQ_cjs.text(
532
+ {
533
+ x: cx,
534
+ y: labelStartY + li * (config.fontSize + 1),
535
+ class: "schematex-ecomap-system-label"
536
+ },
537
+ labelLines[li]
538
+ )
539
+ );
540
+ }
541
+ elements.push(
542
+ chunkHDKDQAEQ_cjs.group(
543
+ {
544
+ class: `schematex-ecomap-system schematex-ecomap-system-${cat}`,
545
+ "data-system-id": ind.id
546
+ },
547
+ [
548
+ chunkHDKDQAEQ_cjs.el("circle", {
549
+ cx,
550
+ cy,
551
+ r,
552
+ class: "schematex-ecomap-system-shape"
553
+ }),
554
+ ...labelElements
555
+ ]
556
+ )
557
+ );
558
+ }
559
+ return chunkHDKDQAEQ_cjs.group({ class: "schematex-ecomap-systems" }, elements);
560
+ }
561
+ function renderConnections(edges) {
562
+ const elements = [];
563
+ for (const edge of edges) {
564
+ const coords = extractLineCoords(edge.path);
565
+ if (!coords) continue;
566
+ const relType = edge.relationship.type;
567
+ const flow = edge.relationship.energyFlow;
568
+ const lineElements = [];
569
+ const arrowAttrs = getArrowAttrs(flow);
570
+ switch (relType) {
571
+ case "strong":
572
+ lineElements.push(
573
+ ...parallelLines(coords, 3, 4, {
574
+ class: "schematex-ecomap-eco-line-parallel",
575
+ ...arrowAttrs
576
+ })
577
+ );
578
+ break;
579
+ case "moderate":
580
+ lineElements.push(
581
+ ...parallelLines(coords, 2, 4, {
582
+ class: "schematex-ecomap-eco-line-parallel",
583
+ ...arrowAttrs
584
+ })
585
+ );
586
+ break;
587
+ case "weak":
588
+ lineElements.push(
589
+ chunkHDKDQAEQ_cjs.el("line", {
590
+ x1: coords.x1,
591
+ y1: coords.y1,
592
+ x2: coords.x2,
593
+ y2: coords.y2,
594
+ class: "schematex-ecomap-eco-line-weak",
595
+ ...arrowAttrs
596
+ })
597
+ );
598
+ break;
599
+ case "stressful":
600
+ case "stressful-strong":
601
+ lineElements.push(
602
+ chunkHDKDQAEQ_cjs.el("path", {
603
+ d: wavyPath(
604
+ coords.x1,
605
+ coords.y1,
606
+ coords.x2,
607
+ coords.y2,
608
+ 8,
609
+ 20
610
+ ),
611
+ class: "schematex-ecomap-eco-line-stressful",
612
+ "stroke-width": relType === "stressful-strong" ? "3" : "2",
613
+ ...arrowAttrs
614
+ })
615
+ );
616
+ break;
617
+ case "conflictual":
618
+ lineElements.push(
619
+ chunkHDKDQAEQ_cjs.el("path", {
620
+ d: wavyPath(
621
+ coords.x1,
622
+ coords.y1,
623
+ coords.x2,
624
+ coords.y2,
625
+ 8,
626
+ 20
627
+ ),
628
+ class: "schematex-ecomap-eco-line-stressful",
629
+ ...arrowAttrs
630
+ })
631
+ );
632
+ lineElements.push(
633
+ ...conflictMarks(coords)
634
+ );
635
+ break;
636
+ case "broken":
637
+ lineElements.push(
638
+ chunkHDKDQAEQ_cjs.el("line", {
639
+ x1: coords.x1,
640
+ y1: coords.y1,
641
+ x2: coords.x2,
642
+ y2: coords.y2,
643
+ class: "schematex-ecomap-eco-line-broken",
644
+ ...arrowAttrs
645
+ })
646
+ );
647
+ break;
648
+ default:
649
+ lineElements.push(
650
+ chunkHDKDQAEQ_cjs.el("line", {
651
+ x1: coords.x1,
652
+ y1: coords.y1,
653
+ x2: coords.x2,
654
+ y2: coords.y2,
655
+ class: "schematex-ecomap-eco-line",
656
+ ...arrowAttrs
657
+ })
658
+ );
659
+ break;
660
+ }
661
+ elements.push(
662
+ chunkHDKDQAEQ_cjs.group(
663
+ {
664
+ class: `schematex-ecomap-connection schematex-ecomap-connection-${relType}`,
665
+ "data-from": edge.from,
666
+ "data-to": edge.to
667
+ },
668
+ lineElements
669
+ )
670
+ );
671
+ }
672
+ return chunkHDKDQAEQ_cjs.group({ class: "schematex-ecomap-connections" }, elements);
673
+ }
674
+ function renderConnectionLabels(edges, t) {
675
+ const elements = [];
676
+ for (const edge of edges) {
677
+ if (!edge.relationship.label) continue;
678
+ const coords = extractLineCoords(edge.path);
679
+ if (!coords) continue;
680
+ const mx = (coords.x1 + coords.x2) / 2;
681
+ const my = (coords.y1 + coords.y2) / 2;
682
+ elements.push(
683
+ chunkHDKDQAEQ_cjs.group({ class: "schematex-ecomap-conn-label-group" }, [
684
+ chunkHDKDQAEQ_cjs.el("rect", {
685
+ x: mx - 40,
686
+ y: my - 8,
687
+ width: 80,
688
+ height: 16,
689
+ rx: 3,
690
+ fill: t.bg,
691
+ "fill-opacity": "0.85"
692
+ }),
693
+ chunkHDKDQAEQ_cjs.text(
694
+ { x: mx, y: my + 4, class: "schematex-ecomap-eco-conn-label" },
695
+ edge.relationship.label
696
+ )
697
+ ])
698
+ );
699
+ }
700
+ return chunkHDKDQAEQ_cjs.group({ class: "schematex-ecomap-connection-labels" }, elements);
701
+ }
702
+ function extractLineCoords(pathData) {
703
+ const m = pathData.match(
704
+ /M\s*([\d.-]+)\s+([\d.-]+)\s*L\s*([\d.-]+)\s+([\d.-]+)/
705
+ );
706
+ if (!m) return null;
707
+ return { x1: +m[1], y1: +m[2], x2: +m[3], y2: +m[4] };
708
+ }
709
+ function parallelLines(coords, count, gap, attrs) {
710
+ const { x1, y1, x2, y2 } = coords;
711
+ const dx = x2 - x1;
712
+ const dy = y2 - y1;
713
+ const len = Math.sqrt(dx * dx + dy * dy);
714
+ if (len < 1) return [];
715
+ const nx = -dy / len;
716
+ const ny = dx / len;
717
+ const lines = [];
718
+ const offsets = count === 2 ? [-gap / 2, gap / 2] : count === 3 ? [-gap, 0, gap] : [0];
719
+ for (const off of offsets) {
720
+ lines.push(
721
+ chunkHDKDQAEQ_cjs.el("line", {
722
+ x1: x1 + nx * off,
723
+ y1: y1 + ny * off,
724
+ x2: x2 + nx * off,
725
+ y2: y2 + ny * off,
726
+ ...attrs
727
+ })
728
+ );
729
+ }
730
+ return lines;
731
+ }
732
+ function wavyPath(x1, y1, x2, y2, amplitude, wavelength) {
733
+ const dx = x2 - x1;
734
+ const dy = y2 - y1;
735
+ const len = Math.sqrt(dx * dx + dy * dy);
736
+ const segments = Math.max(4, Math.round(len / wavelength));
737
+ const ux = dx / len;
738
+ const uy = dy / len;
739
+ const nx = -uy;
740
+ const ny = ux;
741
+ let d = `M ${x1} ${y1}`;
742
+ for (let i = 0; i < segments; i++) {
743
+ const t1 = (i + 0.5) / segments;
744
+ const t2 = (i + 1) / segments;
745
+ const sign = i % 2 === 0 ? 1 : -1;
746
+ const cpx = x1 + dx * t1 + nx * amplitude * sign;
747
+ const cpy = y1 + dy * t1 + ny * amplitude * sign;
748
+ const ex = x1 + dx * t2;
749
+ const ey = y1 + dy * t2;
750
+ d += ` Q ${cpx} ${cpy} ${ex} ${ey}`;
751
+ }
752
+ return d;
753
+ }
754
+ function conflictMarks(coords) {
755
+ const mx = (coords.x1 + coords.x2) / 2;
756
+ const my = (coords.y1 + coords.y2) / 2;
757
+ const dx = coords.x2 - coords.x1;
758
+ const dy = coords.y2 - coords.y1;
759
+ const len = Math.sqrt(dx * dx + dy * dy);
760
+ if (len < 1) return [];
761
+ const nx = -dy / len;
762
+ const ny = dx / len;
763
+ const markLen = 6;
764
+ return [
765
+ chunkHDKDQAEQ_cjs.el("line", {
766
+ x1: mx - 3 + nx * markLen,
767
+ y1: my - 3 + ny * markLen,
768
+ x2: mx - 3 - nx * markLen,
769
+ y2: my - 3 - ny * markLen,
770
+ class: "schematex-ecomap-eco-line",
771
+ "stroke-width": "2"
772
+ }),
773
+ chunkHDKDQAEQ_cjs.el("line", {
774
+ x1: mx + 3 + nx * markLen,
775
+ y1: my + 3 + ny * markLen,
776
+ x2: mx + 3 - nx * markLen,
777
+ y2: my + 3 - ny * markLen,
778
+ class: "schematex-ecomap-eco-line",
779
+ "stroke-width": "2"
780
+ })
781
+ ];
782
+ }
783
+ function getArrowAttrs(flow) {
784
+ if (!flow || flow === "none") return {};
785
+ switch (flow) {
786
+ case "from":
787
+ return { "marker-end": "url(#schematex-ecomap-eco-arrow)" };
788
+ case "to":
789
+ return { "marker-start": "url(#schematex-ecomap-eco-arrow)" };
790
+ case "mutual":
791
+ return {
792
+ "marker-start": "url(#schematex-ecomap-eco-arrow)",
793
+ "marker-end": "url(#schematex-ecomap-eco-arrow)"
794
+ };
795
+ default:
796
+ return {};
797
+ }
798
+ }
799
+ function capitalize(s) {
800
+ return s.charAt(0).toUpperCase() + s.slice(1);
801
+ }
802
+ function wrapLabel(label, maxChars) {
803
+ if (label.length <= maxChars) return [label];
804
+ const words = label.split(/\s+/);
805
+ const lines = [];
806
+ let current = "";
807
+ for (const word of words) {
808
+ if (current && current.length + word.length + 1 > maxChars) {
809
+ lines.push(current);
810
+ current = word;
811
+ } else {
812
+ current = current ? current + " " + word : word;
813
+ }
814
+ }
815
+ if (current) lines.push(current);
816
+ return lines;
817
+ }
818
+
819
+ // src/diagrams/ecomap/index.ts
820
+ var ecomap = {
821
+ type: "ecomap",
822
+ detect(text2) {
823
+ const firstLine = text2.trim().split("\n")[0]?.trim().toLowerCase() ?? "";
824
+ return firstLine === "ecomap" || firstLine.startsWith("ecomap ");
825
+ },
826
+ render(text2, config) {
827
+ const ast = parseEcomap(text2);
828
+ const layout = layoutEcomap(ast);
829
+ const renderConfig = {
830
+ fontFamily: config?.fontFamily ?? "system-ui, -apple-system, sans-serif",
831
+ fontSize: config?.fontSize ?? 12,
832
+ theme: config?.theme ?? "default",
833
+ padding: config?.padding ?? 20
834
+ };
835
+ return renderEcomap(layout, renderConfig);
836
+ }
837
+ };
838
+
839
+ exports.EcomapParseError = EcomapParseError;
840
+ exports.ecomap = ecomap;
841
+ exports.layoutEcomap = layoutEcomap;
842
+ exports.parseEcomap = parseEcomap;
843
+ exports.renderEcomap = renderEcomap;
844
+ //# sourceMappingURL=chunk-S6BK5DB6.cjs.map
845
+ //# sourceMappingURL=chunk-S6BK5DB6.cjs.map