From 7f5b1a866e239b2137ede22235f7b69731b6e743 Mon Sep 17 00:00:00 2001
From: Ralph Amissah <ralph@amissah.com>
Date: Thu, 2 Feb 2017 13:20:08 -0500
Subject: ao_doc_abstraction.org (moved/renamed ao_abstract_doc_source.org)

---
 org/ao_abstract_doc_source.org | 5978 ---------------------------------------
 org/ao_doc_abstraction.org     | 5998 ++++++++++++++++++++++++++++++++++++++++
 org/ao_summary_and_debugs.org  |   16 +-
 3 files changed, 6002 insertions(+), 5990 deletions(-)
 delete mode 100644 org/ao_abstract_doc_source.org
 create mode 100644 org/ao_doc_abstraction.org

(limited to 'org')

diff --git a/org/ao_abstract_doc_source.org b/org/ao_abstract_doc_source.org
deleted file mode 100644
index e441b7d..0000000
--- a/org/ao_abstract_doc_source.org
+++ /dev/null
@@ -1,5978 +0,0 @@
-#+TITLE: sdp document abstraction
-#+AUTHOR: Ralph Amissah
-#+EMAIL: ralph.amissah@gmail.com
-#+STARTUP: indent
-#+LANGUAGE: en
-#+OPTIONS: H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
-#+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
-#+OPTIONS: author:nil email:nil creator:nil timestamp:nil
-#+PROPERTY: header-args :padline no :exports code :noweb yes
-#+EXPORT_SELECT_TAGS: export
-#+EXPORT_EXCLUDE_TAGS: noexport
-#+FILETAGS: :sdp:rel:ao:
-#+TAGS: assert(a) class(c) debug(d) mixin(m) sdp(s) tangle(T) template(t) WEB(W) noexport(n)
-
-[[./sdp.org][sdp]]  [[./][org/]]
-* 1. Document Abstraction                                  :abstract:process:
-Process markup document, create document abstraction.
-
-** 0. ao abstract doc source:                       :ao_abstract_doc_source:
-
-#+BEGIN_SRC d :tangle ../src/sdp/ao_abstract_doc_source.d
-/++
-  document abstraction:
-  abstraction of sisu markup for downstream processing
-  ao_abstract_doc_source.d
-+/
-template SiSUdocAbstraction() {
-  /+ ↓ abstraction imports +/
-  <<abs_imports>>
-  /+ ↓ abstraction mixins +/
-  <<abs_mixins>>
-  /+ ↓ abstraction struct init +/
-  <<abs_init_struct>>
-  /+ ↓ abstract marked up document +/
-  auto SiSUdocAbstraction(Src,Make,Meta,Opt)(
-    Src                  markup_sourcefile_content,
-    Make                 dochead_make_aa,
-    Meta                 dochead_meta_aa,
-    Opt                  opt_action_bool,
-  ) {
-    auto rgx = Rgx();
-    debug(asserts){
-      static assert(is(typeof(markup_sourcefile_content) == char[][]));
-      static assert(is(typeof(dochead_make_aa)           == string[string][string]));
-      static assert(is(typeof(dochead_meta_aa)           == string[string][string]));
-      static assert(is(typeof(opt_action_bool)           == bool[string]));
-    }
-    /+ ↓ abstraction init +/
-    <<abs_init_rest>>
-    /+ abstraction init ↑ +/
-    /+ ↓ loop markup document/text line by line +/
-    srcDocLoop:
-    foreach (line; markup_sourcefile_content) {
-      /+ ↓ markup document/text line by line +/
-      <<abs_in_loop_body_00>>
-      if (type["code"] == TriState.on) {
-        <<abs_in_loop_body_00_code_block>>
-      } else if (!matchFirst(line, rgx.skip_from_regular_parse)) {
-        /+ object other than "code block" object
-           (includes regular text paragraph, headings & blocks other than code) +/
-        <<abs_in_loop_body_non_code_obj>>
-        } else {
-          /+ not within a block group +/
-          <<abs_in_loop_body_open_block_obj_assert>>
-          if (matchFirst(line, rgx.block_open)) {
-            <<abs_in_loop_body_open_block_obj>>
-          } else if (!line.empty) {
-            /+ line not empty +/
-            /+ non blocks (headings, paragraphs) & closed blocks +/
-            <<abs_in_loop_body_not_block_obj>>
-          } else if (type["blocks"] == TriState.closing) {
-            /+ line empty, with blocks flag +/
-            <<abs_in_loop_body_not_block_obj_line_empty_blocks_flags>>
-          } else {
-            /+ line.empty, post contents, empty variables: +/
-            <<abs_in_loop_body_not_block_obj_line_empty>>
-          } // close else for line empty
-        } // close else for not the above
-      } // close after non code, other blocks or regular text
-      <<abs_in_loop_body_01>>
-    } /+ ← closed: loop markup document/text line by line +/
-    /+ ↓ post loop markup document/text +/
-    <<abs_post>>
-    /+ post loop markup document/text ↑ +/
-  } /+ ← closed: abstract doc source +/
-  /+ ↓ abstraction functions +/
-  <<abs_functions_object_reset>>
-  <<abs_functions_header_set_common>>
-  <<abs_functions_ocn_status>>
-  <<abs_functions_block>>
-  <<abs_functions_block_code>>
-  <<abs_functions_block_biblio>>
-  // <<abs_functions_block_glossary>>
-  <<abs_functions_block_poem>>
-  <<abs_functions_block_group>>
-  <<abs_functions_block_block>>
-  <<abs_functions_block_quote>>
-  <<abs_functions_block_table>>
-  <<abs_functions_block_line_status_empty>>
-  <<abs_functions_book_index>>
-  <<abs_functions_heading>>
-  <<abs_functions_para>>
-  /+ abstraction functions ↑ +/
-  /+ ↓ abstraction function emitters +/
-  <<ao_emitters_ocn>>
-  /+ +/
-  <<ao_emitters_obj_inline_markup_munge>>
-  <<ao_emitters_obj_inline_markup>>
-  <<ao_emitters_obj_inline_markup_and_anchor_tags>>
-  <<ao_emitters_obj_inline_markup_table_of_contents>>
-  <<ao_emitters_obj_inline_markup_private>>
-  <<ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags>>
-  <<ao_emitters_obj_inline_markup_close>>
-  /+ +/
-  <<ao_emitters_obj_attributes>>
-  <<ao_emitters_obj_attributes_public>>
-  <<ao_emitters_obj_attributes_private>>
-  <<ao_emitters_obj_attributes_private_an_attribute>>
-  <<ao_emitters_obj_attributes_private_json>>
-  <<ao_emitters_obj_attributes_private_close>>
-  /+ +/
-  <<ao_emitters_book_index_nugget>>
-  <<ao_emitters_book_index_report_indented>>
-  <<ao_emitters_book_index_report_section>>
-  /+ +/
-  <<ao_emitters_endnotes>>
-  /+ +/
-  <<ao_emitters_bibliography>>
-  /+ +/
-  <<ao_emitters_metadata>>
-  /+ abstraction functions emitters ↑ +/
-  /+ ↓ abstraction functions assertions +/
-  <<abs_functions_assertions>>
-  /+ abstraction functions assertions ↑ +/
-} /+ ← closed: template SiSUdocAbstraction +/
-#+END_SRC
-
-** _1. pre loop processing_                                              :pre:
-*** imports                                                       :imports:
-
-[[./ao_defaults.org][ao_defaults]]
-
-#+name: abs_imports
-#+BEGIN_SRC d
-import
-  ao_object_setter,
-  ao_defaults,
-  ao_rgx,
-  output_hub;
-private import
-  std.algorithm,
-  std.array,
-  std.container,
-  std.exception,
-  std.file,
-  std.getopt,
-  std.json,
-  std.path,
-  std.process,
-  std.range,
-  std.regex,
-  std.stdio,
-  std.string,
-  std.traits,
-  std.typecons,
-  std.uni,
-  std.utf,
-  std.conv : to;
-#+END_SRC
-
-*** mixins                                                         :mixins:
-
-#+name: abs_mixins
-#+BEGIN_SRC d
-mixin ObjectSetter;
-mixin InternalMarkup;
-mixin SiSUrgxInit;
-#+END_SRC
-
-*** initialize                                                 :initialize:
-**** initialize general
-
-#+name: abs_init_struct
-#+BEGIN_SRC d
-/+ initialize +/
-ObjGenericComposite[][string] the_table_of_contents_section;
-ObjGenericComposite[] the_document_head_section, the_document_body_section, the_bibliography_section, the_glossary_section, the_blurb_section;
-ObjGenericComposite[] the_dom_tail_section;
-string[string] an_object, processing;
-string an_object_key;
-string[] anchor_tags;
-string anchor_tag_;
-string segment_anchor_tag_that_object_belongs_to;
-string segment_anchor_tag_that_object_belongs_to_uri;
-auto note_section = NotesSection();
-/+ enum +/
-enum State { off, on }
-enum TriState { off, on, closing }
-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 }
-/+ biblio variables +/
-string biblio_tag_name, biblio_tag_entry, st;
-string[] biblio_arr_json;
-string biblio_entry_str_json;
-JSONValue[] bib_arr_json;
-int bib_entry;
-/+ counters +/
-int cntr, previous_count, previous_length;
-int[string] line_occur;
-string[] html_segnames=["toc"];
-int html_segnames_ptr=0;
-int html_segnames_ptr_cntr=0;
-int verse_line, heading_ptr;
-/+ paragraph attributes +/
-int[string] indent;
-bool bullet = true;
-string content_non_header = "8";
-auto obj_im = ObjInlineMarkup();
-auto obj_att = ObjAttributes();
-/+ ocn +/
-int obj_cite_number, obj_cite_number_;
-auto object_citation_number = OCNemitter();
-int[] dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
-int[] dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
-int[] dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
-int[] dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
-enum DomTags { none, open, close, close_and_open, open_still, }
-#+END_SRC
-
-**** initialize heading ancestors
-
-#+name: abs_init_struct
-#+BEGIN_SRC d
-void heading_ancestors(O)(
-  auto ref O         obj,
-  ref string[]       lv_ancestors,
-) {
-  switch (obj.heading_lev_markup) {
-  case 0:
-    lv_ancestors[0] = to!string(obj.text);
-    foreach(k; 1..8) {
-      lv_ancestors[k] = "";
-    }
-    goto default;
-  case 1:
-    lv_ancestors[1] = to!string(obj.text);
-    foreach(k; 2..8) {
-      lv_ancestors[k] = "";
-    }
-    goto default;
-  case 2:
-    lv_ancestors[2] = to!string(obj.text);
-    foreach(k; 3..8) {
-      lv_ancestors[k] = "";
-    }
-    goto default;
-  case 3:
-    lv_ancestors[3] = to!string(obj.text);
-    foreach(k; 4..8) {
-      lv_ancestors[k] = "";
-    }
-    goto default;
-  case 4:
-    lv_ancestors[4] = to!string(obj.text);
-    foreach(k; 5..8) {
-      lv_ancestors[k] = "";
-    }
-    goto default;
-  case 5:
-    lv_ancestors[5] = to!string(obj.text);
-    foreach(k; 6..8) {
-      lv_ancestors[k] = "";
-    }
-    goto default;
-  case 6:
-    lv_ancestors[6] = to!string(obj.text);
-    lv_ancestors[7] = "";
-    goto default;
-  case 7:
-    lv_ancestors[7] = to!string(obj.text);
-    goto default;
-  default:
-    obj.heading_ancestors_text = lv_ancestors.dup;
-  }
-}
-#+END_SRC
-
-**** initialize dom markup tags
-
-#+name: abs_init_struct
-#+BEGIN_SRC d
-auto dom_set_markup_tags(int[] dom, int lev) {
-  foreach (i; 0 .. 8) {
-    if (i < lev) {
-      if (dom[i] == DomTags.open
-         || dom[i] == DomTags.close_and_open
-      ) {
-        dom[i] = DomTags.open_still;
-      } else if (dom[i] == DomTags.close) {
-        dom[i] = DomTags.none;
-      }
-    } else if (i == lev) {
-      if (lev  == 0
-        && dom[i] == DomTags.open_still
-      ) {
-        dom[i] = DomTags.close;
-      } else if (dom[i] == DomTags.open
-        || dom[i] == DomTags.open_still
-        || dom[i] == DomTags.close_and_open
-      ) {
-        dom[i] = DomTags.close_and_open;
-      } else {
-        dom[i] = DomTags.open;
-      }
-    } else if (i > lev) {
-      if (dom[i] == DomTags.close) {
-        dom[i] = DomTags.none;
-      } else if (dom[i] == DomTags.open
-        || dom[i] == DomTags.open_still
-        || dom[i] == DomTags.close_and_open
-      ) {
-        dom[i] = DomTags.close;
-      }
-    }
-  }
-  debug(dom) {
-    writeln(lev, ": ", dom);
-  }
-  return dom;
-}
-#+END_SRC
-
-**** initialize dom collapsed tags
-
-#+name: abs_init_struct
-#+BEGIN_SRC d
-auto dom_set_collapsed_tags(int[] dom, int lev) {
-  foreach (i; 0 .. 8) {
-    if (i < lev) {
-      if (dom[i] == DomTags.open
-         || dom[i] == DomTags.close_and_open
-      ) {
-        dom[i] = DomTags.open_still;
-      } else if (dom[i] == DomTags.close) {
-        dom[i] = DomTags.none;
-      }
-    } else if (i == lev) {
-      if (lev  == 0
-        && dom[i] == DomTags.open_still
-      ) {
-        dom[i] = DomTags.close;
-      } else if (dom[i] == DomTags.open
-        || dom[i] == DomTags.open_still
-        || dom[i] == DomTags.close_and_open
-      ) {
-        dom[i] = DomTags.close_and_open;
-      } else {
-        dom[i] = DomTags.open;
-      }
-    } else if (i > lev) {
-      if (dom[i] == DomTags.close) {
-        dom[i] = DomTags.none;
-      } else if (dom[i] == DomTags.open
-        || dom[i] == DomTags.open_still
-        || dom[i] == DomTags.close_and_open
-      ) {
-        dom[i] = DomTags.close;
-      }
-    }
-  }
-  debug(dom) {
-    writeln(lev, ": ", dom);
-  }
-  return dom;
-}
-#+END_SRC
-
-**** initialize ocn emit
-
-#+name: abs_init_struct
-#+BEGIN_SRC d
-int ocn_emit(int ocn_status_flag) {
-  return object_citation_number.ocn_emitter(ocn_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 +/
-ObjGenericComposite comp_obj_heading, comp_obj_location, comp_obj_block, comp_obj_code, comp_obj_poem_ocn, comp_obj_comment;
-auto node_construct = NodeStructureMetadata();
-#+END_SRC
-
-*** scope
-
-#+name: abs_init_rest
-#+BEGIN_SRC d
-scope(success) {
-}
-scope(failure) {
-}
-scope(exit) {
-  destroy(the_document_head_section);
-  destroy(the_table_of_contents_section);
-  destroy(the_document_body_section);
-  destroy(the_bibliography_section);
-  destroy(an_object);
-  destroy(processing);
-  destroy(biblio_arr_json);
-}
-#+END_SRC
-
-*** init rest
-
-#+name: abs_init_rest
-#+BEGIN_SRC d
-mixin SiSUrgxInitFlags;
-mixin SiSUnode;
-auto node_para_int_    = node_metadata_para_int;
-auto node_para_str_    = node_metadata_para_str;
-ObjGenericComposite comp_obj_heading_, comp_obj_para, comp_obj_toc;
-line_occur = [
-  "heading"  : 0,
-  "para"     : 0,
-  "glossary" : 0,
-  "blurb"    : 0,
-];
-auto type = flags_type_init;
-string[string] obj_cite_number_poem = [
-  "start" : "",
-  "end"   : ""
-];
-string[] lv_ancestors = [ "", "", "", "", "", "", "", "", ];
-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_int_collapsed" : 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)")
-];
-string _anchor_tag;
-string toc_txt_;
-an_object["glossary_nugget"] = "";
-an_object["blurb_nugget"] = "";
-comp_obj_heading_                       = comp_obj_heading_.init;
-comp_obj_heading_.use                   = "frontmatter";
-comp_obj_heading_.is_of                 = "para";
-comp_obj_heading_.is_a                  = "heading";
-comp_obj_heading_.text                  = "Table of Contents";
-comp_obj_heading_.ocn                   = 0;
-comp_obj_heading_.obj_cite_number       = "";
-comp_obj_heading_.segment_anchor_tag    = "toc";
-comp_obj_heading_.marked_up_level       = "1";
-comp_obj_heading_.heading_lev_markup    = 4;
-comp_obj_heading_.heading_lev_collapsed = 1;
-comp_obj_heading_.parent_ocn            = 1;
-comp_obj_heading_.parent_lev_markup     = 0;
-comp_obj_heading_.ptr_html_segnames     = html_segnames_ptr;
-comp_obj_heading_.anchor_tags           = ["toc"];
-auto toc_head                           = comp_obj_heading_;
-html_segnames_ptr_cntr++;
-the_table_of_contents_section = [
-  "seg": [toc_head],
-  "scroll": [toc_head],
-];
-auto mkup = InlineMarkup();
-auto munge = ObjInlineMarkupMunge();
-string[][string] lev4_subtoc;
-#+END_SRC
-
-** _2. loop: process document body_ [+6]                                :loop:
-*** loop scope                                                      :scope:
-
-#+name: abs_in_loop_body_00
-#+BEGIN_SRC d
-/+ scope +/
-scope(exit) {
-}
-scope(failure) {
-  stderr.writefln(
-    "%s\n%s\n%s:%s failed here:\n  line: %s",
-    __MODULE__, __FUNCTION__,
-    __FILE__, __LINE__,
-    line,
-  );
-}
-line = replaceAll(line, rgx.true_dollar, "$$$$");
-  // dollar represented as $$ needed to stop submatching on $
-  // (substitutions using ${identifiers} must take into account (i.e. happen earlier))
-debug(source) {                                  // source lines
-  writeln(line);
-}
-debug(srclines) {
-  if (!line.empty) {                             // source lines, not empty
-    writefln(
-      "* %s",
-      line
-    );
-  }
-}
-#+END_SRC
-
-*** check whether obj_cite_number is on or turned off                 :ocn:
-
-#+name: abs_in_loop_body_00
-#+BEGIN_SRC d
-if (!line.empty) {
-  _check_ocn_status_(line, type);
-}
-#+END_SRC
-
-*** [#A] separate regular markup text from code blocks [+5]
-**** code blocks                                              :block:code:
-
-#+name: abs_in_loop_body_00_code_block
-#+BEGIN_SRC d
-/+ block object: code +/
-_code_block_(line, an_object, type);
-continue;
-#+END_SRC
-
-**** non code objects (other blocks or regular text) [+4]       :non_code:
-***** in section (biblio, glossary, blurb) (block group) [+1] :block:active:
-****** within section: biblio                                   :biblio:
-
-#+name: abs_in_loop_body_non_code_obj
-#+BEGIN_SRC d
-if ((matchFirst(line, rgx.heading_biblio)
-|| (type["biblio_section"] == State.on
-&& (!matchFirst(line, rgx.heading_blurb_glossary))))
-&& (!matchFirst(line, rgx.heading))
-&& (!matchFirst(line, rgx.comment))) {
-  /+ within section (block object): biblio +/
-  type["glossary_section"] = State.off;
-  type["biblio_section"] = State.on;
-  type["blurb_section"] = State.off;
-  if (opt_action_bool["backmatter"] && opt_action_bool["section_biblio"]) {
-    _biblio_block_(line, type, bib_entry, biblio_entry_str_json, biblio_arr_json); //
-    debug(bibliobuild) {
-      writeln("-  ", biblio_entry_str_json);
-      writeln("-> ", biblio_arr_json.length);
-    }
-  }
-  continue;
-#+END_SRC
-
-****** within section: glossary                               :glossary:
-
-if there is a glossary section you need to:
-- extract it
-- create standard headings
-- markup contents in standard way like regular paragraphs
-  - need indentation and regular paragraph inline markup
-- reconstitute the document with the glossary section following the endnotes
-
-#+name: abs_in_loop_body_non_code_obj
-#+BEGIN_SRC d
-} else if ((matchFirst(line, rgx.heading_glossary)
-|| (type["glossary_section"] == State.on
-&& (!matchFirst(line, rgx.heading_biblio_blurb))))
-&& (!matchFirst(line, rgx.heading))
-&& (!matchFirst(line, rgx.comment))) {
-  /+ within section (block object): glossary +/
-  debug(glossary) {
-    writeln(__LINE__);
-    writeln(line);
-  }
-  // _glossary_block_(line, type);
-  type["glossary_section"] = State.on;
-  type["biblio_section"] = State.off;
-  type["blurb_section"] = State.off;
-  if (opt_action_bool["backmatter"] && opt_action_bool["section_glossary"]) {
-    indent=[
-      "hang_position" : 0,
-      "base_position" : 0,
-    ];
-    bullet = false;
-    type["para"] = State.on;
-    line_occur["para"] = State.off;
-    an_object_key="glossary_nugget"; //
-    if (matchFirst(line, rgx.heading_glossary)) {
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "backmatter";
-      comp_obj_heading_.is_of                 = "para";
-      comp_obj_heading_.is_a                  = "heading";
-      comp_obj_heading_.text                  = "Glossary";
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.marked_up_level       = "B";
-      comp_obj_heading_.heading_lev_markup    = 1;
-      comp_obj_heading_.heading_lev_collapsed = 1;
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      the_glossary_section                    ~= comp_obj_heading_;
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "backmatter";
-      comp_obj_heading_.is_of                 = "para";
-      comp_obj_heading_.is_a                  = "heading";
-      comp_obj_heading_.text                  = "Glossary";
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.segment_anchor_tag    = "glossary";
-      comp_obj_heading_.marked_up_level       = "1";
-      comp_obj_heading_.heading_lev_markup    = 4;
-      comp_obj_heading_.heading_lev_collapsed = 2;
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      comp_obj_heading_.anchor_tags           = ["glossary"];
-      the_glossary_section                    ~= comp_obj_heading_;
-    } else {
-      _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
-      comp_obj_para                       = comp_obj_para.init;
-      comp_obj_para.use                   = "backmatter";
-      comp_obj_para.is_of                 = "para";
-      comp_obj_para.is_a                  = "glossary";
-      comp_obj_para.text                  = to!string(line).strip;
-      comp_obj_para.ocn                   = 0;
-      comp_obj_para.obj_cite_number       = "";
-      comp_obj_para.indent_hang           = indent["hang_position"];
-      comp_obj_para.indent_base           = indent["base_position"];
-      comp_obj_para.bullet                = bullet;
-      the_glossary_section                ~= comp_obj_para;
-    }
-    type["ocn_status"] = TriState.off;
-  }
-  continue;
-#+END_SRC
-
-****** within section: blurb                                     :blurb:
-
-if there is a blurb section you need to:
-- extract it
-- create standard headings (or use line provided in 1~ heading)
-- markup contents in standard way like regular paragraphs
-  - need regular paragraph inline markup
-- reconstitute the document with the blurb section at the very end of the doucment
-
-#+name: abs_in_loop_body_non_code_obj
-#+BEGIN_SRC d
-} else if ((matchFirst(line, rgx.heading_blurb)
-|| (type["blurb_section"] == State.on
-&& (!matchFirst(line, rgx.heading_biblio_glossary))))
-&& (!matchFirst(line, rgx.heading))
-&& (!matchFirst(line, rgx.comment))) {
-  /+ within section (block object): blurb +/
-  debug(blurb) {
-    writeln(__LINE__);
-    writeln(line);
-  }
-  type["glossary_section"] = State.off;
-  type["biblio_section"] = State.off;
-  type["blurb_section"] = State.on;
-  if (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"]) {
-    indent=[
-      "hang_position" : 0,
-      "base_position" : 0,
-    ];
-    bullet = false;
-    type["para"] = State.on;
-    line_occur["para"] = State.off;
-    an_object_key="blurb_nugget";
-    if (matchFirst(line, rgx.heading_blurb)) {
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "backmatter";
-      comp_obj_heading_.is_of                 = "para";
-      comp_obj_heading_.is_a                  = "heading";
-      comp_obj_heading_.text                  = "Blurb";
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.marked_up_level       = "B";
-      comp_obj_heading_.heading_lev_markup    = 1;
-      comp_obj_heading_.heading_lev_collapsed = 1;
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      the_blurb_section                       ~= comp_obj_heading_;
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "backmatter";
-      comp_obj_heading_.is_of                 = "para";
-      comp_obj_heading_.is_a                  = "heading";
-      comp_obj_heading_.text                  = "Blurb";
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.segment_anchor_tag    = "blurb";
-      comp_obj_heading_.marked_up_level       = "1";
-      comp_obj_heading_.heading_lev_markup    = 4;
-      comp_obj_heading_.heading_lev_collapsed = 2;
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      comp_obj_heading_.anchor_tags           = ["blurb"];
-      the_blurb_section                       ~= comp_obj_heading_;
-    } else if ((matchFirst(line, rgx.heading))
-    && (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"])) {
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "backmatter";
-      comp_obj_heading_.is_of                 = "para";
-      comp_obj_heading_.is_a                  = "heading";
-      comp_obj_heading_.text                  = to!string(line);
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.segment_anchor_tag    = "blurb";
-      comp_obj_heading_.marked_up_level       = to!string(an_object["lev"]);
-      comp_obj_heading_.heading_lev_markup    = to!int(an_object["lev_markup_number"]);    // make int, remove need to conv
-      comp_obj_heading_.heading_lev_collapsed = to!int(an_object["lev_collapsed_number"]); // make int, remove need to conv
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      the_blurb_section                   ~= comp_obj_heading_;
-    } else {
-      _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
-      comp_obj_para                       = comp_obj_para.init;
-      comp_obj_para.use                   = "backmatter";
-      comp_obj_para.is_of                 = "para";
-      comp_obj_para.is_a                  = "blurb";
-      comp_obj_para.text                  = to!string(line).strip;
-      comp_obj_para.ocn                   = 0;
-      comp_obj_para.obj_cite_number       = "";
-      comp_obj_para.indent_hang           = indent["hang_position"];
-      comp_obj_para.indent_base           = indent["base_position"];
-      comp_obj_para.bullet                = bullet;
-      the_blurb_section                   ~= comp_obj_para;
-    }
-    type["ocn_status"] = TriState.off;
-  }
-  continue;
-#+END_SRC
-
-***** in blocks [+1]                                       :block:active:
-****** within block: poem                                         :poem:
-
-#+name: abs_in_loop_body_non_code_obj
-#+BEGIN_SRC d
-} else if (type["poem"] == TriState.on) {
-  /+ within block object: poem +/
-  _poem_block_(line, an_object, type, cntr, obj_cite_number_poem, dochead_make_aa);
-  continue;
-#+END_SRC
-
-****** within block: group                                       :group:
-
-#+name: abs_in_loop_body_non_code_obj
-#+BEGIN_SRC d
-/+ within block object: group +/
-} else if (type["group"] == TriState.on) {
-  /+ within block object: group +/
-  _group_block_(line, an_object, type);
-  continue;
-#+END_SRC
-
-****** within block: block                                       :block:
-
-#+name: abs_in_loop_body_non_code_obj
-#+BEGIN_SRC d
-} else if (type["block"] == TriState.on) {
-  /+ within block object: block +/
-  _block_block_(line, an_object, type);
-  continue;
-#+END_SRC
-
-****** within block: quote                                       :quote:
-
-#+name: abs_in_loop_body_non_code_obj
-#+BEGIN_SRC d
-} else if (type["quote"] == TriState.on) {
-  /+ within block object: quote +/
-  _quote_block_(line, an_object, type);
-  continue;
-#+END_SRC
-
-****** within block: table                                       :table:
-
-#+name: abs_in_loop_body_non_code_obj
-#+BEGIN_SRC d
-} else if (type["table"] == TriState.on) {
-  /+ within block object: table +/
-  _table_block_(line, an_object, type);
-  continue;
-#+END_SRC
-
-***** not identified as being within block group (could still be, or not) [+3]
-****** assert
-
-#+name: abs_in_loop_body_open_block_obj_assert
-#+BEGIN_SRC d
-assert(
-  (type["blocks"] == TriState.off)
-  || (type["blocks"] == TriState.closing),
-  "block status: none or closed"
-);
-assertions_flag_types_block_status_none_or_closed(type);
-#+END_SRC
-
-****** block open
-
-#+name: abs_in_loop_body_open_block_obj
-#+BEGIN_SRC d
-if (matchFirst(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);
-}
-_start_block_(line, type, obj_cite_number_poem);
-continue;
-#+END_SRC
-
-****** line not empty [+2]
-******* asserts                                                :assert:
-
-#+name: abs_in_loop_body_not_block_obj
-#+BEGIN_SRC d
-assert(
-  !line.empty,
-  "line tested, line not empty surely"
-);
-assert(
-  (type["blocks"] == TriState.off)
-  || (type["blocks"] == TriState.closing),
-  "code block status: none or closed"
-);
-if (type["blocks"] == TriState.closing) {
-  // blocks closed, unless followed by book index
-  debug(check) {                           // block
-    writeln(__LINE__);
-    writeln(line);
-  }
-  assert(
-    matchFirst(line, rgx.book_index)
-    || matchFirst(line, rgx.book_index_open)
-    || type["book_index"] == State.on
-  );
-}
-#+END_SRC
-
-******* book index                                          :bookindex:
-
-#+name: abs_in_loop_body_not_block_obj
-#+BEGIN_SRC d
-if ((matchFirst(line, rgx.book_index))
-|| (matchFirst(line, rgx.book_index_open))
-|| (type["book_index"] == State.on ))  {
-  /+ book_index +/
-  _book_index_(line, book_idx_tmp, an_object, type, opt_action_bool);
-#+END_SRC
-
-******* not book index [+1]
-
-#+name: abs_in_loop_body_not_block_obj
-#+BEGIN_SRC d
-} else {
-  /+ not book_index +/
-#+END_SRC
-
-******** matched: comment                              :comment:match:
-
-#+name: abs_in_loop_body_not_block_obj
-#+BEGIN_SRC d
-  an_object_key="body_nugget";
-  if (auto m = matchFirst(line, rgx.comment)) {
-    /+ matched comment +/
-    debug(comment) {
-      writeln(line);
-    }
-    an_object[an_object_key] ~= line ~= "\n";
-    comp_obj_comment                   = comp_obj_comment.init;
-    comp_obj_comment.use               = "comment";
-    comp_obj_comment.is_of             = "comment";
-    comp_obj_comment.is_a              = "comment";
-    comp_obj_comment.text              = an_object[an_object_key].strip;
-    the_document_body_section          ~= comp_obj_comment;
-    _common_reset_(line_occur, an_object, type);
-    processing.remove("verse");
-    ++cntr;
-#+END_SRC
-
-******** flag not set & line not exist: heading or para :heading:paragraph:
-
-#+name: abs_in_loop_body_not_block_obj
-#+BEGIN_SRC d
-  } 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 ((dochead_make_aa["make"]["headings"].length > 2)
-    && (type["make_headings"] == State.off)) {
-      /+ heading found +/
-      _heading_found_(line, dochead_make_aa["make"]["headings"], heading_match_str, heading_match_rgx, 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 +/
-      _heading_make_set_(line, line_occur, heading_match_rgx, type);
-    }
-    /+ TODO node info: all headings identified at this point,
-       - extract node info here??
-       - how long can it wait?
-       - should be incorporated in composite objects
-       - should happen before endnote links set (they need to be moved down?)
-      // node_construct.node_emitter_heading segment anchor tag
-    +/
-    if (matchFirst(line, rgx.heading)) {
-      /+ heading match +/
-      _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa);
-    } else if (line_occur["para"] == State.off) {
-      /+ para match +/
-      an_object_key="body_nugget";
-      _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
-    }
-#+END_SRC
-
-******** line exist: heading                                 :heading:
-
-#+name: abs_in_loop_body_not_block_obj
-#+BEGIN_SRC d
-  } else if (line_occur["heading"] > State.off) {
-    /+ heading +/
-    debug(heading) {
-      writeln(line);
-    }
-    an_object[an_object_key] ~= line ~= "\n";
-    ++line_occur["heading"];
-#+END_SRC
-
-******** line exist: para                                       :para:
-
-#+name: abs_in_loop_body_not_block_obj
-#+BEGIN_SRC d
-  } else if (line_occur["para"] > State.off) {
-    /+ paragraph +/
-    debug(para) {
-      writeln(line);
-    }
-    an_object[an_object_key] ~= " " ~ line;
-    ++line_occur["para"];
-  }
-}
-#+END_SRC
-
-****** line empty, with block flag
-
-#+name: abs_in_loop_body_not_block_obj_line_empty_blocks_flags
-#+BEGIN_SRC d
-_block_flag_line_empty_(
-  line,
-  an_object,
-  the_document_body_section,
-  bookindex_unordered_hashes,
-  obj_cite_number,
-  comp_obj_heading,
-  cntr,
-  type,
-  obj_cite_number_poem,
-  dochead_make_aa
-);
-#+END_SRC
-
-****** line empty [+1]
-******* assert line empty                                      :assert:
-
-#+name: abs_in_loop_body_not_block_obj_line_empty
-#+BEGIN_SRC d
-assert(
-  line.empty,
-  "line should be empty"
-);
-assert(
-  (type["blocks"] == State.off),
-  "code block status: none"
-);
-#+END_SRC
-
-******* heading object                                 :heading:object:
-
-#+name: abs_in_loop_body_not_block_obj_line_empty
-#+BEGIN_SRC d
-if ((type["heading"] == State.on)
-&& (line_occur["heading"] > State.off)) {
-  /+ heading object (current line empty) +/
-  obj_cite_number = (to!int(an_object["lev_markup_number"]) == 0)
-  ? (ocn_emit(3))
-  : (obj_cite_number = ocn_emit(type["ocn_status"]));
-  an_object["bookindex_nugget"] =
-    ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
-  bookindex_unordered_hashes =
-    bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
-  an_object["is"] = "heading";
-  an_object_key="body_nugget";
-  auto substantive_object_and_anchor_tags_tuple =
-    obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-  an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-  anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-  if (to!int(an_object["lev_markup_number"]) == 4) {
-    segment_anchor_tag_that_object_belongs_to = anchor_tags[0];
-    segment_anchor_tag_that_object_belongs_to_uri = anchor_tags[0] ~ ".fnSuffix";
-    anchor_tag_ = anchor_tags[0];
-  } else if (to!int(an_object["lev_markup_number"]) > 4) {
-    segment_anchor_tag_that_object_belongs_to = anchor_tag_;
-    segment_anchor_tag_that_object_belongs_to_uri = anchor_tag_ ~ ".fnSuffix#" ~ to!string(obj_cite_number);
-  } else if (to!int(an_object["lev_markup_number"]) < 4) {
-    segment_anchor_tag_that_object_belongs_to = "";
-    segment_anchor_tag_that_object_belongs_to_uri = "";
-  }
-  /+ (incrementally build toc) table of contents here! +/
-  _anchor_tag=to!string(obj_cite_number);
-  the_table_of_contents_section = obj_im.table_of_contents_gather_headings(
-    an_object,
-    dochead_make_aa,
-    segment_anchor_tag_that_object_belongs_to,
-    _anchor_tag,
-    lev4_subtoc,
-    the_table_of_contents_section,
-  );
-  if (an_object["lev_markup_number"] == "4") {
-    html_segnames ~= segment_anchor_tag_that_object_belongs_to;
-    html_segnames_ptr = html_segnames_ptr_cntr;
-    html_segnames_ptr_cntr++;
-  }
-  auto comp_obj_heading =
-    node_construct.node_emitter_heading(
-      an_object["substantive"],                     // string
-      an_object["lev"],                             // string
-      an_object["lev_markup_number"],               // string
-      an_object["lev_collapsed_number"],            // string
-      segment_anchor_tag_that_object_belongs_to,    // string
-      obj_cite_number,                              // int
-      cntr,                                         // int
-      heading_ptr,                                  // int
-      lv_ancestors,                                 // string[]
-      an_object["is"],                              // string
-      html_segnames_ptr,                            // int
-    );
-  ++heading_ptr;
-  debug(segments) {
-    writeln(an_object["lev_markup_number"]);
-    writeln(segment_anchor_tag_that_object_belongs_to);
-  }
-  the_document_body_section ~= comp_obj_heading;
-  // track previous heading and make assertions
-  debug(objectrelated1) { // check
-    writeln(line);
-  }
-  _common_reset_(line_occur, an_object, type);
-  an_object.remove("lev");
-  an_object.remove("lev_markup_number");
-  processing.remove("verse");
-  ++cntr;
-#+END_SRC
-
-******* paragraph object                             :paragraph:object:
-
-#+name: abs_in_loop_body_not_block_obj_line_empty
-#+BEGIN_SRC d
-} else if ((type["para"] == State.on) && (line_occur["para"] > State.off)) {
-  /+ paragraph object (current line empty) +/
-  obj_cite_number = ocn_emit(type["ocn_status"]);
-  an_object["bookindex_nugget"] =
-    ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
-  bookindex_unordered_hashes =
-    bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
-  an_object["is"] = "para";
-  auto comp_obj_heading =
-    node_construct.node_location_emitter(
-      content_non_header,
-      segment_anchor_tag_that_object_belongs_to,
-      obj_cite_number,
-      cntr,
-      heading_ptr-1,
-      an_object["is"],
-    );
-  auto substantive_object_and_anchor_tags_tuple =
-    obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-  an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-  anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-  comp_obj_para                       = comp_obj_para.init;
-  comp_obj_para.use                   = "body";
-  comp_obj_para.is_of                 = "para";
-  comp_obj_para.is_a                  = "para";
-  comp_obj_para.text                  = to!string(an_object["substantive"]).strip;
-  comp_obj_para.ocn                   = obj_cite_number;
-  comp_obj_para.obj_cite_number       = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-  comp_obj_para.indent_hang           = indent["hang_position"];
-  comp_obj_para.indent_base           = indent["base_position"];
-  comp_obj_para.bullet                = bullet;
-  comp_obj_para.anchor_tags           = anchor_tags;
-  the_document_body_section           ~= comp_obj_para;
-  _common_reset_(line_occur, an_object, type);
-  indent=[
-    "hang_position" : 0,
-    "base_position" : 0,
-  ];
-  bullet = false;
-  processing.remove("verse");
-  ++cntr;
-} else {
-  assert(
-    line == null,
-    "line variable should be empty, should not occur"
-  );
-  // check what happens when paragraph separated by 2 newlines
-}
-#+END_SRC
-
-** close non code objects (regular text)
-*** regular text objects                                   :text:paragraph:
-
-#+name: abs_in_loop_body_01
-#+BEGIN_SRC d
-/+ unless (the_document_body_section.length == 0) ? +/
-if (the_document_body_section.length > 0) {
-  if (((the_document_body_section[$-1].is_a == "para")
-  || (the_document_body_section[$-1].is_a == "heading")
-  || (the_document_body_section[$-1].is_a == "group"))
-  && (the_document_body_section.length > previous_length)
-) {
-    if ((the_document_body_section[$-1].is_a == "heading")
-    && (the_document_body_section[$-1].heading_lev_markup < 5)) {
-      type["biblio_section"] = State.off;
-      type["glossary_section"] = State.off;
-      type["blurb_section"] = State.off;
-    }
-    previous_length = to!int(the_document_body_section.length);
-    if (
-      match(the_document_body_section[$-1].text,
-      rgx.inline_notes_delimiter_al_regular_number_note)
-    ) {
-      previous_count=to!int(the_document_body_section.length -1);
-      note_section.gather_notes_for_endnote_section(
-        the_document_body_section,
-        segment_anchor_tag_that_object_belongs_to,
-        to!int(the_document_body_section.length-1),
-      );
-    }
-  }
-}
-#+END_SRC
-
-** _3. post main-loop processing_                                       :post:
-/+
-  Backmatter:
-  - endnotes
-  - glossary
-  - bibliography / references
-  - book index
-  - blurb
-+/
-
-*** tie up preparation of document sections
-**** endnotes section (scroll & seg)                            :endnotes:
-
-#+name: abs_post
-#+BEGIN_SRC d
-auto en_tuple =
-  note_section.endnote_objects(obj_cite_number, opt_action_bool);
-static assert(!isTypeTuple!(en_tuple));
-auto the_endnotes_section = en_tuple[0];
-obj_cite_number = en_tuple[1];
-debug(endnotes) {
-  writefln(
-    "%s %s",
-    __LINE__,
-    the_endnotes_section.length
-  );
-  foreach (o; the_endnotes_section) {
-    writeln(o);
-  }
-}
-#+END_SRC
-
-**** no glossary section?                                       :glossary:
-
-#+name: abs_post
-#+BEGIN_SRC d
-if (an_object["glossary_nugget"].length == 0) {
-  comp_obj_heading_                       = comp_obj_heading_.init;
-  comp_obj_heading_.use                   = "empty";
-  comp_obj_heading_.is_of                 = "para";
-  comp_obj_heading_.is_a                  = "heading";
-  comp_obj_heading_.text                  = "(skip) there is no Glossary section";
-  comp_obj_heading_.ocn                   = 0;
-  comp_obj_heading_.obj_cite_number       = "";
-  comp_obj_heading_.marked_up_level       = "B";
-  comp_obj_heading_.heading_lev_markup    = 1;
-  comp_obj_heading_.heading_lev_collapsed = 1;
-  comp_obj_heading_.parent_ocn            = 1;
-  comp_obj_heading_.parent_lev_markup     = 0;
-  the_glossary_section                    ~= comp_obj_heading_;
-} else {
-  writeln("gloss");
-}
-debug(glossary) {
-  foreach (gloss; the_glossary_section) {
-    writeln(gloss.text);
-  }
-}
-#+END_SRC
-
-**** bibliography section (objects)                         :bibliography:
-
-#+name: abs_post
-#+BEGIN_SRC d
-auto biblio_unsorted_incomplete = biblio_arr_json.dup;
-auto biblio = Bibliography();
-auto biblio_ordered =
-  biblio._bibliography_(biblio_unsorted_incomplete, bib_arr_json);
-#+END_SRC
-
-#+name: abs_post
-#+BEGIN_SRC d
-if (biblio_ordered.length > 0) {
-  comp_obj_heading_                       = comp_obj_heading_.init;
-  comp_obj_heading_.use                   = "backmatter";
-  comp_obj_heading_.is_of                 = "para";
-  comp_obj_heading_.is_a                  = "heading";
-  comp_obj_heading_.text                  = "Bibliography";
-  comp_obj_heading_.ocn                   = 0;
-  comp_obj_heading_.obj_cite_number       = "";
-  comp_obj_heading_.marked_up_level       = "B";
-  comp_obj_heading_.heading_lev_markup    = 1;
-  comp_obj_heading_.heading_lev_collapsed = 1;
-  comp_obj_heading_.parent_ocn            = 1;
-  comp_obj_heading_.parent_lev_markup     = 0;
-  the_bibliography_section                ~= comp_obj_heading_;
-  // ---
-  comp_obj_heading_                       = comp_obj_heading_.init;
-  comp_obj_heading_.use                   = "backmatter";
-  comp_obj_heading_.is_of                 = "para";
-  comp_obj_heading_.is_a                  = "heading";
-  comp_obj_heading_.text                  = "Bibliography";
-  comp_obj_heading_.ocn                   = 0;
-  comp_obj_heading_.obj_cite_number       = "";
-  comp_obj_heading_.segment_anchor_tag    = "bibliography";
-  comp_obj_heading_.marked_up_level       = "1";
-  comp_obj_heading_.heading_lev_markup    = 4;
-  comp_obj_heading_.heading_lev_collapsed = 2;
-  comp_obj_heading_.parent_ocn            = 1;
-  comp_obj_heading_.parent_lev_markup     = 0;
-  comp_obj_heading_.anchor_tags           = ["bibliography"];
-  the_bibliography_section                ~= comp_obj_heading_;
-} else {
-  comp_obj_heading_                       = comp_obj_heading_.init;
-  comp_obj_heading_.use                   = "empty";
-  comp_obj_heading_.is_of                 = "para";
-  comp_obj_heading_.is_a                  = "heading";
-  comp_obj_heading_.text                  = "(skip) there is no Bibliography";
-  comp_obj_heading_.ocn                   = 0;
-  comp_obj_heading_.obj_cite_number       = "";
-  comp_obj_heading_.marked_up_level       = "B";
-  comp_obj_heading_.heading_lev_markup    = 1;
-  comp_obj_heading_.heading_lev_collapsed = 1;
-  comp_obj_heading_.parent_ocn            = 1;
-  comp_obj_heading_.parent_lev_markup     = 0;
-  the_bibliography_section                ~= comp_obj_heading_;
-}
-#+END_SRC
-
-***** format biblio string
-
-#+name: abs_post
-#+BEGIN_SRC d
-string out_;
-foreach (entry; biblio_ordered) {
-  out_ = format(
-    "%s \"%s\"%s%s%s%s%s%s%s%s%s.",
-    ((entry["author"].str.empty) ? entry["editor"].str : entry["author"].str),
-    entry["fulltitle"].str,
-    ((entry["journal"].str.empty) ? "" : ", /{" ~ entry["journal"].str ~ "}/"),
-    ((entry["volume"].str.empty) ? "" : ", " ~ entry["volume"].str),
-    ((entry["in"].str.empty) ? "" : ", " ~ entry["in"].str),
-    ((!(entry["author"].str.empty) && (!(entry["editor"].str.empty))) ? entry["editor"].str : ""),
-    ", " ~ entry["year"].str,
-    ((entry["pages"].str.empty) ? "" : ", " ~ entry["pages"].str),
-    ((entry["publisher"].str.empty) ? "" : ", " ~ entry["publisher"].str),
-    ((entry["place"].str.empty) ? "" : ", " ~ entry["place"].str),
-    ((entry["url"].str.empty) ? "" : ", [" ~ entry["url"].str ~ "]"),
-  );
-  comp_obj_para                       = comp_obj_para.init;
-  comp_obj_para.use                   = "backmatter";
-  comp_obj_para.is_of                 = "para";
-  comp_obj_para.is_a                  = "bibliography";
-  comp_obj_para.text                  = to!string(out_).strip;
-  comp_obj_para.ocn                   = 0;
-  comp_obj_para.obj_cite_number       = "";
-  comp_obj_para.indent_hang           = 0;
-  comp_obj_para.indent_base           = 1;
-  comp_obj_para.bullet                = bullet;
-  comp_obj_para.anchor_tags           = anchor_tags;
-  the_bibliography_section            ~= comp_obj_para;
-}
-#+END_SRC
-
-#+name: abs_post
-#+BEGIN_SRC d
-debug(bibliosection) {
-  foreach (o; the_bibliography_section) {
-    writeln(o.text);
-  }
-}
-#+END_SRC
-
-***** bibliography components
-
-auto biblio_entry_tags_jsonstr =  `{
-  "is"                   : "",
-  "sortby_deemed_author_year_title"  : "",
-  "deemed_author"                    : "",
-  "author_raw"                       : "",
-  "author"                           : "",
-  "author_arr"                       : [ "" ],
-  "editor_raw"                       : "",
-  "editor"                           : "",
-  "editor_arr"                       : [ "" ],
-  "title"                            : "",
-  "subtitle"                         : "",
-  "fulltitle"                        : "",
-  "language"                         : "",
-  "trans"                            : "",
-  "src"                              : "",
-  "journal"                          : "",
-  "in"                               : "",
-  "volume"                           : "",
-  "edition"                          : "",
-  "year"                             : "",
-  "place"                            : "",
-  "publisher"                        : "",
-  "url"                              : "",
-  "pages"                            : "",
-  "note"                             : "",
-  "short_name"                       : "",
-  "id"                               : ""
-}`; // is: book, article, magazine, newspaper, blog, other
-
-**** bookindex section (scroll & seg)                         :book:index:
-
-#+name: abs_post
-#+BEGIN_SRC d
-auto bi = BookIndexReportSection();
-auto bi_tuple =
-  bi.bookindex_build_abstraction_section(
-    bookindex_unordered_hashes,
-    obj_cite_number,
-    segment_anchor_tag_that_object_belongs_to,
-    opt_action_bool,
-  );
-static assert(!isTypeTuple!(bi_tuple));
-auto the_bookindex_section = bi_tuple[0];
-obj_cite_number = bi_tuple[1];
-debug(bookindex) {
-  foreach (bi_entry; the_bookindex_section["seg"]) {
-    writeln(bi_entry);
-  }
-}
-#+END_SRC
-
-**** no blurb section?                                             :blurb:
-
-#+name: abs_post
-#+BEGIN_SRC d
-if (an_object["blurb_nugget"].length == 0) {
-  comp_obj_heading_                       = comp_obj_heading_.init;
-  comp_obj_heading_.use                   = "empty";
-  comp_obj_heading_.is_of                 = "para";
-  comp_obj_heading_.is_a                  = "heading";
-  comp_obj_heading_.text                  = "(skip) there is no Blurb section";
-  comp_obj_heading_.ocn                   = 0;
-  comp_obj_para.obj_cite_number           = "";
-  comp_obj_heading_.segment_anchor_tag    = "";
-  comp_obj_heading_.marked_up_level       = "B";
-  comp_obj_heading_.heading_lev_markup    = 1;
-  comp_obj_heading_.heading_lev_collapsed = 1;
-  comp_obj_heading_.parent_ocn            = 1;
-  comp_obj_heading_.parent_lev_markup     = 0;
-  the_blurb_section                       ~= comp_obj_heading_;
-}
-debug(blurb) {
-  foreach (blurb; the_blurb_section) {
-    writeln(blurb.text);
-  }
-}
-#+END_SRC
-
-**** toc backmatter, table of contents backmatter (scroll & seg) :contents:
-
-#+name: abs_post
-#+BEGIN_SRC d
-indent=[
-  "hang_position" : 1,
-  "base_position" : 1,
-];
-comp_obj_toc                       = comp_obj_toc.init;
-comp_obj_toc.use                   = "frontmatter";
-comp_obj_toc.is_of                 = "para";
-comp_obj_toc.is_a                  = "toc";
-comp_obj_toc.ocn                   = 0;
-comp_obj_toc.obj_cite_number       = "";
-comp_obj_toc.indent_hang           = indent["hang_position"];
-comp_obj_toc.indent_base           = indent["base_position"];
-comp_obj_toc.bullet                = false;
-if (the_endnotes_section.length > 1) {
-  toc_txt_ = format(
-    "{ %s }%s../%s.fnSuffix",
-    "Endnotes",
-    mkup.mark_internal_site_lnk,
-    "endnotes",               // segment_anchor_tag_that_object_belongs_to
-  );
-  toc_txt_= munge.url_links(toc_txt_);
-  comp_obj_toc.text                       = to!string(toc_txt_).strip;
-  the_table_of_contents_section["seg"]    ~= comp_obj_toc;
-}
-if (the_glossary_section.length > 1) {
-  toc_txt_ = format(
-    "{ %s }%s../%s.fnSuffixs",
-    "Glossary",
-    mkup.mark_internal_site_lnk,
-    "glossary",               // segment_anchor_tag_that_object_belongs_to
-  );
-  toc_txt_= munge.url_links(toc_txt_);
-  comp_obj_toc.text                       = to!string(toc_txt_).strip;
-  the_table_of_contents_section["seg"]    ~= comp_obj_toc;
-  toc_txt_ = format(
-    "{ %s }#%s",
-    "Glossary",
-    "glossary",               // _anchor_tag
-  );
-  toc_txt_= munge.url_links(toc_txt_);
-  comp_obj_toc.text                       = to!string(toc_txt_).strip;
-  the_table_of_contents_section["scroll"] ~= comp_obj_toc;
-}
-if (the_bibliography_section.length > 1){
-  toc_txt_ = format(
-    "{ %s }%s../%s.fnSuffix",
-    "Bibliography",
-    mkup.mark_internal_site_lnk,
-    "bibliography",           // segment_anchor_tag_that_object_belongs_to
-  );
-  toc_txt_= munge.url_links(toc_txt_);
-  comp_obj_toc.text                       = to!string(toc_txt_).strip;
-  the_table_of_contents_section["seg"]    ~= comp_obj_toc;
-
-  toc_txt_ = format(
-    "{ %s }#%s",
-    "Bibliography",
-    "bibliography",           // _anchor_tag
-  );
-  toc_txt_= munge.url_links(toc_txt_);
-  comp_obj_toc.text                       = to!string(toc_txt_).strip;
-  the_table_of_contents_section["scroll"] ~= comp_obj_toc;
-}
-if (the_bookindex_section["seg"].length > 1) {
-  toc_txt_ = format(
-    "{ %s }%s../%s.fnSuffix",
-    "Book Index",
-    mkup.mark_internal_site_lnk,
-    "bookindex",              // segment_anchor_tag_that_object_belongs_to
-  );
-  toc_txt_= munge.url_links(toc_txt_);
-  comp_obj_toc.text                       = to!string(toc_txt_).strip;
-  the_table_of_contents_section["seg"]    ~= comp_obj_toc;
-}
-if (the_bookindex_section["scroll"].length > 1) {
-  toc_txt_ = format(
-    "{ %s }#%s",
-    "Book Index",
-    "bookindex",              // _anchor_tag
-  );
-  toc_txt_= munge.url_links(toc_txt_);
-  comp_obj_toc.text                       = to!string(toc_txt_).strip;
-  the_table_of_contents_section["scroll"] ~= comp_obj_toc;
-}
-if (the_blurb_section.length > 1) {
-  toc_txt_ = format(
-    "{ %s }%s../%s.fnSuffix",
-    "Blurb",
-    mkup.mark_internal_site_lnk,
-    "blurb",                  // segment_anchor_tag_that_object_belongs_to
-  );
-  toc_txt_= munge.url_links(toc_txt_);
-  comp_obj_toc.text                       = to!string(toc_txt_).strip;
-  the_table_of_contents_section["seg"]    ~= comp_obj_toc;
-  toc_txt_ = format(
-    "{ %s }#%s",
-    "Blurb",
-    "blurb",                  // _anchor_tag
-  );
-  toc_txt_= munge.url_links(toc_txt_);
-  comp_obj_toc.text                       = to!string(toc_txt_).strip;
-  the_table_of_contents_section["scroll"] ~= comp_obj_toc;
-}
-debug(toc) {
-  writefln(
-    "%s %s",
-    __LINE__,
-    the_table_of_contents_section["seg"].length
-  );
-  foreach (toc_linked_heading; the_table_of_contents_section["seg"]) {
-    writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text);
-  }
-}
-debug(tocscroll) {
-  writefln(
-    "%s %s",
-    __LINE__,
-    the_table_of_contents_section["seg"].length
-  );
-  foreach (toc_linked_heading; the_table_of_contents_section["scroll"]) {
-    writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text);
-  }
-}
-#+END_SRC
-
-**** doc head (separate document head from body, make space for toc)
-
-#+name: abs_post
-#+BEGIN_SRC d
-the_document_head_section ~= the_document_body_section[0];
-the_document_body_section=the_document_body_section[1..$];
-#+END_SRC
-
-*** TODO minor loops                                                 :post:
-**** 1. loop: backmatter loop up to lev4: html_segnames, set backmatter pointers
-
-could optimise by
-- skipping second and third pass unless the output html seg or epub is being made!
-NOTE there are issues attempting to do this on first pass
-- as
-  - backmatter is created out of sequence and
-  - it is not certain which are present
-it is quite neat to have all in one place as we have here:
-
-#+name: abs_post
-#+BEGIN_SRC d
-if (the_endnotes_section.length > 1) {
-  html_segnames ~= "endnotes";
-  html_segnames_ptr = html_segnames_ptr_cntr;
-  foreach (ref section; the_endnotes_section) {
-    if (section.heading_lev_markup == 4) {
-      section.ptr_html_segnames = html_segnames_ptr;
-      break;
-    }
-  }
-  html_segnames_ptr_cntr++;
-}
-if (the_glossary_section.length > 1) {
-  html_segnames ~= "glossary";
-  html_segnames_ptr = html_segnames_ptr_cntr;
-  foreach (ref section; the_glossary_section) {
-    if (section.heading_lev_markup == 4) {
-      section.ptr_html_segnames = html_segnames_ptr;
-      break;
-    }
-  }
-  html_segnames_ptr_cntr++;
-}
-if (the_bibliography_section.length > 1) {
-  html_segnames ~= "bibliography";
-  html_segnames_ptr = html_segnames_ptr_cntr;
-  foreach (ref section; the_bibliography_section) {
-    if (section.heading_lev_markup == 4) {
-      section.ptr_html_segnames = html_segnames_ptr;
-      break;
-    }
-  }
-  html_segnames_ptr_cntr++;
-}
-if (the_bookindex_section["scroll"].length > 1) {
-  html_segnames ~= "bookindex";
-  html_segnames_ptr = html_segnames_ptr_cntr;
-  foreach (ref section; the_bookindex_section["scroll"]) {
-    if (section.heading_lev_markup == 4) {
-      section.ptr_html_segnames = html_segnames_ptr;
-      break;
-    }
-  }
-  foreach (ref section; the_bookindex_section["seg"]) {
-    if (section.heading_lev_markup == 4) {
-      section.ptr_html_segnames = html_segnames_ptr;
-      break;
-    }
-  }
-  html_segnames_ptr_cntr++;
-}
-if (the_blurb_section.length > 1) {
-  html_segnames ~= "blurb";
-  html_segnames_ptr = html_segnames_ptr_cntr;
-  foreach (ref section; the_blurb_section) {
-    if (section.heading_lev_markup == 4) {
-      section.ptr_html_segnames = html_segnames_ptr;
-      break;
-    }
-  }
-  html_segnames_ptr_cntr++;
-}
-#+END_SRC
-
-**** 2. loop: all objects structural relationships (sections, segments, objects)
-
-needed for DOM structure, segnames & subtoc, backmatter pointers
-
-if used minimally only for DOM structure, segnames, subtoc, could optimise by
-- skipping second and third pass unless the output html seg or epub is being
-  made!
-
-or could conveniently be used more extensively for ancestors as well (though
-this can be extracted earlier)
-
-Build here:
-- DOM structure
-- ancestors and decendants
-
-(as needed) up to document heading 1~, lev4 html:
-
-during the third pass all previous and next segment names are known
-next are not yet known for backmatter during the second pass
-
-#+name: abs_post
-#+BEGIN_SRC d
-foreach (ref obj; the_document_head_section) {
-  if (obj.is_a == "heading") {
-    debug(dom) {
-      writeln(obj.text);
-    }
-    if ((opt_action_bool["html"])
-    || (opt_action_bool["html_scroll"])
-    || (opt_action_bool["html_seg"])
-    || (opt_action_bool["epub"])) {
-      obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
-      obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
-    }
-    heading_ancestors(obj, lv_ancestors);
-  }
-}
-if (the_table_of_contents_section["scroll"].length > 1) {
-  dom_markedup_buffer = dom_markedup.dup;
-  dom_collapsed_buffer = dom_collapsed.dup;
-  foreach (ref obj; the_table_of_contents_section["scroll"]) {
-    if (obj.is_a == "heading") {
-      if (obj.heading_lev_markup == 4) {
-        obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
-      }
-      if ((opt_action_bool["html"])
-      || (opt_action_bool["html_scroll"])
-      || (opt_action_bool["html_seg"])
-      || (opt_action_bool["epub"])) {
-        obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
-        obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
-      }
-      heading_ancestors(obj, lv_ancestors);
-    }
-  }
-  dom_markedup = dom_markedup_buffer.dup;
-  dom_collapsed = dom_collapsed_buffer.dup;
-  foreach (ref obj; the_table_of_contents_section["seg"]) {
-    if (obj.is_a == "heading") {
-      debug(dom) {
-        writeln(obj.text);
-      }
-      if (obj.heading_lev_markup == 4) {
-        obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
-      }
-      if ((opt_action_bool["html"])
-      || (opt_action_bool["html_scroll"])
-      || (opt_action_bool["html_seg"])
-      || (opt_action_bool["epub"])) {
-        obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
-        obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
-      }
-      heading_ancestors(obj, lv_ancestors);
-    }
-  }
-}
-/+ multiple 1~ levels, loop through document body +/
-if (the_document_body_section.length > 1) {
-  foreach (ref obj; the_document_body_section) {
-    if (obj.is_a == "heading") {
-      debug(dom) {
-        writeln(obj.text);
-      }
-      if (obj.heading_lev_markup == 4) {
-        obj.lev4_subtoc = lev4_subtoc[obj.segment_anchor_tag];
-        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-        if (html_segnames.length > obj.ptr_html_segnames + 1) {
-          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-        }
-        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
-      }
-      if ((opt_action_bool["html"])
-      || (opt_action_bool["html_scroll"])
-      || (opt_action_bool["html_seg"])
-      || (opt_action_bool["epub"])) {
-        obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
-        obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
-      }
-      heading_ancestors(obj, lv_ancestors);
-    }
-  }
-}
-/+ optional only one 1~ level +/
-if (the_endnotes_section.length > 1) {
-  dom_markedup_buffer = dom_markedup.dup;
-  dom_collapsed_buffer = dom_collapsed.dup;
-  dom_markedup = dom_markedup_buffer.dup;
-  dom_collapsed = dom_collapsed_buffer.dup;
-  foreach (ref obj; the_endnotes_section) {
-    if (obj.is_a == "heading") {
-      debug(dom) {
-        writeln(obj.text);
-      }
-      if (obj.heading_lev_markup == 4) {
-        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-        if (html_segnames.length > obj.ptr_html_segnames + 1) {
-          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-        }
-        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
-      }
-      if ((opt_action_bool["html"])
-      || (opt_action_bool["html_scroll"])
-      || (opt_action_bool["html_seg"])
-      || (opt_action_bool["epub"])) {
-        obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
-        obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
-      }
-      heading_ancestors(obj, lv_ancestors);
-    }
-  }
-}
-/+ optional only one 1~ level +/
-if (the_glossary_section.length > 1) {
-  foreach (ref obj; the_glossary_section) {
-    if (obj.is_a == "heading") {
-      debug(dom) {
-        writeln(obj.text);
-      }
-      if (obj.heading_lev_markup == 4) {
-        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-        if (html_segnames.length > obj.ptr_html_segnames + 1) {
-          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-        }
-        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
-      }
-      if ((opt_action_bool["html"])
-      || (opt_action_bool["html_scroll"])
-      || (opt_action_bool["html_seg"])
-      || (opt_action_bool["epub"])) {
-        obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
-        obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
-      }
-      heading_ancestors(obj, lv_ancestors);
-    }
-  }
-}
-/+ optional only one 1~ level +/
-if (the_bibliography_section.length > 1) {
-  foreach (ref obj; the_bibliography_section) {
-    if (obj.is_a == "heading") {
-      debug(dom) {
-        writeln(obj.text);
-      }
-      if (obj.heading_lev_markup == 4) {
-        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-        if (html_segnames.length > obj.ptr_html_segnames + 1) {
-          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-        }
-        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
-      }
-      if ((opt_action_bool["html"])
-      || (opt_action_bool["html_scroll"])
-      || (opt_action_bool["html_seg"])
-      || (opt_action_bool["epub"])) {
-        obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
-        obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
-      }
-      heading_ancestors(obj, lv_ancestors);
-    }
-  }
-}
-/+ optional only one 1~ level +/
-if (the_bookindex_section["scroll"].length > 1) {
-  dom_markedup_buffer = dom_markedup.dup;
-  dom_collapsed_buffer = dom_collapsed.dup;
-  foreach (ref obj; the_bookindex_section["scroll"]) {
-    if (obj.is_a == "heading") {
-      debug(dom) {
-      // writeln(obj.text);
-      }
-      if (obj.heading_lev_markup == 4) {
-        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-        if (html_segnames.length > obj.ptr_html_segnames + 1) {
-          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-        }
-        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
-      }
-      if ((opt_action_bool["html"])
-      || (opt_action_bool["html_scroll"])
-      || (opt_action_bool["html_seg"])
-      || (opt_action_bool["epub"])) {
-        obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
-        obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
-      }
-      heading_ancestors(obj, lv_ancestors);
-    }
-  }
-  dom_markedup = dom_markedup_buffer.dup;
-  dom_collapsed = dom_collapsed_buffer.dup;
-  foreach (ref obj; the_bookindex_section["seg"]) {
-    if (obj.is_a == "heading") {
-      debug(dom) {
-        writeln(obj.text);
-      }
-      if (obj.heading_lev_markup == 4) {
-        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-        if (html_segnames.length > obj.ptr_html_segnames + 1) {
-          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-        }
-        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
-      }
-      if ((opt_action_bool["html"])
-      || (opt_action_bool["html_scroll"])
-      || (opt_action_bool["html_seg"])
-      || (opt_action_bool["epub"])) {
-        obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
-        obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
-      }
-      heading_ancestors(obj, lv_ancestors);
-    }
-  }
-}
-/+ optional only one 1~ level +/
-if (the_blurb_section.length > 1) {
-  foreach (ref obj; the_blurb_section) {
-    if (obj.is_a == "heading") {
-      debug(dom) {
-        writeln(obj.text);
-      }
-      if (obj.heading_lev_markup == 4) {
-        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-        if (html_segnames.length > obj.ptr_html_segnames + 1) {
-          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-        }
-        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
-      }
-      if ((opt_action_bool["html"])
-      || (opt_action_bool["html_scroll"])
-      || (opt_action_bool["html_seg"])
-      || (opt_action_bool["epub"])) {
-        obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
-        obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
-      }
-      heading_ancestors(obj, lv_ancestors);
-    }
-  }
-  /+ TODO
-    - note create/insert heading object sole purpose eof close all open tags
-      sort out:
-      - obj.dom_markedup = dom_markedup;
-      - obj.dom_collapsed = dom_collapsed;
-  +/
-  dom_markedup = dom_set_markup_tags(dom_markedup, 0);
-  dom_collapsed = dom_set_collapsed_tags(dom_collapsed, 0);
-  comp_obj_heading_                       = comp_obj_heading_.init;
-  comp_obj_heading_.use                   = "empty";
-  comp_obj_heading_.is_of                 = "para";
-  comp_obj_heading_.is_a                  = "heading";
-  // comp_obj_heading_.text                  = "(skip) this is the DOM tail";
-  comp_obj_heading_.ocn                   = 0;
-  comp_obj_para.obj_cite_number           = "";
-  comp_obj_heading_.segment_anchor_tag    = "";
-  comp_obj_heading_.marked_up_level       = "";
-  comp_obj_heading_.heading_lev_markup    = 9;
-  comp_obj_heading_.heading_lev_collapsed = 9;
-  comp_obj_heading_.parent_ocn            = 0;
-  comp_obj_heading_.parent_lev_markup     = 0;
-  comp_obj_heading_.dom_markedup          = dom_markedup.dup;
-  comp_obj_heading_.dom_collapsed         = dom_collapsed.dup;
-  the_dom_tail_section                    ~= comp_obj_heading_;
-}
-#+END_SRC
-
-** _4. return document tuple_                                           :post:
-*** the document                                                 :document:
-
-#+name: abs_post
-#+BEGIN_SRC d
-auto document_the = [
-  "head":             the_document_head_section,
-  "toc_seg":          the_table_of_contents_section["seg"],
-  "toc_scroll":       the_table_of_contents_section["scroll"],
-  /+ substantive/body: +/
-  "body":             the_document_body_section,
-  /+ backmatter: +/
-  "endnotes":         the_endnotes_section,
-  "glossary":         the_glossary_section,
-  "bibliography":     the_bibliography_section,
-  "bookindex_scroll": the_bookindex_section["scroll"],
-  "bookindex_seg":    the_bookindex_section["seg"],
-  "blurb":            the_blurb_section,
-  /+ dom tail only +/
-  "tail":             the_dom_tail_section,
-];
-#+END_SRC
-
-*** document _section keys_ sequence
-
-#+name: abs_post
-#+BEGIN_SRC d
-string[][string] document_section_keys_sequenced = [
-  "seg":    ["head", "toc_seg", "body",],
-  "scroll": ["head", "toc_scroll", "body",]
-];
-if (document_the["endnotes"].length > 1) {
-  document_section_keys_sequenced["seg"]    ~= "endnotes";
-  document_section_keys_sequenced["scroll"] ~= "endnotes";
-}
-if (document_the["glossary"].length > 1) {
-  document_section_keys_sequenced["seg"]    ~= "glossary";
-  document_section_keys_sequenced["scroll"] ~= "glossary";
-}
-if (document_the["bibliography"].length > 1) {
-  document_section_keys_sequenced["seg"]    ~= "bibliography";
-  document_section_keys_sequenced["scroll"] ~= "bibliography";
-}
-if (document_the["bookindex_seg"].length > 1) {
-  document_section_keys_sequenced["seg"]    ~= "bookindex_seg";
-}
-if (document_the["bookindex_scroll"].length > 1) {
-  document_section_keys_sequenced["scroll"] ~= "bookindex_scroll";
-}
-if (document_the["blurb"].length > 1) {
-  document_section_keys_sequenced["seg"]    ~= "blurb";
-  document_section_keys_sequenced["scroll"] ~= "blurb";
-}
-if ((opt_action_bool["html"])
-|| (opt_action_bool["html_scroll"])
-|| (opt_action_bool["html_seg"])
-|| (opt_action_bool["epub"])) {
-  document_section_keys_sequenced["seg"]    ~= "tail";
-  document_section_keys_sequenced["scroll"] ~= "tail";
-}
-#+END_SRC
-
-*** clean out structure
-
-#+name: abs_post
-destroy(the_document_head_section);
-destroy(the_document_table_of_contents_section);
-destroy(the_document_body_section);
-destroy(the_endnotes_section);
-destroy(the_glossary_section);
-destroy(the_bibliography_section);
-destroy(the_bookindex_section);
-destroy(the_blurb_section);
-#+END_SRC
-
-*** [#A] _return document tuple_                               :return:tuple:
-
-#+name: abs_post
-#+BEGIN_SRC d
-auto t = tuple(
-  document_the,
-  document_section_keys_sequenced,
-  html_segnames,
-);
-return t;
-#+END_SRC
-
-** 5. Functions                                          :abstract:function:
-
-functions used in document abstraction
-
-*** set & resets                                                    :reset:
-**** object reset: remove (clean)                          :object:remove:
-
-#+name: abs_functions_object_reset
-#+BEGIN_SRC d
-auto object_reset(O)(ref O an_object) {
-  debug(asserts){
-    static assert(is(typeof(an_object) == string[string]));
-  }
-  an_object.remove("body_nugget");
-  an_object.remove("substantive");
-  an_object.remove("is");
-  an_object.remove("attrib");
-  an_object.remove("bookindex_nugget");
-}
-#+END_SRC
-
-**** set, initialize or re-initialize                                :set:
-
-#+name: abs_functions_header_set_common
-#+BEGIN_SRC d
-auto _common_reset_(L,O,T)(
-  ref L line_occur,
-  ref O an_object,
-  ref T type
-) {
-  debug(asserts){
-    static assert(is(typeof(line_occur) == int[string]));
-    static assert(is(typeof(an_object)  == string[string]));
-    static assert(is(typeof(type)       == int[string]));
-  }
-  line_occur["heading"] = State.off;
-  line_occur["para"]    = State.off;
-  type["heading"]       = State.off;
-  type["para"]          = State.off;
-  object_reset(an_object);
-}
-#+END_SRC
-
-*** check obj_cite_number status in document                          :ocn:
-
-#+name: abs_functions_ocn_status
-#+BEGIN_SRC d
-void _check_ocn_status_(L,T)(
-  L     line,
-  ref T type
-) {
-  debug(asserts){
-    static assert(is(typeof(line) == char[]));
-    static assert(is(typeof(type) == int[string]));
-  }
-  auto rgx = Rgx();
-  if ((!line.empty) && (type["ocn_status_multi_obj"] == TriState.off)) {
-    /+ not multi-line object, check whether obj_cite_number is on or turned off +/
-    if (matchFirst(line, rgx.obj_cite_number_block_marks)) {
-      /+ switch off obj_cite_number +/
-      if (matchFirst(line, rgx.obj_cite_number_off_block)) {
-        type["ocn_status_multi_obj"] = TriState.on;
-        debug(ocnoff) {
-          writeln(line);
-        }
-      }
-      if (matchFirst(line, rgx.obj_cite_number_off_block_dh)) {
-        type["ocn_status_multi_obj"] = TriState.closing;
-        debug(ocnoff) {
-          writeln(line);
-        }
-      }
-    } else {
-      if (type["ocn_status_multi_obj"] == TriState.off) {
-        if (matchFirst(line, rgx.obj_cite_number_off)) {
-          type["ocn_status"] = TriState.on;
-        } else if (matchFirst(line, rgx.obj_cite_number_off_dh)) {
-          type["ocn_status"] = TriState.closing;
-        } else {
-          type["ocn_status"] = TriState.off;
-        }
-      } else {
-        type["ocn_status"] =
-          type["ocn_status_multi_obj"];
-      }
-    }
-  } else if ((!line.empty) && (type["ocn_status_multi_obj"] > TriState.off)) {
-    if (matchFirst(line, rgx.obj_cite_number_off_block_close)) {
-      type["ocn_status_multi_obj"] = TriState.off;
-      type["ocn_status"] = TriState.off;
-      debug(ocnoff) {
-        writeln(line);
-      }
-    }
-  }
-}
-#+END_SRC
-
-*** block                                                           :block:
-**** block start (open) block                                      :start:
-***** function open for block starts
-
-#+name: abs_functions_block
-#+BEGIN_SRC d
-void _start_block_(L,T,N)(
-  L     line,
-  ref T type,
-  N     obj_cite_number_poem
-) {
-  debug(asserts){
-    static assert(is(typeof(line)                 == char[]));
-    static assert(is(typeof(type)                 == int[string]));
-    static assert(is(typeof(obj_cite_number_poem) == string[string]));
-  }
-#+END_SRC
-
-***** block (various) curly open                                  :curly:
-
-#+name: abs_functions_block
-#+BEGIN_SRC d
-  auto rgx = Rgx();
-  if (matchFirst(line, rgx.block_curly_code_open)) {
-    /+ curly code open +/
-    debug(code) {                              // code (curly) open
-      writefln(
-        "* [code curly] %s",
-        line
-      );
-    }
-    type["blocks"] = TriState.on;
-    type["code"] = TriState.on;
-    type["curly_code"] = TriState.on;
-  } else if (matchFirst(line, rgx.block_curly_poem_open)) {
-    /+ curly poem open +/
-    debug(poem) {                              // poem (curly) open
-      writefln(
-        "* [poem curly] %s",
-        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 (matchFirst(line, rgx.block_curly_group_open)) {
-    /+ curly group open +/
-    debug(group) {                             // group (curly) open
-      writefln(
-        "* [group curly] %s",
-        line
-      );
-    }
-    type["blocks"] = TriState.on;
-    type["group"] = TriState.on;
-    type["curly_group"] = TriState.on;
-  } else if (matchFirst(line, rgx.block_curly_block_open)) {
-    /+ curly block open +/
-    debug(block) {                             // block (curly) open
-      writefln(
-        "* [block curly] %s",
-        line
-      );
-    }
-    type["blocks"] = TriState.on;
-    type["block"] = TriState.on;
-    type["curly_block"] = TriState.on;
-  } else if (matchFirst(line, rgx.block_curly_quote_open)) {
-    /+ curly quote open +/
-    debug(quote) {                             // quote (curly) open
-      writefln(
-        "* [quote curly] %s",
-        line
-      );
-    }
-    type["blocks"] = TriState.on;
-    type["quote"] = TriState.on;
-    type["curly_quote"] = TriState.on;
-  } else if (matchFirst(line, rgx.block_curly_table_open)) {
-    /+ curly table open +/
-    debug(table) {                             // table (curly) open
-      writefln(
-        "* [table curly] %s",
-        line
-      );
-    }
-    type["blocks"] = TriState.on;
-    type["table"] = TriState.on;
-    type["curly_table"] = TriState.on;
-#+END_SRC
-
-***** block (various) tic open                                      :tic:
-
-#+name: abs_functions_block
-#+BEGIN_SRC d
-  } else if (matchFirst(line, rgx.block_tic_code_open)) {
-    /+ tic code open +/
-    debug(code) {                              // code (tic) open
-      writefln(
-        "* [code tic] %s",
-        line
-      );
-    }
-    type["blocks"] = TriState.on;
-    type["code"] = TriState.on;
-    type["tic_code"] = TriState.on;
-  } else if (matchFirst(line, rgx.block_tic_poem_open)) {
-    /+ tic poem open +/
-    debug(poem) {                              // poem (tic) open
-      writefln(
-        "* [poem tic] %s",
-        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 (matchFirst(line, rgx.block_tic_group_open)) {
-    /+ tic group open +/
-    debug(group) {                             // group (tic) open
-      writefln(
-        "* [group tic] %s",
-        line
-      );
-    }
-    type["blocks"] = TriState.on;
-    type["group"] = TriState.on;
-    type["tic_group"] = TriState.on;
-  } else if (matchFirst(line, rgx.block_tic_block_open)) {
-    /+ tic block open +/
-    debug(block) {                             // block (tic) open
-      writefln(
-        "* [block tic] %s",
-        line
-      );
-    }
-    type["blocks"] = TriState.on;
-    type["block"] = TriState.on;
-    type["tic_block"] = TriState.on;
-  } else if (matchFirst(line, rgx.block_tic_quote_open)) {
-    /+ tic quote open +/
-    debug(quote) {                             // quote (tic) open
-      writefln(
-        "* [quote tic] %s",
-        line
-      );
-    }
-    type["blocks"] = TriState.on;
-    type["quote"] = TriState.on;
-    type["tic_quote"] = TriState.on;
-  } else if (matchFirst(line, rgx.block_tic_table_open)) {
-    /+ tic table open +/
-    debug(table) {                             // table (tic) open
-      writefln(
-        "* [table tic] %s",
-        line
-      );
-    }
-    type["blocks"] = TriState.on;
-    type["table"] = TriState.on;
-    type["tic_table"] = TriState.on;
-  }
-#+END_SRC
-
-***** function close for block starts
-
-#+name: abs_functions_block
-#+BEGIN_SRC d
-}
-#+END_SRC
-
-**** block continue (an open block)                             :continue:
-***** code block (special status, deal with first)                 :code:
-
-#+name: abs_functions_block_code
-#+BEGIN_SRC d
-void _code_block_(L,O,T)(
-  ref L line,
-  ref O an_object,
-  ref T type
-) {
-  debug(asserts){
-    static assert(is(typeof(line)      == char[]));
-    static assert(is(typeof(an_object) == string[string]));
-    static assert(is(typeof(type)      == int[string]));
-  }
-  auto rgx = Rgx();
-  if (type["curly_code"] == TriState.on) {
-    if (matchFirst(line, rgx.block_curly_code_close)) {
-      debug(code) {                                    // code (curly) close
-        writeln(line);
-      }
-      type["blocks"] = TriState.closing;
-      type["code"] = TriState.closing;
-      type["curly_code"] = TriState.off;
-    } else {
-      debug(code) {                                    // code (curly) line
-        writeln(line);
-      }
-      an_object[an_object_key] ~= line ~= "\n";        // code (curly) line
-    }
-  } else if (type["tic_code"] == TriState.on) {
-    if (matchFirst(line, rgx.block_tic_close)) {
-      debug(code) {                                    // code (tic) close
-        writeln(line);
-      }
-      type["blocks"] = TriState.closing;
-      type["code"] = TriState.closing;
-      type["tic_code"] = TriState.off;
-    } else {
-      debug(code) {                                    // code (tic) line
-        writeln(line);
-      }
-      an_object[an_object_key] ~= line ~= "\n";        // code (tic) line
-    }
-  }
-}
-#+END_SRC
-
-***** biblio block                                               :biblio:
-****** biblio tag map
-
-#+name: abs_functions_block_biblio
-#+BEGIN_SRC d
-final string biblio_tag_map(A)(A abr) {
-  debug(asserts){
-    static assert(is(typeof(abr) == string));
-  }
-  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];
-}
-#+END_SRC
-
-******* +consider+
-
-#+name: none
-#+BEGIN_SRC d
-final string biblio_tag_map_(A)(A abr) {
-  debug(asserts){
-    static assert(is(typeof(abr) == string));
-  }
-  string name;
-  switch (abr) {
-  case "au":
-    name="author_raw";
-    break;
-  case "ed":
-    name="editor_raw";
-    break;
-  case "ti":
-    name="fulltitle";
-    break;
-  case "lng":
-    name="language";
-    break;
-  case "jo":
-    name="journal";
-    break;
-  case "vol":
-    name="volume";
-    break;
-  case "edn":
-    name="edition";
-    break;
-  case "yr":
-    name="year";
-    break;
-  case "pl":
-    name="place";
-    break;
-  case "pb":
-    name="publisher";
-    break;
-  case "pub":
-    name="publisher";
-    break;
-  case "pg":
-    name="pages";
-    break;
-  case "pgs":
-    name="pages";
-    break;
-  case "sn":
-    name="short_name";
-    break;
-  default:
-    name=abr;
-    break;
-  }
-  return name;
-}
-#+END_SRC
-
-****** biblio block
-
-#+name: abs_functions_block_biblio
-#+BEGIN_SRC d
-void _biblio_block_(
-  char[] line,
-  ref int[string] type,
-  ref int bib_entry,
-  ref string biblio_entry_str_json,
-  ref string[] biblio_arr_json
-) {
-  mixin SiSUbiblio;
-  auto jsn = BibJsnStr();
-  auto rgx = Rgx();
-  if (matchFirst(line, rgx.heading_biblio)) {
-    type["biblio_section"] = TriState.on;
-    type["blurb_section"] = State.off;
-    type["glossary_section"] = State.off;
-  }
-  if (line.empty) {
-    debug {
-      debug(biblioblock) {
-        writeln("---");
-      }
-      debug(biblioblockinclude) {
-        writeln(biblio_entry_str_json.length);
-      }
-    }
-    if ((bib_entry == State.off)
-    && (biblio_entry_str_json.empty)) {
-      bib_entry = State.on;
-      biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr;
-    } else if (!(biblio_entry_str_json.empty)) {
-      bib_entry = State.off;
-      if (!(biblio_entry_str_json == jsn.biblio_entry_tags_jsonstr)) {
-        auto biblio_entry = parseJSON(biblio_entry_str_json);
-        if (biblio_entry["fulltitle"].str.empty) {
-          writeln("check problem entry (Title missing): ", biblio_entry_str_json);
-        } else if ((biblio_entry["author_raw"].str.empty) && (biblio_entry["editor_raw"].str.empty)) {
-          writeln("check problem entry (No author and no editor): ", biblio_entry_str_json);
-        } else {
-          biblio_arr_json ~= biblio_entry_str_json;
-        }
-        biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr;
-      }
-    } else { // CHECK ERROR
-      writeln("?? 2. ERROR ", biblio_entry_str_json, "??");
-      biblio_entry_str_json = "";
-    }
-  } else if (matchFirst(line, rgx.biblio_tags)) {
-    debug(biblioblock) {
-      writeln(line);
-    }
-    auto bt = match(line, rgx.biblio_tags);
-    bib_entry = State.off;
-    st=to!string(bt.captures[1]);
-    auto header_tag_value=to!string(bt.captures[2]);
-    JSONValue j = parseJSON(biblio_entry_str_json);
-    biblio_tag_name = (match(st, rgx.biblio_abbreviations))
-      ? (biblio_tag_map(st))
-      : st;
-    j.object[biblio_tag_name] = header_tag_value;
-    debug(bibliounsortedcheckduplicates) {
-      writeln(biblio_tag_name, ": ", header_tag_value);
-      writeln("--");
-    }
-    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, "");
-      j["author"].str = tmp;
-      goto default;
-    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, "");
-      j["editor"].str = tmp;
-      goto default;
-    case "fulltitle": // title & subtitle
-      goto default;
-    default:
-      break;
-    }
-    auto s = j.toString();
-    debug(biblio1) {
-      writefln(
-        "* %s: %s\n%s",
-        biblio_tag_name,
-        biblio_tag_entry,
-        j[biblio_tag_name]
-      );
-    }
-    if ((match(line, rgx.comment))) {
-      writeln("ERROR", line, "COMMENT");
-      writeln("ERROR", s, "%%");
-    }
-    if (!(match(line, rgx.comment))) {
-      debug(biblioblockinclude) {
-        writeln(line);
-      }
-      biblio_entry_str_json = s;
-    } else {
-      biblio_entry_str_json = "";
-    }
-    header_tag_value="";
-  }
-}
-#+END_SRC
-
-***** TODO poem block, verse objects                         :poem:verse:
-
-why extra object stuff only in poem/verse?
-
-#+name: abs_functions_block_poem
-#+BEGIN_SRC d
-void _poem_block_(L,O,T,C,N,Ma)(
-  L     line,
-  ref O an_object,
-  ref T type,
-  ref C cntr,
-  N     obj_cite_number_poem,
-  Ma    dochead_make_aa,
-) {
-  debug(asserts){
-    static assert(is(typeof(line)                 == char[]));
-    static assert(is(typeof(an_object)            == string[string]));
-    static assert(is(typeof(type)                 == int[string]));
-    static assert(is(typeof(cntr)                 == int));
-    static assert(is(typeof(obj_cite_number_poem) == string[string]));
-    static assert(is(typeof(dochead_make_aa)      == string[string][string]));
-  }
-  auto rgx = Rgx();
-  if (type["curly_poem"] == TriState.on) {
-    if (matchFirst(line, rgx.block_curly_poem_close)) {
-      an_object[an_object_key]="verse";
-      debug(poem) {                               // poem (curly) close
-        writefln(
-          "* [poem curly] %s",
-          line
-        );
-      }
-      if (processing.length > 0) {
-        an_object[an_object_key] = processing["verse"];
-      }
-      debug(poem) {                               // poem (curly) close
-        writeln(__LINE__);
-        writefln(
-          "* %s %s",
-          obj_cite_number,
-          line
-        );
-      }
-      if (an_object.length > 0) {
-        debug(poem) {                             // poem (curly) close
-          writeln(
-            obj_cite_number,
-            an_object[an_object_key]
-          );
-        }
-        an_object["is"] = "verse";
-        auto substantive_object_and_anchor_tags_tuple =
-          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-        comp_obj_block                            = comp_obj_block.init;
-        comp_obj_block.use                        = "body";
-        comp_obj_block.is_of                      = "block";
-        comp_obj_block.is_a                       = "verse";
-        comp_obj_block.ocn                        = obj_cite_number;
-        comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-        comp_obj_block.text                       = an_object["substantive"];
-        the_document_body_section                 ~= comp_obj_block;
-        object_reset(an_object);
-        processing.remove("verse");
-        ++cntr;
-      }
-      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 =
-          ocn_emit(type["ocn_status"]);
-        type["verse_new"] = State.off;
-      } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) {
-        verse_line = TriState.off;
-        type["verse_new"] = State.on;
-      }
-      if (type["verse_new"] == State.on) {
-        verse_line=1;
-        an_object[an_object_key] = processing["verse"];
-        debug(poem) {                          // poem verse
-          writefln(
-            "* %s curly\n%s",
-            obj_cite_number,
-            an_object[an_object_key]
-          );
-        }
-        processing.remove("verse");
-        an_object["is"] = "verse";
-        auto comp_obj_location = node_construct.node_location_emitter(
-          content_non_header,
-          segment_anchor_tag_that_object_belongs_to,
-          obj_cite_number,
-          cntr,
-          heading_ptr-1,
-          an_object["is"]
-        );
-        auto substantive_object_and_anchor_tags_tuple =
-          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-        comp_obj_block                            = comp_obj_block.init;
-        comp_obj_block.use                        = "body";
-        comp_obj_block.is_of                      = "block";
-        comp_obj_block.is_a                       = "verse";
-        comp_obj_block.ocn                        = obj_cite_number;
-        comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-        comp_obj_block.text                       = an_object["substantive"];
-        the_document_body_section                 ~= comp_obj_block;
-        object_reset(an_object);
-        processing.remove("verse");
-        ++cntr;
-      }
-    }
-  } else if (type["tic_poem"] == TriState.on) {
-    if (auto m = matchFirst(line, rgx.block_tic_close)) { // tic_poem_close
-      an_object[an_object_key]="verse";
-      debug(poem) {                                       // poem (curly) close
-        writefln(
-          "* [poem tic] %s",
-          line
-        );
-      }
-      if (processing.length > 0) {
-        an_object[an_object_key] = processing["verse"];
-      }
-      if (an_object.length > 0) {
-        debug(poem) {                                     // poem (tic) close
-          writeln(__LINE__);
-          writeln(obj_cite_number, line);
-        }
-        processing.remove("verse");
-        an_object["is"] = "verse";
-        auto substantive_object_and_anchor_tags_tuple =
-          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-        comp_obj_block                            = comp_obj_block.init;
-        comp_obj_block.use                        = "body";
-        comp_obj_block.is_of                      = "block";
-        comp_obj_block.is_a                       = "verse";
-        comp_obj_block.ocn                        = obj_cite_number;
-        comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-        comp_obj_block.text                       = an_object["substantive"];
-        the_document_body_section                 ~= comp_obj_block;
-        obj_cite_number_poem["end"]               = to!string(obj_cite_number);
-        object_reset(an_object);
-        processing.remove("verse");
-        ++cntr;
-      }
-      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 =
-          ocn_emit(type["ocn_status"]);
-        type["verse_new"] = State.off;
-      } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) {
-        type["verse_new"] = State.on;
-        verse_line = TriState.off;
-      }
-      if (type["verse_new"] == State.on) {
-        verse_line=1;
-        an_object[an_object_key] = processing["verse"];
-        debug(poem) {                            // poem (tic) close
-          writefln(
-            "* %s tic\n%s",
-            obj_cite_number,
-            an_object[an_object_key]
-          );
-        }
-        processing.remove("verse");
-        an_object["is"] = "verse";
-        auto comp_obj_location =
-          node_construct.node_location_emitter(
-            content_non_header,
-            segment_anchor_tag_that_object_belongs_to,
-            obj_cite_number,
-            cntr,
-            heading_ptr-1,
-            an_object["is"]
-          );
-        auto substantive_object_and_anchor_tags_tuple =
-          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-        comp_obj_block                            = comp_obj_block.init;
-        comp_obj_block.use                        = "body";
-        comp_obj_block.is_of                      = "block";
-        comp_obj_block.is_a                       = "verse";
-        comp_obj_block.ocn                        = obj_cite_number;
-        comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-        comp_obj_block.text                       = an_object["substantive"];
-        the_document_body_section                 ~= comp_obj_block;
-        object_reset(an_object);
-        processing.remove("verse");
-        ++cntr;
-      }
-    }
-  }
-}
-#+END_SRC
-
-***** group block                                                 :group:
-
-#+name: abs_functions_block_group
-#+BEGIN_SRC d
-void _group_block_(L,O,T)(
-  ref L line,
-  ref O an_object,
-  ref T type
-) {
-  debug(asserts){
-    static assert(is(typeof(line)      == char[]));
-    static assert(is(typeof(an_object) == string[string]));
-    static assert(is(typeof(type)      == int[string]));
-  }
-  auto rgx = Rgx();
-  if (type["curly_group"] == State.on) {
-    if (matchFirst(line, rgx.block_curly_group_close)) {
-      debug(group) {                              // group (curly) close
-        writeln(line);
-      }
-      type["blocks"] = TriState.closing;
-      type["group"] = TriState.closing;
-      type["curly_group"] = TriState.off;
-    } else {
-      debug(group) {                              // group
-        writeln(line);
-      }
-      an_object[an_object_key] ~= line ~= "\n";   // build group array (or string)
-    }
-  } else if (type["tic_group"] == TriState.on) {
-    if (matchFirst(line, rgx.block_tic_close)) {
-      debug(group) {                              // group (tic) close
-        writeln(line);
-      }
-      type["blocks"] = TriState.closing;
-      type["group"] = TriState.closing;
-      type["tic_group"] = TriState.off;
-    } else {
-      debug(group) {                              // group
-        writeln(line);
-      }
-      an_object[an_object_key] ~= line ~= "\n";   // build group array (or string)
-    }
-  }
-}
-#+END_SRC
-
-***** block block                                                 :block:
-
-#+name: abs_functions_block_block
-#+BEGIN_SRC d
-void _block_block_(L,O,T)(
-  ref L line,
-  ref O an_object,
-  ref T type
-) {
-  debug(asserts){
-    static assert(is(typeof(line)      == char[]));
-    static assert(is(typeof(an_object) == string[string]));
-    static assert(is(typeof(type)      == int[string]));
-  }
-  auto rgx = Rgx();
-  if (type["curly_block"] == TriState.on) {
-    if (matchFirst(line, rgx.block_curly_block_close)) {
-      debug(block) {                             // block (curly) close
-        writeln(line);
-      }
-      type["blocks"] = TriState.closing;
-      type["block"] = TriState.closing;
-      type["curly_block"] = TriState.off;
-    } else {
-      debug(block) {                             // block
-        writeln(line);
-      }
-      an_object[an_object_key] ~= line ~= "\n";   // build block array (or string)
-    }
-  } else if (type["tic_block"] == TriState.on) {
-    if (matchFirst(line, rgx.block_tic_close)) {
-      debug(block) {                              // block (tic) close
-        writeln(line);
-      }
-      type["blocks"] = TriState.closing;
-      type["block"] = TriState.closing;
-      type["tic_block"] = TriState.off;
-    } else {
-      debug(block) {                             // block
-        writeln(line);
-      }
-      an_object[an_object_key] ~= line ~= "\n";   // build block array (or string)
-    }
-  }
-}
-#+END_SRC
-
-***** quote block                                                 :quote:
-
-#+name: abs_functions_block_quote
-#+BEGIN_SRC d
-void _quote_block_(L,O,T)(
-  ref L line,
-  ref O an_object,
-  ref T type
-) {
-  debug(asserts){
-    static assert(is(typeof(line)      == char[]));
-    static assert(is(typeof(an_object) == string[string]));
-    static assert(is(typeof(type)      == int[string]));
-  }
-  auto rgx = Rgx();
-  if (type["curly_quote"] == TriState.on) {
-    if (matchFirst(line, rgx.block_curly_quote_close)) {
-      debug(quote) {                              // quote (curly) close
-        writeln(line);
-      }
-      type["blocks"] = TriState.closing;
-      type["quote"] = TriState.closing;
-      type["curly_quote"] = TriState.off;
-    } else {
-      debug(quote) {
-        writeln(line);
-      }
-      an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string)
-    }
-  } else if (type["tic_quote"] == TriState.on) {
-    if (matchFirst(line, rgx.block_tic_close)) {
-      debug(quote) {                              // quote (tic) close
-        writeln(line);
-      }
-      type["blocks"] = TriState.closing;
-      type["quote"] = TriState.closing;
-      type["tic_quote"] = TriState.off;
-    } else {
-      debug(quote) {
-        writeln(line);
-      }
-      an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string)
-    }
-  }
-}
-#+END_SRC
-
-***** table block                                                 :table:
-
-#+name: abs_functions_block_table
-#+BEGIN_SRC d
-void _table_block_(L,O,T)(
-  ref L line,
-  ref O an_object,
-  ref T type
-) {
-  debug(asserts){
-    static assert(is(typeof(line)      == char[]));
-    static assert(is(typeof(an_object) == string[string]));
-    static assert(is(typeof(type)      == int[string]));
-  }
-  auto rgx = Rgx();
-  if (type["curly_table"] == TriState.on) {
-    if (matchFirst(line, rgx.block_curly_table_close)) {
-      debug(table) {                           // table (curly) close
-        writeln(line);
-      }
-      type["blocks"] = TriState.closing;
-      type["table"] = TriState.closing;
-      type["curly_table"] = TriState.off;
-    } else {
-      debug(table) {                           // table
-        writeln(line);
-      }
-      an_object[an_object_key] ~= line ~= "\n";           // build table array (or string)
-    }
-  } else if (type["tic_table"] == TriState.on) {
-    if (matchFirst(line, rgx.block_tic_close)) {
-      debug(table) {                           // table (tic) close
-        writeln(line);
-      }
-      type["blocks"] = TriState.closing;
-      type["table"] = TriState.closing;
-      type["tic_table"] = TriState.off;
-    } else {
-      debug(table) {                           // table
-        writeln(line);
-      }
-      an_object[an_object_key] ~= line ~= "\n";           // build table array (or string)
-    }
-  }
-}
-#+END_SRC
-
-**** block end (close an open block): line empty, block flag       :close:
-
-#+name: abs_functions_block_line_status_empty
-#+BEGIN_SRC d
-void _block_flag_line_empty_(
-  char[]                       line,
-  ref string[string]           an_object,
-  ref ObjGenericComposite[]    the_document_body_section,
-  ref string[][string][string] bookindex_unordered_hashes,
-  ref int                      obj_cite_number,
-  ref ObjGenericComposite      _comp_obj_heading,
-  ref int                      cntr,
-  ref int[string]              type,
-  string[string]               obj_cite_number_poem,
-  string[string][string]       dochead_make_aa,
-) {
-  // 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 =
-      ocn_emit(type["ocn_status"]);
-    an_object["bookindex_nugget"] =
-      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
-    bookindex_unordered_hashes =
-      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
-    an_object["is"] = "code";
-    auto comp_obj_location =
-      node_construct.node_location_emitter(
-        content_non_header,
-        segment_anchor_tag_that_object_belongs_to,
-        obj_cite_number,
-        cntr,
-        heading_ptr-1,
-        an_object["is"]
-      );
-    auto substantive_object_and_anchor_tags_tuple =
-      obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-    an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-    anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-    comp_obj_code                             = comp_obj_code.init;
-    comp_obj_code.use                         = "body";
-    comp_obj_code.is_of                       = "block";
-    comp_obj_code.is_a                        = "code";
-    comp_obj_code.ocn                         = obj_cite_number;
-    comp_obj_code.obj_cite_number             = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-    comp_obj_code.text                        = an_object["substantive"];
-    the_document_body_section                 ~= comp_obj_code;
-    object_reset(an_object);
-    processing.remove("verse");
-    ++cntr;
-    type["blocks"] = TriState.off;
-    type["code"] = TriState.off;
-  } else if (type["poem"] == TriState.closing) {
-    an_object["bookindex_nugget"] =
-      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
-    bookindex_unordered_hashes =
-      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
-    an_object["is"] = "verse"; // check also
-    auto comp_obj_location =
-      node_construct.node_location_emitter(
-        content_non_header,
-        segment_anchor_tag_that_object_belongs_to,
-        obj_cite_number,
-        cntr,
-        heading_ptr-1,
-        an_object["is"]
-      );
-    comp_obj_poem_ocn                         = comp_obj_poem_ocn.init;
-    comp_obj_poem_ocn.use                     = "body";
-    comp_obj_poem_ocn.is_of                   = "block";
-    comp_obj_poem_ocn.is_a                    = "poem";
-    comp_obj_poem_ocn.ocn                     = obj_cite_number;
-    comp_obj_poem_ocn.obj_cite_number         = (obj_cite_number_poem["start"], obj_cite_number_poem["end"]);
-    comp_obj_poem_ocn.text                    = ""; // an_object["substantive"];
-    the_document_body_section                 ~= comp_obj_poem_ocn;
-    object_reset(an_object);
-    processing.remove("verse");
-    type["blocks"] = TriState.off;
-    type["poem"] = TriState.off;
-  } else if (type["table"] == TriState.closing) {
-    obj_cite_number =
-      ocn_emit(type["ocn_status"]);
-    an_object["bookindex_nugget"] =
-      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
-    bookindex_unordered_hashes =
-      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
-    an_object["is"] = "table";
-    auto comp_obj_location =
-      node_construct.node_location_emitter(
-        content_non_header,
-        segment_anchor_tag_that_object_belongs_to,
-        obj_cite_number,
-        cntr,
-        heading_ptr-1,
-        an_object["is"]
-      );
-    auto substantive_object_and_anchor_tags_tuple =
-      obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-    an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-    anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-    comp_obj_block                            = comp_obj_block.init;
-    comp_obj_block.use                        = "body";
-    comp_obj_block.is_of                      = "block";
-    comp_obj_block.is_a                       = "table";
-    comp_obj_block.ocn                        = obj_cite_number;
-    comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-    comp_obj_block.text                       = an_object["substantive"];
-    the_document_body_section                 ~= comp_obj_block;
-    object_reset(an_object);
-    processing.remove("verse");
-    ++cntr;
-    type["blocks"] = TriState.off;
-    type["table"] = TriState.off;
-  } else if (type["group"] == TriState.closing) {
-    obj_cite_number =
-      ocn_emit(type["ocn_status"]);
-    an_object["bookindex_nugget"] =
-      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
-    bookindex_unordered_hashes =
-      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
-    an_object["is"] = "group";
-    auto comp_obj_location =
-      node_construct.node_location_emitter(
-        content_non_header,
-        segment_anchor_tag_that_object_belongs_to,
-        obj_cite_number,
-        cntr,
-        heading_ptr-1,
-        an_object["is"]
-      );
-    auto substantive_object_and_anchor_tags_tuple =
-      obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-    an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-    anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-    comp_obj_block                            = comp_obj_block.init;
-    comp_obj_block.use                        = "body";
-    comp_obj_block.is_of                      = "block";
-    comp_obj_block.is_a                       = "group";
-    comp_obj_block.ocn                        = obj_cite_number;
-    comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-    comp_obj_block.text                       = an_object["substantive"];
-    the_document_body_section                 ~= comp_obj_block;
-    object_reset(an_object);
-    processing.remove("verse");
-    ++cntr;
-    type["blocks"] = TriState.off;
-    type["group"] = TriState.off;
-  } else if (type["block"] == TriState.closing) {
-    obj_cite_number = ocn_emit(type["ocn_status"]);
-    an_object["bookindex_nugget"] =
-      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
-    bookindex_unordered_hashes =
-      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
-    an_object["is"] = "block";
-    auto comp_obj_location =
-      node_construct.node_location_emitter(
-        content_non_header,
-        segment_anchor_tag_that_object_belongs_to,
-        obj_cite_number,
-        cntr,
-        heading_ptr-1,
-        an_object["is"]
-       );
-    auto substantive_object_and_anchor_tags_tuple =
-      obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-    an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-    anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-    comp_obj_block                            = comp_obj_block.init;
-    comp_obj_block.use                        = "body";
-    comp_obj_block.is_of                      = "block";
-    comp_obj_block.is_a                       = "block";
-    comp_obj_block.ocn                        = obj_cite_number;
-    comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-    comp_obj_block.text                       = an_object["substantive"];
-    the_document_body_section                 ~= comp_obj_block;
-    object_reset(an_object);
-    processing.remove("verse");
-    ++cntr;
-    type["blocks"] = TriState.off;
-    type["block"] = TriState.off;
-  } else if (type["quote"] == TriState.closing) {
-    obj_cite_number =
-      ocn_emit(type["ocn_status"]);
-    an_object["bookindex_nugget"] =
-      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
-    bookindex_unordered_hashes =
-      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
-    an_object["is"] = "quote";
-    auto comp_obj_location =
-      node_construct.node_location_emitter(
-        content_non_header,
-        segment_anchor_tag_that_object_belongs_to,
-        obj_cite_number,
-        cntr,
-        heading_ptr-1,
-        an_object["is"]
-      );
-    auto substantive_object_and_anchor_tags_tuple =
-      obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
-    an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
-    anchor_tags = substantive_object_and_anchor_tags_tuple[1];
-    comp_obj_block                            = comp_obj_block.init;
-    comp_obj_block.use                        = "body";
-    comp_obj_block.is_of                      = "block";
-    comp_obj_block.is_a                       = "quote";
-    comp_obj_block.ocn                        = obj_cite_number;
-    comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-    comp_obj_block.text                       = an_object["substantive"];
-    the_document_body_section                 ~= comp_obj_block;
-    object_reset(an_object);
-    processing.remove("verse");
-    ++cntr;
-    type["blocks"] = TriState.off;
-    type["quote"] = TriState.off;
-  }
-}
-#+END_SRC
-
-*** book index                                                  :bookindex:
-
-#+name: abs_functions_book_index
-#+BEGIN_SRC d
-auto _book_index_(L,I,O,T,B)(
-  L      line,
-  ref I  book_idx_tmp,
-  ref O  an_object,
-  ref T  type,
-  B      opt_action_bool,
-) {
-  debug(asserts){
-    static assert(is(typeof(line)            == char[]));
-    static assert(is(typeof(book_idx_tmp)    == string));
-    static assert(is(typeof(an_object)       == string[string]));
-    static assert(is(typeof(type)            == int[string]));
-    static assert(is(typeof(opt_action_bool) == bool[string]));
-  }
-  auto rgx = Rgx();
-  if (auto m = match(line, rgx.book_index)) {
-    /+ match book_index +/
-    debug(bookindexmatch) {                       // book index
-      writefln(
-        "* [bookindex] %s\n",
-        to!string(m.captures[1]),
-      );
-    }
-    an_object["bookindex_nugget"] = to!string(m.captures[1]);
-  } else if (auto m = match(line, rgx.book_index_open))  {
-    /+ match open book_index +/
-    type["book_index"] = State.on;
-    if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) {
-      book_idx_tmp = to!string(m.captures[1]);
-      debug(bookindexmatch) {                       // book index
-        writefln(
-          "* [bookindex] %s\n",
-          book_idx_tmp,
-        );
-      }
-    }
-  } 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;
-      if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) {
-        an_object["bookindex_nugget"] = book_idx_tmp ~ to!string(m.captures[1]);
-        debug(bookindexmatch) {                     // book index
-          writefln(
-            "* [bookindex] %s\n",
-            book_idx_tmp,
-          );
-        }
-      }
-      book_idx_tmp = "";
-    } else {
-      if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) {
-        book_idx_tmp ~= line;
-      }
-    }
-  }
-}
-#+END_SRC
-
-*** heading or paragraph                                :heading:paragraph:
-**** heading found                                               :heading:
-
-#+name: abs_functions_heading
-#+BEGIN_SRC d
-auto _heading_found_(L,X,H,R,T)(
-  L     line,
-  X     dochead_make_identify_unmarked_headings,
-  ref H heading_match_str,
-  ref R heading_match_rgx,
-  ref T type
-) {
-  debug(asserts){
-    static assert(is(typeof(line)                                    == char[]));
-    static assert(is(typeof(dochead_make_identify_unmarked_headings) == string));
-    static assert(is(typeof(heading_match_str)                       == string[string]));
-    static assert(is(typeof(heading_match_rgx)                       == Regex!(char)[string]));
-    static assert(is(typeof(type)                                    == int[string]));
-  }
-  auto rgx = Rgx();
-  if ((dochead_make_identify_unmarked_headings.length > 2)
-  && (type["make_headings"] == State.off)) {
-    /+ headings found +/
-    debug(headingsfound) {
-      writeln(dochead_make_identify_unmarked_headings);
-    }
-    char[][] make_headings_spl =
-      split(
-        cast(char[]) dochead_make_identify_unmarked_headings,
-        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;
-  }
-}
-#+END_SRC
-
-**** heading make set                                       :heading:
-
-#+name: abs_functions_heading
-#+BEGIN_SRC d
-auto _heading_make_set_(L,C,R,T)(
-  L     line,
-  C     line_occur,
-  ref R heading_match_rgx,
-  ref T type
-) {
-  debug(asserts){
-    static assert(is(typeof(line)              == char[]));
-    static assert(is(typeof(line_occur)        == int[string]));
-    static assert(is(typeof(heading_match_rgx) == Regex!(char)[string]));
-    static assert(is(typeof(type)              == int[string]));
-  }
-  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 (matchFirst(line, heading_match_rgx["h_B"])) {
-      line = "B~ " ~ line;
-      debug(headingsfound) {
-        writeln(line);
-      }
-    }
-    if (matchFirst(line, heading_match_rgx["h_C"])) {
-      line = "C~ " ~ line;
-      debug(headingsfound) {
-        writeln(line);
-      }
-    }
-    if (matchFirst(line, heading_match_rgx["h_D"])) {
-      line = "D~ " ~ line;
-      debug(headingsfound) {
-        writeln(line);
-      }
-    }
-    if (matchFirst(line, heading_match_rgx["h_1"])) {
-      line = "1~ " ~ line;
-      debug(headingsfound) {
-        writeln(line);
-      }
-    }
-    if (matchFirst(line, heading_match_rgx["h_2"])) {
-      line = "2~ " ~ line;
-      debug(headingsfound) {
-        writeln(line);
-      }
-    }
-    if (matchFirst(line, heading_match_rgx["h_3"])) {
-      line = "3~ " ~ line;
-      debug(headingsfound) {
-        writeln(line);
-      }
-    }
-    if (matchFirst(line, heading_match_rgx["h_4"])) {
-      line = "4~ " ~ line;
-      debug(headingsfound) {
-        writeln(line);
-      }
-    }
-  }
-}
-#+END_SRC
-
-**** heading match                                               :heading:
-
-#+name: abs_functions_heading
-#+BEGIN_SRC d
-auto _heading_matched_(L,C,O,K,Lv,Lc,T,Me)(
-  ref L  line,
-  ref C  line_occur,
-  ref O  an_object,
-  ref K  an_object_key,
-  ref Lv lv,
-  ref Lc collapsed_lev,
-  ref T  type,
-  ref Me dochead_meta_aa,
-) {
-  debug(asserts){
-    static assert(is(typeof(line)            == char[]));
-    static assert(is(typeof(line_occur)      == int[string]));
-    static assert(is(typeof(an_object)       == string[string]));
-    static assert(is(typeof(an_object_key)   == string));
-    static assert(is(typeof(lv)              == int[string]));
-    static assert(is(typeof(collapsed_lev)   == int[string]));
-    static assert(is(typeof(type)            == int[string]));
-    static assert(is(typeof(dochead_meta_aa) == string[string][string]));
-  }
-  auto rgx = Rgx();
-  if (auto m = match(line, rgx.heading)) {
-    /+ heading match +/
-    type["heading"] = State.on;
-    if (match(line, rgx.heading_seg_and_above)) {
-      type["biblio_section"] = State.off;
-      type["glossary_section"] = State.off;
-      type["blurb_section"] = State.off;
-    }
-    type["para"] = State.off;
-    ++line_occur["heading"];
-    an_object[an_object_key] ~= 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":
-      an_object[an_object_key]=replaceFirst(an_object[an_object_key],
-        rgx.variable_doc_title, (dochead_meta_aa["title"]["full"] ~ ","));
-      an_object[an_object_key]=replaceFirst(an_object[an_object_key],
-        rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]);
-      collapsed_lev["h0"] = 0;
-      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(strip(line));
-    }
-  }
-}
-#+END_SRC
-
-**** para match                                                     :para:
-
-#+name: abs_functions_para
-#+BEGIN_SRC d
-auto _para_match_(L,O,K,I,B,T,C)(
-  ref L  line,
-  ref O  an_object,
-  ref K  an_object_key,
-  ref I  indent,
-  ref B  bullet,
-  ref T  type,
-  ref C  line_occur,
-) {
-  debug(asserts){
-    static assert(is(typeof(line)          == char[]));
-    static assert(is(typeof(an_object)     == string[string]));
-    static assert(is(typeof(an_object_key) == string));
-    static assert(is(typeof(indent)        == int[string]));
-    static assert(is(typeof(bullet)        == bool));
-    static assert(is(typeof(type)          == int[string]));
-    static assert(is(typeof(line_occur)    == int[string]));
-  }
-  auto rgx = Rgx();
-  if (line_occur["para"] == State.off) {
-    /+ para matches +/
-    type["para"] = State.on;
-    an_object[an_object_key] ~= line;        // body_nugget
-    indent=[
-      "hang_position" : 0,
-      "base_position" : 0,
-    ];
-    bullet = false;
-    if (auto m = matchFirst(line, rgx.para_indent)) {
-      debug(paraindent) {                    // para indent
-        writeln(line);
-      }
-      indent["hang_position"] = to!int(m.captures[1]);
-      indent["base_position"] = 0;
-    } else if (matchFirst(line, rgx.para_bullet)) {
-      debug(parabullet) {                    // para bullet
-        writeln(line);
-      }
-      bullet = true;
-    } else if (auto m = matchFirst(line, rgx.para_indent_hang)) {
-      debug(paraindenthang) {                // para indent hang
-        writeln(line);
-      }
-      indent=[
-        "hang_position" : to!int(m.captures[1]),
-        "base_position" : to!int(m.captures[2]),
-      ];
-    } else if (auto m = matchFirst(line, rgx.para_bullet_indent)) {
-      debug(parabulletindent) {              // para bullet indent
-        writeln(line);
-      }
-      indent=[
-        "hang_position" : to!int(m.captures[1]),
-        "base_position" : 0,
-      ];
-      bullet = true;
-    }
-    ++line_occur["para"];
-  }
-}
-#+END_SRC
-
-*** function emitters                                            :emitters:
-**** object                                                       :object:
-***** ocn                                                           :ocn:
-
-#+name: ao_emitters_ocn
-#+BEGIN_SRC d
-struct OCNemitter {
-  int obj_cite_number, obj_cite_number_;
-  int ocn_emitter(int ocn_status_flag)
-  in { assert(ocn_status_flag <= 3); }
-  body {
-    if (ocn_status_flag == 3) {
-      obj_cite_number = obj_cite_number_ = 1;
-    } else {
-      obj_cite_number=(ocn_status_flag == 0)
-      ? ++obj_cite_number_
-      : 0;
-    }
-    assert(obj_cite_number >= 0);
-    return obj_cite_number;
-  }
-  invariant() {
-  }
-}
-#+END_SRC
-
-***** object inline markup munge                          :markup:inline:
-
-#+name: ao_emitters_obj_inline_markup_munge
-#+BEGIN_SRC d
-struct ObjInlineMarkupMunge {
-  string[string] obj_txt;
-  int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus;
-  string asterisks_;
-  string obj_txt_out, tail, note;
-  auto rgx = Rgx();
-  auto mkup = InlineMarkup();
-  private auto initialize_note_numbers() {
-    n_foot = 0;
-    n_foot_reg = 0;
-    n_foot_sp_asterisk = 0;
-    n_foot_sp_plus = 0;
-  }
-  string url_links(Ot)(Ot obj_txt_in) {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-    /+ url matched +/
-    if (auto m = matchAll(obj_txt_in, rgx.inline_url)) {
-      /+ link: naked url: http://url +/
-      if (match(obj_txt_in, rgx.inline_link_naked_url)) {
-        obj_txt_in =
-          replaceAll(
-            obj_txt_in,
-            rgx.inline_link_naked_url,
-            ("$1" ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~  mkup.url_o ~ "$2" ~  mkup.url_c ~ "$3")            // ("$1{ $2 }$2$3")
-          );
-      }
-      /+ link with helper for endnote including the url:
-           {~^ link which includes url as footnote }http://url
-         maps to:
-           { link which includes url as footnote }http://url~{ { http://url }http://url }~
-      +/
-      if (match(obj_txt_in, rgx.inline_link_endnote_url_helper)) {
-        obj_txt_in =
-          replaceAll(
-            obj_txt_in,
-            rgx.inline_link_endnote_url_helper_punctuated,
-            (mkup.lnk_o ~ " $1 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~  " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3")
-          );
-        obj_txt_in =
-          replaceAll(
-            obj_txt_in,
-            rgx.inline_link_endnote_url_helper,
-            (mkup.lnk_o ~ " $1 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~  " }~")   // ("{ $1 }$2~{ { $2 }$2 }~")
-          );
-      }
-      /+ link with regular markup:
-         { linked text or image }http://url
-      +/
-      if (match(obj_txt_in, rgx.inline_link_markup_regular)) {
-        obj_txt_in =
-          replaceAll(
-            obj_txt_in,
-            rgx.inline_link_markup_regular,
-            ("$1" ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~  mkup.url_o ~ "$3" ~  mkup.url_c ~ "$4")            // ("$1{ $2 }$3$4")
-          );
-      }
-    }
-    return obj_txt_in;
-  }
-  string footnotes_endnotes_markup_and_number_or_stars(Ot)(Ot obj_txt_in) {                                // here endnotes are marked up
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-    /+ endnotes (regular) +/
-    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)) {
-      if (auto m = matchAll(obj_txt_in, rgx.inline_text_and_note_al_)) {
-        foreach(n; m) {
-          if (match(to!string(n.hit), rgx.inline_al_delimiter_open_symbol_star)) {
-            ++n_foot_sp_asterisk;
-            asterisks_ = "*";
-            n_foot=n_foot_sp_asterisk;
-            obj_txt_out ~=
-              (replaceFirst(
-                to!string(n.hit),
-                rgx.inline_al_delimiter_open_symbol_star,
-                (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ")
-              ) ~ "\n");
-          } else if (match(to!string(n.hit), rgx.inline_al_delimiter_open_regular)) {
-            ++n_foot_reg;
-            n_foot=n_foot_reg;
-            obj_txt_out ~=
-              (replaceFirst(
-                to!string(n.hit),
-                rgx.inline_al_delimiter_open_regular,
-                (mkup.en_a_o ~ to!string(n_foot) ~ " ")
-              ) ~ "\n");
-          } else {
-            obj_txt_out ~= to!string(n.hit) ~ "\n";
-          }
-        }
-      }
-    } else {
-      obj_txt_out = obj_txt_in;
-    }
-    return obj_txt_out;
-  }
-  private auto object_notes_(string obj_txt_in)
-  in { }
-  body {
-    obj_txt_out = "";
-    tail = "";
-    /+ special endnotes +/
-    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)
-      );
-    /+ url matched +/
-    if (auto m = matchAll(obj_txt_in, rgx.inline_url)) {
-      obj_txt_in = url_links(obj_txt_in);
-    }
-    obj_txt_out = footnotes_endnotes_markup_and_number_or_stars(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(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    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(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    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"]=strip(obj_txt["munge"]);
-    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() {
-  }
-  /+ revisit +/
-  string code(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  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(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    obj_txt["munge"]=obj_txt_in;
-    obj_txt["munge"]=object_notes_(obj_txt["munge"]);
-    return obj_txt["munge"];
-  }
-  invariant() {
-  }
-  string verse(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    obj_txt["munge"]=obj_txt_in;
-    obj_txt["munge"]=object_notes_(obj_txt["munge"]);
-    return obj_txt["munge"];
-  }
-  invariant() {
-  }
-  string quote(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    obj_txt["munge"]=obj_txt_in;
-    return obj_txt["munge"];
-  }
-  invariant() {
-  }
-  string table(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    obj_txt["munge"]=obj_txt_in;
-    return obj_txt["munge"];
-  }
-  invariant() {
-  }
-  string comment(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    obj_txt["munge"]=obj_txt_in;
-    return obj_txt["munge"];
-  }
-  invariant() {
-  }
-}
-#+END_SRC
-
-***** toc, tags, object inline markup                     :markup:inline:
-****** open
-
-#+name: ao_emitters_obj_inline_markup
-#+BEGIN_SRC d
-struct ObjInlineMarkup {
-  auto rgx = Rgx();
-  auto munge = ObjInlineMarkupMunge();
-  string[string] obj_txt;
-#+END_SRC
-
-****** object inline markup and anchor tags              :markup:inline:
-
-#+name: ao_emitters_obj_inline_markup_and_anchor_tags
-#+BEGIN_SRC d
-  auto obj_inline_markup_and_anchor_tags(O,K,Ma)(
-    O  obj_,
-    K  obj_key_,
-    Ma dochead_make_aa
-  )
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_)            == string[string]));
-      static assert(is(typeof(obj_key_)        == string));
-      static assert(is(typeof(dochead_make_aa) == string[string][string]));
-    }
-  }
-  body {
-    obj_txt["munge"]=obj_[obj_key_].dup;
-    obj_txt["munge"]=(match(obj_["is"], ctRegex!(`verse|code`)))
-    ? obj_txt["munge"]
-    : strip(obj_txt["munge"]);
-    static __gshared string[] anchor_tags_ = [];
-    switch (obj_["is"]) {
-    case "heading":
-      static __gshared string anchor_tag = "";
-      // TODO WORK ON, you still need to ensure that level 1 anchor_tags are unique
-      obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, dochead_make_aa);
-      obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"]);
-      if (auto m = match(obj_txt["munge"], rgx.heading_anchor_tag)) {
-        anchor_tag = m.captures[1];
-        anchor_tags_ ~=anchor_tag;
-      } else if (obj_["lev"] == "1") {
-        writeln("heading anchor tag missing: ", obj_txt["munge"]);
-      }
-      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;
-    }
-    auto t = tuple(
-     obj_txt["munge"],
-     anchor_tags_,
-    );
-    anchor_tags_=[];
-    return t;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-****** toc, table of contents build, gather headings     :markup:inline:
-
-#+name: ao_emitters_obj_inline_markup_table_of_contents
-#+BEGIN_SRC d
-  auto _clean_heading_toc_(Toc)(
-    Toc heading_toc_,
-  ) {
-   debug(asserts){
-     static assert(is(typeof(heading_toc_) == char[]));
-   }
-   auto m = matchFirst(cast(char[]) heading_toc_, rgx.heading);
-   heading_toc_ =
-     replaceAll(
-       m.post,
-       rgx.inline_notes_curly_gen,
-       ("")
-     );
-   return heading_toc_;
-  };
-  auto table_of_contents_gather_headings(O,Ma,Ts,Ta,X,Toc)(
-    O     obj_,
-    Ma    dochead_make_aa,
-    Ts    segment_anchor_tag_that_object_belongs_to,
-    Ta    _anchor_tag,
-    ref X lev4_subtoc,
-    Toc   the_table_of_contents_section,
-  )
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_)                                      == string[string]));
-      static assert(is(typeof(dochead_make_aa)                           == string[string][string]));
-      static assert(is(typeof(segment_anchor_tag_that_object_belongs_to) == string));
-      static assert(is(typeof(_anchor_tag)                               == string));
-      static assert(is(typeof(lev4_subtoc)                               == string[][string]));
-      static assert(is(typeof(the_table_of_contents_section)             == ObjGenericComposite[][string]));
-    }
-  }
-  body {
-    ObjGenericComposite comp_obj_toc;
-    mixin InternalMarkup;
-    auto mkup = InlineMarkup();
-    char[] heading_toc_ = to!(char[])(obj_["body_nugget"].dup.strip);
-    heading_toc_ = _clean_heading_toc_(heading_toc_);
-    auto attrib="";
-    string toc_txt_, subtoc_txt_;
-    int[string] indent;
-    if (to!int(obj_["lev_markup_number"]) > 0) {
-      indent=[
-        "hang_position" : to!int(obj_["lev_markup_number"]),
-        "base_position" : to!int(obj_["lev_markup_number"]),
-      ];
-      toc_txt_ = format(
-        "{ %s }#%s",
-        heading_toc_,
-        _anchor_tag,
-      );
-      toc_txt_= munge.url_links(toc_txt_);
-      comp_obj_toc                       = comp_obj_toc.init;
-      comp_obj_toc.use                   = "frontmatter";
-      comp_obj_toc.is_of                 = "para";
-      comp_obj_toc.is_a                  = "toc";
-      comp_obj_toc.ocn                   = 0;
-      comp_obj_toc.obj_cite_number       = "";
-      comp_obj_toc.indent_hang           = indent["hang_position"];
-      comp_obj_toc.indent_base           = indent["base_position"];
-      comp_obj_toc.bullet                = false;
-      comp_obj_toc.text                  = to!string(toc_txt_).strip;
-      the_table_of_contents_section["scroll"] ~= comp_obj_toc;
-    } else {
-      indent=[
-        "hang_position" : 0,
-        "base_position" : 0,
-      ];
-      comp_obj_toc                       = comp_obj_toc.init;
-      comp_obj_toc.use                   = "frontmatter";
-      comp_obj_toc.is_of                 = "para";
-      comp_obj_toc.is_a                  = "toc";
-      comp_obj_toc.ocn                   = 0;
-      comp_obj_toc.obj_cite_number       = "";
-      comp_obj_toc.indent_hang           = indent["hang_position"];
-      comp_obj_toc.indent_base           = indent["base_position"];
-      comp_obj_toc.bullet                = false;
-      comp_obj_toc.text                  = "Table of Contents";
-      the_table_of_contents_section["scroll"] ~= comp_obj_toc;
-    }
-    comp_obj_toc                       = comp_obj_toc.init;
-    comp_obj_toc.use                   = "frontmatter";
-    comp_obj_toc.is_of                 = "para";
-    comp_obj_toc.is_a                  = "toc";
-    comp_obj_toc.ocn                   = 0;
-    comp_obj_toc.obj_cite_number       = "";
-    comp_obj_toc.bullet                = false;
-    switch (to!int(obj_["lev_markup_number"])) {
-    case 0:
-      indent=[
-        "hang_position" : 0,
-        "base_position" : 0,
-      ];
-      toc_txt_ = "{ Table of Contents }" ~ mkup.mark_internal_site_lnk ~ "../toc.fnSuffix";
-      toc_txt_= munge.url_links(toc_txt_);
-      comp_obj_toc.indent_hang             = indent["hang_position"];
-      comp_obj_toc.indent_base             = indent["base_position"];
-      comp_obj_toc.text                    = to!string(toc_txt_).strip;
-      the_table_of_contents_section["seg"] ~= comp_obj_toc;
-      break;
-    case 1: .. case 3:
-      indent=[
-        "hang_position" : to!int(obj_["lev_markup_number"]),
-        "base_position" : to!int(obj_["lev_markup_number"]),
-      ];
-      toc_txt_ = format(
-        "%s",
-        heading_toc_,
-      );
-      toc_txt_= munge.url_links(toc_txt_);
-      comp_obj_toc.indent_hang             = indent["hang_position"];
-      comp_obj_toc.indent_base             = indent["base_position"];
-      comp_obj_toc.text                    = to!string(toc_txt_).strip;
-      the_table_of_contents_section["seg"] ~= comp_obj_toc;
-      break;
-    case 4:
-      toc_txt_ = format(
-        "{ %s }%s../%s.fnSuffix",
-        heading_toc_,
-        mkup.mark_internal_site_lnk,
-        segment_anchor_tag_that_object_belongs_to,
-      );
-      lev4_subtoc[segment_anchor_tag_that_object_belongs_to] = [];
-      toc_txt_= munge.url_links(toc_txt_);
-      indent=[
-        "hang_position" : to!int(obj_["lev_markup_number"]),
-        "base_position" : to!int(obj_["lev_markup_number"]),
-      ];
-      comp_obj_toc.indent_hang             = indent["hang_position"];
-      comp_obj_toc.indent_base             = indent["base_position"];
-      comp_obj_toc.text                    = to!string(toc_txt_).strip;
-      the_table_of_contents_section["seg"] ~= comp_obj_toc;
-      break;
-    case 5: .. case 7:
-      toc_txt_ = format(
-        "{ %s }%s../%s.fnSuffix#%s",
-        heading_toc_,
-        mkup.mark_internal_site_lnk,
-        segment_anchor_tag_that_object_belongs_to,
-        _anchor_tag,
-      );
-      subtoc_txt_ = format(
-        "{ %s }#%s",
-        heading_toc_,
-        _anchor_tag,
-      );
-      lev4_subtoc[segment_anchor_tag_that_object_belongs_to] ~= obj_["lev_markup_number"] ~ "~ " ~ to!string(subtoc_txt_).strip;
-      toc_txt_= munge.url_links(toc_txt_);
-      indent=[
-        "hang_position" : to!int(obj_["lev_markup_number"]),
-        "base_position" : to!int(obj_["lev_markup_number"]),
-      ];
-      comp_obj_toc.indent_hang             = indent["hang_position"];
-      comp_obj_toc.indent_base             = indent["base_position"];
-      comp_obj_toc.text                    = to!string(toc_txt_).strip;
-      the_table_of_contents_section["seg"] ~= comp_obj_toc;
-      break;
-    default:
-      break;
-    }
-    return the_table_of_contents_section;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-****** private:
-
-#+name: ao_emitters_obj_inline_markup_private
-#+BEGIN_SRC d
-private:
-#+END_SRC
-
-******* make heading number and segment anchor tags if instructed :markup:inline:segment:anchor:tags:
-
-#+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags
-#+BEGIN_SRC d
-  static string _configured_auto_heading_numbering_and_segment_anchor_tags(M,O,Ma)(
-    M  munge_,
-    O  obj_,
-    Ma dochead_make_aa
-  ) {
-    debug(asserts){
-      static assert(is(typeof(munge_)          == string));
-      static assert(is(typeof(obj_)            == string[string]));
-      static assert(is(typeof(dochead_make_aa) == string[string][string]));
-    }
-    if (dochead_make_aa["make"]["num_top"].length > 0) {
-      if (!(match(munge_, rgx.heading_anchor_tag))) {
-        static __gshared int heading_num_top_level=9;
-        static __gshared int heading_num_depth=2;
-        static __gshared int heading_num_0 = 0;
-        static __gshared int heading_num_1 = 0;
-        static __gshared int heading_num_2 = 0;
-        static __gshared int heading_num_3 = 0;
-        static __gshared string heading_number_auto_composite = "";
-        if (heading_num_top_level==9) {
-          if (dochead_make_aa["make"]["num_depth"].length > 0) {
-            heading_num_depth = to!uint(dochead_make_aa["make"]["num_depth"]);
-          }
-          switch (dochead_make_aa["make"]["num_top"]) {
-          case "A":
-            break;
-          case "B":
-            heading_num_top_level=1;
-            break;
-          case "C":
-            heading_num_top_level=2;
-            break;
-          case "D":
-            heading_num_top_level=3;
-            break;
-          case "1":
-            heading_num_top_level=4;
-            break;
-          case "2":
-            heading_num_top_level=5;
-            break;
-          case "3":
-            heading_num_top_level=6;
-            break;
-          case "4":
-            heading_num_top_level=7;
-            break;
-          default:
-            break;
-          }
-        }
-        /+ num_depth minimum 0 (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement +/
-        if (heading_num_top_level > to!uint(obj_["lev_markup_number"])) {
-          heading_num_0 = 0;
-          heading_num_1 = 0;
-          heading_num_2 = 0;
-          heading_num_3 = 0;
-        } else if (heading_num_top_level == to!uint(obj_["lev_markup_number"])) {
-          heading_num_0 ++;
-          heading_num_1 = 0;
-          heading_num_2 = 0;
-          heading_num_3 = 0;
-        } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 1)) {
-          heading_num_1 ++;
-          heading_num_2 = 0;
-          heading_num_3 = 0;
-        } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 2)) {
-          heading_num_2 ++;
-          heading_num_3 = 0;
-        } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 3)) {
-          heading_num_3 ++;
-        }
-        if (heading_num_3 > 0) {
-          heading_number_auto_composite =
-            (heading_num_depth == 3)
-            ? ( to!string(heading_num_0) ~ "." ~
-                  to!string(heading_num_1) ~ "." ~
-                  to!string(heading_num_2) ~ "." ~
-                  to!string(heading_num_3)
-                )
-            : "";
-        } else if (heading_num_2 > 0) {
-          heading_number_auto_composite =
-            ((heading_num_depth >= 2)
-            && (heading_num_depth <= 3))
-            ?  ( to!string(heading_num_0) ~ "." ~
-                  to!string(heading_num_1) ~ "." ~
-                  to!string(heading_num_2)
-                )
-            : "";
-        } else if (heading_num_1 > 0) {
-          heading_number_auto_composite =
-            ((heading_num_depth >= 1)
-            && (heading_num_depth <= 3))
-            ? ( to!string(heading_num_0) ~ "." ~
-                  to!string(heading_num_1)
-                )
-            : "";
-        } else if (heading_num_0 > 0) {
-          heading_number_auto_composite =
-            ((heading_num_depth >= 0)
-            && (heading_num_depth <= 3))
-            ?  (to!string(heading_num_0))
-            : "";
-        } else {
-          heading_number_auto_composite = "";
-        }
-        debug(heading_number_auto) {
-          writeln(heading_number_auto_composite);
-        }
-        if (!empty(heading_number_auto_composite)) {
-          munge_=replaceFirst(munge_, rgx.heading,
-            "$1~$2 " ~ heading_number_auto_composite ~ ". ");
-          munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
-            "$1~" ~ heading_number_auto_composite ~ " ");
-        }
-      }
-    }
-    return munge_;
-  }
-#+END_SRC
-
-******** unittests
-
-#+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags
-#+BEGIN_SRC d
-#+END_SRC
-
-******* make segment anchor tags if not provided :markup:inline:segment:anchor:tags:
-
-#+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags
-#+BEGIN_SRC d
-
-  static string _make_segment_anchor_tags_if_none_provided(M,Lv)(M munge_, Lv lev_) {
-    debug(asserts){
-      static assert(is(typeof(munge_) == string));
-      static assert(is(typeof(lev_)   == string));
-    }
-    if (!(match(munge_, rgx.heading_anchor_tag))) { // if (anchor_tags_.length == 0) {
-      if (match(munge_, rgx.heading_identify_anchor_tag)) {
-        if (auto m = match(munge_, rgx.heading_extract_named_anchor_tag)) {
-          munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
-            "$1~" ~ toLower(m.captures[1]) ~ "_"  ~ m.captures[2] ~ " ");
-        } else if (auto m = match(munge_, rgx.heading_extract_unnamed_anchor_tag)) {
-          munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
-            "$1~" ~ "s" ~ m.captures[1] ~ " ");
-        }
-      } else if (lev_ == "1") { // (if not successful) manufacture a unique anchor tag for lev=="1"
-        static __gshared int heading_num_lev1 = 0;
-        heading_num_lev1 ++;
-        munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
-          "$1~" ~ "x" ~ to!string(heading_num_lev1) ~ " ");
-      }
-    }
-    return munge_;
-  }
-#+END_SRC
-
-******** unittests
-
-#+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags
-#+BEGIN_SRC d
-  unittest {
-    string txt_lev="1";
-    string txt_in, txt_out;
-
-    txt_in = "1~copyright Copyright";
-    txt_out ="1~copyright Copyright";
-    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
-
-    txt_in = "1~ 6. Writing Copyright Licenses";
-    txt_out ="1~s6 6. Writing Copyright Licenses";
-    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
-
-    txt_in= "1~ 1. Reinforcing trends";
-    txt_out= "1~s1 1. Reinforcing trends";
-    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
-
-    txt_in= "1~ 11 SCIENCE AS A COMMONS";
-    txt_out= "1~s11 11 SCIENCE AS A COMMONS";
-    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
-
-    txt_in= "1~ Chapter 1";
-    txt_out="1~chapter_1 Chapter 1";
-    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
-
-    txt_in= "1~ Chapter 1.";
-    txt_out="1~chapter_1 Chapter 1.";
-    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
-
-    txt_in= "1~ Chapter 1: Done";
-    txt_out="1~chapter_1 Chapter 1: Done";
-    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
-
-    txt_in=  "1~ Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment";
-    txt_out= "1~chapter_11 Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment";
-    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
-
-    txt_in= "1~ CHAPTER I.";
-    txt_out="1~x1 CHAPTER I.";
-    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
-
-    txt_in= "1~ CHAPTER II.";
-    txt_out="1~x2 CHAPTER II.";
-    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
-  }
-#+END_SRC
-
-****** close
-
-#+name: ao_emitters_obj_inline_markup_close
-#+BEGIN_SRC d
-}
-#+END_SRC
-
-***** object attrib                                          :attributes:
-****** attributes structure open, public
-
-#+name: ao_emitters_obj_attributes
-#+BEGIN_SRC d
-struct ObjAttributes {
-  string[string] _obj_attrib;
-#+END_SRC
-
-****** attributes structure open, public
-
-#+name: ao_emitters_obj_attributes_public
-#+BEGIN_SRC d
-  string obj_attributes(Oi,OR,OH)(
-    Oi obj_is_,
-    OR obj_raw,
-    OH _comp_obj_heading,
-  )
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_is_)           == string));
-      static assert(is(typeof(obj_raw)           == string));
-      static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite));
-    }
-  }
-  body {
-    scope(exit) {
-      destroy(obj_is_);
-      destroy(obj_raw);
-      destroy(_comp_obj_heading);
-    }
-    _obj_attrib["json"] ="{";
-    switch (obj_is_) {
-    case "heading":
-      _obj_attrib["json"] ~= _heading(obj_raw);
-      break;
-    case "para":
-      _obj_attrib["json"] ~= _para_and_blocks(obj_raw)
-      ~ _para(obj_raw);
-      break;
-    case "code":
-      _obj_attrib["json"] ~= _code(obj_raw);
-      break;
-    case "group":
-      _obj_attrib["json"] ~= _para_and_blocks(obj_raw)
-      ~ _group(obj_raw);
-      break;
-    case "block":
-      _obj_attrib["json"] ~= _para_and_blocks(obj_raw)
-      ~ _block(obj_raw);
-      break;
-    case "verse":
-      _obj_attrib["json"] ~= _verse(obj_raw);
-      break;
-    case "quote":
-      _obj_attrib["json"] ~= _quote(obj_raw);
-      break;
-    case "table":
-      _obj_attrib["json"] ~= _table(obj_raw);
-      break;
-    case "comment":
-      _obj_attrib["json"] ~= _comment(obj_raw);
-      break;
-    default:
-      _obj_attrib["json"] ~= _para(obj_raw);
-      break;
-    }
-    _obj_attrib["json"] ~=" }";
-    _obj_attrib["json"]=_set_additional_values_parse_as_json(_obj_attrib["json"], obj_is_, _comp_obj_heading);
-    debug(structattrib) {
-      if (oa_j["is"].str() == "heading") {
-        writeln(_obj_attrib["json"]);
-        writeln(
-          "is: ", oa_j["is"].str(),
-          "; obj_cite_number: ", oa_j["obj_cite_number"].integer()
-        );
-      }
-    }
-    return _obj_attrib["json"];
-  }
-  invariant() {
-  }
-#+END_SRC
-
-****** private
-
-#+name: ao_emitters_obj_attributes_private
-#+BEGIN_SRC d
-  private:
-  string _obj_attributes;
-#+END_SRC
-
-******* attrubutes
-******** para and block
-
-#+name: ao_emitters_obj_attributes_private_an_attribute
-#+BEGIN_SRC d
-  string _para_and_blocks(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    if (matchFirst(obj_txt_in, rgx.para_bullet)) {
-      _obj_attributes =" \"bullet\": \"true\","
-      ~ " \"indent_hang\": 0,"
-      ~ " \"indent_base\": 0,";
-    } else if (auto m = matchFirst(obj_txt_in, rgx.para_bullet_indent)) {
-      _obj_attributes =" \"bullet\": \"true\","
-      ~ " \"indent_hang\": " ~ to!string(m.captures[1]) ~ ","
-      ~ " \"indent_base\": " ~ to!string(m.captures[1]) ~ ",";
-    } else if (auto m = matchFirst(obj_txt_in, rgx.para_indent_hang)) {
-      _obj_attributes =" \"bullet\": \"false\","
-      ~ " \"indent_hang\": " ~ to!string(m.captures[1]) ~ ","
-      ~ " \"indent_base\": " ~  to!string(m.captures[2]) ~ ",";
-    } else if (auto m = matchFirst(obj_txt_in, rgx.para_indent)) {
-      _obj_attributes =" \"bullet\": \"false\","
-      ~ " \"indent_hang\": " ~ to!string(m.captures[1]) ~ ","
-      ~ " \"indent_base\": " ~ to!string(m.captures[1]) ~ ",";
-    } else {
-      _obj_attributes =" \"bullet\": \"false\","
-      ~ " \"indent_hang\": 0,"
-      ~ " \"indent_base\": 0,";
-    }
-    return _obj_attributes;
-  }
-#+END_SRC
-
-******** para
-
-#+name: ao_emitters_obj_attributes_private_an_attribute
-#+BEGIN_SRC d
-  string _para(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    _obj_attributes = " \"use\": \"content\","
-    ~ " \"of\": \"para\","
-    ~ " \"is\": \"para\"";
-    return _obj_attributes;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-******** heading
-
-#+name: ao_emitters_obj_attributes_private_an_attribute
-#+BEGIN_SRC d
-  string _heading(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    _obj_attributes = " \"use\": \"content\","
-    ~ " \"of\": \"para\","
-    ~ " \"is\": \"heading\"";
-    return _obj_attributes;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-******** code
-
-#+name: ao_emitters_obj_attributes_private_an_attribute
-#+BEGIN_SRC d
-  string _code(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    _obj_attributes = " \"use\": \"content\","
-    ~ " \"of\": \"block\","
-    ~ " \"is\": \"code\"";
-    return _obj_attributes;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-******** group
-
-#+name: ao_emitters_obj_attributes_private_an_attribute
-#+BEGIN_SRC d
-  string _group(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    _obj_attributes = " \"use\": \"content\","
-    ~ " \"of\": \"block\","
-    ~ " \"is\": \"group\"";
-    return _obj_attributes;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-******** block
-
-#+name: ao_emitters_obj_attributes_private_an_attribute
-#+BEGIN_SRC d
-  string _block(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    _obj_attributes = " \"use\": \"content\","
-    ~ " \"of\": \"block\","
-    ~ " \"is\": \"block\"";
-    return _obj_attributes;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-******** verse
-
-#+name: ao_emitters_obj_attributes_private_an_attribute
-#+BEGIN_SRC d
-  string _verse(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    _obj_attributes = " \"use\": \"content\","
-    ~ " \"of\": \"block\","
-    ~ " \"is\": \"verse\"";
-    return _obj_attributes;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-******** quote
-
-#+name: ao_emitters_obj_attributes_private_an_attribute
-#+BEGIN_SRC d
-  string _quote(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    _obj_attributes = " \"use\": \"content\","
-    ~ " \"of\": \"block\","
-    ~ " \"is\": \"quote\"";
-    return _obj_attributes;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-******** table
-
-#+name: ao_emitters_obj_attributes_private_an_attribute
-#+BEGIN_SRC d
-  string _table(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    _obj_attributes = " \"use\": \"content\","
-    ~ " \"of\": \"block\","
-    ~ " \"is\": \"table\"";
-    return _obj_attributes;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-******** comment
-
-#+name: ao_emitters_obj_attributes_private_an_attribute
-#+BEGIN_SRC d
-  string _comment(Ot)(Ot obj_txt_in)
-  in {
-    debug(asserts){
-      static assert(is(typeof(obj_txt_in) == string));
-    }
-  }
-  body {
-    _obj_attributes = " \"use\": \"comment\","
-    ~ " \"of\": \"comment\","
-    ~ " \"is\": \"comment\"";
-    return _obj_attributes;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-******* set additional attribute values, parse as json
-
-#+name: ao_emitters_obj_attributes_private_json
-#+BEGIN_SRC d
-  string _set_additional_values_parse_as_json(OA,Oi,OH)(
-    OA _obj_attrib,
-    Oi obj_is_,
-    OH _comp_obj_heading,
-  ) {
-    debug(asserts){
-      static assert(is(typeof(_obj_attrib)       == string));
-      static assert(is(typeof(obj_is_)           == string));
-      static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite));
-    }
-    JSONValue oa_j = parseJSON(_obj_attrib);
-    assert(
-      (oa_j.type == JSON_TYPE.OBJECT)
-    );
-    if (obj_is_ == "heading") {
-      oa_j.object["obj_cite_number"] = _comp_obj_heading.ocn;
-      oa_j.object["lev_markup_number"] = _comp_obj_heading.heading_lev_markup;
-      oa_j.object["lev_collapsed_number"] = _comp_obj_heading.heading_lev_collapsed;
-      oa_j.object["heading_ptr"] =
-        _comp_obj_heading.ptr_heading;
-      oa_j.object["doc_object_ptr"] =
-        _comp_obj_heading.ptr_doc_object;
-    }
-    oa_j.object["parent_obj_cite_number"] = _comp_obj_heading.parent_ocn;
-    oa_j.object["parent_lev_markup_number"] = _comp_obj_heading.parent_lev_markup;
-    _obj_attrib = oa_j.toString();
-    return _obj_attrib;
-  }
-#+END_SRC
-
-****** close
-
-#+name: ao_emitters_obj_attributes_private_close
-#+BEGIN_SRC d
-}
-#+END_SRC
-
-**** book index                                               :book:index:
-***** book index nugget hash                                :hash:nugget:
-
-#+name: ao_emitters_book_index_nugget
-#+BEGIN_SRC d
-struct BookIndexNuggetHash {
-  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(BI,N)(
-    BI bookindex_section,
-    N  obj_cite_number
-  )
-  in {
-    debug(asserts){
-      static assert(is(typeof(bookindex_section) == string));
-      static assert(is(typeof(obj_cite_number)   == int));
-    }
-    debug(bookindexraw) {
-      if (!bookindex_section.empty) {
-        writeln(
-          "* [bookindex] ",
-          "[", 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() {
-  }
-}
-#+END_SRC
-
-***** book index (sort &) report indented               :report:indented:
-
-#+name: ao_emitters_book_index_report_indented
-#+BEGIN_SRC d
-struct BookIndexReportIndent {
-  int mkn, skn;
-  auto bookindex_report_indented(BI)(
-    BI bookindex_unordered_hashes
-  ) {
-    debug(asserts){
-      static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string]));
-    }
-    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]
-          ));
-        }
-        ++skn;
-      }
-      ++mkn;
-    }
-  }
-}
-#+END_SRC
-
-***** book index (sort &) report section                 :report:section:
-****** book index struct open
-
-#+name: ao_emitters_book_index_report_section
-#+BEGIN_SRC d
-struct BookIndexReportSection {
-  int  mkn, skn;
-  auto rgx = Rgx();
-  auto munge = ObjInlineMarkupMunge();
-#+END_SRC
-
-****** bookindex write section
-
-#+name: ao_emitters_book_index_report_section
-#+BEGIN_SRC d
-  auto bookindex_write_section(BI)(
-    BI bookindex_unordered_hashes
-  ) {
-    debug(asserts){
-      static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string]));
-    }
-    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;
-    }
-  }
-#+END_SRC
-
-****** book index (sort &) build section                :report:section:
-
-#+name: ao_emitters_book_index_report_section
-#+BEGIN_SRC d
-  auto bookindex_build_abstraction_section(BI,N,Ta,B)(
-    BI bookindex_unordered_hashes,
-    N  obj_cite_number,
-    Ta segment_anchor_tag_that_object_belongs_to,
-    B  opt_action_bool,
-  ) {
-    debug(asserts){
-      static assert(is(typeof(bookindex_unordered_hashes)                == string[][string][string]));
-      static assert(is(typeof(obj_cite_number)                           == int));
-      static assert(is(typeof(segment_anchor_tag_that_object_belongs_to) == string));
-      static assert(is(typeof(opt_action_bool)                           == bool[string]));
-    }
-    mixin SiSUnode;
-    mixin InternalMarkup;
-    auto mkup = InlineMarkup();
-    string type_is;
-    string lev;
-    int heading_lev_markup, heading_lev_collapsed;
-    string attrib;
-    int[string] indent;
-    auto mainkeys =
-      bookindex_unordered_hashes.byKey.array.sort().release;
-    ObjGenericComposite[][string] bookindex_section;
-    ObjGenericComposite comp_obj_heading_, comp_obj_para;
-    auto node_para_int_ = node_metadata_para_int;
-    auto node_para_str_ = node_metadata_para_str;
-    if ((mainkeys.length > 0)
-    && (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"])) {
-      string bi_tmp_seg, bi_tmp_scroll;
-      string[] bi_tmp_tags;
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "backmatter";
-      comp_obj_heading_.is_of                 = "para";
-      comp_obj_heading_.is_a                  = "heading";
-      comp_obj_heading_.text                  = "Book Index";
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.marked_up_level       = "B";
-      comp_obj_heading_.heading_lev_markup    = 1;
-      comp_obj_heading_.heading_lev_collapsed = 1;
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      bookindex_section["scroll"]             ~= comp_obj_heading_;
-      bookindex_section["seg"]                ~= comp_obj_heading_;
-      ++obj_cite_number;
-      ++mkn;
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "backmatter";
-      comp_obj_heading_.is_of                 = "para";
-      comp_obj_heading_.is_a                  = "heading";
-      comp_obj_heading_.text                  = "Index";
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.segment_anchor_tag    = "bookindex";
-      comp_obj_heading_.marked_up_level       = "1";
-      comp_obj_heading_.heading_lev_markup    = 4;
-      comp_obj_heading_.heading_lev_collapsed = 2;
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      comp_obj_heading_.anchor_tags           = ["bookindex"];
-      bookindex_section["scroll"]             ~= comp_obj_heading_;
-      bookindex_section["seg"]                ~= comp_obj_heading_;
-      ++obj_cite_number;
-      ++mkn;
-      import std.array : appender;
-      auto buffer = appender!(char[])();
-      string[dchar] transTable = [' ' : "_"];
-      foreach (mainkey; mainkeys) {
-        bi_tmp_tags = [""];
-        bi_tmp_scroll = "!{" ~ mainkey ~ "}! ";
-        buffer.clear();
-        bi_tmp_tags ~= translate(mainkey, transTable);
-        bi_tmp_seg = "!{" ~ mainkey ~ "}! ";
-        foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
-          auto go = replaceAll(ref_, rgx.book_index_go, "$1");
-          bi_tmp_scroll ~= munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ");
-          bi_tmp_seg ~= (segment_anchor_tag_that_object_belongs_to.empty)
-          ? munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ")
-          : munge.url_links(" {" ~ ref_ ~ "}" ~ mkup.mark_internal_site_lnk ~ "../" ~ segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#" ~ go ~ ", ");
-        }
-        bi_tmp_scroll ~= " \\\\\n    ";
-        bi_tmp_seg ~= " \\\\\n    ";
-        bookindex_unordered_hashes[mainkey].remove("_a");
-        auto subkeys =
-          bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
-        foreach (subkey; subkeys) {
-          bi_tmp_scroll ~= subkey ~ ", ";
-          buffer.clear();
-          bi_tmp_tags ~= translate(subkey, transTable);
-          bi_tmp_seg ~= subkey ~ ", ";
-          foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
-            auto go = replaceAll(ref_, rgx.book_index_go, "$1");
-            bi_tmp_scroll ~= munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ");
-            bi_tmp_seg ~= (segment_anchor_tag_that_object_belongs_to.empty)
-            ? munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ")
-            : munge.url_links(" {" ~ ref_ ~ "}" ~ mkup.mark_internal_site_lnk ~ "../" ~ segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#" ~ go ~ ", ");
-          }
-          bi_tmp_scroll ~= " \\\\\n    ";
-          bi_tmp_seg ~= " \\\\\n    ";
-          ++skn;
-        }
-        bi_tmp_scroll = replaceFirst(bi_tmp_scroll, rgx.trailing_linebreak, "");
-        bi_tmp_seg = replaceFirst(bi_tmp_seg, rgx.trailing_linebreak, "");
-        comp_obj_para                       = comp_obj_para.init;
-        comp_obj_para.use                   = "backmatter";
-        comp_obj_para.is_of                 = "para";
-        comp_obj_para.is_a                  = "bookindex";
-        comp_obj_para.text                  = to!string(bi_tmp_scroll).strip;
-        comp_obj_para.ocn                   = obj_cite_number;
-        comp_obj_para.obj_cite_number       = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-        comp_obj_para.anchor_tags           = bi_tmp_tags;
-        comp_obj_para.indent_hang           = 0;
-        comp_obj_para.indent_base           = 1;
-        comp_obj_para.bullet                = false;
-        bookindex_section["scroll"]         ~= comp_obj_para;
-        comp_obj_para.text                  = to!string(bi_tmp_seg).strip;
-        bookindex_section["seg"]            ~= comp_obj_para;
-        ++obj_cite_number;
-        ++mkn;
-      }
-    } else {                              // no book index, (figure out what to do here)
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.text                  = "(skip) there is no Book Index";
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.marked_up_level       = "B";
-      comp_obj_heading_.heading_lev_markup    = 1;
-      comp_obj_heading_.heading_lev_collapsed = 1;
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      bookindex_section["scroll"]             ~= comp_obj_heading_;
-      bookindex_section["seg"]                ~= comp_obj_heading_;
-    }
-    auto t = tuple(bookindex_section, obj_cite_number);
-    return t;
-  }
-#+END_SRC
-
-****** book index struct close
-
-#+name: ao_emitters_book_index_report_section
-#+BEGIN_SRC d
-}
-#+END_SRC
-
-**** (end)notes section                                 :endnotes:section:
-
-#+name: ao_emitters_endnotes
-#+BEGIN_SRC d
-struct NotesSection {
-  string[string] object_notes;
-  int previous_count;
-  int mkn;
-  auto rgx = Rgx();
-#+END_SRC
-
-***** gather notes for endnote section struct open
-
-#+name: ao_emitters_endnotes
-#+BEGIN_SRC d
-  private auto gather_notes_for_endnote_section(
-    ObjGenericComposite[] contents_am,
-    string                segment_anchor_tag_that_object_belongs_to,
-    int                   cntr,
-  )
-  in {
-    // endnotes/ footnotes for
-    // doc objects other than paragraphs & headings
-    // various forms of grouped text
-    assert((contents_am[cntr].is_a == "para")
-    || (contents_am[cntr].is_a == "heading")
-    || (contents_am[cntr].is_a == "group"));
-    assert(cntr >= previous_count);
-    previous_count=cntr;
-    assert(
-      match(contents_am[cntr].text,
-      rgx.inline_notes_delimiter_al_regular_number_note)
-    );
-  }
-  body {
-    mixin InternalMarkup;
-    auto mkup = InlineMarkup();
-    auto munge = ObjInlineMarkupMunge();
-    foreach(
-      m;
-      matchAll(
-        contents_am[cntr].text,
-        rgx.inline_notes_delimiter_al_regular_number_note
-      )
-    ) {
-      debug(endnotes_build) {
-        writeln(
-          "{^{", m.captures[1], ".}^}" ~ mkup.mark_internal_site_lnk ~ "../", segment_anchor_tag_that_object_belongs_to, ".fnSuffix#noteref_\n  ", m.captures[1], " ",
-          m.captures[2]); // sometimes need segment name (segmented html & epub)
-      }
-      // TODO NEXT you need anchor for segments at this point ->
-      object_notes["anchor"] ~= "#note_" ~ m.captures[1] ~ "』";
-      object_notes["notes"] ~= (segment_anchor_tag_that_object_belongs_to.empty)
-      ? (munge.url_links(
-          "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~
-          m.captures[1]) ~ " " ~ m.captures[2] ~ "』"
-        )
-      : (munge.url_links(
-          "{^{" ~ m.captures[1] ~ ".}^}" ~ mkup.mark_internal_site_lnk ~ "../" ~
-          segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#noteref_" ~
-          m.captures[1]) ~ " " ~ m.captures[2] ~ "』"
-        );
-    }
-    return object_notes;
-  }
-#+END_SRC
-
-***** gathered notes
-
-#+name: ao_emitters_endnotes
-#+BEGIN_SRC d
-  private auto gathered_notes()
-  in {
-  }
-  body {
-    string[][string] endnotes_;
-    if (object_notes.length > 1) {
-      endnotes_["notes"] = (split(object_notes["notes"], rgx.break_string))[0..$-1];
-      endnotes_["anchor"] = (split(object_notes["anchor"], rgx.break_string))[0..$-1];
-    } else {
-      endnotes_["notes"] = [];
-      endnotes_["anchor"] = [];
-    }
-    return endnotes_;
-  }
-#+END_SRC
-
-***** endnote objects
-
-#+name: ao_emitters_endnotes
-#+BEGIN_SRC d
-  private auto endnote_objects(
-    int            obj_cite_number,
-    bool[string]   opt_action_bool,
-  )
-  in {
-  }
-  body {
-    mixin SiSUnode;
-    ObjGenericComposite[] the_endnotes_section;
-    auto endnotes_ = gathered_notes();
-    string type_is;
-    string lev, lev_markup_number, lev_collapsed_number;
-    string attrib;
-    int[string] indent;
-    ObjGenericComposite comp_obj_heading_;
-    if ((endnotes_["notes"].length > 0)
-    && (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"])) {
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "backmatter";
-      comp_obj_heading_.is_of                 = "para";
-      comp_obj_heading_.is_a                  = "heading";
-      comp_obj_heading_.text                  = "Endnotes";
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.marked_up_level       = "B";
-      comp_obj_heading_.heading_lev_markup    = 1;
-      comp_obj_heading_.heading_lev_collapsed = 1;
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      the_endnotes_section                    ~= comp_obj_heading_;
-      ++obj_cite_number;
-      ++mkn;
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "backmatter";
-      comp_obj_heading_.is_of                 = "para";
-      comp_obj_heading_.is_a                  = "heading";
-      comp_obj_heading_.text                  = "Endnotes";
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.segment_anchor_tag    = "endnotes";
-      comp_obj_heading_.marked_up_level       = "1";
-      comp_obj_heading_.heading_lev_markup    = 4;
-      comp_obj_heading_.heading_lev_collapsed = 2;
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      comp_obj_heading_.anchor_tags           = ["endnotes"];
-      the_endnotes_section                    ~= comp_obj_heading_;
-      ++obj_cite_number;
-      ++mkn;
-    } else {
-      comp_obj_heading_                       = comp_obj_heading_.init;
-      comp_obj_heading_.use                   = "empty";
-      comp_obj_heading_.is_of                 = "para";
-      comp_obj_heading_.is_a                  = "heading";
-      comp_obj_heading_.text                  = "(skip) there are no Endnotes";
-      comp_obj_heading_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_heading_.marked_up_level       = "B";
-      comp_obj_heading_.heading_lev_markup    = 1;
-      comp_obj_heading_.heading_lev_collapsed = 1;
-      comp_obj_heading_.parent_ocn            = 1;
-      comp_obj_heading_.parent_lev_markup     = 0;
-      the_endnotes_section                    ~= comp_obj_heading_;
-    }
-    if (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"]) {
-      ObjGenericComposite comp_obj_endnote_;
-      comp_obj_endnote_                       = comp_obj_endnote_.init;
-      comp_obj_endnote_.use                   = "backmatter";
-      comp_obj_endnote_.is_of                 = "para";
-      comp_obj_endnote_.is_a                  = "endnote";
-      comp_obj_endnote_.ocn                   = 0;
-      comp_obj_heading_.obj_cite_number       = "";
-      comp_obj_endnote_.indent_hang           = 0;
-      comp_obj_endnote_.indent_base           = 0;
-      comp_obj_endnote_.bullet                = false;
-      foreach (i, endnote; endnotes_["notes"]) {
-        auto     m                            = (matchFirst(endnote, rgx.note_ref));
-        string   notenumber                   = to!string(m.captures[1]);
-        string   anchor_tag                   = "note_" ~ notenumber;
-        comp_obj_endnote_.anchor_tags         ~= [ endnotes_["anchor"][i] ];
-        comp_obj_endnote_.text                = endnote.strip;
-        the_endnotes_section                  ~= comp_obj_endnote_;
-      }
-    }
-    auto t = tuple(the_endnotes_section, obj_cite_number);
-    return t;
-  }
-#+END_SRC
-
-***** gather notes for endnote section struct close
-
-#+name: ao_emitters_endnotes
-#+BEGIN_SRC d
-}
-#+END_SRC
-
-**** bibliography                                           :bibliography:
-***** biblio struct open
-
-#+name: ao_emitters_bibliography
-#+BEGIN_SRC d
-struct Bibliography {
-#+END_SRC
-
-***** biblio
-
-#+name: ao_emitters_bibliography
-#+BEGIN_SRC d
-  public JSONValue[] _bibliography_(Bi,BJ)(
-    ref Bi biblio_unsorted_incomplete,
-    ref BJ bib_arr_json
-  )
-  in {
-    debug(asserts){
-      static assert(is(typeof(biblio_unsorted_incomplete) == string[]));
-      static assert(is(typeof(bib_arr_json)               == JSONValue[]));
-    }
- }
-  body {
-    JSONValue[] biblio_unsorted =
-      _biblio_unsorted_complete_(biblio_unsorted_incomplete, bib_arr_json);
-    JSONValue[] biblio_sorted__ = biblio_sort(biblio_unsorted);
-    biblio_debug(biblio_sorted__);
-    debug(biblio0) {
-      writeln("---");
-      writeln("unsorted incomplete: ", biblio_unsorted_incomplete.length);
-      writeln("json:                ", bib_arr_json.length);
-      writeln("unsorted:            ", biblio_unsorted.length);
-      writeln("sorted:              ", biblio_sorted__.length);
-      int cntr;
-      int[7] x;
-      while (cntr < x.length) {
-        writeln(cntr, ": ", biblio_sorted__[cntr]["fulltitle"]);
-        cntr++;
-      }
-    }
-    return biblio_sorted__;
-  }
-#+END_SRC
-
-***** biblio unsorted complete
-
-#+name: ao_emitters_bibliography
-#+BEGIN_SRC d
-  final private JSONValue[] _biblio_unsorted_complete_(Bi,BJ)(
-    Bi     biblio_unordered,
-    ref BJ bib_arr_json
-  ) {
-    debug(asserts){
-      static assert(is(typeof(biblio_unordered) == string[]));
-      static assert(is(typeof(bib_arr_json)     == JSONValue[]));
-    }
-    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;
-  }
-#+END_SRC
-
-***** biblio sort
-
-#+name: ao_emitters_bibliography
-#+BEGIN_SRC d
-  final private JSONValue[] biblio_sort(BJ)(BJ biblio_unordered) {
-    debug(asserts){
-      static assert(is(typeof(biblio_unordered) == JSONValue[]));
-    }
-    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"]);
-        }
-      }
-    }
-    return biblio_sorted_;
-  }
-#+END_SRC
-
-***** biblio debug
-
-#+name: ao_emitters_bibliography
-#+BEGIN_SRC d
-  void biblio_debug(BJ)(BJ biblio_sorted) {
-    debug(asserts){
-      static assert(is(typeof(biblio_sorted) == JSONValue[]));
-    }
-    debug(biblio0) {
-      foreach (j; biblio_sorted) {
-        if (!empty(j["fulltitle"].str)) {
-          writeln(j["sortby_deemed_author_year_title"]);
-        }
-      }
-    }
-  }
-#+END_SRC
-
-***** biblio struct close
-
-#+name: ao_emitters_bibliography
-#+BEGIN_SRC d
-}
-#+END_SRC
-
-**** node structure metadata                     :structure:metadata:node:
-***** metadata node struct open
-
-#+name: ao_emitters_metadata
-#+BEGIN_SRC d
-struct NodeStructureMetadata {
-  int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7;
-  int obj_cite_number;
-  int[string] p_; // p_ parent_
-  auto rgx = Rgx();
-#+END_SRC
-
-***** TODO node metadata emitter
-
-#+name: ao_emitters_metadata
-#+BEGIN_SRC d
-  ObjGenericComposite node_location_emitter(Lv,Ta,N,C,P,I)(
-    Lv lev_markup_number,
-    Ta segment_anchor_tag,
-    N  obj_cite_number_,
-    C  cntr_,
-    P  ptr_,
-    I  is_
-  )
-  in {
-    debug(asserts){
-      static assert(is(typeof(lev_markup_number)  == string));
-      static assert(is(typeof(segment_anchor_tag) == string));
-      static assert(is(typeof(obj_cite_number_)   == int));
-      static assert(is(typeof(cntr_)              == int));
-      static assert(is(typeof(ptr_)               == int));
-      static assert(is(typeof(is_)                == string));
-    }
-    assert(is_ != "heading");
-    assert(to!int(obj_cite_number_) >= 0);
-  }
-  body {
-    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;
-    }
-    ObjGenericComposite comp_obj_location;
-    comp_obj_location                       = comp_obj_location.init;
-    comp_obj_location.is_a                  = is_;
-    comp_obj_location.ocn                   = obj_cite_number_;
-    comp_obj_location.segment_anchor_tag    = to!string(segment_anchor_tag);
-    comp_obj_location.parent_ocn            = p_["obj_cite_number"];
-    comp_obj_location.parent_lev_markup     = p_["lev_markup_number"];
-    debug(node) {
-      if (match(lev_markup_number, rgx.levels_numbered_headings)) {
-        writeln("x ", to!string(_node));
-      } else {
-        writeln("- ", to!string(_node));
-      }
-    }
-    assert(comp_obj_location.parent_lev_markup >= 4);
-    assert(comp_obj_location.parent_lev_markup <= 7);
-    assert(comp_obj_location.parent_ocn >= 0);
-    return comp_obj_location;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-***** TODO node metadata emitter heading, (including most segnames & their pointers)
-
-#+name: ao_emitters_metadata
-#+BEGIN_SRC d
-  ObjGenericComposite node_emitter_heading(T,L,Lm,Lc,Ta,N,C,P,LA,I,PSn)(
-    T   _text,
-    L   lev,
-    Lm  lev_markup_number,
-    Lc  lev_collapsed_number,
-    Ta  segment_anchor_tag,
-    N   obj_cite_number_,
-    C   cntr_,
-    P   ptr_,
-    LA  lv_ancestors,
-    I   is_,
-    PSn html_segnames_ptr,
-  )
-  in {
-    debug(asserts){
-      static assert(is(typeof(_text)                == string));
-      static assert(is(typeof(lev)                  == string));
-      static assert(is(typeof(lev_markup_number)    == string));
-      static assert(is(typeof(lev_collapsed_number) == string));
-      static assert(is(typeof(segment_anchor_tag)   == string));
-      static assert(is(typeof(obj_cite_number_)     == int));
-      static assert(is(typeof(cntr_)                == int));
-      static assert(is(typeof(ptr_)                 == int));
-      static assert(is(typeof(lv_ancestors)         == string[]));
-      static assert(is(typeof(is_)                  == string));
-      static assert(is(typeof(html_segnames_ptr)    == int));
-    }
-    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_))
-    );
-    if (match(lev_markup_number, rgx.levels_numbered)) {
-      if (to!int(lev_markup_number) == 0) {
-        assert(to!int(obj_cite_number_) == 1);
-      }
-    }
-  }
-  body {
-    int obj_cite_number = to!int(obj_cite_number_);
-    switch (to!int(lev_markup_number)) {
-    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:
-      break;
-    }
-    ObjGenericComposite _comp_obj_heading_;
-    _comp_obj_heading_                           = _comp_obj_heading_.init;
-    _comp_obj_heading_.use                       = "body";
-    _comp_obj_heading_.is_of                     = "para";
-    _comp_obj_heading_.is_a                      = "heading";   //                   = is_; // check whether needed, constant???
-    _comp_obj_heading_.text                      = to!string(_text).strip;
-    _comp_obj_heading_.ocn                       = obj_cite_number_;
-    _comp_obj_heading_.obj_cite_number           = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
-    _comp_obj_heading_.segment_anchor_tag        = to!string(segment_anchor_tag);
-    _comp_obj_heading_.marked_up_level           = lev;
-    _comp_obj_heading_.heading_lev_markup        = (!(lev_markup_number.empty) ? to!int(lev_markup_number) : 0);
-    _comp_obj_heading_.heading_lev_collapsed     = (!(lev_collapsed_number.empty) ? to!int(lev_collapsed_number) : 0);
-    _comp_obj_heading_.parent_ocn                = p_["obj_cite_number"];
-    _comp_obj_heading_.parent_lev_markup         = p_["lev_markup_number"];
-    _comp_obj_heading_.heading_ancestors_text    = lv_ancestors;
-    _comp_obj_heading_.ptr_doc_object            = cntr_;
-    _comp_obj_heading_.ptr_html_segnames         = ((lev_markup_number == "4") ? html_segnames_ptr : 0);
-    _comp_obj_heading_.ptr_heading               = ptr_;
-    debug(node) {
-      if (match(lev_markup_number, rgx.levels_numbered_headings)) {
-        writeln("* ", to!string(_node));
-      }
-    }
-    debug(nodeheading) {
-      if (match(lev_markup_number, rgx.levels_numbered_headings)) {
-        writeln("* ", to!string(_node));
-      }
-    }
-    assert(_comp_obj_heading_.parent_lev_markup <= 7);
-    assert(_comp_obj_heading_.parent_ocn >= 0);
-    if (match(lev_markup_number, rgx.levels_numbered_headings)) {
-      assert(_comp_obj_heading_.heading_lev_markup <= 7);
-      assert(_comp_obj_heading_.ocn >= 0);
-      if (_comp_obj_heading_.parent_lev_markup > 0) {
-        assert(_comp_obj_heading_.parent_lev_markup < _comp_obj_heading_.heading_lev_markup);
-        if (_comp_obj_heading_.ocn != 0) {
-          assert(_comp_obj_heading_.parent_ocn < _comp_obj_heading_.ocn);
-        }
-      }
-      if (_comp_obj_heading_.heading_lev_markup == 0) {
-        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A);
-      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_B) {
-        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A);
-      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_C) {
-        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_B);
-      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_D) {
-        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_C);
-      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_1) {
-        assert(_comp_obj_heading_.parent_lev_markup <= DocStructMarkupHeading.h_sect_D);
-      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_2) {
-        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_1);
-      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_3) {
-        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_2);
-      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_4) {
-        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_3);
-      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_5) {
-      }
-    }
-    return _comp_obj_heading_;
-  }
-  invariant() {
-  }
-#+END_SRC
-
-***** metadata node struct close
-
-#+name: ao_emitters_metadata
-#+BEGIN_SRC d
-}
-#+END_SRC
-
-*** function assertions                                        :assertions:
-**** mixin template: assertions on markup document structure :doc_structure:
-
-#+name: abs_functions_assertions
-#+BEGIN_SRC d
-auto assertions_doc_structure(O,Lv)(
-  O  an_object,
-  Lv lv
-) {
-  debug(asserts){
-    static assert(is(typeof(an_object) == string[string]));
-    static assert(is(typeof(lv)        == int[string]));
-  }
-  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;
-  }
-}
-#+END_SRC
-
-**** mixin template: assertions on blocks                         :blocks:
-
-#+name: abs_functions_assertions
-#+BEGIN_SRC d
-auto assertions_flag_types_block_status_none_or_closed(T)(T type) {
-  debug(asserts){
-    static assert(is(typeof(type) == int[string]));
-  }
-  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");
-}
-#+END_SRC
-
-* 2. Object Setter                                          :abstract:object:
-
-set abstracted objects for downstream processing
-
-** 0. ao object setter:                                   :ao_object_setter:
-
-#+BEGIN_SRC d :tangle ../src/sdp/ao_object_setter.d
-/++
-  object setter:
-  setting of sisu objects for downstream processing
-  ao_object_setter.d
-+/
-template ObjectSetter() {
-  /+ structs +/
-  <<ao_structs_init>>
-}
-#+END_SRC
-
-** 1. initialize structs                                            :struct:
-*** heading attribute
-
-#+name: ao_structs_init
-#+BEGIN_SRC d
-struct HeadingAttrib {
-  string lev                            = "9";
-  int    heading_lev_markup             = 9;
-  int    heading_lev_collapsed          = 9;
-  int[]  closes_lev_collapsed           = [];
-  int[]  closes_lev_markup              = [];
-  int    array_ptr                      = 0;
-  int    heading_array_ptr_segments     = 0;
-}
-#+END_SRC
-
-*** TODO composite object
-
-#+name: ao_structs_init
-#+BEGIN_SRC d
-struct ObjGenericComposite {
-  // size_t id;
-  string                 use                          = "";
-  string                 is_of                        = "";
-  string                 is_a                         = "";
-  string                 text                         = "";
-  string                 obj_cite_number              = "";
-  string[]               anchor_tags                  = [];
-  string                 marked_up_level              = "9";
-  int[]                  closes_lev_collapsed         = [];
-  int[]                  closes_lev_markup            = [];
-  int                    indent_base                  = 0;
-  int                    indent_hang                  = 0;
-  bool                   bullet                       = false;
-  string                 syntax                       = "";
-  int                    ocn                          = 0;
-  string                 segment_anchor_tag           = "";
-  string                 segname_prev                 = "";
-  string                 segname_next                 = "";
-  int                    parent_lev_markup            = 0;
-  int                    parent_ocn                   = 0;
-  int[]                  ancestors                    = [];
-  int                    heading_lev_markup           = 9;
-  int                    heading_lev_collapsed        = 9;
-  int[]                  heading_closes_lev_collapsed = [];
-  int[]                  heading_closes_lev_markup    = [];
-  string[]               heading_ancestors_text       = [ "", "", "", "", "", "", "", "", ];
-  int                    heading_array_ptr            = 0;
-  int                    ptr_doc_object               = 0;
-  int                    ptr_html_segnames            = 0;
-  int                    ptr_heading                  = 0;
-  int                    array_ptr                    = 0;
-  int                    heading_array_ptr_segments   = 0;
-  string[]               lev4_subtoc                  = [];
-  string[string][string] node;
-  int[]                  dom_markedup                 = [ 0, 0, 0, 0, 0, 0, 0, 0,];
-  int[]                  dom_collapsed                = [ 0, 0, 0, 0, 0, 0, 0, 0,];
-}
-#+END_SRC
-
-*** The Objects: generic composite object array
-
-#+name: ao_structs_init
-#+BEGIN_SRC d
-struct TheObjects {
-  ObjGenericComposite[] oca;
-}
-#+END_SRC
diff --git a/org/ao_doc_abstraction.org b/org/ao_doc_abstraction.org
new file mode 100644
index 0000000..6911b63
--- /dev/null
+++ b/org/ao_doc_abstraction.org
@@ -0,0 +1,5998 @@
+#+TITLE: sdp document abstraction
+#+AUTHOR: Ralph Amissah
+#+EMAIL: ralph.amissah@gmail.com
+#+STARTUP: indent
+#+LANGUAGE: en
+#+OPTIONS: H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
+#+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
+#+OPTIONS: author:nil email:nil creator:nil timestamp:nil
+#+PROPERTY: header-args :padline no :exports code :noweb yes
+#+EXPORT_SELECT_TAGS: export
+#+EXPORT_EXCLUDE_TAGS: noexport
+#+FILETAGS: :sdp:rel:ao:
+#+TAGS: assert(a) class(c) debug(d) mixin(m) sdp(s) tangle(T) template(t) WEB(W) noexport(n)
+
+[[./sdp.org][sdp]]  [[./][org/]]
+* 1. Document Abstraction                                  :abstract:process:
+Process markup document, create document abstraction.
+
+** 0. ao abstract doc source:                       :ao_abstract_doc_source:
+
+#+BEGIN_SRC d :tangle ../src/sdp/ao_abstract_doc_source.d
+/++
+  document abstraction:
+  abstraction of sisu markup for downstream processing
+  ao_abstract_doc_source.d
++/
+template SiSUdocAbstraction() {
+  /+ ↓ abstraction imports +/
+  <<abs_imports>>
+  /+ ↓ abstraction mixins +/
+  <<abs_mixins>>
+  /+ ↓ abstraction struct init +/
+  <<abs_init_struct>>
+  /+ ↓ abstract marked up document +/
+  auto SiSUdocAbstraction(Src,Make,Meta,Opt)(
+    Src                  markup_sourcefile_content,
+    Make                 dochead_make_aa,
+    Meta                 dochead_meta_aa,
+    Opt                  opt_action_bool,
+  ) {
+    auto rgx = Rgx();
+    debug(asserts){
+      static assert(is(typeof(markup_sourcefile_content) == char[][]));
+      static assert(is(typeof(dochead_make_aa)           == string[string][string]));
+      static assert(is(typeof(dochead_meta_aa)           == string[string][string]));
+      static assert(is(typeof(opt_action_bool)           == bool[string]));
+    }
+    /+ ↓ abstraction init +/
+    <<abs_init_rest>>
+    /+ abstraction init ↑ +/
+    /+ ↓ loop markup document/text line by line +/
+    srcDocLoop:
+    foreach (line; markup_sourcefile_content) {
+      /+ ↓ markup document/text line by line +/
+      <<abs_in_loop_body_00>>
+      if (type["code"] == TriState.on) {
+        <<abs_in_loop_body_00_code_block>>
+      } else if (!matchFirst(line, rgx.skip_from_regular_parse)) {
+        /+ object other than "code block" object
+           (includes regular text paragraph, headings & blocks other than code) +/
+        <<abs_in_loop_body_non_code_obj>>
+        } else {
+          /+ not within a block group +/
+          <<abs_in_loop_body_open_block_obj_assert>>
+          if (matchFirst(line, rgx.block_open)) {
+            <<abs_in_loop_body_open_block_obj>>
+          } else if (!line.empty) {
+            /+ line not empty +/
+            /+ non blocks (headings, paragraphs) & closed blocks +/
+            <<abs_in_loop_body_not_block_obj>>
+          } else if (type["blocks"] == TriState.closing) {
+            /+ line empty, with blocks flag +/
+            <<abs_in_loop_body_not_block_obj_line_empty_blocks_flags>>
+          } else {
+            /+ line.empty, post contents, empty variables: +/
+            <<abs_in_loop_body_not_block_obj_line_empty>>
+          } // close else for line empty
+        } // close else for not the above
+      } // close after non code, other blocks or regular text
+      <<abs_in_loop_body_01>>
+    } /+ ← closed: loop markup document/text line by line +/
+    /+ ↓ post loop markup document/text +/
+    <<abs_post>>
+    /+ post loop markup document/text ↑ +/
+  } /+ ← closed: abstract doc source +/
+  /+ ↓ abstraction functions +/
+  <<abs_functions_object_reset>>
+  <<abs_functions_header_set_common>>
+  <<abs_functions_ocn_status>>
+  <<abs_functions_block>>
+  <<abs_functions_block_code>>
+  <<abs_functions_block_biblio>>
+  // <<abs_functions_block_glossary>>
+  <<abs_functions_block_poem>>
+  <<abs_functions_block_group>>
+  <<abs_functions_block_block>>
+  <<abs_functions_block_quote>>
+  <<abs_functions_block_table>>
+  <<abs_functions_block_line_status_empty>>
+  <<abs_functions_book_index>>
+  <<abs_functions_heading>>
+  <<abs_functions_para>>
+  /+ abstraction functions ↑ +/
+  /+ ↓ abstraction function emitters +/
+  <<ao_emitters_ocn>>
+  /+ +/
+  <<ao_emitters_obj_inline_markup_munge>>
+  <<ao_emitters_obj_inline_markup>>
+  <<ao_emitters_obj_inline_markup_and_anchor_tags>>
+  <<ao_emitters_obj_inline_markup_table_of_contents>>
+  <<ao_emitters_obj_inline_markup_private>>
+  <<ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags>>
+  <<ao_emitters_obj_inline_markup_close>>
+  /+ +/
+  <<ao_emitters_obj_attributes>>
+  <<ao_emitters_obj_attributes_public>>
+  <<ao_emitters_obj_attributes_private>>
+  <<ao_emitters_obj_attributes_private_an_attribute>>
+  <<ao_emitters_obj_attributes_private_json>>
+  <<ao_emitters_obj_attributes_private_close>>
+  /+ +/
+  <<ao_emitters_book_index_nugget>>
+  <<ao_emitters_book_index_report_indented>>
+  <<ao_emitters_book_index_report_section>>
+  /+ +/
+  <<ao_emitters_endnotes>>
+  /+ +/
+  <<ao_emitters_bibliography>>
+  /+ +/
+  <<ao_emitters_metadata>>
+  /+ abstraction functions emitters ↑ +/
+  /+ ↓ abstraction functions assertions +/
+  <<abs_functions_assertions>>
+  /+ abstraction functions assertions ↑ +/
+} /+ ← closed: template SiSUdocAbstraction +/
+#+END_SRC
+
+** 1. _pre loop processing_                                            :pre:
+*** imports                                                       :imports:
+
+[[./ao_defaults.org][ao_defaults]]
+
+#+name: abs_imports
+#+BEGIN_SRC d
+import
+  ao_object_setter,
+  ao_defaults,
+  ao_rgx,
+  output_hub;
+private import
+  std.algorithm,
+  std.array,
+  std.container,
+  std.exception,
+  std.file,
+  std.getopt,
+  std.json,
+  std.path,
+  std.process,
+  std.range,
+  std.regex,
+  std.stdio,
+  std.string,
+  std.traits,
+  std.typecons,
+  std.uni,
+  std.utf,
+  std.conv : to;
+#+END_SRC
+
+*** mixins                                                         :mixins:
+
+#+name: abs_mixins
+#+BEGIN_SRC d
+mixin ObjectSetter;
+mixin InternalMarkup;
+mixin SiSUrgxInit;
+#+END_SRC
+
+*** initialize                                                 :initialize:
+**** initialize general
+
+#+name: abs_init_struct
+#+BEGIN_SRC d
+/+ initialize +/
+ObjGenericComposite[][string] the_table_of_contents_section;
+ObjGenericComposite[] the_document_head_section, the_document_body_section, the_bibliography_section, the_glossary_section, the_blurb_section;
+ObjGenericComposite[] the_dom_tail_section;
+string[string] an_object, processing;
+string an_object_key;
+string[] anchor_tags;
+string anchor_tag_;
+string segment_anchor_tag_that_object_belongs_to;
+string segment_anchor_tag_that_object_belongs_to_uri;
+auto note_section = NotesSection();
+/+ enum +/
+enum State { off, on }
+enum TriState { off, on, closing }
+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 }
+/+ biblio variables +/
+string biblio_tag_name, biblio_tag_entry, st;
+string[] biblio_arr_json;
+string biblio_entry_str_json;
+JSONValue[] bib_arr_json;
+int bib_entry;
+/+ counters +/
+int cntr, previous_count, previous_length;
+int[string] line_occur;
+string[] html_segnames=["toc"];
+int html_segnames_ptr=0;
+int html_segnames_ptr_cntr=0;
+int verse_line, heading_ptr;
+/+ paragraph attributes +/
+int[string] indent;
+bool bullet = true;
+string content_non_header = "8";
+auto obj_im = ObjInlineMarkup();
+auto obj_att = ObjAttributes();
+/+ ocn +/
+int obj_cite_number, obj_cite_number_;
+auto object_citation_number = OCNemitter();
+int[] dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
+int[] dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
+int[] dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
+int[] dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
+enum DomTags { none, open, close, close_and_open, open_still, }
+#+END_SRC
+
+**** initialize heading ancestors
+
+#+name: abs_init_struct
+#+BEGIN_SRC d
+void heading_ancestors(O)(
+  auto ref O         obj,
+  ref string[]       lv_ancestors,
+) {
+  switch (obj.heading_lev_markup) {
+  case 0:
+    lv_ancestors[0] = to!string(obj.text);
+    foreach(k; 1..8) {
+      lv_ancestors[k] = "";
+    }
+    goto default;
+  case 1:
+    lv_ancestors[1] = to!string(obj.text);
+    foreach(k; 2..8) {
+      lv_ancestors[k] = "";
+    }
+    goto default;
+  case 2:
+    lv_ancestors[2] = to!string(obj.text);
+    foreach(k; 3..8) {
+      lv_ancestors[k] = "";
+    }
+    goto default;
+  case 3:
+    lv_ancestors[3] = to!string(obj.text);
+    foreach(k; 4..8) {
+      lv_ancestors[k] = "";
+    }
+    goto default;
+  case 4:
+    lv_ancestors[4] = to!string(obj.text);
+    foreach(k; 5..8) {
+      lv_ancestors[k] = "";
+    }
+    goto default;
+  case 5:
+    lv_ancestors[5] = to!string(obj.text);
+    foreach(k; 6..8) {
+      lv_ancestors[k] = "";
+    }
+    goto default;
+  case 6:
+    lv_ancestors[6] = to!string(obj.text);
+    lv_ancestors[7] = "";
+    goto default;
+  case 7:
+    lv_ancestors[7] = to!string(obj.text);
+    goto default;
+  default:
+    obj.heading_ancestors_text = lv_ancestors.dup;
+  }
+}
+#+END_SRC
+
+**** initialize dom markup tags
+
+#+name: abs_init_struct
+#+BEGIN_SRC d
+auto dom_set_markup_tags(int[] dom, int lev) {
+  foreach (i; 0 .. 8) {
+    if (i < lev) {
+      if (dom[i] == DomTags.open
+         || dom[i] == DomTags.close_and_open
+      ) {
+        dom[i] = DomTags.open_still;
+      } else if (dom[i] == DomTags.close) {
+        dom[i] = DomTags.none;
+      }
+    } else if (i == lev) {
+      if (lev  == 0
+        && dom[i] == DomTags.open_still
+      ) {
+        dom[i] = DomTags.close;
+      } else if (dom[i] == DomTags.open
+        || dom[i] == DomTags.open_still
+        || dom[i] == DomTags.close_and_open
+      ) {
+        dom[i] = DomTags.close_and_open;
+      } else {
+        dom[i] = DomTags.open;
+      }
+    } else if (i > lev) {
+      if (dom[i] == DomTags.close) {
+        dom[i] = DomTags.none;
+      } else if (dom[i] == DomTags.open
+        || dom[i] == DomTags.open_still
+        || dom[i] == DomTags.close_and_open
+      ) {
+        dom[i] = DomTags.close;
+      }
+    }
+  }
+  debug(dom) {
+    writeln(lev, ": ", dom);
+  }
+  return dom;
+}
+#+END_SRC
+
+**** initialize dom collapsed tags
+
+#+name: abs_init_struct
+#+BEGIN_SRC d
+auto dom_set_collapsed_tags(int[] dom, int lev) {
+  foreach (i; 0 .. 8) {
+    if (i < lev) {
+      if (dom[i] == DomTags.open
+         || dom[i] == DomTags.close_and_open
+      ) {
+        dom[i] = DomTags.open_still;
+      } else if (dom[i] == DomTags.close) {
+        dom[i] = DomTags.none;
+      }
+    } else if (i == lev) {
+      if (lev  == 0
+        && dom[i] == DomTags.open_still
+      ) {
+        dom[i] = DomTags.close;
+      } else if (dom[i] == DomTags.open
+        || dom[i] == DomTags.open_still
+        || dom[i] == DomTags.close_and_open
+      ) {
+        dom[i] = DomTags.close_and_open;
+      } else {
+        dom[i] = DomTags.open;
+      }
+    } else if (i > lev) {
+      if (dom[i] == DomTags.close) {
+        dom[i] = DomTags.none;
+      } else if (dom[i] == DomTags.open
+        || dom[i] == DomTags.open_still
+        || dom[i] == DomTags.close_and_open
+      ) {
+        dom[i] = DomTags.close;
+      }
+    }
+  }
+  debug(dom) {
+    writeln(lev, ": ", dom);
+  }
+  return dom;
+}
+#+END_SRC
+
+**** initialize ocn emit
+
+#+name: abs_init_struct
+#+BEGIN_SRC d
+int ocn_emit(int ocn_status_flag) {
+  return object_citation_number.ocn_emitter(ocn_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 +/
+ObjGenericComposite comp_obj_heading, comp_obj_location, comp_obj_block, comp_obj_code, comp_obj_poem_ocn, comp_obj_comment;
+auto node_construct = NodeStructureMetadata();
+#+END_SRC
+
+*** scope
+
+#+name: abs_init_rest
+#+BEGIN_SRC d
+scope(success) {
+}
+scope(failure) {
+}
+scope(exit) {
+  destroy(the_document_head_section);
+  destroy(the_table_of_contents_section);
+  destroy(the_document_body_section);
+  destroy(the_bibliography_section);
+  destroy(an_object);
+  destroy(processing);
+  destroy(biblio_arr_json);
+}
+#+END_SRC
+
+*** init rest
+
+#+name: abs_init_rest
+#+BEGIN_SRC d
+mixin SiSUrgxInitFlags;
+mixin SiSUnode;
+auto node_para_int_    = node_metadata_para_int;
+auto node_para_str_    = node_metadata_para_str;
+ObjGenericComposite comp_obj_heading_, comp_obj_para, comp_obj_toc;
+line_occur = [
+  "heading"  : 0,
+  "para"     : 0,
+  "glossary" : 0,
+  "blurb"    : 0,
+];
+auto type = flags_type_init;
+string[string] obj_cite_number_poem = [
+  "start" : "",
+  "end"   : ""
+];
+string[] lv_ancestors = [ "", "", "", "", "", "", "", "", ];
+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_int_collapsed" : 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)")
+];
+string _anchor_tag;
+string toc_txt_;
+an_object["glossary_nugget"] = "";
+an_object["blurb_nugget"] = "";
+comp_obj_heading_                       = comp_obj_heading_.init;
+comp_obj_heading_.use                   = "frontmatter";
+comp_obj_heading_.is_of                 = "para";
+comp_obj_heading_.is_a                  = "heading";
+comp_obj_heading_.text                  = "Table of Contents";
+comp_obj_heading_.ocn                   = 0;
+comp_obj_heading_.obj_cite_number       = "";
+comp_obj_heading_.segment_anchor_tag    = "toc";
+comp_obj_heading_.marked_up_level       = "1";
+comp_obj_heading_.heading_lev_markup    = 4;
+comp_obj_heading_.heading_lev_collapsed = 1;
+comp_obj_heading_.parent_ocn            = 1;
+comp_obj_heading_.parent_lev_markup     = 0;
+comp_obj_heading_.ptr_html_segnames     = html_segnames_ptr;
+comp_obj_heading_.anchor_tags           = ["toc"];
+auto toc_head                           = comp_obj_heading_;
+html_segnames_ptr_cntr++;
+the_table_of_contents_section = [
+  "seg": [toc_head],
+  "scroll": [toc_head],
+];
+auto mkup = InlineMarkup();
+auto munge = ObjInlineMarkupMunge();
+string[][string] lev4_subtoc;
+#+END_SRC
+
+** 2. _loop: process document body_ [+6]                              :loop:
+*** loop scope                                                      :scope:
+
+#+name: abs_in_loop_body_00
+#+BEGIN_SRC d
+/+ scope +/
+scope(exit) {
+}
+scope(failure) {
+  stderr.writefln(
+    "%s\n%s\n%s:%s failed here:\n  line: %s",
+    __MODULE__, __FUNCTION__,
+    __FILE__, __LINE__,
+    line,
+  );
+}
+line = replaceAll(line, rgx.true_dollar, "$$$$");
+  // dollar represented as $$ needed to stop submatching on $
+  // (substitutions using ${identifiers} must take into account (i.e. happen earlier))
+debug(source) {                                  // source lines
+  writeln(line);
+}
+debug(srclines) {
+  if (!line.empty) {                             // source lines, not empty
+    writefln(
+      "* %s",
+      line
+    );
+  }
+}
+#+END_SRC
+
+*** check whether obj_cite_number is on or turned off                 :ocn:
+
+#+name: abs_in_loop_body_00
+#+BEGIN_SRC d
+if (!line.empty) {
+  _check_ocn_status_(line, type);
+}
+#+END_SRC
+
+*** [#A] separate regular markup text from code blocks [+5]
+**** code blocks                                              :block:code:
+
+#+name: abs_in_loop_body_00_code_block
+#+BEGIN_SRC d
+/+ block object: code +/
+_code_block_(line, an_object, type);
+continue;
+#+END_SRC
+
+**** non code objects (other blocks or regular text) [+4]       :non_code:
+***** in section (biblio, glossary, blurb) (block group) [+1] :block:active:
+****** within section: biblio                                   :biblio:
+
+#+name: abs_in_loop_body_non_code_obj
+#+BEGIN_SRC d
+if ((matchFirst(line, rgx.heading_biblio)
+|| (type["biblio_section"] == State.on
+&& (!matchFirst(line, rgx.heading_blurb_glossary))))
+&& (!matchFirst(line, rgx.heading))
+&& (!matchFirst(line, rgx.comment))) {
+  /+ within section (block object): biblio +/
+  type["glossary_section"] = State.off;
+  type["biblio_section"] = State.on;
+  type["blurb_section"] = State.off;
+  if (opt_action_bool["backmatter"] && opt_action_bool["section_biblio"]) {
+    _biblio_block_(line, type, bib_entry, biblio_entry_str_json, biblio_arr_json); //
+    debug(bibliobuild) {
+      writeln("-  ", biblio_entry_str_json);
+      writeln("-> ", biblio_arr_json.length);
+    }
+  }
+  continue;
+#+END_SRC
+
+****** within section: glossary                               :glossary:
+
+if there is a glossary section you need to:
+- extract it
+- create standard headings
+- markup contents in standard way like regular paragraphs
+  - need indentation and regular paragraph inline markup
+- reconstitute the document with the glossary section following the endnotes
+
+#+name: abs_in_loop_body_non_code_obj
+#+BEGIN_SRC d
+} else if ((matchFirst(line, rgx.heading_glossary)
+|| (type["glossary_section"] == State.on
+&& (!matchFirst(line, rgx.heading_biblio_blurb))))
+&& (!matchFirst(line, rgx.heading))
+&& (!matchFirst(line, rgx.comment))) {
+  /+ within section (block object): glossary +/
+  debug(glossary) {
+    writeln(__LINE__);
+    writeln(line);
+  }
+  // _glossary_block_(line, type);
+  type["glossary_section"] = State.on;
+  type["biblio_section"] = State.off;
+  type["blurb_section"] = State.off;
+  if (opt_action_bool["backmatter"] && opt_action_bool["section_glossary"]) {
+    indent=[
+      "hang_position" : 0,
+      "base_position" : 0,
+    ];
+    bullet = false;
+    type["para"] = State.on;
+    line_occur["para"] = State.off;
+    an_object_key="glossary_nugget"; //
+    if (matchFirst(line, rgx.heading_glossary)) {
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.use                   = "backmatter";
+      comp_obj_heading_.is_of                 = "para";
+      comp_obj_heading_.is_a                  = "heading";
+      comp_obj_heading_.text                  = "Glossary";
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.marked_up_level       = "B";
+      comp_obj_heading_.heading_lev_markup    = 1;
+      comp_obj_heading_.heading_lev_collapsed = 1;
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      the_glossary_section                    ~= comp_obj_heading_;
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.use                   = "backmatter";
+      comp_obj_heading_.is_of                 = "para";
+      comp_obj_heading_.is_a                  = "heading";
+      comp_obj_heading_.text                  = "Glossary";
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.segment_anchor_tag    = "glossary";
+      comp_obj_heading_.marked_up_level       = "1";
+      comp_obj_heading_.heading_lev_markup    = 4;
+      comp_obj_heading_.heading_lev_collapsed = 2;
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      comp_obj_heading_.anchor_tags           = ["glossary"];
+      the_glossary_section                    ~= comp_obj_heading_;
+    } else {
+      _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
+      comp_obj_para                       = comp_obj_para.init;
+      comp_obj_para.use                   = "backmatter";
+      comp_obj_para.is_of                 = "para";
+      comp_obj_para.is_a                  = "glossary";
+      comp_obj_para.text                  = to!string(line).strip;
+      comp_obj_para.ocn                   = 0;
+      comp_obj_para.obj_cite_number       = "";
+      comp_obj_para.indent_hang           = indent["hang_position"];
+      comp_obj_para.indent_base           = indent["base_position"];
+      comp_obj_para.bullet                = bullet;
+      the_glossary_section                ~= comp_obj_para;
+    }
+    type["ocn_status"] = TriState.off;
+  }
+  continue;
+#+END_SRC
+
+****** within section: blurb                                     :blurb:
+
+if there is a blurb section you need to:
+- extract it
+- create standard headings (or use line provided in 1~ heading)
+- markup contents in standard way like regular paragraphs
+  - need regular paragraph inline markup
+- reconstitute the document with the blurb section at the very end of the doucment
+
+#+name: abs_in_loop_body_non_code_obj
+#+BEGIN_SRC d
+} else if ((matchFirst(line, rgx.heading_blurb)
+|| (type["blurb_section"] == State.on
+&& (!matchFirst(line, rgx.heading_biblio_glossary))))
+&& (!matchFirst(line, rgx.heading))
+&& (!matchFirst(line, rgx.comment))) {
+  /+ within section (block object): blurb +/
+  debug(blurb) {
+    writeln(__LINE__);
+    writeln(line);
+  }
+  type["glossary_section"] = State.off;
+  type["biblio_section"] = State.off;
+  type["blurb_section"] = State.on;
+  if (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"]) {
+    indent=[
+      "hang_position" : 0,
+      "base_position" : 0,
+    ];
+    bullet = false;
+    type["para"] = State.on;
+    line_occur["para"] = State.off;
+    an_object_key="blurb_nugget";
+    if (matchFirst(line, rgx.heading_blurb)) {
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.use                   = "backmatter";
+      comp_obj_heading_.is_of                 = "para";
+      comp_obj_heading_.is_a                  = "heading";
+      comp_obj_heading_.text                  = "Blurb";
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.marked_up_level       = "B";
+      comp_obj_heading_.heading_lev_markup    = 1;
+      comp_obj_heading_.heading_lev_collapsed = 1;
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      the_blurb_section                       ~= comp_obj_heading_;
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.use                   = "backmatter";
+      comp_obj_heading_.is_of                 = "para";
+      comp_obj_heading_.is_a                  = "heading";
+      comp_obj_heading_.text                  = "Blurb";
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.segment_anchor_tag    = "blurb";
+      comp_obj_heading_.marked_up_level       = "1";
+      comp_obj_heading_.heading_lev_markup    = 4;
+      comp_obj_heading_.heading_lev_collapsed = 2;
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      comp_obj_heading_.anchor_tags           = ["blurb"];
+      the_blurb_section                       ~= comp_obj_heading_;
+    } else if ((matchFirst(line, rgx.heading))
+    && (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"])) {
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.use                   = "backmatter";
+      comp_obj_heading_.is_of                 = "para";
+      comp_obj_heading_.is_a                  = "heading";
+      comp_obj_heading_.text                  = to!string(line);
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.segment_anchor_tag    = "blurb";
+      comp_obj_heading_.marked_up_level       = to!string(an_object["lev"]);
+      comp_obj_heading_.heading_lev_markup    = to!int(an_object["lev_markup_number"]);    // make int, remove need to conv
+      comp_obj_heading_.heading_lev_collapsed = to!int(an_object["lev_collapsed_number"]); // make int, remove need to conv
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      the_blurb_section                   ~= comp_obj_heading_;
+    } else {
+      _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
+      comp_obj_para                       = comp_obj_para.init;
+      comp_obj_para.use                   = "backmatter";
+      comp_obj_para.is_of                 = "para";
+      comp_obj_para.is_a                  = "blurb";
+      comp_obj_para.text                  = to!string(line).strip;
+      comp_obj_para.ocn                   = 0;
+      comp_obj_para.obj_cite_number       = "";
+      comp_obj_para.indent_hang           = indent["hang_position"];
+      comp_obj_para.indent_base           = indent["base_position"];
+      comp_obj_para.bullet                = bullet;
+      the_blurb_section                   ~= comp_obj_para;
+    }
+    type["ocn_status"] = TriState.off;
+  }
+  continue;
+#+END_SRC
+
+***** in blocks [+1]                                       :block:active:
+****** within block: poem                                         :poem:
+
+#+name: abs_in_loop_body_non_code_obj
+#+BEGIN_SRC d
+} else if (type["poem"] == TriState.on) {
+  /+ within block object: poem +/
+  _poem_block_(line, an_object, type, cntr, obj_cite_number_poem, dochead_make_aa);
+  continue;
+#+END_SRC
+
+****** within block: group                                       :group:
+
+#+name: abs_in_loop_body_non_code_obj
+#+BEGIN_SRC d
+/+ within block object: group +/
+} else if (type["group"] == TriState.on) {
+  /+ within block object: group +/
+  _group_block_(line, an_object, type);
+  continue;
+#+END_SRC
+
+****** within block: block                                       :block:
+
+#+name: abs_in_loop_body_non_code_obj
+#+BEGIN_SRC d
+} else if (type["block"] == TriState.on) {
+  /+ within block object: block +/
+  _block_block_(line, an_object, type);
+  continue;
+#+END_SRC
+
+****** within block: quote                                       :quote:
+
+#+name: abs_in_loop_body_non_code_obj
+#+BEGIN_SRC d
+} else if (type["quote"] == TriState.on) {
+  /+ within block object: quote +/
+  _quote_block_(line, an_object, type);
+  continue;
+#+END_SRC
+
+****** within block: table                                       :table:
+
+#+name: abs_in_loop_body_non_code_obj
+#+BEGIN_SRC d
+} else if (type["table"] == TriState.on) {
+  /+ within block object: table +/
+  _table_block_(line, an_object, type);
+  continue;
+#+END_SRC
+
+***** not identified as being within block group (could still be, or not) [+3]
+****** assert
+
+#+name: abs_in_loop_body_open_block_obj_assert
+#+BEGIN_SRC d
+assert(
+  (type["blocks"] == TriState.off)
+  || (type["blocks"] == TriState.closing),
+  "block status: none or closed"
+);
+assertions_flag_types_block_status_none_or_closed(type);
+#+END_SRC
+
+****** block open
+
+#+name: abs_in_loop_body_open_block_obj
+#+BEGIN_SRC d
+if (matchFirst(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);
+}
+_start_block_(line, type, obj_cite_number_poem);
+continue;
+#+END_SRC
+
+****** line not empty [+2]
+******* asserts                                                :assert:
+
+#+name: abs_in_loop_body_not_block_obj
+#+BEGIN_SRC d
+assert(
+  !line.empty,
+  "line tested, line not empty surely"
+);
+assert(
+  (type["blocks"] == TriState.off)
+  || (type["blocks"] == TriState.closing),
+  "code block status: none or closed"
+);
+if (type["blocks"] == TriState.closing) {
+  // blocks closed, unless followed by book index
+  debug(check) {                           // block
+    writeln(__LINE__);
+    writeln(line);
+  }
+  assert(
+    matchFirst(line, rgx.book_index)
+    || matchFirst(line, rgx.book_index_open)
+    || type["book_index"] == State.on
+  );
+}
+#+END_SRC
+
+******* book index                                          :bookindex:
+
+#+name: abs_in_loop_body_not_block_obj
+#+BEGIN_SRC d
+if ((matchFirst(line, rgx.book_index))
+|| (matchFirst(line, rgx.book_index_open))
+|| (type["book_index"] == State.on ))  {
+  /+ book_index +/
+  _book_index_(line, book_idx_tmp, an_object, type, opt_action_bool);
+#+END_SRC
+
+******* not book index [+1]
+
+#+name: abs_in_loop_body_not_block_obj
+#+BEGIN_SRC d
+} else {
+  /+ not book_index +/
+#+END_SRC
+
+******** matched: comment                              :comment:match:
+
+#+name: abs_in_loop_body_not_block_obj
+#+BEGIN_SRC d
+  an_object_key="body_nugget";
+  if (auto m = matchFirst(line, rgx.comment)) {
+    /+ matched comment +/
+    debug(comment) {
+      writeln(line);
+    }
+    an_object[an_object_key] ~= line ~= "\n";
+    comp_obj_comment                   = comp_obj_comment.init;
+    comp_obj_comment.use               = "comment";
+    comp_obj_comment.is_of             = "comment";
+    comp_obj_comment.is_a              = "comment";
+    comp_obj_comment.text              = an_object[an_object_key].strip;
+    the_document_body_section          ~= comp_obj_comment;
+    _common_reset_(line_occur, an_object, type);
+    processing.remove("verse");
+    ++cntr;
+#+END_SRC
+
+******** flag not set & line not exist: heading or para :heading:paragraph:
+
+#+name: abs_in_loop_body_not_block_obj
+#+BEGIN_SRC d
+  } 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 ((dochead_make_aa["make"]["headings"].length > 2)
+    && (type["make_headings"] == State.off)) {
+      /+ heading found +/
+      _heading_found_(line, dochead_make_aa["make"]["headings"], heading_match_str, heading_match_rgx, 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 +/
+      _heading_make_set_(line, line_occur, heading_match_rgx, type);
+    }
+    /+ TODO node info: all headings identified at this point,
+       - extract node info here??
+       - how long can it wait?
+       - should be incorporated in composite objects
+       - should happen before endnote links set (they need to be moved down?)
+      // node_construct.node_emitter_heading segment anchor tag
+    +/
+    if (matchFirst(line, rgx.heading)) {
+      /+ heading match +/
+      _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa);
+    } else if (line_occur["para"] == State.off) {
+      /+ para match +/
+      an_object_key="body_nugget";
+      _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
+    }
+#+END_SRC
+
+******** line exist: heading                                 :heading:
+
+#+name: abs_in_loop_body_not_block_obj
+#+BEGIN_SRC d
+  } else if (line_occur["heading"] > State.off) {
+    /+ heading +/
+    debug(heading) {
+      writeln(line);
+    }
+    an_object[an_object_key] ~= line ~= "\n";
+    ++line_occur["heading"];
+#+END_SRC
+
+******** line exist: para                                       :para:
+
+#+name: abs_in_loop_body_not_block_obj
+#+BEGIN_SRC d
+  } else if (line_occur["para"] > State.off) {
+    /+ paragraph +/
+    debug(para) {
+      writeln(line);
+    }
+    an_object[an_object_key] ~= " " ~ line;
+    ++line_occur["para"];
+  }
+}
+#+END_SRC
+
+****** line empty, with block flag
+
+#+name: abs_in_loop_body_not_block_obj_line_empty_blocks_flags
+#+BEGIN_SRC d
+_block_flag_line_empty_(
+  line,
+  an_object,
+  the_document_body_section,
+  bookindex_unordered_hashes,
+  obj_cite_number,
+  comp_obj_heading,
+  cntr,
+  type,
+  obj_cite_number_poem,
+  dochead_make_aa
+);
+#+END_SRC
+
+****** line empty [+1]
+******* assert line empty                                      :assert:
+
+#+name: abs_in_loop_body_not_block_obj_line_empty
+#+BEGIN_SRC d
+assert(
+  line.empty,
+  "line should be empty"
+);
+assert(
+  (type["blocks"] == State.off),
+  "code block status: none"
+);
+#+END_SRC
+
+******* heading object                                 :heading:object:
+
+#+name: abs_in_loop_body_not_block_obj_line_empty
+#+BEGIN_SRC d
+if ((type["heading"] == State.on)
+&& (line_occur["heading"] > State.off)) {
+  /+ heading object (current line empty) +/
+  obj_cite_number = (to!int(an_object["lev_markup_number"]) == 0)
+  ? (ocn_emit(3))
+  : (obj_cite_number = ocn_emit(type["ocn_status"]));
+  an_object["bookindex_nugget"] =
+    ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
+  bookindex_unordered_hashes =
+    bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
+  an_object["is"] = "heading";
+  an_object_key="body_nugget";
+  auto substantive_object_and_anchor_tags_tuple =
+    obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+  an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+  anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+  if (to!int(an_object["lev_markup_number"]) == 4) {
+    segment_anchor_tag_that_object_belongs_to = anchor_tags[0];
+    segment_anchor_tag_that_object_belongs_to_uri = anchor_tags[0] ~ ".fnSuffix";
+    anchor_tag_ = anchor_tags[0];
+  } else if (to!int(an_object["lev_markup_number"]) > 4) {
+    segment_anchor_tag_that_object_belongs_to = anchor_tag_;
+    segment_anchor_tag_that_object_belongs_to_uri = anchor_tag_ ~ ".fnSuffix#" ~ to!string(obj_cite_number);
+  } else if (to!int(an_object["lev_markup_number"]) < 4) {
+    segment_anchor_tag_that_object_belongs_to = "";
+    segment_anchor_tag_that_object_belongs_to_uri = "";
+  }
+  /+ (incrementally build toc) table of contents here! +/
+  _anchor_tag=to!string(obj_cite_number);
+  the_table_of_contents_section = obj_im.table_of_contents_gather_headings(
+    an_object,
+    dochead_make_aa,
+    segment_anchor_tag_that_object_belongs_to,
+    _anchor_tag,
+    lev4_subtoc,
+    the_table_of_contents_section,
+  );
+  if (an_object["lev_markup_number"] == "4") {
+    html_segnames ~= segment_anchor_tag_that_object_belongs_to;
+    html_segnames_ptr = html_segnames_ptr_cntr;
+    html_segnames_ptr_cntr++;
+  }
+  auto comp_obj_heading =
+    node_construct.node_emitter_heading(
+      an_object["substantive"],                     // string
+      an_object["lev"],                             // string
+      an_object["lev_markup_number"],               // string
+      an_object["lev_collapsed_number"],            // string
+      segment_anchor_tag_that_object_belongs_to,    // string
+      obj_cite_number,                              // int
+      cntr,                                         // int
+      heading_ptr,                                  // int
+      lv_ancestors,                                 // string[]
+      an_object["is"],                              // string
+      html_segnames_ptr,                            // int
+    );
+  ++heading_ptr;
+  debug(segments) {
+    writeln(an_object["lev_markup_number"]);
+    writeln(segment_anchor_tag_that_object_belongs_to);
+  }
+  the_document_body_section ~= comp_obj_heading;
+  // track previous heading and make assertions
+  debug(objectrelated1) { // check
+    writeln(line);
+  }
+  _common_reset_(line_occur, an_object, type);
+  an_object.remove("lev");
+  an_object.remove("lev_markup_number");
+  processing.remove("verse");
+  ++cntr;
+#+END_SRC
+
+******* paragraph object                             :paragraph:object:
+
+#+name: abs_in_loop_body_not_block_obj_line_empty
+#+BEGIN_SRC d
+} else if ((type["para"] == State.on) && (line_occur["para"] > State.off)) {
+  /+ paragraph object (current line empty) +/
+  obj_cite_number = ocn_emit(type["ocn_status"]);
+  an_object["bookindex_nugget"] =
+    ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
+  bookindex_unordered_hashes =
+    bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
+  an_object["is"] = "para";
+  auto comp_obj_heading =
+    node_construct.node_location_emitter(
+      content_non_header,
+      segment_anchor_tag_that_object_belongs_to,
+      obj_cite_number,
+      cntr,
+      heading_ptr-1,
+      an_object["is"],
+    );
+  auto substantive_object_and_anchor_tags_tuple =
+    obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+  an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+  anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+  comp_obj_para                       = comp_obj_para.init;
+  comp_obj_para.use                   = "body";
+  comp_obj_para.is_of                 = "para";
+  comp_obj_para.is_a                  = "para";
+  comp_obj_para.text                  = to!string(an_object["substantive"]).strip;
+  comp_obj_para.ocn                   = obj_cite_number;
+  comp_obj_para.obj_cite_number       = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+  comp_obj_para.indent_hang           = indent["hang_position"];
+  comp_obj_para.indent_base           = indent["base_position"];
+  comp_obj_para.bullet                = bullet;
+  comp_obj_para.anchor_tags           = anchor_tags;
+  the_document_body_section           ~= comp_obj_para;
+  _common_reset_(line_occur, an_object, type);
+  indent=[
+    "hang_position" : 0,
+    "base_position" : 0,
+  ];
+  bullet = false;
+  processing.remove("verse");
+  ++cntr;
+} else {
+  assert(
+    line == null,
+    "line variable should be empty, should not occur"
+  );
+  // check what happens when paragraph separated by 2 newlines
+}
+#+END_SRC
+
+*** regular text objects                                   :text:paragraph:
+
+#+name: abs_in_loop_body_01
+#+BEGIN_SRC d
+/+ unless (the_document_body_section.length == 0) ? +/
+if (the_document_body_section.length > 0) {
+  if (((the_document_body_section[$-1].is_a == "para")
+  || (the_document_body_section[$-1].is_a == "heading")
+  || (the_document_body_section[$-1].is_a == "group"))
+  && (the_document_body_section.length > previous_length)
+) {
+    if ((the_document_body_section[$-1].is_a == "heading")
+    && (the_document_body_section[$-1].heading_lev_markup < 5)) {
+      type["biblio_section"] = State.off;
+      type["glossary_section"] = State.off;
+      type["blurb_section"] = State.off;
+    }
+    previous_length = to!int(the_document_body_section.length);
+    if (
+      match(the_document_body_section[$-1].text,
+      rgx.inline_notes_delimiter_al_regular_number_note)
+    ) {
+      previous_count=to!int(the_document_body_section.length -1);
+      note_section.gather_notes_for_endnote_section(
+        the_document_body_section,
+        segment_anchor_tag_that_object_belongs_to,
+        to!int(the_document_body_section.length-1),
+      );
+    }
+  }
+}
+#+END_SRC
+
+** 3. _post main-loop processing_                                       :post:
+/+
+  Backmatter:
+  - endnotes
+  - glossary
+  - bibliography / references
+  - book index
+  - blurb
++/
+
+*** tie up preparation of document sections
+**** endnotes section (scroll & seg)                            :endnotes:
+
+#+name: abs_post
+#+BEGIN_SRC d
+auto en_tuple =
+  note_section.endnote_objects(obj_cite_number, opt_action_bool);
+static assert(!isTypeTuple!(en_tuple));
+auto the_endnotes_section = en_tuple[0];
+obj_cite_number = en_tuple[1];
+debug(endnotes) {
+  writefln(
+    "%s %s",
+    __LINE__,
+    the_endnotes_section.length
+  );
+  foreach (o; the_endnotes_section) {
+    writeln(o);
+  }
+}
+#+END_SRC
+
+**** no glossary section?                                       :glossary:
+
+#+name: abs_post
+#+BEGIN_SRC d
+if (an_object["glossary_nugget"].length == 0) {
+  comp_obj_heading_                       = comp_obj_heading_.init;
+  comp_obj_heading_.use                   = "empty";
+  comp_obj_heading_.is_of                 = "para";
+  comp_obj_heading_.is_a                  = "heading";
+  comp_obj_heading_.text                  = "(skip) there is no Glossary section";
+  comp_obj_heading_.ocn                   = 0;
+  comp_obj_heading_.obj_cite_number       = "";
+  comp_obj_heading_.marked_up_level       = "B";
+  comp_obj_heading_.heading_lev_markup    = 1;
+  comp_obj_heading_.heading_lev_collapsed = 1;
+  comp_obj_heading_.parent_ocn            = 1;
+  comp_obj_heading_.parent_lev_markup     = 0;
+  the_glossary_section                    ~= comp_obj_heading_;
+} else {
+  writeln("gloss");
+}
+debug(glossary) {
+  foreach (gloss; the_glossary_section) {
+    writeln(gloss.text);
+  }
+}
+#+END_SRC
+
+**** bibliography section (objects)                         :bibliography:
+
+#+name: abs_post
+#+BEGIN_SRC d
+auto biblio_unsorted_incomplete = biblio_arr_json.dup;
+auto biblio = Bibliography();
+auto biblio_ordered =
+  biblio._bibliography_(biblio_unsorted_incomplete, bib_arr_json);
+#+END_SRC
+
+#+name: abs_post
+#+BEGIN_SRC d
+if (biblio_ordered.length > 0) {
+  comp_obj_heading_                       = comp_obj_heading_.init;
+  comp_obj_heading_.use                   = "backmatter";
+  comp_obj_heading_.is_of                 = "para";
+  comp_obj_heading_.is_a                  = "heading";
+  comp_obj_heading_.text                  = "Bibliography";
+  comp_obj_heading_.ocn                   = 0;
+  comp_obj_heading_.obj_cite_number       = "";
+  comp_obj_heading_.marked_up_level       = "B";
+  comp_obj_heading_.heading_lev_markup    = 1;
+  comp_obj_heading_.heading_lev_collapsed = 1;
+  comp_obj_heading_.parent_ocn            = 1;
+  comp_obj_heading_.parent_lev_markup     = 0;
+  the_bibliography_section                ~= comp_obj_heading_;
+  // ---
+  comp_obj_heading_                       = comp_obj_heading_.init;
+  comp_obj_heading_.use                   = "backmatter";
+  comp_obj_heading_.is_of                 = "para";
+  comp_obj_heading_.is_a                  = "heading";
+  comp_obj_heading_.text                  = "Bibliography";
+  comp_obj_heading_.ocn                   = 0;
+  comp_obj_heading_.obj_cite_number       = "";
+  comp_obj_heading_.segment_anchor_tag    = "bibliography";
+  comp_obj_heading_.marked_up_level       = "1";
+  comp_obj_heading_.heading_lev_markup    = 4;
+  comp_obj_heading_.heading_lev_collapsed = 2;
+  comp_obj_heading_.parent_ocn            = 1;
+  comp_obj_heading_.parent_lev_markup     = 0;
+  comp_obj_heading_.anchor_tags           = ["bibliography"];
+  the_bibliography_section                ~= comp_obj_heading_;
+} else {
+  comp_obj_heading_                       = comp_obj_heading_.init;
+  comp_obj_heading_.use                   = "empty";
+  comp_obj_heading_.is_of                 = "para";
+  comp_obj_heading_.is_a                  = "heading";
+  comp_obj_heading_.text                  = "(skip) there is no Bibliography";
+  comp_obj_heading_.ocn                   = 0;
+  comp_obj_heading_.obj_cite_number       = "";
+  comp_obj_heading_.marked_up_level       = "B";
+  comp_obj_heading_.heading_lev_markup    = 1;
+  comp_obj_heading_.heading_lev_collapsed = 1;
+  comp_obj_heading_.parent_ocn            = 1;
+  comp_obj_heading_.parent_lev_markup     = 0;
+  the_bibliography_section                ~= comp_obj_heading_;
+}
+#+END_SRC
+
+***** format biblio string
+
+#+name: abs_post
+#+BEGIN_SRC d
+string out_;
+foreach (entry; biblio_ordered) {
+  out_ = format(
+    "%s \"%s\"%s%s%s%s%s%s%s%s%s.",
+    ((entry["author"].str.empty) ? entry["editor"].str : entry["author"].str),
+    entry["fulltitle"].str,
+    ((entry["journal"].str.empty) ? "" : ", /{" ~ entry["journal"].str ~ "}/"),
+    ((entry["volume"].str.empty) ? "" : ", " ~ entry["volume"].str),
+    ((entry["in"].str.empty) ? "" : ", " ~ entry["in"].str),
+    ((!(entry["author"].str.empty) && (!(entry["editor"].str.empty))) ? entry["editor"].str : ""),
+    ", " ~ entry["year"].str,
+    ((entry["pages"].str.empty) ? "" : ", " ~ entry["pages"].str),
+    ((entry["publisher"].str.empty) ? "" : ", " ~ entry["publisher"].str),
+    ((entry["place"].str.empty) ? "" : ", " ~ entry["place"].str),
+    ((entry["url"].str.empty) ? "" : ", [" ~ entry["url"].str ~ "]"),
+  );
+  comp_obj_para                       = comp_obj_para.init;
+  comp_obj_para.use                   = "backmatter";
+  comp_obj_para.is_of                 = "para";
+  comp_obj_para.is_a                  = "bibliography";
+  comp_obj_para.text                  = to!string(out_).strip;
+  comp_obj_para.ocn                   = 0;
+  comp_obj_para.obj_cite_number       = "";
+  comp_obj_para.indent_hang           = 0;
+  comp_obj_para.indent_base           = 1;
+  comp_obj_para.bullet                = bullet;
+  comp_obj_para.anchor_tags           = anchor_tags;
+  the_bibliography_section            ~= comp_obj_para;
+}
+#+END_SRC
+
+#+name: abs_post
+#+BEGIN_SRC d
+debug(bibliosection) {
+  foreach (o; the_bibliography_section) {
+    writeln(o.text);
+  }
+}
+#+END_SRC
+
+***** bibliography components
+
+auto biblio_entry_tags_jsonstr =  `{
+  "is"                   : "",
+  "sortby_deemed_author_year_title"  : "",
+  "deemed_author"                    : "",
+  "author_raw"                       : "",
+  "author"                           : "",
+  "author_arr"                       : [ "" ],
+  "editor_raw"                       : "",
+  "editor"                           : "",
+  "editor_arr"                       : [ "" ],
+  "title"                            : "",
+  "subtitle"                         : "",
+  "fulltitle"                        : "",
+  "language"                         : "",
+  "trans"                            : "",
+  "src"                              : "",
+  "journal"                          : "",
+  "in"                               : "",
+  "volume"                           : "",
+  "edition"                          : "",
+  "year"                             : "",
+  "place"                            : "",
+  "publisher"                        : "",
+  "url"                              : "",
+  "pages"                            : "",
+  "note"                             : "",
+  "short_name"                       : "",
+  "id"                               : ""
+}`; // is: book, article, magazine, newspaper, blog, other
+
+**** bookindex section (scroll & seg)                         :book:index:
+
+#+name: abs_post
+#+BEGIN_SRC d
+auto bi = BookIndexReportSection();
+auto bi_tuple =
+  bi.bookindex_build_abstraction_section(
+    bookindex_unordered_hashes,
+    obj_cite_number,
+    segment_anchor_tag_that_object_belongs_to,
+    opt_action_bool,
+  );
+static assert(!isTypeTuple!(bi_tuple));
+auto the_bookindex_section = bi_tuple[0];
+obj_cite_number = bi_tuple[1];
+debug(bookindex) {
+  foreach (bi_entry; the_bookindex_section["seg"]) {
+    writeln(bi_entry);
+  }
+}
+#+END_SRC
+
+**** no blurb section?                                             :blurb:
+
+#+name: abs_post
+#+BEGIN_SRC d
+if (an_object["blurb_nugget"].length == 0) {
+  comp_obj_heading_                       = comp_obj_heading_.init;
+  comp_obj_heading_.use                   = "empty";
+  comp_obj_heading_.is_of                 = "para";
+  comp_obj_heading_.is_a                  = "heading";
+  comp_obj_heading_.text                  = "(skip) there is no Blurb section";
+  comp_obj_heading_.ocn                   = 0;
+  comp_obj_para.obj_cite_number           = "";
+  comp_obj_heading_.segment_anchor_tag    = "";
+  comp_obj_heading_.marked_up_level       = "B";
+  comp_obj_heading_.heading_lev_markup    = 1;
+  comp_obj_heading_.heading_lev_collapsed = 1;
+  comp_obj_heading_.parent_ocn            = 1;
+  comp_obj_heading_.parent_lev_markup     = 0;
+  the_blurb_section                       ~= comp_obj_heading_;
+}
+debug(blurb) {
+  foreach (blurb; the_blurb_section) {
+    writeln(blurb.text);
+  }
+}
+#+END_SRC
+
+**** toc backmatter, table of contents backmatter (scroll & seg) :contents:
+
+#+name: abs_post
+#+BEGIN_SRC d
+indent=[
+  "hang_position" : 1,
+  "base_position" : 1,
+];
+comp_obj_toc                       = comp_obj_toc.init;
+comp_obj_toc.use                   = "frontmatter";
+comp_obj_toc.is_of                 = "para";
+comp_obj_toc.is_a                  = "toc";
+comp_obj_toc.ocn                   = 0;
+comp_obj_toc.obj_cite_number       = "";
+comp_obj_toc.indent_hang           = indent["hang_position"];
+comp_obj_toc.indent_base           = indent["base_position"];
+comp_obj_toc.bullet                = false;
+if (the_endnotes_section.length > 1) {
+  toc_txt_ = format(
+    "{ %s }%s../%s.fnSuffix",
+    "Endnotes",
+    mkup.mark_internal_site_lnk,
+    "endnotes",               // segment_anchor_tag_that_object_belongs_to
+  );
+  toc_txt_= munge.url_links(toc_txt_);
+  comp_obj_toc.text                       = to!string(toc_txt_).strip;
+  the_table_of_contents_section["seg"]    ~= comp_obj_toc;
+}
+if (the_glossary_section.length > 1) {
+  toc_txt_ = format(
+    "{ %s }%s../%s.fnSuffixs",
+    "Glossary",
+    mkup.mark_internal_site_lnk,
+    "glossary",               // segment_anchor_tag_that_object_belongs_to
+  );
+  toc_txt_= munge.url_links(toc_txt_);
+  comp_obj_toc.text                       = to!string(toc_txt_).strip;
+  the_table_of_contents_section["seg"]    ~= comp_obj_toc;
+  toc_txt_ = format(
+    "{ %s }#%s",
+    "Glossary",
+    "glossary",               // _anchor_tag
+  );
+  toc_txt_= munge.url_links(toc_txt_);
+  comp_obj_toc.text                       = to!string(toc_txt_).strip;
+  the_table_of_contents_section["scroll"] ~= comp_obj_toc;
+}
+if (the_bibliography_section.length > 1){
+  toc_txt_ = format(
+    "{ %s }%s../%s.fnSuffix",
+    "Bibliography",
+    mkup.mark_internal_site_lnk,
+    "bibliography",           // segment_anchor_tag_that_object_belongs_to
+  );
+  toc_txt_= munge.url_links(toc_txt_);
+  comp_obj_toc.text                       = to!string(toc_txt_).strip;
+  the_table_of_contents_section["seg"]    ~= comp_obj_toc;
+
+  toc_txt_ = format(
+    "{ %s }#%s",
+    "Bibliography",
+    "bibliography",           // _anchor_tag
+  );
+  toc_txt_= munge.url_links(toc_txt_);
+  comp_obj_toc.text                       = to!string(toc_txt_).strip;
+  the_table_of_contents_section["scroll"] ~= comp_obj_toc;
+}
+if (the_bookindex_section["seg"].length > 1) {
+  toc_txt_ = format(
+    "{ %s }%s../%s.fnSuffix",
+    "Book Index",
+    mkup.mark_internal_site_lnk,
+    "bookindex",              // segment_anchor_tag_that_object_belongs_to
+  );
+  toc_txt_= munge.url_links(toc_txt_);
+  comp_obj_toc.text                       = to!string(toc_txt_).strip;
+  the_table_of_contents_section["seg"]    ~= comp_obj_toc;
+}
+if (the_bookindex_section["scroll"].length > 1) {
+  toc_txt_ = format(
+    "{ %s }#%s",
+    "Book Index",
+    "bookindex",              // _anchor_tag
+  );
+  toc_txt_= munge.url_links(toc_txt_);
+  comp_obj_toc.text                       = to!string(toc_txt_).strip;
+  the_table_of_contents_section["scroll"] ~= comp_obj_toc;
+}
+if (the_blurb_section.length > 1) {
+  toc_txt_ = format(
+    "{ %s }%s../%s.fnSuffix",
+    "Blurb",
+    mkup.mark_internal_site_lnk,
+    "blurb",                  // segment_anchor_tag_that_object_belongs_to
+  );
+  toc_txt_= munge.url_links(toc_txt_);
+  comp_obj_toc.text                       = to!string(toc_txt_).strip;
+  the_table_of_contents_section["seg"]    ~= comp_obj_toc;
+  toc_txt_ = format(
+    "{ %s }#%s",
+    "Blurb",
+    "blurb",                  // _anchor_tag
+  );
+  toc_txt_= munge.url_links(toc_txt_);
+  comp_obj_toc.text                       = to!string(toc_txt_).strip;
+  the_table_of_contents_section["scroll"] ~= comp_obj_toc;
+}
+debug(toc) {
+  writefln(
+    "%s %s",
+    __LINE__,
+    the_table_of_contents_section["seg"].length
+  );
+  foreach (toc_linked_heading; the_table_of_contents_section["seg"]) {
+    writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text);
+  }
+}
+debug(tocscroll) {
+  writefln(
+    "%s %s",
+    __LINE__,
+    the_table_of_contents_section["seg"].length
+  );
+  foreach (toc_linked_heading; the_table_of_contents_section["scroll"]) {
+    writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text);
+  }
+}
+#+END_SRC
+
+**** doc head (separate document head from body, make space for toc)
+
+#+name: abs_post
+#+BEGIN_SRC d
+the_document_head_section ~= the_document_body_section[0];
+the_document_body_section=the_document_body_section[1..$];
+#+END_SRC
+
+*** TODO minor loops                                                 :post:
+**** 1. loop: backmatter loop up to lev4: html_segnames, set backmatter pointers
+
+could optimise by
+- skipping second and third pass unless the output html seg or epub is being made!
+NOTE there are issues attempting to do this on first pass
+- as
+  - backmatter is created out of sequence and
+  - it is not certain which are present
+it is quite neat to have all in one place as we have here:
+
+#+name: abs_post
+#+BEGIN_SRC d
+if (the_endnotes_section.length > 1) {
+  html_segnames ~= "endnotes";
+  html_segnames_ptr = html_segnames_ptr_cntr;
+  foreach (ref section; the_endnotes_section) {
+    if (section.heading_lev_markup == 4) {
+      section.ptr_html_segnames = html_segnames_ptr;
+      break;
+    }
+  }
+  html_segnames_ptr_cntr++;
+}
+if (the_glossary_section.length > 1) {
+  html_segnames ~= "glossary";
+  html_segnames_ptr = html_segnames_ptr_cntr;
+  foreach (ref section; the_glossary_section) {
+    if (section.heading_lev_markup == 4) {
+      section.ptr_html_segnames = html_segnames_ptr;
+      break;
+    }
+  }
+  html_segnames_ptr_cntr++;
+}
+if (the_bibliography_section.length > 1) {
+  html_segnames ~= "bibliography";
+  html_segnames_ptr = html_segnames_ptr_cntr;
+  foreach (ref section; the_bibliography_section) {
+    if (section.heading_lev_markup == 4) {
+      section.ptr_html_segnames = html_segnames_ptr;
+      break;
+    }
+  }
+  html_segnames_ptr_cntr++;
+}
+if (the_bookindex_section["scroll"].length > 1) {
+  html_segnames ~= "bookindex";
+  html_segnames_ptr = html_segnames_ptr_cntr;
+  foreach (ref section; the_bookindex_section["scroll"]) {
+    if (section.heading_lev_markup == 4) {
+      section.ptr_html_segnames = html_segnames_ptr;
+      break;
+    }
+  }
+  foreach (ref section; the_bookindex_section["seg"]) {
+    if (section.heading_lev_markup == 4) {
+      section.ptr_html_segnames = html_segnames_ptr;
+      break;
+    }
+  }
+  html_segnames_ptr_cntr++;
+}
+if (the_blurb_section.length > 1) {
+  html_segnames ~= "blurb";
+  html_segnames_ptr = html_segnames_ptr_cntr;
+  foreach (ref section; the_blurb_section) {
+    if (section.heading_lev_markup == 4) {
+      section.ptr_html_segnames = html_segnames_ptr;
+      break;
+    }
+  }
+  html_segnames_ptr_cntr++;
+}
+#+END_SRC
+
+**** 2. loop: all objects structural relationships (sections, segments, objects)
+
+needed for DOM structure, segnames & subtoc, backmatter pointers & unique image
+list
+
+if used minimally only for DOM structure, segnames, subtoc, could optimise by
+- skipping second and third pass unless the output html seg or epub is being
+  made!
+
+or could conveniently be used more extensively for ancestors as well (though
+this can be extracted earlier)
+
+Build here:
+- DOM structure
+- ancestors and decendants
+
+(as needed) up to document heading 1~, lev4 html:
+
+during the third pass all previous and next segment names are known
+next are not yet known for backmatter during the second pass
+
+#+name: abs_post
+#+BEGIN_SRC d
+foreach (ref obj; the_document_head_section) {
+  if (obj.is_a == "heading") {
+    debug(dom) {
+      writeln(obj.text);
+    }
+    if ((opt_action_bool["html"])
+    || (opt_action_bool["html_scroll"])
+    || (opt_action_bool["html_seg"])
+    || (opt_action_bool["epub"])) {
+      obj.dom_markedup =
+        dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
+      obj.dom_collapsed =
+        dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
+    }
+    heading_ancestors(obj, lv_ancestors);
+  }
+}
+if (the_table_of_contents_section["scroll"].length > 1) {
+  dom_markedup_buffer = dom_markedup.dup;
+  dom_collapsed_buffer = dom_collapsed.dup;
+  foreach (ref obj; the_table_of_contents_section["scroll"]) {
+    if (obj.is_a == "heading") {
+      if (obj.heading_lev_markup == 4) {
+        obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        obj.dom_markedup =
+          dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
+        obj.dom_collapsed =
+          dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
+      }
+      heading_ancestors(obj, lv_ancestors);
+    }
+  }
+  dom_markedup = dom_markedup_buffer.dup;
+  dom_collapsed = dom_collapsed_buffer.dup;
+  foreach (ref obj; the_table_of_contents_section["seg"]) {
+    if (obj.is_a == "heading") {
+      debug(dom) {
+        writeln(obj.text);
+      }
+      if (obj.heading_lev_markup == 4) {
+        obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        obj.dom_markedup =
+          dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
+        obj.dom_collapsed =
+          dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
+      }
+      heading_ancestors(obj, lv_ancestors);
+    }
+  }
+}
+/+ multiple 1~ levels, loop through document body +/
+if (the_document_body_section.length > 1) {
+  foreach (ref obj; the_document_body_section) {
+    if (obj.is_a == "heading") {
+      debug(dom) {
+        writeln(obj.text);
+      }
+      if (obj.heading_lev_markup == 4) {
+        obj.lev4_subtoc = lev4_subtoc[obj.segment_anchor_tag];
+        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+        if (html_segnames.length > obj.ptr_html_segnames + 1) {
+          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+        }
+        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        obj.dom_markedup =
+          dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
+        obj.dom_collapsed =
+          dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
+      }
+      heading_ancestors(obj, lv_ancestors);
+    }
+  }
+}
+/+ optional only one 1~ level +/
+if (the_endnotes_section.length > 1) {
+  dom_markedup_buffer = dom_markedup.dup;
+  dom_collapsed_buffer = dom_collapsed.dup;
+  dom_markedup = dom_markedup_buffer.dup;
+  dom_collapsed = dom_collapsed_buffer.dup;
+  foreach (ref obj; the_endnotes_section) {
+    if (obj.is_a == "heading") {
+      debug(dom) {
+        writeln(obj.text);
+      }
+      if (obj.heading_lev_markup == 4) {
+        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+        if (html_segnames.length > obj.ptr_html_segnames + 1) {
+          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+        }
+        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        obj.dom_markedup =
+          dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
+        obj.dom_collapsed =
+          dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
+      }
+      heading_ancestors(obj, lv_ancestors);
+    }
+  }
+}
+/+ optional only one 1~ level +/
+if (the_glossary_section.length > 1) {
+  foreach (ref obj; the_glossary_section) {
+    if (obj.is_a == "heading") {
+      debug(dom) {
+        writeln(obj.text);
+      }
+      if (obj.heading_lev_markup == 4) {
+        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+        if (html_segnames.length > obj.ptr_html_segnames + 1) {
+          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+        }
+        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        obj.dom_markedup =
+          dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
+        obj.dom_collapsed =
+          dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
+      }
+      heading_ancestors(obj, lv_ancestors);
+    }
+  }
+}
+/+ optional only one 1~ level +/
+if (the_bibliography_section.length > 1) {
+  foreach (ref obj; the_bibliography_section) {
+    if (obj.is_a == "heading") {
+      debug(dom) {
+        writeln(obj.text);
+      }
+      if (obj.heading_lev_markup == 4) {
+        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+        if (html_segnames.length > obj.ptr_html_segnames + 1) {
+          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+        }
+        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        obj.dom_markedup =
+          dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
+        obj.dom_collapsed =
+          dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
+      }
+      heading_ancestors(obj, lv_ancestors);
+    }
+  }
+}
+/+ optional only one 1~ level +/
+if (the_bookindex_section["scroll"].length > 1) {
+  dom_markedup_buffer = dom_markedup.dup;
+  dom_collapsed_buffer = dom_collapsed.dup;
+  foreach (ref obj; the_bookindex_section["scroll"]) {
+    if (obj.is_a == "heading") {
+      debug(dom) {
+      // writeln(obj.text);
+      }
+      if (obj.heading_lev_markup == 4) {
+        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+        if (html_segnames.length > obj.ptr_html_segnames + 1) {
+          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+        }
+        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        obj.dom_markedup =
+          dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
+        obj.dom_collapsed =
+          dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
+      }
+      heading_ancestors(obj, lv_ancestors);
+    }
+  }
+  dom_markedup = dom_markedup_buffer.dup;
+  dom_collapsed = dom_collapsed_buffer.dup;
+  foreach (ref obj; the_bookindex_section["seg"]) {
+    if (obj.is_a == "heading") {
+      debug(dom) {
+        writeln(obj.text);
+      }
+      if (obj.heading_lev_markup == 4) {
+        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+        if (html_segnames.length > obj.ptr_html_segnames + 1) {
+          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+        }
+        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        obj.dom_markedup =
+          dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
+        obj.dom_collapsed =
+          dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
+      }
+      heading_ancestors(obj, lv_ancestors);
+    }
+  }
+}
+/+ optional only one 1~ level +/
+if (the_blurb_section.length > 1) {
+  foreach (ref obj; the_blurb_section) {
+    if (obj.is_a == "heading") {
+      debug(dom) {
+        writeln(obj.text);
+      }
+      if (obj.heading_lev_markup == 4) {
+        obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+        if (html_segnames.length > obj.ptr_html_segnames + 1) {
+          obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+        }
+        assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+      }
+      if ((opt_action_bool["html"])
+      || (opt_action_bool["html_scroll"])
+      || (opt_action_bool["html_seg"])
+      || (opt_action_bool["epub"])) {
+        obj.dom_markedup =
+          dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
+        obj.dom_collapsed =
+          dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
+      }
+      heading_ancestors(obj, lv_ancestors);
+    }
+  }
+  /+ TODO
+    - note create/insert heading object sole purpose eof close all open tags
+      sort out:
+      - obj.dom_markedup = dom_markedup;
+      - obj.dom_collapsed = dom_collapsed;
+  +/
+  dom_markedup = dom_set_markup_tags(dom_markedup, 0);
+  dom_collapsed = dom_set_collapsed_tags(dom_collapsed, 0);
+  comp_obj_heading_                       = comp_obj_heading_.init;
+  comp_obj_heading_.use                   = "empty";
+  comp_obj_heading_.is_of                 = "para";
+  comp_obj_heading_.is_a                  = "heading";
+  // comp_obj_heading_.text                  = "(skip) this is the DOM tail";
+  comp_obj_heading_.ocn                   = 0;
+  comp_obj_para.obj_cite_number           = "";
+  comp_obj_heading_.segment_anchor_tag    = "";
+  comp_obj_heading_.marked_up_level       = "";
+  comp_obj_heading_.heading_lev_markup    = 9;
+  comp_obj_heading_.heading_lev_collapsed = 9;
+  comp_obj_heading_.parent_ocn            = 0;
+  comp_obj_heading_.parent_lev_markup     = 0;
+  comp_obj_heading_.dom_markedup          = dom_markedup.dup;
+  comp_obj_heading_.dom_collapsed         = dom_collapsed.dup;
+  the_dom_tail_section                    ~= comp_obj_heading_;
+}
+#+END_SRC
+
+** 4. _return document tuple_                                         :post:
+*** the document                                                 :document:
+
+#+name: abs_post
+#+BEGIN_SRC d
+auto document_the = [
+  "head":             the_document_head_section,
+  "toc_seg":          the_table_of_contents_section["seg"],
+  "toc_scroll":       the_table_of_contents_section["scroll"],
+  /+ substantive/body: +/
+  "body":             the_document_body_section,
+  /+ backmatter: +/
+  "endnotes":         the_endnotes_section,
+  "glossary":         the_glossary_section,
+  "bibliography":     the_bibliography_section,
+  "bookindex_scroll": the_bookindex_section["scroll"],
+  "bookindex_seg":    the_bookindex_section["seg"],
+  "blurb":            the_blurb_section,
+  /+ dom tail only +/
+  "tail":             the_dom_tail_section,
+];
+#+END_SRC
+
+*** document _section keys_ sequence
+
+#+name: abs_post
+#+BEGIN_SRC d
+string[][string] document_section_keys_sequenced = [
+  "seg":    ["head", "toc_seg", "body",],
+  "scroll": ["head", "toc_scroll", "body",]
+];
+if (document_the["endnotes"].length > 1) {
+  document_section_keys_sequenced["seg"]    ~= "endnotes";
+  document_section_keys_sequenced["scroll"] ~= "endnotes";
+}
+if (document_the["glossary"].length > 1) {
+  document_section_keys_sequenced["seg"]    ~= "glossary";
+  document_section_keys_sequenced["scroll"] ~= "glossary";
+}
+if (document_the["bibliography"].length > 1) {
+  document_section_keys_sequenced["seg"]    ~= "bibliography";
+  document_section_keys_sequenced["scroll"] ~= "bibliography";
+}
+if (document_the["bookindex_seg"].length > 1) {
+  document_section_keys_sequenced["seg"]    ~= "bookindex_seg";
+}
+if (document_the["bookindex_scroll"].length > 1) {
+  document_section_keys_sequenced["scroll"] ~= "bookindex_scroll";
+}
+if (document_the["blurb"].length > 1) {
+  document_section_keys_sequenced["seg"]    ~= "blurb";
+  document_section_keys_sequenced["scroll"] ~= "blurb";
+}
+if ((opt_action_bool["html"])
+|| (opt_action_bool["html_scroll"])
+|| (opt_action_bool["html_seg"])
+|| (opt_action_bool["epub"])) {
+  document_section_keys_sequenced["seg"]    ~= "tail";
+  document_section_keys_sequenced["scroll"] ~= "tail";
+}
+#+END_SRC
+
+*** clean out structure
+
+#+name: abs_post
+destroy(the_document_head_section);
+destroy(the_document_table_of_contents_section);
+destroy(the_document_body_section);
+destroy(the_endnotes_section);
+destroy(the_glossary_section);
+destroy(the_bibliography_section);
+destroy(the_bookindex_section);
+destroy(the_blurb_section);
+#+END_SRC
+
+*** [#A] _return document tuple_                               :return:tuple:
+
+#+name: abs_post
+#+BEGIN_SRC d
+auto t = tuple(
+  document_the,
+  document_section_keys_sequenced,
+  html_segnames,
+);
+return t;
+#+END_SRC
+
+** 5. Functions                                          :abstract:function:
+
+functions used in document abstraction
+
+*** set & resets                                                    :reset:
+**** object reset: remove (clean)                          :object:remove:
+
+#+name: abs_functions_object_reset
+#+BEGIN_SRC d
+auto object_reset(O)(ref O an_object) {
+  debug(asserts){
+    static assert(is(typeof(an_object) == string[string]));
+  }
+  an_object.remove("body_nugget");
+  an_object.remove("substantive");
+  an_object.remove("is");
+  an_object.remove("attrib");
+  an_object.remove("bookindex_nugget");
+}
+#+END_SRC
+
+**** set, initialize or re-initialize                                :set:
+
+#+name: abs_functions_header_set_common
+#+BEGIN_SRC d
+auto _common_reset_(L,O,T)(
+  ref L line_occur,
+  ref O an_object,
+  ref T type
+) {
+  debug(asserts){
+    static assert(is(typeof(line_occur) == int[string]));
+    static assert(is(typeof(an_object)  == string[string]));
+    static assert(is(typeof(type)       == int[string]));
+  }
+  line_occur["heading"] = State.off;
+  line_occur["para"]    = State.off;
+  type["heading"]       = State.off;
+  type["para"]          = State.off;
+  object_reset(an_object);
+}
+#+END_SRC
+
+*** check obj_cite_number status in document                          :ocn:
+
+#+name: abs_functions_ocn_status
+#+BEGIN_SRC d
+void _check_ocn_status_(L,T)(
+  L     line,
+  ref T type
+) {
+  debug(asserts){
+    static assert(is(typeof(line) == char[]));
+    static assert(is(typeof(type) == int[string]));
+  }
+  auto rgx = Rgx();
+  if ((!line.empty) && (type["ocn_status_multi_obj"] == TriState.off)) {
+    /+ not multi-line object, check whether obj_cite_number is on or turned off +/
+    if (matchFirst(line, rgx.obj_cite_number_block_marks)) {
+      /+ switch off obj_cite_number +/
+      if (matchFirst(line, rgx.obj_cite_number_off_block)) {
+        type["ocn_status_multi_obj"] = TriState.on;
+        debug(ocnoff) {
+          writeln(line);
+        }
+      }
+      if (matchFirst(line, rgx.obj_cite_number_off_block_dh)) {
+        type["ocn_status_multi_obj"] = TriState.closing;
+        debug(ocnoff) {
+          writeln(line);
+        }
+      }
+    } else {
+      if (type["ocn_status_multi_obj"] == TriState.off) {
+        if (matchFirst(line, rgx.obj_cite_number_off)) {
+          type["ocn_status"] = TriState.on;
+        } else if (matchFirst(line, rgx.obj_cite_number_off_dh)) {
+          type["ocn_status"] = TriState.closing;
+        } else {
+          type["ocn_status"] = TriState.off;
+        }
+      } else {
+        type["ocn_status"] =
+          type["ocn_status_multi_obj"];
+      }
+    }
+  } else if ((!line.empty) && (type["ocn_status_multi_obj"] > TriState.off)) {
+    if (matchFirst(line, rgx.obj_cite_number_off_block_close)) {
+      type["ocn_status_multi_obj"] = TriState.off;
+      type["ocn_status"] = TriState.off;
+      debug(ocnoff) {
+        writeln(line);
+      }
+    }
+  }
+}
+#+END_SRC
+
+*** block                                                           :block:
+**** block start (open) block                                      :start:
+***** function open for block starts
+
+#+name: abs_functions_block
+#+BEGIN_SRC d
+void _start_block_(L,T,N)(
+  L     line,
+  ref T type,
+  N     obj_cite_number_poem
+) {
+  debug(asserts){
+    static assert(is(typeof(line)                 == char[]));
+    static assert(is(typeof(type)                 == int[string]));
+    static assert(is(typeof(obj_cite_number_poem) == string[string]));
+  }
+#+END_SRC
+
+***** block (various) curly open                                  :curly:
+
+#+name: abs_functions_block
+#+BEGIN_SRC d
+  auto rgx = Rgx();
+  if (matchFirst(line, rgx.block_curly_code_open)) {
+    /+ curly code open +/
+    debug(code) {                              // code (curly) open
+      writefln(
+        "* [code curly] %s",
+        line
+      );
+    }
+    type["blocks"] = TriState.on;
+    type["code"] = TriState.on;
+    type["curly_code"] = TriState.on;
+  } else if (matchFirst(line, rgx.block_curly_poem_open)) {
+    /+ curly poem open +/
+    debug(poem) {                              // poem (curly) open
+      writefln(
+        "* [poem curly] %s",
+        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 (matchFirst(line, rgx.block_curly_group_open)) {
+    /+ curly group open +/
+    debug(group) {                             // group (curly) open
+      writefln(
+        "* [group curly] %s",
+        line
+      );
+    }
+    type["blocks"] = TriState.on;
+    type["group"] = TriState.on;
+    type["curly_group"] = TriState.on;
+  } else if (matchFirst(line, rgx.block_curly_block_open)) {
+    /+ curly block open +/
+    debug(block) {                             // block (curly) open
+      writefln(
+        "* [block curly] %s",
+        line
+      );
+    }
+    type["blocks"] = TriState.on;
+    type["block"] = TriState.on;
+    type["curly_block"] = TriState.on;
+  } else if (matchFirst(line, rgx.block_curly_quote_open)) {
+    /+ curly quote open +/
+    debug(quote) {                             // quote (curly) open
+      writefln(
+        "* [quote curly] %s",
+        line
+      );
+    }
+    type["blocks"] = TriState.on;
+    type["quote"] = TriState.on;
+    type["curly_quote"] = TriState.on;
+  } else if (matchFirst(line, rgx.block_curly_table_open)) {
+    /+ curly table open +/
+    debug(table) {                             // table (curly) open
+      writefln(
+        "* [table curly] %s",
+        line
+      );
+    }
+    type["blocks"] = TriState.on;
+    type["table"] = TriState.on;
+    type["curly_table"] = TriState.on;
+#+END_SRC
+
+***** block (various) tic open                                      :tic:
+
+#+name: abs_functions_block
+#+BEGIN_SRC d
+  } else if (matchFirst(line, rgx.block_tic_code_open)) {
+    /+ tic code open +/
+    debug(code) {                              // code (tic) open
+      writefln(
+        "* [code tic] %s",
+        line
+      );
+    }
+    type["blocks"] = TriState.on;
+    type["code"] = TriState.on;
+    type["tic_code"] = TriState.on;
+  } else if (matchFirst(line, rgx.block_tic_poem_open)) {
+    /+ tic poem open +/
+    debug(poem) {                              // poem (tic) open
+      writefln(
+        "* [poem tic] %s",
+        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 (matchFirst(line, rgx.block_tic_group_open)) {
+    /+ tic group open +/
+    debug(group) {                             // group (tic) open
+      writefln(
+        "* [group tic] %s",
+        line
+      );
+    }
+    type["blocks"] = TriState.on;
+    type["group"] = TriState.on;
+    type["tic_group"] = TriState.on;
+  } else if (matchFirst(line, rgx.block_tic_block_open)) {
+    /+ tic block open +/
+    debug(block) {                             // block (tic) open
+      writefln(
+        "* [block tic] %s",
+        line
+      );
+    }
+    type["blocks"] = TriState.on;
+    type["block"] = TriState.on;
+    type["tic_block"] = TriState.on;
+  } else if (matchFirst(line, rgx.block_tic_quote_open)) {
+    /+ tic quote open +/
+    debug(quote) {                             // quote (tic) open
+      writefln(
+        "* [quote tic] %s",
+        line
+      );
+    }
+    type["blocks"] = TriState.on;
+    type["quote"] = TriState.on;
+    type["tic_quote"] = TriState.on;
+  } else if (matchFirst(line, rgx.block_tic_table_open)) {
+    /+ tic table open +/
+    debug(table) {                             // table (tic) open
+      writefln(
+        "* [table tic] %s",
+        line
+      );
+    }
+    type["blocks"] = TriState.on;
+    type["table"] = TriState.on;
+    type["tic_table"] = TriState.on;
+  }
+#+END_SRC
+
+***** function close for block starts
+
+#+name: abs_functions_block
+#+BEGIN_SRC d
+}
+#+END_SRC
+
+**** block continue (an open block)                             :continue:
+***** code block (special status, deal with first)                 :code:
+
+#+name: abs_functions_block_code
+#+BEGIN_SRC d
+void _code_block_(L,O,T)(
+  ref L line,
+  ref O an_object,
+  ref T type
+) {
+  debug(asserts){
+    static assert(is(typeof(line)      == char[]));
+    static assert(is(typeof(an_object) == string[string]));
+    static assert(is(typeof(type)      == int[string]));
+  }
+  auto rgx = Rgx();
+  if (type["curly_code"] == TriState.on) {
+    if (matchFirst(line, rgx.block_curly_code_close)) {
+      debug(code) {                                    // code (curly) close
+        writeln(line);
+      }
+      type["blocks"] = TriState.closing;
+      type["code"] = TriState.closing;
+      type["curly_code"] = TriState.off;
+    } else {
+      debug(code) {                                    // code (curly) line
+        writeln(line);
+      }
+      an_object[an_object_key] ~= line ~= "\n";        // code (curly) line
+    }
+  } else if (type["tic_code"] == TriState.on) {
+    if (matchFirst(line, rgx.block_tic_close)) {
+      debug(code) {                                    // code (tic) close
+        writeln(line);
+      }
+      type["blocks"] = TriState.closing;
+      type["code"] = TriState.closing;
+      type["tic_code"] = TriState.off;
+    } else {
+      debug(code) {                                    // code (tic) line
+        writeln(line);
+      }
+      an_object[an_object_key] ~= line ~= "\n";        // code (tic) line
+    }
+  }
+}
+#+END_SRC
+
+***** biblio block                                               :biblio:
+****** biblio tag map
+
+#+name: abs_functions_block_biblio
+#+BEGIN_SRC d
+final string biblio_tag_map(A)(A abr) {
+  debug(asserts){
+    static assert(is(typeof(abr) == string));
+  }
+  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];
+}
+#+END_SRC
+
+******* +consider+
+
+#+name: none
+#+BEGIN_SRC d
+final string biblio_tag_map_(A)(A abr) {
+  debug(asserts){
+    static assert(is(typeof(abr) == string));
+  }
+  string name;
+  switch (abr) {
+  case "au":
+    name="author_raw";
+    break;
+  case "ed":
+    name="editor_raw";
+    break;
+  case "ti":
+    name="fulltitle";
+    break;
+  case "lng":
+    name="language";
+    break;
+  case "jo":
+    name="journal";
+    break;
+  case "vol":
+    name="volume";
+    break;
+  case "edn":
+    name="edition";
+    break;
+  case "yr":
+    name="year";
+    break;
+  case "pl":
+    name="place";
+    break;
+  case "pb":
+    name="publisher";
+    break;
+  case "pub":
+    name="publisher";
+    break;
+  case "pg":
+    name="pages";
+    break;
+  case "pgs":
+    name="pages";
+    break;
+  case "sn":
+    name="short_name";
+    break;
+  default:
+    name=abr;
+    break;
+  }
+  return name;
+}
+#+END_SRC
+
+****** biblio block
+
+#+name: abs_functions_block_biblio
+#+BEGIN_SRC d
+void _biblio_block_(
+  char[] line,
+  ref int[string] type,
+  ref int bib_entry,
+  ref string biblio_entry_str_json,
+  ref string[] biblio_arr_json
+) {
+  mixin SiSUbiblio;
+  auto jsn = BibJsnStr();
+  auto rgx = Rgx();
+  if (matchFirst(line, rgx.heading_biblio)) {
+    type["biblio_section"] = TriState.on;
+    type["blurb_section"] = State.off;
+    type["glossary_section"] = State.off;
+  }
+  if (line.empty) {
+    debug {
+      debug(biblioblock) {
+        writeln("---");
+      }
+      debug(biblioblockinclude) {
+        writeln(biblio_entry_str_json.length);
+      }
+    }
+    if ((bib_entry == State.off)
+    && (biblio_entry_str_json.empty)) {
+      bib_entry = State.on;
+      biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr;
+    } else if (!(biblio_entry_str_json.empty)) {
+      bib_entry = State.off;
+      if (!(biblio_entry_str_json == jsn.biblio_entry_tags_jsonstr)) {
+        auto biblio_entry = parseJSON(biblio_entry_str_json);
+        if (biblio_entry["fulltitle"].str.empty) {
+          writeln("check problem entry (Title missing): ", biblio_entry_str_json);
+        } else if ((biblio_entry["author_raw"].str.empty) && (biblio_entry["editor_raw"].str.empty)) {
+          writeln("check problem entry (No author and no editor): ", biblio_entry_str_json);
+        } else {
+          biblio_arr_json ~= biblio_entry_str_json;
+        }
+        biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr;
+      }
+    } else { // CHECK ERROR
+      writeln("?? 2. ERROR ", biblio_entry_str_json, "??");
+      biblio_entry_str_json = "";
+    }
+  } else if (matchFirst(line, rgx.biblio_tags)) {
+    debug(biblioblock) {
+      writeln(line);
+    }
+    auto bt = match(line, rgx.biblio_tags);
+    bib_entry = State.off;
+    st=to!string(bt.captures[1]);
+    auto header_tag_value=to!string(bt.captures[2]);
+    JSONValue j = parseJSON(biblio_entry_str_json);
+    biblio_tag_name = (match(st, rgx.biblio_abbreviations))
+      ? (biblio_tag_map(st))
+      : st;
+    j.object[biblio_tag_name] = header_tag_value;
+    debug(bibliounsortedcheckduplicates) {
+      writeln(biblio_tag_name, ": ", header_tag_value);
+      writeln("--");
+    }
+    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, "");
+      j["author"].str = tmp;
+      goto default;
+    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, "");
+      j["editor"].str = tmp;
+      goto default;
+    case "fulltitle": // title & subtitle
+      goto default;
+    default:
+      break;
+    }
+    auto s = j.toString();
+    debug(biblio1) {
+      writefln(
+        "* %s: %s\n%s",
+        biblio_tag_name,
+        biblio_tag_entry,
+        j[biblio_tag_name]
+      );
+    }
+    if ((match(line, rgx.comment))) {
+      writeln("ERROR", line, "COMMENT");
+      writeln("ERROR", s, "%%");
+    }
+    if (!(match(line, rgx.comment))) {
+      debug(biblioblockinclude) {
+        writeln(line);
+      }
+      biblio_entry_str_json = s;
+    } else {
+      biblio_entry_str_json = "";
+    }
+    header_tag_value="";
+  }
+}
+#+END_SRC
+
+***** TODO poem block, verse objects                         :poem:verse:
+
+why extra object stuff only in poem/verse?
+
+#+name: abs_functions_block_poem
+#+BEGIN_SRC d
+void _poem_block_(L,O,T,C,N,Ma)(
+  L     line,
+  ref O an_object,
+  ref T type,
+  ref C cntr,
+  N     obj_cite_number_poem,
+  Ma    dochead_make_aa,
+) {
+  debug(asserts){
+    static assert(is(typeof(line)                 == char[]));
+    static assert(is(typeof(an_object)            == string[string]));
+    static assert(is(typeof(type)                 == int[string]));
+    static assert(is(typeof(cntr)                 == int));
+    static assert(is(typeof(obj_cite_number_poem) == string[string]));
+    static assert(is(typeof(dochead_make_aa)      == string[string][string]));
+  }
+  auto rgx = Rgx();
+  if (type["curly_poem"] == TriState.on) {
+    if (matchFirst(line, rgx.block_curly_poem_close)) {
+      an_object[an_object_key]="verse";
+      debug(poem) {                               // poem (curly) close
+        writefln(
+          "* [poem curly] %s",
+          line
+        );
+      }
+      if (processing.length > 0) {
+        an_object[an_object_key] = processing["verse"];
+      }
+      debug(poem) {                               // poem (curly) close
+        writeln(__LINE__);
+        writefln(
+          "* %s %s",
+          obj_cite_number,
+          line
+        );
+      }
+      if (an_object.length > 0) {
+        debug(poem) {                             // poem (curly) close
+          writeln(
+            obj_cite_number,
+            an_object[an_object_key]
+          );
+        }
+        an_object["is"] = "verse";
+        auto substantive_object_and_anchor_tags_tuple =
+          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+        comp_obj_block                            = comp_obj_block.init;
+        comp_obj_block.use                        = "body";
+        comp_obj_block.is_of                      = "block";
+        comp_obj_block.is_a                       = "verse";
+        comp_obj_block.ocn                        = obj_cite_number;
+        comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+        comp_obj_block.text                       = an_object["substantive"];
+        the_document_body_section                 ~= comp_obj_block;
+        object_reset(an_object);
+        processing.remove("verse");
+        ++cntr;
+      }
+      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 =
+          ocn_emit(type["ocn_status"]);
+        type["verse_new"] = State.off;
+      } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) {
+        verse_line = TriState.off;
+        type["verse_new"] = State.on;
+      }
+      if (type["verse_new"] == State.on) {
+        verse_line=1;
+        an_object[an_object_key] = processing["verse"];
+        debug(poem) {                          // poem verse
+          writefln(
+            "* %s curly\n%s",
+            obj_cite_number,
+            an_object[an_object_key]
+          );
+        }
+        processing.remove("verse");
+        an_object["is"] = "verse";
+        auto comp_obj_location = node_construct.node_location_emitter(
+          content_non_header,
+          segment_anchor_tag_that_object_belongs_to,
+          obj_cite_number,
+          cntr,
+          heading_ptr-1,
+          an_object["is"]
+        );
+        auto substantive_object_and_anchor_tags_tuple =
+          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+        comp_obj_block                            = comp_obj_block.init;
+        comp_obj_block.use                        = "body";
+        comp_obj_block.is_of                      = "block";
+        comp_obj_block.is_a                       = "verse";
+        comp_obj_block.ocn                        = obj_cite_number;
+        comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+        comp_obj_block.text                       = an_object["substantive"];
+        the_document_body_section                 ~= comp_obj_block;
+        object_reset(an_object);
+        processing.remove("verse");
+        ++cntr;
+      }
+    }
+  } else if (type["tic_poem"] == TriState.on) {
+    if (auto m = matchFirst(line, rgx.block_tic_close)) { // tic_poem_close
+      an_object[an_object_key]="verse";
+      debug(poem) {                                       // poem (curly) close
+        writefln(
+          "* [poem tic] %s",
+          line
+        );
+      }
+      if (processing.length > 0) {
+        an_object[an_object_key] = processing["verse"];
+      }
+      if (an_object.length > 0) {
+        debug(poem) {                                     // poem (tic) close
+          writeln(__LINE__);
+          writeln(obj_cite_number, line);
+        }
+        processing.remove("verse");
+        an_object["is"] = "verse";
+        auto substantive_object_and_anchor_tags_tuple =
+          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+        comp_obj_block                            = comp_obj_block.init;
+        comp_obj_block.use                        = "body";
+        comp_obj_block.is_of                      = "block";
+        comp_obj_block.is_a                       = "verse";
+        comp_obj_block.ocn                        = obj_cite_number;
+        comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+        comp_obj_block.text                       = an_object["substantive"];
+        the_document_body_section                 ~= comp_obj_block;
+        obj_cite_number_poem["end"]               = to!string(obj_cite_number);
+        object_reset(an_object);
+        processing.remove("verse");
+        ++cntr;
+      }
+      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 =
+          ocn_emit(type["ocn_status"]);
+        type["verse_new"] = State.off;
+      } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) {
+        type["verse_new"] = State.on;
+        verse_line = TriState.off;
+      }
+      if (type["verse_new"] == State.on) {
+        verse_line=1;
+        an_object[an_object_key] = processing["verse"];
+        debug(poem) {                            // poem (tic) close
+          writefln(
+            "* %s tic\n%s",
+            obj_cite_number,
+            an_object[an_object_key]
+          );
+        }
+        processing.remove("verse");
+        an_object["is"] = "verse";
+        auto comp_obj_location =
+          node_construct.node_location_emitter(
+            content_non_header,
+            segment_anchor_tag_that_object_belongs_to,
+            obj_cite_number,
+            cntr,
+            heading_ptr-1,
+            an_object["is"]
+          );
+        auto substantive_object_and_anchor_tags_tuple =
+          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+        comp_obj_block                            = comp_obj_block.init;
+        comp_obj_block.use                        = "body";
+        comp_obj_block.is_of                      = "block";
+        comp_obj_block.is_a                       = "verse";
+        comp_obj_block.ocn                        = obj_cite_number;
+        comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+        comp_obj_block.text                       = an_object["substantive"];
+        the_document_body_section                 ~= comp_obj_block;
+        object_reset(an_object);
+        processing.remove("verse");
+        ++cntr;
+      }
+    }
+  }
+}
+#+END_SRC
+
+***** group block                                                 :group:
+
+#+name: abs_functions_block_group
+#+BEGIN_SRC d
+void _group_block_(L,O,T)(
+  ref L line,
+  ref O an_object,
+  ref T type
+) {
+  debug(asserts){
+    static assert(is(typeof(line)      == char[]));
+    static assert(is(typeof(an_object) == string[string]));
+    static assert(is(typeof(type)      == int[string]));
+  }
+  auto rgx = Rgx();
+  if (type["curly_group"] == State.on) {
+    if (matchFirst(line, rgx.block_curly_group_close)) {
+      debug(group) {                              // group (curly) close
+        writeln(line);
+      }
+      type["blocks"] = TriState.closing;
+      type["group"] = TriState.closing;
+      type["curly_group"] = TriState.off;
+    } else {
+      debug(group) {                              // group
+        writeln(line);
+      }
+      an_object[an_object_key] ~= line ~= "\n";   // build group array (or string)
+    }
+  } else if (type["tic_group"] == TriState.on) {
+    if (matchFirst(line, rgx.block_tic_close)) {
+      debug(group) {                              // group (tic) close
+        writeln(line);
+      }
+      type["blocks"] = TriState.closing;
+      type["group"] = TriState.closing;
+      type["tic_group"] = TriState.off;
+    } else {
+      debug(group) {                              // group
+        writeln(line);
+      }
+      an_object[an_object_key] ~= line ~= "\n";   // build group array (or string)
+    }
+  }
+}
+#+END_SRC
+
+***** block block                                                 :block:
+
+#+name: abs_functions_block_block
+#+BEGIN_SRC d
+void _block_block_(L,O,T)(
+  ref L line,
+  ref O an_object,
+  ref T type
+) {
+  debug(asserts){
+    static assert(is(typeof(line)      == char[]));
+    static assert(is(typeof(an_object) == string[string]));
+    static assert(is(typeof(type)      == int[string]));
+  }
+  auto rgx = Rgx();
+  if (type["curly_block"] == TriState.on) {
+    if (matchFirst(line, rgx.block_curly_block_close)) {
+      debug(block) {                             // block (curly) close
+        writeln(line);
+      }
+      type["blocks"] = TriState.closing;
+      type["block"] = TriState.closing;
+      type["curly_block"] = TriState.off;
+    } else {
+      debug(block) {                             // block
+        writeln(line);
+      }
+      an_object[an_object_key] ~= line ~= "\n";   // build block array (or string)
+    }
+  } else if (type["tic_block"] == TriState.on) {
+    if (matchFirst(line, rgx.block_tic_close)) {
+      debug(block) {                              // block (tic) close
+        writeln(line);
+      }
+      type["blocks"] = TriState.closing;
+      type["block"] = TriState.closing;
+      type["tic_block"] = TriState.off;
+    } else {
+      debug(block) {                             // block
+        writeln(line);
+      }
+      an_object[an_object_key] ~= line ~= "\n";   // build block array (or string)
+    }
+  }
+}
+#+END_SRC
+
+***** quote block                                                 :quote:
+
+#+name: abs_functions_block_quote
+#+BEGIN_SRC d
+void _quote_block_(L,O,T)(
+  ref L line,
+  ref O an_object,
+  ref T type
+) {
+  debug(asserts){
+    static assert(is(typeof(line)      == char[]));
+    static assert(is(typeof(an_object) == string[string]));
+    static assert(is(typeof(type)      == int[string]));
+  }
+  auto rgx = Rgx();
+  if (type["curly_quote"] == TriState.on) {
+    if (matchFirst(line, rgx.block_curly_quote_close)) {
+      debug(quote) {                              // quote (curly) close
+        writeln(line);
+      }
+      type["blocks"] = TriState.closing;
+      type["quote"] = TriState.closing;
+      type["curly_quote"] = TriState.off;
+    } else {
+      debug(quote) {
+        writeln(line);
+      }
+      an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string)
+    }
+  } else if (type["tic_quote"] == TriState.on) {
+    if (matchFirst(line, rgx.block_tic_close)) {
+      debug(quote) {                              // quote (tic) close
+        writeln(line);
+      }
+      type["blocks"] = TriState.closing;
+      type["quote"] = TriState.closing;
+      type["tic_quote"] = TriState.off;
+    } else {
+      debug(quote) {
+        writeln(line);
+      }
+      an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string)
+    }
+  }
+}
+#+END_SRC
+
+***** table block                                                 :table:
+
+#+name: abs_functions_block_table
+#+BEGIN_SRC d
+void _table_block_(L,O,T)(
+  ref L line,
+  ref O an_object,
+  ref T type
+) {
+  debug(asserts){
+    static assert(is(typeof(line)      == char[]));
+    static assert(is(typeof(an_object) == string[string]));
+    static assert(is(typeof(type)      == int[string]));
+  }
+  auto rgx = Rgx();
+  if (type["curly_table"] == TriState.on) {
+    if (matchFirst(line, rgx.block_curly_table_close)) {
+      debug(table) {                           // table (curly) close
+        writeln(line);
+      }
+      type["blocks"] = TriState.closing;
+      type["table"] = TriState.closing;
+      type["curly_table"] = TriState.off;
+    } else {
+      debug(table) {                           // table
+        writeln(line);
+      }
+      an_object[an_object_key] ~= line ~= "\n";           // build table array (or string)
+    }
+  } else if (type["tic_table"] == TriState.on) {
+    if (matchFirst(line, rgx.block_tic_close)) {
+      debug(table) {                           // table (tic) close
+        writeln(line);
+      }
+      type["blocks"] = TriState.closing;
+      type["table"] = TriState.closing;
+      type["tic_table"] = TriState.off;
+    } else {
+      debug(table) {                           // table
+        writeln(line);
+      }
+      an_object[an_object_key] ~= line ~= "\n";           // build table array (or string)
+    }
+  }
+}
+#+END_SRC
+
+**** block end (close an open block): line empty, block flag       :close:
+
+#+name: abs_functions_block_line_status_empty
+#+BEGIN_SRC d
+void _block_flag_line_empty_(
+  char[]                       line,
+  ref string[string]           an_object,
+  ref ObjGenericComposite[]    the_document_body_section,
+  ref string[][string][string] bookindex_unordered_hashes,
+  ref int                      obj_cite_number,
+  ref ObjGenericComposite      _comp_obj_heading,
+  ref int                      cntr,
+  ref int[string]              type,
+  string[string]               obj_cite_number_poem,
+  string[string][string]       dochead_make_aa,
+) {
+  // 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 =
+      ocn_emit(type["ocn_status"]);
+    an_object["bookindex_nugget"] =
+      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
+    bookindex_unordered_hashes =
+      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
+    an_object["is"] = "code";
+    auto comp_obj_location =
+      node_construct.node_location_emitter(
+        content_non_header,
+        segment_anchor_tag_that_object_belongs_to,
+        obj_cite_number,
+        cntr,
+        heading_ptr-1,
+        an_object["is"]
+      );
+    auto substantive_object_and_anchor_tags_tuple =
+      obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+    an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+    anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+    comp_obj_code                             = comp_obj_code.init;
+    comp_obj_code.use                         = "body";
+    comp_obj_code.is_of                       = "block";
+    comp_obj_code.is_a                        = "code";
+    comp_obj_code.ocn                         = obj_cite_number;
+    comp_obj_code.obj_cite_number             = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+    comp_obj_code.text                        = an_object["substantive"];
+    the_document_body_section                 ~= comp_obj_code;
+    object_reset(an_object);
+    processing.remove("verse");
+    ++cntr;
+    type["blocks"] = TriState.off;
+    type["code"] = TriState.off;
+  } else if (type["poem"] == TriState.closing) {
+    an_object["bookindex_nugget"] =
+      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
+    bookindex_unordered_hashes =
+      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
+    an_object["is"] = "verse"; // check also
+    auto comp_obj_location =
+      node_construct.node_location_emitter(
+        content_non_header,
+        segment_anchor_tag_that_object_belongs_to,
+        obj_cite_number,
+        cntr,
+        heading_ptr-1,
+        an_object["is"]
+      );
+    comp_obj_poem_ocn                         = comp_obj_poem_ocn.init;
+    comp_obj_poem_ocn.use                     = "body";
+    comp_obj_poem_ocn.is_of                   = "block";
+    comp_obj_poem_ocn.is_a                    = "poem";
+    comp_obj_poem_ocn.ocn                     = obj_cite_number;
+    comp_obj_poem_ocn.obj_cite_number         = (obj_cite_number_poem["start"], obj_cite_number_poem["end"]);
+    comp_obj_poem_ocn.text                    = ""; // an_object["substantive"];
+    the_document_body_section                 ~= comp_obj_poem_ocn;
+    object_reset(an_object);
+    processing.remove("verse");
+    type["blocks"] = TriState.off;
+    type["poem"] = TriState.off;
+  } else if (type["table"] == TriState.closing) {
+    obj_cite_number =
+      ocn_emit(type["ocn_status"]);
+    an_object["bookindex_nugget"] =
+      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
+    bookindex_unordered_hashes =
+      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
+    an_object["is"] = "table";
+    auto comp_obj_location =
+      node_construct.node_location_emitter(
+        content_non_header,
+        segment_anchor_tag_that_object_belongs_to,
+        obj_cite_number,
+        cntr,
+        heading_ptr-1,
+        an_object["is"]
+      );
+    auto substantive_object_and_anchor_tags_tuple =
+      obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+    an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+    anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+    comp_obj_block                            = comp_obj_block.init;
+    comp_obj_block.use                        = "body";
+    comp_obj_block.is_of                      = "block";
+    comp_obj_block.is_a                       = "table";
+    comp_obj_block.ocn                        = obj_cite_number;
+    comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+    comp_obj_block.text                       = an_object["substantive"];
+    the_document_body_section                 ~= comp_obj_block;
+    object_reset(an_object);
+    processing.remove("verse");
+    ++cntr;
+    type["blocks"] = TriState.off;
+    type["table"] = TriState.off;
+  } else if (type["group"] == TriState.closing) {
+    obj_cite_number =
+      ocn_emit(type["ocn_status"]);
+    an_object["bookindex_nugget"] =
+      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
+    bookindex_unordered_hashes =
+      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
+    an_object["is"] = "group";
+    auto comp_obj_location =
+      node_construct.node_location_emitter(
+        content_non_header,
+        segment_anchor_tag_that_object_belongs_to,
+        obj_cite_number,
+        cntr,
+        heading_ptr-1,
+        an_object["is"]
+      );
+    auto substantive_object_and_anchor_tags_tuple =
+      obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+    an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+    anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+    comp_obj_block                            = comp_obj_block.init;
+    comp_obj_block.use                        = "body";
+    comp_obj_block.is_of                      = "block";
+    comp_obj_block.is_a                       = "group";
+    comp_obj_block.ocn                        = obj_cite_number;
+    comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+    comp_obj_block.text                       = an_object["substantive"];
+    the_document_body_section                 ~= comp_obj_block;
+    object_reset(an_object);
+    processing.remove("verse");
+    ++cntr;
+    type["blocks"] = TriState.off;
+    type["group"] = TriState.off;
+  } else if (type["block"] == TriState.closing) {
+    obj_cite_number = ocn_emit(type["ocn_status"]);
+    an_object["bookindex_nugget"] =
+      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
+    bookindex_unordered_hashes =
+      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
+    an_object["is"] = "block";
+    auto comp_obj_location =
+      node_construct.node_location_emitter(
+        content_non_header,
+        segment_anchor_tag_that_object_belongs_to,
+        obj_cite_number,
+        cntr,
+        heading_ptr-1,
+        an_object["is"]
+       );
+    auto substantive_object_and_anchor_tags_tuple =
+      obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+    an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+    anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+    comp_obj_block                            = comp_obj_block.init;
+    comp_obj_block.use                        = "body";
+    comp_obj_block.is_of                      = "block";
+    comp_obj_block.is_a                       = "block";
+    comp_obj_block.ocn                        = obj_cite_number;
+    comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+    comp_obj_block.text                       = an_object["substantive"];
+    the_document_body_section                 ~= comp_obj_block;
+    object_reset(an_object);
+    processing.remove("verse");
+    ++cntr;
+    type["blocks"] = TriState.off;
+    type["block"] = TriState.off;
+  } else if (type["quote"] == TriState.closing) {
+    obj_cite_number =
+      ocn_emit(type["ocn_status"]);
+    an_object["bookindex_nugget"] =
+      ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
+    bookindex_unordered_hashes =
+      bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
+    an_object["is"] = "quote";
+    auto comp_obj_location =
+      node_construct.node_location_emitter(
+        content_non_header,
+        segment_anchor_tag_that_object_belongs_to,
+        obj_cite_number,
+        cntr,
+        heading_ptr-1,
+        an_object["is"]
+      );
+    auto substantive_object_and_anchor_tags_tuple =
+      obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
+    an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
+    anchor_tags = substantive_object_and_anchor_tags_tuple[1];
+    comp_obj_block                            = comp_obj_block.init;
+    comp_obj_block.use                        = "body";
+    comp_obj_block.is_of                      = "block";
+    comp_obj_block.is_a                       = "quote";
+    comp_obj_block.ocn                        = obj_cite_number;
+    comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+    comp_obj_block.text                       = an_object["substantive"];
+    the_document_body_section                 ~= comp_obj_block;
+    object_reset(an_object);
+    processing.remove("verse");
+    ++cntr;
+    type["blocks"] = TriState.off;
+    type["quote"] = TriState.off;
+  }
+}
+#+END_SRC
+
+*** book index                                                  :bookindex:
+
+#+name: abs_functions_book_index
+#+BEGIN_SRC d
+auto _book_index_(L,I,O,T,B)(
+  L      line,
+  ref I  book_idx_tmp,
+  ref O  an_object,
+  ref T  type,
+  B      opt_action_bool,
+) {
+  debug(asserts){
+    static assert(is(typeof(line)            == char[]));
+    static assert(is(typeof(book_idx_tmp)    == string));
+    static assert(is(typeof(an_object)       == string[string]));
+    static assert(is(typeof(type)            == int[string]));
+    static assert(is(typeof(opt_action_bool) == bool[string]));
+  }
+  auto rgx = Rgx();
+  if (auto m = match(line, rgx.book_index)) {
+    /+ match book_index +/
+    debug(bookindexmatch) {                       // book index
+      writefln(
+        "* [bookindex] %s\n",
+        to!string(m.captures[1]),
+      );
+    }
+    an_object["bookindex_nugget"] = to!string(m.captures[1]);
+  } else if (auto m = match(line, rgx.book_index_open))  {
+    /+ match open book_index +/
+    type["book_index"] = State.on;
+    if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) {
+      book_idx_tmp = to!string(m.captures[1]);
+      debug(bookindexmatch) {                       // book index
+        writefln(
+          "* [bookindex] %s\n",
+          book_idx_tmp,
+        );
+      }
+    }
+  } 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;
+      if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) {
+        an_object["bookindex_nugget"] = book_idx_tmp ~ to!string(m.captures[1]);
+        debug(bookindexmatch) {                     // book index
+          writefln(
+            "* [bookindex] %s\n",
+            book_idx_tmp,
+          );
+        }
+      }
+      book_idx_tmp = "";
+    } else {
+      if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) {
+        book_idx_tmp ~= line;
+      }
+    }
+  }
+}
+#+END_SRC
+
+*** heading or paragraph                                :heading:paragraph:
+**** heading found                                               :heading:
+
+#+name: abs_functions_heading
+#+BEGIN_SRC d
+auto _heading_found_(L,X,H,R,T)(
+  L     line,
+  X     dochead_make_identify_unmarked_headings,
+  ref H heading_match_str,
+  ref R heading_match_rgx,
+  ref T type
+) {
+  debug(asserts){
+    static assert(is(typeof(line)                                    == char[]));
+    static assert(is(typeof(dochead_make_identify_unmarked_headings) == string));
+    static assert(is(typeof(heading_match_str)                       == string[string]));
+    static assert(is(typeof(heading_match_rgx)                       == Regex!(char)[string]));
+    static assert(is(typeof(type)                                    == int[string]));
+  }
+  auto rgx = Rgx();
+  if ((dochead_make_identify_unmarked_headings.length > 2)
+  && (type["make_headings"] == State.off)) {
+    /+ headings found +/
+    debug(headingsfound) {
+      writeln(dochead_make_identify_unmarked_headings);
+    }
+    char[][] make_headings_spl =
+      split(
+        cast(char[]) dochead_make_identify_unmarked_headings,
+        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;
+  }
+}
+#+END_SRC
+
+**** heading make set                                       :heading:
+
+#+name: abs_functions_heading
+#+BEGIN_SRC d
+auto _heading_make_set_(L,C,R,T)(
+  L     line,
+  C     line_occur,
+  ref R heading_match_rgx,
+  ref T type
+) {
+  debug(asserts){
+    static assert(is(typeof(line)              == char[]));
+    static assert(is(typeof(line_occur)        == int[string]));
+    static assert(is(typeof(heading_match_rgx) == Regex!(char)[string]));
+    static assert(is(typeof(type)              == int[string]));
+  }
+  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 (matchFirst(line, heading_match_rgx["h_B"])) {
+      line = "B~ " ~ line;
+      debug(headingsfound) {
+        writeln(line);
+      }
+    }
+    if (matchFirst(line, heading_match_rgx["h_C"])) {
+      line = "C~ " ~ line;
+      debug(headingsfound) {
+        writeln(line);
+      }
+    }
+    if (matchFirst(line, heading_match_rgx["h_D"])) {
+      line = "D~ " ~ line;
+      debug(headingsfound) {
+        writeln(line);
+      }
+    }
+    if (matchFirst(line, heading_match_rgx["h_1"])) {
+      line = "1~ " ~ line;
+      debug(headingsfound) {
+        writeln(line);
+      }
+    }
+    if (matchFirst(line, heading_match_rgx["h_2"])) {
+      line = "2~ " ~ line;
+      debug(headingsfound) {
+        writeln(line);
+      }
+    }
+    if (matchFirst(line, heading_match_rgx["h_3"])) {
+      line = "3~ " ~ line;
+      debug(headingsfound) {
+        writeln(line);
+      }
+    }
+    if (matchFirst(line, heading_match_rgx["h_4"])) {
+      line = "4~ " ~ line;
+      debug(headingsfound) {
+        writeln(line);
+      }
+    }
+  }
+}
+#+END_SRC
+
+**** heading match                                               :heading:
+
+#+name: abs_functions_heading
+#+BEGIN_SRC d
+auto _heading_matched_(L,C,O,K,Lv,Lc,T,Me)(
+  ref L  line,
+  ref C  line_occur,
+  ref O  an_object,
+  ref K  an_object_key,
+  ref Lv lv,
+  ref Lc collapsed_lev,
+  ref T  type,
+  ref Me dochead_meta_aa,
+) {
+  debug(asserts){
+    static assert(is(typeof(line)            == char[]));
+    static assert(is(typeof(line_occur)      == int[string]));
+    static assert(is(typeof(an_object)       == string[string]));
+    static assert(is(typeof(an_object_key)   == string));
+    static assert(is(typeof(lv)              == int[string]));
+    static assert(is(typeof(collapsed_lev)   == int[string]));
+    static assert(is(typeof(type)            == int[string]));
+    static assert(is(typeof(dochead_meta_aa) == string[string][string]));
+  }
+  auto rgx = Rgx();
+  if (auto m = match(line, rgx.heading)) {
+    /+ heading match +/
+    type["heading"] = State.on;
+    if (match(line, rgx.heading_seg_and_above)) {
+      type["biblio_section"] = State.off;
+      type["glossary_section"] = State.off;
+      type["blurb_section"] = State.off;
+    }
+    type["para"] = State.off;
+    ++line_occur["heading"];
+    an_object[an_object_key] ~= 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":
+      an_object[an_object_key]=replaceFirst(an_object[an_object_key],
+        rgx.variable_doc_title, (dochead_meta_aa["title"]["full"] ~ ","));
+      an_object[an_object_key]=replaceFirst(an_object[an_object_key],
+        rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]);
+      collapsed_lev["h0"] = 0;
+      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(strip(line));
+    }
+  }
+}
+#+END_SRC
+
+**** para match                                                     :para:
+
+#+name: abs_functions_para
+#+BEGIN_SRC d
+auto _para_match_(L,O,K,I,B,T,C)(
+  ref L  line,
+  ref O  an_object,
+  ref K  an_object_key,
+  ref I  indent,
+  ref B  bullet,
+  ref T  type,
+  ref C  line_occur,
+) {
+  debug(asserts){
+    static assert(is(typeof(line)          == char[]));
+    static assert(is(typeof(an_object)     == string[string]));
+    static assert(is(typeof(an_object_key) == string));
+    static assert(is(typeof(indent)        == int[string]));
+    static assert(is(typeof(bullet)        == bool));
+    static assert(is(typeof(type)          == int[string]));
+    static assert(is(typeof(line_occur)    == int[string]));
+  }
+  auto rgx = Rgx();
+  if (line_occur["para"] == State.off) {
+    /+ para matches +/
+    type["para"] = State.on;
+    an_object[an_object_key] ~= line;        // body_nugget
+    indent=[
+      "hang_position" : 0,
+      "base_position" : 0,
+    ];
+    bullet = false;
+    if (auto m = matchFirst(line, rgx.para_indent)) {
+      debug(paraindent) {                    // para indent
+        writeln(line);
+      }
+      indent["hang_position"] = to!int(m.captures[1]);
+      indent["base_position"] = 0;
+    } else if (matchFirst(line, rgx.para_bullet)) {
+      debug(parabullet) {                    // para bullet
+        writeln(line);
+      }
+      bullet = true;
+    } else if (auto m = matchFirst(line, rgx.para_indent_hang)) {
+      debug(paraindenthang) {                // para indent hang
+        writeln(line);
+      }
+      indent=[
+        "hang_position" : to!int(m.captures[1]),
+        "base_position" : to!int(m.captures[2]),
+      ];
+    } else if (auto m = matchFirst(line, rgx.para_bullet_indent)) {
+      debug(parabulletindent) {              // para bullet indent
+        writeln(line);
+      }
+      indent=[
+        "hang_position" : to!int(m.captures[1]),
+        "base_position" : 0,
+      ];
+      bullet = true;
+    }
+    ++line_occur["para"];
+  }
+}
+#+END_SRC
+
+*** function emitters                                            :emitters:
+**** object                                                       :object:
+***** ocn                                                           :ocn:
+
+#+name: ao_emitters_ocn
+#+BEGIN_SRC d
+struct OCNemitter {
+  int obj_cite_number, obj_cite_number_;
+  int ocn_emitter(int ocn_status_flag)
+  in { assert(ocn_status_flag <= 3); }
+  body {
+    if (ocn_status_flag == 3) {
+      obj_cite_number = obj_cite_number_ = 1;
+    } else {
+      obj_cite_number=(ocn_status_flag == 0)
+      ? ++obj_cite_number_
+      : 0;
+    }
+    assert(obj_cite_number >= 0);
+    return obj_cite_number;
+  }
+  invariant() {
+  }
+}
+#+END_SRC
+
+***** object inline markup munge                          :markup:inline:
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
+struct ObjInlineMarkupMunge {
+  string[string] obj_txt;
+  int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus;
+  string asterisks_;
+  string obj_txt_out, tail, note;
+  auto rgx = Rgx();
+  auto mkup = InlineMarkup();
+  private auto initialize_note_numbers() {
+    n_foot = 0;
+    n_foot_reg = 0;
+    n_foot_sp_asterisk = 0;
+    n_foot_sp_plus = 0;
+  }
+  string url_links(Ot)(Ot obj_txt_in) {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+    /+ url matched +/
+    if (auto m = matchAll(obj_txt_in, rgx.inline_url)) {
+      /+ link: naked url: http://url +/
+      if (match(obj_txt_in, rgx.inline_link_naked_url)) {
+        obj_txt_in =
+          replaceAll(
+            obj_txt_in,
+            rgx.inline_link_naked_url,
+            ("$1" ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~  mkup.url_o ~ "$2" ~  mkup.url_c ~ "$3")            // ("$1{ $2 }$2$3")
+          );
+      }
+      /+ link with helper for endnote including the url:
+           {~^ link which includes url as footnote }http://url
+         maps to:
+           { link which includes url as footnote }http://url~{ { http://url }http://url }~
+      +/
+      if (match(obj_txt_in, rgx.inline_link_endnote_url_helper)) {
+        obj_txt_in =
+          replaceAll(
+            obj_txt_in,
+            rgx.inline_link_endnote_url_helper_punctuated,
+            (mkup.lnk_o ~ " $1 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~  " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3")
+          );
+        obj_txt_in =
+          replaceAll(
+            obj_txt_in,
+            rgx.inline_link_endnote_url_helper,
+            (mkup.lnk_o ~ " $1 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~  " }~")   // ("{ $1 }$2~{ { $2 }$2 }~")
+          );
+      }
+      /+ link with regular markup:
+         { linked text or image }http://url
+      +/
+      if (match(obj_txt_in, rgx.inline_link_markup_regular)) {
+        obj_txt_in =
+          replaceAll(
+            obj_txt_in,
+            rgx.inline_link_markup_regular,
+            ("$1" ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~  mkup.url_o ~ "$3" ~  mkup.url_c ~ "$4")            // ("$1{ $2 }$3$4")
+          );
+      }
+    }
+    return obj_txt_in;
+  }
+  string footnotes_endnotes_markup_and_number_or_stars(Ot)(Ot obj_txt_in) {                                // here endnotes are marked up
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+    /+ endnotes (regular) +/
+    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)) {
+      if (auto m = matchAll(obj_txt_in, rgx.inline_text_and_note_al_)) {
+        foreach(n; m) {
+          if (match(to!string(n.hit), rgx.inline_al_delimiter_open_symbol_star)) {
+            ++n_foot_sp_asterisk;
+            asterisks_ = "*";
+            n_foot=n_foot_sp_asterisk;
+            obj_txt_out ~=
+              (replaceFirst(
+                to!string(n.hit),
+                rgx.inline_al_delimiter_open_symbol_star,
+                (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ")
+              ) ~ "\n");
+          } else if (match(to!string(n.hit), rgx.inline_al_delimiter_open_regular)) {
+            ++n_foot_reg;
+            n_foot=n_foot_reg;
+            obj_txt_out ~=
+              (replaceFirst(
+                to!string(n.hit),
+                rgx.inline_al_delimiter_open_regular,
+                (mkup.en_a_o ~ to!string(n_foot) ~ " ")
+              ) ~ "\n");
+          } else {
+            obj_txt_out ~= to!string(n.hit) ~ "\n";
+          }
+        }
+      }
+    } else {
+      obj_txt_out = obj_txt_in;
+    }
+    return obj_txt_out;
+  }
+  private auto object_notes_(string obj_txt_in)
+  in { }
+  body {
+    obj_txt_out = "";
+    tail = "";
+    /+ special endnotes +/
+    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)
+      );
+    /+ url matched +/
+    if (auto m = matchAll(obj_txt_in, rgx.inline_url)) {
+      obj_txt_in = url_links(obj_txt_in);
+    }
+    obj_txt_out = footnotes_endnotes_markup_and_number_or_stars(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(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    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(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    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"]=strip(obj_txt["munge"]);
+    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() {
+  }
+  /+ revisit +/
+  string code(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  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(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    obj_txt["munge"]=obj_txt_in;
+    obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+    return obj_txt["munge"];
+  }
+  invariant() {
+  }
+  string verse(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    obj_txt["munge"]=obj_txt_in;
+    obj_txt["munge"]=object_notes_(obj_txt["munge"]);
+    return obj_txt["munge"];
+  }
+  invariant() {
+  }
+  string quote(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    obj_txt["munge"]=obj_txt_in;
+    return obj_txt["munge"];
+  }
+  invariant() {
+  }
+  string table(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    obj_txt["munge"]=obj_txt_in;
+    return obj_txt["munge"];
+  }
+  invariant() {
+  }
+  string comment(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    obj_txt["munge"]=obj_txt_in;
+    return obj_txt["munge"];
+  }
+  invariant() {
+  }
+}
+#+END_SRC
+
+***** toc, tags, object inline markup                     :markup:inline:
+****** open
+
+#+name: ao_emitters_obj_inline_markup
+#+BEGIN_SRC d
+struct ObjInlineMarkup {
+  auto rgx = Rgx();
+  auto munge = ObjInlineMarkupMunge();
+  string[string] obj_txt;
+#+END_SRC
+
+****** object inline markup and anchor tags              :markup:inline:
+
+#+name: ao_emitters_obj_inline_markup_and_anchor_tags
+#+BEGIN_SRC d
+  auto obj_inline_markup_and_anchor_tags(O,K,Ma)(
+    O  obj_,
+    K  obj_key_,
+    Ma dochead_make_aa
+  )
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_)            == string[string]));
+      static assert(is(typeof(obj_key_)        == string));
+      static assert(is(typeof(dochead_make_aa) == string[string][string]));
+    }
+  }
+  body {
+    obj_txt["munge"]=obj_[obj_key_].dup;
+    obj_txt["munge"]=(match(obj_["is"], ctRegex!(`verse|code`)))
+    ? obj_txt["munge"]
+    : strip(obj_txt["munge"]);
+    static __gshared string[] anchor_tags_ = [];
+    switch (obj_["is"]) {
+    case "heading":
+      static __gshared string anchor_tag = "";
+      // TODO WORK ON, you still need to ensure that level 1 anchor_tags are unique
+      obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, dochead_make_aa);
+      obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"]);
+      if (auto m = match(obj_txt["munge"], rgx.heading_anchor_tag)) {
+        anchor_tag = m.captures[1];
+        anchor_tags_ ~=anchor_tag;
+      } else if (obj_["lev"] == "1") {
+        writeln("heading anchor tag missing: ", obj_txt["munge"]);
+      }
+      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;
+    }
+    auto t = tuple(
+     obj_txt["munge"],
+     anchor_tags_,
+    );
+    anchor_tags_=[];
+    return t;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+****** toc, table of contents build, gather headings     :markup:inline:
+
+#+name: ao_emitters_obj_inline_markup_table_of_contents
+#+BEGIN_SRC d
+  auto _clean_heading_toc_(Toc)(
+    Toc heading_toc_,
+  ) {
+   debug(asserts){
+     static assert(is(typeof(heading_toc_) == char[]));
+   }
+   auto m = matchFirst(cast(char[]) heading_toc_, rgx.heading);
+   heading_toc_ =
+     replaceAll(
+       m.post,
+       rgx.inline_notes_curly_gen,
+       ("")
+     );
+   return heading_toc_;
+  };
+  auto table_of_contents_gather_headings(O,Ma,Ts,Ta,X,Toc)(
+    O     obj_,
+    Ma    dochead_make_aa,
+    Ts    segment_anchor_tag_that_object_belongs_to,
+    Ta    _anchor_tag,
+    ref X lev4_subtoc,
+    Toc   the_table_of_contents_section,
+  )
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_)                                      == string[string]));
+      static assert(is(typeof(dochead_make_aa)                           == string[string][string]));
+      static assert(is(typeof(segment_anchor_tag_that_object_belongs_to) == string));
+      static assert(is(typeof(_anchor_tag)                               == string));
+      static assert(is(typeof(lev4_subtoc)                               == string[][string]));
+      static assert(is(typeof(the_table_of_contents_section)             == ObjGenericComposite[][string]));
+    }
+  }
+  body {
+    ObjGenericComposite comp_obj_toc;
+    mixin InternalMarkup;
+    auto mkup = InlineMarkup();
+    char[] heading_toc_ = to!(char[])(obj_["body_nugget"].dup.strip);
+    heading_toc_ = _clean_heading_toc_(heading_toc_);
+    auto attrib="";
+    string toc_txt_, subtoc_txt_;
+    int[string] indent;
+    if (to!int(obj_["lev_markup_number"]) > 0) {
+      indent=[
+        "hang_position" : to!int(obj_["lev_markup_number"]),
+        "base_position" : to!int(obj_["lev_markup_number"]),
+      ];
+      toc_txt_ = format(
+        "{ %s }#%s",
+        heading_toc_,
+        _anchor_tag,
+      );
+      toc_txt_= munge.url_links(toc_txt_);
+      comp_obj_toc                       = comp_obj_toc.init;
+      comp_obj_toc.use                   = "frontmatter";
+      comp_obj_toc.is_of                 = "para";
+      comp_obj_toc.is_a                  = "toc";
+      comp_obj_toc.ocn                   = 0;
+      comp_obj_toc.obj_cite_number       = "";
+      comp_obj_toc.indent_hang           = indent["hang_position"];
+      comp_obj_toc.indent_base           = indent["base_position"];
+      comp_obj_toc.bullet                = false;
+      comp_obj_toc.text                  = to!string(toc_txt_).strip;
+      the_table_of_contents_section["scroll"] ~= comp_obj_toc;
+    } else {
+      indent=[
+        "hang_position" : 0,
+        "base_position" : 0,
+      ];
+      comp_obj_toc                       = comp_obj_toc.init;
+      comp_obj_toc.use                   = "frontmatter";
+      comp_obj_toc.is_of                 = "para";
+      comp_obj_toc.is_a                  = "toc";
+      comp_obj_toc.ocn                   = 0;
+      comp_obj_toc.obj_cite_number       = "";
+      comp_obj_toc.indent_hang           = indent["hang_position"];
+      comp_obj_toc.indent_base           = indent["base_position"];
+      comp_obj_toc.bullet                = false;
+      comp_obj_toc.text                  = "Table of Contents";
+      the_table_of_contents_section["scroll"] ~= comp_obj_toc;
+    }
+    comp_obj_toc                       = comp_obj_toc.init;
+    comp_obj_toc.use                   = "frontmatter";
+    comp_obj_toc.is_of                 = "para";
+    comp_obj_toc.is_a                  = "toc";
+    comp_obj_toc.ocn                   = 0;
+    comp_obj_toc.obj_cite_number       = "";
+    comp_obj_toc.bullet                = false;
+    switch (to!int(obj_["lev_markup_number"])) {
+    case 0:
+      indent=[
+        "hang_position" : 0,
+        "base_position" : 0,
+      ];
+      toc_txt_ = "{ Table of Contents }" ~ mkup.mark_internal_site_lnk ~ "../toc.fnSuffix";
+      toc_txt_= munge.url_links(toc_txt_);
+      comp_obj_toc.indent_hang             = indent["hang_position"];
+      comp_obj_toc.indent_base             = indent["base_position"];
+      comp_obj_toc.text                    = to!string(toc_txt_).strip;
+      the_table_of_contents_section["seg"] ~= comp_obj_toc;
+      break;
+    case 1: .. case 3:
+      indent=[
+        "hang_position" : to!int(obj_["lev_markup_number"]),
+        "base_position" : to!int(obj_["lev_markup_number"]),
+      ];
+      toc_txt_ = format(
+        "%s",
+        heading_toc_,
+      );
+      toc_txt_= munge.url_links(toc_txt_);
+      comp_obj_toc.indent_hang             = indent["hang_position"];
+      comp_obj_toc.indent_base             = indent["base_position"];
+      comp_obj_toc.text                    = to!string(toc_txt_).strip;
+      the_table_of_contents_section["seg"] ~= comp_obj_toc;
+      break;
+    case 4:
+      toc_txt_ = format(
+        "{ %s }%s../%s.fnSuffix",
+        heading_toc_,
+        mkup.mark_internal_site_lnk,
+        segment_anchor_tag_that_object_belongs_to,
+      );
+      lev4_subtoc[segment_anchor_tag_that_object_belongs_to] = [];
+      toc_txt_= munge.url_links(toc_txt_);
+      indent=[
+        "hang_position" : to!int(obj_["lev_markup_number"]),
+        "base_position" : to!int(obj_["lev_markup_number"]),
+      ];
+      comp_obj_toc.indent_hang             = indent["hang_position"];
+      comp_obj_toc.indent_base             = indent["base_position"];
+      comp_obj_toc.text                    = to!string(toc_txt_).strip;
+      the_table_of_contents_section["seg"] ~= comp_obj_toc;
+      break;
+    case 5: .. case 7:
+      toc_txt_ = format(
+        "{ %s }%s../%s.fnSuffix#%s",
+        heading_toc_,
+        mkup.mark_internal_site_lnk,
+        segment_anchor_tag_that_object_belongs_to,
+        _anchor_tag,
+      );
+      subtoc_txt_ = format(
+        "{ %s }#%s",
+        heading_toc_,
+        _anchor_tag,
+      );
+      lev4_subtoc[segment_anchor_tag_that_object_belongs_to] ~= obj_["lev_markup_number"] ~ "~ " ~ to!string(subtoc_txt_).strip;
+      toc_txt_= munge.url_links(toc_txt_);
+      indent=[
+        "hang_position" : to!int(obj_["lev_markup_number"]),
+        "base_position" : to!int(obj_["lev_markup_number"]),
+      ];
+      comp_obj_toc.indent_hang             = indent["hang_position"];
+      comp_obj_toc.indent_base             = indent["base_position"];
+      comp_obj_toc.text                    = to!string(toc_txt_).strip;
+      the_table_of_contents_section["seg"] ~= comp_obj_toc;
+      break;
+    default:
+      break;
+    }
+    return the_table_of_contents_section;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+****** private:
+
+#+name: ao_emitters_obj_inline_markup_private
+#+BEGIN_SRC d
+private:
+#+END_SRC
+
+******* make heading number and segment anchor tags if instructed :markup:inline:segment:anchor:tags:
+
+#+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags
+#+BEGIN_SRC d
+  static string _configured_auto_heading_numbering_and_segment_anchor_tags(M,O,Ma)(
+    M  munge_,
+    O  obj_,
+    Ma dochead_make_aa
+  ) {
+    debug(asserts){
+      static assert(is(typeof(munge_)          == string));
+      static assert(is(typeof(obj_)            == string[string]));
+      static assert(is(typeof(dochead_make_aa) == string[string][string]));
+    }
+    if (dochead_make_aa["make"]["num_top"].length > 0) {
+      if (!(match(munge_, rgx.heading_anchor_tag))) {
+        static __gshared int heading_num_top_level=9;
+        static __gshared int heading_num_depth=2;
+        static __gshared int heading_num_0 = 0;
+        static __gshared int heading_num_1 = 0;
+        static __gshared int heading_num_2 = 0;
+        static __gshared int heading_num_3 = 0;
+        static __gshared string heading_number_auto_composite = "";
+        if (heading_num_top_level==9) {
+          if (dochead_make_aa["make"]["num_depth"].length > 0) {
+            heading_num_depth = to!uint(dochead_make_aa["make"]["num_depth"]);
+          }
+          switch (dochead_make_aa["make"]["num_top"]) {
+          case "A":
+            break;
+          case "B":
+            heading_num_top_level=1;
+            break;
+          case "C":
+            heading_num_top_level=2;
+            break;
+          case "D":
+            heading_num_top_level=3;
+            break;
+          case "1":
+            heading_num_top_level=4;
+            break;
+          case "2":
+            heading_num_top_level=5;
+            break;
+          case "3":
+            heading_num_top_level=6;
+            break;
+          case "4":
+            heading_num_top_level=7;
+            break;
+          default:
+            break;
+          }
+        }
+        /+ num_depth minimum 0 (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement +/
+        if (heading_num_top_level > to!uint(obj_["lev_markup_number"])) {
+          heading_num_0 = 0;
+          heading_num_1 = 0;
+          heading_num_2 = 0;
+          heading_num_3 = 0;
+        } else if (heading_num_top_level == to!uint(obj_["lev_markup_number"])) {
+          heading_num_0 ++;
+          heading_num_1 = 0;
+          heading_num_2 = 0;
+          heading_num_3 = 0;
+        } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 1)) {
+          heading_num_1 ++;
+          heading_num_2 = 0;
+          heading_num_3 = 0;
+        } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 2)) {
+          heading_num_2 ++;
+          heading_num_3 = 0;
+        } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 3)) {
+          heading_num_3 ++;
+        }
+        if (heading_num_3 > 0) {
+          heading_number_auto_composite =
+            (heading_num_depth == 3)
+            ? ( to!string(heading_num_0) ~ "." ~
+                  to!string(heading_num_1) ~ "." ~
+                  to!string(heading_num_2) ~ "." ~
+                  to!string(heading_num_3)
+                )
+            : "";
+        } else if (heading_num_2 > 0) {
+          heading_number_auto_composite =
+            ((heading_num_depth >= 2)
+            && (heading_num_depth <= 3))
+            ?  ( to!string(heading_num_0) ~ "." ~
+                  to!string(heading_num_1) ~ "." ~
+                  to!string(heading_num_2)
+                )
+            : "";
+        } else if (heading_num_1 > 0) {
+          heading_number_auto_composite =
+            ((heading_num_depth >= 1)
+            && (heading_num_depth <= 3))
+            ? ( to!string(heading_num_0) ~ "." ~
+                  to!string(heading_num_1)
+                )
+            : "";
+        } else if (heading_num_0 > 0) {
+          heading_number_auto_composite =
+            ((heading_num_depth >= 0)
+            && (heading_num_depth <= 3))
+            ?  (to!string(heading_num_0))
+            : "";
+        } else {
+          heading_number_auto_composite = "";
+        }
+        debug(heading_number_auto) {
+          writeln(heading_number_auto_composite);
+        }
+        if (!empty(heading_number_auto_composite)) {
+          munge_=replaceFirst(munge_, rgx.heading,
+            "$1~$2 " ~ heading_number_auto_composite ~ ". ");
+          munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
+            "$1~" ~ heading_number_auto_composite ~ " ");
+        }
+      }
+    }
+    return munge_;
+  }
+#+END_SRC
+
+******** unittests
+
+#+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags
+#+BEGIN_SRC d
+#+END_SRC
+
+******* make segment anchor tags if not provided :markup:inline:segment:anchor:tags:
+
+#+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags
+#+BEGIN_SRC d
+
+  static string _make_segment_anchor_tags_if_none_provided(M,Lv)(M munge_, Lv lev_) {
+    debug(asserts){
+      static assert(is(typeof(munge_) == string));
+      static assert(is(typeof(lev_)   == string));
+    }
+    if (!(match(munge_, rgx.heading_anchor_tag))) { // if (anchor_tags_.length == 0) {
+      if (match(munge_, rgx.heading_identify_anchor_tag)) {
+        if (auto m = match(munge_, rgx.heading_extract_named_anchor_tag)) {
+          munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
+            "$1~" ~ toLower(m.captures[1]) ~ "_"  ~ m.captures[2] ~ " ");
+        } else if (auto m = match(munge_, rgx.heading_extract_unnamed_anchor_tag)) {
+          munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
+            "$1~" ~ "s" ~ m.captures[1] ~ " ");
+        }
+      } else if (lev_ == "1") { // (if not successful) manufacture a unique anchor tag for lev=="1"
+        static __gshared int heading_num_lev1 = 0;
+        heading_num_lev1 ++;
+        munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
+          "$1~" ~ "x" ~ to!string(heading_num_lev1) ~ " ");
+      }
+    }
+    return munge_;
+  }
+#+END_SRC
+
+******** unittests
+
+#+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags
+#+BEGIN_SRC d
+  unittest {
+    string txt_lev="1";
+    string txt_in, txt_out;
+
+    txt_in = "1~copyright Copyright";
+    txt_out ="1~copyright Copyright";
+    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
+
+    txt_in = "1~ 6. Writing Copyright Licenses";
+    txt_out ="1~s6 6. Writing Copyright Licenses";
+    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
+
+    txt_in= "1~ 1. Reinforcing trends";
+    txt_out= "1~s1 1. Reinforcing trends";
+    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
+
+    txt_in= "1~ 11 SCIENCE AS A COMMONS";
+    txt_out= "1~s11 11 SCIENCE AS A COMMONS";
+    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
+
+    txt_in= "1~ Chapter 1";
+    txt_out="1~chapter_1 Chapter 1";
+    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
+
+    txt_in= "1~ Chapter 1.";
+    txt_out="1~chapter_1 Chapter 1.";
+    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
+
+    txt_in= "1~ Chapter 1: Done";
+    txt_out="1~chapter_1 Chapter 1: Done";
+    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
+
+    txt_in=  "1~ Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment";
+    txt_out= "1~chapter_11 Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment";
+    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
+
+    txt_in= "1~ CHAPTER I.";
+    txt_out="1~x1 CHAPTER I.";
+    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
+
+    txt_in= "1~ CHAPTER II.";
+    txt_out="1~x2 CHAPTER II.";
+    assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
+  }
+#+END_SRC
+
+****** close
+
+#+name: ao_emitters_obj_inline_markup_close
+#+BEGIN_SRC d
+}
+#+END_SRC
+
+***** object attrib                                          :attributes:
+****** attributes structure open, public
+
+#+name: ao_emitters_obj_attributes
+#+BEGIN_SRC d
+struct ObjAttributes {
+  string[string] _obj_attrib;
+#+END_SRC
+
+****** attributes structure open, public
+
+#+name: ao_emitters_obj_attributes_public
+#+BEGIN_SRC d
+  string obj_attributes(Oi,OR,OH)(
+    Oi obj_is_,
+    OR obj_raw,
+    OH _comp_obj_heading,
+  )
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_is_)           == string));
+      static assert(is(typeof(obj_raw)           == string));
+      static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite));
+    }
+  }
+  body {
+    scope(exit) {
+      destroy(obj_is_);
+      destroy(obj_raw);
+      destroy(_comp_obj_heading);
+    }
+    _obj_attrib["json"] ="{";
+    switch (obj_is_) {
+    case "heading":
+      _obj_attrib["json"] ~= _heading(obj_raw);
+      break;
+    case "para":
+      _obj_attrib["json"] ~= _para_and_blocks(obj_raw)
+      ~ _para(obj_raw);
+      break;
+    case "code":
+      _obj_attrib["json"] ~= _code(obj_raw);
+      break;
+    case "group":
+      _obj_attrib["json"] ~= _para_and_blocks(obj_raw)
+      ~ _group(obj_raw);
+      break;
+    case "block":
+      _obj_attrib["json"] ~= _para_and_blocks(obj_raw)
+      ~ _block(obj_raw);
+      break;
+    case "verse":
+      _obj_attrib["json"] ~= _verse(obj_raw);
+      break;
+    case "quote":
+      _obj_attrib["json"] ~= _quote(obj_raw);
+      break;
+    case "table":
+      _obj_attrib["json"] ~= _table(obj_raw);
+      break;
+    case "comment":
+      _obj_attrib["json"] ~= _comment(obj_raw);
+      break;
+    default:
+      _obj_attrib["json"] ~= _para(obj_raw);
+      break;
+    }
+    _obj_attrib["json"] ~=" }";
+    _obj_attrib["json"]=_set_additional_values_parse_as_json(_obj_attrib["json"], obj_is_, _comp_obj_heading);
+    debug(structattrib) {
+      if (oa_j["is"].str() == "heading") {
+        writeln(_obj_attrib["json"]);
+        writeln(
+          "is: ", oa_j["is"].str(),
+          "; obj_cite_number: ", oa_j["obj_cite_number"].integer()
+        );
+      }
+    }
+    return _obj_attrib["json"];
+  }
+  invariant() {
+  }
+#+END_SRC
+
+****** private
+
+#+name: ao_emitters_obj_attributes_private
+#+BEGIN_SRC d
+  private:
+  string _obj_attributes;
+#+END_SRC
+
+******* attrubutes
+******** para and block
+
+#+name: ao_emitters_obj_attributes_private_an_attribute
+#+BEGIN_SRC d
+  string _para_and_blocks(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    if (matchFirst(obj_txt_in, rgx.para_bullet)) {
+      _obj_attributes =" \"bullet\": \"true\","
+      ~ " \"indent_hang\": 0,"
+      ~ " \"indent_base\": 0,";
+    } else if (auto m = matchFirst(obj_txt_in, rgx.para_bullet_indent)) {
+      _obj_attributes =" \"bullet\": \"true\","
+      ~ " \"indent_hang\": " ~ to!string(m.captures[1]) ~ ","
+      ~ " \"indent_base\": " ~ to!string(m.captures[1]) ~ ",";
+    } else if (auto m = matchFirst(obj_txt_in, rgx.para_indent_hang)) {
+      _obj_attributes =" \"bullet\": \"false\","
+      ~ " \"indent_hang\": " ~ to!string(m.captures[1]) ~ ","
+      ~ " \"indent_base\": " ~  to!string(m.captures[2]) ~ ",";
+    } else if (auto m = matchFirst(obj_txt_in, rgx.para_indent)) {
+      _obj_attributes =" \"bullet\": \"false\","
+      ~ " \"indent_hang\": " ~ to!string(m.captures[1]) ~ ","
+      ~ " \"indent_base\": " ~ to!string(m.captures[1]) ~ ",";
+    } else {
+      _obj_attributes =" \"bullet\": \"false\","
+      ~ " \"indent_hang\": 0,"
+      ~ " \"indent_base\": 0,";
+    }
+    return _obj_attributes;
+  }
+#+END_SRC
+
+******** para
+
+#+name: ao_emitters_obj_attributes_private_an_attribute
+#+BEGIN_SRC d
+  string _para(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    _obj_attributes = " \"use\": \"content\","
+    ~ " \"of\": \"para\","
+    ~ " \"is\": \"para\"";
+    return _obj_attributes;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+******** heading
+
+#+name: ao_emitters_obj_attributes_private_an_attribute
+#+BEGIN_SRC d
+  string _heading(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    _obj_attributes = " \"use\": \"content\","
+    ~ " \"of\": \"para\","
+    ~ " \"is\": \"heading\"";
+    return _obj_attributes;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+******** code
+
+#+name: ao_emitters_obj_attributes_private_an_attribute
+#+BEGIN_SRC d
+  string _code(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    _obj_attributes = " \"use\": \"content\","
+    ~ " \"of\": \"block\","
+    ~ " \"is\": \"code\"";
+    return _obj_attributes;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+******** group
+
+#+name: ao_emitters_obj_attributes_private_an_attribute
+#+BEGIN_SRC d
+  string _group(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    _obj_attributes = " \"use\": \"content\","
+    ~ " \"of\": \"block\","
+    ~ " \"is\": \"group\"";
+    return _obj_attributes;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+******** block
+
+#+name: ao_emitters_obj_attributes_private_an_attribute
+#+BEGIN_SRC d
+  string _block(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    _obj_attributes = " \"use\": \"content\","
+    ~ " \"of\": \"block\","
+    ~ " \"is\": \"block\"";
+    return _obj_attributes;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+******** verse
+
+#+name: ao_emitters_obj_attributes_private_an_attribute
+#+BEGIN_SRC d
+  string _verse(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    _obj_attributes = " \"use\": \"content\","
+    ~ " \"of\": \"block\","
+    ~ " \"is\": \"verse\"";
+    return _obj_attributes;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+******** quote
+
+#+name: ao_emitters_obj_attributes_private_an_attribute
+#+BEGIN_SRC d
+  string _quote(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    _obj_attributes = " \"use\": \"content\","
+    ~ " \"of\": \"block\","
+    ~ " \"is\": \"quote\"";
+    return _obj_attributes;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+******** table
+
+#+name: ao_emitters_obj_attributes_private_an_attribute
+#+BEGIN_SRC d
+  string _table(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    _obj_attributes = " \"use\": \"content\","
+    ~ " \"of\": \"block\","
+    ~ " \"is\": \"table\"";
+    return _obj_attributes;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+******** comment
+
+#+name: ao_emitters_obj_attributes_private_an_attribute
+#+BEGIN_SRC d
+  string _comment(Ot)(Ot obj_txt_in)
+  in {
+    debug(asserts){
+      static assert(is(typeof(obj_txt_in) == string));
+    }
+  }
+  body {
+    _obj_attributes = " \"use\": \"comment\","
+    ~ " \"of\": \"comment\","
+    ~ " \"is\": \"comment\"";
+    return _obj_attributes;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+******* set additional attribute values, parse as json
+
+#+name: ao_emitters_obj_attributes_private_json
+#+BEGIN_SRC d
+  string _set_additional_values_parse_as_json(OA,Oi,OH)(
+    OA _obj_attrib,
+    Oi obj_is_,
+    OH _comp_obj_heading,
+  ) {
+    debug(asserts){
+      static assert(is(typeof(_obj_attrib)       == string));
+      static assert(is(typeof(obj_is_)           == string));
+      static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite));
+    }
+    JSONValue oa_j = parseJSON(_obj_attrib);
+    assert(
+      (oa_j.type == JSON_TYPE.OBJECT)
+    );
+    if (obj_is_ == "heading") {
+      oa_j.object["obj_cite_number"] = _comp_obj_heading.ocn;
+      oa_j.object["lev_markup_number"] = _comp_obj_heading.heading_lev_markup;
+      oa_j.object["lev_collapsed_number"] = _comp_obj_heading.heading_lev_collapsed;
+      oa_j.object["heading_ptr"] =
+        _comp_obj_heading.ptr_heading;
+      oa_j.object["doc_object_ptr"] =
+        _comp_obj_heading.ptr_doc_object;
+    }
+    oa_j.object["parent_obj_cite_number"] = _comp_obj_heading.parent_ocn;
+    oa_j.object["parent_lev_markup_number"] = _comp_obj_heading.parent_lev_markup;
+    _obj_attrib = oa_j.toString();
+    return _obj_attrib;
+  }
+#+END_SRC
+
+****** close
+
+#+name: ao_emitters_obj_attributes_private_close
+#+BEGIN_SRC d
+}
+#+END_SRC
+
+**** book index                                               :book:index:
+***** book index nugget hash                                :hash:nugget:
+
+#+name: ao_emitters_book_index_nugget
+#+BEGIN_SRC d
+struct BookIndexNuggetHash {
+  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(BI,N)(
+    BI bookindex_section,
+    N  obj_cite_number
+  )
+  in {
+    debug(asserts){
+      static assert(is(typeof(bookindex_section) == string));
+      static assert(is(typeof(obj_cite_number)   == int));
+    }
+    debug(bookindexraw) {
+      if (!bookindex_section.empty) {
+        writeln(
+          "* [bookindex] ",
+          "[", 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() {
+  }
+}
+#+END_SRC
+
+***** book index (sort &) report indented               :report:indented:
+
+#+name: ao_emitters_book_index_report_indented
+#+BEGIN_SRC d
+struct BookIndexReportIndent {
+  int mkn, skn;
+  auto bookindex_report_indented(BI)(
+    BI bookindex_unordered_hashes
+  ) {
+    debug(asserts){
+      static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string]));
+    }
+    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]
+          ));
+        }
+        ++skn;
+      }
+      ++mkn;
+    }
+  }
+}
+#+END_SRC
+
+***** book index (sort &) report section                 :report:section:
+****** book index struct open
+
+#+name: ao_emitters_book_index_report_section
+#+BEGIN_SRC d
+struct BookIndexReportSection {
+  int  mkn, skn;
+  auto rgx = Rgx();
+  auto munge = ObjInlineMarkupMunge();
+#+END_SRC
+
+****** bookindex write section
+
+#+name: ao_emitters_book_index_report_section
+#+BEGIN_SRC d
+  auto bookindex_write_section(BI)(
+    BI bookindex_unordered_hashes
+  ) {
+    debug(asserts){
+      static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string]));
+    }
+    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;
+    }
+  }
+#+END_SRC
+
+****** book index (sort &) build section                :report:section:
+
+#+name: ao_emitters_book_index_report_section
+#+BEGIN_SRC d
+  auto bookindex_build_abstraction_section(BI,N,Ta,B)(
+    BI bookindex_unordered_hashes,
+    N  obj_cite_number,
+    Ta segment_anchor_tag_that_object_belongs_to,
+    B  opt_action_bool,
+  ) {
+    debug(asserts){
+      static assert(is(typeof(bookindex_unordered_hashes)                == string[][string][string]));
+      static assert(is(typeof(obj_cite_number)                           == int));
+      static assert(is(typeof(segment_anchor_tag_that_object_belongs_to) == string));
+      static assert(is(typeof(opt_action_bool)                           == bool[string]));
+    }
+    mixin SiSUnode;
+    mixin InternalMarkup;
+    auto mkup = InlineMarkup();
+    string type_is;
+    string lev;
+    int heading_lev_markup, heading_lev_collapsed;
+    string attrib;
+    int[string] indent;
+    auto mainkeys =
+      bookindex_unordered_hashes.byKey.array.sort().release;
+    ObjGenericComposite[][string] bookindex_section;
+    ObjGenericComposite comp_obj_heading_, comp_obj_para;
+    auto node_para_int_ = node_metadata_para_int;
+    auto node_para_str_ = node_metadata_para_str;
+    if ((mainkeys.length > 0)
+    && (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"])) {
+      string bi_tmp_seg, bi_tmp_scroll;
+      string[] bi_tmp_tags;
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.use                   = "backmatter";
+      comp_obj_heading_.is_of                 = "para";
+      comp_obj_heading_.is_a                  = "heading";
+      comp_obj_heading_.text                  = "Book Index";
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.marked_up_level       = "B";
+      comp_obj_heading_.heading_lev_markup    = 1;
+      comp_obj_heading_.heading_lev_collapsed = 1;
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      bookindex_section["scroll"]             ~= comp_obj_heading_;
+      bookindex_section["seg"]                ~= comp_obj_heading_;
+      ++obj_cite_number;
+      ++mkn;
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.use                   = "backmatter";
+      comp_obj_heading_.is_of                 = "para";
+      comp_obj_heading_.is_a                  = "heading";
+      comp_obj_heading_.text                  = "Index";
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.segment_anchor_tag    = "bookindex";
+      comp_obj_heading_.marked_up_level       = "1";
+      comp_obj_heading_.heading_lev_markup    = 4;
+      comp_obj_heading_.heading_lev_collapsed = 2;
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      comp_obj_heading_.anchor_tags           = ["bookindex"];
+      bookindex_section["scroll"]             ~= comp_obj_heading_;
+      bookindex_section["seg"]                ~= comp_obj_heading_;
+      ++obj_cite_number;
+      ++mkn;
+      import std.array : appender;
+      auto buffer = appender!(char[])();
+      string[dchar] transTable = [' ' : "_"];
+      foreach (mainkey; mainkeys) {
+        bi_tmp_tags = [""];
+        bi_tmp_scroll = "!{" ~ mainkey ~ "}! ";
+        buffer.clear();
+        bi_tmp_tags ~= translate(mainkey, transTable);
+        bi_tmp_seg = "!{" ~ mainkey ~ "}! ";
+        foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
+          auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+          bi_tmp_scroll ~= munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ");
+          bi_tmp_seg ~= (segment_anchor_tag_that_object_belongs_to.empty)
+          ? munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ")
+          : munge.url_links(" {" ~ ref_ ~ "}" ~ mkup.mark_internal_site_lnk ~ "../" ~ segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#" ~ go ~ ", ");
+        }
+        bi_tmp_scroll ~= " \\\\\n    ";
+        bi_tmp_seg ~= " \\\\\n    ";
+        bookindex_unordered_hashes[mainkey].remove("_a");
+        auto subkeys =
+          bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
+        foreach (subkey; subkeys) {
+          bi_tmp_scroll ~= subkey ~ ", ";
+          buffer.clear();
+          bi_tmp_tags ~= translate(subkey, transTable);
+          bi_tmp_seg ~= subkey ~ ", ";
+          foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
+            auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+            bi_tmp_scroll ~= munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ");
+            bi_tmp_seg ~= (segment_anchor_tag_that_object_belongs_to.empty)
+            ? munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ")
+            : munge.url_links(" {" ~ ref_ ~ "}" ~ mkup.mark_internal_site_lnk ~ "../" ~ segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#" ~ go ~ ", ");
+          }
+          bi_tmp_scroll ~= " \\\\\n    ";
+          bi_tmp_seg ~= " \\\\\n    ";
+          ++skn;
+        }
+        bi_tmp_scroll = replaceFirst(bi_tmp_scroll, rgx.trailing_linebreak, "");
+        bi_tmp_seg = replaceFirst(bi_tmp_seg, rgx.trailing_linebreak, "");
+        comp_obj_para                       = comp_obj_para.init;
+        comp_obj_para.use                   = "backmatter";
+        comp_obj_para.is_of                 = "para";
+        comp_obj_para.is_a                  = "bookindex";
+        comp_obj_para.text                  = to!string(bi_tmp_scroll).strip;
+        comp_obj_para.ocn                   = obj_cite_number;
+        comp_obj_para.obj_cite_number       = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+        comp_obj_para.anchor_tags           = bi_tmp_tags;
+        comp_obj_para.indent_hang           = 0;
+        comp_obj_para.indent_base           = 1;
+        comp_obj_para.bullet                = false;
+        bookindex_section["scroll"]         ~= comp_obj_para;
+        comp_obj_para.text                  = to!string(bi_tmp_seg).strip;
+        bookindex_section["seg"]            ~= comp_obj_para;
+        ++obj_cite_number;
+        ++mkn;
+      }
+    } else {                              // no book index, (figure out what to do here)
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.text                  = "(skip) there is no Book Index";
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.marked_up_level       = "B";
+      comp_obj_heading_.heading_lev_markup    = 1;
+      comp_obj_heading_.heading_lev_collapsed = 1;
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      bookindex_section["scroll"]             ~= comp_obj_heading_;
+      bookindex_section["seg"]                ~= comp_obj_heading_;
+    }
+    auto t = tuple(bookindex_section, obj_cite_number);
+    return t;
+  }
+#+END_SRC
+
+****** book index struct close
+
+#+name: ao_emitters_book_index_report_section
+#+BEGIN_SRC d
+}
+#+END_SRC
+
+**** (end)notes section                                 :endnotes:section:
+
+#+name: ao_emitters_endnotes
+#+BEGIN_SRC d
+struct NotesSection {
+  string[string] object_notes;
+  int previous_count;
+  int mkn;
+  auto rgx = Rgx();
+#+END_SRC
+
+***** gather notes for endnote section struct open
+
+#+name: ao_emitters_endnotes
+#+BEGIN_SRC d
+  private auto gather_notes_for_endnote_section(
+    ObjGenericComposite[] contents_am,
+    string                segment_anchor_tag_that_object_belongs_to,
+    int                   cntr,
+  )
+  in {
+    // endnotes/ footnotes for
+    // doc objects other than paragraphs & headings
+    // various forms of grouped text
+    assert((contents_am[cntr].is_a == "para")
+    || (contents_am[cntr].is_a == "heading")
+    || (contents_am[cntr].is_a == "group"));
+    assert(cntr >= previous_count);
+    previous_count=cntr;
+    assert(
+      match(contents_am[cntr].text,
+      rgx.inline_notes_delimiter_al_regular_number_note)
+    );
+  }
+  body {
+    mixin InternalMarkup;
+    auto mkup = InlineMarkup();
+    auto munge = ObjInlineMarkupMunge();
+    foreach(
+      m;
+      matchAll(
+        contents_am[cntr].text,
+        rgx.inline_notes_delimiter_al_regular_number_note
+      )
+    ) {
+      debug(endnotes_build) {
+        writeln(
+          "{^{", m.captures[1], ".}^}" ~ mkup.mark_internal_site_lnk ~ "../", segment_anchor_tag_that_object_belongs_to, ".fnSuffix#noteref_\n  ", m.captures[1], " ",
+          m.captures[2]); // sometimes need segment name (segmented html & epub)
+      }
+      // TODO NEXT you need anchor for segments at this point ->
+      object_notes["anchor"] ~= "#note_" ~ m.captures[1] ~ "』";
+      object_notes["notes"] ~= (segment_anchor_tag_that_object_belongs_to.empty)
+      ? (munge.url_links(
+          "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~
+          m.captures[1]) ~ " " ~ m.captures[2] ~ "』"
+        )
+      : (munge.url_links(
+          "{^{" ~ m.captures[1] ~ ".}^}" ~ mkup.mark_internal_site_lnk ~ "../" ~
+          segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#noteref_" ~
+          m.captures[1]) ~ " " ~ m.captures[2] ~ "』"
+        );
+    }
+    return object_notes;
+  }
+#+END_SRC
+
+***** gathered notes
+
+#+name: ao_emitters_endnotes
+#+BEGIN_SRC d
+  private auto gathered_notes()
+  in {
+  }
+  body {
+    string[][string] endnotes_;
+    if (object_notes.length > 1) {
+      endnotes_["notes"] = (split(object_notes["notes"], rgx.break_string))[0..$-1];
+      endnotes_["anchor"] = (split(object_notes["anchor"], rgx.break_string))[0..$-1];
+    } else {
+      endnotes_["notes"] = [];
+      endnotes_["anchor"] = [];
+    }
+    return endnotes_;
+  }
+#+END_SRC
+
+***** endnote objects
+
+#+name: ao_emitters_endnotes
+#+BEGIN_SRC d
+  private auto endnote_objects(
+    int            obj_cite_number,
+    bool[string]   opt_action_bool,
+  )
+  in {
+  }
+  body {
+    mixin SiSUnode;
+    ObjGenericComposite[] the_endnotes_section;
+    auto endnotes_ = gathered_notes();
+    string type_is;
+    string lev, lev_markup_number, lev_collapsed_number;
+    string attrib;
+    int[string] indent;
+    ObjGenericComposite comp_obj_heading_;
+    if ((endnotes_["notes"].length > 0)
+    && (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"])) {
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.use                   = "backmatter";
+      comp_obj_heading_.is_of                 = "para";
+      comp_obj_heading_.is_a                  = "heading";
+      comp_obj_heading_.text                  = "Endnotes";
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.marked_up_level       = "B";
+      comp_obj_heading_.heading_lev_markup    = 1;
+      comp_obj_heading_.heading_lev_collapsed = 1;
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      the_endnotes_section                    ~= comp_obj_heading_;
+      ++obj_cite_number;
+      ++mkn;
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.use                   = "backmatter";
+      comp_obj_heading_.is_of                 = "para";
+      comp_obj_heading_.is_a                  = "heading";
+      comp_obj_heading_.text                  = "Endnotes";
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.segment_anchor_tag    = "endnotes";
+      comp_obj_heading_.marked_up_level       = "1";
+      comp_obj_heading_.heading_lev_markup    = 4;
+      comp_obj_heading_.heading_lev_collapsed = 2;
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      comp_obj_heading_.anchor_tags           = ["endnotes"];
+      the_endnotes_section                    ~= comp_obj_heading_;
+      ++obj_cite_number;
+      ++mkn;
+    } else {
+      comp_obj_heading_                       = comp_obj_heading_.init;
+      comp_obj_heading_.use                   = "empty";
+      comp_obj_heading_.is_of                 = "para";
+      comp_obj_heading_.is_a                  = "heading";
+      comp_obj_heading_.text                  = "(skip) there are no Endnotes";
+      comp_obj_heading_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.marked_up_level       = "B";
+      comp_obj_heading_.heading_lev_markup    = 1;
+      comp_obj_heading_.heading_lev_collapsed = 1;
+      comp_obj_heading_.parent_ocn            = 1;
+      comp_obj_heading_.parent_lev_markup     = 0;
+      the_endnotes_section                    ~= comp_obj_heading_;
+    }
+    if (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"]) {
+      ObjGenericComposite comp_obj_endnote_;
+      comp_obj_endnote_                       = comp_obj_endnote_.init;
+      comp_obj_endnote_.use                   = "backmatter";
+      comp_obj_endnote_.is_of                 = "para";
+      comp_obj_endnote_.is_a                  = "endnote";
+      comp_obj_endnote_.ocn                   = 0;
+      comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_endnote_.indent_hang           = 0;
+      comp_obj_endnote_.indent_base           = 0;
+      comp_obj_endnote_.bullet                = false;
+      foreach (i, endnote; endnotes_["notes"]) {
+        auto     m                            = (matchFirst(endnote, rgx.note_ref));
+        string   notenumber                   = to!string(m.captures[1]);
+        string   anchor_tag                   = "note_" ~ notenumber;
+        comp_obj_endnote_.anchor_tags         ~= [ endnotes_["anchor"][i] ];
+        comp_obj_endnote_.text                = endnote.strip;
+        the_endnotes_section                  ~= comp_obj_endnote_;
+      }
+    }
+    auto t = tuple(the_endnotes_section, obj_cite_number);
+    return t;
+  }
+#+END_SRC
+
+***** gather notes for endnote section struct close
+
+#+name: ao_emitters_endnotes
+#+BEGIN_SRC d
+}
+#+END_SRC
+
+**** bibliography                                           :bibliography:
+***** biblio struct open
+
+#+name: ao_emitters_bibliography
+#+BEGIN_SRC d
+struct Bibliography {
+#+END_SRC
+
+***** biblio
+
+#+name: ao_emitters_bibliography
+#+BEGIN_SRC d
+  public JSONValue[] _bibliography_(Bi,BJ)(
+    ref Bi biblio_unsorted_incomplete,
+    ref BJ bib_arr_json
+  )
+  in {
+    debug(asserts){
+      static assert(is(typeof(biblio_unsorted_incomplete) == string[]));
+      static assert(is(typeof(bib_arr_json)               == JSONValue[]));
+    }
+ }
+  body {
+    JSONValue[] biblio_unsorted =
+      _biblio_unsorted_complete_(biblio_unsorted_incomplete, bib_arr_json);
+    JSONValue[] biblio_sorted__ = biblio_sort(biblio_unsorted);
+    biblio_debug(biblio_sorted__);
+    debug(biblio0) {
+      writeln("---");
+      writeln("unsorted incomplete: ", biblio_unsorted_incomplete.length);
+      writeln("json:                ", bib_arr_json.length);
+      writeln("unsorted:            ", biblio_unsorted.length);
+      writeln("sorted:              ", biblio_sorted__.length);
+      int cntr;
+      int[7] x;
+      while (cntr < x.length) {
+        writeln(cntr, ": ", biblio_sorted__[cntr]["fulltitle"]);
+        cntr++;
+      }
+    }
+    return biblio_sorted__;
+  }
+#+END_SRC
+
+***** biblio unsorted complete
+
+#+name: ao_emitters_bibliography
+#+BEGIN_SRC d
+  final private JSONValue[] _biblio_unsorted_complete_(Bi,BJ)(
+    Bi     biblio_unordered,
+    ref BJ bib_arr_json
+  ) {
+    debug(asserts){
+      static assert(is(typeof(biblio_unordered) == string[]));
+      static assert(is(typeof(bib_arr_json)     == JSONValue[]));
+    }
+    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;
+  }
+#+END_SRC
+
+***** biblio sort
+
+#+name: ao_emitters_bibliography
+#+BEGIN_SRC d
+  final private JSONValue[] biblio_sort(BJ)(BJ biblio_unordered) {
+    debug(asserts){
+      static assert(is(typeof(biblio_unordered) == JSONValue[]));
+    }
+    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"]);
+        }
+      }
+    }
+    return biblio_sorted_;
+  }
+#+END_SRC
+
+***** biblio debug
+
+#+name: ao_emitters_bibliography
+#+BEGIN_SRC d
+  void biblio_debug(BJ)(BJ biblio_sorted) {
+    debug(asserts){
+      static assert(is(typeof(biblio_sorted) == JSONValue[]));
+    }
+    debug(biblio0) {
+      foreach (j; biblio_sorted) {
+        if (!empty(j["fulltitle"].str)) {
+          writeln(j["sortby_deemed_author_year_title"]);
+        }
+      }
+    }
+  }
+#+END_SRC
+
+***** biblio struct close
+
+#+name: ao_emitters_bibliography
+#+BEGIN_SRC d
+}
+#+END_SRC
+
+**** node structure metadata                     :structure:metadata:node:
+***** metadata node struct open
+
+#+name: ao_emitters_metadata
+#+BEGIN_SRC d
+struct NodeStructureMetadata {
+  int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7;
+  int obj_cite_number;
+  int[string] p_; // p_ parent_
+  auto rgx = Rgx();
+#+END_SRC
+
+***** TODO node metadata emitter
+
+#+name: ao_emitters_metadata
+#+BEGIN_SRC d
+  ObjGenericComposite node_location_emitter(Lv,Ta,N,C,P,I)(
+    Lv lev_markup_number,
+    Ta segment_anchor_tag,
+    N  obj_cite_number_,
+    C  cntr_,
+    P  ptr_,
+    I  is_
+  )
+  in {
+    debug(asserts){
+      static assert(is(typeof(lev_markup_number)  == string));
+      static assert(is(typeof(segment_anchor_tag) == string));
+      static assert(is(typeof(obj_cite_number_)   == int));
+      static assert(is(typeof(cntr_)              == int));
+      static assert(is(typeof(ptr_)               == int));
+      static assert(is(typeof(is_)                == string));
+    }
+    assert(is_ != "heading");
+    assert(to!int(obj_cite_number_) >= 0);
+  }
+  body {
+    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;
+    }
+    ObjGenericComposite comp_obj_location;
+    comp_obj_location                       = comp_obj_location.init;
+    comp_obj_location.is_a                  = is_;
+    comp_obj_location.ocn                   = obj_cite_number_;
+    comp_obj_location.segment_anchor_tag    = to!string(segment_anchor_tag);
+    comp_obj_location.parent_ocn            = p_["obj_cite_number"];
+    comp_obj_location.parent_lev_markup     = p_["lev_markup_number"];
+    debug(node) {
+      if (match(lev_markup_number, rgx.levels_numbered_headings)) {
+        writeln("x ", to!string(_node));
+      } else {
+        writeln("- ", to!string(_node));
+      }
+    }
+    assert(comp_obj_location.parent_lev_markup >= 4);
+    assert(comp_obj_location.parent_lev_markup <= 7);
+    assert(comp_obj_location.parent_ocn >= 0);
+    return comp_obj_location;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+***** TODO node metadata emitter heading, (including most segnames & their pointers)
+
+#+name: ao_emitters_metadata
+#+BEGIN_SRC d
+  ObjGenericComposite node_emitter_heading(T,L,Lm,Lc,Ta,N,C,P,LA,I,PSn)(
+    T   _text,
+    L   lev,
+    Lm  lev_markup_number,
+    Lc  lev_collapsed_number,
+    Ta  segment_anchor_tag,
+    N   obj_cite_number_,
+    C   cntr_,
+    P   ptr_,
+    LA  lv_ancestors,
+    I   is_,
+    PSn html_segnames_ptr,
+  )
+  in {
+    debug(asserts){
+      static assert(is(typeof(_text)                == string));
+      static assert(is(typeof(lev)                  == string));
+      static assert(is(typeof(lev_markup_number)    == string));
+      static assert(is(typeof(lev_collapsed_number) == string));
+      static assert(is(typeof(segment_anchor_tag)   == string));
+      static assert(is(typeof(obj_cite_number_)     == int));
+      static assert(is(typeof(cntr_)                == int));
+      static assert(is(typeof(ptr_)                 == int));
+      static assert(is(typeof(lv_ancestors)         == string[]));
+      static assert(is(typeof(is_)                  == string));
+      static assert(is(typeof(html_segnames_ptr)    == int));
+    }
+    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_))
+    );
+    if (match(lev_markup_number, rgx.levels_numbered)) {
+      if (to!int(lev_markup_number) == 0) {
+        assert(to!int(obj_cite_number_) == 1);
+      }
+    }
+  }
+  body {
+    int obj_cite_number = to!int(obj_cite_number_);
+    switch (to!int(lev_markup_number)) {
+    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:
+      break;
+    }
+    ObjGenericComposite _comp_obj_heading_;
+    _comp_obj_heading_                           = _comp_obj_heading_.init;
+    _comp_obj_heading_.use                       = "body";
+    _comp_obj_heading_.is_of                     = "para";
+    _comp_obj_heading_.is_a                      = "heading";   //                   = is_; // check whether needed, constant???
+    _comp_obj_heading_.text                      = to!string(_text).strip;
+    _comp_obj_heading_.ocn                       = obj_cite_number_;
+    _comp_obj_heading_.obj_cite_number           = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
+    _comp_obj_heading_.segment_anchor_tag        = to!string(segment_anchor_tag);
+    _comp_obj_heading_.marked_up_level           = lev;
+    _comp_obj_heading_.heading_lev_markup        = (!(lev_markup_number.empty) ? to!int(lev_markup_number) : 0);
+    _comp_obj_heading_.heading_lev_collapsed     = (!(lev_collapsed_number.empty) ? to!int(lev_collapsed_number) : 0);
+    _comp_obj_heading_.parent_ocn                = p_["obj_cite_number"];
+    _comp_obj_heading_.parent_lev_markup         = p_["lev_markup_number"];
+    _comp_obj_heading_.heading_ancestors_text    = lv_ancestors;
+    _comp_obj_heading_.ptr_doc_object            = cntr_;
+    _comp_obj_heading_.ptr_html_segnames         = ((lev_markup_number == "4") ? html_segnames_ptr : 0);
+    _comp_obj_heading_.ptr_heading               = ptr_;
+    debug(node) {
+      if (match(lev_markup_number, rgx.levels_numbered_headings)) {
+        writeln("* ", to!string(_node));
+      }
+    }
+    debug(nodeheading) {
+      if (match(lev_markup_number, rgx.levels_numbered_headings)) {
+        writeln("* ", to!string(_node));
+      }
+    }
+    assert(_comp_obj_heading_.parent_lev_markup <= 7);
+    assert(_comp_obj_heading_.parent_ocn >= 0);
+    if (match(lev_markup_number, rgx.levels_numbered_headings)) {
+      assert(_comp_obj_heading_.heading_lev_markup <= 7);
+      assert(_comp_obj_heading_.ocn >= 0);
+      if (_comp_obj_heading_.parent_lev_markup > 0) {
+        assert(_comp_obj_heading_.parent_lev_markup < _comp_obj_heading_.heading_lev_markup);
+        if (_comp_obj_heading_.ocn != 0) {
+          assert(_comp_obj_heading_.parent_ocn < _comp_obj_heading_.ocn);
+        }
+      }
+      if (_comp_obj_heading_.heading_lev_markup == 0) {
+        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A);
+      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_B) {
+        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A);
+      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_C) {
+        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_B);
+      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_D) {
+        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_C);
+      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_1) {
+        assert(_comp_obj_heading_.parent_lev_markup <= DocStructMarkupHeading.h_sect_D);
+      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_2) {
+        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_1);
+      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_3) {
+        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_2);
+      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_4) {
+        assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_3);
+      } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_5) {
+      }
+    }
+    return _comp_obj_heading_;
+  }
+  invariant() {
+  }
+#+END_SRC
+
+***** metadata node struct close
+
+#+name: ao_emitters_metadata
+#+BEGIN_SRC d
+}
+#+END_SRC
+
+*** function assertions                                        :assertions:
+**** mixin template: assertions on markup document structure :doc_structure:
+
+#+name: abs_functions_assertions
+#+BEGIN_SRC d
+auto assertions_doc_structure(O,Lv)(
+  O  an_object,
+  Lv lv
+) {
+  debug(asserts){
+    static assert(is(typeof(an_object) == string[string]));
+    static assert(is(typeof(lv)        == int[string]));
+  }
+  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;
+  }
+}
+#+END_SRC
+
+**** mixin template: assertions on blocks                         :blocks:
+
+#+name: abs_functions_assertions
+#+BEGIN_SRC d
+auto assertions_flag_types_block_status_none_or_closed(T)(T type) {
+  debug(asserts){
+    static assert(is(typeof(type) == int[string]));
+  }
+  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");
+}
+#+END_SRC
+
+* 2. Object Setter                                          :abstract:object:
+
+set abstracted objects for downstream processing
+
+** 0. ao object setter:                                   :ao_object_setter:
+
+#+BEGIN_SRC d :tangle ../src/sdp/ao_object_setter.d
+/++
+  object setter:
+  setting of sisu objects for downstream processing
+  ao_object_setter.d
++/
+template ObjectSetter() {
+  /+ structs +/
+  <<ao_structs_init>>
+}
+#+END_SRC
+
+** 1. initialize structs                                            :struct:
+*** heading attribute
+
+#+name: ao_structs_init
+#+BEGIN_SRC d
+struct HeadingAttrib {
+  string lev                            = "9";
+  int    heading_lev_markup             = 9;
+  int    heading_lev_collapsed          = 9;
+  int[]  closes_lev_collapsed           = [];
+  int[]  closes_lev_markup              = [];
+  int    array_ptr                      = 0;
+  int    heading_array_ptr_segments     = 0;
+}
+#+END_SRC
+
+*** TODO composite object
+
+#+name: ao_structs_init
+#+BEGIN_SRC d
+struct ObjGenericComposite {
+  // size_t id;
+  string                 use                          = "";
+  string                 is_of                        = "";
+  string                 is_a                         = "";
+  string                 text                         = "";
+  string                 obj_cite_number              = "";
+  string[]               anchor_tags                  = [];
+  string                 marked_up_level              = "9";
+  int[]                  closes_lev_collapsed         = [];
+  int[]                  closes_lev_markup            = [];
+  int                    indent_base                  = 0;
+  int                    indent_hang                  = 0;
+  bool                   bullet                       = false;
+  string                 syntax                       = "";
+  int                    ocn                          = 0;
+  string                 segment_anchor_tag           = "";
+  string                 segname_prev                 = "";
+  string                 segname_next                 = "";
+  int                    parent_lev_markup            = 0;
+  int                    parent_ocn                   = 0;
+  int[]                  ancestors                    = [];
+  int                    heading_lev_markup           = 9;
+  int                    heading_lev_collapsed        = 9;
+  int[]                  heading_closes_lev_collapsed = [];
+  int[]                  heading_closes_lev_markup    = [];
+  string[]               heading_ancestors_text       = [ "", "", "", "", "", "", "", "", ];
+  int                    heading_array_ptr            = 0;
+  int                    ptr_doc_object               = 0;
+  int                    ptr_html_segnames            = 0;
+  int                    ptr_heading                  = 0;
+  int                    array_ptr                    = 0;
+  int                    heading_array_ptr_segments   = 0;
+  string[]               lev4_subtoc                  = [];
+  string[string][string] node;
+  int[]                  dom_markedup                 = [ 0, 0, 0, 0, 0, 0, 0, 0,];
+  int[]                  dom_collapsed                = [ 0, 0, 0, 0, 0, 0, 0, 0,];
+}
+#+END_SRC
+
+*** The Objects: generic composite object array
+
+#+name: ao_structs_init
+#+BEGIN_SRC d
+struct TheObjects {
+  ObjGenericComposite[] oca;
+}
+#+END_SRC
diff --git a/org/ao_summary_and_debugs.org b/org/ao_summary_and_debugs.org
index c921700..2fc405e 100644
--- a/org/ao_summary_and_debugs.org
+++ b/org/ao_summary_and_debugs.org
@@ -13,8 +13,8 @@
 #+TAGS: assert(a) class(c) debug(d) mixin(m) sdp(s) tangle(T) template(t) WEB(W) noexport(n)
 
 [[./sdp.org][sdp]]  [[./][org/]]
-* 1. abstraction summary [#A]
-** 0. code structure:                                     :ao_doc_debugs:
+* 1. abstraction summary [#A]                       :summary:doc:abstraction:
+** 0. code structure:                                  :abstraction_summary:
 
 #+BEGIN_SRC d :tangle ../src/sdp/abstraction_summary.d
 template SiSUabstractionSummary() {
@@ -40,15 +40,9 @@ import
   ao_defaults,
   ao_rgx;
 import
-  std.algorithm,
   std.array,
-  std.container,
   std.exception,
-  std.getopt,
   std.stdio,
-  std.file,
-  std.path,
-  std.range,
   std.regex,
   std.string,
   std.traits,
@@ -139,8 +133,8 @@ markup.repeat_character_by_number_provided("-", 10)
 markup.repeat_character_by_number_provided("-", (doc_matters.dochead_meta["title"]["full"].length))
 markup.repeat_character_by_number_provided("-", (doc_matters.source_filename.length))
 
-* 2. abstraction debugs                                        :debug:output:
-** 0. code structure:                                     :ao_output_debugs:
+* 2. abstraction debugs                               :debug:doc:abstraction:
+** 0. code structure:                                        :ao_doc_debugs:
 
 #+BEGIN_SRC d :tangle ../src/sdp/ao_doc_debugs.d
 /++
@@ -178,9 +172,7 @@ private import
   std.array,
   std.container,
   std.exception,
-  std.getopt,
   std.json,
-  std.process,
   std.stdio,
   std.file,
   std.path,
-- 
cgit v1.2.3