mind-elixir 5.8.3-beta.1 → 5.9.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.
@@ -1,178 +1,228 @@
1
- const L = `- Root Node
1
+ class x {
2
+ node;
3
+ children = [];
4
+ // slots[i] represents elements that appear *before* children[i]
5
+ // slots[children.length] represents elements that appear *after* all children
6
+ slots;
7
+ constructor(e) {
8
+ this.node = e;
9
+ const s = e.children?.length ?? 0;
10
+ this.slots = Array.from({ length: s + 1 }, () => []);
11
+ }
12
+ }
13
+ function j(a) {
14
+ const { nodeData: e, arrows: s = [], summaries: n = [] } = a, o = /* @__PURE__ */ new Map();
15
+ function r(t) {
16
+ const d = new x(t);
17
+ return o.set(t.id, d), t.children && (d.children = t.children.map(r)), d;
18
+ }
19
+ const i = r(e), l = [], g = /* @__PURE__ */ new Set();
20
+ for (const t of s) {
21
+ g.add(t.from), g.add(t.to);
22
+ const d = t.metadata, u = d?.parentId, p = d?.index ?? 1 / 0;
23
+ if (!u) {
24
+ l.push(t);
25
+ continue;
26
+ }
27
+ const w = o.get(u);
28
+ if (w) {
29
+ const y = Math.min(p, w.children.length);
30
+ w.slots[y].push({ type: "arrow", arrow: t });
31
+ } else
32
+ l.push(t);
33
+ }
34
+ for (const t of n) {
35
+ const d = o.get(t.parent);
36
+ if (d) {
37
+ const u = Math.min(t.end + 1, d.children.length);
38
+ d.slots[u].push({ type: "summary", summary: t });
39
+ }
40
+ }
41
+ function h(t) {
42
+ return o.get(t)?.node.metadata?.refId ?? t;
43
+ }
44
+ const f = [];
45
+ function c(t, d) {
46
+ const u = " ".repeat(d), p = " ".repeat(d + 1), w = t.node.metadata, y = [t.node.topic], M = w?.refId ?? (g.has(t.node.id) ? t.node.id : void 0);
47
+ M && y.push(`[^${M}]`), t.node.style && Object.keys(t.node.style).length > 0 && y.push(JSON.stringify(t.node.style)), f.push(`${u}- ${y.join(" ")}`);
48
+ for (let I = 0; I <= t.children.length; I++) {
49
+ for (const C of t.slots[I])
50
+ if (C.type === "arrow") {
51
+ const m = C.arrow, $ = m.bidirectional ? `<-${m.label ?? ""}->` : `>-${m.label ?? ""}->`;
52
+ f.push(`${p}- > [^${h(m.from)}] ${$} [^${h(m.to)}]`);
53
+ } else if (C.type === "summary") {
54
+ const m = C.summary, $ = m.end - m.start + 1, b = $ === t.children.length ? "" : `:${$} `;
55
+ f.push(`${p}- }${b}${m.label}`);
56
+ }
57
+ I < t.children.length && c(t.children[I], d + 1);
58
+ }
59
+ }
60
+ c(i, 0);
61
+ for (const t of l) {
62
+ const d = t.bidirectional ? `<-${t.label ?? ""}->` : `>-${t.label ?? ""}->`;
63
+ f.push(`- > [^${h(t.from)}] ${d} [^${h(t.to)}]`);
64
+ }
65
+ return f.join(`
66
+ `) + `
67
+ `;
68
+ }
69
+ function N() {
70
+ return ((/* @__PURE__ */ new Date()).getTime().toString(16) + Math.random().toString(16).substring(2)).substring(2, 18);
71
+ }
72
+ const k = `- Root Node
2
73
  - Child Node 1
3
74
  - Child Node 1-1 {"color": "#e87a90", "fontSize": "18px"}
4
75
  - Child Node 1-2
5
76
  - Child Node 1-3
6
77
  - }:2 Summary of first two nodes
7
78
  - Child Node 2
8
- - Child Node 2-1 [^id1]
79
+ - Child Node 2-1 [^node-2-1]
9
80
  - Child Node 2-2 [^id2]
10
81
  - Child Node 2-3
