mind-elixir
Version:
Mind elixir is a free open source mind map core.
222 lines (221 loc) • 6.99 kB
JavaScript
//#region src/utils/mindElixirToPlaintext.ts
var e = class {
node;
children = [];
slots;
constructor(e) {
this.node = e;
let t = e.children?.length ?? 0;
this.slots = Array.from({ length: t + 1 }, () => []);
}
};
function t(t) {
let { nodeData: n, arrows: r = [], summaries: i = [] } = t, a = /* @__PURE__ */ new Map();
function o(t) {
let n = new e(t);
return a.set(t.id, n), t.children && (n.children = t.children.map(o)), n;
}
let s = o(n), c = [], l = /* @__PURE__ */ new Set();
for (let e of r) {
l.add(e.from), l.add(e.to);
let t = e.metadata, n = t?.parentId, r = t?.index ?? Infinity;
if (!n) {
c.push(e);
continue;
}
let i = a.get(n);
if (i) {
let t = Math.min(r, i.children.length);
i.slots[t].push({
type: "arrow",
arrow: e
});
} else c.push(e);
}
for (let e of i) {
let t = a.get(e.parent);
if (t) {
let n = Math.min(e.end + 1, t.children.length);
t.slots[n].push({
type: "summary",
summary: e
});
}
}
function u(e) {
return a.get(e)?.node.metadata?.refId ?? e;
}
let d = [];
function f(e, t) {
let n = " ".repeat(t), r = " ".repeat(t + 1), i = e.node.metadata, a = [e.node.topic], o = i?.refId ?? (l.has(e.node.id) ? e.node.id : void 0);
o && a.push(`[^${o}]`), e.node.style && Object.keys(e.node.style).length > 0 && a.push(JSON.stringify(e.node.style)), d.push(`${n}- ${a.join(" ")}`);
for (let n = 0; n <= e.children.length; n++) {
for (let t of e.slots[n]) if (t.type === "arrow") {
let e = t.arrow, n = e.bidirectional ? `<-${e.label ?? ""}->` : `>-${e.label ?? ""}->`, i = e.delta1 ? ` (${e.delta1.x},${e.delta1.y})` : "", a = e.delta2 ? ` (${e.delta2.x},${e.delta2.y})` : "";
d.push(`${r}- > [^${u(e.from)}]${i} ${n}${a} [^${u(e.to)}]`);
} else if (t.type === "summary") {
let n = t.summary, i = n.end - n.start + 1, a = i === e.children.length ? "" : `:${i} `;
d.push(`${r}- }${a}${n.label}`);
}
n < e.children.length && f(e.children[n], t + 1);
}
}
f(s, 0);
for (let e of c) {
let t = e.bidirectional ? `<-${e.label ?? ""}->` : `>-${e.label ?? ""}->`, n = e.delta1 ? ` (${e.delta1.x},${e.delta1.y})` : "", r = e.delta2 ? ` (${e.delta2.x},${e.delta2.y})` : "";
d.push(`- > [^${u(e.from)}]${n} ${t}${r} [^${u(e.to)}]`);
}
return d.join("\n") + "\n";
}
//#endregion
//#region src/utils/index.ts
function n() {
return Date.now().toString(36) + Math.random().toString(36).substring(2, 8);
}
//#endregion
//#region src/utils/plaintextToMindElixir.ts
var r = "- 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";
function i(e, t = "Root") {
let r = e.split("\n").filter((e) => e.trim());
if (r.length === 0) throw Error("Failed to parse plaintext: no root node found");
let i = {
arrowLines: [],
nodeIdMap: /* @__PURE__ */ new Map()
}, o = [], u = [], d = [];
for (let e of r) {
let t = a(e), r = s(e);
for (; u.length > 0 && u[u.length - 1].indent >= t;) u.pop();
let c = u.length > 0 ? u[u.length - 1].node : null, f = c ? c.children ??= [] : d;
if (r.type === "arrow") {
i.arrowLines.push({
content: r.content,
parentId: c?.id ?? null,
index: f.length
});
continue;
}
if (r.type === "summary") {
let e = l(r.content, f, c?.id ?? "");
e && o.push(e);
continue;
}
let p = n(), m = {
topic: r.topic,
id: p
};
r.style && (m.style = r.style), r.refId && (i.nodeIdMap.set(r.refId, p), m.metadata = { refId: r.refId }), f.push(m), u.push({
indent: t,
node: m
});
}
if (d.length === 0) throw Error("Failed to parse plaintext: no root node found");
let f;
f = d.length === 1 ? d[0] : {
topic: t,
id: n(),
children: d
};
let p = i.arrowLines.map(({ content: e, parentId: t, index: n }) => {
let r = c(e, i);
return r && (r.metadata = {
parentId: t,
index: n
}), r;
}).filter((e) => e !== null);
return {
nodeData: f,
arrows: p.length > 0 ? p : void 0,
summaries: o.length > 0 ? o : void 0
};
}
function a(e) {
let t = e.match(/^(\s*)/);
return t ? t[1].length : 0;
}
function o(e) {
try {
return JSON.parse(e);
} catch {
return console.warn(`[plaintext] Invalid node style (must be valid JSON), ignored: ${e}`), null;
}
}
function s(e) {
let t = e.trim().replace(/^-\s*/, "");
if (t.startsWith(">")) return {
type: "arrow",
topic: "",
content: t.substring(1).trim()
};
if (t.startsWith("}")) return {
type: "summary",
topic: "",
content: t.substring(1).trim()
};
let n = t, r, i, a = n.match(/\s*(\{[^}]+\})\s*$/);
if (a) {
let e = o(a[1]);
e && (i = e, n = n.substring(0, n.length - a[0].length).trim());
}
let s = n.match(/\s*\[\^([\w-]+)\]\s*$/);
return s && (r = s[1], n = n.substring(0, n.length - s[0].length).trim()), {
type: "node",
topic: n,
content: n,
refId: r,
style: i
};
}
function c(e, t) {
let r = e.match(/\[\^([\w-]+)\](?:\s*\(([\d.-]+),([\d.-]+)\))?\s*<-([^-]*)->(?:\s*\(([\d.-]+),([\d.-]+)\))?\s*\[\^([\w-]+)\]/);
if (r) {
let e = r[1], i = r[2], a = r[3], o = r[4].trim(), s = r[5], c = r[6], l = r[7];
return {
id: n(),
label: o,
from: t.nodeIdMap.get(e) || e,
to: t.nodeIdMap.get(l) || l,
delta1: i && a ? {
x: Number(i),
y: Number(a)
} : void 0,
delta2: s && c ? {
x: Number(s),
y: Number(c)
} : void 0,
bidirectional: !0
};
}
let i = e.match(/\[\^([\w-]+)\](?:\s*\(([\d.-]+),([\d.-]+)\))?\s*>-([^-]*)->(?:\s*\(([\d.-]+),([\d.-]+)\))?\s*\[\^([\w-]+)\]/);
if (i) {
let e = i[1], r = i[2], a = i[3], o = i[4].trim(), s = i[5], c = i[6], l = i[7];
return {
id: n(),
label: o,
from: t.nodeIdMap.get(e) || e,
to: t.nodeIdMap.get(l) || l,
delta1: r && a ? {
x: Number(r),
y: Number(a)
} : void 0,
delta2: s && c ? {
x: Number(s),
y: Number(c)
} : void 0
};
}
return null;
}
function l(e, t, r) {
let i = e.match(/^:(\d+)\s+(.*)/), a, o;
if (i ? (a = parseInt(i[1], 10), o = i[2]) : (a = t.length, o = e.trim()), t.length === 0 || a === 0) return null;
let s = t.slice(-a), c = t.indexOf(s[0]), l = t.indexOf(s[s.length - 1]);
return {
id: n(),
label: o,
parent: r,
start: c,
end: l
};
}
//#endregion
export { t as mindElixirToPlaintext, r as plaintextExample, i as plaintextToMindElixir };