From ef717e73137e7ce0c0f699bbfa4fc2da461fce37 Mon Sep 17 00:00:00 2001 From: Ralph Amissah Date: Wed, 22 Apr 2026 15:28:10 -0400 Subject: add children_headings to document abstraction Add int[] children_headings field to DocObj_MetaInfo_ and compute it in the post-processing pass of metadoc_from_src.d, right after last_descendant_ocn. Single O(n) pass builds a parent_ocn -> child heading OCNs map, then assigns to each heading object. Useful for tree-structured output. The .ssp serializer now reads directly from the abstraction field instead of pre-computing its own map. metadoc_object_setter.d: +1 line (field declaration) metadoc_from_src.d: +17 lines (computation) create_abstraction_txt.d: -10 lines (simplified) Co-Authored-By: Anthropic Claude Opus 4.6 (1M context) --- src/sisudoc/io_out/create_abstraction_txt.d | 14 ++------------ src/sisudoc/meta/metadoc_from_src.d | 19 +++++++++++++++++++ src/sisudoc/meta/metadoc_object_setter.d | 1 + 3 files changed, 22 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/sisudoc/io_out/create_abstraction_txt.d b/src/sisudoc/io_out/create_abstraction_txt.d index f92b83c..af98f61 100644 --- a/src/sisudoc/io_out/create_abstraction_txt.d +++ b/src/sisudoc/io_out/create_abstraction_txt.d @@ -162,16 +162,6 @@ template spineAbstractionTxt() { output ~= "}"; output ~= ""; - /+ ↓ pre-compute heading children map (one pass over body) +/ - int[][int] heading_children; // parent_ocn -> [child heading OCNs] - if ("body" in doc_abstraction) { - foreach (obj; doc_abstraction["body"]) { - if (obj.metainfo.is_a == "heading" && obj.metainfo.parent_ocn != 0) { - heading_children[obj.metainfo.parent_ocn] ~= obj.metainfo.ocn; - } - } - } - /+ ↓ document sections +/ string[] section_order = ["head", "toc", "body", "endnotes", "glossary", "bibliography", "bookindex", "blurb"]; @@ -212,9 +202,9 @@ template spineAbstractionTxt() { output ~= ".last_descendant: " ~ obj.metainfo.last_descendant_ocn.to!string; /+ ↓ child headings (from pre-computed map) +/ - if (obj.metainfo.is_a == "heading" && obj.metainfo.ocn in heading_children) { + if (obj.metainfo.children_headings.length > 0) { string[] ch; - foreach (c; heading_children[obj.metainfo.ocn]) { + foreach (c; obj.metainfo.children_headings) { ch ~= c.to!string; } output ~= ".children: " ~ ch.join(" "); diff --git a/src/sisudoc/meta/metadoc_from_src.d b/src/sisudoc/meta/metadoc_from_src.d index a4388fb..4967c1f 100644 --- a/src/sisudoc/meta/metadoc_from_src.d +++ b/src/sisudoc/meta/metadoc_from_src.d @@ -1331,6 +1331,25 @@ template docAbstraction() { } } } + /+ ↓ compute children_headings for heading objects +/ + { + int[][int] heading_children; + foreach (obj; the_document_body_section) { + if (obj.metainfo.is_a == "heading" && obj.metainfo.parent_ocn != 0) { + heading_children[obj.metainfo.parent_ocn] ~= obj.metainfo.ocn; + } + } + foreach (ref obj; the_document_head_section) { + if (obj.metainfo.is_a == "heading" && obj.metainfo.ocn in heading_children) { + obj.metainfo.children_headings = heading_children[obj.metainfo.ocn]; + } + } + foreach (ref obj; the_document_body_section) { + if (obj.metainfo.is_a == "heading" && obj.metainfo.ocn in heading_children) { + obj.metainfo.children_headings = heading_children[obj.metainfo.ocn]; + } + } + } // TODO // - note create/insert heading object sole purpose eof close all open tags // sort out: diff --git a/src/sisudoc/meta/metadoc_object_setter.d b/src/sisudoc/meta/metadoc_object_setter.d index bd4f7c8..018c51b 100644 --- a/src/sisudoc/meta/metadoc_object_setter.d +++ b/src/sisudoc/meta/metadoc_object_setter.d @@ -173,6 +173,7 @@ template ObjectSetter() { int parent_lev_markup = 0; int parent_ocn = 0; int last_descendant_ocn = 0; + int[] children_headings; ubyte[32] sha256; } struct ObjGenericComposite { -- cgit v1.2.3