11
- - > [^id1] <-Bidirectional Link-> [^id2]
82
+ - > [^node-2-1] <-Bidirectional Link-> [^id2]
12
83
  - Child Node 3
13
84
  - Child Node 3-1 [^id3]
14
85
  - Child Node 3-2 [^id4]
15
86
  - Child Node 3-3 [^id5] {"fontFamily": "Arial", "fontWeight": "bold"}
16
87
  - > [^id3] >-Unidirectional Link-> [^id4]
17
- - > [^id3] <-Unidirectional Link-< [^id5]
18
88
  - Child Node 4
19
89
  - Child Node 4-1 [^id6]
20
90
  - Child Node 4-2 [^id7]
21
91
  - Child Node 4-3 [^id8]
22
92
  - } Summary of all previous nodes
23
93
  - Child Node 4-4
24
- - > [^id1] <-Link position is not restricted, as long as the id can be found during rendering-> [^id8]
94
+ - > [^node-2-1] <-Link position is not restricted, as long as the id can be found during rendering-> [^id8]
95
+
25
96
  `;
26
- function b(r) {
27
- const e = r.split(`
28
- `).filter((t) => t.trim()), d = {
97
+ function v(a, e = "Root") {
98
+ const s = a.split(`
99
+ `).filter((h) => h.trim());
100
+ if (s.length === 0)
101
+ throw new Error("Failed to parse plaintext: no root node found");
102
+ const n = {
29
103
  arrowLines: [],
30
- summaryLines: [],
31
104
  nodeIdMap: /* @__PURE__ */ new Map()
32
- }, n = y(e, 0, -2, d);
33
- if (!n.node)
105
+ }, o = [], r = [], i = [];
106
+ for (const h of s) {
107
+ const f = S(h), c = T(h);
108
+ for (; r.length > 0 && r[r.length - 1].indent >= f; )
109
+ r.pop();
110
+ const t = r.length > 0 ? r[r.length - 1].node : null, d = t ? t.children ??= [] : i;
111
+ if (c.type === "arrow") {
112
+ n.arrowLines.push({
113
+ content: c.content,
114
+ parentId: t?.id ?? null,
115
+ index: d.length
116
+ });
117
+ continue;
118
+ }
119
+ if (c.type === "summary") {
120
+ const w = O(c.content, d, t?.id ?? "");
121
+ w && o.push(w);
122
+ continue;
123
+ }
124
+ const u = N(), p = {
125
+ topic: c.topic,
126
+ id: u
127
+ };
128
+ c.style && (p.style = c.style), c.refId && (n.nodeIdMap.set(c.refId, u), p.metadata = { refId: c.refId }), d.push(p), r.push({ indent: f, node: p });
129
+ }
130
+ if (i.length === 0)
34
131
  throw new Error("Failed to parse plaintext: no root node found");
35
- const s = d.arrowLines.map(({ content: t }) => N(t, d)).filter((t) => t !== null), o = d.summaryLines.map(({ content: t, parentChildren: i, parentId: l }) => g(t, i, l)).filter((t) => t !== null);
132
+ let l;
133
+ i.length === 1 ? l = i[0] : l = {
134
+ topic: e,
135
+ id: N(),
136
+ children: i
137
+ };
138
+ const g = n.arrowLines.map(({ content: h, parentId: f, index: c }) => {
139
+ const t = R(h, n);
140
+ return t && (t.metadata = { parentId: f, index: c }), t;
141
+ }).filter((h) => h !== null);
36
142
  return {
37
- nodeData: n.node,
38
- arrows: s.length > 0 ? s : void 0,
143
+ nodeData: l,
144
+ arrows: g.length > 0 ? g : void 0,
39
145
  summaries: o.length > 0 ? o : void 0
40
146
  };
41
147
  }
42
- function y(r, e, d, n) {
43
- if (e >= r.length)
44
- return { node: null, nextIndex: e };
45
- const s = r[e], o = I(s);
46
- if (o <= d)
47
- return { node: null, nextIndex: e };
48
- const t = w(s);
49
- if (t.type === "arrow" || t.type === "summary")
50
- return { node: null, nextIndex: e + 1 };
51
- const i = u(), l = {
52
- topic: t.topic,
53
- id: i
54
- };
55
- t.style && (l.style = t.style), t.refId && n.nodeIdMap.set(t.refId, i);
56
- const c = [];
57
- let a = e + 1;
58
- for (; a < r.length; ) {
59
- const m = r[a], p = I(m);
60
- if (p <= o)
61
- break;
62
- if (p === o + 2) {
63
- const f = w(m);
64
- if (f.type === "arrow")
65
- n.arrowLines.push({
66
- content: f.content,
67
- parentChildren: c
68
- }), a++;
69
- else if (f.type === "summary")
70
- n.summaryLines.push({
71
- content: f.content,
72
- parentChildren: c,
73
- parentId: i
74
- // Pass parent node ID
75
- }), a++;
76
- else {
77
- const h = y(r, a, o, n);
78
- h.node && c.push(h.node), a = h.nextIndex;
79
- }
80
- } else
81
- a++;
82
- }
83
- return c.length > 0 && (l.children = c), { node: l, nextIndex: a };
84
- }
85
- function I(r) {
86
- const e = r.match(/^(\s*)/);
148
+ function S(a) {
149
+ const e = a.match(/^(\s*)/);
87
150
  return e ? e[1].length : 0;
88
151
  }
89
- function C(r) {
152
+ function L(a) {
90
153
  try {
91
- const e = r.trim().startsWith("{") ? r : `{${r}}`;
154
+ const e = a.trim().startsWith("{") ? a : `{${a}}`;
92
155
  return JSON.parse(e);
93
156
  } catch {
94
157
  return {};
95
158
  }
96
159
  }
97
- function w(r) {
98
- const d = r.trim().replace(/^-\s*/, "");
99
- if (d.startsWith(">"))
160
+ function T(a) {
161
+ const s = a.trim().replace(/^-\s*/, "");
162
+ if (s.startsWith(">"))
100
163
  return {
101
164
  type: "arrow",
102
165
  topic: "",
103
- content: d.substring(1).trim()
166
+ content: s.substring(1).trim()
104
167
  };
105
- if (d.startsWith("}"))
168
+ if (s.startsWith("}"))
106
169
  return {
107
170
  type: "summary",
108
171
  topic: "",
109
- content: d.substring(1).trim()
172
+ content: s.substring(1).trim()
110
173
  };
111
- let n = d, s, o;
112
- const t = n.match(/\[\^(\w+)\]/);
113
- t && (s = t[1], n = n.replace(t[0], "").trim());
114
- const i = n.match(/\{([^}]+)\}/);
115
- return i && (o = C(i[1]), n = n.replace(i[0], "").trim()), {
174
+ let n = s, o, r;
175
+ const i = n.match(/\[\^([\w-]+)\]/);
176
+ i && (o = i[1], n = n.replace(i[0], "").trim());
177
+ const l = n.match(/\{([^}]+)\}/);
178
+ return l && (r = L(l[1]), n = n.replace(l[0], "").trim()), {
116
179
  type: "node",
117
180
  topic: n,
118
181
  content: n,
119
- refId: s,
120
- style: o
182
+ refId: o,
183
+ style: r
121
184
  };
122
185
  }
123
- function N(r, e) {
124
- const d = r.match(/\[\^(\w+)\]\s*<-([^-]*)->\s*\[\^(\w+)\]/);
125
- if (d) {
126
- const o = d[1], t = d[2].trim(), i = d[3];
186
+ function R(a, e) {
187
+ const s = a.match(/\[\^([\w-]+)\]\s*<-([^-]*)->\s*\[\^([\w-]+)\]/);
188
+ if (s) {
189
+ const o = s[1], r = s[2].trim(), i = s[3];
127
190
  return {
128
- id: u(),
129
- label: t,
191
+ id: N(),
192
+ label: r,
130
193
  from: e.nodeIdMap.get(o) || o,
131
194
  to: e.nodeIdMap.get(i) || i,
132
195
  bidirectional: !0
133
196
  };
134
197
  }
135
- const n = r.match(/\[\^(\w+)\]\s*>-([^-]*)->\s*\[\^(\w+)\]/);
198
+ const n = a.match(/\[\^([\w-]+)\]\s*>-([^-]*)->\s*\[\^([\w-]+)\]/);
136
199
  if (n) {
137
- const o = n[1], t = n[2].trim(), i = n[3];
200
+ const o = n[1], r = n[2].trim(), i = n[3];
138
201
  return {
139
- id: u(),
140
- label: t,
141
- from: e.nodeIdMap.get(o) || o,
142
- to: e.nodeIdMap.get(i) || i
143
- };
144
- }
145
- const s = r.match(/\[\^(\w+)\]\s*<-([^-]*)-<\s*\[\^(\w+)\]/);
146
- if (s) {
147
- const o = s[3], t = s[2].trim(), i = s[1];
148
- return {
149
- id: u(),
150
- label: t,
202
+ id: N(),
203
+ label: r,
151
204
  from: e.nodeIdMap.get(o) || o,
152
205
  to: e.nodeIdMap.get(i) || i
153
206
  };
154
207
  }
155
208
  return null;
156
209
  }
157
- function g(r, e, d) {
158
- const n = r.match(/^:(\d+)\s+(.*)/);
159
- let s, o;
160
- if (n ? (s = parseInt(n[1], 10), o = n[2]) : (s = e.length, o = r.trim()), e.length === 0 || s === 0)
210
+ function O(a, e, s) {
211
+ const n = a.match(/^:(\d+)\s+(.*)/);
212
+ let o, r;
213
+ if (n ? (o = parseInt(n[1], 10), r = n[2]) : (o = e.length, r = a.trim()), e.length === 0 || o === 0)
161
214
  return null;
162
- const t = e.slice(-s), i = e.indexOf(t[0]), l = e.indexOf(t[t.length - 1]);
215
+ const i = e.slice(-o), l = e.indexOf(i[0]), g = e.indexOf(i[i.length - 1]);
163
216
  return {
164
- id: u(),
165
- label: o,
166
- parent: d,
167
- start: i,
168
- end: l
217
+ id: N(),
218
+ label: r,
219
+ parent: s,
220
+ start: l,
221
+ end: g
169
222
  };
170
223
  }
171
- let M = 0;
172
- function u() {
173
- return `node-${Date.now()}-${M++}`;
174
- }
175
224
  export {
176
- L as plaintextExample,
177
- b as plaintextToMindElixir
225
+ j as mindElixirToPlaintext,
226
+ k as plaintextExample,
227
+ v as plaintextToMindElixir
178
228
  };
@@ -26,7 +26,7 @@ export interface ArrowStyle {
26
26
  */
27
27
  labelColor?: string;
28
28
  }
29
- export interface Arrow {
29
+ export interface Arrow<M = unknown> {
30
30
  id: string;
31
31
  /**
32
32
  * label of arrow
@@ -62,6 +62,10 @@ export interface Arrow {
62
62
  * style properties for the arrow
63
63
  */
64
64
  style?: ArrowStyle;
65
+ /**
66
+ * Generic metadata for the arrow, can be used to store any custom data.
67
+ */
68
+ metadata?: M;
65
69
  }
66
70
  export interface DivData {
67
71
  cx: number;
@@ -26,10 +26,10 @@ declare namespace MindElixir {
26
26
  selectArrow: (this: MindElixirInstance, link: import("./docs").CustomSvg) => void;
27
27
  unselectArrow: (this: MindElixirInstance) => void;
28
28
  rmSubline: (this: MindElixirInstance, tpc: Topic) => Promise<void>;
29
- reshapeNode: (this: MindElixirInstance, tpc: Topic, patchData: Partial<import("./docs").NodeObj>) => Promise<void>;
30
- insertSibling: (this: MindElixirInstance, type: "before" | "after", el?: Topic | undefined, node?: import("./docs").NodeObj | undefined) => Promise<void>;
31
- insertParent: (this: MindElixirInstance, el?: Topic | undefined, node?: import("./docs").NodeObj | undefined) => Promise<void>;
32
- addChild: (this: MindElixirInstance, el?: Topic | undefined, node?: import("./docs").NodeObj | undefined) => Promise<void>;
29
+ reshapeNode: (this: MindElixirInstance, tpc: Topic, patchData: Partial<import("./docs").NodeObj<unknown>>) => Promise<void>;
30
+ insertSibling: (this: MindElixirInstance, type: "before" | "after", el?: Topic | undefined, node?: import("./docs").NodeObj<unknown> | undefined) => Promise<void>;
31
+ insertParent: (this: MindElixirInstance, el?: Topic | undefined, node?: import("./docs").NodeObj<unknown> | undefined) => Promise<void>;
32
+ addChild: (this: MindElixirInstance, el?: Topic | undefined, node?: import("./docs").NodeObj<unknown> | undefined) => Promise<void>;
33
33
  copyNode: (this: MindElixirInstance, node: Topic, to: Topic) => Promise<void>;
34
34
  copyNodes: (this: MindElixirInstance, tpcs: Topic[], to: Topic) => Promise<void>;
35
35
  moveUpNode: (this: MindElixirInstance, el?: Topic | undefined) => Promise<void>;
@@ -31,10 +31,10 @@ declare const methods: {
31
31
  selectArrow: (this: MindElixirInstance, link: import("./docs").CustomSvg) => void;
32
32
  unselectArrow: (this: MindElixirInstance) => void;
33
33
  rmSubline: (this: MindElixirInstance, tpc: import("./docs").Topic) => Promise<void>;
34
- reshapeNode: (this: MindElixirInstance, tpc: import("./docs").Topic, patchData: Partial<import("./types").NodeObj>) => Promise<void>;
35
- insertSibling: (this: MindElixirInstance, type: "before" | "after", el?: import("./docs").Topic | undefined, node?: import("./types").NodeObj | undefined) => Promise<void>;
36
- insertParent: (this: MindElixirInstance, el?: import("./docs").Topic | undefined, node?: import("./types").NodeObj | undefined) => Promise<void>;
37
- addChild: (this: MindElixirInstance, el?: import("./docs").Topic | undefined, node?: import("./types").NodeObj | undefined) => Promise<void>;
34
+ reshapeNode: (this: MindElixirInstance, tpc: import("./docs").Topic, patchData: Partial<import("./types").NodeObj<unknown>>) => Promise<void>;
35
+ insertSibling: (this: MindElixirInstance, type: "before" | "after", el?: import("./docs").Topic | undefined, node?: import("./types").NodeObj<unknown> | undefined) => Promise<void>;
36
+ insertParent: (this: MindElixirInstance, el?: import("./docs").Topic | undefined, node?: import("./types").NodeObj<unknown> | undefined) => Promise<void>;
37
+ addChild: (this: MindElixirInstance, el?: import("./docs").Topic | undefined, node?: import("./types").NodeObj<unknown> | undefined) => Promise<void>;
38
38
  copyNode: (this: MindElixirInstance, node: import("./docs").Topic, to: import("./docs").Topic) => Promise<void>;
39
39
  copyNodes: (this: MindElixirInstance, tpcs: import("./docs").Topic[], to: import("./docs").Topic) => Promise<void>;
40
40
  moveUpNode: (this: MindElixirInstance, el?: import("./docs").Topic | undefined) => Promise<void>;
@@ -180,7 +180,7 @@ export interface TagObj {
180
180
  *
181
181
  * @public
182
182
  */
183
- export interface NodeObj {
183
+ export interface NodeObj<M = unknown> {
184
184
  topic: string;
185
185
  id: Uid;
186
186
  style?: Partial<{
@@ -225,6 +225,10 @@ export interface NodeObj {
225
225
  * Extra data for the node, which can be used to store any custom data.
226
226
  */
227
227
  note?: string;
228
+ /**
229
+ * Generic metadata for the node, can be used to store any custom data.
230
+ */
231
+ metadata?: M;
228
232
  }
229
233
  export type NodeObjExport = Omit<NodeObj, 'parent'>;
230
234
  /**
@@ -0,0 +1,8 @@
1
+ import type { MindElixirData } from '../types';
2
+ /**
3
+ * Convert MindElixirData back to plaintext format
4
+ *
5
+ * @param data - The MindElixirData object to convert
6
+ * @returns Plaintext string
7
+ */
8
+ export declare function mindElixirToPlaintext(data: MindElixirData): string;
@@ -1,18 +1,2 @@
1
- import type { MindElixirData } from '../types';
2
- export declare const plaintextExample = "- Root Node\n - Child Node 1\n - Child Node 1-1 {\"color\": \"#e87a90\", \"fontSize\": \"18px\"}\n - Child Node 1-2\n - Child Node 1-3\n - }:2 Summary of first two nodes\n - Child Node 2\n - Child Node 2-1 [^id1]\n - Child Node 2-2 [^id2]\n - Child Node 2-3\n - > [^id1] <-Bidirectional Link-> [^id2]\n - Child Node 3\n - Child Node 3-1 [^id3]\n - Child Node 3-2 [^id4]\n - Child Node 3-3 [^id5] {\"fontFamily\": \"Arial\", \"fontWeight\": \"bold\"}\n - > [^id3] >-Unidirectional Link-> [^id4]\n - > [^id3] <-Unidirectional Link-< [^id5]\n - Child Node 4\n - Child Node 4-1 [^id6]\n - Child Node 4-2 [^id7]\n - Child Node 4-3 [^id8]\n - } Summary of all previous nodes\n - Child Node 4-4\n - > [^id1] <-Link position is not restricted, as long as the id can be found during rendering-> [^id8]\n";
3
- /**
4
- * Convert plaintext format to MindElixirData
5
- *
6
- * Format:
7
- * - Root node
8
- * - Child 1
9
- * - Child 1-1 [^id1]
10
- * - Child 1-2 {"color": "#e87a90", "fontSize": "18px", "fontFamily": "Arial"}
11
- * - }:2 Summary of first two nodes
12
- * - Child 2 [^id2]
13
- * - > [^id1] <-label-> [^id2]
14
- *
15
- * @param plaintext - The plaintext string to convert
16
- * @returns MindElixirData object
17
- */
18
- export declare function plaintextToMindElixir(plaintext: string): MindElixirData;
1
+ export * from './mindElixirToPlaintext';
2
+ export * from './plaintextToMindElixir';
@@ -0,0 +1,30 @@
1
+ import type { MindElixirData } from '../types';
2
+ export interface NodePlaintextMeta {
3
+ refId: string;
4
+ }
5
+ export interface ArrowPlaintextMeta {
6
+ parentId: string | null;
7
+ index: number;
8
+ }
9
+ export declare const plaintextExample = "- Root Node\n - Child Node 1\n - Child Node 1-1 {\"color\": \"#e87a90\", \"fontSize\": \"18px\"}\n - Child Node 1-2\n - Child Node 1-3\n - }:2 Summary of first two nodes\n - Child Node 2\n - Child Node 2-1 [^node-2-1]\n - Child Node 2-2 [^id2]\n - Child Node 2-3\n - > [^node-2-1] <-Bidirectional Link-> [^id2]\n - Child Node 3\n - Child Node 3-1 [^id3]\n - Child Node 3-2 [^id4]\n - Child Node 3-3 [^id5] {\"fontFamily\": \"Arial\", \"fontWeight\": \"bold\"}\n - > [^id3] >-Unidirectional Link-> [^id4]\n - Child Node 4\n - Child Node 4-1 [^id6]\n - Child Node 4-2 [^id7]\n - Child Node 4-3 [^id8]\n - } Summary of all previous nodes\n - Child Node 4-4\n- > [^node-2-1] <-Link position is not restricted, as long as the id can be found during rendering-> [^id8]\n\n";
10
+ /**
11
+ * Convert plaintext format to MindElixirData
12
+ *
13
+ * Format:
14
+ * - Root node
15
+ * - Child 1
16
+ * - Child 1-1 [^id1]
17
+ * - Child 1-2 {"color": "#e87a90", "fontSize": "18px", "fontFamily": "Arial"}
18
+ * - }:2 Summary of first two nodes
19
+ * - Child 2 [^id2]
20
+ * - > [^id1] <-label-> [^id2]
21
+ *
22
+ * When the plaintext contains more than one top-level node, a synthetic root
23
+ * node is automatically created to wrap them as first-level children.
24
+ *
25
+ * @param plaintext - The plaintext string to convert
26
+ * @param rootName - Optional name for the synthetic root node when multiple
27
+ * top-level nodes are detected (defaults to 'Root')
28
+ * @returns MindElixirData object
29
+ */
30
+ export declare function plaintextToMindElixir(plaintext: string, rootName?: string): MindElixirData;