From 9c14b019a6f695b54a035605e3bb3fc76bf20aa6 Mon Sep 17 00:00:00 2001
From: Ralph Amissah <ralph@amissah.com>
Date: Sun, 24 Apr 2016 22:35:39 -0400
Subject: step2

---
 lib/sdp/ao_abstract_doc_source.d | 5053 ++++++++++++++++++++++++++------------
 lib/sdp/ao_ansi_colors.d         |   74 +
 lib/sdp/ao_assertions.d          |  221 --
 lib/sdp/ao_defaults.d            |   85 +-
 lib/sdp/ao_object_setter.d       |  172 +-
 lib/sdp/ao_output_debugs.d       |  138 +-
 lib/sdp/ao_read_markup_source.d  |   55 -
 lib/sdp/ao_read_source_files.d   |  281 +++
 lib/sdp/ao_rgx.d                 |   50 +-
 lib/sdp/ao_scan_inserts.d        |  199 --
 lib/sdp/ao_structs.d             |   43 -
 lib/sdp/ao_utils.d               |   74 -
 lib/sdp/compile_time_info.d      |    2 +-
 lib/sdp/sdp.d                    |  186 ++
 14 files changed, 4239 insertions(+), 2394 deletions(-)
 create mode 100644 lib/sdp/ao_ansi_colors.d
 delete mode 100644 lib/sdp/ao_assertions.d
 delete mode 100644 lib/sdp/ao_read_markup_source.d
 create mode 100644 lib/sdp/ao_read_source_files.d
 delete mode 100644 lib/sdp/ao_scan_inserts.d
 delete mode 100644 lib/sdp/ao_structs.d
 delete mode 100644 lib/sdp/ao_utils.d
 create mode 100755 lib/sdp/sdp.d

(limited to 'lib/sdp')

diff --git a/lib/sdp/ao_abstract_doc_source.d b/lib/sdp/ao_abstract_doc_source.d
index 34e4072..74d1baa 100644
--- a/lib/sdp/ao_abstract_doc_source.d
+++ b/lib/sdp/ao_abstract_doc_source.d
@@ -2,126 +2,146 @@
   document abstraction
   ao_abstract_doc_source.d
 +/
