From 249e8d2d61f3650d934582b65200ca8fa0b47495 Mon Sep 17 00:00:00 2001
From: Ralph Amissah <ralph@amissah.com>
Date: Thu, 29 Dec 2016 20:36:41 -0500
Subject: dom structure, levels marked up & collapsed (use e.g. in epub toc)

---
 src/sdp.d                        |  49 ++--
 src/sdp/ao_abstract_doc_source.d | 534 ++++++++++++++++++++++++++++++++++-----
 src/sdp/ao_object_setter.d       |   5 +
 src/sdp/ao_output_debugs.d       |  93 ++++++-
 src/sdp/ao_rgx.d                 |   2 +-
 src/sdp/output_html.d            | 134 +++++++---
 6 files changed, 686 insertions(+), 131 deletions(-)

(limited to 'src')

diff --git a/src/sdp.d b/src/sdp.d
index ff9128f..5ec249b 100755
--- a/src/sdp.d
+++ b/src/sdp.d
@@ -218,50 +218,39 @@ void main(string[] args) {
       auto doc_ao_contents = t[0]; // head ~ toc ~ contents ~ endnotes_seg ~ glossary ~ bibliography ~ bookindex ~blurb;
       auto doc_html_segnames = t[1];
       string[][string] document_section_keys_sequenced = [
-        "seg": [
-           "head",
-           "toc_seg",
-           "body",
-         ],
-         "scroll": [
-           "head",
-           "toc_scroll",
-           "body",
-         ]
+        "seg": ["head", "toc_seg", "body",],
+        "scroll": ["head", "toc_scroll", "body",]
       ];
       if (doc_ao_contents["endnotes_seg"].length > 1) {
-        document_section_keys_sequenced["seg"] =
-          document_section_keys_sequenced["seg"] ~= "endnotes_seg";
+        document_section_keys_sequenced["seg"] ~= "endnotes_seg";
       }
       if (doc_ao_contents["endnotes_scroll"].length > 1) {
-        document_section_keys_sequenced["scroll"] =
-          document_section_keys_sequenced["scroll"] ~= "endnotes_scroll";
+        document_section_keys_sequenced["scroll"] ~= "endnotes_scroll";
       }
       if (doc_ao_contents["glossary"].length > 1) {
-        document_section_keys_sequenced["seg"] =
-          document_section_keys_sequenced["seg"] ~= "glossary";
-        document_section_keys_sequenced["scroll"] =
-          document_section_keys_sequenced["scroll"] ~= "glossary";
+        document_section_keys_sequenced["seg"] ~= "glossary";
+        document_section_keys_sequenced["scroll"] ~= "glossary";
       }
       if (doc_ao_contents["bibliography"].length > 1) {
-        document_section_keys_sequenced["seg"] =
-          document_section_keys_sequenced["seg"] ~= "bibliography";
-        document_section_keys_sequenced["scroll"] =
-          document_section_keys_sequenced["scroll"] ~= "bibliography";
+        document_section_keys_sequenced["seg"] ~= "bibliography";
+        document_section_keys_sequenced["scroll"] ~= "bibliography";
       }
       if (doc_ao_contents["bookindex_seg"].length > 1) {
-        document_section_keys_sequenced["seg"] =
-          document_section_keys_sequenced["seg"] ~= "bookindex_seg";
+        document_section_keys_sequenced["seg"] ~= "bookindex_seg";
       }
       if (doc_ao_contents["bookindex_scroll"].length > 1) {
-        document_section_keys_sequenced["scroll"] =
-          document_section_keys_sequenced["scroll"] ~= "bookindex_scroll";
+        document_section_keys_sequenced["scroll"] ~= "bookindex_scroll";
       }
       if (doc_ao_contents["blurb"].length > 1) {
-        document_section_keys_sequenced["seg"] =
-          document_section_keys_sequenced["seg"] ~= "blurb";
-        document_section_keys_sequenced["scroll"] =
-          document_section_keys_sequenced["scroll"] ~= "blurb";
+        document_section_keys_sequenced["seg"] ~= "blurb";
+        document_section_keys_sequenced["scroll"] ~= "blurb";
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        document_section_keys_sequenced["seg"] ~= "tail";
+        document_section_keys_sequenced["scroll"] ~= "tail";
       }
       /+ ↓ debugs +/
       debug(checkdoc) {
diff --git a/src/sdp/ao_abstract_doc_source.d b/src/sdp/ao_abstract_doc_source.d
index 0697ae4..c11ee4a 100644
--- a/src/sdp/ao_abstract_doc_source.d
+++ b/src/sdp/ao_abstract_doc_source.d
@@ -19,6 +19,7 @@ template SiSUdocAbstraction() {
     auto rgx = Rgx();
     ObjGenericComposite[][string] the_table_of_contents_section;
     ObjGenericComposite[] the_document_head_section, the_document_body_section, the_bibliography_section, the_glossary_section, the_blurb_section;
+    ObjGenericComposite[] the_dom_tail_section;
     string[string] an_object, processing;
     string an_object_key;
     string[] anchor_tags;
@@ -49,10 +50,10 @@ template SiSUdocAbstraction() {
     /+ counters +/
     int cntr, previous_count, previous_length;
     int[string] line_occur;
-    int verse_line, heading_ptr;
-    string[] html_segnames=[];
+    string[] html_segnames=["toc"];
     int html_segnames_ptr=0;
     int html_segnames_ptr_cntr=0;
+    int verse_line, heading_ptr;
     /+ paragraph attributes +/
     int[string] indent;
     bool bullet = true;
@@ -62,6 +63,89 @@ template SiSUdocAbstraction() {
     /+ ocn +/
     int obj_cite_number, obj_cite_number_;
     auto object_citation_number = OCNemitter();
+    int[] dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
+    int[] dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
+    int[] dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
+    int[] dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
+    enum DomTags { none, open, close, close_and_open, open_still, }
+    auto dom_set_markup_tags(int[] dom, int lev) {
+      foreach (i; 0 .. 8) {
+        if (i < lev) {
+          if (dom[i] == DomTags.open
+             || dom[i] == DomTags.close_and_open
+          ) {
+            dom[i] = DomTags.open_still;
+          } else if (dom[i] == DomTags.close) {
+            dom[i] = DomTags.none;
+          }
+        } else if (i == lev) {
+          if (lev  == 0
+            && dom[i] == DomTags.open_still
+          ) {
+            dom[i] = DomTags.close;
+          } else if (dom[i] == DomTags.open
+            || dom[i] == DomTags.open_still
+            || dom[i] == DomTags.close_and_open
+          ) {
+            dom[i] = DomTags.close_and_open;
+          } else {
+            dom[i] = DomTags.open;
+          }
+        } else if (i > lev) {
+          if (dom[i] == DomTags.close) {
+            dom[i] = DomTags.none;
+          } else if (dom[i] == DomTags.open
+            || dom[i] == DomTags.open_still
+            || dom[i] == DomTags.close_and_open
+          ) {
+            dom[i] = DomTags.close;
+          }
+        }
+      }
+      debug(dom) {
+        writeln(lev, ": ", dom);
+      }
+      return dom;
+    }
+    auto dom_set_collapsed_tags(int[] dom, int lev) {
+      foreach (i; 0 .. 8) {
+        if (i < lev) {
+          if (dom[i] == DomTags.open
+             || dom[i] == DomTags.close_and_open
+          ) {
+            dom[i] = DomTags.open_still;
+          } else if (dom[i] == DomTags.close) {
+            dom[i] = DomTags.none;
+          }
+        } else if (i == lev) {
+          if (lev  == 0
+            && dom[i] == DomTags.open_still
+          ) {
+            dom[i] = DomTags.close;
+          } else if (dom[i] == DomTags.open
+            || dom[i] == DomTags.open_still
+            || dom[i] == DomTags.close_and_open
+          ) {
+            dom[i] = DomTags.close_and_open;
+          } else {
+            dom[i] = DomTags.open;
+          }
+        } else if (i > lev) {
+          if (dom[i] == DomTags.close) {
+            dom[i] = DomTags.none;
+          } else if (dom[i] == DomTags.open
+            || dom[i] == DomTags.open_still
+            || dom[i] == DomTags.close_and_open
+          ) {
+            dom[i] = DomTags.close;
+          }
+        }
+      }
+      debug(dom) {
+        writeln(lev, ": ", dom);
+      }
+      return dom;
+    }
     int ocn_emit(int ocn_status_flag) {
       return object_citation_number.ocn_emitter(ocn_status_flag);
     }
@@ -160,7 +244,7 @@ template SiSUdocAbstraction() {
       an_object["glossary_nugget"] = "";
       an_object["blurb_nugget"] = "";
       comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "content";
+      comp_obj_heading_.use                   = "frontmatter";
       comp_obj_heading_.is_of                 = "para";
       comp_obj_heading_.is_a                  = "heading";
       comp_obj_heading_.text                  = "Table of Contents";
@@ -169,17 +253,20 @@ template SiSUdocAbstraction() {
       comp_obj_heading_.segment_anchor_tag    = "toc";
       comp_obj_heading_.marked_up_level       = "1";
       comp_obj_heading_.heading_lev_markup    = 4;
-      comp_obj_heading_.heading_lev_collapsed = 2;
+      comp_obj_heading_.heading_lev_collapsed = 1;
       comp_obj_heading_.parent_ocn            = 1;
       comp_obj_heading_.parent_lev_markup     = 0;
+      comp_obj_heading_.ptr_html_segnames     = html_segnames_ptr;
       comp_obj_heading_.anchor_tags           = ["toc"];
-      auto toc_head                       = comp_obj_heading_;
+      auto toc_head                           = comp_obj_heading_;
+      html_segnames_ptr_cntr++;
       the_table_of_contents_section = [
         "seg": [toc_head],
         "scroll": [toc_head],
       ];
       auto mkup = InlineMarkup();
       auto munge = ObjInlineMarkupMunge();
+      string[][string] lev4_subtoc;
       /+ abstraction init ↑ +/
       /+ ↓ loop markup document/text line by line +/
       srcDocLoop:
@@ -262,7 +349,7 @@ template SiSUdocAbstraction() {
               an_object_key="glossary_nugget"; //
               if (matchFirst(line, rgx.heading_glossary)) {
                 comp_obj_heading_                       = comp_obj_heading_.init;
-                comp_obj_heading_.use                   = "content";
+                comp_obj_heading_.use                   = "backmatter";
                 comp_obj_heading_.is_of                 = "para";
                 comp_obj_heading_.is_a                  = "heading";
                 comp_obj_heading_.text                  = "Glossary";
@@ -275,7 +362,7 @@ template SiSUdocAbstraction() {
                 comp_obj_heading_.parent_lev_markup     = 0;
                 the_glossary_section                    ~= comp_obj_heading_;
                 comp_obj_heading_                       = comp_obj_heading_.init;
-                comp_obj_heading_.use                   = "content";
+                comp_obj_heading_.use                   = "backmatter";
                 comp_obj_heading_.is_of                 = "para";
                 comp_obj_heading_.is_a                  = "heading";
                 comp_obj_heading_.text                  = "Glossary";
@@ -288,13 +375,13 @@ template SiSUdocAbstraction() {
                 comp_obj_heading_.parent_ocn            = 1;
                 comp_obj_heading_.parent_lev_markup     = 0;
                 comp_obj_heading_.anchor_tags           = ["glossary"];
-                the_glossary_section                ~= comp_obj_heading_;
+                the_glossary_section                    ~= comp_obj_heading_;
               // } else if (matchFirst(line, rgx.heading)) {
               //   _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa); // levels?
               } else {
                 _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
                 comp_obj_para                       = comp_obj_para.init;
-                comp_obj_para.use                   = "content";
+                comp_obj_para.use                   = "backmatter";
                 comp_obj_para.is_of                 = "para";
                 comp_obj_para.is_a                  = "glossary";
                 comp_obj_para.text                  = to!string(line).strip;
@@ -333,7 +420,7 @@ template SiSUdocAbstraction() {
               an_object_key="blurb_nugget";
               if (matchFirst(line, rgx.heading_blurb)) {
                 comp_obj_heading_                       = comp_obj_heading_.init;
-                comp_obj_heading_.use                   = "content";
+                comp_obj_heading_.use                   = "backmatter";
                 comp_obj_heading_.is_of                 = "para";
                 comp_obj_heading_.is_a                  = "heading";
                 comp_obj_heading_.text                  = "Blurb";
@@ -346,7 +433,7 @@ template SiSUdocAbstraction() {
                 comp_obj_heading_.parent_lev_markup     = 0;
                 the_blurb_section                       ~= comp_obj_heading_;
                 comp_obj_heading_                       = comp_obj_heading_.init;
-                comp_obj_heading_.use                   = "content";
+                comp_obj_heading_.use                   = "backmatter";
                 comp_obj_heading_.is_of                 = "para";
                 comp_obj_heading_.is_a                  = "heading";
                 comp_obj_heading_.text                  = "Blurb";
@@ -363,7 +450,7 @@ template SiSUdocAbstraction() {
               } else if ((matchFirst(line, rgx.heading))
               && (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"])) {
                 comp_obj_heading_                       = comp_obj_heading_.init;
-                comp_obj_heading_.use                   = "content";
+                comp_obj_heading_.use                   = "backmatter";
                 comp_obj_heading_.is_of                 = "para";
                 comp_obj_heading_.is_a                  = "heading";
                 comp_obj_heading_.text                  = to!string(line);
@@ -379,12 +466,12 @@ template SiSUdocAbstraction() {
               } else {
                 _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
                 comp_obj_para                       = comp_obj_para.init;
-                comp_obj_para.use                   = "content";
+                comp_obj_para.use                   = "backmatter";
                 comp_obj_para.is_of                 = "para";
-                comp_obj_para.is_a                  = "para";
+                comp_obj_para.is_a                  = "blurb";
                 comp_obj_para.text                  = to!string(line).strip;
-                comp_obj_para.ocn                   = obj_cite_number;
-                comp_obj_para.obj_cite_number       = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+                comp_obj_para.ocn                   = 0;
+                comp_obj_para.obj_cite_number       = "";
                 comp_obj_para.indent_hang           = indent["hang_position"];
                 comp_obj_para.indent_base           = indent["base_position"];
                 comp_obj_para.bullet                = bullet;
@@ -576,6 +663,7 @@ template SiSUdocAbstraction() {
                   dochead_make_aa,
                   segment_anchor_tag_that_object_belongs_to,
                   _anchor_tag,
+                  lev4_subtoc,
                   the_table_of_contents_section,
                 );
                 if (an_object["lev_markup_number"] == "4") {
@@ -633,7 +721,7 @@ template SiSUdocAbstraction() {
                 an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
                 anchor_tags = substantive_object_and_anchor_tags_tuple[1];
                 comp_obj_para                       = comp_obj_para.init;
-                comp_obj_para.use                   = "content";
+                comp_obj_para.use                   = "body";
                 comp_obj_para.is_of                 = "para";
                 comp_obj_para.is_a                  = "para";
                 comp_obj_para.text                  = to!string(an_object["substantive"]).strip;
@@ -720,9 +808,8 @@ template SiSUdocAbstraction() {
         }
       }
       if (an_object["glossary_nugget"].length == 0) {
-        writeln("no gloss");
         comp_obj_heading_                       = comp_obj_heading_.init;
-        comp_obj_heading_.use                   = "content";
+        comp_obj_heading_.use                   = "empty";
         comp_obj_heading_.is_of                 = "para";
         comp_obj_heading_.is_a                  = "heading";
         comp_obj_heading_.text                  = "(skip) there is no Glossary section";
@@ -733,7 +820,7 @@ template SiSUdocAbstraction() {
         comp_obj_heading_.heading_lev_collapsed = 1;
         comp_obj_heading_.parent_ocn            = 1;
         comp_obj_heading_.parent_lev_markup     = 0;
-        the_glossary_section                ~= comp_obj_heading_;
+        the_glossary_section                    ~= comp_obj_heading_;
       } else {
         writeln("gloss");
       }
@@ -749,7 +836,7 @@ template SiSUdocAbstraction() {
         biblio._bibliography_(biblio_unsorted_incomplete, bib_arr_json);
       if (biblio_ordered.length > 0) {
         comp_obj_heading_                       = comp_obj_heading_.init;
-        comp_obj_heading_.use                   = "content";
+        comp_obj_heading_.use                   = "backmatter";
         comp_obj_heading_.is_of                 = "para";
         comp_obj_heading_.is_a                  = "heading";
         comp_obj_heading_.text                  = "Bibliography";
@@ -763,7 +850,7 @@ template SiSUdocAbstraction() {
         the_bibliography_section                ~= comp_obj_heading_;
         // ---
         comp_obj_heading_                       = comp_obj_heading_.init;
-        comp_obj_heading_.use                   = "content";
+        comp_obj_heading_.use                   = "backmatter";
         comp_obj_heading_.is_of                 = "para";
         comp_obj_heading_.is_a                  = "heading";
         comp_obj_heading_.text                  = "Bibliography";
@@ -779,7 +866,7 @@ template SiSUdocAbstraction() {
         the_bibliography_section                ~= comp_obj_heading_;
       } else {
         comp_obj_heading_                       = comp_obj_heading_.init;
-        comp_obj_heading_.use                   = "content";
+        comp_obj_heading_.use                   = "empty";
         comp_obj_heading_.is_of                 = "para";
         comp_obj_heading_.is_a                  = "heading";
         comp_obj_heading_.text                  = "(skip) there is no Bibliography";
@@ -809,7 +896,7 @@ template SiSUdocAbstraction() {
           ((entry["url"].str.empty) ? "" : ", [" ~ entry["url"].str ~ "]"),
         );
         comp_obj_para                       = comp_obj_para.init;
-        comp_obj_para.use                   = "content";
+        comp_obj_para.use                   = "backmatter";
         comp_obj_para.is_of                 = "para";
         comp_obj_para.is_a                  = "bibliography";
         comp_obj_para.text                  = to!string(out_).strip;
@@ -828,7 +915,7 @@ template SiSUdocAbstraction() {
       }
       auto bi = BookIndexReportSection();
       auto bi_tuple =
-        bi.bookindex_build_section(
+        bi.bookindex_build_abstraction_section(
           bookindex_unordered_hashes,
           obj_cite_number,
           segment_anchor_tag_that_object_belongs_to,
@@ -843,21 +930,20 @@ template SiSUdocAbstraction() {
         }
       }
       if (an_object["blurb_nugget"].length == 0) {
-        writeln("no blurb");
         comp_obj_heading_                       = comp_obj_heading_.init;
-        comp_obj_heading_.use                   = "content";
+        comp_obj_heading_.use                   = "empty";
         comp_obj_heading_.is_of                 = "para";
         comp_obj_heading_.is_a                  = "heading";
         comp_obj_heading_.text                  = "(skip) there is no Blurb section";
         comp_obj_heading_.ocn                   = 0;
         comp_obj_para.obj_cite_number           = "";
-        comp_obj_heading_.segment_anchor_tag    = "bibliography";
-        comp_obj_heading_.marked_up_level       = "1";
-        comp_obj_heading_.heading_lev_markup    = 4;
-        comp_obj_heading_.heading_lev_collapsed = 2;
+        comp_obj_heading_.segment_anchor_tag    = "";
+        comp_obj_heading_.marked_up_level       = "B";
+        comp_obj_heading_.heading_lev_markup    = 1;
+        comp_obj_heading_.heading_lev_collapsed = 1;
         comp_obj_heading_.parent_ocn            = 1;
         comp_obj_heading_.parent_lev_markup     = 0;
-        the_blurb_section                   ~= comp_obj_heading_;
+        the_blurb_section                       ~= comp_obj_heading_;
       } else {
         writeln("blurb");
       }
@@ -866,13 +952,12 @@ template SiSUdocAbstraction() {
           writeln(blurb.text);
         }
       }
-      
       indent=[
         "hang_position" : 1,
         "base_position" : 1,
       ];
       comp_obj_toc                       = comp_obj_toc.init;
-      comp_obj_toc.use                   = "content";
+      comp_obj_toc.use                   = "frontmatter";
       comp_obj_toc.is_of                 = "para";
       comp_obj_toc.is_a                  = "toc";
       comp_obj_toc.ocn                   = 0;
@@ -987,6 +1072,313 @@ template SiSUdocAbstraction() {
       }
       the_document_head_section ~= the_document_body_section[0];
       the_document_body_section=the_document_body_section[1..$];
+      if (the_endnotes_section["scroll"].length > 1) {
+        html_segnames ~= "endnotes";
+        html_segnames_ptr = html_segnames_ptr_cntr;
+        foreach (ref section; the_endnotes_section["scroll"]) {
+          if (section.heading_lev_markup == 4) {
+            section.ptr_html_segnames = html_segnames_ptr;
+            break;
+          }
+        }
+        foreach (ref section; the_endnotes_section["seg"]) {
+          if (section.heading_lev_markup == 4) {
+            section.ptr_html_segnames = html_segnames_ptr;
+            break;
+          }
+        }
+        html_segnames_ptr_cntr++;
+      }
+      if (the_glossary_section.length > 1) {
+        html_segnames ~= "glossary";
+        html_segnames_ptr = html_segnames_ptr_cntr;
+        foreach (ref section; the_glossary_section) {
+          if (section.heading_lev_markup == 4) {
+            section.ptr_html_segnames = html_segnames_ptr;
+            break;
+          }
+        }
+        html_segnames_ptr_cntr++;
+      }
+      if (the_bibliography_section.length > 1) {
+        html_segnames ~= "bibliography";
+        html_segnames_ptr = html_segnames_ptr_cntr;
+        foreach (ref section; the_bibliography_section) {
+          if (section.heading_lev_markup == 4) {
+            section.ptr_html_segnames = html_segnames_ptr;
+            break;
+          }
+        }
+        html_segnames_ptr_cntr++;
+      }
+      if (the_bookindex_section["scroll"].length > 1) {
+        html_segnames ~= "bookindex";
+        html_segnames_ptr = html_segnames_ptr_cntr;
+        foreach (ref section; the_bookindex_section["scroll"]) {
+          if (section.heading_lev_markup == 4) {
+            section.ptr_html_segnames = html_segnames_ptr;
+            break;
+          }
+        }
+        foreach (ref section; the_bookindex_section["seg"]) {
+          if (section.heading_lev_markup == 4) {
+            section.ptr_html_segnames = html_segnames_ptr;
+            break;
+          }
+        }
+        html_segnames_ptr_cntr++;
+      }
+      if (the_blurb_section.length > 1) {
+        html_segnames ~= "blurb";
+        html_segnames_ptr = html_segnames_ptr_cntr;
+        foreach (ref section; the_blurb_section) {
+          if (section.heading_lev_markup == 4) {
+            section.ptr_html_segnames = html_segnames_ptr;
+            break;
+          }
+        }
+        html_segnames_ptr_cntr++;
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        foreach (ref obj; the_document_head_section) {
+          if (obj.is_a == "heading") {
+            debug(dom) {
+              writeln(obj.text);
+            }
+            dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+            obj.dom_markedup = dom_markedup.dup;
+            dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+            obj.dom_collapsed = dom_collapsed.dup;
+          }
+        }
+        if (the_table_of_contents_section["scroll"].length > 1) {
+          dom_markedup_buffer = dom_markedup.dup;
+          dom_collapsed_buffer = dom_collapsed.dup;
+          foreach (ref obj; the_table_of_contents_section["scroll"]) {
+            if (obj.is_a == "heading") {
+              debug(dom) {
+              // writeln(obj.text);
+              }
+              if (obj.heading_lev_markup == 4) {
+                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+                assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+              }
+              dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+              obj.dom_markedup = dom_markedup.dup;
+              dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+              obj.dom_collapsed = dom_collapsed.dup;
+            }
+          }
+          dom_markedup = dom_markedup_buffer.dup;
+          dom_collapsed = dom_collapsed_buffer.dup;
+          foreach (ref obj; the_table_of_contents_section["seg"]) {
+            if (obj.is_a == "heading") {
+              debug(dom) {
+                writeln(obj.text);
+              }
+              if (obj.heading_lev_markup == 4) {
+                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+                assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+              }
+              dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+              obj.dom_markedup = dom_markedup.dup;
+              dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+              obj.dom_collapsed = dom_collapsed.dup;
+            }
+          }
+        }
+        /+ multiple 1~ levels, loop through document body +/
+        if (the_document_body_section.length > 1) {
+          foreach (ref obj; the_document_body_section) {
+            if (obj.is_a == "heading") {
+              debug(dom) {
+                writeln(obj.text);
+              }
+              if (obj.heading_lev_markup == 4) {
+                obj.lev4_subtoc = lev4_subtoc[obj.segment_anchor_tag];
+                obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+                if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                  obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+                }
+                assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+              }
+              dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+              obj.dom_markedup = dom_markedup.dup;
+              dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+              obj.dom_collapsed = dom_collapsed.dup;
+            }
+          }
+        }
+        /+ optional only one 1~ level +/
+        if (the_endnotes_section["scroll"].length > 1) {
+          dom_markedup_buffer = dom_markedup.dup;
+          dom_collapsed_buffer = dom_collapsed.dup;
+          foreach (ref obj; the_endnotes_section["scroll"]) {
+            if (obj.is_a == "heading") {
+              debug(dom) {
+              }
+              if (obj.heading_lev_markup == 4) {
+                obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+                if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                  obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+                }
+                assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+              }
+              dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+              obj.dom_markedup = dom_markedup.dup;
+              dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+              obj.dom_collapsed = dom_collapsed.dup;
+            }
+          }
+          dom_markedup = dom_markedup_buffer.dup;
+          dom_collapsed = dom_collapsed_buffer.dup;
+          foreach (ref obj; the_endnotes_section["seg"]) {
+            if (obj.is_a == "heading") {
+              debug(dom) {
+                writeln(obj.text);
+              }
+              if (obj.heading_lev_markup == 4) {
+                obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+                if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                  obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+                }
+                assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+              }
+              dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+              obj.dom_markedup = dom_markedup.dup;
+              dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+              obj.dom_collapsed = dom_collapsed.dup;
+            }
+          }
+        }
+        /+ optional only one 1~ level +/
+        if (the_glossary_section.length > 1) {
+          foreach (ref obj; the_glossary_section) {
+            if (obj.is_a == "heading") {
+              debug(dom) {
+                writeln(obj.text);
+              }
+              if (obj.heading_lev_markup == 4) {
+                obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+                if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                  obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+                }
+                assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+              }
+              dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+              obj.dom_markedup = dom_markedup.dup;
+              dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+              obj.dom_collapsed = dom_collapsed.dup;
+            }
+          }
+        }
+        /+ optional only one 1~ level +/
+        if (the_bibliography_section.length > 1) {
+          foreach (ref obj; the_bibliography_section) {
+            if (obj.is_a == "heading") {
+              debug(dom) {
+                writeln(obj.text);
+              }
+              if (obj.heading_lev_markup == 4) {
+                obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+                if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                  obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+                }
+                assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+              }
+              dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+              obj.dom_markedup = dom_markedup.dup;
+              dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+              obj.dom_collapsed = dom_collapsed.dup;
+            }
+          }
+        }
+        /+ optional only one 1~ level +/
+        if (the_bookindex_section["scroll"].length > 1) {
+          dom_markedup_buffer = dom_markedup.dup;
+          dom_collapsed_buffer = dom_collapsed.dup;
+          foreach (ref obj; the_bookindex_section["scroll"]) {
+            if (obj.is_a == "heading") {
+              debug(dom) {
+              // writeln(obj.text);
+              }
+              if (obj.heading_lev_markup == 4) {
+                obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+                if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                  obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+                }
+                assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+              }
+              dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+              obj.dom_markedup = dom_markedup.dup;
+              dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+              obj.dom_collapsed = dom_collapsed.dup;
+            }
+          }
+          dom_markedup = dom_markedup_buffer.dup;
+          dom_collapsed = dom_collapsed_buffer.dup;
+          foreach (ref obj; the_bookindex_section["seg"]) {
+            if (obj.is_a == "heading") {
+              debug(dom) {
+                writeln(obj.text);
+              }
+              if (obj.heading_lev_markup == 4) {
+                obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+                if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                  obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+                }
+                assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+              }
+              dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+              obj.dom_markedup = dom_markedup.dup;
+              dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+              obj.dom_collapsed = dom_collapsed.dup;
+            }
+          }
+        }
+        /+ optional only one 1~ level +/
+        if (the_blurb_section.length > 1) {
+          foreach (ref obj; the_blurb_section) {
+            if (obj.is_a == "heading") {
+              debug(dom) {
+                writeln(obj.text);
+              }
+              if (obj.heading_lev_markup == 4) {
+                obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+                if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                  obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+                }
+                assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+              }
+              dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup);
+              obj.dom_markedup = dom_markedup.dup;
+              dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed);
+              obj.dom_collapsed = dom_collapsed.dup;
+            }
+          }
+        }
+        dom_markedup = dom_set_markup_tags(dom_markedup, 0);
+        dom_collapsed = dom_set_collapsed_tags(dom_collapsed, 0);
+        comp_obj_heading_                       = comp_obj_heading_.init;
+        comp_obj_heading_.use                   = "empty";
+        comp_obj_heading_.is_of                 = "para";
+        comp_obj_heading_.is_a                  = "heading";
+        // comp_obj_heading_.text                  = "(skip) this is the DOM tail";
+        comp_obj_heading_.ocn                   = 0;
+        comp_obj_para.obj_cite_number           = "";
+        comp_obj_heading_.segment_anchor_tag    = "";
+        comp_obj_heading_.marked_up_level       = "";
+        comp_obj_heading_.heading_lev_markup    = 9;
+        comp_obj_heading_.heading_lev_collapsed = 9;
+        comp_obj_heading_.parent_ocn            = 0;
+        comp_obj_heading_.parent_lev_markup     = 0;
+        comp_obj_heading_.dom_markedup          = dom_markedup.dup;
+        comp_obj_heading_.dom_collapsed         = dom_collapsed.dup;
+        the_dom_tail_section                    ~= comp_obj_heading_;
+      }
       auto document_the = [
         "head":             the_document_head_section,
         "toc_seg":          the_table_of_contents_section["seg"],
@@ -1001,6 +1393,8 @@ template SiSUdocAbstraction() {
         "bookindex_scroll": the_bookindex_section["scroll"],
         "bookindex_seg":    the_bookindex_section["seg"],
         "blurb":            the_blurb_section,
+        /+ dom tail only +/
+        "tail":             the_dom_tail_section,
       ];
       auto t = tuple(
         document_the,
@@ -1430,7 +1824,7 @@ template SiSUdocAbstraction() {
             an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
             anchor_tags = substantive_object_and_anchor_tags_tuple[1];
             comp_obj_block                            = comp_obj_block.init;
-            comp_obj_block.use                        = "content";
+            comp_obj_block.use                        = "body";
             comp_obj_block.is_of                      = "block";
             comp_obj_block.is_a                       = "verse";
             comp_obj_block.ocn                        = obj_cite_number;
@@ -1481,7 +1875,7 @@ template SiSUdocAbstraction() {
             an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
             anchor_tags = substantive_object_and_anchor_tags_tuple[1];
             comp_obj_block                            = comp_obj_block.init;
-            comp_obj_block.use                        = "content";
+            comp_obj_block.use                        = "body";
             comp_obj_block.is_of                      = "block";
             comp_obj_block.is_a                       = "verse";
             comp_obj_block.ocn                        = obj_cite_number;
@@ -1517,7 +1911,7 @@ template SiSUdocAbstraction() {
             an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
             anchor_tags = substantive_object_and_anchor_tags_tuple[1];
             comp_obj_block                            = comp_obj_block.init;
-            comp_obj_block.use                        = "content";
+            comp_obj_block.use                        = "body";
             comp_obj_block.is_of                      = "block";
             comp_obj_block.is_a                       = "verse";
             comp_obj_block.ocn                        = obj_cite_number;
@@ -1568,7 +1962,7 @@ template SiSUdocAbstraction() {
             an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
             anchor_tags = substantive_object_and_anchor_tags_tuple[1];
             comp_obj_block                            = comp_obj_block.init;
-            comp_obj_block.use                        = "content";
+            comp_obj_block.use                        = "body";
             comp_obj_block.is_of                      = "block";
             comp_obj_block.is_a                       = "verse";
             comp_obj_block.ocn                        = obj_cite_number;
@@ -1766,7 +2160,7 @@ template SiSUdocAbstraction() {
         an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         comp_obj_code                             = comp_obj_code.init;
-        comp_obj_code.use                         = "content";
+        comp_obj_code.use                         = "body";
         comp_obj_code.is_of                       = "block";
         comp_obj_code.is_a                        = "code";
         comp_obj_code.ocn                         = obj_cite_number;
@@ -1794,7 +2188,7 @@ template SiSUdocAbstraction() {
             an_object["is"]
           );
         comp_obj_poem_ocn                         = comp_obj_poem_ocn.init;
-        comp_obj_poem_ocn.use                     = "content";
+        comp_obj_poem_ocn.use                     = "body";
         comp_obj_poem_ocn.is_of                   = "block";
         comp_obj_poem_ocn.is_a                    = "poem";
         comp_obj_poem_ocn.ocn                     = obj_cite_number;
@@ -1827,7 +2221,7 @@ template SiSUdocAbstraction() {
         an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         comp_obj_block                            = comp_obj_block.init;
-        comp_obj_block.use                        = "content";
+        comp_obj_block.use                        = "body";
         comp_obj_block.is_of                      = "block";
         comp_obj_block.is_a                       = "table";
         comp_obj_block.ocn                        = obj_cite_number;
@@ -1861,7 +2255,7 @@ template SiSUdocAbstraction() {
         an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         comp_obj_block                            = comp_obj_block.init;
-        comp_obj_block.use                        = "content";
+        comp_obj_block.use                        = "body";
         comp_obj_block.is_of                      = "block";
         comp_obj_block.is_a                       = "group";
         comp_obj_block.ocn                        = obj_cite_number;
@@ -1894,7 +2288,7 @@ template SiSUdocAbstraction() {
         an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         comp_obj_block                            = comp_obj_block.init;
-        comp_obj_block.use                        = "content";
+        comp_obj_block.use                        = "body";
         comp_obj_block.is_of                      = "block";
         comp_obj_block.is_a                       = "block";
         comp_obj_block.ocn                        = obj_cite_number;
@@ -1928,7 +2322,7 @@ template SiSUdocAbstraction() {
         an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         comp_obj_block                            = comp_obj_block.init;
-        comp_obj_block.use                        = "content";
+        comp_obj_block.use                        = "body";
         comp_obj_block.is_of                      = "block";
         comp_obj_block.is_a                       = "quote";
         comp_obj_block.ocn                        = obj_cite_number;
@@ -2160,7 +2554,7 @@ template SiSUdocAbstraction() {
             rgx.variable_doc_title, (dochead_meta_aa["title"]["full"] ~ ","));
           an_object[an_object_key]=replaceFirst(an_object[an_object_key],
             rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]);
-          collapsed_lev["h0"] = 1;
+          collapsed_lev["h0"] = 0;
           an_object["lev_collapsed_number"] =
             to!string(collapsed_lev["h0"]);
           lv["lv"] = DocStructMarkupHeading.h_sect_A;
@@ -2655,6 +3049,7 @@ template SiSUdocAbstraction() {
         string[string][string]        dochead_make_aa,
         string                        segment_anchor_tag_that_object_belongs_to,
         string                        _anchor_tag,
+        ref string[][string]          lev4_subtoc,
         ObjGenericComposite[][string] the_table_of_contents_section,
       )
       in { }
@@ -2663,7 +3058,7 @@ template SiSUdocAbstraction() {
         char[] heading_toc_ = to!(char[])(obj_["body_nugget"].dup.strip);
         heading_toc_ = _clean_heading_toc_(heading_toc_);
         auto attrib="";
-        string toc_txt_;
+        string toc_txt_, subtoc_txt_;
         int[string] indent;
         if (to!int(obj_["lev_markup_number"]) > 0) {
           indent=[
@@ -2677,7 +3072,7 @@ template SiSUdocAbstraction() {
           );
           toc_txt_= munge.url_links(toc_txt_);
           comp_obj_toc                       = comp_obj_toc.init;
-          comp_obj_toc.use                   = "content";
+          comp_obj_toc.use                   = "frontmatter";
           comp_obj_toc.is_of                 = "para";
           comp_obj_toc.is_a                  = "toc";
           comp_obj_toc.ocn                   = 0;
@@ -2693,7 +3088,7 @@ template SiSUdocAbstraction() {
             "base_position" : 0,
           ];
           comp_obj_toc                       = comp_obj_toc.init;
-          comp_obj_toc.use                   = "content";
+          comp_obj_toc.use                   = "frontmatter";
           comp_obj_toc.is_of                 = "para";
           comp_obj_toc.is_a                  = "toc";
           comp_obj_toc.ocn                   = 0;
@@ -2705,7 +3100,7 @@ template SiSUdocAbstraction() {
           the_table_of_contents_section["scroll"] ~= comp_obj_toc;
         }
         comp_obj_toc                       = comp_obj_toc.init;
-        comp_obj_toc.use                   = "content";
+        comp_obj_toc.use                   = "frontmatter";
         comp_obj_toc.is_of                 = "para";
         comp_obj_toc.is_a                  = "toc";
         comp_obj_toc.ocn                   = 0;
@@ -2745,6 +3140,7 @@ template SiSUdocAbstraction() {
             heading_toc_,
             segment_anchor_tag_that_object_belongs_to,
           );
+          lev4_subtoc[segment_anchor_tag_that_object_belongs_to] = [];
           toc_txt_= munge.url_links(toc_txt_);
           indent=[
             "hang_position" : to!int(obj_["lev_markup_number"]),
@@ -2762,6 +3158,12 @@ template SiSUdocAbstraction() {
             segment_anchor_tag_that_object_belongs_to,
             _anchor_tag,
           );
+          subtoc_txt_ = format(                         // 5 .. 7
+            "{ %s }#%s",
+            heading_toc_,
+            _anchor_tag,
+          );
+          lev4_subtoc[segment_anchor_tag_that_object_belongs_to] ~= obj_["lev_markup_number"] ~ "~ " ~ to!string(subtoc_txt_).strip;
           toc_txt_= munge.url_links(toc_txt_);
           indent=[
             "hang_position" : to!int(obj_["lev_markup_number"]),
@@ -3300,7 +3702,7 @@ template SiSUdocAbstraction() {
           ++mkn;
         }
       }
-      auto bookindex_build_section(
+      auto bookindex_build_abstraction_section(
         string[][string][string] bookindex_unordered_hashes,
         int                      obj_cite_number,
         string                   segment_anchor_tag_that_object_belongs_to,
@@ -3321,12 +3723,14 @@ template SiSUdocAbstraction() {
         if ((mainkeys.length > 0)
         && (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"])) {
           string bi_tmp_seg, bi_tmp_scroll;
+          string[] bi_tmp_tags;
           comp_obj_heading_                       = comp_obj_heading_.init;
-          comp_obj_heading_.use                   = "content";
+          comp_obj_heading_.use                   = "backmatter";
           comp_obj_heading_.is_of                 = "para";
           comp_obj_heading_.is_a                  = "heading";
           comp_obj_heading_.text                  = "Book Index";
           comp_obj_heading_.ocn                   = 0;
+          comp_obj_heading_.obj_cite_number       = "";
           comp_obj_heading_.marked_up_level       = "B";
           comp_obj_heading_.heading_lev_markup    = 1;
           comp_obj_heading_.heading_lev_collapsed = 1;
@@ -3337,11 +3741,12 @@ template SiSUdocAbstraction() {
           ++obj_cite_number;
           ++mkn;
           comp_obj_heading_                       = comp_obj_heading_.init;
-          comp_obj_heading_.use                   = "content";
+          comp_obj_heading_.use                   = "backmatter";
           comp_obj_heading_.is_of                 = "para";
           comp_obj_heading_.is_a                  = "heading";
           comp_obj_heading_.text                  = "Index";
           comp_obj_heading_.ocn                   = 0;
+          comp_obj_heading_.obj_cite_number       = "";
           comp_obj_heading_.segment_anchor_tag    = "bookindex";
           comp_obj_heading_.marked_up_level       = "1";
           comp_obj_heading_.heading_lev_markup    = 4;
@@ -3353,8 +3758,14 @@ template SiSUdocAbstraction() {
           bookindex_section["seg"]                ~= comp_obj_heading_;
           ++obj_cite_number;
           ++mkn;
+          import std.array : appender;
+          auto buffer = appender!(char[])();
+          string[dchar] transTable = [' ' : "_"];
           foreach (mainkey; mainkeys) {
+            bi_tmp_tags = [""];
             bi_tmp_scroll = "!{" ~ mainkey ~ "}! ";
+            buffer.clear();
+            bi_tmp_tags ~= translate(mainkey, transTable);
             bi_tmp_seg = "!{" ~ mainkey ~ "}! ";
             foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
               auto go = replaceAll(ref_, rgx.book_index_go, "$1");
@@ -3370,6 +3781,8 @@ template SiSUdocAbstraction() {
               bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
             foreach (subkey; subkeys) {
               bi_tmp_scroll ~= subkey ~ ", ";
+              buffer.clear();
+              bi_tmp_tags ~= translate(subkey, transTable);
               bi_tmp_seg ~= subkey ~ ", ";
               foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
                 auto go = replaceAll(ref_, rgx.book_index_go, "$1");
@@ -3385,12 +3798,13 @@ template SiSUdocAbstraction() {
             bi_tmp_scroll = replaceFirst(bi_tmp_scroll, rgx.trailing_linebreak, "");
             bi_tmp_seg = replaceFirst(bi_tmp_seg, rgx.trailing_linebreak, "");
             comp_obj_para                       = comp_obj_para.init;
-            comp_obj_para.use                   = "content";
+            comp_obj_para.use                   = "backmatter";
             comp_obj_para.is_of                 = "para";
             comp_obj_para.is_a                  = "bookindex";
             comp_obj_para.text                  = to!string(bi_tmp_scroll).strip;
             comp_obj_para.ocn                   = obj_cite_number;
             comp_obj_para.obj_cite_number       = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+            comp_obj_para.anchor_tags           = bi_tmp_tags;
             comp_obj_para.indent_hang           = 0;
             comp_obj_para.indent_base           = 1;
             comp_obj_para.bullet                = false;
@@ -3404,6 +3818,7 @@ template SiSUdocAbstraction() {
           comp_obj_heading_                       = comp_obj_heading_.init;
           comp_obj_heading_.text                  = "(skip) there is no Book Index";
           comp_obj_heading_.ocn                   = 0;
+          comp_obj_heading_.obj_cite_number       = "";
           comp_obj_heading_.marked_up_level       = "B";
           comp_obj_heading_.heading_lev_markup    = 1;
           comp_obj_heading_.heading_lev_collapsed = 1;
@@ -3508,11 +3923,12 @@ template SiSUdocAbstraction() {
         if ((endnotes_["seg"].length > 0)
         && (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"])) {
           comp_obj_heading_                       = comp_obj_heading_.init;
-          comp_obj_heading_.use                   = "content";
+          comp_obj_heading_.use                   = "backmatter";
           comp_obj_heading_.is_of                 = "para";
           comp_obj_heading_.is_a                  = "heading";
           comp_obj_heading_.text                  = "Endnotes";
           comp_obj_heading_.ocn                   = 0;
+          comp_obj_heading_.obj_cite_number       = "";
           comp_obj_heading_.marked_up_level       = "B";
           comp_obj_heading_.heading_lev_markup    = 1;
           comp_obj_heading_.heading_lev_collapsed = 1;
@@ -3523,11 +3939,12 @@ template SiSUdocAbstraction() {
           ++obj_cite_number;
           ++mkn;
           comp_obj_heading_                       = comp_obj_heading_.init;
-          comp_obj_heading_.use                   = "content";
+          comp_obj_heading_.use                   = "backmatter";
           comp_obj_heading_.is_of                 = "para";
           comp_obj_heading_.is_a                  = "heading";
           comp_obj_heading_.text                  = "Endnotes";
           comp_obj_heading_.ocn                   = 0;
+          comp_obj_heading_.obj_cite_number       = "";
           comp_obj_heading_.segment_anchor_tag    = "endnotes";
           comp_obj_heading_.marked_up_level       = "1";
           comp_obj_heading_.heading_lev_markup    = 4;
@@ -3541,11 +3958,12 @@ template SiSUdocAbstraction() {
           ++mkn;
         } else {
           comp_obj_heading_                       = comp_obj_heading_.init;
-          comp_obj_heading_.use                   = "content";
+          comp_obj_heading_.use                   = "empty";
           comp_obj_heading_.is_of                 = "para";
           comp_obj_heading_.is_a                  = "heading";
           comp_obj_heading_.text                  = "(skip) there are no Endnotes";
           comp_obj_heading_.ocn                   = 0;
+          comp_obj_heading_.obj_cite_number       = "";
           comp_obj_heading_.marked_up_level       = "B";
           comp_obj_heading_.heading_lev_markup    = 1;
           comp_obj_heading_.heading_lev_collapsed = 1;
@@ -3557,7 +3975,7 @@ template SiSUdocAbstraction() {
         if (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"]) {
           ObjGenericComposite comp_obj_endnote_;
           comp_obj_endnote_                       = comp_obj_endnote_.init;
-          comp_obj_endnote_.use                   = "content";
+          comp_obj_endnote_.use                   = "backmatter";
           comp_obj_endnote_.is_of                 = "para";
           comp_obj_endnote_.is_a                  = "endnote";
           comp_obj_endnote_.ocn                   = 0;
@@ -3834,7 +4252,7 @@ template SiSUdocAbstraction() {
         }
         ObjGenericComposite _comp_obj_heading_;
         _comp_obj_heading_                       = _comp_obj_heading_.init;
-        _comp_obj_heading_.use                   = "content";
+        _comp_obj_heading_.use                   = "body";
         _comp_obj_heading_.is_of                 = "para";
         _comp_obj_heading_.is_a                  = "heading";
         _comp_obj_heading_.text                  = to!string(_text).strip;
diff --git a/src/sdp/ao_object_setter.d b/src/sdp/ao_object_setter.d
index 13bcc36..1f10b66 100644
--- a/src/sdp/ao_object_setter.d
+++ b/src/sdp/ao_object_setter.d
@@ -31,6 +31,8 @@ template ObjectSetter() {
     string                 syntax                       = "";
     int                    ocn                          = 0;
     string                 segment_anchor_tag           = "";
+    string                 segname_prev                 = "";
+    string                 segname_next                 = "";
     int                    parent_lev_markup            = 0;
     int                    parent_ocn                   = 0;
     int[]                  ancestors                    = [];
@@ -44,7 +46,10 @@ template ObjectSetter() {
     int                    ptr_heading                  = 0;
     int                    array_ptr                    = 0;
     int                    heading_array_ptr_segments   = 0;
+    string[]               lev4_subtoc                  = [];
     string[string][string] node;
+    int[]                  dom_markedup                          = [ 0, 0, 0, 0, 0, 0, 0, 0,];
+    int[]                  dom_collapsed                         = [ 0, 0, 0, 0, 0, 0, 0, 0,];
   }
   struct TheObjects {
     ObjGenericComposite[] oca;
diff --git a/src/sdp/ao_output_debugs.d b/src/sdp/ao_output_debugs.d
index e4eaccb..35e250c 100644
--- a/src/sdp/ao_output_debugs.d
+++ b/src/sdp/ao_output_debugs.d
@@ -26,7 +26,7 @@ template SiSUoutputDebugs() {
         );
         foreach (key; document_section_keys_sequenced["seg"]) {
           foreach (obj; contents[key]) {
-            if (obj.use == "content") {
+            if (obj.use != "empty") {
               if (obj.is_a == "heading") {
                 writefln(
                   "%s node: %s heading: %s %s",
@@ -48,7 +48,7 @@ template SiSUoutputDebugs() {
           __LINE__,
         );
         foreach (obj; contents) {
-          if (obj.use == "content") {
+          if (obj.use != "empty") {
             writefln(
               "[%s][%s]\n%s",
               obj.obj_cite_number,
@@ -58,6 +58,21 @@ template SiSUoutputDebugs() {
           }
         }
       }
+      void out_segnames(S)(
+        auto ref const S         contents,
+        string[]                 keys,
+        string[]                 html_segnames,
+      ) {
+        foreach (key; keys) {
+          if (contents[key].length > 1) {
+            foreach (obj; contents[key]) {
+              if (obj.heading_lev_markup == 4) {
+                writeln(obj.ptr_html_segnames, ". (", html_segnames[obj.ptr_html_segnames], ") -> ",  obj.text);
+              }
+            }
+          }
+        }
+      }
       void out_toc(S)(
         auto ref const S         contents,
         string                   key,
@@ -128,6 +143,28 @@ template SiSUoutputDebugs() {
         key="toc_scroll";
         out_toc(contents, key);
       }
+      debug(segnames) {
+        key="toc_scroll";
+        writeln(__LINE__);
+        string[] keys;
+        keys ~= [ "toc_seg", "body" ];
+        if (contents["endnotes_seg"].length > 1) {
+          keys ~= "endnotes_seg";
+        }
+        if (contents["glossary"].length > 1) {
+          keys ~= "glossary";
+        }
+        if (contents["bibliography"].length > 1) {
+          keys ~= "bibliography";
+        }
+        if (contents["bookindex_seg"].length > 1) {
+          keys ~= "bookindex_seg";
+        }
+        if (contents["blurb"].length > 1) {
+          keys ~= "blurb";
+        }
+        out_segnames(contents, keys, html_segnames);
+      }
       debug(section_body) {
         key="body";
         if (contents[key].length > 1) {
@@ -141,6 +178,54 @@ template SiSUoutputDebugs() {
           }
         }
       }
+      debug(dom) {
+        enum DomTags { none, open, close, close_and_open, open_still, }
+        foreach (sect; document_section_keys_sequenced["seg"]) {
+          foreach (obj; contents[sect]) {
+            if (obj.is_a == "heading") {
+              foreach_reverse (k; 0 .. 7) {
+                switch (obj.dom_markedup[k]) {
+                case DomTags.close :
+                  writeln(markup.indent_by_spaces_provided(k), "</", k, ">");
+                  break;
+                case DomTags.close_and_open :
+                  writeln(markup.indent_by_spaces_provided(k), "</", k, ">");
+                  writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text);
+                  break;
+                case DomTags.open :
+                  writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text);
+                  break;
+                default :
+                  break;
+                }
+              }
+            }
+          }
+        }
+        writeln("--------------------");
+        foreach (sect; document_section_keys_sequenced["seg"]) {
+          foreach (obj; contents[sect]) {
+            if (obj.is_a == "heading") {
+              foreach_reverse (k; 0 .. 7) {
+                switch (obj.dom_collapsed[k]) {
+                case DomTags.close :
+                  writeln(markup.indent_by_spaces_provided(k), "</", k, ">");
+                  break;
+                case DomTags.close_and_open :
+                  writeln(markup.indent_by_spaces_provided(k), "</", k, ">");
+                  writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text);
+                  break;
+                case DomTags.open :
+                  writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text);
+                  break;
+                default :
+                  break;
+                }
+              }
+            }
+          }
+        }
+      }
       debug(section_endnotes) {
         key="endnotes_seg";
         out_endnotes(contents, key);
@@ -212,7 +297,7 @@ template SiSUoutputDebugs() {
           __LINE__,
         );
         foreach (obj; contents) {
-          if (obj.use == "content") {
+          if (obj.use != "empty") {
             writefln(
               "* [%s][%s] %s",
               obj.obj_cite_number,
@@ -435,7 +520,7 @@ template SiSUoutputDebugs() {
         debug(checkdoc) {
           foreach (k; document_section_keys_sequenced["seg"]) {
             foreach (obj; contents[k]) {
-              if (obj.use == "content") {
+              if (obj.use != "empty") {
                 if (!empty(obj.obj_cite_number)) {
                   check["last_obj_cite_number"] = obj.obj_cite_number;
                 }
diff --git a/src/sdp/ao_rgx.d b/src/sdp/ao_rgx.d
index aa4cd58..6534cdd 100644
--- a/src/sdp/ao_rgx.d
+++ b/src/sdp/ao_rgx.d
@@ -96,7 +96,7 @@ template RgxInit() {
     static block_tic_close                                = ctRegex!("^(`{3})$","m");
     /+ blocked markup curly +/
     static block_curly_open                               = ctRegex!(`^((code([.][a-z][0-9a-z_]+)?|poem|group|block|quote|table)[{].*?$)`);
-    static block_curly_code_open                          = ctRegex!(`^(code([.][a-z][0-9a-z_]+)?[{].*?$)`);
+    static block_curly_code_open                          = ctRegex!(`^(code([.][a-z][0-9a-z_]+)?[{](.*?)$)`);
     static block_curly_code_close                         = ctRegex!(`^([}]code)`);
     static block_curly_poem_open                          = ctRegex!(`^(poem[{].*?$)`);
     static block_curly_poem_close                         = ctRegex!(`^([}]poem)`);
diff --git a/src/sdp/output_html.d b/src/sdp/output_html.d
index 5cd1b26..0390799 100644
--- a/src/sdp/output_html.d
+++ b/src/sdp/output_html.d
@@ -16,23 +16,38 @@ template SiSUoutputHTML() {
     ) {
       auto tags = _html_anchor_tags(obj.anchor_tags);
       string o;
-      o = format(q"¶<br><hr /><br>
+      if (obj.obj_cite_number.empty) {
+        o = format(q"¶<br><hr /><br>
+      <div class="substance">
+        <h%s class="%s">%s
+          %s
+        </h%s>
+      </div>¶",
+          obj.heading_lev_markup,
+          obj.is_a,
+          tags,
+          obj.text,
+          obj.heading_lev_markup,
+        );
+      } else {
+        o = format(q"¶<br><hr /><br>
       <div class="substance">
         <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label>
         <h%s class="%s" id="%s"><a name="%s"></a>%s
           %s
         </h%s>
       </div>¶",
-      obj.obj_cite_number,
-      obj.obj_cite_number,
-      obj.heading_lev_markup,
-      obj.is_a,
-      obj.obj_cite_number,
-      obj.obj_cite_number,
-      tags,
-      obj.text,
-      obj.heading_lev_markup,
-      );
+        obj.obj_cite_number,
+        obj.obj_cite_number,
+        obj.heading_lev_markup,
+        obj.is_a,
+        obj.obj_cite_number,
+        obj.obj_cite_number,
+        tags,
+        obj.text,
+        obj.heading_lev_markup,
+        );
+      }
       return o;
     }
     auto html_para(O)(
@@ -42,13 +57,10 @@ template SiSUoutputHTML() {
       string o;
       if (obj.obj_cite_number.empty) {
         o = format(q"¶  <div class="substance">
-      <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label>
       <p class="%s" indent="h%si%s">%s
         %s
       </p>
     </div>¶",
-          obj.obj_cite_number,
-          obj.obj_cite_number,
           obj.is_a,
           obj.indent_hang,
           obj.indent_base,
@@ -78,18 +90,29 @@ template SiSUoutputHTML() {
       auto ref const O         obj,
     ) {
       string o;
-      o = format(q"¶  <div class="substance">
+      if (obj.obj_cite_number.empty) {
+        o = format(q"¶  <div class="substance">
+      <p class="%s">
+        %s
+      </p>
+    </div>¶",
+          obj.is_a,
+          obj.text
+        );
+      } else {
+        o = format(q"¶  <div class="substance">
       <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label>
       <p class="%s" id="%s">
         %s
       </p>
     </div>¶",
-      obj.obj_cite_number,
-      obj.obj_cite_number,
-      obj.is_a,
-      obj.obj_cite_number,
-      obj.text
-      );
+          obj.obj_cite_number,
+          obj.obj_cite_number,
+          obj.is_a,
+          obj.obj_cite_number,
+          obj.text
+        );
+      }
       return o;
     }
     auto scroll_head_html() {
@@ -99,7 +122,7 @@ template SiSUoutputHTML() {
     <head>
       <meta charset="utf-8">
       <title>
-        Title
+        %s%s
       </title>
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
       <meta name="dc.title" content="Title" />
@@ -120,7 +143,10 @@ template SiSUoutputHTML() {
       <link href="../../../_sisu/css/html.css" rel="stylesheet">
     </head>
     <body lang="en">
-    <a name="top" id="top"></a>¶");
+    <a name="top" id="top"></a>¶",
+    dochead_meta["title"]["full"],
+    (dochead_meta["creator"]["author"].empty) ? "" : ", " ~ dochead_meta["creator"]["author"],
+    );
       return o;
     }
     auto html_toc(O)(
@@ -175,7 +201,7 @@ template SiSUoutputHTML() {
       string[] doc;
       foreach (part; document_section_keys_sequenced["scroll"]) {
         foreach (obj; contents[part]) {
-          if (obj.use == "content") {
+          if (obj.use == "frontmatter") {
             switch (obj.is_of) {
             case "para":
               switch (obj.is_a) {
@@ -185,22 +211,23 @@ template SiSUoutputHTML() {
               case "toc":
                 body_html ~= html_toc(obj);
                 break;
-              case "para":
-                body_html ~= html_para(obj);
-                break;
-              case "endnote":
-                body_html ~= html_endnote(obj);
-                break;
-              case "glossary":
-                body_html ~= html_para(obj);
-                break;
-              case "bibliography":
-                body_html ~= html_para(obj);
+              default:
+                writeln(__FILE__, ":", __LINE__, ": ", obj.is_a);
                 break;
-              case "bookindex":
-                body_html ~= html_para(obj);
+              }
+              break;
+            default:
+              writeln(__FILE__, ":", __LINE__, ": ", obj.is_a);
+              break;
+            }
+          } else if (obj.use == "body") {
+            switch (obj.is_of) {
+            case "para":
+              switch (obj.is_a) {
+              case "heading":
+                body_html ~= html_heading(obj);
                 break;
-              case "blurb":
+              case "para":
                 body_html ~= html_para(obj);
                 break;
               default:
@@ -239,6 +266,37 @@ template SiSUoutputHTML() {
               writeln(__FILE__, ":", __LINE__, ": ", obj.is_of);
               break;
             }
+          } else if (obj.use == "backmatter") {
+            switch (obj.is_of) {
+            case "para":
+              switch (obj.is_a) {
+              case "heading":
+                body_html ~= html_heading(obj);
+                break;
+              case "endnote":
+                body_html ~= html_endnote(obj);
+                break;
+              case "glossary":
+                body_html ~= html_para(obj);
+                break;
+              case "bibliography":
+                body_html ~= html_para(obj);
+                break;
+              case "bookindex":
+                body_html ~= html_para(obj);
+                break;
+              case "blurb":
+                body_html ~= html_para(obj);
+                break;
+              default:
+                writeln(__FILE__, ":", __LINE__, ": ", obj.is_a);
+                break;
+              }
+              break;
+            default:
+              writeln(__FILE__, ":", __LINE__, ": ", obj.is_a);
+              break;
+            }
           }
         }
       }
-- 
cgit v1.2.3