diff --git a/src/importreport.test.ts b/src/importreport.test.ts
index fe7cd21..58736b3 100644
--- a/src/importreport.test.ts
+++ b/src/importreport.test.ts
@@ -124,3 +124,15 @@ test("XMind 7 boundaries are read too", async () => {
expect(roots[0].bounds).toEqual([roots[0].children[1].id, ...roots[0].children.map((k) => k.id)]); // "(0,)" runs to the last child
expect(lost).toEqual(["boundary titles dropped", "boundaries over several topics drawn around each topic"]);
});
+
+test("a structure set on a single topic is reported, one equal to the sheet's is not", async () => {
+ const sheet = [{ id: "s", class: "sheet", title: "S", rootTopic: { id: "r", title: "root", structureClass: "org.xmind.ui.map.clockwise", children: { attached: [
+ { id: "a", title: "A", structureClass: "org.xmind.ui.org-chart.down", children: { attached: [{ id: "a1", title: "A1", structureClass: "org.xmind.ui.org-chart.down" }] } },
+ { id: "b", title: "B", structureClass: "org.xmind.ui.map.clockwise" },
+ ] } } }];
+ const { lost } = await importXmindReport(zip({ "content.json": JSON.stringify(sheet) }));
+ expect(lost).toEqual(["2 × structures set on individual topics dropped"]);
+ const xml = `r
+ ab`;
+ expect((await importXmindReport(zip({ "content.xml": xml }))).lost).toEqual(["structures set on individual topics dropped"]);
+});
diff --git a/src/xmind.ts b/src/xmind.ts
index 539fc95..fee2c93 100644
--- a/src/xmind.ts
+++ b/src/xmind.ts
@@ -192,7 +192,7 @@ const picturesOf = (files: Map, rep: Report): Pictures => (t
};
/** Summaries and boundaries found while reading topics; both live on the root of a sheet. */
-type Acc = { sums: Summary[]; bounds: string[] };
+type Acc = { sums: Summary[]; bounds: string[]; rootClass?: string };
/** "(2,4)" -> [2, 4]: the first and last summarised child. */
const rangeOf = (r: string | undefined) => {
@@ -201,6 +201,8 @@ const rangeOf = (r: string | undefined) => {
};
const fromX = (t: XTopic, ids: Map, rep: Report, acc: Acc, pic: Pictures, isRoot = false): Node => {
+ if (isRoot) acc.rootClass = t.structureClass;
+ else if (t.structureClass && t.structureClass !== acc.rootClass) rep.add("structures set on individual topics dropped");
const children = (t.children?.attached ?? []).map((c) => fromX(c, ids, rep, acc, pic));
// Floating topics hang off the central topic; elsewhere XMind has none and neither do we.
const floating = t.children?.detached ?? [];
diff --git a/src/xmindxml.ts b/src/xmindxml.ts
index 734e794..b876cc0 100644
--- a/src/xmindxml.ts
+++ b/src/xmindxml.ts
@@ -142,9 +142,10 @@ export function resolveTopicLinks(roots: Node[], ids: Map) {
roots.forEach(fix);
}
-function topicFromXml(t: XNode, ids: Map, rep: Report, bounds: string[]): Node {
+function topicFromXml(t: XNode, ids: Map, rep: Report, bounds: string[], rootClass?: string): Node {
+ if (rootClass !== undefined && t.attrs["structure-class"] && t.attrs["structure-class"] !== rootClass) rep.add("structures set on individual topics dropped");
const attached = kid(t, "children")?.children.find((c) => c.name === "topics" && (c.attrs.type ?? "attached") === "attached");
- const children = (attached?.children ?? []).filter((c) => c.name === "topic").map((c) => topicFromXml(c, ids, rep, bounds));
+ const children = (attached?.children ?? []).filter((c) => c.name === "topic").map((c) => topicFromXml(c, ids, rep, bounds, rootClass ?? t.attrs["structure-class"] ?? ""));
const subs = kid(t, "children")?.children.filter((c) => c.name === "topics") ?? [];
rep.add("floating topics dropped", subs.filter((c) => c.attrs.type === "detached").reduce((n, c) => n + c.children.length, 0));
rep.add("summaries dropped", subs.filter((c) => c.attrs.type === "summary").reduce((n, c) => n + c.children.length, 0));