-mixin template SiSUdocAbstraction() {
+template SiSUdocAbstraction() {
   private:
   struct Abstraction {
+
+    /+ ↓ abstraction imports +/
+    import
+      lib.sdp.ao_defaults,                  // sdp/ao_defaults.d
+      lib.sdp.ao_object_setter,             // sdp/ao_object_setter.d
+      lib.sdp.ao_rgx,                       // sdp/ao_rgx.d
+      lib.sdp.ao_ansi_colors;               // sdp/ao_ansi_colors.d
+
+    /+ ↓ abstraction mixins +/
+    mixin ObjectSetter;
+    mixin InternalMarkup;
+    // // mixin SiSUrgxInitFlags;
+    // // mixin AssertionsOnBlocks;
+    // mixin SiSUbiblio; // issue
+    // mixin SiSUheader;
+
+    /+ ↓ abstraction struct init +/
+    /+ initialize +/
+    
+    auto rgx = Rgx();
+    string[string][] contents_the_objects;
+    string[string] an_object, processing;
+    auto set_abstract_object = ObjectAbstractSet();
+    auto set_header = HeaderDocMetadataMakeJson();
+    auto note_section = NotesSection();
+    
+    /+ enum +/
+    enum State { off, on }
+    enum TriState { off, on, closing } // make aware, possibility of third state
+    enum DocStructMarkupHeading {
+      h_sect_A,
+      h_sect_B,
+      h_sect_C,
+      h_sect_D,
+      h_text_1,
+      h_text_2,
+      h_text_3,
+      h_text_4,
+      h_text_5, // extra level, drop
+      content_non_header
+    } // header section A-D; header text 1-4
+    enum DocStructCollapsedHeading { lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7 } // not yet used
+    
+    /+ biblio variables +/
+    string biblio_tag_name, biblio_tag_entry, st;
+    string[] biblio_arr_json;
+    JSONValue[] bib_arr_json;
+    int bib_entry;
+    
+    /+ counters +/
+    long counter, previous_count;
+    int[string] line_occur;
+    int verse_line, heading_pointer;
+    
+    /+ paragraph attributes +/
+    string[string] indent;
+    bool bullet = true;
+    string content_non_header = "8";
+    
+    auto obj_im = ObjInlineMarkup();
+    auto obj_att = ObjAttrib();
+    
+    /+ ocn +/
+    int obj_cite_number, obj_cite_number_;
+    auto object_citation_number = OCNemitter();
+    int obj_cite_number_emit(int obj_cite_number_status_flag) {
+      return object_citation_number.obj_cite_number_emitter(obj_cite_number_status_flag);
+    }
+    
+    /+ book index variables +/
+    string book_idx_tmp;
+    string[][string][string] bookindex_unordered_hashes;
+    auto bookindex_extract_hash = BookIndexNuggetHash();
+    string[][string][string] bkidx_hash(string bookindex_section, int obj_cite_number) {
+      return bookindex_extract_hash.bookindex_nugget_hash(bookindex_section, obj_cite_number);
+    }
+    
+    /+ node +/
+    string node;
+    auto node_construct = NodeStructureMetadata();
+    string node_jstr(
+      string lev_markup_number,
+      int obj_cite_number_,
+      long counter,
+      int heading_pointer,
+      string is_
+    ) {
+      return node_construct.node_emitter(
+        lev_markup_number,
+        obj_cite_number_,
+        counter,
+        heading_pointer,
+        is_
+      );
+    }
+    string node_jstr_heading(
+      string lev_markup_number,
+      string lev_collapsed_number,
+      int obj_cite_number_,
+      long counter,
+      int heading_pointer,
+      string is_
+    ) {
+      return node_construct.node_emitter_heading(
+        lev_markup_number,
+        lev_collapsed_number,
+        obj_cite_number_,
+        counter,
+        heading_pointer,
+        is_
+      );
+    }
+    // mixin SiSUdocAbstractionFunctions;
+
     /+ ↓ abstract marked up document +/
     auto abstract_doc_source(char[][] markup_sourcefile_content) {
-      /+ initialize +/
-      mixin ObjectSetters;
-      mixin AssertionsOnMarkupDocumentStructure;
-      mixin AssertionsOnBlocks;
-      mixin ScreenTxtColors;
-      auto rgx = Rgx();
-      auto set_oa = ObjectAbstractSet();
-      auto set_header = HeaderDocMetadataMakeJson();
-      auto notesection = NotesSection();
-      string[string][] contents;
-      mixin Structs;
-      string notes_str;
-      string[string] object, processing, head;
-      string biblio_tag_name, biblio_tag_entry, book_idx_tmp, st;
-      string[] biblio_arr_json;
-      JSONValue[] bib_arr_json;
-      uint[string] line_occur;
-      uint counter, ocn, ocn_, verse_line, bib_entry, heading_pointer, notepoint, count_biblio_entry;
-      ulong previous_count;
-      string indent_first, indent_second;
-      string[][string][string] bookindex_unordered_hashes;
-      bool bullet = true;
-      uint[string] lv = [
-        "lv" : 0,
-        "h0" : 0,
-        "h1" : 0,
-        "h2" : 0,
-        "h3" : 0,
-        "h4" : 0,
-        "h5" : 0,
-        "h6" : 0,
-        "h7" : 0,
-        "lcn" : 0,
-      ];
-      int[string] collapsed_lev = [
-        "h0" : 0,
-        "h1" : 0,
-        "h2" : 0,
-        "h3" : 0,
-        "h4" : 0,
-        "h5" : 0,
-        "h6" : 0,
-        "h7" : 0
-      ];
-      auto rgx_h_A = regex(r"^(none)");
-      auto rgx_h_B = regex(r"^(none)");
-      auto rgx_h_C = regex(r"^(none)");
-      auto rgx_h_D = regex(r"^(none)");
-      auto rgx_h_1 = regex(r"^(none)");
-      auto rgx_h_2 = regex(r"^(none)");
-      auto rgx_h_3 = regex(r"^(none)");
-      auto rgx_h_4 = regex(r"^(none)");
-      auto str_h_A = "^(none)";
-      auto str_h_B = "^(none)";
-      auto str_h_C = "^(none)";
-      auto str_h_D = "^(none)";
-      auto str_h_1 = "^(none)";
-      auto str_h_2 = "^(none)";
-      auto str_h_3 = "^(none)";
-      auto str_h_4 = "^(none)";
-      string content_non_header = "8";
-      string node;
-      auto obj_im = ObjInlineMarkup();
-      auto obj_att = ObjAttrib();
-      auto object_citation_number = OCNemitter();
-      auto ft = flag_type.dup;
-      int ocn_emit(int ocn_status_flag) {
-        return object_citation_number.ocn_emitter(ocn_status_flag);
-      }
-      auto bookindex_extract_hash = BookIndexNuggetHash();
-      string[][string][string] bkidx_hash(string bookindex, int ocn) {
-        return bookindex_extract_hash.bookindex_nugget_hash(bookindex, ocn);
-      }
-      auto node_construct = NodeStructureMetadata();
-      string node_jstr(
-        string lvn,
-        int ocn_,
-        int counter,
-        int heading_pointer,
-        string is_
-      ) {
-        return node_construct.node_emitter(
-          lvn,
-          ocn_,
-          counter,
-          heading_pointer,
-          is_
-        );
+
+      /+ ↓ abstraction init +/
+      scope(success) {
       }
-      string node_jstr_heading(
-        string lvn,
-        string lcn,
-        int ocn_,
-        int counter,
-        int heading_pointer,
-        string is_
-      ) {
-        return node_construct.node_emitter_heading(
-          lvn,
-          lcn,
-          ocn_,
-          counter,
-          heading_pointer,
-          is_
-        );
+      scope(failure) {
       }
-      string[string] ocn_poem = [
-        "start" : "",
-        "end"   : ""
-      ];
-      int tell_lo(string color, int ocn, in char[] line) {
+      scope(exit) {
+        destroy(contents_the_objects);
+        destroy(an_object);
+        destroy(processing);
+        destroy(biblio_arr_json);
+      }
+      auto type = flags_type_init;
+      auto dochead_make = parseJSON(header_make_jsonstr).object;
+      auto dochead_metadata = parseJSON(header_metadata_jsonstr).object;
+      mixin ScreenTxtColors;
+      int tell_lo(string color, int obj_cite_number, in char[] line) {
         writefln(
           "%s%s %s",
           scr_txt_marker[color],
-          to!string(ocn),
+          to!string(obj_cite_number),
           to!string(line)
         );
         return 0;
@@ -134,29 +154,66 @@ mixin template SiSUdocAbstraction() {
         );
         return 0;
       }
-      scope(success) {
-      }
-      scope(failure) {
-      }
-      scope(exit) {
-        destroy(contents);
-        destroy(object);
-        destroy(processing);
-        destroy(biblio_arr_json);
-      }
-      auto dochead_make = parseJSON(header_make_jsonstr).object;
-      auto dochead_metadata = parseJSON(header_metadata_jsonstr).object;
+      string[string] obj_cite_number_poem = [
+        "start" : "",
+        "end"   : ""
+      ];
+      int[string] lv = [
+        "lv" : State.off,
+        "h0" : State.off,
+        "h1" : State.off,
+        "h2" : State.off,
+        "h3" : State.off,
+        "h4" : State.off,
+        "h5" : State.off,
+        "h6" : State.off,
+        "h7" : State.off,
+        "lev_collapsed_number" : 0,
+      ];
+      int[string] collapsed_lev = [
+        "h0" : State.off,
+        "h1" : State.off,
+        "h2" : State.off,
+        "h3" : State.off,
+        "h4" : State.off,
+        "h5" : State.off,
+        "h6" : State.off,
+        "h7" : State.off
+      ];
+      string[string] heading_match_str = [
+        "h_A": "^(none)",
+        "h_B": "^(none)",
+        "h_C": "^(none)",
+        "h_D": "^(none)",
+        "h_1": "^(none)",
+        "h_2": "^(none)",
+        "h_3": "^(none)",
+        "h_4": "^(none)"
+      ];
+      auto heading_match_rgx = [
+        "h_A": regex(r"^(none)"),
+        "h_B": regex(r"^(none)"),
+        "h_C": regex(r"^(none)"),
+        "h_D": regex(r"^(none)"),
+        "h_1": regex(r"^(none)"),
+        "h_2": regex(r"^(none)"),
+        "h_3": regex(r"^(none)"),
+        "h_4": regex(r"^(none)")
+      ];
+      /+ abstraction init ↑ +/
+
       /+ ↓ loop markup document/text line by line +/
+      srcDocLoop:
       foreach (line; markup_sourcefile_content) {
+
         /+ ↓ markup document/text line by line +/
         /+ scope +/
         scope(exit) {
         }
         scope(failure) {
-          writefln(
-            "%s:%s failed here: \n  line: %s",
-            __FILE__,
-            __LINE__,
+          stderr.writefln(
+            "%s:%s failed here:\n  line: %s",
+            __FILE__, __LINE__,
             line,
           );
         }
@@ -176,679 +233,74 @@ mixin template SiSUdocAbstraction() {
             );
           }
         }
-        if ((!line.empty) && (ft["ocn_status_multi_obj"] == 0)) {
-        /+ not multi-line object, check whether ocn is on or turned off +/
-          if (match(line, rgx.ocn_block_marks)) {
-          /+ switch off ocn +/
-            if (match(line, rgx.ocn_off_block)) {
-              ft["ocn_status_multi_obj"] = 1;
-              debug(ocnoff) {
-                tell_l("fuchsia", line);
-              }
-            }
-            if (match(line, rgx.ocn_off_block_dh)) {
-              ft["ocn_status_multi_obj"] = 2;
-              debug(ocnoff) {
-                tell_l("fuchsia", line);
-              }
-            }
-          } else {
-            if (ft["ocn_status_multi_obj"] == 0) {
-              if (match(line, rgx.ocn_off)) {
-                ft["ocn_status"] = 1;
-              } else if (match(line, rgx.ocn_off_dh)) {
-                ft["ocn_status"] = 2;
-              } else {
-                ft["ocn_status"] = 2;
-                ft["ocn_status"] = 0;
-              }
-            } else {
-              ft["ocn_status"] = ft["ocn_status_multi_obj"];
-            }
-          }
-        } else if ((!line.empty) && (ft["ocn_status_multi_obj"] > 0)) {
-          if (auto m = match(line, rgx.ocn_off_block_close)) {
-            ft["ocn_status_multi_obj"] = 0;
-            ft["ocn_status"] = 0;
-            debug(ocnoff) {
-              tell_l("green", line);
-            }
-          }
+        if (!line.empty) {
+          check_obj_cite_number_status(line, type);
         }
-        if (ft["code"] == 1) {
-        /+ block object: code +/
-          if (ft["curly_code"] == 1) {
-            if (auto m = match(line, rgx.block_curly_code_close)) {
-              debug(code) {                              // code (curly) close
-                tell_l("blue", line);
-              }
-              ft["blocks"] = 2;
-              ft["code"] = 2;
-              ft["curly_code"] = 0;
-            } else {
-              debug(code) {                              // code (curly) line
-                tell_l("blue", line);
-              }
-              object["obj"] ~= line ~= "\n";             // code (curly) line
-            }
-          } else if (ft["tic_code"] == 1) {
-            if (auto m = match(line, rgx.block_tic_close)) {
-              debug(code) {                              // code (tic) close
-                tell_l("blue", line);
-              }
-              ft["blocks"] = 2;
-              ft["code"] = 2;
-              ft["tic_code"] = 0;
-            } else {
-              debug(code) {                              // code (tic) line
-                tell_l("blue", line);
-              }
-              object["obj"] ~= line ~= "\n";             // code (tic) line
-            }
-          }
+        if (type["code"] == TriState.on) {
+          /+ block object: code +/
+          code_block(line, an_object, type);
+          continue;
         } else if (!match(line, rgx.regular_parse_skip)) {
-        /+ object other than code block object (includes regular text paragraph) +/
+          /+ object other than code block object (includes regular text paragraph) +/
           if (((match(line, rgx.heading_biblio)
-          || (ft["heading_biblio"] == 1)))
+          || (type["heading_biblio"] == State.on)))
           && (!match(line, rgx.heading))
           && (!match(line, rgx.comment))) {
-          /+ within block object: biblio +/
-            if (match(line, rgx.heading_biblio)) {
-              ft["heading_biblio"] = 1;
-            }
-            if (empty(line) && (bib_entry == 0)) {
-              ++count_biblio_entry;
-              biblio_arr_json ~= biblio_entry_tags_jsonstr;
-              bib_entry = 1;
-            }
-            debug(biblio) {
-              writefln(
-                "%s * %s %s",
-                scr_txt_color["yellow"],
-                scr_txt_color["off"],
-                line
-              );
-            }
-            if (match(line, rgx.biblio_tags)) {
-              auto bt = match(line, rgx.biblio_tags);
-              bib_entry = 0;
-              st=to!string(bt.captures[1]);
-              biblio_tag_entry=to!string(bt.captures[2]);
-              JSONValue j = parseJSON(biblio_arr_json[count_biblio_entry-1]); // core.exception.RangeError@lib/sdp/ao_abstract_doc_source.d(288): Range violation (LDC) [: same for 343], fix to subtract 1 done!
-              if (match(st, rgx.biblio_abbreviations)) {
-                biblio_tag_name=biblio_tag_map[st];
-              } else {
-                biblio_tag_name=st;
-              }
-              j.object[biblio_tag_name] = biblio_tag_entry;
-              auto header_tag_value=to!string(bt.captures[2]);
-              switch (biblio_tag_name) {
-              case "author_raw": // author_arr author (fn sn)
-                j["author_arr"]=split(header_tag_value, rgx.arr_delimiter);
-                string tmp;
-                foreach (au; j["author_arr"].array) {
-                  if (auto x = match(au.str, rgx.name_delimiter)) {
-                    tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", ";
-                  } else {
-                    tmp ~= au.str;
-                  }
-                }
-                tmp = replace(tmp, rgx.trailing_comma, "");
-                j["author"].str = tmp;
-                break;
-              case "editor_raw": // editor_arr editor (fn sn)
-                j["editor_arr"]=split(header_tag_value, rgx.arr_delimiter);
-                string tmp;
-                foreach (ed; j["editor_arr"].array) {
-                  if (auto x = match(ed.str, rgx.name_delimiter)) {
-                    tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", ";
-                  } else {
-                    tmp ~= ed.str;
-                  }
-                }
-                tmp = replace(tmp, rgx.trailing_comma, "");
-                j["editor"].str = tmp;
-                break;
-              case "fulltitle": // title & subtitle
-                break;
-              default:
-                break;
-              }
-              auto s = to!string(j);
-              s = j.toString();
-              debug(biblio) {
-                writefln(
-                  "%s* %s%s: %s\n%s",
-                  scr_txt_color["red"],
-                  scr_txt_color["off"],
-                  biblio_tag_name,
-                  biblio_tag_entry,
-                  j[biblio_tag_name]
-                );
-                writeln(j[biblio_tag_name], ":", j[biblio_tag_name]);
-              }
-              biblio_arr_json[count_biblio_entry-1] = s;
-              biblio_tag_entry="";
-            }
-          } else if (ft["poem"] == 1) {
-          /+ within block object: poem +/
-            if (ft["curly_poem"] == 1) {
-              if (auto m = match(line, rgx.block_curly_poem_close)) {
-                object["obj"]="verse"; // check that this is as you please
-                debug(poem) {                            // poem (curly) close
-                  writefln(
-                    "%s* [poem curly] %s%s",
-                    scr_txt_color["red"],
-                    scr_txt_color["off"],
-                    line
-                  );
-                }
-                if (processing.length > 0) {
-                  object["obj"] = processing["verse"];
-                }
-                debug(poem) {                            // poem (curly) close
-                  writeln(__LINE__);
-                  writefln(
-                    "%s%s %s",
-                    scr_txt_marker["fuchsia"],
-                    ocn,
-                    line
-                  );
-                }
-                if (object.length > 0) {
-                  debug(poem) {                            // poem (curly) close
-                    writeln(__LINE__);
-                    tell_lo(
-                      "fuchsia",
-                      ocn,
-                      object["obj"]
-                    );
-                    writeln(__LINE__);
-                  }
-                  object["is"] = "verse";
-                  object["markup"] =
-                    obj_im.obj_inline_markup(object["is"], object["obj"]);
-                  object["attrib"] =
-                    obj_att.obj_attributes(object["is"], object["obj"], node);
-                  contents ~=
-                    set_oa.contents_block(
-                      object["is"],
-                      object["markup"],
-                      object["attrib"],
-                      ocn
-                    );
-                  object.remove("obj");
-                  object.remove("markup");
-                  object.remove("is");
-                  object.remove("attrib");
-                  object.remove("bookindex");
-                  processing.remove("verse");
-                  counter++;
-                }
-                ocn_poem["end"] = to!string(ocn);
-                ft["blocks"] = 2;
-                ft["poem"] = 2;
-                ft["curly_poem"] = 0;
-              } else {
-                processing["verse"] ~= line ~= "\n";
-                if (ft["verse_new"] == 1) {
-                  ocn = ocn_emit(ft["ocn_status"]);
-                  ft["verse_new"] = 0;
-                } else if (match(line, rgx.line_delimiter_only)) {
-                  verse_line = 0;
-                  ft["verse_new"] = 1;
-                }
-                if (ft["verse_new"] == 1) {
-                  verse_line=1;
-                  object["obj"] = processing["verse"];
-                  debug(poem) {                          // poem verse
-                    writefln(
-                      "%s%s curly\n%s",
-                      scr_txt_marker["green"],
-                      ocn,
-                      object["obj"]
-                    );
-                  }
-                  processing.remove("verse");
-                  object["is"] = "verse";
-                  node = node_jstr(
-                    content_non_header,
-                    ocn,
-                    counter,
-                    heading_pointer-1,
-                    object["is"]
-                  );
-                  object["markup"] = obj_im.obj_inline_markup(object["is"], object["obj"]);
-                  object["attrib"] = obj_att.obj_attributes(object["is"], object["obj"], node);
-                  contents ~=
-                    set_oa.contents_block(
-                      object["is"],
-                      object["markup"],
-                      object["attrib"],
-                      ocn
-                    );
-                  object.remove("obj");
-                  object.remove("markup");
-                  object.remove("is");
-                  object.remove("attrib");
-                  object.remove("bookindex");
-                  processing.remove("verse");
-                  counter++;
-                }
-              }
-            } else if (ft["tic_poem"] == 1) {
-              if (auto m = match(line, rgx.block_tic_close)) { // tic_poem_close
-                object["obj"]="verse"; // check that this is as you please
-                debug(poem) {                            // poem (curly) close
-                  writefln(
-                    "%s* [poem tic] %s%s",
-                    scr_txt_color["red"],
-                    scr_txt_color["off"],
-                    line
-                  );
-                }
-                if (processing.length > 0) {       // needs looking at
-                  object["obj"] = processing["verse"];
-                }
-                if (object.length > 0) {
-                  debug(poem) {                            // poem (tic) close
-                    writeln(__LINE__);
-                    tell_lo("fuchsia", ocn, line);
-                  }
-                  processing.remove("verse");
-                  object["is"] = "verse";
-                  object["markup"] =
-                    obj_im.obj_inline_markup(object["is"], object["obj"]);
-                  object["attrib"] =
-                    obj_att.obj_attributes(object["is"], object["obj"], node);
-                  contents ~=
-                    set_oa.contents_block(
-                      object["is"],
-                      object["markup"],
-                      object["attrib"],
-                      ocn
-                    );
-                  ocn_poem["end"] = to!string(ocn);
-                  object.remove("obj");
-                  object.remove("markup");
-                  object.remove("is");
-                  object.remove("attrib");
-                  object.remove("bookindex");
-                  processing.remove("verse");
-                  counter++;
-                }
-                ft["blocks"] = 2;
-                ft["poem"] = 2;
-                ft["tic_poem"] = 0;
-              } else {
-                processing["verse"] ~= line ~= "\n";
-                if (ft["verse_new"] == 1) {
-                  ocn = ocn_emit(ft["ocn_status"]);
-                  ft["verse_new"] = 0;
-                } else if (match(line, rgx.line_delimiter_only)) {
-                  ft["verse_new"] = 1;
-                  verse_line = 0;
-                }
-                if (ft["verse_new"] == 1) {
-                  verse_line=1;
-                  object["obj"] = processing["verse"];
-                  debug(poem) {                            // poem (tic) close
-                    writefln(
-                      "%s%s tic\n%s",
-                      scr_txt_marker["green"],
-                      ocn,
-                      object["obj"]
-                    );
-                  }
-                  processing.remove("verse");
-                  object["is"] = "verse";
-                  node =
-                    node_jstr(
-                      content_non_header,
-                      ocn,
-                      counter,
-                      heading_pointer-1,
-                      object["is"]
-                    );
-                  object["markup"] =
-                    obj_im.obj_inline_markup(object["is"], object["obj"]);
-                  object["attrib"] =
-                    obj_att.obj_attributes(object["is"], object["obj"], node);
-                  contents ~=
-                    set_oa.contents_block(
-                      object["is"],
-                      object["markup"],
-                      object["attrib"],
-                      ocn
-                    );
-                  object.remove("obj");
-                  object.remove("markup");
-                  object.remove("is");
-                  object.remove("attrib");
-                  object.remove("bookindex");
-                  processing.remove("verse");
-                  counter++;
-                }
-              }
-            }
+            /+ within block object: biblio +/
+            biblio_block(line, type, bib_entry, biblio_arr_json);
+            continue;
+          } else if (type["poem"] == TriState.on) {
+            /+ within block object: poem +/
+            poem_block(line, an_object, type, counter, obj_cite_number_poem);
+            continue;
           /+ within block object: group +/
-          } else if (ft["group"] == 1) {
-            if (ft["curly_group"] == 1) {
-              if (auto m = match(line, rgx.block_curly_group_close)) {
-                debug(group) {                           // group (curly) close
-                  tell_l("blue", line);
-                }
-                ft["blocks"] = 2;
-                ft["group"] = 2;
-                ft["curly_group"] = 0;
-              } else {
-                debug(group) {                           // group
-                  tell_l("blue", line);
-                }
-                object["obj"] ~= line ~= "\n";           // build group array (or string)
-              }
-            } else if (ft["tic_group"] == 1) {
-              if (auto m = match(line, rgx.block_tic_close)) {
-                debug(group) {                           // group (tic) close
-                  tell_l("blue", line);
-                }
-                ft["blocks"] = 2;
-                ft["group"] = 2;
-                ft["tic_group"] = 0;
-              } else {
-                debug(group) {                           // group
-                  tell_l("blue", line);
-                }
-                object["obj"] ~= line ~= "\n";           // build group array (or string)
-              }
-            }
-          } else if (ft["block"] == 1) {
-          /+ within block object: block +/
-            if (ft["curly_block"] == 1) {
-              if (auto m = match(line, rgx.block_curly_block_close)) {
-                debug(block) {                           // block (curly) close
-                  tell_l("blue", line);
-                }
-                ft["blocks"] = 2;
-                ft["block"] = 2;
-                ft["curly_block"] = 0;
-              } else {
-                debug(block) {                           // block
-                  tell_l("blue", line);
-                }
-                object["obj"] ~= line ~= "\n";           // build block array (or string)
-              }
-            } else if (ft["tic_block"] == 1) {
-              if (auto m = match(line, rgx.block_tic_close)) {
-                debug(block) {                           // block (tic) close
-                  tell_l("blue", line);
-                }
-                ft["blocks"] = 2;
-                ft["block"] = 2;
-                ft["tic_block"] = 0;
-              } else {
-                debug(block) {                           // block
-                  tell_l("blue", line);
-                }
-                object["obj"] ~= line ~= "\n";           // build block array (or string)
-              }
-            }
-          } else if (ft["quote"] == 1) {
-          /+ within block object: quote +/
-            if (ft["curly_quote"] == 1) {
-              if (auto m = match(line, rgx.block_curly_quote_close)) {
-                debug(quote) {                           // quote (curly) close
-                  tell_l("blue", line);
-                }
-                ft["blocks"] = 2;
-                ft["quote"] = 2;
-                ft["curly_quote"] = 0;
-              } else {
-                debug(quote) {                           // quote
-                  tell_l("blue", line);
-                }
-                object["obj"] ~= line ~= "\n";           // build quote array (or string)
-              }
-            } else if (ft["tic_quote"] == 1) {
-              if (auto m = match(line, rgx.block_tic_close)) {
-                debug(quote) {                           // quote (tic) close
-                  tell_l("blue", line);
-                }
-                ft["blocks"] = 2;
-                ft["quote"] = 2;
-                ft["tic_quote"] = 0;
-              } else {
-                debug(quote) {                           // quote
-                  tell_l("blue", line);
-                }
-                object["obj"] ~= line ~= "\n";           // build quote array (or string)
-              }
-            }
-          } else if (ft["table"] == 1) {
-          /+ within block object: table +/
-            if (ft["curly_table"] == 1) {
-              if (auto m = match(line, rgx.block_curly_table_close)) {
-                debug(table) {                           // table (curly) close
-                  tell_l("blue", line);
-                }
-                ft["blocks"] = 2;
-                ft["table"] = 2;
-                ft["curly_table"] = 0;
-              } else {
-                debug(table) {                           // table
-                  tell_l("blue", line);
-                }
-                object["obj"] ~= line ~= "\n";           // build table array (or string)
-              }
-            } else if (ft["tic_table"] == 1) {
-              if (auto m = match(line, rgx.block_tic_close)) {
-                debug(table) {                           // table (tic) close
-                  tell_l("blue", line);
-                }
-                ft["blocks"] = 2;
-                ft["table"] = 2;
-                ft["tic_table"] = 0;
-              } else {
-                debug(table) {                           // table
-                  tell_l("blue", line);
-                }
-                object["obj"] ~= line ~= "\n";           // build table array (or string)
-              }
-            }
+          } else if (type["group"] == TriState.on) {
+            /+ within block object: group +/
+            group_block(line, an_object, type);
+            continue;
+          } else if (type["block"] == TriState.on) {
+            /+ within block object: block +/
+            block_block(line, an_object, type);
+            continue;
+          } else if (type["quote"] == TriState.on) {
+            /+ within block object: quote +/
+            quote_block(line, an_object, type);
+            continue;
+          } else if (type["table"] == TriState.on) {
+            /+ within block object: table +/
+            table_block(line, an_object, type);
+            continue;
           } else {
           /+ not within a block group +/
             assert(
-              (ft["blocks"] == 0)
-              || (ft["blocks"] == 2),
+              (type["blocks"] == TriState.off)
+              || (type["blocks"] == TriState.closing),
               "block status: none or closed"
             );
-            assertions_flag_types_block_status_none_or_closed(ft);
-            if (auto m = match(line, rgx.block_curly_code_open)) {
-            /+ curly code open +/
-              debug(code) {                              // code (curly) open
-                writefln(
-                  "%s* [code curly] %s%s",
-                  scr_txt_color["blue"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ft["blocks"] = 1;
-              ft["code"] = 1;
-              ft["curly_code"] = 1;
-            } else if (auto m = match(line, rgx.block_curly_poem_open)) {
-            /+ curly poem open +/
-              object.remove("obj");
-              object.remove("markup");
-              object.remove("is");
-              object.remove("attrib");
-              object.remove("bookindex");
-              processing.remove("verse");
-              debug(poem) {                              // poem (curly) open
-                writefln(
-                  "%s* [poem curly] %s%s",
-                  scr_txt_color["red"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ocn_poem["start"] = to!string(ocn);
-              ft["blocks"] = 1;
-              ft["verse_new"] = 1;
-              ft["poem"] = 1;
-              ft["curly_poem"] = 1;
-            } else if (auto m = match(line, rgx.block_curly_group_open)) {
-            /+ curly group open +/
-              debug(group) {                             // group (curly) open
-                writefln(
-                  "%s* [group curly] %s%s",
-                  scr_txt_color["blue"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ft["blocks"] = 1;
-              ft["group"] = 1;
-              ft["curly_group"] = 1;
-            } else if (auto m = match(line, rgx.block_curly_block_open)) {
-            /+ curly block open +/
-              debug(block) {                             // block (curly) open
-                writefln(
-                  "%s* [block curly] %s%s",
-                  scr_txt_color["blue"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ft["blocks"] = 1;
-              ft["block"] = 1;
-              ft["curly_block"] = 1;
-            } else if (auto m = match(line, rgx.block_curly_quote_open)) {
-            /+ curly quote open +/
-              debug(quote) {                             // quote (curly) open
-                writefln(
-                  "%s* [quote curly] %s%s",
-                  scr_txt_color["blue"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ft["blocks"] = 1;
-              ft["quote"] = 1;
-              ft["curly_quote"] = 1;
-            } else if (auto m = match(line, rgx.block_curly_table_open)) {
-            /+ curly table open +/
-              debug(table) {                             // table (curly) open
-                writefln(
-                  "%s* [table curly] %s%s",
-                  scr_txt_color["blue"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ft["blocks"] = 1;
-              ft["table"] = 1;
-              ft["curly_table"] = 1;
-            } else if (auto m = match(line, rgx.block_tic_code_open)) {
-            /+ tic code open +/
-              debug(code) {                              // code (tic) open
-                writefln(
-                  "%s* [code tic] %s%s",
-                  scr_txt_color["blue"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ft["blocks"] = 1;
-              ft["code"] = 1;
-              ft["tic_code"] = 1;
-            } else if (auto m = match(line, rgx.block_tic_poem_open)) {
-            /+ tic poem open +/
-              object.remove("obj");
-              object.remove("markup");
-              object.remove("is");
-              object.remove("attrib");
-              object.remove("bookindex");
-              processing.remove("verse");
-              debug(poem) {                              // poem (tic) open
-                writefln(
-                  "%s* [poem tic] %s%s",
-                  scr_txt_color["red"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ocn_poem["start"] = to!string(ocn);
-              ft["blocks"] = 1;
-              ft["verse_new"] = 1;
-              ft["poem"] = 1;
-              ft["tic_poem"] = 1;
-            } else if (auto m = match(line, rgx.block_tic_group_open)) {
-            /+ tic group open +/
-              debug(group) {                             // group (tic) open
-                writefln(
-                  "%s* [group tic] %s%s",
-                  scr_txt_color["blue"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ft["blocks"] = 1;
-              ft["group"] = 1;
-              ft["tic_group"] = 1;
-            } else if (auto m = match(line, rgx.block_tic_block_open)) {
-            /+ tic block open +/
-              debug(block) {                             // block (tic) open
-                writefln(
-                  "%s* [block tic] %s%s",
-                  scr_txt_color["blue"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ft["blocks"] = 1;
-              ft["block"] = 1;
-              ft["tic_block"] = 1;
-            } else if (auto m = match(line, rgx.block_tic_quote_open)) {
-            /+ tic quote open +/
-              debug(quote) {                             // quote (tic) open
-                writefln(
-                  "%s* [quote tic] %s%s",
-                  scr_txt_color["blue"],
-                  scr_txt_color["off"],
-                  line
-                );
-              }
-              ft["blocks"] = 1;
-              ft["quote"] = 1;
-              ft["tic_quote"] = 1;
-            } else if (auto m = match(line, rgx.block_tic_table_open)) {
-            /+ tic table open +/
-              debug(table) {                             // table (tic) open
-                writefln(
-                  "%s* [table tic] %s%s",
-                  scr_txt_color["blue"],
-                  scr_txt_color["off"],
-                  line
-                );
+            assertions_flag_types_block_status_none_or_closed(type);
+            if (match(line, rgx.block_open)) {
+              if (match(line, (rgx.block_poem_open))) {
+                /+ poem to verse exceptions! +/
+                object_reset(an_object);
+                processing.remove("verse");
+                obj_cite_number_poem["start"] = to!string(obj_cite_number);
               }
-              ft["blocks"] = 1;
-              ft["table"] = 1;
-              ft["tic_table"] = 1;
+              start_block(line, type, obj_cite_number_poem);
+              continue;
             } else if (!line.empty) {
-            /+ line not empty +/
-            /+ non blocks (headers, paragraphs) & closed blocks +/
+              /+ line not empty +/
+              /+ non blocks (headers, paragraphs) & closed blocks +/
               assert(
                 !line.empty,
                 "line tested, line not empty surely"
               );
               assert(
-                (ft["blocks"] == 0)
-                || (ft["blocks"] == 2),
+                (type["blocks"] == TriState.off)
+                || (type["blocks"] == TriState.closing),
                 "code block status: none or closed"
               );
-              if (ft["blocks"] == 2) {
-              // blocks closed, unless followed by book index
+              if (type["blocks"] == TriState.closing) {
+                // blocks closed, unless followed by book index
                 debug(check) {                           // block
                   writeln(__LINE__);
                   tell_l("red", line);
@@ -856,655 +308,98 @@ mixin template SiSUdocAbstraction() {
                 assert(
                   match(line, rgx.book_index)
                   || match(line, rgx.book_index_open)
-                  || ft["book_index"] == 1
+                  || type["book_index"] == State.on
                 );
               }
-              if (auto m = match(line, rgx.book_index)) {
-              /+ match book_index +/
-                debug(bookindexmatch) {                       // book index
-                  writefln(
-                    "%s* [bookindex] %s%s\n",
-                    scr_txt_color["blue"],
-                    scr_txt_color["off"],
-                    to!string(m.captures[1]),
-                  );
-                  // writeln(scr_txt_marker["blue"], to!string(m.captures[1]), "\n");
-                }
-                object["bookindex"] = to!string(m.captures[1]);
-              } else if (auto m = match(line, rgx.book_index_open))  {
-              /* match open book_index */
-                ft["book_index"] = 1;
-                book_idx_tmp = to!string(m.captures[1]);
-                debug(bookindexmatch) {                       // book index
-                  writefln(
-                    "%s* [bookindex] %s%s\n",
-                    scr_txt_color["blue"],
-                    scr_txt_color["off"],
-                    book_idx_tmp,
-                  );
-                }
-              } else if (ft["book_index"] == 1 )  {
-              /+ book_index flag set +/
-                if (auto m = match(line, rgx.book_index_close))  {
-                  ft["book_index"] = 0;
-                  object["bookindex"] = book_idx_tmp ~ to!string(m.captures[1]);
-                  debug(bookindexmatch) {                     // book index
-                    writefln(
-                      "%s* [bookindex] %s%s\n",
-                      scr_txt_color["blue"],
-                      scr_txt_color["off"],
-                      book_idx_tmp,
-                    );
-                  }
-                  book_idx_tmp = "";
-                } else {
-                  book_idx_tmp ~= line;
-                }
+              if ((match(line, rgx.book_index))
+              || (match(line, rgx.book_index_open))
+              || (type["book_index"] == State.on ))  {
+                /+ book_index +/
+                book_index(line, book_idx_tmp, an_object, type);
               } else {
-              /+ not book_index +/
+                /+ not book_index +/
                 if (auto m = match(line, rgx.comment)) {
-                /+ matched comment +/
+                  /+ matched comment +/
                   debug(comment) {
                     tell_l("blue", line);
                   }
-                  object["obj"] ~= line ~= "\n";
-                  contents ~=
-                    set_oa.contents_comment(strip(object["obj"]));
-                  object.remove("obj");
-                  object.remove("markup");
-                  object.remove("is");
-                  object.remove("attrib");
-                  object.remove("bookindex");
+                  an_object["obj"] ~= line ~= "\n";
+                  contents_the_objects ~=
+                    set_abstract_object.contents_comment(strip(an_object["obj"]));
+                  header_set_common(line_occur, an_object, type);
                   processing.remove("verse");
-                  line_occur["header_metadata"] = 0;
-                  line_occur["header_make"] = 0;
-                  line_occur["heading"] = 0;
-                  line_occur["para"] = 0;
-                  ft["header"] = 0;
-                  ft["header_make"] = 0;
-                  ft["header_metadata"] = 0;
-                  ft["heading"] = 0;
-                  ft["para"] = 0;
-                  counter++;
-                } else if (auto m = match(line, rgx.header_make)) {
-                /+ matched header_make +/
-                  debug(header1) {                          // header
-                    tell_l("yellow", line);
-                  }
-                  ft["header"] = 1;
-                  ft["header_make"] = 1;
-                  ft["header_metadata"] = 0;
-                  ft["heading"] = 0;
-                  ft["para"] = 0;
-                  line_occur["header_make"]++;
-                  object["obj"] ~= line ~= "\n";
-                } else if (auto m = match(line, rgx.header_metadata)) {
-                /+ matched header_metadata +/
-                  debug(header1) {                          // header
-                    tell_l("yellow", line);
-                  }
-                  ft["header"] = 1;
-                  ft["header_make"] = 0;
-                  ft["header_metadata"] = 1;
-                  ft["heading"] = 0;
-                  ft["para"] = 0;
-                  line_occur["header_metadata"]++;
-                  object["obj"] ~= line ~= "\n";
-                } else if (ft["header_make"] == 1
-                && (line_occur["header_make"] > 0)) {
-                /+ header_make flag set +/
-                  if (auto m = match(line, rgx.header_sub)) {
-                  /+ sub-header +/
-                    debug(header1) {
-                      tell_l("yellow", line);
-                    }
-                    line_occur["header_make"]++;
-                    object["obj"] ~= line ~= "\n";
-                  }
-                } else if (ft["header_metadata"] == 1
-                && (line_occur["header_metadata"] > 0)) {
-                /+ header_metadata flag set +/
-                  if (auto m = match(line, rgx.header_sub)) {
-                  /+ sub-header +/
-                    debug(header1) {
-                      tell_l("yellow", line);
-                    }
-                    line_occur["header_metadata"]++;
-                    object["obj"] ~= line ~= "\n";
-                  }
-                } else if (((line_occur["para"] == 0)
-                && (line_occur["heading"] == 0))
-                && ((ft["para"] == 0)
-                && (ft["heading"] == 0))) {
-                /+ heading or para but neither flag nor line exists +/
+                  type["header_make"] = State.off;
+                  type["header_metadata"] = State.off;
+                  ++counter;
+                } else if ((match(line, rgx.header_make))
+                  || (match(line, rgx.header_metadata))
+                  || (type["header_make"] == State.on
+                  && (line_occur["header_make"] > State.off))
+                  || (type["header_metadata"] == State.on
+                  && (line_occur["header_metadata"] > State.off))) {
+                    header_extract(line, line_occur, an_object, type);
+                } else if (((line_occur["para"] == State.off)
+                && (line_occur["heading"] == State.off))
+                && ((type["para"] == State.off)
+                && (type["heading"] == State.off))) {
+                  /+ heading or para but neither flag nor line exists +/
                   if ((to!string(dochead_make["make"]["headings"]).length > 2)
-                  && (ft["make_headings"] == 0)) {
-                  /+ headings found +/
-                    debug(headingsfound) {
-                      writeln(dochead_make["make"]["headings"]);
-                    }
-                    auto make_headings_txt =
-                      match(
-                        to!string(dochead_make["make"]["headings"]),
-                        rgx.within_quotes);
-                    char[][] make_headings_spl =
-                      split(
-                        cast(char[]) make_headings_txt.captures[1],
-                        rgx.make_heading_delimiter);
-                    debug(headingsfound) {
-                      writeln(make_headings_spl.length);
-                      writeln(make_headings_spl);
-                    }
-                    switch (make_headings_spl.length) {
-                    case 7 :
-                      if (!empty(make_headings_spl[6])) {
-                        str_h_4 = "^(" ~ to!string(make_headings_spl[6]) ~ ")";
-                        rgx_h_4 = regex(str_h_4);
-                      }
-                      goto case;
-                    case 6 :
-                      if (!empty(make_headings_spl[5])) {
-                        str_h_3 = "^(" ~ to!string(make_headings_spl[5]) ~ ")";
-                        rgx_h_3 = regex(str_h_3);
-                      }
-                      goto case;
-                    case 5 :
-                      if (!empty(make_headings_spl[4])) {
-                        str_h_2 = "^(" ~ to!string(make_headings_spl[4]) ~ ")";
-                        rgx_h_2 = regex(str_h_2);
-                      }
-                      goto case;
-                    case 4 :
-                      if (!empty(make_headings_spl[3])) {
-                        str_h_1 = "^(" ~ to!string(make_headings_spl[3]) ~ ")";
-                        rgx_h_1 = regex(str_h_1);
-                      }
-                      goto case;
-                    case 3 :
-                      if (!empty(make_headings_spl[2])) {
-                        str_h_D = "^(" ~ to!string(make_headings_spl[2]) ~ ")";
-                        rgx_h_D = regex(str_h_D);
-                      }
-                      goto case;
-                    case 2 :
-                      if (!empty(make_headings_spl[1])) {
-                        str_h_C = "^(" ~ to!string(make_headings_spl[1]) ~ ")";
-                        rgx_h_C = regex(str_h_C);
-                      }
-                      goto case;
-                    case 1 :
-                      if (!empty(make_headings_spl[0])) {
-                        str_h_B = "^(" ~ to!string(make_headings_spl[0]) ~ ")";
-                        rgx_h_B = regex(str_h_B);
-                      }
-                      break;
-                    default:
-                      break;
-                    }
-                    ft["make_headings"] = 1;
+                  && (type["make_headings"] == State.off)) {
+                    /+ heading found +/
+                    auto dochead_make_headings =
+                      to!string(dochead_make["make"]["headings"]);
+                    heading_found(line, dochead_make_headings, heading_match_str, heading_match_rgx, type);
                   }
-                  if ((ft["make_headings"] == 1)
-                  && ((line_occur["para"] == 0)
-                  && (line_occur["heading"] == 0))
-                  && ((ft["para"] == 0)
-                  && (ft["heading"] == 0))) {
-                  /+ heading make set +/
-                    if (match(line, rgx_h_B)) {
-                      line = "B~ " ~ line;
-                      debug(headingsfound) {
-                        writeln(line);
-                      }
-                    }
-                    if (match(line, rgx_h_C)) {
-                      line = "C~ " ~ line;
-                      debug(headingsfound) {
-                        writeln(line);
-                      }
-                    }
-                    if (match(line, rgx_h_D)) {
-                      line = "D~ " ~ line;
-                      debug(headingsfound) {
-                        writeln(line);
-                      }
-                    }
-                    if (match(line, rgx_h_1)) {
-                      line = "1~ " ~ line;
-                      debug(headingsfound) {
-                        writeln(line);
-                      }
-                    }
-                    if (match(line, rgx_h_2)) {
-                      line = "2~ " ~ line;
-                      debug(headingsfound) {
-                        writeln(line);
-                      }
-                    }
-                    if (match(line, rgx_h_3)) {
-                      line = "3~ " ~ line;
-                      debug(headingsfound) {
-                        writeln(line);
-                      }
-                    }
-                    if (match(line, rgx_h_4)) {
-                      line = "4~ " ~ line;
-                      debug(headingsfound) {
-                        writeln(line);
-                      }
-                    }
+                  if ((type["make_headings"] == State.on)
+                  && ((line_occur["para"] == State.off)
+                  && (line_occur["heading"] == State.off))
+                  && ((type["para"] == State.off)
+                  && (type["heading"] == State.off))) {
+                    /+ heading make set +/
+                    heading_make_set(line, line_occur, heading_match_rgx, type);
                   }
                   if (auto m = match(line, rgx.heading)) {
-                  /+ heading match +/
-                    ft["heading"] = 1;
-                    ft["header"] = 0;
-                    ft["header_make"] = 0;
-                    ft["header_metadata"] = 0;
-                    ft["heading_biblio"] = 0;
-                    ft["para"] = 0;
-                    line_occur["heading"]++;
-                    object["obj"] ~= line ~= "\n";
-                    object["lev"] ~= m.captures[1];
-                    assertions_doc_structure(object, lv); // includes most of the logic for collapsed levels
-                    switch (to!string(object["lev"])) {
-                    case "A":
-                      object["lvn"]="0";
-                      lv["lv"] = 0;
-                      lv["h0"]++;
-                      lv["h1"] = 0;
-                      lv["h2"] = 0;
-                      lv["h3"] = 0;
-                      lv["h4"] = 0;
-                      lv["h5"] = 0;
-                      lv["h6"] = 0;
-                      lv["h7"] = 0;
-                      collapsed_lev["h0"] = 1;
-                      object["lcn"] = to!string(collapsed_lev["h0"]);
-                      break;
-                    case "B":
-                      collapsed_lev["h1"] = collapsed_lev["h0"] + 1;
-                      object["lcn"] = to!string(collapsed_lev["h1"]);
-                      object["lvn"]="1";
-                      lv["lv"] = 1;
-                      lv["h1"]++;
-                      lv["h2"] = 0;
-                      lv["h3"] = 0;
-                      lv["h4"] = 0;
-                      lv["h5"] = 0;
-                      lv["h6"] = 0;
-                      lv["h7"] = 0;
-                      break;
-                    case "C":
-                      collapsed_lev["h2"] = collapsed_lev["h1"] + 1;
-                      object["lcn"] = to!string(collapsed_lev["h2"]);
-                      object["lvn"]="2";
-                      lv["lv"] = 2;
-                      lv["h2"]++;
-                      lv["h3"] = 0;
-                      lv["h4"] = 0;
-                      lv["h5"] = 0;
-                      lv["h6"] = 0;
-                      lv["h7"] = 0;
-                      break;
-                    case "D":
-                      collapsed_lev["h3"] = collapsed_lev["h2"] + 1;
-                      object["lcn"] = to!string(collapsed_lev["h3"]);
-                      object["lvn"]="3";
-                      lv["lv"] = 3;
-                      lv["h3"]++;
-                      lv["h4"] = 0;
-                      lv["h5"] = 0;
-                      lv["h6"] = 0;
-                      lv["h7"] = 0;
-                      break;
-                    case "1":
-                      if (lv["h3"] > 0) {
-                        collapsed_lev["h4"] = collapsed_lev["h3"] + 1;
-                      } else if (lv["h2"] > 0) {
-                        collapsed_lev["h4"] = collapsed_lev["h2"] + 1;
-                      } else if (lv["h1"] > 0) {
-                        collapsed_lev["h4"] = collapsed_lev["h1"] + 1;
-                      } else if (lv["h0"] > 0) {
-                        collapsed_lev["h4"] = collapsed_lev["h0"] + 1;
-                      }
-                      object["lcn"] = to!string(collapsed_lev["h4"]);
-                      object["lvn"]="4";
-                      lv["lv"] = 4;
-                      lv["h4"]++;
-                      lv["h5"] = 0;
-                      lv["h6"] = 0;
-                      lv["h7"] = 0;
-                      break;
-                    case "2":
-                      if (lv["h5"] > 0) {
-                        object["lcn"] = to!string(collapsed_lev["h5"]);
-                      } else if (lv["h4"] > 0) {
-                        collapsed_lev["h5"] = collapsed_lev["h4"] + 1;
-                        object["lcn"] = to!string(collapsed_lev["h5"]);
-                      }
-                      object["lvn"]="5";
-                      lv["lv"] = 5;
-                      lv["h5"]++;
-                      lv["h6"] = 0;
-                      lv["h7"] = 0;
-                      break;
-                    case "3":
-                      if (lv["h6"] > 0) {
-                        object["lcn"] = to!string(collapsed_lev["h6"]);
-                      } else if (lv["h5"] > 0) {
-                        collapsed_lev["h6"] = collapsed_lev["h5"] + 1;
-                        object["lcn"] = to!string(collapsed_lev["h6"]);
-                      }
-                      object["lvn"]="6";
-                      lv["lv"] = 6;
-                      lv["h6"]++;
-                      lv["h7"] = 0;
-                      break;
-                    case "4":
-                      if (lv["h7"] > 0) {
-                        object["lcn"] = to!string(collapsed_lev["h7"]);
-                      } else if (lv["h6"] > 0) {
-                        collapsed_lev["h7"] = collapsed_lev["h6"] + 1;
-                        object["lcn"] = to!string(collapsed_lev["h7"]);
-                      }
-                      object["lvn"]="7";
-                      lv["lv"] = 7;
-                      lv["h7"]++;
-                      break;
-                    default:
-                      break;
-                    }
-                    debug(heading) {                         // heading
-                      tell_l("yellow", strip(line));
-                    }
-                  } else if (line_occur["para"] == 0) {
-                  /+ para matches +/
-                    if (auto m = match(line, rgx.para_indent)) {
-                      debug(paraindent) {                    // para indent
-                        tell_l("blue", line);
-                      }
-                      ft["para"] = 1;
-                      object["obj"] ~= line ~= "\n";
-                      indent_first = to!string(m.captures[1]);
-                      indent_second = "0";
-                      bullet = false;
-                    } else if (auto m = match(line, rgx.para_bullet)) {
-                      debug(parabullet) {                    // para bullet
-                        tell_l("blue", line);
-                      }
-                      ft["para"] = 1;
-                      object["obj"] ~= line;
-                      indent_first = "0";
-                      indent_second = "0";
-                      bullet = true;
-                    } else if (auto m = match(line, rgx.para_indent_hang)) {
-                      debug(paraindenthang) {                // para indent hang
-                        tell_l("blue", line);
-                      }
-                      ft["para"] = 1;
-                      object["obj"] ~= line;
-                      indent_first = to!string(m.captures[1]);
-                      indent_second = to!string(m.captures[2]);
-                      bullet = false;
-                    } else if (auto m = match(line, rgx.para_bullet_indent)) {
-                      debug(parabulletindent) {              // para bullet indent
-                        tell_l("blue", line);
-                      }
-                      ft["para"] = 1;
-                      object["obj"] ~= line;
-                      indent_first = to!string(m.captures[1]);
-                      indent_second = "0";
-                      bullet = true;
-                    } else {
-                      ft["para"] = 1;
-                      object["obj"] ~= line;
-                      indent_first = "0";
-                      indent_second = "0";
-                      bullet = false;
-                    }
-                    line_occur["para"]++;
+                    /+ heading match +/
+                    heading_match(line, line_occur, an_object, lv, collapsed_lev, type);
+                  } else if (line_occur["para"] == State.off) {
+                    /+ para match +/
+                    para_match(line, an_object, indent, bullet, type);
                   }
-                } else if (line_occur["header_make"] > 0) {
-                /+ header_make +/
-                // should be caught by sub-header
+                } else if (line_occur["header_make"] > State.off) {
+                  /+ header_make +/
+                  // should be caught by sub-header
                   debug(header) {
                     tell_l("red", line);
                   }
-                  object["obj"] ~= line ~= "\n";
-                  line_occur["header_make"]++;
-                } else if (line_occur["header_metadata"] > 0) {
-                /+ header_metadata +/
-                // should be caught by sub-header
+                  an_object["obj"] ~= line ~= "\n";
+                  ++line_occur["header_make"];
+                } else if (line_occur["header_metadata"] > State.off) {
+                  /+ header_metadata +/
+                  // should be caught by sub-header
                   debug(header) {                          // para
                     tell_l("red", line);
                   }
-                  object["obj"] ~= line ~= "\n";
-                  line_occur["header_metadata"]++;
-                } else if (line_occur["heading"] > 0) {
-                /+ heading +/
+                  an_object["obj"] ~= line ~= "\n";
+                  ++line_occur["header_metadata"];
+                } else if (line_occur["heading"] > State.off) {
+                  /+ heading +/
                   debug(heading) {                         // heading
                     tell_l("blue", line);
                   }
-                  object["obj"] ~= line ~= "\n";
-                  line_occur["heading"]++;
-                } else if (line_occur["para"] > 0) {
-                /+ paragraph +/
+                  an_object["obj"] ~= line ~= "\n";
+                  ++line_occur["heading"];
+                } else if (line_occur["para"] > State.off) {
+                  /+ paragraph +/
                   debug(para) {
                     tell_l("blue", line);
                   }
-                  object["obj"] ~= line;
-                  line_occur["para"]++;
+                  an_object["obj"] ~= line;
+                  ++line_occur["para"];
                 }
               }
-            } else if (ft["blocks"] == 2) {
-            /+ line empty, with blocks flag +/
-              assert(
-                line.empty,
-                "line should be empty"
-              );
-              assert(
-                (ft["blocks"] == 2),
-                "code block status: closed"
-              );
-              assertions_flag_types_block_status_none_or_closed(ft);
-              if (ft["code"] == 2) {
-                ocn = ocn_emit(ft["ocn_status"]);
-                object["bookindex"] =
-                  ("bookindex" in object) ? object["bookindex"] : "";
-                bookindex_unordered_hashes =
-                  bkidx_hash(object["bookindex"], ocn);
-                object["is"] = "code";
-                node =
-                  node_jstr(
-                    content_non_header,
-                    ocn,
-                    counter,
-                    heading_pointer-1,
-                    object["is"]
-                  );
-                object["markup"] =
-                  obj_im.obj_inline_markup(object["is"], object["obj"]);
-                object["attrib"] =
-                  obj_att.obj_attributes(object["is"], object["obj"], node);
-                contents ~=
-                  set_oa.contents_block(
-                    object["is"],
-                    object["markup"],
-                    object["attrib"],
-                    ocn
-                  );
-                object.remove("obj");
-                object.remove("markup");
-                object.remove("is");
-                object.remove("attrib");
-                object.remove("bookindex");
-                processing.remove("verse");
-                counter++;
-                ft["blocks"] = 0;
-                ft["code"] = 0;
-              } else if (ft["poem"] == 2) {
-                object["bookindex"] =
-                  ("bookindex" in object) ? object["bookindex"] : "";
-                bookindex_unordered_hashes =
-                  bkidx_hash(object["bookindex"], ocn);
-                object["is"] = "verse"; // check also
-                node =
-                  node_jstr(
-                    content_non_header,
-                    ocn,
-                    counter,
-                    heading_pointer-1,
-                    object["is"]
-                  );
-                contents ~=
-                  set_oa.contents_block_ocn_string(
-                    "poem",
-                    "",
-                    (ocn_poem["start"], ocn_poem["end"]),
-                    node
-                  ); // bookindex
-                object.remove("obj");
-                object.remove("markup");
-                object.remove("is");
-                object.remove("attrib");
-                object.remove("bookindex");
-                processing.remove("verse");
-                ft["blocks"] = 0;
-                ft["poem"] = 0;
-              } else if (ft["table"] == 2) {
-                ocn = ocn_emit(ft["ocn_status"]);
-                object["bookindex"] =
-                  ("bookindex" in object) ? object["bookindex"] : "";
-                bookindex_unordered_hashes =
-                  bkidx_hash(object["bookindex"], ocn);
-                object["is"] = "table";
-                node =
-                  node_jstr(
-                    content_non_header,
-                    ocn,
-                    counter,
-                    heading_pointer-1,
-                    object["is"]
-                  );
-                object["markup"] =
-                  obj_im.obj_inline_markup(object["is"], object["obj"]);
-                object["attrib"] =
-                  obj_att.obj_attributes(object["is"], object["obj"], node);
-                contents ~=
-                  set_oa.contents_block(
-                    object["is"],
-                    object["markup"],
-                    object["attrib"],
-                    ocn
-                  );
-                object.remove("obj");
-                object.remove("markup");
-                object.remove("is");
-                object.remove("attrib");
-                object.remove("bookindex");
-                processing.remove("verse");
-                counter++;
-                ft["blocks"] = 0;
-                ft["table"] = 0;
-              } else if (ft["group"] == 2) {
-                ocn = ocn_emit(ft["ocn_status"]);
-                object["bookindex"] = ("bookindex" in object) ? object["bookindex"] : "";
-                bookindex_unordered_hashes = bkidx_hash(object["bookindex"], ocn);
-                object["is"] = "group";
-                node =
-                  node_jstr(
-                    content_non_header,
-                    ocn,
-                    counter,
-                    heading_pointer-1,
-                    object["is"]
-                  );
-                object["markup"] =
-                  obj_im.obj_inline_markup(object["is"], object["obj"]);
-                object["attrib"] =
-                  obj_att.obj_attributes(object["is"], object["obj"], node);
-                contents ~=
-                  set_oa.contents_block(
-                    object["is"],
-                    object["markup"],
-                    object["attrib"],
-                    ocn
-                  );
-                object.remove("obj");
-                object.remove("markup");
-                object.remove("is");
-                object.remove("attrib");
-                object.remove("bookindex");
-                processing.remove("verse");
-                counter++;
-                ft["blocks"] = 0;
-                ft["group"] = 0;
-              } else if (ft["block"] == 2) {
-                ocn = ocn_emit(ft["ocn_status"]);
-                object["bookindex"] = ("bookindex" in object) ? object["bookindex"] : "";
-                bookindex_unordered_hashes = bkidx_hash(object["bookindex"], ocn);
-                object["is"] = "block";
-                node =
-                  node_jstr(
-                    content_non_header,
-                    ocn,
-                    counter,
-                    heading_pointer-1,
-                    object["is"]
-                   );
-                object["markup"] =
-                  obj_im.obj_inline_markup(object["is"], object["obj"]);
-                object["attrib"] =
-                  obj_att.obj_attributes(object["is"], object["obj"], node);
-                contents ~=
-                  set_oa.contents_block(
-                    object["is"],
-                    object["markup"],
-                    object["attrib"],
-                    ocn
-                  );
-                object.remove("obj");
-                object.remove("markup");
-                object.remove("is");
-                object.remove("attrib");
-                object.remove("bookindex");
-                processing.remove("verse");
-                counter++;
-                ft["blocks"] = 0;
-                ft["block"] = 0;
-              } else if (ft["quote"] == 2) {
-                ocn = ocn_emit(ft["ocn_status"]);
-                object["bookindex"] = ("bookindex" in object) ? object["bookindex"] : "";
-                bookindex_unordered_hashes =
-                  bkidx_hash(object["bookindex"], ocn);
-                object["is"] = "quote";
-                node =
-                  node_jstr(
-                    content_non_header,
-                    ocn,
-                    counter,
-                    heading_pointer-1,
-                    object["is"]
-                  );
-                object["markup"] =
-                  obj_im.obj_inline_markup(object["is"], object["obj"]);
-                object["attrib"] =
-                  obj_att.obj_attributes(object["is"], object["obj"], node);
-                contents ~=
-                  set_oa.contents_block(
-                    object["is"],
-                    object["markup"],
-                    object["attrib"],
-                    ocn
-                  );
-                object.remove("obj");
-                object.remove("markup");
-                object.remove("is");
-                object.remove("attrib");
-                object.remove("bookindex");
-                processing.remove("verse");
-                counter++;
-                ft["blocks"] = 0;
-                ft["quote"] = 0;
-              }
+            } else if (type["blocks"] == TriState.closing) {
+              /+ line empty, with blocks flag +/
+              block_flag_line_empty(line, an_object, contents_the_objects, bookindex_unordered_hashes, obj_cite_number, node, counter, type, obj_cite_number_poem); // watch
             } else {
             /+ line empty +/
               /+ line.empty, post contents, empty variables: +/
@@ -1513,156 +408,122 @@ mixin template SiSUdocAbstraction() {
                 "line should be empty"
               );
               assert(
-                (ft["blocks"] == 0),
+                (type["blocks"] == State.off),
                 "code block status: none"
               );
-              if ((ft["header_make"] == 1)
-              && (line_occur["header_make"] > 0)) {
-              /+ header_make instructions (current line empty) +/
+              if ((type["header_make"] == State.on)
+              && (line_occur["header_make"] > State.off)) {
+                /+ header_make instructions (current line empty) +/
                 auto dochead_metadata_and_make =
-                  set_header.header_metadata_and_make_jsonstr(strip(object["obj"]), dochead_metadata, dochead_make);
+                  set_header.header_metadata_and_make_jsonstr(strip(an_object["obj"]), dochead_metadata, dochead_make);
                 static assert(!isTypeTuple!(dochead_metadata_and_make));
                 dochead_metadata = dochead_metadata_and_make[0];
                 dochead_make = dochead_metadata_and_make[1];
-                line_occur["header_make"] = 0;
-                line_occur["header_metadata"] = 0;
-                line_occur["heading"] = 0;
-                line_occur["para"]= 0;
-                ft["header"] = 0;
-                ft["heading"] = 0;
-                ft["para"] = 0;
-                object.remove("obj");
-                object.remove("markup");
-                object.remove("is");
-                object.remove("attrib");
-                object.remove("bookindex");
+                header_set_common(line_occur, an_object, type);
                 processing.remove("verse");
-              } else if ((ft["header_metadata"] == 1)
-              && (line_occur["header_metadata"] > 0)) {
-              /+ header_metadata (current line empty) +/
+              } else if ((type["header_metadata"] == State.on)
+              && (line_occur["header_metadata"] > State.off)) {
+                /+ header_metadata (current line empty) +/
                 auto dochead_metadata_and_make =
-                  set_header.header_metadata_and_make_jsonstr(strip(object["obj"]), dochead_metadata, dochead_make);
+                  set_header.header_metadata_and_make_jsonstr(strip(an_object["obj"]), dochead_metadata, dochead_make);
                 static assert(!isTypeTuple!(dochead_metadata_and_make));
                 dochead_metadata = dochead_metadata_and_make[0];
                 dochead_make = dochead_metadata_and_make[1];
-                line_occur["header_make"] = 0;
-                line_occur["header_metadata"] = 0;
-                line_occur["heading"] = 0;
-                line_occur["para"]= 0;
-                ft["header"] = 0;
-                ft["header_make"] = 0;
-                ft["header_metadata"] = 0;
-                ft["heading"] = 0;
-                ft["para"] = 0;
-                object.remove("obj");
-                object.remove("markup");
-                object.remove("is");
-                object.remove("attrib");
-                object.remove("bookindex");
+                header_set_common(line_occur, an_object, type);
+                type["header_make"] = State.off;
+                type["header_metadata"] = State.off;
                 processing.remove("verse");
-              } else if ((ft["heading"] == 1)
-              && (line_occur["heading"] > 0)) {
-              /+ heading object (current line empty) +/
-                ocn = ocn_emit(ft["ocn_status"]);
-                object["bookindex"] =
-                  ("bookindex" in object) ? object["bookindex"] : "";
+              } else if ((type["heading"] == State.on)
+              && (line_occur["heading"] > State.off)) {
+                /+ heading object (current line empty) +/
+                obj_cite_number = obj_cite_number_emit(type["obj_cite_number_status"]);
+                an_object["bookindex"] =
+                  ("bookindex" in an_object) ? an_object["bookindex"] : "";
                 bookindex_unordered_hashes =
-                  bkidx_hash(object["bookindex"], ocn);
-                object["is"] = "heading";
+                  bkidx_hash(an_object["bookindex"], obj_cite_number);
+                an_object["is"] = "heading";
                 node =
                   node_jstr_heading(
-                    object["lvn"],
-                    object["lcn"],
-                    ocn,
+                    an_object["lev_markup_number"],
+                    an_object["lev_collapsed_number"],
+                    obj_cite_number,
                     counter,
                     heading_pointer,
-                    object["is"]
+                    an_object["is"]
                   ); // heading
-                object["markup"] =
-                  obj_im.obj_inline_markup(object["is"], object["obj"]);
-                object["attrib"] =
-                  obj_att.obj_attributes(object["is"], object["obj"], node);
-                heading_pointer++;
-                contents ~=
-                  set_oa.contents_heading(
-                    ft["ocn_status"],
-                    object["markup"],
-                    object["attrib"],
-                    ocn, object["lev"],
-                    object["lvn"],
-                    object["lcn"]
+                an_object["substantive"] =
+                  obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+                an_object["attrib"] =
+                  obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+                ++heading_pointer;
+                contents_the_objects ~=
+                  set_abstract_object.contents_heading(
+                    type["obj_cite_number_status"],
+                    an_object["substantive"],
+                    an_object["attrib"],
+                    obj_cite_number, an_object["lev"],
+                    an_object["lev_markup_number"],
+                    an_object["lev_collapsed_number"]
                   );
                 // track previous heading and make assertions
                 debug(objectrelated1) { // check
                   tell_l("blue", line);
+                  // writeln(an_object["obj"]);
+                  // writeln(contents_am[counter]["obj_cite_number"], " ", contents_am[counter]["obj"]);
+                  // writeln(m.hit, "\n");
                 }
-                line_occur["header_make"] = 0;
-                line_occur["header_metadata"] = 0;
-                line_occur["heading"] = 0;
-                line_occur["para"] = 0;
-                ft["header"] = 0;
-                ft["header_make"] = 0;
-                ft["header_metadata"] = 0;
-                ft["heading"] = 0;
-                ft["para"] = 0;
-                object.remove("obj");
-                object.remove("markup");
-                object.remove("is");
-                object.remove("attrib");
-                object.remove("lev");
-                object.remove("lvn");
-                object.remove("bookindex");
+                header_set_common(line_occur, an_object, type);
+                type["header_make"] = State.off;
+                type["header_metadata"] = State.off;
+                an_object.remove("lev");
+                an_object.remove("lev_markup_number");
+                // an_object["lev_markup_number"]="9";
                 processing.remove("verse");
-                counter++;
-              } else if ((ft["para"] == 1) && (line_occur["para"] > 0)) {
-              /+ paragraph object (current line empty) +/
-                ocn = ocn_emit(ft["ocn_status"]);
-                object["bookindex"] =
-                  ("bookindex" in object) ? object["bookindex"] : "";
+                ++counter;
+              } else if ((type["para"] == State.on) && (line_occur["para"] > State.off)) {
+                /+ paragraph object (current line empty) +/
+                obj_cite_number = obj_cite_number_emit(type["obj_cite_number_status"]);
+                an_object["bookindex"] =
+                  ("bookindex" in an_object) ? an_object["bookindex"] : "";
                 bookindex_unordered_hashes =
-                  bkidx_hash(object["bookindex"], ocn);
-                object["is"] = "para";
+                  bkidx_hash(an_object["bookindex"], obj_cite_number);
+                an_object["is"] = "para";
                 node =
                   node_jstr(
                     content_non_header,
-                    ocn,
+                    obj_cite_number,
                     counter,
                     heading_pointer-1,
-                    object["is"]
+                    an_object["is"]
                   );
-                object["markup"] =
-                  obj_im.obj_inline_markup(object["is"], object["obj"]);
-                object["attrib"] =
-                  obj_att.obj_attributes(object["is"], object["obj"], node);
-                contents ~=
-                  set_oa.contents_para(
-                    object["is"],
-                    object["markup"],
-                    object["attrib"],
-                    ocn,
-                    indent_first,
-                    indent_second,
+                an_object["substantive"] =
+                  obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+                an_object["attrib"] =
+                  obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+                contents_the_objects ~=
+                  set_abstract_object.contents_para(
+                    an_object["is"],
+                    an_object["substantive"],
+                    an_object["attrib"],
+                    obj_cite_number,
+                    indent,
                     bullet
                   );
-                line_occur["header_make"] = 0;
-                line_occur["header_metadata"] = 0;
-                line_occur["heading"] = 0;
-                line_occur["para"] = 0;
-                ft["header"] = 0;
-                ft["header_make"] = 0;
-                ft["header_metadata"] = 0;
-                ft["heading"] = 0;
-                ft["para"] = 0;
-                indent_first = "0";
-                indent_second = "0";
+                // contents_the_objects ~=
+                //   set_abstract_object.contents_para(
+                //     an_object,
+                //     obj_cite_number,
+                //     indent,
+                //     bullet
+                //   );
+                header_set_common(line_occur, an_object, type);
+                type["header_make"] = State.off;
+                type["header_metadata"] = State.off;
+                indent["first"] = "0";
+                indent["second"] = "0";
                 bullet = false;
-                object.remove("obj");
-                object.remove("markup");
-                object.remove("is");
-                object.remove("attrib");
-                object.remove("bookindex");
                 processing.remove("verse");
-                counter++;
+                ++counter;
               } else {
                 assert(
                   line == null,
@@ -1673,25 +534,32 @@ mixin template SiSUdocAbstraction() {
             } // close else for line empty
           } // close else for not the above
         } // close after non code, other blocks or regular text
-        if (((contents[$-1]["is"] == "para")
-        || (contents[$-1]["is"] == "heading"))
+        if (((contents_the_objects[$-1]["is"] == "para")
+        || (contents_the_objects[$-1]["is"] == "heading"))
         && (counter-1 > previous_count)) {
-          if (match(contents[$-1]["obj"],
+          if (match(contents_the_objects[$-1]["obj"],
           rgx.inline_notes_delimiter_al_regular_number_note)) {
             // endnotes/ footnotes for
             // doc objects other than paragraphs & headings
             // various forms of grouped text
-            previous_count=contents.length -1;
-            notesection.gather_notes_for_endnote_section(
-              contents,
-              contents.length -1
+            previous_count=contents_the_objects.length -1;
+            note_section.gather_notes_for_endnote_section(
+              contents_the_objects,
+              contents_the_objects.length -1
             );
+            // notes[notepoint]=note_section.notes_section(contents_the_objects, counter-1);
+            // notepoint +=1;
           }
         }
       } /+ ← closed: loop markup document/text line by line +/
+
       /+ ↓ post loop markup document/text +/
       debug(objectrelated2) { // check
           tell_l("blue", line);
+        // writeln(__FILE__, ":", __LINE__);
+        // writeln(counter);
+        // // contents_am[0..counter]
+        // writeln(contents_am.length);
       }
       /+
         Backmatter:
@@ -1701,93 +569,3192 @@ mixin template SiSUdocAbstraction() {
         * book index
       +/
       obj_im.obj_inline_markup("doc_end_reset", "");
-      auto en_tuple = notesection.endnote_objects(ocn);
+      auto en_tuple =
+        note_section.endnote_objects(obj_cite_number);
       static assert(!isTypeTuple!(en_tuple));
-      auto endnotes = en_tuple[0];
-      ocn = en_tuple[1];
+      auto endnotes_section = en_tuple[0];
+      obj_cite_number = en_tuple[1];
       debug(endnotes) {
         writefln(
           "%s %s",
           __LINE__,
-          endnotes.length
+          endnotes_section.length
         );
-        foreach (n; endnotes) {
+        foreach (n; endnotes_section) {
           writeln(n);
         }
       }
       auto biblio_unsorted_incomplete = biblio_arr_json.dup;
+      // destroy(biblio_arr_json);
       auto biblio = Bibliography();
-      auto biblio_ordered = biblio.bibliography(biblio_unsorted_incomplete, bib_arr_json);
+      auto biblio_ordered =
+        biblio.bibliography(biblio_unsorted_incomplete, bib_arr_json);
       auto bi = BookIndexReportSection();
       auto bi_tuple =
-        bi.bookindex_build_section(bookindex_unordered_hashes, ocn);
+        bi.bookindex_build_section(bookindex_unordered_hashes, obj_cite_number);
       static assert(!isTypeTuple!(bi_tuple));
-      auto bookindex = bi_tuple[0];
-      auto document = contents ~ endnotes ~ bookindex;
-      ocn = bi_tuple[1];
+      auto bookindex_section = bi_tuple[0];
+      obj_cite_number = bi_tuple[1];
       debug(bookindex) {                         // bookindex
-        foreach (bi_entry; bookindex) {
+        foreach (bi_entry; bookindex_section) {
           writeln(bi_entry["obj"]);
         }
       }
+      auto document_the =
+        contents_the_objects ~ endnotes_section ~ bookindex_section;
       debug(heading) {                         // heading
         string spc;
-        foreach (o; document) {
+        foreach (o; document_the) {
           if (o["is"] == "heading") {
-            switch (o["lvn"]) {
+            switch (o["lev_markup_number"]) {
             case "0":
+            // case to!string(DocStructMarkupHeading.h_sect_A):
               spc="";
               break;
             case "1":
+            // case to!string(DocStructMarkupHeading.h_sect_B):
               spc="  ";
               break;
             case "2":
+            // case to!string(DocStructMarkupHeading.h_sect_C):
               spc="    ";
               break;
             case "3":
+            // case to!string(DocStructMarkupHeading.h_sect_D):
               spc="      ";
               break;
             case "4":
+            // case to!string(DocStructMarkupHeading.h_text_1):
               spc="        ";
               break;
             case "5":
+            // case to!string(DocStructMarkupHeading.h_text_2):
               spc="          ";
               break;
             case "6":
+            // case to!string(DocStructMarkupHeading.h_text_3):
               spc="            ";
               break;
             case "7":
+            // case to!string(DocStructMarkupHeading.h_text_4):
               spc="              ";
               break;
             case "8":
+            // case to!string(DocStructMarkupHeading.h_text_5):
               spc="                ";
               break;
             default:
               spc="";
               break;
             }
+            // writeln(
+            //   spc, "* ", " ",
+            //   o
+            // );
             writefln(
               "%s*  $s\n            %s",
               spc,
               strip(o["obj"]),
               o["attrib"]
             );
+            // writeln(spc, "* ", to!string(o["lev_collapsed_number"]), " ", strip(o["obj"]));
             // tell_l("yellow", spc, strip(o["obj"]));
           }
         }
       }
-      destroy(contents);
-      destroy(endnotes);
-      destroy(bookindex);
+      destroy(contents_the_objects);
+      destroy(endnotes_section);
+      destroy(bookindex_section);
+      // struct Document {
+      //   char content;
+      //   char head_make;
+      //   char head_metadata;
+      //   char bookindex_section;
+      //   char biblio;
+      // }
+      // struct Document {
+      //   char content;
+      //   char head_make;
+      //   char head_metadata;
+      //   char bookindex_section;
+      //   char biblio;
+      // }
       auto t =
         tuple(
-          document,
+          document_the,
           dochead_make,
           dochead_metadata,
           bookindex_unordered_hashes,
           biblio_ordered
         );
       return t;
+      /+ post loop markup document/text ↑ +/
+
+    } /+ ← closed: abstract doc source +/
+
+    /+ ↓ abstraction functions +/
+    auto object_reset(ref string[string] an_object) {
+      an_object.remove("obj");
+      an_object.remove("substantive");
+      an_object.remove("is");
+      an_object.remove("attrib");
+      an_object.remove("bookindex");
+    }
+    auto header_set_common(
+      ref int[string] line_occur,
+      ref string[string] an_object,
+      ref int[string] type
+    ) {
+      // line_occur["header"] = State.off;
+      line_occur["header_make"] = State.off;
+      line_occur["header_metadata"] = State.off;
+      line_occur["heading"] = State.off;
+      line_occur["para"]= State.off;
+      type["header"] = State.off;
+      // type["header_make"] = State.off;
+      // type["header_metadata"] = State.off;
+      type["heading"] = State.off;
+      type["para"] = State.off;
+      object_reset(an_object);
+    }
+    auto check_obj_cite_number_status(char[] line, ref int[string] type) {
+      if ((!line.empty) && (type["obj_cite_number_status_multi_obj"] == TriState.off)) {
+        /+ not multi-line object, check whether obj_cite_number is on or turned off +/
+        if (match(line, rgx.obj_cite_number_block_marks)) {
+          /+ switch off obj_cite_number +/
+          if (match(line, rgx.obj_cite_number_off_block)) {
+            type["obj_cite_number_status_multi_obj"] = TriState.on;
+            debug(ocnoff) {
+              tell_l("fuchsia", line);
+            }
+          }
+          if (match(line, rgx.obj_cite_number_off_block_dh)) {
+            type["obj_cite_number_status_multi_obj"] = TriState.closing;
+            debug(ocnoff) {
+              tell_l("fuchsia", line);
+            }
+          }
+        } else {
+          if (type["obj_cite_number_status_multi_obj"] == TriState.off) {
+            if (match(line, rgx.obj_cite_number_off)) {
+              type["obj_cite_number_status"] = TriState.on;
+            } else if (match(line, rgx.obj_cite_number_off_dh)) {
+              type["obj_cite_number_status"] = TriState.closing;
+            } else {
+              // type["obj_cite_number_status"] = TriState.closing;
+              type["obj_cite_number_status"] = TriState.off;
+            }
+          } else {
+            type["obj_cite_number_status"] =
+              type["obj_cite_number_status_multi_obj"];
+          }
+        }
+      } else if ((!line.empty) && (type["obj_cite_number_status_multi_obj"] > TriState.off)) {
+        if (auto m = match(line, rgx.obj_cite_number_off_block_close)) {
+          type["obj_cite_number_status_multi_obj"] = TriState.off;
+          type["obj_cite_number_status"] = TriState.off;
+          debug(ocnoff) {
+            tell_l("green", line);
+          }
+        }
+      }
+      return 0;
+    }
+    auto start_block(
+      char[] line,
+      ref int[string] type,
+      string[string] obj_cite_number_poem
+    ) {
+      if (match(line, rgx.block_curly_code_open)) {
+        /+ curly code open +/
+        debug(code) {                              // code (curly) open
+          writefln(
+            "%s* [code curly] %s%s",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        type["blocks"] = TriState.on;
+        type["code"] = TriState.on;
+        type["curly_code"] = TriState.on;
+      } else if (match(line, rgx.block_curly_poem_open)) {
+        /+ curly poem open +/
+        debug(poem) {                              // poem (curly) open
+          writefln(
+            "%s* [poem curly] %s%s",
+            scr_txt_color["red"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        obj_cite_number_poem["start"] =
+          to!string(obj_cite_number);
+        type["blocks"] = TriState.on;
+        type["verse_new"] = State.on;
+        type["poem"] = TriState.on;
+        type["curly_poem"] = TriState.on;
+      } else if (match(line, rgx.block_curly_group_open)) {
+        /+ curly group open +/
+        debug(group) {                             // group (curly) open
+          writefln(
+            "%s* [group curly] %s%s",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        type["blocks"] = TriState.on;
+        type["group"] = TriState.on;
+        type["curly_group"] = TriState.on;
+      } else if (match(line, rgx.block_curly_block_open)) {
+        /+ curly block open +/
+        debug(block) {                             // block (curly) open
+          writefln(
+            "%s* [block curly] %s%s",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        type["blocks"] = TriState.on;
+        type["block"] = TriState.on;
+        type["curly_block"] = TriState.on;
+      } else if (match(line, rgx.block_curly_quote_open)) {
+        /+ curly quote open +/
+        debug(quote) {                             // quote (curly) open
+          writefln(
+            "%s* [quote curly] %s%s",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        type["blocks"] = TriState.on;
+        type["quote"] = TriState.on;
+        type["curly_quote"] = TriState.on;
+      } else if (match(line, rgx.block_curly_table_open)) {
+        /+ curly table open +/
+        debug(table) {                             // table (curly) open
+          writefln(
+            "%s* [table curly] %s%s",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        type["blocks"] = TriState.on;
+        type["table"] = TriState.on;
+        type["curly_table"] = TriState.on;
+      } else if (match(line, rgx.block_tic_code_open)) {
+        /+ tic code open +/
+        debug(code) {                              // code (tic) open
+          writefln(
+            "%s* [code tic] %s%s",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        type["blocks"] = TriState.on;
+        type["code"] = TriState.on;
+        type["tic_code"] = TriState.on;
+      } else if (match(line, rgx.block_tic_poem_open)) {
+        /+ tic poem open +/
+        debug(poem) {                              // poem (tic) open
+          writefln(
+            "%s* [poem tic] %s%s",
+            scr_txt_color["red"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        obj_cite_number_poem["start"] = to!string(obj_cite_number);
+        type["blocks"] = TriState.on;
+        type["verse_new"] = State.on;
+        type["poem"] = TriState.on;
+        type["tic_poem"] = TriState.on;
+      } else if (match(line, rgx.block_tic_group_open)) {
+        /+ tic group open +/
+        debug(group) {                             // group (tic) open
+          writefln(
+            "%s* [group tic] %s%s",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        type["blocks"] = TriState.on;
+        type["group"] = TriState.on;
+        type["tic_group"] = TriState.on;
+      } else if (match(line, rgx.block_tic_block_open)) {
+        /+ tic block open +/
+        debug(block) {                             // block (tic) open
+          writefln(
+            "%s* [block tic] %s%s",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        type["blocks"] = TriState.on;
+        type["block"] = TriState.on;
+        type["tic_block"] = TriState.on;
+      } else if (match(line, rgx.block_tic_quote_open)) {
+        /+ tic quote open +/
+        debug(quote) {                             // quote (tic) open
+          writefln(
+            "%s* [quote tic] %s%s",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        type["blocks"] = TriState.on;
+        type["quote"] = TriState.on;
+        type["tic_quote"] = TriState.on;
+      } else if (match(line, rgx.block_tic_table_open)) {
+        /+ tic table open +/
+        debug(table) {                             // table (tic) open
+          writefln(
+            "%s* [table tic] %s%s",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            line
+          );
+        }
+        type["blocks"] = TriState.on;
+        type["table"] = TriState.on;
+        type["tic_table"] = TriState.on;
+      }
+      return 0;
+    }
+    auto code_block(
+      char[] line,
+      ref string[string] an_object,
+      ref int[string] type
+    ) {
+      if (type["curly_code"] == TriState.on) {
+        if (auto m = match(line, rgx.block_curly_code_close)) {
+          debug(code) {                              // code (curly) close
+            tell_l("blue", line);
+          }
+          type["blocks"] = TriState.closing;
+          type["code"] = TriState.closing;
+          type["curly_code"] = TriState.off;
+        } else {
+          debug(code) {                              // code (curly) line
+            tell_l("blue", line);
+          }
+          an_object["obj"] ~= line ~= "\n";                       // code (curly) line
+        }
+      } else if (type["tic_code"] == TriState.on) {
+        if (auto m = match(line, rgx.block_tic_close)) {
+          debug(code) {                              // code (tic) close
+            tell_l("blue", line);
+          }
+          type["blocks"] = TriState.closing;
+          type["code"] = TriState.closing;
+          type["tic_code"] = TriState.off;
+        } else {
+          debug(code) {                              // code (tic) line
+            tell_l("blue", line);
+          }
+          an_object["obj"] ~= line ~= "\n";                       // code (tic) line
+        }
+      }
+      return 0;
+    }
+    final string biblio_tag_map(string abr) {
+      auto btm = [
+        "au"                               : "author_raw",
+        "ed"                               : "editor_raw",
+        "ti"                               : "fulltitle",
+        "lng"                              : "language",
+        "jo"                               : "journal",
+        "vol"                              : "volume",
+        "edn"                              : "edition",
+        "yr"                               : "year",
+        "pl"                               : "place",
+        "pb"                               : "publisher",
+        "pub"                              : "publisher",
+        "pg"                               : "pages",
+        "pgs"                              : "pages",
+        "sn"                               : "short_name"
+      ];
+      return btm[abr];
+    }
+    auto biblio_block(
+      char[] line,
+      ref int[string] type,
+      ref int bib_entry,
+      ref string[] biblio_arr_json
+    ) {
+      if (match(line, rgx.heading_biblio)) {
+        type["heading_biblio"] = TriState.on;
+      }
+      if (empty(line) && (bib_entry == TriState.off)) {
+        biblio_arr_json ~= biblio_entry_tags_jsonstr;
+        bib_entry = TriState.on;
+      }
+      debug(biblio) {
+        writefln(
+          "%s * %s %s",
+          scr_txt_color["yellow"],
+          scr_txt_color["off"],
+          line
+        );
+      }
+      if (match(line, rgx.biblio_tags)) {
+        auto bt = match(line, rgx.biblio_tags);
+        bib_entry = 0;
+        st=to!string(bt.captures[1]);
+        biblio_tag_entry=to!string(bt.captures[2]);
+        JSONValue j = parseJSON(biblio_arr_json[$-1]);
+        biblio_tag_name = (match(st, rgx.biblio_abbreviations))
+          ? (biblio_tag_map(st))
+          : st;
+        j.object[biblio_tag_name] = biblio_tag_entry;
+        auto header_tag_value=to!string(bt.captures[2]);
+        switch (biblio_tag_name) {
+        case "author_raw": // author_arr author (fn sn)
+          j["author_arr"] =
+            split(header_tag_value, rgx.arr_delimiter);
+          string tmp;
+          biblioAuthorLoop:
+          foreach (au; j["author_arr"].array) {
+            if (auto x = match(au.str, rgx.name_delimiter)) {
+              tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", ";
+            } else {
+              tmp ~= au.str;
+            }
+          }
+          tmp = replace(tmp, rgx.trailing_comma, "");
+          // tmp = replace(tmp, regex(r"(,[ ]*)$","g"), "");
+          j["author"].str = tmp;
+          break;
+        case "editor_raw": // editor_arr editor (fn sn)
+          j["editor_arr"] =
+            split(header_tag_value, rgx.arr_delimiter);
+          string tmp;
+          biblioEditorLoop:
+          foreach (ed; j["editor_arr"].array) {
+            if (auto x = match(ed.str, rgx.name_delimiter)) {
+              tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", ";
+            } else {
+              tmp ~= ed.str;
+            }
+          }
+          tmp = replace(tmp, rgx.trailing_comma, "");
+          // tmp = replace(tmp, regex(r"(,[ ]*)$","g"), "");
+          j["editor"].str = tmp;
+          break;
+        case "fulltitle": // title & subtitle
+          break;
+        default:
+          break;
+        }
+        // header_tag_value="";
+        auto s = to!string(j);
+        s = j.toString();
+        debug(biblio) {
+          writefln(
+            "%s* %s%s: %s\n%s",
+            scr_txt_color["red"],
+            scr_txt_color["off"],
+            biblio_tag_name,
+            biblio_tag_entry,
+            j[biblio_tag_name]
+          );
+        }
+        biblio_arr_json ~= s;
+        biblio_tag_entry="";
+      }
+      return 0;
+    }
+    auto poem_block(
+      char[] line,
+      ref string[string] an_object,
+      ref int[string] type,
+      ref long counter,
+      string[string] obj_cite_number_poem
+    ) {
+      if (type["curly_poem"] == TriState.on) {
+        if (auto m = match(line, rgx.block_curly_poem_close)) {
+          an_object["obj"]="verse"; // check that this is as you please
+          debug(poem) {                            // poem (curly) close
+            writefln(
+              "%s* [poem curly] %s%s",
+              scr_txt_color["red"],
+              scr_txt_color["off"],
+              line
+            );
+          }
+          if (processing.length > 0) {
+            an_object["obj"] = processing["verse"];
+          }
+          debug(poem) {                            // poem (curly) close
+            writeln(__LINE__);
+            writefln(
+              "%s%s %s",
+              scr_txt_marker["fuchsia"],
+              obj_cite_number,
+              line
+            );
+            // writeln(an_object.keys);
+            // writeln(an_object.length);
+          }
+          if (an_object.length > 0) {
+            debug(poem) {                            // poem (curly) close
+              tell_lo(
+                "fuchsia",
+                obj_cite_number,
+                an_object["obj"]
+              );
+            }
+            an_object["is"] = "verse";
+            an_object["substantive"] =
+              obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+            an_object["attrib"] =
+              obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+            contents_the_objects ~=
+              set_abstract_object.contents_block(
+                an_object["is"],
+                an_object["substantive"],
+                an_object["attrib"],
+                obj_cite_number
+              );
+            object_reset(an_object);
+            processing.remove("verse");
+            ++counter;
+          }
+          obj_cite_number_poem["end"] =
+            to!string(obj_cite_number);
+          type["blocks"] = TriState.closing;
+          type["poem"] = TriState.closing;
+          type["curly_poem"] = TriState.off;
+        } else {
+          processing["verse"] ~= line ~= "\n";
+          if (type["verse_new"] == State.on) {
+            obj_cite_number =
+              obj_cite_number_emit(type["obj_cite_number_status"]);
+            type["verse_new"] = State.off;
+          } else if (match(line, rgx.line_delimiter_only)) {
+            verse_line = TriState.off;
+            type["verse_new"] = State.on;
+          }
+          if (type["verse_new"] == State.on) {
+            verse_line=1;
+            an_object["obj"] = processing["verse"];
+            debug(poem) {                          // poem verse
+              writefln(
+                "%s%s curly\n%s",
+                scr_txt_marker["green"],
+                obj_cite_number,
+                an_object["obj"]
+              );
+            }
+            processing.remove("verse");
+            an_object["is"] = "verse";
+            node = node_jstr(
+              content_non_header,
+              obj_cite_number,
+              counter,
+              heading_pointer-1,
+              an_object["is"]
+            );
+            an_object["substantive"] =
+              obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+            an_object["attrib"] =
+              obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+            contents_the_objects ~=
+              set_abstract_object.contents_block(
+                an_object["is"],
+                an_object["substantive"],
+                an_object["attrib"],
+                obj_cite_number
+              );
+            object_reset(an_object);
+            processing.remove("verse");
+            ++counter;
+          }
+        }
+      } else if (type["tic_poem"] == TriState.on) {
+        if (auto m = match(line, rgx.block_tic_close)) { // tic_poem_close
+          an_object["obj"]="verse"; // check that this is as you please
+          debug(poem) {                            // poem (curly) close
+            writefln(
+              "%s* [poem tic] %s%s",
+              scr_txt_color["red"],
+              scr_txt_color["off"],
+              line
+            );
+          }
+          if (processing.length > 0) {       // needs looking at
+            an_object["obj"] = processing["verse"];
+          }
+          if (an_object.length > 0) {
+            debug(poem) {                            // poem (tic) close
+              writeln(__LINE__);
+              tell_lo("fuchsia", obj_cite_number, line);
+            }
+            processing.remove("verse");
+            an_object["is"] = "verse";
+            an_object["substantive"] =
+              obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+            an_object["attrib"] =
+              obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+            contents_the_objects ~=
+              set_abstract_object.contents_block(
+                an_object["is"],
+                an_object["substantive"],
+                an_object["attrib"],
+                obj_cite_number
+              );
+            obj_cite_number_poem["end"] = to!string(obj_cite_number);
+            object_reset(an_object);
+            processing.remove("verse");
+            ++counter;
+          }
+          type["blocks"] = TriState.closing;
+          type["poem"] = TriState.closing;
+          type["tic_poem"] = TriState.off;
+        } else {
+          processing["verse"] ~= line ~= "\n";
+          if (type["verse_new"] == State.on) {
+            obj_cite_number =
+              obj_cite_number_emit(type["obj_cite_number_status"]);
+            type["verse_new"] = State.off;
+          } else if (match(line, rgx.line_delimiter_only)) {
+            type["verse_new"] = State.on;
+            verse_line = TriState.off;
+          }
+          if (type["verse_new"] == State.on) {
+            verse_line=1;
+            an_object["obj"] = processing["verse"];
+            debug(poem) {                            // poem (tic) close
+              writefln(
+                "%s%s tic\n%s",
+                scr_txt_marker["green"],
+                obj_cite_number,
+                an_object["obj"]
+              );
+            }
+            processing.remove("verse");
+            an_object["is"] = "verse";
+            node =
+              node_jstr(
+                content_non_header,
+                obj_cite_number,
+                counter,
+                heading_pointer-1,
+                an_object["is"]
+              );
+            an_object["substantive"] =
+              obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+            an_object["attrib"] =
+              obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+            contents_the_objects ~=
+              set_abstract_object.contents_block(
+                an_object["is"],
+                an_object["substantive"],
+                an_object["attrib"],
+                obj_cite_number
+              );
+            object_reset(an_object);
+            processing.remove("verse");
+            ++counter;
+          }
+        }
+      }
+      return 0;
+    }
+    auto group_block(
+      char[] line,
+      ref string[string] an_object,
+      ref int[string] type
+    ) {
+      if (type["curly_group"] == State.on) {
+        if (match(line, rgx.block_curly_group_close)) {
+          debug(group) {                           // group (curly) close
+            tell_l("blue", line);
+          }
+          type["blocks"] = TriState.closing;
+          type["group"] = TriState.closing;
+          type["curly_group"] = TriState.off;
+        } else {
+          debug(group) {                           // group
+            tell_l("blue", line);
+          }
+          an_object["obj"] ~= line ~= "\n";           // build group array (or string)
+        }
+      } else if (type["tic_group"] == TriState.on) {
+        if (match(line, rgx.block_tic_close)) {
+          debug(group) {                           // group (tic) close
+            tell_l("blue", line);
+          }
+          type["blocks"] = TriState.closing;
+          type["group"] = TriState.closing;
+          type["tic_group"] = TriState.off;
+        } else {
+          debug(group) {                           // group
+            tell_l("blue", line);
+          }
+          an_object["obj"] ~= line ~= "\n";           // build group array (or string)
+        }
+      }
+      return 0;
+    }
+    auto block_block(
+      char[] line,
+      ref string[string] an_object,
+      ref int[string] type
+    ) {
+      if (type["curly_block"] == TriState.on) {
+        if (match(line, rgx.block_curly_block_close)) {
+          debug(block) {                           // block (curly) close
+            tell_l("blue", line);
+          }
+          type["blocks"] = TriState.closing;
+          type["block"] = TriState.closing;
+          type["curly_block"] = TriState.off;
+        } else {
+          debug(block) {                           // block
+            tell_l("blue", line);
+          }
+          an_object["obj"] ~= line ~= "\n";           // build block array (or string)
+        }
+      } else if (type["tic_block"] == TriState.on) {
+        if (match(line, rgx.block_tic_close)) {
+          debug(block) {                           // block (tic) close
+            tell_l("blue", line);
+          }
+          type["blocks"] = TriState.closing;
+          type["block"] = TriState.closing;
+          type["tic_block"] = TriState.off;
+        } else {
+          debug(block) {                           // block
+            tell_l("blue", line);
+          }
+          an_object["obj"] ~= line ~= "\n";           // build block array (or string)
+        }
+      }
+      return 0;
+    }
+    auto quote_block(char[] line, ref string[string] an_object, ref int[string] type) {
+      if (type["curly_quote"] == TriState.on) {
+        if (match(line, rgx.block_curly_quote_close)) {
+          debug(quote) {                           // quote (curly) close
+            tell_l("blue", line);
+          }
+          type["blocks"] = TriState.closing;
+          type["quote"] = TriState.closing;
+          type["curly_quote"] = TriState.off;
+        } else {
+          debug(quote) {                           // quote
+            tell_l("blue", line);
+          }
+          an_object["obj"] ~= line ~= "\n";           // build quote array (or string)
+        }
+      } else if (type["tic_quote"] == TriState.on) {
+        if (match(line, rgx.block_tic_close)) {
+          debug(quote) {                           // quote (tic) close
+            tell_l("blue", line);
+          }
+          type["blocks"] = TriState.closing;
+          type["quote"] = TriState.closing;
+          type["tic_quote"] = TriState.off;
+        } else {
+          debug(quote) {                           // quote
+            tell_l("blue", line);
+          }
+          an_object["obj"] ~= line ~= "\n";           // build quote array (or string)
+        }
+      }
+      return 0;
+    }
+    auto table_block(char[] line, ref string[string] an_object, ref int[string] type) {
+      if (type["curly_table"] == TriState.on) {
+        if (match(line, rgx.block_curly_table_close)) {
+          debug(table) {                           // table (curly) close
+            tell_l("blue", line);
+          }
+          type["blocks"] = TriState.closing;
+          type["table"] = TriState.closing;
+          type["curly_table"] = TriState.off;
+        } else {
+          debug(table) {                           // table
+            tell_l("blue", line);
+          }
+          an_object["obj"] ~= line ~= "\n";           // build table array (or string)
+        }
+      } else if (type["tic_table"] == TriState.on) {
+        if (match(line, rgx.block_tic_close)) {
+          debug(table) {                           // table (tic) close
+            tell_l("blue", line);
+          }
+          type["blocks"] = TriState.closing;
+          type["table"] = TriState.closing;
+          type["tic_table"] = TriState.off;
+        } else {
+          debug(table) {                           // table
+            tell_l("blue", line);
+          }
+          an_object["obj"] ~= line ~= "\n";           // build table array (or string)
+        }
+      }
+      return 0;
+    }
+    auto block_flag_line_empty(
+      char[] line,
+      ref string[string] an_object,
+      ref string[string][] contents_the_objects,
+      ref string[][string][string] bookindex_unordered_hashes,
+      ref int obj_cite_number,
+      ref string node,
+      ref long counter,
+      ref int[string] type,
+      string[string] obj_cite_number_poem
+    ) {
+      // line.empty, post contents, empty variables ---------------
+      assert(
+        line.empty,
+        "line should be empty"
+      );
+      assert(
+        (type["blocks"] == TriState.closing),
+        "code block status: closed"
+      );
+      assertions_flag_types_block_status_none_or_closed(type);
+      if (type["code"] == TriState.closing) {
+        obj_cite_number =
+          obj_cite_number_emit(type["obj_cite_number_status"]);
+        an_object["bookindex"] =
+          ("bookindex" in an_object) ? an_object["bookindex"] : "";
+        bookindex_unordered_hashes =
+          bkidx_hash(an_object["bookindex"], obj_cite_number);
+        an_object["is"] = "code";
+        node =
+          node_jstr(
+            content_non_header,
+            obj_cite_number,
+            counter,
+            heading_pointer-1,
+            an_object["is"]
+          );
+        an_object["substantive"] =
+          obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+        an_object["attrib"] =
+          obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+        contents_the_objects ~=
+          set_abstract_object.contents_block(
+            an_object["is"],
+            an_object["substantive"],
+            an_object["attrib"],
+            obj_cite_number
+          );
+        object_reset(an_object);
+        processing.remove("verse");
+        ++counter;
+        type["blocks"] = TriState.off;
+        type["code"] = TriState.off;
+      } else if (type["poem"] == TriState.closing) {
+        an_object["bookindex"] =
+          ("bookindex" in an_object) ? an_object["bookindex"] : "";
+        bookindex_unordered_hashes =
+          bkidx_hash(an_object["bookindex"], obj_cite_number);
+        // obj_cite_number = obj_cite_number_emit(type["obj_cite_number_status"]);
+        an_object["is"] = "verse"; // check also
+        node =
+          node_jstr(
+            content_non_header,
+            obj_cite_number,
+            counter,
+            heading_pointer-1,
+            an_object["is"]
+            // "verse"
+          );
+        contents_the_objects ~=
+          set_abstract_object.contents_block_obj_cite_number_string(
+            "poem",
+            "",
+            (obj_cite_number_poem["start"], obj_cite_number_poem["end"]),
+            node
+          ); // bookindex
+        object_reset(an_object);
+        processing.remove("verse");
+        // ++obj_cite_number;
+        type["blocks"] = TriState.off;
+        type["poem"] = TriState.off;
+      } else if (type["table"] == TriState.closing) {
+        obj_cite_number =
+          obj_cite_number_emit(type["obj_cite_number_status"]);
+        an_object["bookindex"] =
+          ("bookindex" in an_object) ? an_object["bookindex"] : "";
+        bookindex_unordered_hashes =
+          bkidx_hash(an_object["bookindex"], obj_cite_number);
+        an_object["is"] = "table";
+        node =
+          node_jstr(
+            content_non_header,
+            obj_cite_number,
+            counter,
+            heading_pointer-1,
+            an_object["is"]
+          );
+        an_object["substantive"] =
+          obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+        an_object["attrib"] =
+          obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+        contents_the_objects ~=
+          set_abstract_object.contents_block(
+            an_object["is"],
+            an_object["substantive"],
+            an_object["attrib"],
+            obj_cite_number
+          );
+        object_reset(an_object);
+        processing.remove("verse");
+        ++counter;
+        type["blocks"] = TriState.off;
+        type["table"] = TriState.off;
+      } else if (type["group"] == TriState.closing) {
+        obj_cite_number =
+          obj_cite_number_emit(type["obj_cite_number_status"]);
+        an_object["bookindex"] =
+          ("bookindex" in an_object) ? an_object["bookindex"] : "";
+        bookindex_unordered_hashes =
+          bkidx_hash(an_object["bookindex"], obj_cite_number);
+        an_object["is"] = "group";
+        node =
+          node_jstr(
+            content_non_header,
+            obj_cite_number,
+            counter,
+            heading_pointer-1,
+            an_object["is"]
+          );
+        an_object["substantive"] =
+          obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+        an_object["attrib"] =
+          obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+        contents_the_objects ~=
+          set_abstract_object.contents_block(
+            an_object["is"],
+            an_object["substantive"],
+            an_object["attrib"],
+            obj_cite_number
+          );
+        object_reset(an_object);
+        processing.remove("verse");
+        ++counter;
+        type["blocks"] = TriState.off;
+        type["group"] = TriState.off;
+      } else if (type["block"] == TriState.closing) {
+        obj_cite_number = obj_cite_number_emit(type["obj_cite_number_status"]);
+        an_object["bookindex"] =
+          ("bookindex" in an_object) ? an_object["bookindex"] : "";
+        bookindex_unordered_hashes =
+          bkidx_hash(an_object["bookindex"], obj_cite_number);
+        an_object["is"] = "block";
+        node =
+          node_jstr(
+            content_non_header,
+            obj_cite_number,
+            counter,
+            heading_pointer-1,
+            an_object["is"]
+           );
+        an_object["substantive"] =
+          obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+        an_object["attrib"] =
+          obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+        contents_the_objects ~=
+          set_abstract_object.contents_block(
+            an_object["is"],
+            an_object["substantive"],
+            an_object["attrib"],
+            obj_cite_number
+          );
+        object_reset(an_object);
+        processing.remove("verse");
+        ++counter;
+        type["blocks"] = TriState.off;
+        type["block"] = TriState.off;
+      } else if (type["quote"] == TriState.closing) {
+        obj_cite_number =
+          obj_cite_number_emit(type["obj_cite_number_status"]);
+        an_object["bookindex"] =
+          ("bookindex" in an_object) ? an_object["bookindex"] : "";
+        bookindex_unordered_hashes =
+          bkidx_hash(an_object["bookindex"], obj_cite_number);
+        an_object["is"] = "quote";
+        node =
+          node_jstr(
+            content_non_header,
+            obj_cite_number,
+            counter,
+            heading_pointer-1,
+            an_object["is"]
+          );
+        an_object["substantive"] =
+          obj_im.obj_inline_markup(an_object["is"], an_object["obj"]);
+        an_object["attrib"] =
+          obj_att.obj_attributes(an_object["is"], an_object["obj"], node);
+        contents_the_objects ~=
+          set_abstract_object.contents_block(
+            an_object["is"],
+            an_object["substantive"],
+            an_object["attrib"],
+            obj_cite_number
+          );
+        object_reset(an_object);
+        processing.remove("verse");
+        ++counter;
+        type["blocks"] = TriState.off;
+        type["quote"] = TriState.off;
+      }
+      return 0;
+    }
+    auto book_index(
+      char[] line,
+      ref string book_idx_tmp,
+      ref string[string] an_object,
+      ref int[string] type
+    ) {
+      if (auto m = match(line, rgx.book_index)) {
+        /+ match book_index +/
+        debug(bookindexmatch) {                       // book index
+          writefln(
+            "%s* [bookindex] %s%s\n",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            to!string(m.captures[1]),
+          );
+          // writeln(scr_txt_marker["blue"], to!string(m.captures[1]), "\n");
+        }
+        an_object["bookindex"] = to!string(m.captures[1]);
+      } else if (auto m = match(line, rgx.book_index_open))  {
+        /+ match open book_index +/
+        type["book_index"] = State.on;
+        book_idx_tmp = to!string(m.captures[1]);
+        debug(bookindexmatch) {                       // book index
+          writefln(
+            "%s* [bookindex] %s%s\n",
+            scr_txt_color["blue"],
+            scr_txt_color["off"],
+            book_idx_tmp,
+          );
+          // writeln(scr_txt_marker["blue"], book_idx_tmp, "\n");
+        }
+      } else if (type["book_index"] == State.on )  {
+        /+ book_index flag set +/
+        if (auto m = match(line, rgx.book_index_close))  {
+          type["book_index"] = State.off;
+          an_object["bookindex"] = book_idx_tmp ~ to!string(m.captures[1]);
+          debug(bookindexmatch) {                     // book index
+            writefln(
+              "%s* [bookindex] %s%s\n",
+              scr_txt_color["blue"],
+              scr_txt_color["off"],
+              book_idx_tmp,
+            );
+            // writeln(scr_txt_marker["blue"], book_idx_tmp, "\n");
+          }
+          book_idx_tmp = "";
+        } else {
+          book_idx_tmp ~= line;
+        }
+      }
+    }
+    auto header_extract(
+      char[] line,
+      ref int[string] line_occur,
+      ref string[string] an_object,
+      ref int[string] type
+    ) {
+      if (auto m = match(line, rgx.header_make)) {
+        /+ matched header_make +/
+        debug(header1) {                          // header
+          tell_l("yellow", line);
+        }
+        type["header"] = State.on;
+        type["header_make"] = State.on;
+        type["header_metadata"] = State.off;
+        type["heading"] = State.off;
+        type["para"] = State.off;
+        ++line_occur["header_make"];
+        an_object["obj"] ~= line ~= "\n";
+      } else if (auto m = match(line, rgx.header_metadata)) {
+        /+ matched header_metadata +/
+        debug(header1) {                          // header
+          tell_l("yellow", line);
+        }
+        type["header"] = State.on;
+        type["header_make"] = State.off;
+        type["header_metadata"] = State.on;
+        type["heading"] = State.off;
+        type["para"] = State.off;
+        ++line_occur["header_metadata"];
+        an_object["obj"] ~= line ~= "\n";
+      } else if (type["header_make"] == State.on
+      && (line_occur["header_make"] > State.off)) {
+        /+ header_make flag set +/
+        if (auto m = match(line, rgx.header_sub)) {
+          /+ sub-header +/
+          debug(header1) {
+            tell_l("yellow", line);
+          }
+          // type["header"] = State.on;
+          ++line_occur["header_make"];
+          an_object["obj"] ~= line ~= "\n";
+        }
+      } else if (type["header_metadata"] == State.on
+      && (line_occur["header_metadata"] > State.off)) {
+        /+ header_metadata flag set +/
+        if (auto m = match(line, rgx.header_sub)) {
+          /+ sub-header +/
+          debug(header1) {
+            tell_l("yellow", line);
+          }
+          ++line_occur["header_metadata"];
+          an_object["obj"] ~= line ~= "\n";
+        }
+      }
+      return 0;
+    }
+    auto heading_found(
+      char[] line,
+      string dochead_make_headings,
+      ref string[string] heading_match_str,
+      ref Regex!(char)[string] heading_match_rgx,
+      ref int[string] type
+    ) {
+      if ((to!string(dochead_make_headings).length > 2)
+      && (type["make_headings"] == State.off)) {
+        /+ headings found +/
+        debug(headingsfound) {
+          writeln(dochead_make_headings);
+        }
+        auto make_headings_txt =
+          match(
+            to!string(dochead_make_headings),
+            rgx.within_quotes);
+        char[][] make_headings_spl =
+          split(
+            cast(char[]) make_headings_txt.captures[1],
+            rgx.make_heading_delimiter);
+        debug(headingsfound) {
+          writeln(make_headings_spl.length);
+          writeln(make_headings_spl);
+        }
+        switch (make_headings_spl.length) {
+        case 7 :
+          if (!empty(make_headings_spl[6])) {
+            heading_match_str["h_4"] =
+              "^(" ~ to!string(make_headings_spl[6]) ~ ")";
+            heading_match_rgx["h_4"] =
+              regex(heading_match_str["h_4"]);
+          }
+          goto case;
+        case 6 :
+          if (!empty(make_headings_spl[5])) {
+            heading_match_str["h_3"] =
+              "^(" ~ to!string(make_headings_spl[5]) ~ ")";
+            heading_match_rgx["h_3"] =
+              regex(heading_match_str["h_3"]);
+          }
+          goto case;
+        case 5 :
+          if (!empty(make_headings_spl[4])) {
+            heading_match_str["h_2"] =
+              "^(" ~ to!string(make_headings_spl[4]) ~ ")";
+            heading_match_rgx["h_2"] =
+              regex(heading_match_str["h_2"]);
+          }
+          goto case;
+        case 4 :
+          if (!empty(make_headings_spl[3])) {
+            heading_match_str["h_1"] =
+              "^(" ~ to!string(make_headings_spl[3]) ~ ")";
+            heading_match_rgx["h_1"] =
+              regex(heading_match_str["h_1"]);
+          }
+          goto case;
+        case 3 :
+          if (!empty(make_headings_spl[2])) {
+            heading_match_str["h_D"] =
+              "^(" ~ to!string(make_headings_spl[2]) ~ ")";
+            heading_match_rgx["h_D"] =
+              regex(heading_match_str["h_D"]);
+          }
+          goto case;
+        case 2 :
+          if (!empty(make_headings_spl[1])) {
+            heading_match_str["h_C"] =
+              "^(" ~ to!string(make_headings_spl[1]) ~ ")";
+            heading_match_rgx["h_C"] =
+              regex(heading_match_str["h_C"]);
+          }
+          goto case;
+        case 1 :
+          if (!empty(make_headings_spl[0])) {
+            heading_match_str["h_B"] =
+              "^(" ~ to!string(make_headings_spl[0]) ~ ")";
+            heading_match_rgx["h_B"] =
+              regex(heading_match_str["h_B"]);
+          }
+          break;
+        default:
+          break;
+        }
+        type["make_headings"] = State.on;
+      }
+    }
+    auto heading_make_set(
+      ref char[] line,
+      ref int[string] line_occur,
+      ref Regex!(char)[string] heading_match_rgx,
+      ref int[string] type
+    ) {
+      if ((type["make_headings"] == State.on)
+      && ((line_occur["para"] == State.off)
+      && (line_occur["heading"] == State.off))
+      && ((type["para"] == State.off)
+      && (type["heading"] == State.off))) {
+        /+ heading make set +/
+        if (match(line, heading_match_rgx["h_B"])) {
+          line = "B~ " ~ line;
+          debug(headingsfound) {
+            writeln(line);
+          }
+        }
+        if (match(line, heading_match_rgx["h_C"])) {
+          line = "C~ " ~ line;
+          debug(headingsfound) {
+            writeln(line);
+          }
+        }
+        if (match(line, heading_match_rgx["h_D"])) {
+          line = "D~ " ~ line;
+          debug(headingsfound) {
+            writeln(line);
+          }
+        }
+        if (match(line, heading_match_rgx["h_1"])) {
+          line = "1~ " ~ line;
+          debug(headingsfound) {
+            writeln(line);
+          }
+        }
+        if (match(line, heading_match_rgx["h_2"])) {
+          line = "2~ " ~ line;
+          debug(headingsfound) {
+            writeln(line);
+          }
+        }
+        if (match(line, heading_match_rgx["h_3"])) {
+          line = "3~ " ~ line;
+          debug(headingsfound) {
+            writeln(line);
+          }
+        }
+        if (match(line, heading_match_rgx["h_4"])) {
+          line = "4~ " ~ line;
+          debug(headingsfound) {
+            writeln(line);
+          }
+        }
+      }
+    }
+    auto heading_match(
+      char[] line,
+      ref int[string] line_occur,
+      ref string[string] an_object,
+      ref int[string] lv,
+      ref int[string] collapsed_lev,
+      ref int[string] type
+    ) {
+      if (auto m = match(line, rgx.heading)) {
+        /+ heading match +/
+        type["heading"] = State.on;
+        type["header"] = State.off;
+        type["header_make"] = State.off;
+        type["header_metadata"] = State.off;
+        type["heading_biblio"] = State.off;
+        type["para"] = State.off;
+        ++line_occur["heading"];
+        an_object["obj"] ~= line ~= "\n";
+        an_object["lev"] ~= m.captures[1];
+        assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels
+        switch (an_object["lev"]) {
+        case "A":
+          collapsed_lev["h0"] = 1;
+          an_object["lev_collapsed_number"] =
+            to!string(collapsed_lev["h0"]);
+          lv["lv"] = DocStructMarkupHeading.h_sect_A;
+          ++lv["h0"];
+          lv["h1"] = State.off;
+          lv["h2"] = State.off;
+          lv["h3"] = State.off;
+          lv["h4"] = State.off;
+          lv["h5"] = State.off;
+          lv["h6"] = State.off;
+          lv["h7"] = State.off;
+          goto default;
+        case "B":
+          collapsed_lev["h1"] = collapsed_lev["h0"] + 1;
+          an_object["lev_collapsed_number"] =
+            to!string(collapsed_lev["h1"]);
+          lv["lv"] = DocStructMarkupHeading.h_sect_B;
+          ++lv["h1"];
+          lv["h2"] = State.off;
+          lv["h3"] = State.off;
+          lv["h4"] = State.off;
+          lv["h5"] = State.off;
+          lv["h6"] = State.off;
+          lv["h7"] = State.off;
+          goto default;
+        case "C":
+          collapsed_lev["h2"] = collapsed_lev["h1"] + 1;
+          an_object["lev_collapsed_number"] =
+            to!string(collapsed_lev["h2"]);
+          lv["lv"] = DocStructMarkupHeading.h_sect_C;
+          ++lv["h2"];
+          lv["h3"] = State.off;
+          lv["h4"] = State.off;
+          lv["h5"] = State.off;
+          lv["h6"] = State.off;
+          lv["h7"] = State.off;
+          goto default;
+        case "D":
+          collapsed_lev["h3"] = collapsed_lev["h2"] + 1;
+          an_object["lev_collapsed_number"] =
+            to!string(collapsed_lev["h3"]);
+          lv["lv"] = DocStructMarkupHeading.h_sect_D;
+          ++lv["h3"];
+          lv["h4"] = State.off;
+          lv["h5"] = State.off;
+          lv["h6"] = State.off;
+          lv["h7"] = State.off;
+          goto default;
+        case "1":
+          if (lv["h3"] > State.off) {
+            collapsed_lev["h4"] = collapsed_lev["h3"] + 1;
+          } else if (lv["h2"] > State.off) {
+            collapsed_lev["h4"] = collapsed_lev["h2"] + 1;
+          } else if (lv["h1"] > State.off) {
+            collapsed_lev["h4"] = collapsed_lev["h1"] + 1;
+          } else if (lv["h0"] > State.off) {
+            collapsed_lev["h4"] = collapsed_lev["h0"] + 1;
+          }
+          an_object["lev_collapsed_number"] =
+            to!string(collapsed_lev["h4"]);
+          lv["lv"] = DocStructMarkupHeading.h_text_1;
+          ++lv["h4"];
+          lv["h5"] = State.off;
+          lv["h6"] = State.off;
+          lv["h7"] = State.off;
+          goto default;
+        case "2":
+          if (lv["h5"] > State.off) {
+            an_object["lev_collapsed_number"] =
+              to!string(collapsed_lev["h5"]);
+          } else if (lv["h4"] > State.off) {
+            collapsed_lev["h5"] = collapsed_lev["h4"] + 1;
+            an_object["lev_collapsed_number"] =
+              to!string(collapsed_lev["h5"]);
+          }
+          lv["lv"] = DocStructMarkupHeading.h_text_2;
+          ++lv["h5"];
+          lv["h6"] = State.off;
+          lv["h7"] = State.off;
+          goto default;
+        case "3":
+          if (lv["h6"] > State.off) {
+            an_object["lev_collapsed_number"] =
+              to!string(collapsed_lev["h6"]);
+          } else if (lv["h5"] > State.off) {
+            collapsed_lev["h6"] = collapsed_lev["h5"] + 1;
+            an_object["lev_collapsed_number"] =
+              to!string(collapsed_lev["h6"]);
+          }
+          lv["lv"] = DocStructMarkupHeading.h_text_3;
+          ++lv["h6"];
+          lv["h7"] = State.off;
+          goto default;
+        case "4":
+          if (lv["h7"] > State.off) {
+            an_object["lev_collapsed_number"] =
+              to!string(collapsed_lev["h7"]);
+          } else if (lv["h6"] > State.off) {
+            collapsed_lev["h7"] = collapsed_lev["h6"] + 1;
+            an_object["lev_collapsed_number"] =
+              to!string(collapsed_lev["h7"]);
+          }
+          lv["lv"] = DocStructMarkupHeading.h_text_4;
+          ++lv["h7"];
+          goto default;
+        default:
+          an_object["lev_markup_number"] = to!string(lv["lv"]);
+        }
+        debug(heading) {                         // heading
+          // writeln(m.captures[1], " ", m.captures[2], "\n");      // figure inclusion of post capture text
+          // writeln(m.hit, "\n");
+          tell_l("yellow", strip(line));
+        }
+      }
+    }
+    auto para_match(
+      char[] line,
+      ref string[string] an_object,
+      ref string[string] indent,
+      ref bool bullet,
+      ref int[string] type
+    ) {
+      if (line_occur["para"] == State.off) {
+        /+ para matches +/
+          // paragraphs
+          // (fl  ag_type["heading"] = true) &&
+        if (auto m = match(line, rgx.para_indent)) {
+          debug(paraindent) {                    // para indent
+            tell_l("blue", line);
+          }
+          type["para"] = State.on;
+          an_object["obj"] ~= line ~= "\n";
+          indent["first"] = to!string(m.captures[1]);
+          indent["second"] = "0";
+          bullet = false;
+        } else if (auto m = match(line, rgx.para_bullet)) {
+          debug(parabullet) {                    // para bullet
+            tell_l("blue", line);
+          }
+          type["para"] = State.on;
+          an_object["obj"] ~= line;
+          indent["first"] = "0";
+          indent["second"] = "0";
+          bullet = true;
+        } else if (auto m = match(line, rgx.para_indent_hang)) {
+          debug(paraindenthang) {                // para indent hang
+            tell_l("blue", line);
+          }
+          type["para"] = State.on;
+          an_object["obj"] ~= line;
+          indent["first"] = to!string(m.captures[1]);
+          indent["second"] = to!string(m.captures[2]);
+          bullet = false;
+        } else if (auto m = match(line, rgx.para_bullet_indent)) {
+          debug(parabulletindent) {              // para bullet indent
+            tell_l("blue", line);
+          }
+          type["para"] = State.on;
+          an_object["obj"] ~= line;
+          indent["first"] = to!string(m.captures[1]);
+          indent["second"] = "0";
+          bullet = true;
+        } else {
+          // !line.empty
+          type["para"] = State.on;
+          an_object["obj"] ~= line;
+          indent["first"] = "0";
+          indent["second"] = "0";
+          bullet = false;
+        }
+        ++line_occur["para"];
+      }
+    }
+    /+ abstraction functions ↑ +/
+
+    /+ ↓ abstraction function emitters +/
+    struct OCNemitter {
+    // class OCNemitter : AssertOCN {
+      int obj_cite_number, obj_cite_number_;
+      int obj_cite_number_emitter(int obj_cite_number_status_flag)
+      in { assert(obj_cite_number_status_flag <= 2); }
+      body {
+        if (obj_cite_number_status_flag == 0) {
+          obj_cite_number=++obj_cite_number_;
+        } else {
+          obj_cite_number=0;
+        }
+        assert(obj_cite_number >= 0);
+        return obj_cite_number;
+      }
+      invariant() {
+      }
+    }
+    struct ObjAttributes {
+    // class ObjAttributes : AssertObjAttributes {
+      string[string] obj_txt;
+      string para_and_blocks(string obj_txt_in)
+      in { }
+      body {
+        auto rgx = Rgx();
+        obj_txt["munge"]=obj_txt_in;
+        if (match(obj_txt_in, rgx.para_bullet)) {
+          obj_txt["attrib"] =" \"bullet\": \"true\","
+          ~ " \"indent_first\": 0,"
+          ~ " \"indent_rest\": 0,";
+        } else if (auto m = match(obj_txt_in, rgx.para_bullet_indent)) {
+          obj_txt["attrib"] =" \"bullet\": \"true\","
+          ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ ","
+          ~ " \"indent_rest\": " ~ to!string(m.captures[1]) ~ ",";
+        } else if (auto m = match(obj_txt_in, rgx.para_indent_hang)) {
+          obj_txt["attrib"] =" \"bullet\": \"false\","
+          ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ ","
+          ~ " \"indent_rest\": " ~  to!string(m.captures[2]) ~ ",";
+        } else if (auto m = match(obj_txt_in, rgx.para_indent)) {
+          obj_txt["attrib"] =" \"bullet\": \"false\","
+          ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ ","
+          ~ " \"indent_rest\": " ~ to!string(m.captures[1]) ~ ",";
+        } else {
+          obj_txt["attrib"] =" \"bullet\": \"false\","
+          ~ " \"indent_first\": 0,"
+          ~ " \"indent_rest\": 0,";
+        }
+        return obj_txt["attrib"];
+      }
+      string para(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"content\","
+        ~ " \"of\": \"para\","
+        ~ " \"is\": \"para\"";
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+      string heading(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"content\","
+        ~ " \"of\": \"para\","
+        ~ " \"is\": \"heading\"";
+        // obj_txt["struct"]=;
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+      string header_make(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"head\","
+        ~ " \"of\": \"header\","
+        ~ " \"is\": \"header_make\"";
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+      string header_metadata(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"head\","
+        ~ " \"of\": \"header\","
+        ~ " \"is\": \"header_metadata\"";
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+      string code(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"content\","
+        ~ " \"of\": \"block\","
+        ~ " \"is\": \"code\"";
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+      string group(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"content\","
+        ~ " \"of\": \"block\","
+        ~ " \"is\": \"group\"";
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+      string block(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"content\","
+        ~ " \"of\": \"block\","
+        ~ " \"is\": \"block\"";
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+      string verse(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"content\","
+        ~ " \"of\": \"block\","
+        ~ " \"is\": \"verse\"";
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+      string quote(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"content\","
+        ~ " \"of\": \"block\","
+        ~ " \"is\": \"quote\"";
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+      string table(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"content\","
+        ~ " \"of\": \"block\","
+        ~ " \"is\": \"table\"";
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+      string comment(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["attrib"] = " \"use\": \"comment\","
+        ~ " \"of\": \"comment\","
+        ~ " \"is\": \"comment\"";
+        return obj_txt["attrib"];
+      }
+      invariant() {
+      }
+    }
+    struct ObjInlineMarkupMunge {
+    // struct ObjInlineMarkupMunge : AssertObjInlineMarkup {
+      string[string] obj_txt;
+      int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus;
+      string obj_txt_out, tail, note;
+      private auto initialize_note_numbers() {
+        n_foot = 0;
+        n_foot_reg = 0;
+        n_foot_sp_asterisk = 0;
+        n_foot_sp_plus = 0;
+      }
+      private auto object_notes_(string obj_txt_in)
+      in { }
+      body {
+        auto rgx = Rgx();
+        auto mkup = InlineMarkup();
+        obj_txt_out = "";
+        tail = "";
+        obj_txt_in = replaceAll(
+          obj_txt_in,
+          rgx.inline_notes_curly_sp_asterisk,
+          (mkup.en_a_o ~ "*" ~ " $1" ~ mkup.en_a_c)
+        );
+        obj_txt_in =
+          replaceAll(
+            obj_txt_in,
+            rgx.inline_notes_curly_sp_plus,
+            (mkup.en_a_o ~ "+" ~ " $1" ~ mkup.en_a_c)
+          );
+        obj_txt_in =
+          replaceAll(
+            obj_txt_in,
+            rgx.inline_notes_curly,
+            (mkup.en_a_o ~ " $1" ~ mkup.en_a_c)
+          );
+        if (match(obj_txt_in, rgx.inline_notes_al_gen)) {
+          foreach(m; matchAll(obj_txt_in, rgx.inline_text_and_note_al)) {
+            if (match(obj_txt_in, rgx.inline_al_delimiter_open_asterisk)) {
+              ++n_foot_sp_asterisk;
+              n_foot=n_foot_sp_asterisk;
+            } else if (match(obj_txt_in, rgx.inline_al_delimiter_open_plus)) {
+              ++n_foot_sp_plus;
+              n_foot=n_foot_sp_plus;
+            } else {
+              ++n_foot_reg;
+              n_foot=n_foot_reg;
+            }
+            obj_txt_out ~= replaceFirst(
+              m.hit,
+              rgx.inline_al_delimiter_open_regular,
+              (mkup.en_a_o ~ to!string(n_foot))
+            );
+            tail = m.post;
+            // if (!empty(m.post)) {
+            //   tail = m.post;
+            // } else {
+            //   tail = "";
+            // }
+          }
+        } else {
+          obj_txt_out = obj_txt_in;
+        }
+        debug(footnotes) {
+          writeln(obj_txt_out, tail);
+        }
+        obj_txt_out = obj_txt_out ~ tail;
+        debug(footnotesdone) {
+          foreach(m; matchAll(obj_txt_out,
+          (mkup.en_a_o ~ `\s*(.+?)` ~ mkup.en_a_c))) {
+            writeln(m.captures[1]);
+            writeln(m.hit);
+          }
+        }
+        return obj_txt_out;
+      }
+      string para(string obj_txt_in)
+      in { }
+      body {
+        auto rgx = Rgx();
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.para_attribs, "");
+        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.obj_cite_number_off_all, "");
+        obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+        debug(munge) {
+          writeln(__LINE__);
+          writeln(obj_txt_in);
+          writeln(__LINE__);
+          writeln(to!string(obj_txt["munge"]));
+        }
+        return obj_txt["munge"];
+      }
+      string heading(string obj_txt_in)
+      in { }
+      body {
+        auto rgx = Rgx();
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.heading, "");
+        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.obj_cite_number_off_all, "");
+        obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+        debug(munge) {
+          writeln(__LINE__);
+          writeln(obj_txt_in);
+          writeln(__LINE__);
+          writeln(to!string(obj_txt["munge"]));
+        }
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+      string header_make(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+      string header_metadata(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+      string code(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+      string group(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+      string block(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+      string verse(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+      string quote(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+      string table(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+      string comment(string obj_txt_in)
+      in { }
+      body {
+        obj_txt["munge"]=obj_txt_in;
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+    }
+    struct ObjInlineMarkup {
+    // struct ObjInlineMarkup : AssertObjInlineMarkup {
+      auto munge = ObjInlineMarkupMunge();
+      string[string] obj_txt;
+      string obj_inline_markup(string obj_is_, string obj_raw)
+      in { }
+      body {
+        obj_txt["munge"]=obj_raw.dup;
+        obj_txt["munge"]=(match(obj_is_, ctRegex!(`verse|code`)))
+          ? obj_txt["munge"]
+          : strip(obj_txt["munge"]);
+        switch (obj_is_) {
+        case "header_make":
+          obj_txt["munge"]=munge.header_make(obj_txt["munge"]);
+          break;
+        case "header_metadata":
+          obj_txt["munge"]=munge.header_metadata(obj_txt["munge"]);
+          break;
+        case "heading":
+          obj_txt["munge"]=munge.heading(obj_txt["munge"]);
+          break;
+        case "para":
+          obj_txt["munge"]=munge.para(obj_txt["munge"]);
+          break;
+        case "code":
+          obj_txt["munge"]=munge.code(obj_txt["munge"]);
+          break;
+        case "group":
+          obj_txt["munge"]=munge.group(obj_txt["munge"]);
+          break;
+        case "block":
+          obj_txt["munge"]=munge.block(obj_txt["munge"]);
+          break;
+        case "verse":
+          obj_txt["munge"]=munge.verse(obj_txt["munge"]);
+          break;
+        case "quote":
+          obj_txt["munge"]=munge.quote(obj_txt["munge"]);
+          break;
+        case "table":
+          obj_txt["munge"]=munge.table(obj_txt["munge"]);
+          break;
+        case "comment":
+          obj_txt["munge"]=munge.comment(obj_txt["munge"]);
+          break;
+        case "doc_end_reset":
+          munge.initialize_note_numbers();
+          break;
+        default:
+          break;
+        }
+        return obj_txt["munge"];
+      }
+      invariant() {
+      }
+    }
+    struct ObjAttrib {
+    // struct ObjAttrib : AssertObjAttrib {
+    // auto sink = appender!(char[])();
+      auto attrib = ObjAttributes();
+      string[string] obj_attrib;
+      string obj_attributes(string obj_is_, string obj_raw, string node)
+      in { }
+      body {
+        // string s = "{ \"language\": \"D\", \"rating\": 3.14, \"code\": \"42\" }";
+        scope(exit) {
+          // destroy(obj_is_);
+          destroy(obj_raw);
+          destroy(node);
+        }
+        JSONValue node_j = parseJSON(node);
+        obj_attrib.remove("json");
+        obj_attrib["json"] ="{";
+        switch (obj_is_) {
+        case "header_make":
+          obj_attrib["json"] ~= attrib.header_make(obj_raw);
+          break;
+        case "header_metadata":
+          obj_attrib["json"] ~= attrib.header_metadata(obj_raw);
+          break;
+        case "heading":
+          obj_attrib["json"] ~= attrib.heading(obj_raw); //
+          break;
+        case "para":
+          obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw)
+          ~ attrib.para(obj_raw);
+          break;
+        case "code":
+          obj_attrib["json"] ~= attrib.code(obj_raw);
+          break;
+        case "group":
+          obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw)
+          ~ attrib.group(obj_raw);
+          break;
+        case "block":
+          obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw)
+          ~ attrib.block(obj_raw);
+          break;
+        case "verse":
+          obj_attrib["json"] ~= attrib.verse(obj_raw);
+          break;
+        case "quote":
+          obj_attrib["json"] ~= attrib.quote(obj_raw);
+          break;
+        case "table":
+          obj_attrib["json"] ~= attrib.table(obj_raw);
+          break;
+        case "comment":
+          obj_attrib["json"] ~= attrib.comment(obj_raw);
+          break;
+        default:
+          obj_attrib["json"] ~= attrib.para(obj_raw);
+          break;
+        }
+        obj_attrib["json"] ~=" }";
+        JSONValue oa_j = parseJSON(obj_attrib["json"]);
+        assert(
+          (oa_j.type == JSON_TYPE.OBJECT) &&
+          (node_j.type == JSON_TYPE.OBJECT)
+        );
+        if (obj_is_ == "heading") {
+          oa_j.object["obj_cite_number"] = node_j["obj_cite_number"];
+          oa_j.object["lev_markup_number"] = node_j["lev_markup_number"];
+          oa_j.object["lev_collapsed_number"] = node_j["lev_collapsed_number"];
+          oa_j.object["heading_pointer"] =
+            node_j["heading_pointer"]; // check
+          oa_j.object["doc_object_pointer"] =
+            node_j["doc_object_pointer"]; // check
+        }
+        oa_j.object["parent_obj_cite_number"] = node_j["parent_obj_cite_number"];
+        oa_j.object["parent_lev_markup_number"] = node_j["parent_lev_markup_number"];
+        obj_attrib["json"] = oa_j.toString();
+        debug(structattrib) {
+          if (oa_j["is"].str() == "heading") {
+            // writeln(__LINE__);
+            writeln(obj_attrib["json"]);
+            // writeln(node);
+            writeln(
+              "is: ", oa_j["is"].str(),
+              "; obj_cite_number: ", oa_j["obj_cite_number"].integer()
+            );
+          }
+        }
+        // obj_attrib["json"]="{}";
+        return obj_attrib["json"];
+      }
+      invariant() {
+      }
+    }
+    struct HeaderDocMetadataMakeJson {
+    // class HeaderMetadataMakeHash : AssertHeaderMetadataMakeJson {
+      auto rgx = Rgx();
+      string hm, hs;
+      auto header_metadata_and_make_jsonstr(
+        string header,
+        JSONValue[string] dochead_metadata,
+        JSONValue[string] dochead_make
+      )
+      in { }
+      body {
+        scope(exit) {
+          destroy(header);
+          destroy(dochead_metadata);
+          destroy(dochead_make);
+        }
+        if (auto t = match(header, rgx.head_main)) {
+          char[][] obj_spl = split(
+            cast(char[]) header,
+            rgx.line_delimiter_ws_strip
+          );
+          auto hm = to!string(t.captures[1]);
+          if (match(hm, rgx.main_headers)) {
+            foreach (line; obj_spl) {
+              if (auto m = match(line, rgx.head_main)) {
+                if (!empty(m.captures[2])) {
+                  if (hm == "creator") {
+                    dochead_metadata[hm]["author"].str =
+                      to!string(m.captures[2]);
+                  } else if (hm == "title") {
+                    dochead_metadata[hm]["main"].str =
+                      to!string(m.captures[2]);
+                  } else if (hm == "publisher") {
+                    dochead_metadata[hm]["name"].str =
+                      to!string(m.captures[2]);
+                  }
+                }
+              } else if (auto s = match(line, rgx.head_sub)) {
+                if (!empty(s.captures[2])) {
+                  auto hs = to!string(s.captures[1]);
+                  if ((hm == "make" )
+                  && (dochead_make[hm].type() == JSON_TYPE.OBJECT)) {
+                    switch (hm) {
+                    case "make":
+                      if (match(hs, rgx.subhead_make)) {
+                        if (dochead_make[hm][hs].type() == JSON_TYPE.STRING) {
+                          dochead_make[hm][hs].str = to!string(s.captures[2]);
+                        }
+                      } else {
+                        writeln("not a valid header type:", hm, ":", hs);
+                        destroy(hm);
+                        destroy(hs);
+                      }
+                      break;
+                    default:
+                      break;
+                    }
+                  } else if (dochead_metadata[hm].type() == JSON_TYPE.OBJECT) {
+                    switch (hm) {
+                    case "creator":
+                      if (match(hs, rgx.subhead_creator)) {
+                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+                          dochead_metadata[hm][hs].str =
+                            to!string(s.captures[2]);
+                        }
+                      } else {
+                        writeln("not a valid header type:", hm, ":", hs);
+                        destroy(hm);
+                        destroy(hs);
+                      }
+                      break;
+                    case "title":
+                      if (match(hs, rgx.subhead_title)) {
+                        if ((hs == "subtitle")
+                        && (dochead_metadata[hm]["sub"].type() == JSON_TYPE.STRING)) {
+                          dochead_metadata[hm]["sub"].str =
+                            to!string(s.captures[2]);
+                        } else if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+                          dochead_metadata[hm][hs].str =
+                            to!string(s.captures[2]);
+                        }
+                      } else {
+                        writeln("not a valid header type:", hm, ":", hs);
+                        destroy(hm);
+                        destroy(hs);
+                      }
+                      break;
+                    case "rights":
+                      if (match(hs, rgx.subhead_rights)) {
+                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+                          dochead_metadata[hm][hs].str =
+                            to!string(s.captures[2]);
+                        }
+                      } else {
+                        writeln("not a valid header type:", hm, ":", hs);
+                        destroy(hm);
+                        destroy(hs);
+                      }
+                      break;
+                    case "date":
+                      if (match(hs, rgx.subhead_date)) {
+                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+                          dochead_metadata[hm][hs].str =
+                            to!string(s.captures[2]);
+                        }
+                      } else {
+                        writeln("not a valid header type:", hm, ":", hs);
+                        destroy(hm);
+                        destroy(hs);
+                      }
+                      break;
+                    case "original":
+                      if (match(hs, rgx.subhead_original)) {
+                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+                          dochead_metadata[hm][hs].str =
+                            to!string(s.captures[2]);
+                        }
+                      } else {
+                        writeln("not a valid header type:", hm, ":", hs);
+                        destroy(hm);
+                        destroy(hs);
+                      }
+                      break;
+                    case "classify":
+                      if (match(hs, rgx.subhead_classify)) {
+                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+                          dochead_metadata[hm][hs].str =
+                            to!string(s.captures[2]);
+                        }
+                      } else {
+                        writeln("not a valid header type:", hm, ":", hs);
+                        destroy(hm);
+                        destroy(hs);
+                      }
+                      break;
+                    case "identifier":
+                      if (match(hs, rgx.subhead_identifier)) {
+                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+                          dochead_metadata[hm][hs].str =
+                            to!string(s.captures[2]);
+                        }
+                      } else {
+                        writeln("not a valid header type:", hm, ":", hs);
+                        destroy(hm);
+                        destroy(hs);
+                      }
+                      break;
+                    case "notes":
+                      if (match(hs, rgx.subhead_notes)) {
+                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+                          dochead_metadata[hm][hs].str =
+                            to!string(s.captures[2]);
+                        }
+                      } else {
+                        writeln("not a valid header type:", hm, ":", hs);
+                        destroy(hm);
+                        destroy(hs);
+                      }
+                      break;
+                    case "publisher":
+                      if (match(hs, rgx.subhead_publisher)) {
+                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+                          dochead_metadata[hm][hs].str =
+                            to!string(s.captures[2]);
+                        }
+                      } else {
+                        writeln("not a valid header type:", hm, ":", hs);
+                        destroy(hm);
+                        destroy(hs);
+                      }
+                      break;
+                    case "links":
+                      destroy(hm);
+                      destroy(hs);
+                      // if (match(hs, rgx.subhead_links)) {
+                      //   if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) {
+                      //     dochead_metadata[hm][hs].str = to!string(s.captures[2]);
+                      //   }
+                      // } else {
+                      //   writeln("not a valid header type:", hm, ":", hs);
+                      //   destroy(hm);
+                      //   destroy(hs);
+                      // }
+                      break;
+                    default:
+                      break;
+                    }
+                  }
+                }
+              }
+            }
+          } else {
+            writeln("not a valid header type:", hm);
+          }
+        }
+        auto t = tuple(dochead_metadata, dochead_make);
+        static assert(!isTypeTuple!(t));
+        return t;
+      }
+      // invariant() {
+      // }
+    }
+    class HeaderMetadataMakeHash {
+    // class HeaderMetadataMakeHash : AssertHeaderMetadataMakeHash {
+      auto rgx = Rgx();
+      string header_main;
+      string[string] head;
+      string[string] header_topic_hash(string header)
+      in { }
+      body {
+        if (auto t = match(header, rgx.head_main)) {
+          char[][] obj_spl = split(
+            cast(char[]) header,
+            rgx.line_delimiter_ws_strip
+          );
+          auto header_main = to!string(t.captures[1]);
+          head[header_main] = "{";
+          foreach (line; obj_spl) {
+            if (auto m = match(line, rgx.head_main)) {
+              if (!empty(m.captures[2])) {
+                head[header_main] ~=
+                  "\"" ~ header_main ~
+                  "\": \"" ~
+                  to!string(m.captures[2]) ~
+                  "\",";
+              }
+            } else if (auto s = match(line, rgx.head_sub)) {
+              head[header_main] ~= "\"" ~ s.captures[1] ~ "\":";
+              if (!empty(s.captures[2])) {
+                head[header_main] ~= "\"" ~ s.captures[2] ~ "\",";
+              }
+            }
+          }
+          head[header_main] = replaceFirst(
+            head[header_main],
+            rgx.tailing_comma,
+            ""
+          );
+          head[header_main] ~= "}";
+          debug(headerjson) {
+            JSONValue j = parseJSON(head[header_main]);
+            assert(
+              (j.type == JSON_TYPE.OBJECT)
+            );
+          }
+        }
+        return head;
+      }
+      invariant() {
+      }
+    }
+    struct BookIndexNuggetHash {
+    // class BookIndexNuggetHash : AssertBookIndexNuggetHash {
+      string main_term, sub_term, sub_term_bits;
+      int obj_cite_number_offset, obj_cite_number_endpoint;
+      string[] obj_cite_numbers;
+      string[][string][string] bi;
+      string[][string][string] hash_nugget;
+      string[] bi_main_terms_split_arr;
+      string[][string][string] bookindex_nugget_hash(string bookindex_section, int obj_cite_number)
+      in {
+        debug(bookindexraw) {
+          mixin ScreenTxtColors;
+          if (!bookindex_section.empty) {
+            writeln(
+              scr_txt_color["blue"], "* [bookindex] ", scr_txt_color["off"],
+              "[", to!string(obj_cite_number), "] ", bookindex_section
+            );
+          }
+        }
+      }
+      body {
+        auto rgx = Rgx();
+        if (!bookindex_section.empty) {
+          auto bi_main_terms_split_arr =
+            split(bookindex_section, rgx.bi_main_terms_split);
+          foreach (bi_main_terms_content; bi_main_terms_split_arr) {
+            auto bi_main_term_and_rest =
+              split(bi_main_terms_content, rgx.bi_main_term_plus_rest_split);
+            if (auto m = match(
+              bi_main_term_and_rest[0],
+              rgx.bi_term_and_obj_cite_numbers_match)
+            ) {
+              main_term = strip(m.captures[1]);
+              obj_cite_number_offset = to!int(m.captures[2]);
+              obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset);
+              obj_cite_numbers ~= (to!string(obj_cite_number) ~ "-" ~ to!string(obj_cite_number_endpoint));
+            } else {
+              main_term = strip(bi_main_term_and_rest[0]);
+              obj_cite_numbers ~= to!string(obj_cite_number);
+            }
+            bi[main_term]["_a"] ~= obj_cite_numbers;
+            obj_cite_numbers=null;
+            if (bi_main_term_and_rest.length > 1) {
+              auto bi_sub_terms_split_arr =
+                split(
+                  bi_main_term_and_rest[1],
+                  rgx.bi_sub_terms_plus_obj_cite_number_offset_split
+                );
+              foreach (sub_terms_bits; bi_sub_terms_split_arr) {
+                if (auto m = match(sub_terms_bits, rgx.bi_term_and_obj_cite_numbers_match)) {
+                  sub_term = strip(m.captures[1]);
+                  obj_cite_number_offset = to!int(m.captures[2]);
+                  obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset);
+                  obj_cite_numbers ~= (to!string(obj_cite_number) ~ " - " ~ to!string(obj_cite_number_endpoint));
+                } else {
+                  sub_term = strip(sub_terms_bits);
+                  obj_cite_numbers ~= to!string(obj_cite_number);
+                }
+                if (!empty(sub_term)) {
+                  bi[main_term][sub_term] ~= obj_cite_numbers;
+                }
+                obj_cite_numbers=null;
+              }
+            }
+          }
+        }
+        hash_nugget = bi;
+        return hash_nugget;
+      }
+      invariant() {
+      }
+    }
+    struct BookIndexReport {
+    // class BookIndexReport : AssertBookIndexReport {
+      int mkn, skn;
+      auto bookindex_report_sorted(
+        string[][string][string] bookindex_unordered_hashes
+      ) {
+        auto mainkeys=bookindex_unordered_hashes.byKey.array.
+          sort!("toLower(a) < toLower(b)", SwapStrategy.stable).release;
+        foreach (mainkey; mainkeys) {
+          auto subkeys=bookindex_unordered_hashes[mainkey].byKey.array.
+            sort!("toLower(a) < toLower(b)", SwapStrategy.stable).release;
+          foreach (subkey; subkeys) {
+            debug(bookindex) {
+              writeln(
+                mainkey, ": ",
+                subkey, ": ",
+                to!string(bookindex_unordered_hashes[mainkey][subkey])
+              );
+            }
+            ++skn;
+          }
+          ++mkn;
+        }
+        // return bookindex_the;
+      }
+    }
+    struct BookIndexReportIndent {
+      int mkn, skn;
+      auto bookindex_report_indented(
+        string[][string][string] bookindex_unordered_hashes
+      ) {
+        auto mainkeys=
+          bookindex_unordered_hashes.byKey.array.sort().release;
+        foreach (mainkey; mainkeys) {
+          debug(bookindex) {
+            writeln(mainkey);
+          }
+          auto subkeys=
+            bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
+          foreach (subkey; subkeys) {
+            debug(bookindex) {
+              writeln("  ", subkey);
+              writeln("    ", to!string(
+                bookindex_unordered_hashes[mainkey][subkey]
+              ));
+            }
+            // bookindex_the[mkn][mainkey][skn][subkey] ~= (bookindex_unordered_hashes[mainkey][subkey]);
+            ++skn;
+          }
+          ++mkn;
+        }
+      }
+    }
+    struct BookIndexReportSection {
+      mixin ObjectSetter;
+      int mkn, skn;
+      auto rgx = Rgx();
+      auto bookindex_write_section(
+        string[][string][string] bookindex_unordered_hashes
+      ) {
+        auto mainkeys=bookindex_unordered_hashes.byKey.array.sort().release;
+        foreach (mainkey; mainkeys) {
+          write("_0_1 !{", mainkey, "}! ");
+          foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
+            auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+            write(" {", ref_, "}#", go, ", ");
+          }
+          writeln(" \\\\");
+          bookindex_unordered_hashes[mainkey].remove("_a");
+          auto subkeys=
+            bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
+          foreach (subkey; subkeys) {
+            write("  ", subkey, ", ");
+            foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
+              auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+              write(" {", ref_, "}#", go, ", ");
+            }
+            writeln(" \\\\");
+            ++skn;
+          }
+          ++mkn;
+        }
+      }
+      auto bookindex_build_section(
+        string[][string][string] bookindex_unordered_hashes,
+        int obj_cite_number
+      ) {
+        string type;
+        int type_heading;
+        string lev, lev_markup_number, lev_collapsed_number;
+        string attrib;
+        string[string] indent;
+        auto set_abstract_object = ObjectAbstractSet();
+        auto mainkeys =
+          bookindex_unordered_hashes.byKey.array.sort().release;
+        string bi_tmp;
+        string[string][] bookindex_section;
+        // writeln(mainkeys.length);
+        // B~ Book Index
+        type_heading=1;
+        bi_tmp = "Book Index";
+        attrib="";
+        lev="B";
+        lev_markup_number="1";
+        lev_collapsed_number="1";
+        bookindex_section ~=
+          set_abstract_object.contents_heading(
+            type_heading,
+            bi_tmp,
+            attrib,
+            obj_cite_number,
+            lev,
+            lev_markup_number,
+            lev_collapsed_number
+          );
+        ++obj_cite_number;
+        ++mkn;
+        // 1~ Index
+        type_heading=1;
+        bi_tmp = "Index";
+        attrib="";
+        lev="1";
+        lev_markup_number="4";
+        lev_collapsed_number="2";
+        bookindex_section ~=
+          set_abstract_object.contents_heading(
+            type_heading,
+            bi_tmp,
+            attrib,
+            obj_cite_number,
+            lev,
+            lev_markup_number,
+            lev_collapsed_number
+          );
+        ++obj_cite_number;
+        ++mkn;
+        foreach (mainkey; mainkeys) {
+          bi_tmp = "!{" ~ mainkey ~ "}! ";
+          // bi_tmp = "_0_1 !{" ~ mainkey ~ "}! ";
+          foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
+            auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+            bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", ";
+          }
+          bi_tmp ~= " \\\\\n    ";
+          bookindex_unordered_hashes[mainkey].remove("_a");
+          auto subkeys =
+            bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
+          foreach (subkey; subkeys) {
+            bi_tmp ~= subkey ~ ", ";
+            foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
+              auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+              bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", ";
+            }
+            bi_tmp ~= " \\\\\n    ";
+            ++skn;
+          }
+          bi_tmp = replaceFirst(bi_tmp, rgx.trailing_linebreak, "");
+          type="para";
+          attrib="";
+          indent["first"] = "0";
+          indent["second"] = "1";
+          attrib="";
+          // bookindex_section ~=
+          //   set_abstract_object.contents_para(
+          //     obj,
+          //     obj_cite_number,
+          //     indent,
+          //     false
+          //   );
+          bookindex_section ~=
+            set_abstract_object.contents_para(
+              type,
+              bi_tmp,
+              attrib,
+              obj_cite_number,
+              indent,
+              false
+            );
+          ++obj_cite_number;
+          ++mkn;
+        }
+        auto t = tuple(bookindex_section, obj_cite_number);
+        return t;
+      }
+      auto bookindex_build_section_(
+        string[][string][string] bookindex_unordered_hashes
+      ) {
+        auto mainkeys =
+          bookindex_unordered_hashes.byKey.array.sort().release;
+        string bi_tmp;
+        string[] bookindex_section;
+        // int bi_num;
+        // writeln(mainkeys.length);
+        foreach (mainkey; mainkeys) {
+          bi_tmp = "_0_1 !{" ~ mainkey ~ "}! ";
+          foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
+            auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+            bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", ";
+          }
+          bi_tmp ~= " \\\\\n    ";
+          bookindex_unordered_hashes[mainkey].remove("_a");
+          auto subkeys =
+            bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
+          foreach (subkey; subkeys) {
+            bi_tmp ~= subkey ~ ", ";
+            // bi_tmp ~= "  " ~ subkey ~ ", ";
+            foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
+              auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+              bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", ";
+            }
+            bi_tmp ~= " \\\\\n    ";
+            ++skn;
+          }
+          bi_tmp = replaceFirst(bi_tmp, rgx.trailing_linebreak, "");
+          bookindex_section ~= bi_tmp;
+          ++mkn;
+        }
+        return bookindex_section;
+      }
+    }
+    struct NotesSection {
+      mixin ObjectSetter;
+      string object_notes;
+      long previous_count;
+      int mkn;
+      auto rgx = Rgx();
+      private auto gather_notes_for_endnote_section(
+        string[string][] contents_am,
+        long counter
+      )
+      in {
+        // endnotes/ footnotes for
+        // doc objects other than paragraphs & headings
+        // various forms of grouped text
+        assert((contents_am[counter]["is"] == "para")
+        || (contents_am[counter]["is"] == "heading"));
+        assert(counter > previous_count);
+        previous_count=counter;
+        assert(
+          match(contents_am[counter]["obj"],
+          rgx.inline_notes_delimiter_al_regular_number_note)
+        );
+      }
+      body {
+        foreach(m;
+        matchAll(contents_am[counter]["obj"],
+        rgx.inline_notes_delimiter_al_regular_number_note)) {
+          debug(endnotes_build) {
+            writeln(
+              "{^{", m.captures[1], ".}^}#noteref_", m.captures[1], " ",
+              m.captures[2]); // sometimes need segment name (segmented html & epub)
+            // writeln("{^{", m.captures[1], ".}^}#", contents_am[counter]["obj_cite_number"], " ", m.captures[2]);
+          }
+          object_notes ~=
+            "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~
+            m.captures[1] ~ " " ~ m.captures[2] ~ "』";
+        }
+        return object_notes;
+      }
+      private auto gathered_notes()
+      in {
+      }
+      body {
+        string[] endnotes_;
+        if (object_notes.length > 1) {
+          endnotes_ = (split(object_notes, rgx.break_string))[0..$-1];
+        }
+        return endnotes_;
+      }
+      private auto endnote_objects(int obj_cite_number)
+      in {
+      }
+      body {
+        auto set_abstract_object = ObjectAbstractSet();
+        string[string][] endnotes_section;
+        auto endnotes_ = gathered_notes();
+        // auto endnotes_ = (split(object_notes, rgx.break_string))[0..$-1];
+        string type;
+        int type_heading;
+        string lev, lev_markup_number, lev_collapsed_number;
+        string attrib;
+        string[string] indent;
+        // B~ Endnotes
+        type_heading=1;
+        attrib="";
+        lev="B";
+        lev_markup_number="1";
+        lev_collapsed_number="1";
+        endnotes_section ~=
+          set_abstract_object.contents_heading(
+            type_heading,
+            "Endnotes",
+            attrib,
+            obj_cite_number,
+            lev,
+            lev_markup_number,
+            lev_collapsed_number
+          );
+        ++obj_cite_number;
+        ++mkn;
+        // 1~ Endnotes
+        type_heading=1;
+        attrib="";
+        lev="1";
+        lev_markup_number="4";
+        lev_collapsed_number="2";
+        endnotes_section ~=
+          set_abstract_object.contents_heading(
+            type_heading,
+            "Endnotes",
+            attrib,
+            obj_cite_number,
+            lev,
+            lev_markup_number,
+            lev_collapsed_number
+          );
+        ++obj_cite_number;
+        ++mkn;
+        foreach (endnote; endnotes_) {
+          type="para";
+          attrib="";
+          indent["first"] = "0";
+          indent["second"] = "0";
+          attrib="";
+          // endnotes ~=
+          //   set_abstract_object.contents_para(
+          //     obj,
+          //     obj_cite_number,
+          //     indent,
+          //     false
+          //   );
+          endnotes_section ~=
+            set_abstract_object.contents_para(
+              type,
+              endnote,
+              attrib,
+              obj_cite_number,
+              indent,
+              false
+            );
+          ++obj_cite_number;
+          ++mkn;
+        }
+        auto t = tuple(endnotes_section, obj_cite_number);
+        return t;
+      }
+    }
+    struct Bibliography {
+      public JSONValue[] bibliography(ref string[] biblio_unsorted_incomplete, ref JSONValue[] bib_arr_json)
+      in { }
+      body {
+        JSONValue[] biblio_unsorted =
+          biblio_unsorted_complete(biblio_unsorted_incomplete, bib_arr_json);
+        JSONValue[] biblio_sorted = biblio_sort(biblio_unsorted);
+        biblio_debug(biblio_sorted);
+        return biblio_sorted;
+      }
+      final private JSONValue[] biblio_unsorted_complete(
+        string[] biblio_unordered,
+        ref JSONValue[] bib_arr_json
+      ) {
+        foreach (bibent; biblio_unordered) {
+          // update bib to include deemed_author, needed for:
+          // sort_bibliography_array_by_deemed_author_year_title
+          // either: sort on multiple fields, or; create such sort field
+          JSONValue j = parseJSON(bibent);
+          if (!empty(j["fulltitle"].str)) {
+            if (!empty(j["author_raw"].str)) {
+              j["deemed_author"]=j["author_arr"][0];
+            } else if (!empty(j["editor_raw"].str)) {
+              j["deemed_author"]=j["editor_arr"][0];
+            }
+            j["sortby_deemed_author_year_title"] = (
+              j["deemed_author"].str ~
+               "; " ~
+               j["year"].str ~
+               "; "  ~
+               j["fulltitle"].str
+            );
+          }
+          bib_arr_json ~= j;
+        }
+        JSONValue[] biblio_unsorted_array_of_json_objects =
+          bib_arr_json.dup;
+        return biblio_unsorted_array_of_json_objects;
+      }
+      final private JSONValue[] biblio_sort(JSONValue[] biblio_unordered) {
+        JSONValue[] biblio_sorted;
+        biblio_sorted =
+          sort!((a, b){
+            return ((a["sortby_deemed_author_year_title"].str) < (b["sortby_deemed_author_year_title"].str));
+          })(biblio_unordered).array;
+        debug(bibliosorted) {
+          foreach (j; biblio_sorted) {
+            if (!empty(j["fulltitle"].str)) {
+              writeln(j["sortby_deemed_author_year_title"]);
+              // writeln(j["deemed_author"], " (", j["author"], ") ",  j["fulltitle"]);
+            }
+          }
+        }
+        return biblio_sorted;
+      }
+      auto biblio_debug(JSONValue[] biblio_sorted) {
+        debug(biblio) {
+          foreach (j; biblio_sorted) {
+            if (!empty(j["fulltitle"].str)) {
+              writeln(j["sortby_deemed_author_year_title"]);
+            }
+          }
+        }
+      }
+    }
+    struct NodeStructureMetadata {
+    // class NodeStructureMetadata : AssertNodeJSON {
+      int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7;
+      int obj_cite_number;
+      int[string] p_; // p_ parent_
+      string node;
+      string node_emitter(
+        string lev_markup_number,
+        int obj_cite_number_,
+        long counter_,
+        int pointer_,
+        string is_
+      )
+      in {
+        auto rgx = Rgx();
+        assert(is_ != "heading");
+        assert(to!int(obj_cite_number_) >= 0);
+      }
+      body {
+        // scope(failure) {
+        //   writeln(__FILE__, ":", __LINE__, " failed here:");
+        //   writeln("  is  : ", is_);
+        //   writeln("  node: ", node);
+        // }
+        assert(is_ != "heading"); // should not be necessary
+        assert(to!int(obj_cite_number_) >= 0); // should not be necessary
+        int obj_cite_number=to!int(obj_cite_number_);
+        if (lv7 > State.off) {
+          p_["lev_markup_number"] = DocStructMarkupHeading.h_text_4;
+          p_["obj_cite_number"] = lv7;
+        } else if (lv6 > State.off) {
+          p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3;
+          p_["obj_cite_number"] = lv6;
+        } else if (lv5 > State.off) {
+          p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2;
+          p_["obj_cite_number"] = lv5;
+        } else {
+          p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1;
+          p_["obj_cite_number"] = lv4;
+        }
+        node=("{ " ~
+          "\"is\": \"" ~ is_ ~ "\"" ~
+          ", \"heading_pointer\": " ~ to!string(pointer_) ~
+          ", \"doc_object_pointer\": " ~ to!string(counter_) ~
+          ", \"obj_cite_number\": " ~ to!string(obj_cite_number_) ~
+          ", \"parent_obj_cite_number\": " ~ to!string(p_["obj_cite_number"]) ~
+          ", \"parent_lev_markup_number\": " ~ to!string(p_["lev_markup_number"]) ~
+          " }"
+        );
+        debug(node) {
+          mixin ScreenTxtColors;
+          if (match(lev_markup_number, rgx.levels_numbered_headings)) {
+            writeln(scr_txt_marker["yellow"], to!string(node));
+          } else {
+            writeln(scr_txt_marker["white"], to!string(node));
+          }
+        }
+        JSONValue j = parseJSON(node);
+        assert(j["parent_lev_markup_number"].integer >= 4);
+        assert(j["parent_lev_markup_number"].integer <= 7);
+        assert(j["parent_obj_cite_number"].integer >= 0);
+        return node;
+      }
+      invariant() {
+      }
+      string node_emitter_heading(
+        string lev_markup_number,
+        string lev_collapsed_number,
+        int obj_cite_number_,
+        long counter_,
+        int pointer_,
+        string is_
+      )
+      in {
+        auto rgx = Rgx();
+        assert(is_ == "heading");
+        assert(to!int(obj_cite_number_) >= 0);
+        assert(
+          match(lev_markup_number, rgx.levels_numbered),
+          ("not a valid heading level: " ~ lev_markup_number ~ " at " ~ to!string(obj_cite_number_))
+        );
+        // assert(to!int(obj_cite_number_) >= 0);
+        if (match(lev_markup_number, rgx.levels_numbered)) {
+          if (to!int(lev_markup_number) == 0) {
+            assert(to!int(obj_cite_number_) == 1);
+            // writeln(lev_markup_number);
+          }
+        }
+      }
+      body {
+        // scope(failure) {
+        //   writeln(__FILE__, ":", __LINE__, " failed here:");
+        //   writeln("  is  : ", is_);
+        //   writeln("  node: ", node);
+        // }
+        auto rgx = Rgx();
+        int obj_cite_number = to!int(obj_cite_number_);
+        switch (lev_markup_number) { // switch (to!string(lv)) {
+        case "0":
+          lv = DocStructMarkupHeading.h_sect_A;
+          lv0 = obj_cite_number;
+          lv1=0; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
+          p_["lev_markup_number"] = 0;
+          p_["obj_cite_number"] = 0;
+          break;
+        case "1":
+          lv = DocStructMarkupHeading.h_sect_B;
+          lv1 = obj_cite_number;
+          lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
+          p_["lev_markup_number"] =
+            DocStructMarkupHeading.h_sect_A;
+          p_["obj_cite_number"] = lv0;
+          break;
+        case "2":
+          lv = DocStructMarkupHeading.h_sect_C;
+          lv2 = obj_cite_number;
+          lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
+          p_["lev_markup_number"] =
+            DocStructMarkupHeading.h_sect_B;
+          p_["obj_cite_number"] = lv1;
+          break;
+        case "3":
+          lv = DocStructMarkupHeading.h_sect_D;
+          lv3=obj_cite_number;
+          lv4=0; lv5=0; lv6=0; lv7=0;
+          p_["lev_markup_number"] =
+            DocStructMarkupHeading.h_sect_C;
+          p_["obj_cite_number"] = lv2;
+          break;
+        case "4":
+          lv = DocStructMarkupHeading.h_text_1;
+          lv4 = obj_cite_number;
+          lv5=0; lv6=0; lv7=0;
+          if (lv3 > State.off) {
+            p_["lev_markup_number"] =
+              DocStructMarkupHeading.h_sect_D;
+            p_["obj_cite_number"] = lv3;
+          } else if (lv2 > State.off) {
+            p_["lev_markup_number"] =
+              DocStructMarkupHeading.h_sect_C;
+            p_["obj_cite_number"] = lv2;
+          } else if (lv1 > State.off) {
+            p_["lev_markup_number"] =
+              DocStructMarkupHeading.h_sect_B;
+            p_["obj_cite_number"] = lv1;
+          } else {
+            p_["lev_markup_number"] =
+              DocStructMarkupHeading.h_sect_A;
+            p_["obj_cite_number"] = lv0;
+          }
+          break;
+        case "5":
+          lv = DocStructMarkupHeading.h_text_2;
+          lv5 = obj_cite_number;
+          lv6=0; lv7=0;
+          p_["lev_markup_number"] =
+            DocStructMarkupHeading.h_text_1;
+          p_["obj_cite_number"] = lv4;
+          break;
+        case "6":
+          lv = DocStructMarkupHeading.h_text_3;
+          lv6 = obj_cite_number;
+          lv7=0;
+          p_["lev_markup_number"] =
+            DocStructMarkupHeading.h_text_2;
+          p_["obj_cite_number"] = lv5;
+          break;
+        case "7":
+          lv = DocStructMarkupHeading.h_text_4;
+          lv7 = obj_cite_number;
+          p_["lev_markup_number"] =
+            DocStructMarkupHeading.h_text_3;
+          p_["obj_cite_number"] = lv6;
+          break;
+        default:
+          // if (lv7 > State.off) {
+          //   p_["lev_markup_number"] = 7; p_["obj_cite_number"] = lv7;
+          // } else if (lv6 > State.off) {
+          //   p_["lev_markup_number"] = 6; p_["obj_cite_number"] = lv6;
+          // } else if (lv5 > State.off) {
+          //   p_["lev_markup_number"] = 5; p_["obj_cite_number"] = lv5;
+          // } else {
+          //   p_["lev_markup_number"] = 4; p_["obj_cite_number"] = lv4;
+          // }
+          break;
+        }
+        node=("{ " ~
+          "\"is\": \"" ~ is_ ~ "\"" ~
+          ", \"heading_pointer\": " ~ to!string(pointer_) ~
+          ", \"doc_object_pointer\": " ~ to!string(counter_) ~
+          ", \"obj_cite_number\": " ~ to!string(obj_cite_number_) ~
+          ",  \"lev_markup_number\": " ~ to!string(lev_markup_number) ~
+          ",  \"lev_collapsed_number\": " ~ to!string(lev_collapsed_number) ~
+          ", \"parent_obj_cite_number\": " ~ to!string(p_["obj_cite_number"]) ~
+          ", \"parent_lev_markup_number\": " ~ to!string(p_["lev_markup_number"]) ~
+          " }"
+        );
+        debug(heading) {
+          mixin ScreenTxtColors;
+          if (match(lev_markup_number, rgx.levels_numbered_headings)) {
+            writeln(scr_txt_marker["yellow"], to!string(node));
+          }
+        }
+        debug(node) {
+          mixin ScreenTxtColors;
+          if (match(lev_markup_number, rgx.levels_numbered_headings)) {
+            writeln(scr_txt_marker["yellow"], to!string(node));
+          } else {
+            writeln(scr_txt_marker["white"], to!string(node));
+          }
+        }
+        JSONValue j = parseJSON(node);
+        assert(j["parent_lev_markup_number"].integer <= 7);
+        assert(j["parent_obj_cite_number"].integer >= 0);
+        if (match(lev_markup_number, rgx.levels_numbered_headings)) {
+          assert(j["lev_markup_number"].integer <= 7);
+          assert(j["obj_cite_number"].integer >= 0);
+          if (j["parent_lev_markup_number"].integer > 0) {
+            assert(j["parent_lev_markup_number"].integer < j["lev_markup_number"].integer);
+            if (j["obj_cite_number"].integer != 0) {
+              assert(j["parent_obj_cite_number"].integer < j["obj_cite_number"].integer);
+            }
+          }
+          if (j["lev_markup_number"].integer == 0) {
+            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_sect_A);
+          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_sect_B) {
+            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_sect_A);
+          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_sect_C) {
+            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_sect_B);
+          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_sect_D) {
+            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_sect_C);
+          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_text_1) {
+            assert(j["parent_lev_markup_number"].integer <= DocStructMarkupHeading.h_sect_D);
+          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_text_2) {
+            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_text_1);
+          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_text_3) {
+            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_text_2);
+          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_text_4) {
+            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_text_3);
+          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_text_5) {
+            // writeln(j["parent_lev_markup_number"].integer);
+            // assert(j["parent_lev_markup_number"].integer >= 4);
+            // assert(j["parent_lev_markup_number"].integer <= 7);
+          }
+        }
+        return node;
+      }
+      invariant() {
+      }
+    }
+    /+ abstraction functions emitters ↑ +/
+
+    /+ ↓ abstraction functions assertions +/
+    auto assertions_doc_structure(string[string] an_object, int[string] lv) {
+      if (lv["h3"] > State.off) {
+        assert(lv["h0"] > State.off);
+        assert(lv["h1"] > State.off);
+        assert(lv["h2"] > State.off);
+      } else if (lv["h2"] > State.off) {
+        assert(lv["h0"] > State.off);
+        assert(lv["h1"] > State.off);
+        assert(lv["h3"] == State.off);
+      } else if (lv["h1"] > State.off) {
+        assert(lv["h0"] > State.off);
+        assert(lv["h2"] == State.off);
+        assert(lv["h3"] == State.off);
+      } else if (lv["h0"] > State.off) {
+        assert(lv["h1"] == State.off);
+        assert(lv["h2"] == State.off);
+        assert(lv["h3"] == State.off);
+      } else {
+        assert(lv["h0"] == State.off);
+        assert(lv["h1"] == State.off);
+        assert(lv["h2"] == State.off);
+        assert(lv["h3"] == State.off);
+      }
+      if (lv["h7"] > State.off) {
+        assert(lv["h4"] > State.off);
+        assert(lv["h5"] > State.off);
+        assert(lv["h6"] > State.off);
+      } else if (lv["h6"] > State.off) {
+        assert(lv["h4"] > State.off);
+        assert(lv["h5"] > State.off);
+        assert(lv["h7"] == State.off);
+      } else if (lv["h5"] > State.off) {
+        assert(lv["h4"] > State.off);
+        assert(lv["h6"] == State.off);
+        assert(lv["h7"] == State.off);
+      } else if (lv["h4"] > State.off) {
+        assert(lv["h5"] == State.off);
+        assert(lv["h6"] == State.off);
+        assert(lv["h7"] == State.off);
+      } else {
+        assert(lv["h4"] == State.off);
+        assert(lv["h5"] == State.off);
+        assert(lv["h6"] == State.off);
+        assert(lv["h7"] == State.off);
+      }
+      if (lv["h0"] == State.off) {
+        assert(lv["h1"] == State.off);
+        assert(lv["h2"] == State.off);
+        assert(lv["h3"] == State.off);
+        assert(lv["h4"] == State.off);
+        assert(lv["h5"] == State.off);
+        assert(lv["h6"] == State.off);
+        assert(lv["h7"] == State.off);
+      }
+      if (lv["h1"] == State.off) {
+        assert(lv["h2"] == State.off);
+        assert(lv["h3"] == State.off);
+      }
+      if (lv["h2"] == State.off) {
+        assert(lv["h3"] == State.off);
+      }
+      if (lv["h3"] == State.off) {
+      }
+      if (lv["h4"] == State.off) {
+        assert(lv["h5"] == State.off);
+        assert(lv["h6"] == State.off);
+        assert(lv["h7"] == State.off);
+      }
+      if (lv["h5"] == State.off) {
+        assert(lv["h6"] == State.off);
+        assert(lv["h7"] == State.off);
+      }
+      if (lv["h6"] == State.off) {
+        assert(lv["h7"] == State.off);
+      }
+      if (lv["h7"] == State.off) {
+      }
+      switch (to!string(an_object["lev"])) {
+      case "A":
+        if (lv["h0"] == State.off) {
+          assert(lv["h1"] == State.off);
+          assert(lv["h2"] == State.off);
+          assert(lv["h3"] == State.off);
+          assert(lv["h4"] == State.off);
+          assert(lv["h5"] == State.off);
+          assert(lv["h6"] == State.off);
+          assert(lv["h7"] == State.off);
+        } else {  // (lv["h0"] > State.off)
+          assert(lv["h0"] == State.off,"error should not enter level A a second time");
+        }
+        break;
+      case "B":
+        if (lv["h1"] == State.off) {
+          assert(lv["h0"] > State.off);
+          assert(lv["h2"] == State.off);
+          assert(lv["h3"] == State.off);
+        } else {                 // (lv["h1"] > State.off)
+          assert(lv["h0"] > State.off);
+          assert(lv["h1"] > State.off);  //
+        }
+        break;
+      case "C":
+        if (lv["h2"] == State.off) {
+          assert(lv["h0"] > State.off);
+          assert(lv["h1"] > State.off);
+          assert(lv["h3"] == State.off);
+        } else {                 // (lv["h2"] > State.off)
+          assert(lv["h0"] > State.off);
+          assert(lv["h1"] > State.off);
+          assert(lv["h2"] > State.off);  //
+        }
+        break;
+      case "D":
+        if (lv["h3"] == State.off) {
+          assert(lv["h0"] > State.off);
+          assert(lv["h1"] > State.off);
+          assert(lv["h2"] > State.off);
+        } else {                 // (lv["h3"] > State.off)
+          assert(lv["h0"] > State.off);
+          assert(lv["h1"] > State.off);
+          assert(lv["h2"] > State.off);
+          assert(lv["h3"] > State.off);
+        }
+        break;
+      case "1":
+        if (lv["h4"] == State.off) {
+          assert(lv["h0"] > State.off);
+        } else {                 // (lv["h4"] > State.off)
+          assert(lv["h0"] > State.off);
+          assert(lv["h4"] > State.off);  //
+        }
+        break;
+      case "2":
+        if (lv["h5"] == State.off) {
+          assert(lv["h0"] > State.off);
+          assert(lv["h4"] > State.off);
+        } else {                 // (lv["h5"] > State.off)
+          assert(lv["h0"] > State.off);
+          assert(lv["h4"] > State.off);
+          assert(lv["h5"] > State.off);  //
+        }
+        break;
+      case "3":
+        if (lv["h6"] == State.off) {
+          assert(lv["h0"] > State.off);
+          assert(lv["h4"] > State.off);
+          assert(lv["h5"] > State.off);
+        } else {                 // (lv["h6"] > State.off)
+          assert(lv["h0"] > State.off);
+          assert(lv["h4"] > State.off);
+          assert(lv["h5"] > State.off);
+          assert(lv["h6"] > State.off);  //
+        }
+        break;
+      case "4":
+        if (lv["h7"] == State.off) {
+          assert(lv["h0"] > State.off);
+          assert(lv["h4"] > State.off);
+          assert(lv["h5"] > State.off);
+          assert(lv["h6"] > State.off);
+        } else {                 // (lv["h7"] > State.off)
+          assert(lv["h0"] > State.off);
+          assert(lv["h4"] > State.off);
+          assert(lv["h5"] > State.off);
+          assert(lv["h6"] > State.off);
+          assert(lv["h7"] > State.off);  //
+        }
+        break;
+      default:
+        break;
+      }
+    }
+    auto assertions_flag_types_block_status_none_or_closed(int[string] type) {
+      assert(
+        (type["code"] == TriState.off)
+        || (type["code"] == TriState.closing),
+        "code block status: off or closing");
+      assert(
+        (type["poem"] == TriState.off)
+        || (type["poem"] == TriState.closing),
+        "poem status: off or closing");
+      assert(
+        (type["table"] == TriState.off)
+        || (type["table"] == TriState.closing),
+        "table status: off or closing");
+      assert(
+        (type["group"] == TriState.off)
+        || (type["group"] == TriState.closing),
+        "group block status: off or closing");
+      assert(
+        (type["block"] == TriState.off)
+        || (type["block"] == TriState.closing),
+        "block status: off or closing");
     }
-  }
-}
+    /+ abstraction functions assertions ↑ +/
+
+  } /+ ← closed: struct Abstraction +/
+
+} /+ ← closed: template SiSUdocAbstraction +/
diff --git a/lib/sdp/ao_ansi_colors.d b/lib/sdp/ao_ansi_colors.d
new file mode 100644
index 0000000..e5a46f9
--- /dev/null
+++ b/lib/sdp/ao_ansi_colors.d
@@ -0,0 +1,74 @@
+/+
+  utils
+  ao_util.d
++/
+template ScreenTxtColors() {
+  string[string] scr_txt_color = [
+    "off"           : "\033[0m",
+    "white"         : "\033[37m",
+    "white_bold"    : "\033[1m",
+    "marker"        : "\033[42m",
+    "bold"          : "\033[1m",
+    "underline"     : "\033[4m",
+    "invert"        : "\033[7m",
+    "darkgrey_hi"   : "\033[100m",
+    "grey_hi"       : "\033[47m",
+    "pink_hi"       : "\033[105m",
+    "fuchsia_hi"    : "\033[45m",
+    "red_hi"        : "\033[41m",
+    "orange_hi"     : "\033[101m",
+    "yellow_hi"     : "\033[103m",
+    "brown_hi"      : "\033[43m",
+    "lightgreen_hi" : "\033[102m",
+    "green_hi"      : "\033[42m",
+    "cyan_hi"       : "\033[106m",
+    "blue_hi"       : "\033[104m",
+    "navy_hi"       : "\033[44m",
+    "grey"          : "\033[90m",
+    "pink"          : "\033[95m",
+    "fuchsia"       : "\033[35m",
+    "ruby"          : "\033[31m",
+    "red"           : "\033[91m",
+    "orange"        : "\033[91m",
+    "yellow"        : "\033[93m",
+    "brown"         : "\033[33m",
+    "green"         : "\033[92m",
+    "darkgreen"     : "\033[32m",
+    "cyan"          : "\033[36m",
+    "blue"          : "\033[94m",
+    "navy"          : "\033[34m",
+    "black"         : "\033[30m"
+  ];
+  string[string] scr_txt_marker = [
+    "white"         : "\033[37m*\033[0m ",
+    "bold"          : "\033[1m*\033[0m ",
+    "invert"        : "\033[7m*\033[0m ",
+    "darkgrey_hi"   : "\033[100m*\033[0m ",
+    "grey_hi"       : "\033[47m*\033[0m ",
+    "pink_hi"       : "\033[105m*\033[0m ",
+    "fuchsia_hi"    : "\033[45m*\033[0m ",
+    "red_hi"        : "\033[41m*\033[0m ",
+    "orange_hi"     : "\033[101m*\033[0m ",
+    "yellow_hi"     : "\033[103m*\033[0m ",
+    "brown_hi"      : "\033[43m*\033[0m ",
+    "lightgreen_hi" : "\033[102m*\033[0m ",
+    "green_hi"      : "\033[42m*\033[0m ",
+    "cyan_hi"       : "\033[106m*\033[0m ",
+    "blue_hi"       : "\033[104m*\033[0m ",
+    "navy_hi"       : "\033[44m*\033[0m ",
+    "grey"          : "\033[90m*\033[0m ",
+    "pink"          : "\033[95m*\033[0m ",
+    "fuchsia"       : "\033[35m*\033[0m ",
+    "ruby"          : "\033[31m*\033[0m ",
+    "red"           : "\033[91m*\033[0m ",
+    "orange"        : "\033[91m*\033[0m ",
+    "yellow"        : "\033[93m*\033[0m ",
+    "brown"         : "\033[33m*\033[0m ",
+    "green"         : "\033[92m*\033[0m ",
+    "darkgreen"     : "\033[32m*\033[0m ",
+    "cyan"          : "\033[36m*\033[0m ",
+    "blue"          : "\033[94m*\033[0m ",
+    "navy"          : "\033[34m*\033[0m ",
+    "black"         : "\033[30m*\033[0m "
+  ];
+}
diff --git a/lib/sdp/ao_assertions.d b/lib/sdp/ao_assertions.d
deleted file mode 100644
index 2aa2c1d..0000000
--- a/lib/sdp/ao_assertions.d
+++ /dev/null
@@ -1,221 +0,0 @@
-/+
-  assertions
-  ao_assertions.d
-+/
-mixin template AssertionsOnMarkupDocumentStructure() {
-  auto assertions_doc_structure(string[string] object, uint[string] lv) {
-    if (lv["h3"] > 0) {
-      assert(lv["h0"] > 0);
-      assert(lv["h1"] > 0);
-      assert(lv["h2"] > 0);
-      assert(lv["h3"] > 0);
-    } else if (lv["h2"] > 0) {
-      assert(lv["h0"] > 0);
-      assert(lv["h1"] > 0);
-      assert(lv["h2"] > 0);
-      assert(lv["h3"] == 0);
-    } else if (lv["h1"] > 0) {
-      assert(lv["h0"] > 0);
-      assert(lv["h1"] > 0);
-      assert(lv["h2"] == 0);
-      assert(lv["h3"] == 0);
-    } else if (lv["h0"] > 0) {
-      assert(lv["h0"] > 0);
-      assert(lv["h1"] == 0);
-      assert(lv["h2"] == 0);
-      assert(lv["h3"] == 0);
-    } else {
-      assert(lv["h0"] == 0);
-      assert(lv["h1"] == 0);
-      assert(lv["h2"] == 0);
-      assert(lv["h3"] == 0);
-    }
-    if (lv["h7"] > 0) {
-      assert(lv["h4"] > 0);
-      assert(lv["h5"] > 0);
-      assert(lv["h6"] > 0);
-      assert(lv["h7"] > 0);
-    } else if (lv["h6"] > 0) {
-      assert(lv["h4"] > 0);
-      assert(lv["h5"] > 0);
-      assert(lv["h6"] > 0);
-      assert(lv["h7"] == 0);
-    } else if (lv["h5"] > 0) {
-      assert(lv["h4"] > 0);
-      assert(lv["h5"] > 0);
-      assert(lv["h6"] == 0);
-      assert(lv["h7"] == 0);
-    } else if (lv["h4"] > 0) {
-      assert(lv["h4"] > 0);
-      assert(lv["h5"] == 0);
-      assert(lv["h6"] == 0);
-      assert(lv["h7"] == 0);
-    } else {
-      assert(lv["h4"] == 0);
-      assert(lv["h5"] == 0);
-      assert(lv["h6"] == 0);
-      assert(lv["h7"] == 0);
-    }
-    if (lv["h0"] == 0) {
-      assert(lv["h0"] == 0);
-      assert(lv["h1"] == 0);
-      assert(lv["h2"] == 0);
-      assert(lv["h3"] == 0);
-      assert(lv["h4"] == 0);
-      assert(lv["h5"] == 0);
-      assert(lv["h6"] == 0);
-      assert(lv["h7"] == 0);
-    }
-    if (lv["h1"] == 0) {
-      assert(lv["h1"] == 0);
-      assert(lv["h2"] == 0);
-      assert(lv["h3"] == 0);
-    }
-    if (lv["h2"] == 0) {
-      assert(lv["h2"] == 0);
-      assert(lv["h3"] == 0);
-    }
-    if (lv["h3"] == 0) {
-      assert(lv["h3"] == 0);
-    }
-    if (lv["h4"] == 0) {
-      assert(lv["h4"] == 0);
-      assert(lv["h5"] == 0);
-      assert(lv["h6"] == 0);
-      assert(lv["h7"] == 0);
-    }
-    if (lv["h5"] == 0) {
-      assert(lv["h5"] == 0);
-      assert(lv["h6"] == 0);
-      assert(lv["h7"] == 0);
-    }
-    if (lv["h6"] == 0) {
-      assert(lv["h6"] == 0);
-      assert(lv["h7"] == 0);
-    }
-    if (lv["h6"] == 0) {
-      assert(lv["h7"] == 0);
-    }
-    switch (to!string(object["lev"])) {
-    case "A":
-      if (lv["h0"]==0) {
-        assert(lv["h0"] == 0);
-        assert(lv["h1"] == 0);
-        assert(lv["h2"] == 0);
-        assert(lv["h3"] == 0);
-        assert(lv["h4"] == 0);
-        assert(lv["h5"] == 0);
-        assert(lv["h6"] == 0);
-        assert(lv["h7"] == 0);
-      } else {  // (lv["h0"] >0)
-        assert(lv["h0"] == 0,"error should not enter level A a second time");
-      }
-      break;
-    case "B":
-      if (lv["h1"]==0) {
-        assert(lv["h0"] > 0);
-        assert(lv["h1"] == 0); //
-        assert(lv["h2"] == 0);
-        assert(lv["h3"] == 0);
-      } else {                 // (lv["h1"] >0)
-        assert(lv["h0"] > 0);
-        assert(lv["h1"] > 0);  //
-      }
-      break;
-    case "C":
-      if (lv["h2"]==0) {
-        assert(lv["h0"] > 0);
-        assert(lv["h1"] > 0);
-        assert(lv["h2"] == 0); //
-        assert(lv["h3"] == 0);
-      } else {                 // (lv["h2"] > 0)
-        assert(lv["h0"] > 0);
-        assert(lv["h1"] > 0);
-        assert(lv["h2"] > 0);  //
-      }
-      break;
-    case "D":
-      if (lv["h3"]==0) {
-        assert(lv["h0"] > 0);
-        assert(lv["h1"] > 0);
-        assert(lv["h2"] > 0);
-        assert(lv["h3"] == 0); //
-      } else {                 // (lv["h3"] >0)
-        assert(lv["h0"] > 0);
-        assert(lv["h1"] > 0);
-        assert(lv["h2"] > 0);
-        assert(lv["h3"] > 0);
-      }
-      break;
-    case "1":
-      if (lv["h4"]==0) {
-        assert(lv["h0"] > 0);
-        assert(lv["h4"] == 0); //
-      } else {                 // (lv["h4"] >0)
-        assert(lv["h0"] > 0);
-        assert(lv["h4"] > 0);  //
-      }
-      break;
-    case "2":
-      if (lv["h5"]==0) {
-        assert(lv["h0"] > 0);
-        assert(lv["h4"] > 0);
-        assert(lv["h5"] == 0); //
-      } else {                 // (lv["h5"] >0)
-        assert(lv["h0"] > 0);
-        assert(lv["h4"] > 0);
-        assert(lv["h5"] > 0);  //
-      }
-      break;
-    case "3":
-      if (lv["h6"]==0) {
-        assert(lv["h0"] > 0);
-        assert(lv["h4"] > 0);
-        assert(lv["h5"] > 0);
-        assert(lv["h6"] == 0); //
-      } else {                 // (lv["h6"] >0)
-        assert(lv["h0"] > 0);
-        assert(lv["h4"] > 0);
-        assert(lv["h5"] > 0);
-        assert(lv["h6"] > 0);  //
-      }
-      break;
-    case "4":
-      if (lv["h7"]==0) {
-        assert(lv["h0"] > 0);
-        assert(lv["h4"] > 0);
-        assert(lv["h5"] > 0);
-        assert(lv["h6"] > 0);
-        assert(lv["h7"] == 0); //
-      } else {                 // (lv["h7"] >0)
-        assert(lv["h0"] > 0);
-        assert(lv["h4"] > 0);
-        assert(lv["h5"] > 0);
-        assert(lv["h6"] > 0);
-        assert(lv["h7"] > 0);  //
-      }
-      break;
-    default:
-      break;
-    }
-  }
-}
-mixin template AssertionsOnBlocks() {
-  auto assertions_flag_types_block_status_none_or_closed(int[string] flag_type) {
-    assert(
-      (flag_type["code"] == 0) || (flag_type["code"] == 2),
-      "code block status: none or closed");
-    assert(
-      (flag_type["poem"] == 0) || (flag_type["poem"] == 2),
-      "poem status: none or closed");
-    assert(
-      (flag_type["table"] == 0) || (flag_type["table"] == 2),
-      "table status: none or closed");
-    assert(
-      (flag_type["group"] == 0) || (flag_type["group"] == 2),
-      "group block status: none or closed");
-    assert(
-      (flag_type["block"] == 0) || (flag_type["block"] == 2),
-      "block status: none or closed");
-  }
-}
diff --git a/lib/sdp/ao_defaults.d b/lib/sdp/ao_defaults.d
index 166871b..04f5506 100644
--- a/lib/sdp/ao_defaults.d
+++ b/lib/sdp/ao_defaults.d
@@ -167,37 +167,40 @@ template SiSUheader() {
 }
 /+ regex flags +/
 template SiSUrgxInitFlags() {
-  int[string] flag_type = [
-    "make_headings"        : 0,
-    "header_make"          : 0,
-    "header_metadata"      : 0,
-    "heading"              : 0,
-    "heading_biblio"       : 0,
-    "para"                 : 0,
-    "blocks"               : 0, // 0..2 generic
-    "code"                 : 0, // 0..2
-    "poem"                 : 0, // 0..2
-    "table"                : 0, // 0..2
-    "group"                : 0, // 0..2
-    "block"                : 0, // 0..2
-    "quote"                : 0, // 0..2
-    "verse_new"            : 0,
-    "curly_code"           : 0,
-    "curly_poem"           : 0,
-    "curly_table"          : 0,
-    "curly_group"          : 0,
-    "curly_block"          : 0,
-    "curly_quote"          : 0,
-    "tic_code"             : 0,
-    "tic_poem"             : 0,
-    "tic_table"            : 0,
-    "tic_group"            : 0,
-    "tic_block"            : 0,
-    "tic_quote"            : 0,
-    "ocn_status"           : 0, // 0 ocn; 1 no ocn; 2 no ocn & dummy headings
-    "ocn_status_multi_obj" : 0, // 0 ocn; 1 no ocn; 2 no ocn & dummy headings
-    "book_index"           : 0,
-  ];
+  int[string] flags_type_init() {
+    int[string] flags_type_init = [
+      "make_headings"        : 0,
+      "header_make"          : 0,
+      "header_metadata"      : 0,
+      "heading"              : 0,
+      "heading_biblio"       : 0,
+      "para"                 : 0,
+      "blocks"               : 0, // 0..2 generic
+      "code"                 : 0, // 0..2
+      "poem"                 : 0, // 0..2
+      "table"                : 0, // 0..2
+      "group"                : 0, // 0..2
+      "block"                : 0, // 0..2
+      "quote"                : 0, // 0..2
+      "verse_new"            : 0,
+      "curly_code"           : 0,
+      "curly_poem"           : 0,
+      "curly_table"          : 0,
+      "curly_group"          : 0,
+      "curly_block"          : 0,
+      "curly_quote"          : 0,
+      "tic_code"             : 0,
+      "tic_poem"             : 0,
+      "tic_table"            : 0,
+      "tic_group"            : 0,
+      "tic_block"            : 0,
+      "tic_quote"            : 0,
+      "obj_cite_number_status"           : 0, // 0 obj_cite_number; 1 no obj_cite_number; 2 no obj_cite_number & dummy headings
+      "obj_cite_number_status_multi_obj" : 0, // 0 obj_cite_number; 1 no obj_cite_number; 2 no obj_cite_number & dummy headings
+      "book_index"           : 0,
+    ];
+    return flags_type_init;
+  }
 }
 template SiSUbiblio() {
   auto biblio_entry_tags_jsonstr =  `{
@@ -229,31 +232,15 @@ template SiSUbiblio() {
     "short_name"                       : "",
     "id"                               : ""
   }`; // is: book, article, magazine, newspaper, blog, other
-  auto biblio_tag_map = [
-    "au"                               : "author_raw",
-    "ed"                               : "editor_raw",
-    "ti"                               : "fulltitle",
-    "lng"                              : "language",
-    "jo"                               : "journal",
-    "vol"                              : "volume",
-    "edn"                              : "edition",
-    "yr"                               : "year",
-    "pl"                               : "place",
-    "pb"                               : "publisher",
-    "pub"                              : "publisher",
-    "pg"                               : "pages",
-    "pgs"                              : "pages",
-    "sn"                               : "short_name"
-  ]; // is: book, article, magazine, newspaper, blog, other
 }
 template InternalMarkup() {
-  struct InternalMarkup {
+  struct InlineMarkup {
     auto en_a_o = "【"; auto en_a_c = "】";
     auto en_b_o = "〖"; auto en_b_c = "〗";
     // auto segname_prefix_auto_num_extract = "c";
     // auto segname_prefix_auto_num_provide = "s";
     // auto segname_prefix_auto_num_other = "x";
-    // auto ocn_id_char = "";                                              //'o'; now as before; remove for html5
+    // auto obj_cite_number_id_char = "";                                              //'o'; now as before; remove for html5
     // auto note = "note_";
     // auto note_ref = "noteref_";
     // auto note_astx = "note_astx_";
diff --git a/lib/sdp/ao_object_setter.d b/lib/sdp/ao_object_setter.d
index ce4611d..a44aeb0 100644
--- a/lib/sdp/ao_object_setter.d
+++ b/lib/sdp/ao_object_setter.d
@@ -2,174 +2,92 @@
   object setter
   ao_object_setter.d
 +/
-mixin template ObjectSetters() {
+template ObjectSetter() {
   struct ObjectAbstractSet {
     import std.conv : to;
-    mixin Structs;
-    ObjComposite contents_comment_new(in string object) {
-      ObjComposite object_set;
-      object_set.use                  = "comment";
-      object_set.of                   = "comment";
-      object_set.is_a                 = "comment";
-      object_set.object               = object;
-      // does not have .attrib;
-      // does not have .ocn
-      return object_set;
-    }
     string[string] contents_comment(in string object) {
       string[string] object_set;
       object_set["use"]           = "comment";
       object_set["of"]            = "comment";
       object_set["is"]            = "comment";
       object_set["obj"]           = object;
-      return object_set;
-    }
-    ObjComposite contents_heading_new(
-      in int type,
-      in string object,
-      in string attrib,
-      in int ocn,
-      in string lev,
-      in string lvn,
-      in string lcn,
-    ) {
-      ObjComposite object_set;
-      object_set.use                  = "content";
-      object_set.of                   = "para";
-      object_set.is_a                 = "heading";
-      object_set.object               = object;
-      object_set.ocn                  = (ocn==0) ? "" : to!string(ocn);
-      object_set.attrib               = attrib;
-      object_set.heading.type         = to!string(type);
-      object_set.heading.lev          = to!string(lev);
-      object_set.heading.lvn          = to!string(lvn);
-      object_set.heading.lcn          = to!string(lcn);
+      // object_set["attrib"]     = attrib;
       return object_set;
     }
     string[string] contents_heading(
       in int type,
       in string object,
       in string attrib,
-      in int ocn,
+      in int obj_cite_number,
       in string lev,
-      in string lvn,
-      in string lcn,
+      in string lev_markup_number,
+      in string lev_collapsed_number,
     ) {
       string[string] object_set;
-      object_set["use"]           = "content";
-      object_set["of"]            = "para";
-      object_set["is"]            = "heading";
-      object_set["type"]          = to!string(type);
-      object_set["obj"]           = object;
-      object_set["ocn"]           = (ocn==0) ? "" : to!string(ocn);
-      object_set["lev"]           = to!string(lev);
-      object_set["lvn"]           = to!string(lvn);
-      object_set["lcn"]           = to!string(lcn);
-      object_set["attrib"]        = attrib;
-      return object_set;
-    }
-    ObjComposite contents_para_new(
-      in string is_a,
-      in string object,
-      in string attrib,
-      in int ocn,
-      in string indent_first,
-      in string indent_second,
-      in bool bullet
-    ) {
-      ObjComposite object_set;
-      object_set.use                 = "content";
-      object_set.of                  = "para";
-      object_set.is_a                = "heading";
-      object_set.object              = object;
-      object_set.ocn                 = (ocn==0) ? "" : to!string(ocn);
-      object_set.attrib              = attrib;
-      object_set.para.indent_first        = indent_first;
-      object_set.para.indent_second       = indent_second;
-      object_set.para.bullet              = to!string(bullet);
+      object_set["use"]                  = "content";
+      object_set["of"]                   = "para";
+      object_set["is"]                   = "heading";
+      object_set["type"]                 = to!string(type);
+      // object_set["is"]                = type; // "heading" "heading_dummy"
+      object_set["obj"]                  = object;
+      object_set["obj_cite_number"]      = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+      object_set["lev"]                  = to!string(lev);
+      object_set["lev_markup_number"]    = to!string(lev_markup_number);
+      object_set["lev_collapsed_number"] = to!string(lev_collapsed_number);
+      object_set["attrib"]               = attrib;
+      // object_set["children"]          = children;
       return object_set;
     }
     string[string] contents_para(
       in string is_a,
       in string object,
       in string attrib,
-      in int ocn,
-      in string indent_first,
-      in string indent_second,
+      in int obj_cite_number,
+      in string[string] indent,
       in bool bullet
     ) {
       string[string] object_set;
-      object_set["use"]           = "content";
-      object_set["of"]            = "para";
-      object_set["is"]            = is_a;
-      object_set["obj"]           = object;
-      object_set["ocn"]           = (ocn==0) ? "" : to!string(ocn);
-      object_set["indent_first"]  = indent_first;
-      object_set["indent_second"] = indent_second;
-      object_set["bullet"]        = to!string(bullet);
-      object_set["attrib"]        = attrib;
-      return object_set;
-    }
-    ObjComposite contents_block_new(
-      in string type,
-      in string object,
-      in string attrib,
-      in int ocn
-    ) {
-      ObjComposite object_set;
-      // does not have .attrib;
-      object_set.use                 = "content";
-      object_set.of                  = "block";
-      object_set.is_a                = type;
-      object_set.object              = object;
-      object_set.ocn                 = (ocn==0) ? "" : to!string(ocn);
-      object_set.attrib              = attrib;
+      object_set["use"]              = "content";
+      object_set["of"]               = "para";
+      object_set["is"]               = is_a;
+      // object_set["status"]        = status;
+      object_set["obj"]              = object;
+      object_set["obj_cite_number"]  = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+      object_set["indent_first"]     = indent["first"];
+      object_set["indent_second"]    = indent["second"];
+      object_set["bullet"]           = to!string(bullet);
+      object_set["attrib"]           = attrib;
       return object_set;
     }
     string[string] contents_block(
       in string type,
       in string object,
       in string attrib,
-      in int ocn
+      in int obj_cite_number
     ) {
       string[string] object_set;
-      object_set["use"]           = "content";
-      object_set["of"]            = "block";
-      object_set["is"]            = type;
-      object_set["obj"]           = object;
-      object_set["ocn"]           = (ocn==0) ? "" : to!string(ocn);
-      object_set["attrib"]        = attrib;
-      return object_set;
-    }
-    ObjComposite contents_block_ocn_string_new(
-      in string type,
-      in string object,
-      in string ocn,
-      in string node
-    ) {
-      ObjComposite object_set;
-      object_set.use                 = "content";
-      object_set.of                  = "block";
-      object_set.is_a                = type;
-      object_set.object              = object;
-      object_set.ocn                 = ocn;
-      object_set.block_ocn_string.node  = node;
-      // object_set.attrib              = attrib;
+      object_set["use"]             = "content";
+      object_set["of"]              = "block";
+      object_set["is"]              = type;
+      object_set["obj"]             = object;
+      object_set["obj_cite_number"] = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+      object_set["attrib"]          = attrib;
       return object_set;
     }
-    string[string] contents_block_ocn_string(
+    string[string] contents_block_obj_cite_number_string(
       in string type,
       in string object,
-      in string ocn,
+      in string obj_cite_number,
       in string node
     ) {
       string[string] object_set;
-      object_set["use"]           = "content";
-      object_set["of"]            = "block";
-      object_set["is"]            = type;
-      object_set["obj"]           = object;
-      object_set["ocn"]           = ocn;
-      object_set["node"]          = node;
+      object_set["use"]             = "content";
+      object_set["of"]              = "block";
+      object_set["is"]              = type;
+      object_set["obj"]             = object;
+      object_set["obj_cite_number"] = obj_cite_number;
+      object_set["node"]            = node;
+      // object_set["attrib"]       = "";
       return object_set;
     }
   }
diff --git a/lib/sdp/ao_output_debugs.d b/lib/sdp/ao_output_debugs.d
index d2c2c73..020474e 100644
--- a/lib/sdp/ao_output_debugs.d
+++ b/lib/sdp/ao_output_debugs.d
@@ -11,7 +11,7 @@ template SiSUoutputDebugs() {
       string[][string][string] bookindex_unordered_hashes,
       JSONValue[] biblio,
       string fn_src,
-      string[string] actions
+      bool[string] opt_action_bool
     ) {
       mixin RgxInit;
       mixin ScreenTxtColors;
@@ -28,10 +28,10 @@ template SiSUoutputDebugs() {
               writefln(
                 "%s%s node: %s heading: %s %s",
                 scr_txt_marker["cyan"],
-                obj["ocn"],
-                " node: ", obj["node"],
-                " heading: ", obj["lvn"],
-                " ", obj["obj"],
+                obj["obj_cite_number"],
+                obj["node"],
+                obj["lev_markup_number"],
+                obj["obj"],
               );
             } else {
             }
@@ -49,7 +49,7 @@ template SiSUoutputDebugs() {
           if (obj["use"] == "content") {
             writefln(
               "[%s][%s]\n%s",
-              obj["ocn"],
+              obj["obj_cite_number"],
               obj["is"],
               obj["obj"]
             );
@@ -68,7 +68,7 @@ template SiSUoutputDebugs() {
             writefln(
               "%s* [%s][%s] %s%s",
               scr_txt_color["green"],
-              obj["ocn"],
+              obj["obj_cite_number"],
               obj["is"],
               scr_txt_color["off"],
               obj["obj"]
@@ -236,13 +236,13 @@ template SiSUoutputDebugs() {
       }
       debug(summary) {
         string[string] check = [
-          "last_ocn" : "NA [debug \"checkdoc\" not run]",
+          "last_obj_cite_number" : "NA [debug \"checkdoc\" not run]",
         ];
         debug(checkdoc) {
           foreach (obj; contents) {
             if (obj["use"] == "content") {
-              if (!empty(obj["ocn"])) {
-                check["last_ocn"] = obj["ocn"];
+              if (!empty(obj["obj_cite_number"])) {
+                check["last_obj_cite_number"] = obj["obj_cite_number"];
               }
             }
           }
@@ -260,7 +260,7 @@ template SiSUoutputDebugs() {
                 "%s%s~ [%s] %s",
                 scr_txt_marker["yellow"],
                 obj["lev"],
-                obj["ocn"],
+                obj["obj_cite_number"],
                 // "[", obj["is"], "] ",
                 obj["obj"]
               );
@@ -275,8 +275,8 @@ template SiSUoutputDebugs() {
           fn_src,
           "length contents array: ",
           contents.length,
-          "last ocn: ",
-          check["last_ocn"],
+          "last obj_cite_number: ",
+          check["last_obj_cite_number"],
           "length bookindex: ",
           bookindex_unordered_hashes.length,
           __FILE__,
@@ -284,119 +284,119 @@ template SiSUoutputDebugs() {
         );
         debug(checkdoc) {
           if (auto mfn=match(fn_src, rgx.src_fn)) {
-            if (actions["assert"] == "yes") {
+            if (opt_action_bool["assertions"]) {
               switch (mfn.captures[2]) {
               case "live-manual.ssm":
-                assert(check["last_ocn"] ==
-                  "1019","last ocn should be: 1019 (check test, document is frequently updated)"); // ok
+                assert(check["last_obj_cite_number"] ==
+                  "1019","last obj_cite_number should be: 1019 (check test, document is frequently updated)"); // ok
                 break;
               case "sisu_markup.sst":
-                assert(check["last_ocn"] ==
-                  "297","last ocn should be: 297"); // ok
-                // assert(check["last_ocn"] == "297","last ocn should be: 297");
+                assert(check["last_obj_cite_number"] ==
+                  "297","last obj_cite_number expected to be: 297 rather than " ~ check["last_obj_cite_number"]); // ok
+                // assert(check["last_obj_cite_number"] == "297","last obj_cite_number expected to be: 297 rather than " ~ check["last_obj_cite_number"]);
                 // notes for first divergance study sisu headings 247 250
-                // sisu has issue with code that contains heading 1~ which results in no ocn! ??
-                // sisu currently has incorrect last body ocn of 294!
+                // sisu has issue with code that contains heading 1~ which results in no obj_cite_number! ??
+                // sisu currently has incorrect last body obj_cite_number of 294!
                 // bug in sisu? attend
                 break;
               // sisu-markup-samples:
               case "accelerando.charles_stross.sst":
-                assert(check["last_ocn"] ==
-                  "2861","last ocn should be: 2861"); // ok
+                assert(check["last_obj_cite_number"] ==
+                  "2861","last obj_cite_number expected to be: 2861 rather than " ~ check["last_obj_cite_number"]); // ok
                 break;
               case "alices_adventures_in_wonderland.lewis_carroll.sst":
-                assert(check["last_ocn"] ==
-                  "805","last ocn should be: 805"); // 808
+                assert(check["last_obj_cite_number"] ==
+                  "805","last obj_cite_number expected to be: 805 rather than " ~ check["last_obj_cite_number"]); // 808
                 break;
               case "autonomy_markup0.sst":
-                assert(check["last_ocn"] ==
-                  "77","last ocn should be: 77"); // ok endnotes
-                // assert(check["last_ocn"] == "78","last ocn should be: 78");
+                assert(check["last_obj_cite_number"] ==
+                  "77","last obj_cite_number expected to be: 77 rather than " ~ check["last_obj_cite_number"]); // ok endnotes
+                // assert(check["last_obj_cite_number"] == "78","last obj_cite_number expected to be: 78 rather than " ~ check["last_obj_cite_number"]);
                 break;
               case "content.cory_doctorow.sst":
-                assert(check["last_ocn"] ==
-                  "953","last ocn should be: 953"); // 1007 way off, check ocn off switches
-                // assert(check["last_ocn"] == "953","last ocn should be: 953");
+                assert(check["last_obj_cite_number"] ==
+                  "953","last obj_cite_number expected to be: 953 rather than " ~ check["last_obj_cite_number"]); // 1007 way off, check obj_cite_number off switches
+                // assert(check["last_obj_cite_number"] == "953","last obj_cite_number expected to be: 953 rather than " ~ check["last_obj_cite_number"]);
                 break;
               case "democratizing_innovation.eric_von_hippel.sst":
                 // fixed ERROR! range violation, broken check! endnotes, bookindex, biblio
                 // error in bookindex ... (ch1; ch6; ch8 )
-                assert(check["last_ocn"] ==
-                  "905","last ocn should be: 905"); // 911
+                assert(check["last_obj_cite_number"] ==
+                  "905","last obj_cite_number expected to be: 905 rather than " ~ check["last_obj_cite_number"]); // 911
                 break;
               case "down_and_out_in_the_magic_kingdom.cory_doctorow.sst":
-                assert(check["last_ocn"] ==
-                  "1417","last ocn should be: 1417"); // 1455 check ocn off switches
+                assert(check["last_obj_cite_number"] ==
+                  "1417","last obj_cite_number expected to be: 1417 rather than " ~ check["last_obj_cite_number"]); // 1455 check obj_cite_number off switches
                 break;
               case "for_the_win.cory_doctorow.sst":
-                assert(check["last_ocn"] ==
-                  "3510","last ocn should be: 3510"); // 3569 check ocn off switches
+                assert(check["last_obj_cite_number"] ==
+                  "3510","last obj_cite_number expected to be: 3510 rather than " ~ check["last_obj_cite_number"]); // 3569 check obj_cite_number off switches
                 break;
               case "free_as_in_freedom_2.richard_stallman_and_the_free_software_revolution.sam_williams.richard_stallman.sst":
-                assert(check["last_ocn"] ==
-                  "1082","last ocn should be: 1082"); // check 1079 too few
+                assert(check["last_obj_cite_number"] ==
+                  "1082","last obj_cite_number expected to be: 1082 rather than " ~ check["last_obj_cite_number"]); // check 1079 too few
                 break;
               case "free_culture.lawrence_lessig.sst":
-                assert(check["last_ocn"] ==
-                  "1330","last ocn should be: 1330"); // 1312
+                assert(check["last_obj_cite_number"] ==
+                  "1330","last obj_cite_number expected to be: 1330 rather than " ~ check["last_obj_cite_number"]); // 1312
                 // fixed ERROR! range violation, broken check!
                 // error in bookindex ... sections piracy (ch1) & property (ch10 market concentration) fixed
                 break;
               case "free_for_all.peter_wayner.sst": // endnotes, bookindex, biblio
-                assert(check["last_ocn"] ==
-                  "1559","last ocn should be: 1559"); // 1560, check ocn off switches, has endnotes so 2 too many
-                // assert(check["last_ocn"] == "1559","last ocn should be: 1559");
+                assert(check["last_obj_cite_number"] ==
+                  "1559","last obj_cite_number expected to be: 1559 rather than " ~ check["last_obj_cite_number"]); // 1560, check obj_cite_number off switches, has endnotes so 2 too many
+                // assert(check["last_obj_cite_number"] == "1559","last obj_cite_number expected to be: 1559 rather than " ~ check["last_obj_cite_number"]);
                 break;
               case "gpl2.fsf.sst":
-                assert(check["last_ocn"] ==
-                  "65","last ocn should be: 65"); // ok endnotes? check
-                // assert(check["last_ocn"] == "66","last ocn should be: 66");
+                assert(check["last_obj_cite_number"] ==
+                  "65","last obj_cite_number expected to be: 65 rather than " ~ check["last_obj_cite_number"]); // ok endnotes? check
+                // assert(check["last_obj_cite_number"] == "66","last obj_cite_number expected to be: 66 rather than " ~ check["last_obj_cite_number"]);
                 break;
               case "gpl3.fsf.sst":
-                assert(check["last_ocn"] ==
-                  "123","last ocn should be: 123"); // ok
+                assert(check["last_obj_cite_number"] ==
+                  "123","last obj_cite_number expected to be: 123 rather than " ~ check["last_obj_cite_number"]); // ok
                 break;
               case "gullivers_travels.jonathan_swift.sst":
-                assert(check["last_ocn"] ==
-                  "668","last ocn should be: 668"); // 674
+                assert(check["last_obj_cite_number"] ==
+                  "668","last obj_cite_number expected to be: 668 rather than " ~ check["last_obj_cite_number"]); // 674
                 break;
               case "little_brother.cory_doctorow.sst":
-                assert(check["last_ocn"] ==
-                  "3130","last ocn should be: 3130"); // 3204, check ocn off switches
+                assert(check["last_obj_cite_number"] ==
+                  "3130","last obj_cite_number expected to be: 3130 rather than " ~ check["last_obj_cite_number"]); // 3204, check obj_cite_number off switches
                 break;
               case "the_cathedral_and_the_bazaar.eric_s_raymond.sst":
-                assert(check["last_ocn"] ==
-                  "258","last ocn should be: 258"); // ok
+                assert(check["last_obj_cite_number"] ==
+                  "258","last obj_cite_number expected to be: 258 rather than " ~ check["last_obj_cite_number"]); // ok
                 break;
               case "the_public_domain.james_boyle.sst":
-                assert(check["last_ocn"] ==
-                  "970","last ocn should be: 970"); // 978
+                assert(check["last_obj_cite_number"] ==
+                  "970","last obj_cite_number expected to be: 970 rather than " ~ check["last_obj_cite_number"]); // 978
                 break;
               case "the_wealth_of_networks.yochai_benkler.sst": // endnotes, bookindex
-                assert(check["last_ocn"] ==
-                  "829","last ocn should be: 829"); // ok
-                // assert(check["last_ocn"] == "832","last ocn should be: 832");
+                assert(check["last_obj_cite_number"] ==
+                  "829","last obj_cite_number expected to be: 829 rather than " ~ check["last_obj_cite_number"]); // ok
+                // assert(check["last_obj_cite_number"] == "832","last obj_cite_number expected to be: 832 rather than " ~ check["last_obj_cite_number"]);
                 // has endnotes and bookindex, issue with sisu.rb
                 break;
               case "through_the_looking_glass.lewis_carroll.sst":
-                assert(check["last_ocn"] ==
-                  "949","last ocn should be: 949"); // 955
+                assert(check["last_obj_cite_number"] ==
+                  "949","last obj_cite_number expected to be: 949 rather than " ~ check["last_obj_cite_number"]); // 955
                 break;
               case "two_bits.christopher_kelty.sst": // endnotes, bookindex, biblio
-                assert(check["last_ocn"] ==
-                  "1190","last ocn should be: 1190"); // 1191
-                // assert(check["last_ocn"] == "1193","last ocn should be: 1193"); // 1191 ok?
+                assert(check["last_obj_cite_number"] ==
+                  "1190","last obj_cite_number expected to be: 1190 rather than " ~ check["last_obj_cite_number"]); // 1191
+                // assert(check["last_obj_cite_number"] == "1193","last obj_cite_number expected to be: 1193 rather than " ~ check["last_obj_cite_number"]); // 1191 ok?
                 // has endnotes and bookindex, issue with sisu.rb
                 break;
                 // fixed ERROR! range violation!
                 // error in bookindex ... (ch3 the movement)
               case "un_contracts_international_sale_of_goods_convention_1980.sst":
-                assert(check["last_ocn"] ==
-                  "377","last ocn should be: 377"); // ok
+                assert(check["last_obj_cite_number"] ==
+                  "377","last obj_cite_number expected to be: 377 rather than " ~ check["last_obj_cite_number"]); // ok
                 break;
               case "viral_spiral.david_bollier.sst": // endnotes, bookindex
-                assert(check["last_ocn"] ==
-                  "1078","last ocn should be: 1078"); // 1100
+                assert(check["last_obj_cite_number"] ==
+                  "1078","last obj_cite_number expected to be: 1078 rather than " ~ check["last_obj_cite_number"]); // 1100
                 // fixed ERROR! range violation!
                 // error in bookindex ... (ch7 ... building the cc machine, an extra semi colon)
                 break;
diff --git a/lib/sdp/ao_read_markup_source.d b/lib/sdp/ao_read_markup_source.d
deleted file mode 100644
index 6eaecbe..0000000
--- a/lib/sdp/ao_read_markup_source.d
+++ /dev/null
@@ -1,55 +0,0 @@
-/+
-  read markup source
-  ao_read_markup_source.d
-+/
-mixin template SiSUmarkupRaw() {
-  struct MarkupRaw {
-    auto rgx = Rgx();
-    final private string markupSourceString(in char[] fn_src) {
-      enforce(
-        exists(fn_src)!=0,
-        "file not found"
-      );
-      string source_txt_str;
-      try {
-        if (exists(fn_src)) {
-          source_txt_str = readText(fn_src); // ok
-        }
-      }
-      catch (ErrnoException ex) {
-        // Handle errors
-      }
-      catch (UTFException ex) {
-        // Handle validation errors
-      }
-      catch (FileException ex) {
-        // Handle errors
-      }
-      std.utf.validate(source_txt_str);
-      return source_txt_str;
-    }
-    final private char[][] markupSourceLineArray(in string src_text) {
-      char[][] source_line_arr =
-        split(cast(char[]) src_text, rgx.line_delimiter);
-      return source_line_arr;
-    }
-    final char[][] markupInsertSourceContentRawLineArray(in char[] fn_src) {
-      enforce(
-        match(fn_src, rgx.src_fn_find_inserts),
-        "not a sisu markup filename"
-      );
-      auto source_txt_str = markupSourceString(fn_src);
-      auto source_line_arr = markupSourceLineArray(source_txt_str);
-      return source_line_arr;
-    }
-    final char[][] markupSourceContentRawLineArray(in char[] fn_src) {
-      enforce(
-        match(fn_src, rgx.src_pth),
-        "not a sisu markup filename"
-      );
-      auto source_txt_str = markupSourceString(fn_src);
-      auto source_line_arr = markupSourceLineArray(source_txt_str);
-      return source_line_arr;
-    }
-  }
-}
diff --git a/lib/sdp/ao_read_source_files.d b/lib/sdp/ao_read_source_files.d
new file mode 100644
index 0000000..a5ca084
--- /dev/null
+++ b/lib/sdp/ao_read_source_files.d
@@ -0,0 +1,281 @@
+/+
+  ao_read_source_files.d
+  - open markup files
+  - if master file scan for addional files to import/insert
++/
+// module ao_read_source_files;
+template SiSUmarkupRaw() {
+  private import
+    std.exception,
+    std.regex,
+    std.stdio,
+    std.utf,
+    std.conv : to;
+  private import
+    ao_rgx;       // ao_defaults.d
+  mixin RgxInit;
+  auto rgx = Rgx();
+  struct MarkupRaw {
+    final char[][] sourceContent(in string fn_src) {
+      auto raw = MarkupRawUnit();
+      auto sourcefile_content =
+        raw.markupSourceContentRawLineArray(fn_src, rgx.src_pth);
+      if (match(fn_src, rgx.src_fn_master)) {
+        auto ins = Inserts();
+        sourcefile_content =
+          ins.scan_master_doc_source_for_insert_filenames(sourcefile_content, fn_src);
+        // auto ins = SiSUdocInserts.Inserts();
+      }
+      return sourcefile_content;
+    }
+  }
+  private
+  struct MarkupRawUnit {
+    private import std.file;
+    final private string readInMarkupSource(in string fn_src) {
+      enforce(
+        exists(fn_src)!=0,
+        "file not found"
+      );
+      string source_txt_str;
+      try {
+        if (exists(fn_src)) {
+          source_txt_str = readText(fn_src);
+        }
+      }
+      catch (ErrnoException ex) {
+      //// Handle errors
+      // switch(ex.errno) {
+      // case EPERM:
+      // case EACCES:
+      //   // Permission denied
+      //   break;
+      // case ENOENT:
+      //   // File does not exist
+      //   break;
+      // default:
+      //   // Handle other errors
+      //   break;
+      // }
+      }
+      catch (UTFException ex) {
+        // Handle validation errors
+      }
+      catch (FileException ex) {
+        // Handle errors
+      }
+      std.utf.validate(source_txt_str);
+      return source_txt_str;
+    }
+    final private char[][] markupSourceLineArray(in string src_text) {
+      char[][] source_line_arr =
+        split(cast(char[]) src_text, rgx.line_delimiter);
+      return source_line_arr;
+    }
+    final char[][] markupSourceContentRawLineArray(in string fn_src, Regex!(char) rgx_file ) {
+      enforce(
+        match(fn_src, rgx_file),
+        "not a sisu markup filename"
+      );
+      auto source_txt_str = readInMarkupSource(fn_src);
+      auto source_line_arr = markupSourceLineArray(source_txt_str);
+      return source_line_arr;
+    }
+  }
+  struct Inserts {
+    private import ao_defaults;    // ao_defaults.d
+    private import ao_ansi_colors; // ao_ansi_colors.d
+    auto scan_subdoc_source(
+      char[][] markup_sourcefile_insert_content,
+      string fn_src
+    ) {
+      mixin SiSUrgxInitFlags;
+      char[][] contents_insert;
+      auto type1 = flags_type_init;
+      mixin ScreenTxtColors;
+      int tell_l(string color, in char[] line) {
+        writeln(scr_txt_marker[color], line);
+        return 0;
+      }
+      auto fn_pth_full = match(fn_src, rgx.src_pth);
+      auto markup_src_file_path = fn_pth_full.captures[1];
+      foreach (line; markup_sourcefile_insert_content) {
+        if (type1["curly_code"] == 1) {
+          type1["header_make"] = 0;
+          type1["header_metadata"] = 0;
+          if (auto m = match(line, rgx.block_curly_code_close)) {
+            type1["curly_code"] = 0;
+          }
+          contents_insert ~= line;
+        } else if (auto m = match(line, rgx.block_curly_code_open)) {
+          type1["curly_code"] = 1;
+          type1["header_make"] = 0;
+          type1["header_metadata"] = 0;
+          contents_insert ~= line;
+        } else if (type1["tic_code"] == 1) {
+          type1["header_make"] = 0;
+          type1["header_metadata"] = 0;
+          if (auto m = match(line, rgx.block_tic_close)) {
+            type1["tic_code"] = 0;
+          }
+          contents_insert ~= line;
+        } else if (auto m = match(line, rgx.block_tic_code_open)) {
+          type1["tic_code"] = 1;
+          type1["header_make"] = 0;
+          type1["header_metadata"] = 0;
+          contents_insert ~= line;
+        } else if (
+          (type1["header_make"] == 1)
+          && match(line, rgx.header_sub)
+        ) {
+            type1["header_make"] = 1;
+            type1["header_metadata"] = 0;
+            // cont_dynamic_array ~= "% " ~ line;
+        } else if (
+          (type1["header_metadata"] == 1)
+          && match(line, rgx.header_sub)
+        ) {
+            type1["header_metadata"] = 1;
+            type1["header_make"] = 0;
+            // cont_dynamic_array ~= "% " ~ line;
+        } else if (auto m = match(line, rgx.insert_src_fn_ssi_or_sst)) {
+          type1["header_make"] = 0;
+          type1["header_metadata"] = 0;
+          auto insert_fn = m.captures[2];
+          auto insert_sub_pth = m.captures[1];
+          auto fn_src_insert =
+            to!string(markup_src_file_path ~ insert_sub_pth ~ insert_fn);
+          auto raw = MarkupRawUnit();
+          auto markup_sourcesubfile_insert_content =
+            raw.markupSourceContentRawLineArray(fn_src_insert, rgx.src_fn_find_inserts);
+          debug(insert) {                              // insert file
+            tell_l("red", line);
+            tell_l("red", fn_src_insert);
+            tell_l("fuchsia", "ERROR");
+            writeln(
+              "  length contents insert array: ",
+              markup_sourcesubfile_insert_content.length
+            );
+          }
+          auto ins = Inserts();
+          /+
+            1. load file,
+            2. read lines;
+            3. scan lines,
+            4. if filename insert, and insert filename
+            5.   repeat 1
+            6. else
+            7.   add line to new array;
+          +/
+        } else {
+          type1["header_make"] = 0;
+          type1["header_metadata"] = 0;
+          contents_insert ~= line;
+        }
+      } // end src subdoc (inserts) loop
+      return contents_insert;
+    }
+    auto scan_master_doc_source_for_insert_filenames(
+      char[][] sourcefile_content,
+      string fn_src
+    ) {
+      mixin SiSUrgxInitFlags;
+      char[][] contents;
+      auto type = flags_type_init;
+      mixin ScreenTxtColors;
+      int tell_l(string color, in char[] line) {
+        writeln(scr_txt_marker[color], line);
+        return 0;
+      }
+      auto fn_pth_full = match(fn_src, rgx.src_pth);
+      auto markup_src_file_path = fn_pth_full.captures[1];
+      foreach (line; sourcefile_content) {
+        if (type["curly_code"] == 1) {
+          type["header_make"] = 0;
+          type["header_metadata"] = 0;
+          if (auto m = match(line, rgx.block_curly_code_close)) {
+            type["curly_code"] = 0;
+          }
+          contents ~= line;
+        } else if (auto m = match(line, rgx.block_curly_code_open)) {
+          type["curly_code"] = 1;
+          type["header_make"] = 0;
+          type["header_metadata"] = 0;
+          contents ~= line;
+        } else if (type["tic_code"] == 1) {
+          type["header_make"] = 0;
+          type["header_metadata"] = 0;
+          if (auto m = match(line, rgx.block_tic_close)) {
+            type["tic_code"] = 0;
+          }
+          contents ~= line;
+        } else if (auto m = match(line, rgx.block_tic_code_open)) {
+          type["tic_code"] = 1;
+          type["header_make"] = 0;
+          type["header_metadata"] = 0;
+          contents ~= line;
+        } else if (
+          (type["header_make"] == 1)
+          && match(line, rgx.header_sub)
+        ) {
+          contents ~= line;
+        } else if (
+          (type["header_metadata"] == 1)
+          && match(line, rgx.header_sub)
+        ) {
+          contents ~= line;
+        } else if (auto m = match(line, rgx.header_make)) {
+          type["header_make"] = 1;
+          type["header_metadata"] = 0;
+          contents ~= line;
+        } else if (auto m = match(line, rgx.header_metadata)) {
+          type["header_make"] = 0;
+          type["header_metadata"] = 1;
+          contents ~= line;
+        } else if (auto m = match(line, rgx.insert_src_fn_ssi_or_sst)) {
+          type["header_make"] = 0;
+          type["header_metadata"] = 0;
+          auto insert_fn = m.captures[2];
+          auto insert_sub_pth = m.captures[1];
+          auto fn_src_insert =
+            to!string(markup_src_file_path ~ insert_sub_pth ~ insert_fn);
+          auto raw = MarkupRawUnit();
+          auto markup_sourcefile_insert_content =
+            raw.markupSourceContentRawLineArray(fn_src_insert, rgx.src_fn_find_inserts);
+          debug(insert) {                              // insert file
+            tell_l("red", line);
+            tell_l("red", fn_src_insert);
+            writeln(
+              "  length contents insert array: ",
+              markup_sourcefile_insert_content.length
+            );
+          }
+          auto ins = Inserts();
+          auto contents_insert = ins.scan_subdoc_source(
+            markup_sourcefile_insert_content,
+            to!string(fn_src_insert)
+          );
+          contents ~= contents_insert;
+          /+
+            1. load file,
+            2. read lines;
+            3. scan lines,
+            4. if filename insert, and insert filename
+            5.   repeat 1
+            6. else
+            7.   add line to new array;
+          +/
+        } else {
+          type["header_make"] = 0;
+          type["header_metadata"] = 0;
+          contents ~= line;
+        }
+      } // end src doc loop
+      debug(insert) {                              // insert file
+        writeln(__LINE__);
+        writeln(contents.length);
+      }
+      return contents;
+    }
+  }
+}
diff --git a/lib/sdp/ao_rgx.d b/lib/sdp/ao_rgx.d
index 4c36ff9..e675ca1 100644
--- a/lib/sdp/ao_rgx.d
+++ b/lib/sdp/ao_rgx.d
@@ -2,7 +2,7 @@
   regex
   ao_rgx.d
 +/
-mixin template RgxInit() {
+template RgxInit() {
   struct Rgx {
     /+ misc +/
     static flag_action               = ctRegex!(`^(--[a-z][a-z0-9-]+)$`);
@@ -11,11 +11,14 @@ mixin template RgxInit() {
     static src_fn                    = ctRegex!(`^([a-zA-Z0-9._-]+/)*([a-zA-Z0-9._-]+[.]ss[tm])$`);
     static src_fn_master             = ctRegex!(`^([a-zA-Z0-9._-]+/)*([a-zA-Z0-9._-]+[.]ssm)$`);
     static src_fn_find_inserts       = ctRegex!(`^([a-zA-Z0-9._-]+/)*([a-zA-Z0-9._-]+[.]ss[im])$`);
+    // static ssm_fn                    = ctRegex!(`^[a-zA-Z0-9._-]+[.]ssm$`);
     static line_delimiter            = ctRegex!("\n");
+    // static arr_delimiter             = ctRegex!(`\s*[;]\s*`);
     static within_quotes             = ctRegex!(`"(.+?)"`);
     static make_heading_delimiter    = ctRegex!(`[;][ ]*`);
     static arr_delimiter             = ctRegex!(`[ ]*[;][ ]*`);
     static name_delimiter            = ctRegex!(`^([^,]+)[ ]*,[ ]+(.+?)$`);
+    // static name_delimiter            = ctRegex!(`^(.+?)[ ]*,[ ]*(.+?)$`);
     static book_index_go             = ctRegex!("([0-9]+)(?:-[0-9]+)?");
     static trailing_comma            = ctRegex!(",[ ]*$");
     static trailing_linebreak        = ctRegex!(",[ ]{1,2}\\\\\\\\\n[ ]{4}$","m");
@@ -26,6 +29,7 @@ mixin template RgxInit() {
     static levels_numbered           = ctRegex!(`^[0-9]$`);
     static levels_numbered_headings  = ctRegex!(`^[0-7]$`);
     /+ insert markup file +/
+    // static insert_src_fn_ssi_or_sst  = ctRegex!(`^<<\s*([a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`);
     static insert_src_fn_ssi_or_sst  = ctRegex!(`^<<\s*(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`);
     // static insert_ssi_or_sst_fn      = ctRegex!(`^<<\s*[a-zA-Z0-9._-]+[.]ss[ti]`);
     /+ comments +/
@@ -49,7 +53,13 @@ mixin template RgxInit() {
     static para_indent        = ctRegex!(`^_([1-9]) `);
     static para_indent_hang   = ctRegex!(`^_([0-9])_([0-9]) `);
     static para_attribs       = ctRegex!(`^_(([0-9])(_([0-9]))?|_([1-9])?[*]) `);
+    /+ blocked markup +/
+    static block_open                = ctRegex!("^((code|poem|group|block|quote|table)[{].*?$)|^`{3} (code|poem|group|block|quote|table)");
+    // static block_open_less_code      = ctRegex!("^(((poem|group|block|quote|table)[{].*?$)|`{3} (poem|group|block|quote|table))");
+    static block_poem_open                = ctRegex!("^((poem[{].*?$)|`{3} poem)");
     /+ blocked markup tics +/
+    static block_tic_open            = ctRegex!("^`{3} (code|poem|group|block|quote|table)");
+    // static block_tic_open_less_code  = ctRegex!("^`{3} (poem|group|block|quote|table)");
     static block_tic_code_open       = ctRegex!("^`{3} (code)");
     static block_tic_poem_open       = ctRegex!("^`{3} (poem)");
     static block_tic_group_open      = ctRegex!("^`{3} (group)");
@@ -58,6 +68,8 @@ mixin template RgxInit() {
     static block_tic_table_open      = ctRegex!("^`{3} (table)");
     static block_tic_close           = ctRegex!("^(`{3})$","m");
     /+ blocked markup curly +/
+    static block_curly_open          = ctRegex!(`^((code|poem|group|block|quote|table)[{].*?$)`);
+    // static block_curly_open_less_code = ctRegex!(`^((poem|group|block|quote|table)[{].*?$)`);
     static block_curly_code_open     = ctRegex!(`^(code[{].*?$)`);
     static block_curly_code_close    = ctRegex!(`^([}]code)`);
     static block_curly_poem_open     = ctRegex!(`^(poem[{].*?$)`);
@@ -85,22 +97,33 @@ mixin template RgxInit() {
     static inline_notes_al_gen                   = ctRegex!(`【.+?】`, "m");
     static inline_notes_curly_gen                = ctRegex!(`~\{.+?\}~`, "m");
     static inline_notes_curly                    = ctRegex!(`~\{\s*(.+?)\}~`, "mg");
+    // static inline_notes_curly                    = ctRegex!(`~\{(?:[*+]\s+|\s*)(.+?)\}~`, "mg");
     static inline_al_delimiter_open_regular             = ctRegex!(`【`, "m");
     static inline_al_delimiter_close_regular            = ctRegex!(`】`, "m");
     static inline_al_delimiter_open_and_close_regular   = ctRegex!(`【|】`, "m");
     static inline_notes_delimiter_al_regular            = ctRegex!(`【(.+?)】`, "m");
     static inline_notes_delimiter_al_regular_number_note = ctRegex!(`【(\d+)\s+(.+?)】`, "m");
+    
     static inline_al_delimiter_open_asterisk         = ctRegex!(`【\*`, "m");
     static inline_al_delimiter_open_plus             = ctRegex!(`【\+`, "m");
+    
     static inline_curly_delimiter_open_regular             = ctRegex!(`~\{\s*`, "m");
     static inline_curly_delimiter_close_regular            = ctRegex!(`\s*\}~`, "m");
     static inline_curly_delimiter_open_and_close_regular   = ctRegex!(`~\{\s*|\s*\}~`, "m");
     static inline_notes_delimiter_curly_regular            = ctRegex!(`~\{[ ]*(.+?)\}~`, "m");
+    // static inline_notes_curly_regular            = ctRegex!(`(?:[~][{][ ]*)(.+?)(?:[}][~])`, "m");
+    // static inline_notes_curly_regular            = ctRegex!(`~\{\s*(.+?)\}~`, "m");
+    // static inline_notes_curly                    = ctRegex!(`~\{(?:[*+]\s+|\s*)(.+?)\}~`, "mg");
     static inline_notes_curly_sp                 = ctRegex!(`~\{[*+]+\s+(.+?)\}~`, "m");
     static inline_notes_curly_sp_asterisk        = ctRegex!(`~\{[*]+\s+(.+?)\}~`, "m");
     static inline_notes_curly_sp_plus            = ctRegex!(`~\{[+]+\s+(.+?)\}~`, "m");
+    // static inline_text_and_note_curly            = ctRegex!(`(.+?)~\{(?:[*+]\s+|\s*)(.+?)\}~`, "mg");
     static inline_text_and_note_al               = ctRegex!(`(?P<text>.+?)【(?:[*+ ]*)(?P<note>.+?)】`, "mg");
     static inline_text_and_note_curly            = ctRegex!(`(?P<text>.+?)(?:(?:[~])[{][*+ ]*)(?P<note>.+?)(?:[}][~])`, "mg");
+    // static inline_text_and_note_curly            = ctRegex!(`(?P<text>.+?)~\{(?:[*+]\s+|\s*)(?P<note>.+?)\}~`, "mg");
+    // static inline_text_and_note_curly_sp         = ctRegex!(`(.+?)~\{[*+]+\s+(.+?)\}~`, "mg");
+    // static inline_text_and_note_curly_sp_asterisk = ctRegex!(`(.+?)~\{[*]+\s+(.+?)\}~`, "mg");
+    // static inline_text_and_note_curly_sp_plus    = ctRegex!(`(.+?)~\{[+]+\s+(.+?)\}~`, "mg");
     static inline_note_curly_delimiters          = ctRegex!(`(~\{[*+]?\s*)(.+?)(\}~)`, "mg");
     static inline_notes_square                   = ctRegex!(`~\[\s*(.+?)\]~`, "mg");
     static inline_text_and_note_square_sp        = ctRegex!(`(.+?)~\[[*+]+\s+(.+?)\]~`, "mg");
@@ -110,16 +133,16 @@ mixin template RgxInit() {
     static book_index                = ctRegex!(`^=\{\s*(.+?)\}$`, "m");
     static book_index_open           = ctRegex!(`^=\{\s*([^}]+?)$`);
     static book_index_close          = ctRegex!(`^(.*?)\}$`, "m"); // strip
-    /+ no ocn object +/
-    static ocn_off                   = ctRegex!(`~#$`, "m");
-    static ocn_off_dh                = ctRegex!(`-#$`, "m");
-    static ocn_off_all               = ctRegex!(`[~-]#$`, "m");
-    /+ no ocn block +/
-    static ocn_off_block             = ctRegex!(`^--~#$`);
-    static ocn_off_block_dh          = ctRegex!(`^---#$`);
-    static ocn_off_block_close       = ctRegex!(`^--\+#$`);
-    // static auto_ocn_ignore           = ctRegex!(`^[+~*$-]{3,}$`); // reminder
-    static ocn_block_marks           = ctRegex!(`^--[+~-]#$`);
+    /+ no obj_cite_number object +/
+    static obj_cite_number_off                   = ctRegex!(`~#$`, "m");
+    static obj_cite_number_off_dh                = ctRegex!(`-#$`, "m");
+    static obj_cite_number_off_all               = ctRegex!(`[~-]#$`, "m");
+    /+ no obj_cite_number block +/
+    static obj_cite_number_off_block             = ctRegex!(`^--~#$`);
+    static obj_cite_number_off_block_dh          = ctRegex!(`^---#$`);
+    static obj_cite_number_off_block_close       = ctRegex!(`^--\+#$`);
+    // static auto_obj_cite_number_ignore           = ctRegex!(`^[+~*$-]{3,}$`); // reminder
+    static obj_cite_number_block_marks           = ctRegex!(`^--[+~-]#$`);
     /+ ignore outside code blocks +/
     static regular_parse_skip        = ctRegex!(`^(--[+~-]#|-[\\]{2}-|=[.\\]{2}=)$`); // not structural info
     /+ line & page breaks +/
@@ -148,10 +171,11 @@ mixin template RgxInit() {
     /+ biblio tags +/
     static biblio_tags               = ctRegex!(`^(is|au|author_raw|author|author_arr|editor_raw|ed|editor_arr|ti|title|subtitle|fulltitle|lng|language|trans|src|jo|journal|in|vol|volume|edn|edition|yr|year|pl|place|pb|pub|publisher|url|pg|pages|note|short_name|id):\s+(.+)`);
     static biblio_abbreviations      = ctRegex!(`^(au|ed|ti|lng|jo|vol|edn|yr|pl|pb|pub|pg|pgs|sn)$`);
+    // static biblio_tags               = ctRegex!(`^(is|author_raw|author|author_arr|editor_raw|editor_arr|title|subtitle|fulltitle|language|trans|src|journal|in|volume|edition|year|place|publisher|url|pages|note|short_name|id):\s+(.+)`);
     /+ bookindex split +/
     static bi_main_terms_split       = ctRegex!(`\s*;\s*`);
     static bi_main_term_plus_rest_split = ctRegex!(`\s*:\s*`);
-    static bi_sub_terms_plus_ocn_offset_split = ctRegex!(`\s*\|\s*`);
-    static bi_term_and_ocns_match    = ctRegex!(`^(.+?)\+(\d+)`);
+    static bi_sub_terms_plus_obj_cite_number_offset_split = ctRegex!(`\s*\|\s*`);
+    static bi_term_and_obj_cite_numbers_match    = ctRegex!(`^(.+?)\+(\d+)`);
   }
 }
diff --git a/lib/sdp/ao_scan_inserts.d b/lib/sdp/ao_scan_inserts.d
deleted file mode 100644
index f70b2e7..0000000
--- a/lib/sdp/ao_scan_inserts.d
+++ /dev/null
@@ -1,199 +0,0 @@
-/+
-  inserts
-  ao_inserts.d
-+/
-mixin template SiSUdocInserts() {
-  private:
-  struct Inserts {
-    auto scan_subdoc_source(
-      char[][] markup_sourcefile_insert_content,
-      string fn_src
-    ) {
-      char[][] contents_insert;
-      auto ft1 = flag_type.dup;
-      mixin ScreenTxtColors;
-      auto rgx = Rgx();
-      int tell_l(string color, in char[] line) {
-        writeln(scr_txt_marker[color], line);
-        return 0;
-      }
-      auto fn_pth_full = match(fn_src, rgx.src_pth);
-      auto markup_src_file_path = fn_pth_full.captures[1];
-      foreach (line; markup_sourcefile_insert_content) {
-        if (ft1["curly_code"] == 1) {
-          ft1["header_make"] = 0;
-          ft1["header_metadata"] = 0;
-          if (auto m = match(line, rgx.block_curly_code_close)) {
-            ft1["curly_code"] = 0;
-          }
-          contents_insert ~= line;
-        } else if (auto m = match(line, rgx.block_curly_code_open)) {
-          ft1["curly_code"] = 1;
-          ft1["header_make"] = 0;
-          ft1["header_metadata"] = 0;
-          contents_insert ~= line;
-        } else if (ft1["tic_code"] == 1) {
-          ft1["header_make"] = 0;
-          ft1["header_metadata"] = 0;
-          if (auto m = match(line, rgx.block_tic_close)) {
-            ft1["tic_code"] = 0;
-          }
-          contents_insert ~= line;
-        } else if (auto m = match(line, rgx.block_tic_code_open)) {
-          ft1["tic_code"] = 1;
-          ft1["header_make"] = 0;
-          ft1["header_metadata"] = 0;
-          contents_insert ~= line;
-        } else if (
-          (ft1["header_make"] == 1)
-          && match(line, rgx.header_sub)
-        ) {
-            ft1["header_make"] = 1;
-            ft1["header_metadata"] = 0;
-        } else if (
-          (ft1["header_metadata"] == 1)
-          && match(line, rgx.header_sub)
-        ) {
-            ft1["header_metadata"] = 1;
-            ft1["header_make"] = 0;
-        } else if (auto m = match(line, rgx.insert_src_fn_ssi_or_sst)) {
-          ft1["header_make"] = 0;
-          ft1["header_metadata"] = 0;
-          auto insert_fn = m.captures[2];
-          auto insert_sub_pth = m.captures[1];
-          auto fn_src_insert =
-            (markup_src_file_path ~ insert_sub_pth ~ insert_fn);
-          auto raw = MarkupRaw();
-          auto markup_sourcesubfile_insert_content =
-            raw.markupInsertSourceContentRawLineArray(fn_src_insert);
-          debug(insert) {                              // insert file
-            tell_l("red", line);
-            tell_l("red", fn_src_insert);
-            tell_l("fuchsia", "ERROR");
-            writeln(
-              "  length contents insert array: ",
-              markup_sourcesubfile_insert_content.length
-            );
-          }
-          auto ins = Inserts();
-          /+
-            1. load file,
-            2. read lines;
-            3. scan lines,
-            4. if filename insert, and insert filename
-            5.   repeat 1
-            6. else
-            7.   add line to new array;
-          +/
-        } else {
-          ft1["header_make"] = 0;
-          ft1["header_metadata"] = 0;
-          contents_insert ~= line;
-        }
-      } // end src subdoc (inserts) loop
-      return contents_insert;
-    }
-    auto scan_doc_source(
-      char[][] markup_sourcefile_content,
-      string fn_src
-    ) {
-      char[][] contents;
-      auto ft = flag_type.dup;
-      mixin ScreenTxtColors;
-      auto rgx = Rgx();
-      int tell_l(string color, in char[] line) {
-        writeln(scr_txt_marker[color], line);
-        return 0;
-      }
-      auto fn_pth_full = match(fn_src, rgx.src_pth);
-      auto markup_src_file_path = fn_pth_full.captures[1];
-      foreach (line; markup_sourcefile_content) {
-        if (ft["curly_code"] == 1) {
-          ft["header_make"] = 0;
-          ft["header_metadata"] = 0;
-          if (auto m = match(line, rgx.block_curly_code_close)) {
-            ft["curly_code"] = 0;
-          }
-          contents ~= line;
-        } else if (auto m = match(line, rgx.block_curly_code_open)) {
-          ft["curly_code"] = 1;
-          ft["header_make"] = 0;
-          ft["header_metadata"] = 0;
-          contents ~= line;
-        } else if (ft["tic_code"] == 1) {
-          ft["header_make"] = 0;
-          ft["header_metadata"] = 0;
-          if (auto m = match(line, rgx.block_tic_close)) {
-            ft["tic_code"] = 0;
-          }
-          contents ~= line;
-        } else if (auto m = match(line, rgx.block_tic_code_open)) {
-          ft["tic_code"] = 1;
-          ft["header_make"] = 0;
-          ft["header_metadata"] = 0;
-          contents ~= line;
-        } else if (
-          (ft["header_make"] == 1)
-          && match(line, rgx.header_sub)
-        ) {
-          contents ~= line;
-        } else if (
-          (ft["header_metadata"] == 1)
-          && match(line, rgx.header_sub)
-        ) {
-          contents ~= line;
-        } else if (auto m = match(line, rgx.header_make)) {
-          ft["header_make"] = 1;
-          ft["header_metadata"] = 0;
-          contents ~= line;
-        } else if (auto m = match(line, rgx.header_metadata)) {
-          ft["header_make"] = 0;
-          ft["header_metadata"] = 1;
-          contents ~= line;
-        } else if (auto m = match(line, rgx.insert_src_fn_ssi_or_sst)) {
-          ft["header_make"] = 0;
-          ft["header_metadata"] = 0;
-          auto insert_fn = m.captures[2];
-          auto insert_sub_pth = m.captures[1];
-          auto fn_src_insert =
-            (markup_src_file_path ~ insert_sub_pth ~ insert_fn);
-          auto raw = MarkupRaw();
-          auto markup_sourcefile_insert_content =
-            raw.markupInsertSourceContentRawLineArray(fn_src_insert);
-          debug(insert) {                              // insert file
-            tell_l("red", line);
-            tell_l("red", fn_src_insert);
-            writeln(
-              "  length contents insert array: ",
-              markup_sourcefile_insert_content.length
-            );
-          }
-          auto ins = Inserts();
-          auto contents_insert = ins.scan_subdoc_source(
-            markup_sourcefile_insert_content,
-            to!string(fn_src_insert)
-          );
-          contents ~= contents_insert;
-          /+
-            1. load file,
-            2. read lines;
-            3. scan lines,
-            4. if filename insert, and insert filename
-            5.   repeat 1
-            6. else
-            7.   add line to new array;
-          +/
-        } else {
-          ft["header_make"] = 0;
-          ft["header_metadata"] = 0;
-          contents ~= line;
-        }
-      } // end src doc loop
-      debug(insert) {                              // insert file
-        writeln(__LINE__);
-        writeln(contents.length);
-      }
-      return contents;
-    }
-  }
-}
diff --git a/lib/sdp/ao_structs.d b/lib/sdp/ao_structs.d
deleted file mode 100644
index 0aeb235..0000000
--- a/lib/sdp/ao_structs.d
+++ /dev/null
@@ -1,43 +0,0 @@
-/+
-  structs
-  ao_structs.d
-+/
-/+ structs +/
-
-mixin template Structs() {
-  struct ObjHeading {
-    string type;
-    string lev;
-    string lvn;
-    string lcn;
-  }
-  struct ObjPara {
-    string indent_first;
-    string indent_second;
-    string bullet;
-  }
-  struct ObjComment {
-    // does not have .attrib;
-    // does not have .ocn
-  }
-  struct ObjBlock {
-  }
-  struct ObjBlockOcnString {
-    // does not have .attrib;
-    string node;
-  }
-  struct ObjComposite {
-    // size_t id;
-    string use;
-    string of;
-    string is_a;
-    string object;
-    string ocn;
-    string attrib;
-    // int ocn;
-    ObjHeading heading;
-    ObjPara para;
-    ObjBlock block;
-    ObjBlockOcnString block_ocn_string;
-  }
-}
diff --git a/lib/sdp/ao_utils.d b/lib/sdp/ao_utils.d
deleted file mode 100644
index e5245dd..0000000
--- a/lib/sdp/ao_utils.d
+++ /dev/null
@@ -1,74 +0,0 @@
-/+
-  utils
-  ao_util.d
-+/
-mixin template ScreenTxtColors() {
-  string[string] scr_txt_color = [
-    "off"           : "\033[0m",
-    "white"         : "\033[37m",
-    "white_bold"    : "\033[1m",
-    "marker"        : "\033[42m",
-    "bold"          : "\033[1m",
-    "underline"     : "\033[4m",
-    "invert"        : "\033[7m",
-    "darkgrey_hi"   : "\033[100m",
-    "grey_hi"       : "\033[47m",
-    "pink_hi"       : "\033[105m",
-    "fuchsia_hi"    : "\033[45m",
-    "red_hi"        : "\033[41m",
-    "orange_hi"     : "\033[101m",
-    "yellow_hi"     : "\033[103m",
-    "brown_hi"      : "\033[43m",
-    "lightgreen_hi" : "\033[102m",
-    "green_hi"      : "\033[42m",
-    "cyan_hi"       : "\033[106m",
-    "blue_hi"       : "\033[104m",
-    "navy_hi"       : "\033[44m",
-    "grey"          : "\033[90m",
-    "pink"          : "\033[95m",
-    "fuchsia"       : "\033[35m",
-    "ruby"          : "\033[31m",
-    "red"           : "\033[91m",
-    "orange"        : "\033[91m",
-    "yellow"        : "\033[93m",
-    "brown"         : "\033[33m",
-    "green"         : "\033[92m",
-    "darkgreen"     : "\033[32m",
-    "cyan"          : "\033[36m",
-    "blue"          : "\033[94m",
-    "navy"          : "\033[34m",
-    "black"         : "\033[30m"
-  ];
-  string[string] scr_txt_marker = [
-    "white"         : "\033[37m*\033[0m ",
-    "bold"          : "\033[1m*\033[0m ",
-    "invert"        : "\033[7m*\033[0m ",
-    "darkgrey_hi"   : "\033[100m*\033[0m ",
-    "grey_hi"       : "\033[47m*\033[0m ",
-    "pink_hi"       : "\033[105m*\033[0m ",
-    "fuchsia_hi"    : "\033[45m*\033[0m ",
-    "red_hi"        : "\033[41m*\033[0m ",
-    "orange_hi"     : "\033[101m*\033[0m ",
-    "yellow_hi"     : "\033[103m*\033[0m ",
-    "brown_hi"      : "\033[43m*\033[0m ",
-    "lightgreen_hi" : "\033[102m*\033[0m ",
-    "green_hi"      : "\033[42m*\033[0m ",
-    "cyan_hi"       : "\033[106m*\033[0m ",
-    "blue_hi"       : "\033[104m*\033[0m ",
-    "navy_hi"       : "\033[44m*\033[0m ",
-    "grey"          : "\033[90m*\033[0m ",
-    "pink"          : "\033[95m*\033[0m ",
-    "fuchsia"       : "\033[35m*\033[0m ",
-    "ruby"          : "\033[31m*\033[0m ",
-    "red"           : "\033[91m*\033[0m ",
-    "orange"        : "\033[91m*\033[0m ",
-    "yellow"        : "\033[93m*\033[0m ",
-    "brown"         : "\033[33m*\033[0m ",
-    "green"         : "\033[92m*\033[0m ",
-    "darkgreen"     : "\033[32m*\033[0m ",
-    "cyan"          : "\033[36m*\033[0m ",
-    "blue"          : "\033[94m*\033[0m ",
-    "navy"          : "\033[34m*\033[0m ",
-    "black"         : "\033[30m*\033[0m "
-  ];
-}
diff --git a/lib/sdp/compile_time_info.d b/lib/sdp/compile_time_info.d
index e541113..783ac62 100644
--- a/lib/sdp/compile_time_info.d
+++ b/lib/sdp/compile_time_info.d
@@ -2,7 +2,7 @@
   compile_time_info
   compile_time_info.d
 +/
-mixin template CompileTimeInfo() {
+template CompileTimeInfo() {
   version(Windows) {
     pragma(msg, "[ Windows compilation ]");
     enum os = "Windows";
diff --git a/lib/sdp/sdp.d b/lib/sdp/sdp.d
new file mode 100755
index 0000000..8c44d16
--- /dev/null
+++ b/lib/sdp/sdp.d
@@ -0,0 +1,186 @@
+#!/usr/bin/env rdmd
+// [used by rdmd]
+/+
+  sdp
+  sdp.d
++/
+/+ sdp  sisu document parser +/
+private import
+  std.getopt,
+  std.process,
+  std.stdio,
+  std.algorithm,
+  std.array,
+  std.container,
+  std.exception,
+  std.json,
+  // std.path,
+  std.range,
+  std.regex,
+  // std.stdio,
+  std.string,
+  std.traits,
+  std.typecons,
+  std.utf,
+  // std.variant,
+  std.conv : to;
+/+ sdp  sisu document parser +/
+import
+  compile_time_info,            // compile_time_info.d
+  ao_abstract_doc_source,       // ao_abstract_doc_source.d
+  ao_defaults,                  // ao_defaults.d
+  ao_read_source_files,         // ao_read_source_files.d
+  ao_output_debugs,             // ao_output_debugs.d
+  ao_rgx,                       // ao_rgx.d
+  ao_ansi_colors;               // ao_ansi_colors.d
+  // std.conv;
+mixin(import("version.txt"));
+mixin CompileTimeInfo;
+mixin RgxInit;
+void main(string[] args) {
+  
+  mixin SiSUheader;
+  mixin SiSUbiblio;
+  mixin SiSUrgxInitFlags;
+  mixin SiSUmarkupRaw;
+  mixin SiSUdocAbstraction;
+  mixin SiSUoutputDebugs;
+  mixin ScreenTxtColors;
+  auto raw = MarkupRaw();
+  auto abs = Abstraction();
+  auto dbg = SDPoutputDebugs();
+  /+
+  struct DocumentParts {
+    string[string][] contents;
+    JSONValue[string] metadata_json;
+    JSONValue[string] make_json;
+    string[][string][string] bookindex_unordered_hashes;
+    JSONValue[] biblio;
+  }
+  +/
+  string[] fns_src;
+  string flag_action;
+  string arg_unrecognized;
+  auto rgx = Rgx();
+  scope(success) {
+    debug(checkdoc) {
+      writefln(
+        "%s~ run complete, ok ~ %s (sdp-%s.%s.%s, %s v%s, %s %s)",
+        scr_txt_color["cyan"], scr_txt_color["off"],
+        ver.major, ver.minor, ver.patch,
+        __VENDOR__, __VERSION__,
+        bits, os,
+      );
+    }
+    // stderr.writeln("0");
+  }
+  scope(failure) {
+    debug(checkdoc) {
+      stderr.writefln(
+        "%s~ run failure ~%s",
+         scr_txt_color["fuchsia"], scr_txt_color["off"],
+      );
+    }
+  }
+  
+  bool[string] opt_action_bool = [
+    "assertions"          : false,
+    "html"                : false,
+    "no_obj_cite_number"  : false,
+    "verbose"             : false,
+  ];
+  auto helpInfo = getopt(args,
+    std.getopt.config.passThrough,
+    "assert",    "--assert set optional assertions on",          &opt_action_bool["assertions"],
+    "html",      "--html process html output",                   &opt_action_bool["html"],
+    "no-ocn",    "--no-ocn suppress object cite number output",  &opt_action_bool["no_obj_cite_number"],
+    "verbose|v", "--verbose output to terminal",                 &opt_action_bool["verbose"],
+  );
+  if (helpInfo.helpWanted) {
+    defaultGetoptPrinter("Some information about the program.", helpInfo.options);
+  }
+  foreach(arg; args) {
+    if (match(arg, rgx.flag_action)) {
+      flag_action ~= " " ~ arg;   // flags not taken by getopt
+    } else if (match(arg, rgx.src_pth)) {
+      fns_src ~= arg;             // gather input markup source file names for processing
+    } else {                      // anything remaining, unused
+      arg_unrecognized ~= " " ~ arg;
+    }
+  }
+  foreach(fn_src; fns_src) {
+    if (!empty(fn_src)) {
+      scope(success) {
+        debug(checkdoc) {
+          writefln(
+            "%s~ document complete, ok ~%s",
+            scr_txt_color["green"], scr_txt_color["off"],
+          );
+        }
+        // stderr.writeln("0");
+      }
+      scope(failure) {
+        debug(checkdoc) {
+          stderr.writefln(
+            "%s~ document run failure ~%s (%s  v%s)\n\t%s",
+            scr_txt_color["red"], scr_txt_color["off"],
+            __VENDOR__, __VERSION__,
+            fn_src
+          );
+        }
+        // stderr.writeln("1");
+      }
+      enforce(
+        match(fn_src, rgx.src_pth),
+        "not a sisu markup filename"
+      );
+      /+ ↓ read file +/
+      auto sourcefile_content =
+        raw.sourceContent(fn_src);
+      /+ ↓ porcess document, return abstraction as tuple +/
+      auto t =
+        abs.abstract_doc_source(sourcefile_content);
+      static assert(!isTypeTuple!(t));
+      auto doc_ao_contents = t[0]; // contents ~ endnotes ~ bookindex;
+      // static assert(!isIterable!(doc_ao_contents));
+      auto doc_ao_metadata_json = t[1];
+      auto doc_ao_make_json = t[2];
+      auto doc_ao_bookindex_unordered_hashes = t[3];
+      auto doc_ao_biblio = t[4];
+      // destroy(t);
+      /+ ↓ document parts +/
+      debug(checkdoc) { // checkbook & dumpdoc
+        dbg.abstract_doc_source_debugs(
+          doc_ao_contents,
+          doc_ao_make_json,
+          doc_ao_metadata_json,
+          doc_ao_bookindex_unordered_hashes,
+          doc_ao_biblio,
+          fn_src,
+          opt_action_bool
+        );
+      }
+      scope(exit) {
+        debug(checkdoc) {
+          writefln(
+            "processed file: %s",
+            fn_src
+          );
+        }
+        destroy(sourcefile_content);
+        destroy(t);
+        destroy(doc_ao_contents);
+        destroy(doc_ao_make_json);
+        destroy(doc_ao_metadata_json);
+        destroy(doc_ao_bookindex_unordered_hashes);
+        destroy(doc_ao_biblio);
+        destroy(fn_src);
+      }
+    } else {
+      /+ no recognized filename provided +/
+      writeln("no recognized filename");
+      break;
+      // terminate, stop
+    }
+  }
+}
-- 
cgit v1.2.3