/++
  document abstraction:
  abstraction of sisu markup for downstream processing
  metadoc_from_src.d
+/
module doc_reform.meta.metadoc_from_src;
template DocReformDocAbstraction() {
                                                                                /+ ↓ abstraction imports +/
  import doc_reform.meta;
  import
    std.algorithm,
    std.container,
    std.file,
    std.json,
    std.path;
  import
    doc_reform.meta.defaults,
    doc_reform.meta.object_setter,
    doc_reform.meta.rgx;
                                                                                /+ ↓ abstraction mixins +/
  mixin ObjectSetter;
  mixin InternalMarkup;
  mixin DocReformRgxInit;
                                                                                /+ ↓ abstraction struct init +/
  /+ initialize +/
  ObjGenericComposite[] 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 anchor_tag_;
  string[string] tag_in_seg;
  string lev_anchor_tag;
  string[string][string] tag_assoc;
  string[] lv0_to_3_tags;
  /+ 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 Status { off, on, }
  enum OCNstatus { on, off, bkidx, closing, reset, }
  enum OCN_off_block_status { off, on }
  enum OCNtype { ocn, non, bkidx, }
  /+ 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;
  bool reset_note_numbers=true;
  int[string] line_occur;
  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";
  static auto obj_im = ObjInlineMarkup();
  static auto obj_att = ObjAttributes();
  /+ ocn +/
  struct OCNset {
    int digit;
    int object_number;
    bool off;
    string identifier;
    int bkidx;
    int type;
  }
  OCNset obj_cite_digits;
  int obj_cite_digit_, obj_cite_digit_off, obj_cite_digit_bkidx, obj_cite_digit_type;
  auto object_citation_number = OCNemitter();
  int[] dom_structure_markedup_tags_status         = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
  int[] dom_structure_markedup_tags_status_buffer  = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
  int[] dom_structure_collapsed_tags_status        = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
  int[] dom_structure_collapsed_tags_status_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
  enum DomTags { none, open, close, close_and_open, open_still, }
  pure ObjGenericComposite obj_heading_ancestors()(
    ObjGenericComposite  obj,
    string[]             lv_ancestors_txt,
  ) {
    switch (obj.metainfo.heading_lev_markup) {
    case 0:
      lv_ancestors_txt[0] = obj.text.to!string;
      foreach(k; 1..8) {
        lv_ancestors_txt[k] = "";
      }
      goto default;
    case 1:
      lv_ancestors_txt[1] = obj.text.to!string;
      foreach(k; 2..8) {
        lv_ancestors_txt[k] = "";
      }
      goto default;
    case 2:
      lv_ancestors_txt[2] = obj.text.to!string;
      foreach(k; 3..8) {
        lv_ancestors_txt[k] = "";
      }
      goto default;
    case 3:
      lv_ancestors_txt[3] = obj.text.to!string;
      foreach(k; 4..8) {
        lv_ancestors_txt[k] = "";
      }
      goto default;
    case 4:
      lv_ancestors_txt[4] = obj.text.to!string;
      foreach(k; 5..8) {
        lv_ancestors_txt[k] = "";
      }
      goto default;
    case 5:
      lv_ancestors_txt[5] = obj.text.to!string;
      foreach(k; 6..8) {
        lv_ancestors_txt[k] = "";
      }
      goto default;
    case 6:
      lv_ancestors_txt[6] = obj.text.to!string;
      lv_ancestors_txt[7] = "";
      goto default;
    case 7:
      lv_ancestors_txt[7] = obj.text.to!string;
      goto default;
    default:
      obj.tags.heading_ancestors_text = lv_ancestors_txt.dup;
    }
    return obj;
  }
  pure ObjGenericComposite obj_dom_structure_set_markup_tags()(
    ObjGenericComposite  obj,
    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_magic_numbers) {
      writeln("marked up: ", lev, ": ", dom);
    }
    obj.metainfo.dom_structure_markedup_tags_status = dom.dup;
    return obj;
  }
  pure ObjGenericComposite obj_dom_set_collapsed_tags()(
    ObjGenericComposite  obj,
    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_magic_numbers) {
      writeln("collapsed: ", lev, ": ", dom);
    }
    obj.metainfo.dom_structure_collapsed_tags_status = dom.dup;
    return obj;
  }
  static auto ocn_emit(int ocn_status_flag) {
    return object_citation_number.ocn_emitter(ocn_status_flag);
  }
  static auto inline_markup_faces(L)(L line) {
    static auto rgx = Rgx();
    static auto mkup = InlineMarkup();
    line = replaceAll!(m => mkup.quote_o ~ m[1] ~ mkup.quote_c)(line, rgx.within_quotes);
    line = replaceAll!(m => mkup.mono ~ mkup.ff_o ~ m["text"] ~ mkup.ff_c ~ mkup.mono)(line, rgx.inline_mark_mono);
    line = replaceAll!(m => mkup.cite ~ mkup.ff_o ~ m["text"] ~ mkup.ff_c ~ mkup.cite)(line, rgx.inline_mark_cite);
    foreach (regx; [rgx.inline_mark_emphasis, rgx.inline_mark_bold, rgx.inline_mark_underscore, rgx.inline_mark_italics, rgx.inline_mark_superscript, rgx.inline_mark_subscript, rgx.inline_mark_strike, rgx.inline_mark_insert]) {
      line = replaceAll!(m => m["mark"] ~ mkup.ff_o ~ m["text"] ~ mkup.ff_c ~ m["mark"])(line, regx);
    }
    return line;
  }
  static string links_and_images()(string obj_txt) {
    static auto rgx = Rgx();
    static auto mkup = InlineMarkup();
    if (obj_txt.match(rgx.smid_inline_url_generic)) {
      if (
        obj_txt.match(rgx.smid_inline_link_endnote_url_helper)
        || obj_txt.match(rgx.smid_inline_link_endnote_url_helper_punctuated)
      ) {
        obj_txt = replaceAll!(m => format("%s%s%s%s%s%s%s %s%s%s%s%s%s %s%s",
          mkup.lnk_o, m["content"].strip, mkup.lnk_c,
          mkup.url_o, m["link"], mkup.url_c,
          mkup.en_a_o,
          mkup.lnk_o, m["link"].strip, mkup.lnk_c,
          mkup.url_o, m["link"], mkup.url_c,
          mkup.en_a_c,
          m[3]
        ))(obj_txt, rgx.smid_inline_link_endnote_url_helper_punctuated);
        obj_txt = replaceAll!(m => format("%s%s%s%s%s%s%s %s%s%s%s%s%s %s",
          mkup.lnk_o, m["content"].strip, mkup.lnk_c,
          mkup.url_o, m["link"], mkup.url_c,
          mkup.en_a_o,
          mkup.lnk_o, m["link"].strip, mkup.lnk_c,
          mkup.url_o, m["link"], mkup.url_c,
          mkup.en_a_c
        ))(obj_txt, rgx.smid_inline_link_endnote_url_helper);
    } else {
        obj_txt = replaceAll!(m => format("%s%s%s%s%s%s%s",
          m["pre"],
          mkup.lnk_o, m["content"].strip, mkup.lnk_c,
          mkup.url_o, m["link"], mkup.url_c
        ))(obj_txt, rgx.smid_inline_link_markup_regular);
      }
        obj_txt = replaceAll!(m => format("%s%s%s%s%s%s%s",
          m["pre"],
          mkup.lnk_o, m["link"].strip, mkup.lnk_c,
          mkup.url_o, m["link"], mkup.url_c
        ))(obj_txt, rgx.smid_inline_link_naked_url); //
    }
    return obj_txt;
  }
  /+ book index variables +/
  string book_idx_tmp;
  string[][string][string] bookindex_unordered_hashes;
  /+ 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();
  enum sObj { content, anchor_tag, notes_reg, notes_star, links, image_no_dimensions }
  string[string][string] inline_para_link_anchor()(
    string[string]          an_object,
    string[string]          tag_in_seg,
    string[string][string]  tag_assoc
  ) {
    static auto rgx = Rgx();
    if (auto m = an_object["substantive"].match(rgx.inline_link_anchor)) {
      if (m.captures[1] !in tag_assoc) {
        tag_assoc[(m.captures[1])]["seg_lv4"] = tag_in_seg["seg_lv4"];
        tag_assoc[(m.captures[1])]["seg_lv1_to_4"] = tag_in_seg["seg_lv1_to_4"];
      } else {
        writeln("a tag named  already exists, check text line\n    ", an_object["substantive"]);
      }
    }
    return tag_assoc;
  }
                                                                                /+ ↓ abstract marked up document +/
  auto DocReformDocAbstraction(CMM,Opt,Mf)(
    char[][]           markup_sourcefile_content,
    CMM                conf_make_meta,
    Opt                opt_action,
    Mf                 manifest_matter,
    bool               _new_doc
  ) {
    static auto rgx = Rgx();
                                                                                /+ ↓ abstraction init +/
    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);
      previous_length=0;
      reset_note_numbers=true;
    }
    mixin DocReformRgxInitFlags;
    mixin DocReformNode;
    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,
    ];
    uint[string] dochas = [
      "inline_links" : 0,
      "inline_notes" : 0,
      "inline_notes_star" : 0,
      "codeblock" : 0,
      "table" : 0,
      "block" : 0,
      "group" : 0,
      "poem" : 0,
      "quote" : 0,
      "images" : 0,
    ];
    auto obj_type_status = flags_type_init;
    string[string] object_number_poem = [
      "start" : "",
      "end"   : ""
    ];
    string[] lv_ancestors_txt = [ "", "", "", "", "", "", "", "", ];
    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)"
    ];
    Regex!char[string] 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_.metainfo.is_of_part                          = "frontmatter";
    comp_obj_heading_.metainfo.is_of_section                       = "toc";
    comp_obj_heading_.metainfo.is_of_type                          = "para";
    comp_obj_heading_.metainfo.is_a                                = "heading";
    comp_obj_heading_.text                                         = "Table of Contents";
    comp_obj_heading_.metainfo.ocn                                 = 0;
    comp_obj_heading_.metainfo.identifier                          = "";
    comp_obj_heading_.metainfo.dummy_heading                       = false;
    comp_obj_heading_.metainfo.object_number_off                   = true;
    comp_obj_heading_.metainfo.object_number_type                  = 0;
    comp_obj_heading_.tags.segment_anchor_tag_epub                 = "toc";
    comp_obj_heading_.tags.anchor_tag_html                         = comp_obj_heading_.tags.segment_anchor_tag_epub;
    comp_obj_heading_.tags.in_segment_html                         = comp_obj_heading_.tags.anchor_tag_html;
    comp_obj_heading_.metainfo.heading_lev_markup                  = 4;
    comp_obj_heading_.metainfo.heading_lev_collapsed               = 1;
    comp_obj_heading_.metainfo.parent_ocn                          = 1;
    comp_obj_heading_.metainfo.parent_lev_markup                   = 0;
    comp_obj_heading_.ptr.html_segnames                            = html_segnames_ptr;
    comp_obj_heading_.tags.anchor_tags                             = ["toc"];
    comp_obj_heading_.metainfo.dom_structure_markedup_tags_status  = [ 1, 1, 0, 0, 1, 0, 0, 0];
    comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 1, 0, 0, 0, 0, 0];
    tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
    tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
    auto toc_head                                                  = comp_obj_heading_;
    html_segnames_ptr_cntr++;
    the_table_of_contents_section = [toc_head];
    static auto mkup = InlineMarkup();
    static auto munge = ObjInlineMarkupMunge();
    auto note_section = NotesSection();
    auto bookindex_extract_hash = BookIndexNuggetHash();
    string[][string] lev4_subtoc;
    string[][string] segnames = ["html": ["toc"], "epub": ["toc"]];
    int cnt1 = 1; int cnt2 = 1; int cnt3 = 1;
                                                                                /+ abstraction init ↑ +/
    enum Substitute { match, markup, }
    debug (substitutions) {
      writeln(__LINE__, ":", __FILE__, ": DEBUG substitutions:");
      if (!(conf_make_meta.make.headings.empty)) {
        writeln(conf_make_meta.make.headings);
      }
      if (conf_make_meta.make.substitute) {
        foreach(substitution_pair; conf_make_meta.make.substitute) {
           writeln("regex to match:       ", substitution_pair[Substitute.match]);
           writeln("substitution to make: ", substitution_pair[Substitute.markup]);
        }
      }
      if (conf_make_meta.make.bold) {
        writeln("regex to match:       ", conf_make_meta.make.bold[Substitute.match]);
        writeln("substitution to make: ", conf_make_meta.make.bold[Substitute.markup]);
      }
      if (conf_make_meta.make.emphasis) {
        writeln("regex to match:       ", conf_make_meta.make.emphasis[Substitute.match]);
        writeln("substitution to make: ", conf_make_meta.make.emphasis[Substitute.markup]);
      }
      if (conf_make_meta.make.italics) {
        writeln("regex to match:       ", conf_make_meta.make.italics[Substitute.match]);
        writeln("substitution to make: ", conf_make_meta.make.italics[Substitute.markup]);
      }
    }
                                                                                /+ ↓ ↻ loop markup document/text line by line +/
    srcDocLoop:
    foreach (line; markup_sourcefile_content) {                                 /+ ↓ markup document/text line by line +/
                                                                                // "line" variable can be empty but should never be null
      /+ scope +/
      scope(exit) {
      }
      scope(failure) {
        stderr.writefln(
          "%s\n%s\n%s:%s failed here:\n  line: %s",
          __MODULE__, __FUNCTION__,
          __FILE__, __LINE__,
          line,
        );
      }
      debug(source) {
        writeln(line);
      }
      debug(srclines) {
        if (!line.empty) {
          writefln(
            "* %s",
            line
          );
        }
      }
      if (!line.empty) {
        obj_type_status = line._check_ocn_status_(obj_type_status);
      }
      if (obj_type_status["code"] == TriState.on) {
        /+ block object: code +/
        line.flow_txt_block_code(an_object, obj_type_status);
        continue;
      } else if (!matchFirst(line, rgx.skip_from_regular_parse)) {              /+ object other than "code block" object +/
                                                                                /+ (includes regular text paragraph, headings & blocks other than code) +/
                                                                                /+ heading, glossary, blurb, poem, group, block, quote, table +/
        line = line.inline_markup_faces; // by text line (rather than by text object), linebreaks in para problematic
        if ((line.matchFirst(rgx.heading_biblio)
          && obj_type_status["para"]  != State.on
          && obj_type_status["group"] != State.on
          && obj_type_status["block"] != State.on
          && obj_type_status["poem"]  != State.on
          && obj_type_status["table"] != State.on
          && obj_type_status["quote"] != State.on)
        || (obj_type_status["biblio_section"] == State.on
        && (!(line.matchFirst(rgx.heading_blurb_glossary)))
        && (!(line.matchFirst(rgx.heading)))
        && (!(line.matchFirst(rgx.comment))))) {
          /+ within section (block object): biblio +/
          obj_type_status["glossary_section"] = State.off;
          obj_type_status["biblio_section"]   = State.on;
          obj_type_status["blurb_section"]    = State.off;
          if (opt_action.backmatter && opt_action.section_biblio) {
            line.flow_txt_block_biblio(obj_type_status, bib_entry, biblio_entry_str_json, biblio_arr_json);
            debug(bibliobuild) {
              writeln("-  ", biblio_entry_str_json);
              writeln("-> ", biblio_arr_json.length);
            }
          }
          continue;
        } else if ((line.matchFirst(rgx.heading_glossary)
          && obj_type_status["para"]  != State.on
          && obj_type_status["group"] != State.on
          && obj_type_status["block"] != State.on
          && obj_type_status["poem"]  != State.on
          && obj_type_status["table"] != State.on
          && obj_type_status["quote"] != State.on)
        || (obj_type_status["glossary_section"] == State.on
        && (!(line.matchFirst(rgx.heading_biblio_blurb)))
        && (!(line.matchFirst(rgx.heading)))
        && (!(line.matchFirst(rgx.comment))))) {
          /+ within section (block object): glossary +/
          debug(glossary) {
            writeln(__LINE__);
            writeln(line);
          }
          obj_type_status["glossary_section"] = State.on;
          obj_type_status["biblio_section"]   = State.off;
          obj_type_status["blurb_section"]    = State.off;
          if (opt_action.backmatter && opt_action.section_glossary) {
            indent=[
              "hang_position" : 0,
              "base_position" : 0,
            ];
            bullet = false;
            obj_type_status["para"] = State.on;
            line_occur["para"] = State.off;
            an_object_key="glossary_nugget"; //
            if (line.matchFirst(rgx.heading_glossary)) {
              {
                comp_obj_heading_                                = comp_obj_heading_.init;
                comp_obj_heading_.metainfo.is_of_part            = "backmatter";
                comp_obj_heading_.metainfo.is_of_section         = "glossary";
                comp_obj_heading_.metainfo.is_of_type            = "para";
                comp_obj_heading_.metainfo.is_a                  = "heading";
                comp_obj_heading_.text                           = "Glossary";
                comp_obj_heading_.metainfo.ocn                   = 0;
                comp_obj_heading_.metainfo.identifier            = "";
                comp_obj_heading_.metainfo.dummy_heading         = false;
                comp_obj_heading_.metainfo.object_number_off     = true;
                comp_obj_heading_.metainfo.object_number_type    = 0;
                comp_obj_heading_.tags.segment_anchor_tag_epub   = "_part_glossary";
                comp_obj_heading_.tags.anchor_tag_html           = comp_obj_heading_.tags.segment_anchor_tag_epub;
                comp_obj_heading_.tags.in_segment_html           = "glossary";
                comp_obj_heading_.metainfo.heading_lev_markup    = 1;
                comp_obj_heading_.metainfo.heading_lev_collapsed = 1;
                comp_obj_heading_.metainfo.parent_ocn            = 1;
                comp_obj_heading_.metainfo.parent_lev_markup     = 0;
                comp_obj_heading_.metainfo.dom_structure_markedup_tags_status  = [ 1, 1, 0, 0, 0, 0, 0, 0];
                comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0];
                the_glossary_section                             ~= comp_obj_heading_;
                tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
                tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
              }
              {
                comp_obj_heading_                                = comp_obj_heading_.init;
                comp_obj_heading_.metainfo.is_of_part            = "backmatter";
                comp_obj_heading_.metainfo.is_of_section         = "glossary";
                comp_obj_heading_.metainfo.is_of_type            = "para";
                comp_obj_heading_.metainfo.is_a                  = "heading";
                comp_obj_heading_.text                           = "Glossary";
                comp_obj_heading_.metainfo.ocn                   = 0;
                comp_obj_heading_.metainfo.identifier            = "";
                comp_obj_heading_.metainfo.dummy_heading         = true;
                comp_obj_heading_.metainfo.object_number_off     = true;
                comp_obj_heading_.metainfo.object_number_type    = 0;
                comp_obj_heading_.tags.segment_anchor_tag_epub   = "glossary";
                comp_obj_heading_.tags.anchor_tag_html           = comp_obj_heading_.tags.segment_anchor_tag_epub;
                comp_obj_heading_.tags.in_segment_html           = comp_obj_heading_.tags.anchor_tag_html;
                comp_obj_heading_.metainfo.heading_lev_markup    = 4;
                comp_obj_heading_.metainfo.heading_lev_collapsed = 2;
                comp_obj_heading_.metainfo.parent_ocn            = 1;
                comp_obj_heading_.metainfo.parent_lev_markup     = 0;
                comp_obj_heading_.metainfo.dom_structure_markedup_tags_status  = [ 1, 1, 0, 0, 1, 0, 0, 0];
                comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 1, 0, 0, 0, 0, 0];
                comp_obj_heading_.tags.anchor_tags               = ["glossary"];
                the_glossary_section                             ~= comp_obj_heading_;
                tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
                tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
              }
            } else {
              an_object = line.flow_para_match_(an_object, an_object_key, indent, bullet, obj_type_status, line_occur);
              comp_obj_para                               = comp_obj_para.init;
              comp_obj_para.metainfo.is_of_part           = "backmatter";
              comp_obj_para.metainfo.is_of_section        = "glossary";
              comp_obj_para.metainfo.is_of_type           = "para";
              comp_obj_para.metainfo.is_a                 = "glossary";
              comp_obj_para.text                          = line.to!string.strip;
              comp_obj_para.metainfo.ocn                  = 0;
              comp_obj_para.metainfo.identifier           = "";
              comp_obj_para.metainfo.object_number_off    = true;
              comp_obj_para.metainfo.object_number_type   = 0;
              comp_obj_para.attrib.indent_hang            = indent["hang_position"];
              comp_obj_para.attrib.indent_base            = indent["base_position"];
              comp_obj_para.attrib.bullet                 = bullet;
              the_glossary_section                        ~= comp_obj_para;
            }
            obj_type_status["ocn_status"] = OCNstatus.on;
          }
          continue;
        } else if ((line.matchFirst(rgx.heading_blurb)
          && obj_type_status["para"]  != State.on
          && obj_type_status["group"] != State.on
          && obj_type_status["block"] != State.on
          && obj_type_status["poem"]  != State.on
          && obj_type_status["table"] != State.on
          && obj_type_status["quote"] != State.on)
        || (obj_type_status["blurb_section"] == State.on
        && (!(line.matchFirst(rgx.heading_biblio_glossary)))
        && (!(line.matchFirst(rgx.heading)))
        && (!(line.matchFirst(rgx.comment))))) {
          /+ within section (block object): blurb +/
          debug(blurb) {
            writeln(__LINE__);
            writeln(line);
          }
          obj_type_status["glossary_section"] = State.off;
          obj_type_status["biblio_section"]   = State.off;
          obj_type_status["blurb_section"]    = State.on;
          if (opt_action.backmatter && opt_action.section_blurb) {
            indent=[
              "hang_position" : 0,
              "base_position" : 0,
            ];
            bullet = false;
            if (auto m = line.matchFirst(rgx.para_indent)) {
              debug(paraindent) {
                writeln(line);
              }
              indent["hang_position"] = (m["indent"]).to!int;
              indent["base_position"] = (m["indent"]).to!int;
            } else if (line.matchFirst(rgx.para_bullet)) {
              debug(parabullet) {
                writeln(line);
              }
              bullet = true;
            } else if (auto m = line.matchFirst(rgx.para_indent_hang)) {
              debug(paraindenthang) {
                writeln(line);
              }
              indent=[
                "hang_position" : (m["hang"]).to!int,
                "base_position" : (m["indent"]).to!int,
              ];
            } else if (auto m = line.matchFirst(rgx.para_bullet_indent)) {
              debug(parabulletindent) {
                writeln(line);
              }
              indent=[
                "hang_position" : (m["indent"]).to!int,
                "base_position" : (m["indent"]).to!int,
              ];
              bullet = true;
            }
            obj_type_status["para"] = State.on;
            line_occur["para"] = State.off;
            an_object_key="blurb_nugget";
            if (line.matchFirst(rgx.heading_blurb)) {
              {
                comp_obj_heading_                                              = comp_obj_heading_.init;
                comp_obj_heading_.metainfo.is_of_part                          = "backmatter";
                comp_obj_heading_.metainfo.is_of_section                       = "blurb";
                comp_obj_heading_.metainfo.is_of_type                          = "para";
                comp_obj_heading_.metainfo.is_a                                = "heading";
                comp_obj_heading_.text                                         = "Blurb";
                comp_obj_heading_.metainfo.ocn                                 = 0;
                comp_obj_heading_.metainfo.identifier                          = "";
                comp_obj_heading_.metainfo.dummy_heading                       = false;
                comp_obj_heading_.metainfo.object_number_off                   = true;
                comp_obj_heading_.metainfo.object_number_type                  = 0;
                comp_obj_heading_.tags.segment_anchor_tag_epub                 = "_part_blurb";
                comp_obj_heading_.tags.anchor_tag_html                         = comp_obj_heading_.tags.segment_anchor_tag_epub;
                comp_obj_heading_.tags.in_segment_html                         = "blurb";
                comp_obj_heading_.metainfo.heading_lev_markup                  = 1;
                comp_obj_heading_.metainfo.heading_lev_collapsed               = 1;
                comp_obj_heading_.metainfo.parent_ocn                          = 1;
                comp_obj_heading_.metainfo.parent_lev_markup                   = 0;
                comp_obj_heading_.metainfo.dom_structure_markedup_tags_status  = [ 1, 1, 0, 0, 0, 0, 0, 0];
                comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0];
                the_blurb_section                                              ~= comp_obj_heading_;
                tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
                tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
              }
              {
                comp_obj_heading_                                              = comp_obj_heading_.init;
                comp_obj_heading_.metainfo.is_of_part                          = "backmatter";
                comp_obj_heading_.metainfo.is_of_section                       = "blurb";
                comp_obj_heading_.metainfo.is_of_type                          = "para";
                comp_obj_heading_.metainfo.is_a                                = "heading";
                comp_obj_heading_.text                                         = "Blurb";
                comp_obj_heading_.metainfo.ocn                                 = 0;
                comp_obj_heading_.metainfo.identifier                          = "";
                comp_obj_heading_.metainfo.dummy_heading                       = true;
                comp_obj_heading_.metainfo.object_number_off                   = true;
                comp_obj_heading_.metainfo.object_number_type                  = 0;
                comp_obj_heading_.tags.segment_anchor_tag_epub                 = "blurb";
                comp_obj_heading_.tags.anchor_tag_html                         = comp_obj_heading_.tags.segment_anchor_tag_epub;
                comp_obj_heading_.tags.in_segment_html                         = comp_obj_heading_.tags.anchor_tag_html;
                comp_obj_heading_.metainfo.heading_lev_markup                  = 4;
                comp_obj_heading_.metainfo.heading_lev_collapsed               = 2;
                comp_obj_heading_.metainfo.parent_ocn                          = 1;
                comp_obj_heading_.metainfo.parent_lev_markup                   = 0;
                comp_obj_heading_.tags.anchor_tags                             = ["blurb"];
                comp_obj_heading_.metainfo.dom_structure_markedup_tags_status  = [ 1, 1, 0, 0, 1, 0, 0, 0];
                comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 1, 0, 0, 0, 0, 0];
                the_blurb_section                                              ~= comp_obj_heading_;
                tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
                tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
              }
            } else if (line.matchFirst(rgx.heading)
            && (opt_action.backmatter && opt_action.section_blurb)) {
              comp_obj_heading_                                              = comp_obj_heading_.init;
              comp_obj_heading_.metainfo.is_of_part                          = "backmatter";
              comp_obj_heading_.metainfo.is_of_section                       = "blurb";
              comp_obj_heading_.metainfo.is_of_type                          = "para";
              comp_obj_heading_.metainfo.is_a                                = "heading";
              comp_obj_heading_.text                                         = line.to!string;
              comp_obj_heading_.metainfo.ocn                                 = 0;
              comp_obj_heading_.metainfo.identifier                          = "";
              comp_obj_heading_.metainfo.dummy_heading                       = false;
              comp_obj_heading_.metainfo.object_number_off                   = true;
              comp_obj_heading_.metainfo.object_number_type                  = 0;
              comp_obj_heading_.tags.segment_anchor_tag_epub                 = "blurb";
              comp_obj_heading_.tags.anchor_tag_html                         = comp_obj_heading_.tags.segment_anchor_tag_epub;
              comp_obj_heading_.tags.in_segment_html                         = comp_obj_heading_.tags.anchor_tag_html;
              comp_obj_heading_.metainfo.heading_lev_markup                  = an_object["lev_markup_number"].to!int;    // make int, remove need to conv
              comp_obj_heading_.metainfo.heading_lev_collapsed               = an_object["lev_collapsed_number"].to!int; // make int, remove need to conv
              comp_obj_heading_.metainfo.parent_ocn                          = 1;
              comp_obj_heading_.metainfo.parent_lev_markup                   = 0;
              the_blurb_section                                              ~= comp_obj_heading_;
              tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
              tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
            } else {
              an_object = line.flow_para_match_(an_object, an_object_key, indent, bullet, obj_type_status, line_occur);
              comp_obj_para                               = comp_obj_para.init;
              comp_obj_para.metainfo.is_of_part           = "backmatter";
              comp_obj_para.metainfo.is_of_section        = "blurb";
              comp_obj_para.metainfo.is_of_type           = "para";
              comp_obj_para.metainfo.is_a                 = "blurb";
              comp_obj_para.text                          = links_and_images(line.to!string.strip).replaceFirst(rgx.para_attribs, "");
              comp_obj_para.metainfo.ocn                  = 0;
              comp_obj_para.metainfo.identifier           = "";
              comp_obj_para.metainfo.object_number_off    = true;
              comp_obj_para.metainfo.object_number_type   = 0;
              comp_obj_para.attrib.indent_hang            = indent["hang_position"];
              comp_obj_para.attrib.indent_base            = indent["base_position"];
              comp_obj_para.has.inline_links              = true;
              comp_obj_para.attrib.bullet                 = bullet;
              the_blurb_section                           ~= comp_obj_para;
            }
            obj_type_status["ocn_status"] = OCNstatus.on;
          }
          continue;
        } else if (obj_type_status["quote"] == TriState.on) {                          /+ within block object: quote +/
          line = line
            ._doc_header_and_make_substitutions_(conf_make_meta)
            ._doc_header_and_make_substitutions_fontface_(conf_make_meta);
          an_object = line.flow_txt_block_quote(an_object, obj_type_status);
          continue;
        /+ within block object: group +/
        } else if (obj_type_status["group"] == TriState.on) {                          /+ within block object: group +/
          line = line
            ._doc_header_and_make_substitutions_(conf_make_meta)
            ._doc_header_and_make_substitutions_fontface_(conf_make_meta)
            .replaceAll(rgx.para_delimiter, mkup.br_paragraph ~ "$1");
          an_object = line.flow_txt_block_group(an_object, obj_type_status);
          continue;
        } else if (obj_type_status["block"] == TriState.on) {                          /+ within block object: block +/
          line = line
            ._doc_header_and_make_substitutions_(conf_make_meta)
            ._doc_header_and_make_substitutions_fontface_(conf_make_meta);
          if (auto m = line.match(rgx.spaces_keep)) {
            line = line
              .replaceAll(rgx.spaces_keep, (m.captures[1]).translate([ ' ' : mkup.nbsp ]));
          }
          an_object = line.flow_txt_block_block(an_object, obj_type_status);
          continue;
        } else if (obj_type_status["poem"] == TriState.on) {                           /+ within block object: poem +/
          an_object = line.flow_txt_block_poem(an_object, obj_type_status, cntr, object_number_poem, conf_make_meta, tag_in_seg);
          continue;
        } else if (obj_type_status["table"] == TriState.on) {                          /+ within block object: table +/
          an_object = line.flow_txt_block_table(an_object, obj_type_status, conf_make_meta);
          continue;
        } else {                                                                /+ not within a block group +/
          assert(
            (obj_type_status["blocks"] == TriState.off)
            || (obj_type_status["blocks"] == TriState.closing),
            "block status: none or closed"
          );
          assertions_flag_types_block_status_none_or_closed(obj_type_status);
          if (line.matchFirst(rgx.block_open)) {
            if (line.matchFirst(rgx.block_poem_open)) {                                    /+ poem to verse exceptions! +/
              object_reset(an_object);
              processing.remove("verse");
              object_number_poem["start"] = obj_cite_digits.object_number.to!string;
            }
            line.flow_txt_block_start(obj_type_status, dochas, object_number_poem);
            continue;
          } else if (!line.empty) {                                             /+ line not empty +/
                                                                                /+ non blocks (headings, paragraphs) & closed blocks +/
            assert(
              !line.empty,
              "line tested, line not empty surely:\n  \"" ~ line ~ "\""
            );
            assert(
              (obj_type_status["blocks"] == TriState.off)
              || (obj_type_status["blocks"] == TriState.closing),
              "code block status: none or closed"
            );
            if (obj_type_status["blocks"] == TriState.closing) {
              debug(check) {
                writeln(__LINE__);
                writeln(line);
              }
              assert(
                line.matchFirst(rgx.book_index)
                || line.matchFirst(rgx.book_index_open)
                || obj_type_status["book_index"] == State.on,
                "\nblocks closed, unless followed by book index, non-matching line:\n  \""
                ~ line ~ "\""
              );
            }
            if (line.matchFirst(rgx.book_index)
            || line.matchFirst(rgx.book_index_open)
            || obj_type_status["book_index"] == State.on )  {                              /+ book_index +/
              an_object = line.flow_book_index_(an_object, book_idx_tmp, obj_type_status, opt_action);
            } else {                                                                       /+ not book_index +/
              an_object_key="body_nugget";
              if (auto m = line.matchFirst(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.metainfo.is_of_part    = "comment"; // breaks flow
                comp_obj_comment.metainfo.is_of_section = "comment"; // breaks flow
                comp_obj_comment.metainfo.is_of_type    = "comment";
                comp_obj_comment.metainfo.is_a          = "comment";
                comp_obj_comment.text                   = an_object[an_object_key].strip;
                the_document_body_section               ~= comp_obj_comment;
                flow_common_reset_(line_occur, an_object, obj_type_status);
                processing.remove("verse");
                ++cntr;
              } else if (((line_occur["para"] == State.off)
              && (line_occur["heading"] == State.off))
              && ((obj_type_status["para"] == State.off)
              && (obj_type_status["heading"] == State.off))) {                             /+ heading or para but neither flag nor line exists +/
                if ((conf_make_meta.make.headings.length > 2)
                && (obj_type_status["make_headings"] == State.off)) {                      /+ heading found +/
                  heading_match_str = line.flow_heading_found_(heading_match_str, conf_make_meta.make.headings, heading_match_rgx, obj_type_status);
                }
                if ((obj_type_status["make_headings"] == State.on)
                && ((line_occur["para"] == State.off)
                && (line_occur["heading"] == State.off))
                && ((obj_type_status["para"] == State.off)
                && (obj_type_status["heading"] == State.off))) {                           /+ heading make set +/
                  line = line.flow_heading_make_set_(line_occur, heading_match_rgx, obj_type_status);
                }
                /+ 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?)
                +/
                if (line.matchFirst(rgx.heading)) {                                        /+ heading match +/
                  line = line._doc_header_and_make_substitutions_(conf_make_meta);
                  an_object = line.flow_heading_matched_(an_object, line_occur, an_object_key, lv, collapsed_lev, obj_type_status, conf_make_meta);
                } else if (line_occur["para"] == State.off) {                              /+ para match +/
                  an_object_key="body_nugget";
                  line = line
                    ._doc_header_and_make_substitutions_(conf_make_meta)
                    ._doc_header_and_make_substitutions_fontface_(conf_make_meta);
                  an_object = line.flow_para_match_(an_object, an_object_key, indent, bullet, obj_type_status, line_occur);
                }
              } else if (line_occur["heading"] > State.off) {                              /+ heading +/
                debug(heading) {
                  writeln(line);
                }
                an_object[an_object_key] ~= line ~= "\n";
                ++line_occur["heading"];
              } else if (line_occur["para"] > State.off) {                                 /+ paragraph +/
                debug(para) {
                  writeln(an_object_key, "-> ", line);
                }
                line = line
                  ._doc_header_and_make_substitutions_(conf_make_meta)
                  ._doc_header_and_make_substitutions_fontface_(conf_make_meta);
                an_object[an_object_key] ~= " " ~ line;
                ++line_occur["para"];
              }
            }
          } else if (obj_type_status["blocks"] == TriState.closing) {           /+ line empty, with blocks flag +/
            an_object = line.flow_block_flag_line_empty_(
              an_object,
              bookindex_extract_hash,
              the_document_body_section,
              bookindex_unordered_hashes,
              obj_cite_digits,
              comp_obj_heading,
              cntr,
              obj_type_status,
              object_number_poem,
              conf_make_meta,
              tag_in_seg,
            );
          } else {                                                              /+ line.empty, post contents, empty variables: +/
            assert(
              line.empty,
              "\nline should be empty:\n  \""
              ~ line ~ "\""
            );
            assert(
              (obj_type_status["blocks"] == State.off),
              "code block status: none"
            );
            if (_new_doc) {
              tag_assoc = tag_assoc.init;
              lv0_to_3_tags = lv0_to_3_tags.init;
              tag_in_seg = tag_in_seg.init;
            }
            if ((obj_type_status["heading"] == State.on)
            && (line_occur["heading"] > State.off)) {                                      /+ heading object (current line empty) +/
              obj_cite_digits = (an_object["lev_markup_number"].to!int == 0)
              ? ocn_emit(OCNstatus.reset)
              : ocn_emit(obj_type_status["ocn_status"]);
              an_object["is"] = "heading";
              an_object_key="body_nugget";
              auto substantive_object_and_anchor_tags_tuple
                = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, ((_new_doc) ? Yes._new_doc : No._new_doc));
              an_object["substantive"] = substantive_object_and_anchor_tags_tuple[sObj.content];
              anchor_tag = substantive_object_and_anchor_tags_tuple[sObj.anchor_tag];
              if (_new_doc) {
                cnt1 = 1;
                cnt2 = 1;
                cnt3 = 1;
                _new_doc = false;
              }
              if (
                an_object["lev_markup_number"].to!int == 4
                && (!(anchor_tag.empty)
                || (lv0_to_3_tags.length > 0))
              ) {
                tag_in_seg["seg_lv4"] = anchor_tag;
                tag_in_seg["seg_lv1_to_4"] = anchor_tag;
                lev_anchor_tag = anchor_tag;
                tag_assoc[anchor_tag]["seg_lv4"] = tag_in_seg["seg_lv4"];
                tag_assoc[anchor_tag]["seg_lv1_to_4"] = tag_in_seg["seg_lv1_to_4"];
                if (lv0_to_3_tags.length > 0) { /+ names used for html markup segments 1 to 4 (rather than epub which has separate segments for A to D) +/
                  foreach (lv0_to_lv3_html_tag; lv0_to_3_tags) {
                    tag_assoc[lv0_to_lv3_html_tag]["seg_lv4"] = anchor_tag;
                  }
                }
                anchor_tag_ = anchor_tag;
                lv0_to_3_tags = lv0_to_3_tags.init;
              } else if (an_object["lev_markup_number"].to!int > 4) {
                tag_in_seg["seg_lv4"] = anchor_tag_;
                tag_in_seg["seg_lv1_to_4"] = anchor_tag_;
                lev_anchor_tag = anchor_tag;
                tag_assoc[anchor_tag]["seg_lv4"] = tag_in_seg["seg_lv4"];
                tag_assoc[anchor_tag]["seg_lv1_to_4"] = tag_in_seg["seg_lv1_to_4"];
              } else if (an_object["lev_markup_number"].to!int < 4) {
                string segn;
                switch (an_object["lev_markup_number"].to!int) {                           /+ names used for epub markup segments A to D +/
                case 0:
                  segn = "_the_title";
                  goto default;
                case 1:
                  segn = "_part_" ~ cnt1.to!string;
                  ++cnt1;
                  goto default;
                case 2:
                  segn = "_part_" ~ cnt1.to!string ~ "_" ~ cnt2.to!string;
                  ++cnt2;
                  goto default;
                case 3:
                  segn =  "_part_" ~ cnt1.to!string ~ "_" ~ cnt2.to!string ~ "_" ~ cnt3.to!string;
                  ++cnt3;
                  goto default;
                default:
                  lv0_to_3_tags ~= obj_cite_digits.object_number.to!string;
                  lv0_to_3_tags ~= segn;
                  tag_in_seg["seg_lv4"] = segn; // for html segname need following lv4 not yet known
                  tag_in_seg["seg_lv1_to_4"] = segn;
                  break;
                }
              }
              an_object["bookindex_nugget"]
                = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
              bookindex_unordered_hashes
                = bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_digits, tag_in_seg);
              /+ (incrementally build toc) table of contents here! +/
              _anchor_tag                   = obj_cite_digits.identifier;
              the_table_of_contents_section = obj_im.flow_table_of_contents_gather_headings(
                an_object,
                conf_make_meta,
                tag_in_seg,
                _anchor_tag,
                lev4_subtoc,
                the_table_of_contents_section,
              );
              if (an_object["lev_markup_number"] == "4") {
                segnames["html"] ~= tag_in_seg["seg_lv4"];
                html_segnames_ptr = html_segnames_ptr_cntr;
                html_segnames_ptr_cntr++;
              }
              if (an_object["lev_markup_number"].to!int <= 4) {
                segnames["epub"] ~= tag_in_seg["seg_lv1_to_4"];
              }
              auto comp_obj_heading
                = node_construct.node_emitter_heading(
                  an_object["substantive"],
                  an_object["lev_markup_number"],
                  an_object["lev_collapsed_number"],
                  an_object["dummy_heading_status"],
                  tag_in_seg,
                  lev_anchor_tag,
                  tag_assoc,
                  obj_cite_digits,                              // OCNset
                  cntr,                                         // int
                  heading_ptr,                                  // int
                  lv_ancestors_txt,                             // string[]
                  an_object["is"],                              // string
                  html_segnames_ptr,                            // int
                  substantive_object_and_anchor_tags_tuple[sObj.notes_reg],
                  substantive_object_and_anchor_tags_tuple[sObj.notes_star],
                  substantive_object_and_anchor_tags_tuple[sObj.links],
                );
              ++heading_ptr;
              debug(segments) {
                writeln(an_object["lev_markup_number"]);
                writeln(tag_in_seg["seg_lv4"]);
                writeln(tag_in_seg["seg_lv1_to_4"]);
              }
              the_document_body_section ~= comp_obj_heading;
              debug(objectrelated1) { // check
                writeln(line);
              }
              flow_common_reset_(line_occur, an_object, obj_type_status);
              an_object.remove("lev");
              an_object.remove("lev_markup_number");
              processing.remove("verse");
              ++cntr;
            } else if ((obj_type_status["para"] == State.on)
            && (line_occur["para"] > State.off)) {
              /+ paragraph object (current line empty) +/
              /+ repeated character paragraph separator +/
              if ((an_object[an_object_key].to!string).matchFirst(rgx.repeated_character_line_separator)) {
                obj_type_status["ocn_status"]                          = OCNstatus.off;
              }
              obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]);
              an_object["bookindex_nugget"]
                = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
              bookindex_unordered_hashes
                = bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_digits, tag_in_seg);
              an_object["is"] = "para";
              auto comp_obj_heading
                = node_construct.node_location_emitter(
                  content_non_header,
                  tag_in_seg,
                  lev_anchor_tag,
                  tag_assoc,
                  obj_cite_digits,
                  cntr,
                  heading_ptr-1,
                  an_object["is"],
                );
              auto substantive_obj_misc_tuple
                = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc);
              an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
              anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag];
              comp_obj_para                                             = comp_obj_para.init;
              comp_obj_para.metainfo.is_of_part                         = "body";
              comp_obj_para.metainfo.is_of_section                      = "body";
              comp_obj_para.metainfo.is_of_type                         = "para";
              comp_obj_para.metainfo.is_a                               = "para";
              comp_obj_para.text                                        = an_object["substantive"].to!string.strip;
              comp_obj_para.tags.html_segment_anchor_tag_is             = tag_in_seg["seg_lv4"];
              comp_obj_para.tags.epub_segment_anchor_tag_is             = tag_in_seg["seg_lv1_to_4"];
              comp_obj_para.metainfo.ocn                                = obj_cite_digits.object_number;
              comp_obj_para.metainfo.identifier                         = obj_cite_digits.identifier;
              comp_obj_para.metainfo.object_number_off                  = (obj_cite_digits.off==0)   ? true : false; // TODO
              comp_obj_para.metainfo.o_n_book_index                     = obj_cite_digits.bkidx;
              comp_obj_para.metainfo.object_number_type                 = obj_cite_digits.type;
              comp_obj_para.attrib.indent_hang                          = indent["hang_position"];
              comp_obj_para.attrib.indent_base                          = indent["base_position"];
              comp_obj_para.attrib.bullet                               = bullet;
              comp_obj_para.tags.anchor_tags                            = [anchor_tag];
              comp_obj_para.has.inline_notes_reg                        = substantive_obj_misc_tuple[sObj.notes_reg];
              comp_obj_para.has.inline_notes_star                       = substantive_obj_misc_tuple[sObj.notes_star];
              comp_obj_para.has.inline_links                            = substantive_obj_misc_tuple[sObj.links];
              comp_obj_para.has.image_without_dimensions                = substantive_obj_misc_tuple[sObj.image_no_dimensions];
              the_document_body_section                                 ~= comp_obj_para;
              tag_assoc                                                 = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
              flow_common_reset_(line_occur, an_object, obj_type_status);
              indent=[
                "hang_position" : 0,
                "base_position" : 0,
              ];
              bullet = false;
              processing.remove("verse");
              ++cntr;
            } else {
              // could be useful to test line variable should be empty and never null
            }
          }                                                                     // close else for line empty
        }                                                                       // close else for not the above
      }                                                                         // close after non code, other blocks or regular text
      /+ unless (the_document_body_section.length == 0) ? +/
      if (the_document_body_section.length > 0) {
        if (((the_document_body_section[$-1].metainfo.is_a == "para")
          || (the_document_body_section[$-1].metainfo.is_a == "heading")
          || (the_document_body_section[$-1].metainfo.is_a == "quote")
          || (the_document_body_section[$-1].metainfo.is_a == "group")
          || (the_document_body_section[$-1].metainfo.is_a == "block")
          || (the_document_body_section[$-1].metainfo.is_a == "verse"))
        && (the_document_body_section.length > previous_length)) {
          if ((the_document_body_section[$-1].metainfo.is_a == "heading")
          && (the_document_body_section[$-1].metainfo.heading_lev_markup < 5)) {
            obj_type_status["glossary_section"] = State.off;
            obj_type_status["biblio_section"]   = State.off;
            obj_type_status["blurb_section"]    = State.off;
          }
          if (the_document_body_section[$-1].metainfo.is_a == "verse") {             /+ scan for endnotes for whole poem (each verse in poem) +/
            foreach (i; previous_length .. the_document_body_section.length) {
              if (the_document_body_section[i].metainfo.is_a == "verse") {
                if ((the_document_body_section[i].text).match(
                  rgx.inline_notes_al_regular_number_note
                )) {
                  note_section.gather_notes_for_endnote_section(
                    the_document_body_section,
                    tag_in_seg,
                    (i).to!int,
                  );
                }
              }
            }
          } else {                                                                   /+ scan object for endnotes +/
            previous_length = the_document_body_section.length.to!int;
            if ((the_document_body_section[$-1].text).match(
              rgx.inline_notes_al_regular_number_note
            )) {
              previous_count=(the_document_body_section.length -1).to!int;
              note_section.gather_notes_for_endnote_section(
                the_document_body_section,
                tag_in_seg,
                (the_document_body_section.length-1).to!int,
              );
            }
          }
          previous_length = the_document_body_section.length.to!int;
        }
      }
    }                                                                           /+ ← srcDocLoop closed: loop markup document/text line by line +/
                                                                                /+ ↓ post loop markup document/text +/
    auto en_tuple
      = note_section.endnote_objects(obj_cite_digits, opt_action);
    static assert(!isTypeTuple!(en_tuple));
    auto the_endnotes_section = en_tuple[0];
    obj_cite_digits = en_tuple[1];
    debug(endnotes) {
      writefln(
        "%s %s",
        __LINE__,
        the_endnotes_section.length
      );
      foreach (o; the_endnotes_section) {
        writeln(o);
      }
    }
    if (an_object["glossary_nugget"].length == 0) {
      comp_obj_heading_                                 = comp_obj_heading_.init;
      comp_obj_heading_.metainfo.is_of_part             = "empty";
      comp_obj_heading_.metainfo.is_of_section          = "empty";
      comp_obj_heading_.metainfo.is_of_type             = "para";
      comp_obj_heading_.metainfo.is_a                   = "heading";
      comp_obj_heading_.text                            = "(skip) there is no Glossary section";
      comp_obj_heading_.metainfo.ocn                    = 0;
      comp_obj_heading_.metainfo.identifier             = "";
      comp_obj_heading_.metainfo.dummy_heading          = true;
      comp_obj_heading_.metainfo.object_number_off      = true;
      comp_obj_heading_.metainfo.object_number_type     = 0;
      comp_obj_heading_.metainfo.heading_lev_markup     = 1;
      comp_obj_heading_.metainfo.heading_lev_collapsed  = 1;
      comp_obj_heading_.metainfo.parent_ocn             = 1;
      comp_obj_heading_.metainfo.parent_lev_markup      = 0;
      the_glossary_section                              ~= comp_obj_heading_;
    }
    debug(glossary) {
      foreach (gloss; the_glossary_section) {
        writeln(gloss.text);
      }
    }
    auto biblio_unsorted_incomplete = biblio_arr_json.dup;
    auto biblio = Bibliography();
    auto biblio_ordered
      = biblio.flow_bibliography_(biblio_unsorted_incomplete, bib_arr_json);
    if (biblio_ordered.length > 0) {
      {
        comp_obj_heading_                                 = comp_obj_heading_.init;
        comp_obj_heading_.metainfo.is_of_part             = "backmatter";
        comp_obj_heading_.metainfo.is_of_section          = "bibliography";
        comp_obj_heading_.metainfo.is_of_type             = "para";
        comp_obj_heading_.metainfo.is_a                   = "heading";
        comp_obj_heading_.text                            = "Bibliography";
        comp_obj_heading_.metainfo.ocn                    = 0;
        comp_obj_heading_.metainfo.identifier             = "";
        comp_obj_heading_.metainfo.dummy_heading          = true;
        comp_obj_heading_.metainfo.object_number_off      = true;
        comp_obj_heading_.metainfo.object_number_type     = 0;
        comp_obj_heading_.tags.segment_anchor_tag_epub    = "_part_bibliography";
        comp_obj_heading_.tags.anchor_tag_html            = comp_obj_heading_.tags.segment_anchor_tag_epub;
        comp_obj_heading_.tags.in_segment_html            = "bibliography";
        comp_obj_heading_.metainfo.heading_lev_markup     = 1;
        comp_obj_heading_.metainfo.heading_lev_collapsed  = 1;
        comp_obj_heading_.metainfo.parent_ocn             = 1;
        comp_obj_heading_.metainfo.parent_lev_markup      = 0;
        the_bibliography_section                          ~= comp_obj_heading_;
        tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
        tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
      }
      {
        comp_obj_heading_                                 = comp_obj_heading_.init;
        comp_obj_heading_.metainfo.is_of_part             = "backmatter";
        comp_obj_heading_.metainfo.is_of_section          = "bibliography";
        comp_obj_heading_.metainfo.is_of_type             = "para";
        comp_obj_heading_.metainfo.is_a                   = "heading";
        comp_obj_heading_.text                            = "Bibliography";
        comp_obj_heading_.metainfo.ocn                    = 0;
        comp_obj_heading_.metainfo.identifier             = "";
        comp_obj_heading_.metainfo.dummy_heading          = true;
        comp_obj_heading_.metainfo.object_number_off      = true;
        comp_obj_heading_.metainfo.object_number_type     = 0;
        comp_obj_heading_.tags.segment_anchor_tag_epub    = "bibliography";
        comp_obj_heading_.tags.anchor_tag_html            = comp_obj_heading_.tags.segment_anchor_tag_epub;
        comp_obj_heading_.tags.in_segment_html            = comp_obj_heading_.tags.anchor_tag_html;
        comp_obj_heading_.metainfo.heading_lev_markup     = 4;
        comp_obj_heading_.metainfo.heading_lev_collapsed  = 2;
        comp_obj_heading_.metainfo.parent_ocn             = 1;
        comp_obj_heading_.metainfo.parent_lev_markup      = 0;
        comp_obj_heading_.tags.anchor_tags                = ["bibliography"];
        the_bibliography_section                          ~= comp_obj_heading_;
        tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
        tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
      }
    } else {
      comp_obj_heading_                                 = comp_obj_heading_.init;
      comp_obj_heading_.metainfo.is_of_part             = "empty";
      comp_obj_heading_.metainfo.is_of_section          = "empty";
      comp_obj_heading_.metainfo.is_of_type             = "para";
      comp_obj_heading_.metainfo.is_a                   = "heading";
      comp_obj_heading_.text                            = "(skip) there is no Bibliography";
      comp_obj_heading_.metainfo.ocn                    = 0;
      comp_obj_heading_.metainfo.identifier             = "";
      comp_obj_heading_.metainfo.dummy_heading          = true;
      comp_obj_heading_.metainfo.object_number_off      = true;
      comp_obj_heading_.metainfo.object_number_type     = 0;
      comp_obj_heading_.metainfo.heading_lev_markup     = 1;
      comp_obj_heading_.metainfo.heading_lev_collapsed  = 1;
      comp_obj_heading_.metainfo.parent_ocn             = 1;
      comp_obj_heading_.metainfo.parent_lev_markup      = 0;
      the_bibliography_section                          ~= comp_obj_heading_;
    }
    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) ? "" : ", " ~ mkup.italic ~ mkup.ff_o ~ entry["journal"].str ~ mkup.ff_c ~ mkup.italic),
        ((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.metainfo.is_of_part           = "backmatter";
      comp_obj_para.metainfo.is_of_section        = "bibliography";
      comp_obj_para.metainfo.is_of_type           = "para";
      comp_obj_para.metainfo.is_a                 = "bibliography";
      comp_obj_para.text                          = out_.to!string.strip;
      comp_obj_para.metainfo.ocn                  = 0;
      comp_obj_para.metainfo.identifier           = "";
      comp_obj_para.metainfo.object_number_off    = true;
      comp_obj_para.metainfo.object_number_type   = 0;
      comp_obj_para.attrib.indent_hang            = 0;
      comp_obj_para.attrib.indent_base            = 1;
      comp_obj_para.attrib.bullet                 = bullet;
      comp_obj_para.tags.anchor_tags              = [anchor_tag];
      the_bibliography_section                    ~= comp_obj_para;
    }
    debug(bibliosection) {
      foreach (o; the_bibliography_section) {
        writeln(o.text);
      }
    }
    auto bi = BookIndexReportSection();
    auto bi_tuple
      = bi.bookindex_build_abstraction_section(
        bookindex_unordered_hashes,
        obj_cite_digits,
        opt_action,
      );
    destroy(bookindex_unordered_hashes);
    static assert(!isTypeTuple!(bi_tuple));
    auto the_bookindex_section = bi_tuple[0];
    obj_cite_digits = bi_tuple[1];
    debug(bookindex) {
      foreach (bi_entry; the_bookindex_section) {
        writeln(bi_entry);
      }
    }
    if (an_object["blurb_nugget"].length == 0) {
      comp_obj_heading_                                = comp_obj_heading_.init;
      comp_obj_heading_.metainfo.is_of_part            = "empty";
      comp_obj_heading_.metainfo.is_of_section         = "empty";
      comp_obj_heading_.metainfo.is_of_type            = "para";
      comp_obj_heading_.metainfo.is_a                  = "heading";
      comp_obj_heading_.text                           = "(skip) there is no Blurb section";
      comp_obj_heading_.metainfo.ocn                   = 0;
      comp_obj_heading_.metainfo.identifier            = "";
      comp_obj_para.metainfo.object_number_off         = true;
      comp_obj_para.metainfo.object_number_type        = 0;
      comp_obj_heading_.tags.segment_anchor_tag_epub   = "";
      comp_obj_heading_.tags.anchor_tag_html           = "";
      comp_obj_heading_.tags.in_segment_html           = "";
      comp_obj_heading_.metainfo.heading_lev_markup    = 1;
      comp_obj_heading_.metainfo.heading_lev_collapsed = 1;
      comp_obj_heading_.metainfo.parent_ocn            = 1;
      comp_obj_heading_.metainfo.parent_lev_markup     = 0;
      the_blurb_section                                ~= comp_obj_heading_;
    }
    debug(blurb) {
      foreach (blurb; the_blurb_section) {
        writeln(blurb.text);
      }
    }
    indent=[
      "hang_position" : 1,
      "base_position" : 1,
    ];
    comp_obj_toc                               = comp_obj_toc.init;
    comp_obj_toc.metainfo.is_of_part           = "frontmatter";
    comp_obj_toc.metainfo.is_of_section        = "toc";
    comp_obj_toc.metainfo.is_of_type           = "para";
    comp_obj_toc.metainfo.is_a                 = "toc";
    comp_obj_toc.metainfo.ocn                  = 0;
    comp_obj_toc.metainfo.identifier           = "";
    comp_obj_toc.metainfo.object_number_off    = true;
    comp_obj_toc.metainfo.object_number_type   = 0;
    comp_obj_toc.attrib.indent_hang            = indent["hang_position"];
    comp_obj_toc.attrib.indent_base            = indent["base_position"];
    comp_obj_toc.attrib.bullet                 = false;
    if (the_endnotes_section.length > 1) {
      toc_txt_ = format(
        mkup.lnk_o ~ "%s" ~ mkup.lnk_c ~  mkup.url_o ~ "#%s"~  mkup.url_c,
        "Endnotes",
        "endnotes",
      );
      toc_txt_= toc_txt_.links_and_images;
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.has.inline_links           = true;
      the_table_of_contents_section           ~= comp_obj_toc;
    }
    if (the_glossary_section.length > 1) {
      toc_txt_ = format(
        mkup.lnk_o ~ "%s" ~ mkup.lnk_c ~  mkup.url_o ~ "#%s"~  mkup.url_c,
        "Glossary",
        "glossary",
      );
      toc_txt_= toc_txt_.links_and_images;
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.has.inline_links           = true;
      the_table_of_contents_section           ~= comp_obj_toc;
    }
    if (the_bibliography_section.length > 1){
      toc_txt_ = format(
        mkup.lnk_o ~ "%s" ~ mkup.lnk_c ~  mkup.url_o ~ "#%s"~  mkup.url_c,
        "Bibliography",
        "bibliography",
      );
      toc_txt_= toc_txt_.links_and_images;
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.has.inline_links           = true;
      the_table_of_contents_section           ~= comp_obj_toc;
    }
    if (the_bookindex_section.length > 1) {
      toc_txt_ = format(
        mkup.lnk_o ~ "%s" ~ mkup.lnk_c ~  mkup.url_o ~ "#%s"~  mkup.url_c,
        "Book Index",
        "bookindex",
      );
      toc_txt_= toc_txt_.links_and_images;
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.has.inline_links           = true;
      the_table_of_contents_section           ~= comp_obj_toc;
    }
    if (the_blurb_section.length > 1) {
      toc_txt_ = format(
        mkup.lnk_o ~ "%s" ~ mkup.lnk_c ~  mkup.url_o ~ "#%s"~  mkup.url_c,
        "Blurb",
        "blurb",
      );
      toc_txt_= toc_txt_.links_and_images;
      comp_obj_toc.has.inline_links           = true;
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      the_table_of_contents_section           ~= comp_obj_toc;
    }
    debug(toc) {
      writefln(
        "%s %s",
        __LINE__,
      );
      foreach (toc_linked_heading; the_table_of_contents_section) {
        writeln(mkup.indent_by_spaces_provided(toc_linked_heading.attrib.indent_hang), toc_linked_heading.text);
      }
    }
    the_document_head_section ~= the_document_body_section[0];
    the_document_body_section=the_document_body_section[1..$];
    int[] _get_ancestors_markup(O)(O obj, ref int[] _ancestors_markup) {
      if (obj.metainfo.is_a == "heading") {
        debug(dom) {
          writeln(obj.text);
        }
        if (obj.metainfo.heading_lev_markup == 1) {
          _ancestors_markup = [
            _ancestors_markup[0],
            0,0,0,0,0,0,0
          ];
        }
        if (obj.metainfo.heading_lev_markup == 2) {
          _ancestors_markup = [
            _ancestors_markup[0],
            _ancestors_markup[1],
            0,0,0,0,0,0
          ];
        }
        if (obj.metainfo.heading_lev_markup == 3) {
          _ancestors_markup = [
            _ancestors_markup[0],
            _ancestors_markup[1],
            _ancestors_markup[2],
            0,0,0,0,0
          ];
        }
        if (obj.metainfo.heading_lev_markup == 4) {
          _ancestors_markup = [
            _ancestors_markup[0],
            _ancestors_markup[1],
            _ancestors_markup[2],
            _ancestors_markup[3],
            0,0,0,0
          ];
        }
        if (obj.metainfo.heading_lev_markup == 5) {
          _ancestors_markup = [
            _ancestors_markup[0],
            _ancestors_markup[1],
            _ancestors_markup[2],
            _ancestors_markup[3],
            _ancestors_markup[4],
            0,0,0
          ];
        }
        if (obj.metainfo.heading_lev_markup == 6) {
          _ancestors_markup = [
            _ancestors_markup[0],
            _ancestors_markup[1],
            _ancestors_markup[2],
            _ancestors_markup[3],
            _ancestors_markup[4],
            _ancestors_markup[5],
            0,0
          ];
        }
        if (obj.metainfo.heading_lev_markup == 7) {
          _ancestors_markup = [
            _ancestors_markup[0],
            _ancestors_markup[1],
            _ancestors_markup[2],
            _ancestors_markup[3],
            _ancestors_markup[4],
            _ancestors_markup[5],
            _ancestors_markup[6],
            0
          ];
        }
        if (obj.metainfo.heading_lev_markup == 8) {
          _ancestors_markup = [
            _ancestors_markup[0],
            _ancestors_markup[1],
            _ancestors_markup[2],
            _ancestors_markup[3],
            _ancestors_markup[4],
            _ancestors_markup[5],
            _ancestors_markup[6],
            _ancestors_markup[7]
          ];
        }
        _ancestors_markup[obj.metainfo.heading_lev_markup] = obj.metainfo.ocn;
      }
      debug(ancestor_markup) {
        writeln("marked up: ", _ancestors_markup);
      }
      return _ancestors_markup;
    }
    int[] _get_ancestors_collapsed(O)(O obj, ref int[] _ancestors_collapsed) {
      if (obj.metainfo.is_a == "heading") {
        if (obj.metainfo.heading_lev_collapsed == 1) {
          _ancestors_collapsed = [
            _ancestors_collapsed[0],
            0,0,0,0,0,0,0
          ];
        }
        if (obj.metainfo.heading_lev_collapsed == 2) {
          _ancestors_collapsed = [
            _ancestors_collapsed[0],
            _ancestors_collapsed[1],
            0,0,0,0,0,0
          ];
        }
        if (obj.metainfo.heading_lev_collapsed == 3) {
          _ancestors_collapsed = [
            _ancestors_collapsed[0],
            _ancestors_collapsed[1],
            _ancestors_collapsed[2],
            0,0,0,0,0
          ];
        }
        if (obj.metainfo.heading_lev_collapsed == 4) {
          _ancestors_collapsed = [
            _ancestors_collapsed[0],
            _ancestors_collapsed[1],
            _ancestors_collapsed[2],
            _ancestors_collapsed[3],
            0,0,0,0
          ];
        }
        if (obj.metainfo.heading_lev_collapsed == 5) {
          _ancestors_collapsed = [
            _ancestors_collapsed[0],
            _ancestors_collapsed[1],
            _ancestors_collapsed[2],
            _ancestors_collapsed[3],
            _ancestors_collapsed[4],
            0,0,0
          ];
        }
        if (obj.metainfo.heading_lev_collapsed == 6) {
          _ancestors_collapsed = [
            _ancestors_collapsed[0],
            _ancestors_collapsed[1],
            _ancestors_collapsed[2],
            _ancestors_collapsed[3],
            _ancestors_collapsed[4],
            _ancestors_collapsed[5],
            0,0
          ];
        }
        if (obj.metainfo.heading_lev_collapsed == 7) {
          _ancestors_collapsed = [
            _ancestors_collapsed[0],
            _ancestors_collapsed[1],
            _ancestors_collapsed[2],
            _ancestors_collapsed[3],
            _ancestors_collapsed[4],
            _ancestors_collapsed[5],
            _ancestors_collapsed[6],
            0
          ];
        }
        if (obj.metainfo.heading_lev_collapsed == 8) {
          _ancestors_collapsed = [
            _ancestors_collapsed[0],
            _ancestors_collapsed[1],
            _ancestors_collapsed[2],
            _ancestors_collapsed[3],
            _ancestors_collapsed[4],
            _ancestors_collapsed[5],
            _ancestors_collapsed[6],
            _ancestors_collapsed[7]
          ];
        }
        _ancestors_collapsed[obj.metainfo.heading_lev_collapsed] = obj.metainfo.ocn;
      }
      debug(ancestor_collapsed) {
        writeln("collapsed: ", _ancestors_collapsed);
      }
      return _ancestors_collapsed;
    }
    /+ multiple 1~ levels, loop through document body +/
    if (the_document_body_section.length > 1) {
      int[] _ancestors_markup = [0,0,0,0,0,0,0,0];
      int[][] _ancestors_markup_;
      _ancestors_markup = [1,0,0,0,0,0,0,0];
      _ancestors_markup_ ~= _ancestors_markup;
      int[] _ancestors_collapsed = [0,0,0,0,0,0,0,0];
      int[][] _ancestors_collapsed_;
      _ancestors_collapsed = [1,0,0,0,0,0,0,0];
      _ancestors_collapsed_ ~= _ancestors_collapsed;
      foreach (ref obj; the_document_body_section) {
        if (obj.metainfo.is_a == "heading") {
          obj.metainfo.markedup_ancestors = _get_ancestors_markup(obj, _ancestors_markup);
          obj.metainfo.collapsed_ancestors = _get_ancestors_collapsed(obj, _ancestors_collapsed);
          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup];
        }
      }
      debug(ancestors) {
        writeln("ancestors markup o_n:    ", obj.metainfo.markedup_ancestors);
        writeln("ancestors collapsed o_n: ", obj.metainfo.markedup_ancestors);
      }
    }
    if (the_endnotes_section.length > 1) {
      segnames["html"] ~= "endnotes";
      segnames["epub"] ~= "endnotes";
      html_segnames_ptr = html_segnames_ptr_cntr;
      foreach (ref obj; the_endnotes_section) {
        if (obj.metainfo.is_a == "heading") {
          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup];
        }
        if (obj.metainfo.heading_lev_markup == 4) {
          obj.ptr.html_segnames = html_segnames_ptr;
          break;
        }
      }
      html_segnames_ptr_cntr++;
    }
    if (the_glossary_section.length > 1) {
      segnames["html"] ~= "glossary";
      segnames["epub"] ~= "glossary";
      html_segnames_ptr = html_segnames_ptr_cntr;
      foreach (ref obj; the_glossary_section) {
        if (obj.metainfo.is_a == "heading") {
          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup];
        }
        if (obj.metainfo.heading_lev_markup == 4) {
          obj.ptr.html_segnames = html_segnames_ptr;
          break;
        }
      }
      html_segnames_ptr_cntr++;
    }
    if (the_bibliography_section.length > 1) {
      segnames["html"] ~= "bibliography";
      segnames["epub"] ~= "bibliography";
      html_segnames_ptr = html_segnames_ptr_cntr;
      foreach (ref obj; the_bibliography_section) {
        if (obj.metainfo.is_a == "heading") {
          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup];
        }
        if (obj.metainfo.heading_lev_markup == 4) {
          obj.ptr.html_segnames = html_segnames_ptr;
          break;
        }
      }
      html_segnames_ptr_cntr++;
    }
    if (the_bookindex_section.length > 1) {
      segnames["html"] ~= "bookindex";
      segnames["epub"] ~= "bookindex";
      html_segnames_ptr = html_segnames_ptr_cntr;
      foreach (ref obj; the_bookindex_section) {
        if (obj.metainfo.is_a == "heading") {
          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup];
        }
        if (obj.metainfo.heading_lev_markup == 4) {
          obj.ptr.html_segnames = html_segnames_ptr;
          break;
        }
      }
      html_segnames_ptr_cntr++;
    }
    if (the_blurb_section.length > 1) {
      segnames["html"] ~= "blurb";
      segnames["epub"] ~= "blurb";
      html_segnames_ptr = html_segnames_ptr_cntr;
      foreach (ref obj; the_blurb_section) {
        if (obj.metainfo.is_a == "heading") {
          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup];
        }
        if (obj.metainfo.heading_lev_markup == 4) {
          obj.ptr.html_segnames = html_segnames_ptr;
          break;
        }
      }
      html_segnames_ptr_cntr++;
    }
    auto get_decendants()(ObjGenericComposite[] document_sections) {
      int[string] _heading_ocn_decendants;
      string[] _ocn_open_key = ["","","","","","","",""];
      auto _doc_sect_length = document_sections.length - 1;
      int _last_ocn;
      foreach (_lg, ref obj; document_sections) {
        if (obj.metainfo.is_a == "heading") {
          foreach (_dts_lv, dom_tag_status; obj.metainfo.dom_structure_markedup_tags_status) {
            switch (dom_tag_status) with (DomTags) {
            case none: break;
            case open:
                _ocn_open_key[_dts_lv] = (obj.metainfo.ocn).to!string;
                _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn;
              break;
            case close:
              if (_ocn_open_key[_dts_lv].empty) {
                _ocn_open_key[_dts_lv] = "0";
              }
              _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn - 1;
              _ocn_open_key[_dts_lv] = (0).to!string;
              break;
            case close_and_open:
              if (_ocn_open_key[_dts_lv].empty) {
                _ocn_open_key[_dts_lv] = "0";
              }
              _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn - 1;
              _ocn_open_key[_dts_lv] = (obj.metainfo.ocn).to!string;
              _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn;
              break;
            case open_still: break;
            default: break;
            }
          }
        }
        if (obj.metainfo.ocn > 0) {
          _last_ocn = obj.metainfo.ocn;
        }
        if (_lg == _doc_sect_length) {
          _heading_ocn_decendants["1"] = _last_ocn; // close existing o_n key
        }
      }
      Tuple!(int, int)[] pairs;
      foreach (pair; _heading_ocn_decendants.byPair) {
        pairs ~= tuple(pair[0].to!int, pair[1]);
      }
      return pairs.sort;
    }
    string[] _images;
    string[] extract_images()(string content_block) {
      string[] images_;
      if (auto m = content_block.matchAll(rgx.image)) {
        images_ ~= m.captures[1];
      }
      return images_;
    }
    string[] segnames_0_to_4;
    auto _image_dimensions(O,M)(O obj, M manifest_matter) {
      if (obj.has.image_without_dimensions) {
        import std.math;
        import imageformats;
        int w, h, chans;
        real _w, _h;
        int max_width = 640;
        foreach (m; obj.text.matchAll(rgx.inline_image_without_dimensions)) {
          debug(images) {
            writeln(manifest_matter.src.image_dir_path ~ "/" ~ m["img"]);
          }
          read_image_info(manifest_matter.src.image_dir_path ~ "/" ~ m["img"], w, h, chans);
          // calculate, decide max width and proportionally reduce to keep w & h within it
          debug(images) {
            writeln("width: ", w, ", height: ", h);
          }
          if (w > max_width) {
            _w = max_width;
            _h = round((max_width / w.to!real) * h.to!real);
          } else {
            _w = w;
            _h = h;
          }
          obj.text = obj.text.replaceFirst(
            rgx.inline_image_without_dimensions,
            format(q"┃%s☼%s,w%sh%s %s┃",
              "$1",
              "$3",
              _w.to!string,
              _h.to!string,
              "$6",
            )
          );
        }
        debug(images) {
          writeln("image without dimensions: ", obj.text);
        }
      }
      return obj;
    }
    auto _links(O)(O obj) {
      if (auto m = obj.text.match(rgx.inline_link_stow_uri)) {
        debug(links) {
          writeln("number of link matches to stow: ", (obj.text.match(rgx.inline_link_stow_uri)).count);
          writeln("links to stow: ", (obj.text.match(rgx.inline_link_stow_uri)));
        }
        int _n_matches = (obj.text.match(rgx.inline_link_stow_uri)).count.to!int;
        for(int i=0; i < _n_matches; ++i) {
          if (obj.text.match(rgx.inline_link_stow_uri)) {
            obj.stow.link ~= obj.text.matchFirst(rgx.inline_link_stow_uri)[2];
            obj.text = obj.text.replaceFirst(
              rgx.inline_link_stow_uri,
              format(q"┃┥%s┝┤%s├┃", "$1", i)
            );
          }
        }
      }
      return obj;
    }
    foreach (ref obj; the_document_head_section) {
      if (obj.metainfo.is_a == "heading") {
        debug(dom) {
          writeln(obj.text);
        }
        if (obj.metainfo.heading_lev_markup <= 4) {
          segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub;
        }
        if (obj.metainfo.heading_lev_markup == 0) {
          /+ TODO second hit (of two) with same assertion failure, check, fix and reinstate
          assert( obj.metainfo.ocn == 1,
            "Title OCN should be 1 not: " ~ obj.metainfo.ocn.to!string); // bug introduced 0.18.1
          +/
          obj.metainfo.ocn = 1;
          obj.metainfo.identifier = "1";
          obj.metainfo.object_number_type = OCNtype.ocn;
        }
        /+ dom structure (marked up & collapsed) +/
        if (opt_action.meta_processing_xml_dom) {
          obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup);
          obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed);
        }
        obj = obj.obj_heading_ancestors(lv_ancestors_txt);
      }
      obj = _links(obj);
    }
    if (the_table_of_contents_section.length > 1) {
      /+ scroll +/
      dom_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup;
      dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup;
      foreach (ref obj; the_table_of_contents_section) {
        if (obj.metainfo.is_a == "heading") {
          if (obj.metainfo.heading_lev_markup <= 4) {
            segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub;
            if (obj.metainfo.heading_lev_markup == 4) {
              obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1];
              assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames],
                obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]);
            }
          }
          /+ dom structure (marked up & collapsed) +/
          if (opt_action.meta_processing_xml_dom) {
            obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup);
            obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed);
          }
          obj = obj.obj_heading_ancestors(lv_ancestors_txt);
        }
        obj = _links(obj);
      }
    }
    /+ multiple 1~ levels, loop through document body +/
    if (the_document_body_section.length > 1) {
      foreach (ref obj; the_document_body_section) {
        if (!(obj.metainfo.identifier.empty)) {
          if (!(((obj.metainfo.identifier) in tag_assoc)
            && ("seg_lv4" in tag_assoc[(obj.metainfo.identifier)]))
          ) {
            tag_assoc[(obj.metainfo.identifier)]["seg_lv4"]
            = obj.tags.html_segment_anchor_tag_is;
          }
          tag_assoc[(obj.metainfo.identifier)]["seg_lv1_to_4"]
          = obj.tags.epub_segment_anchor_tag_is;
        }
        if (obj.metainfo.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          if (obj.metainfo.heading_lev_markup <= 4) {
            segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub;
            if (obj.metainfo.heading_lev_markup == 4) {
              obj.tags.lev4_subtoc = lev4_subtoc[obj.tags.anchor_tag_html];
              obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1];
              if (segnames["html"].length > obj.ptr.html_segnames + 1) {
                obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1];
              }
              assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames],
                obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]);
            }
          }
          /+ dom structure (marked up & collapsed) +/
          if (opt_action.meta_processing_xml_dom) {
            obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup);
            obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed);
          }
          obj = obj.obj_heading_ancestors(lv_ancestors_txt);
        } else if (obj.metainfo.is_a == "para") {
           _images ~= extract_images(obj.text);
           obj = _image_dimensions(obj, manifest_matter);
        }
        obj = _links(obj);
      }
    }
    auto image_list = (_images.sort()).uniq;
    /+ optional only one 1~ level +/
    if (the_endnotes_section.length > 1) {
      dom_structure_markedup_tags_status_buffer  = dom_structure_markedup_tags_status.dup;
      dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup;
      dom_structure_markedup_tags_status         = dom_structure_markedup_tags_status_buffer.dup;
      dom_structure_collapsed_tags_status        = dom_structure_collapsed_tags_status_buffer.dup;
      foreach (ref obj; the_endnotes_section) {
        if (obj.metainfo.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          obj_cite_digits         = ocn_emit(OCNstatus.on);
          obj.metainfo.ocn        = obj_cite_digits.object_number;
          obj.metainfo.identifier = obj_cite_digits.identifier;
          if (obj.metainfo.heading_lev_markup <= 4) {
            segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub;
            if (obj.metainfo.heading_lev_markup == 4) {
              obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1];
              if (segnames["html"].length > obj.ptr.html_segnames + 1) {
                obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1];
              }
              assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames],
                obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]);
            }
          }
          /+ dom structure (marked up & collapsed) +/
          if (opt_action.meta_processing_xml_dom) {
            obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup);
            obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed);
          }
          obj = obj.obj_heading_ancestors(lv_ancestors_txt);
        }
        obj = _links(obj);
      }
    }
    /+ optional only one 1~ level +/
    if (the_glossary_section.length > 1) {
      foreach (ref obj; the_glossary_section) {
        if (obj.metainfo.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          obj_cite_digits         = ocn_emit(OCNstatus.on);
          obj.metainfo.ocn        = obj_cite_digits.object_number;
          obj.metainfo.identifier = obj_cite_digits.identifier;
          if (obj.metainfo.heading_lev_markup <= 4) {
            segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub;
            if (obj.metainfo.heading_lev_markup == 4) {
              obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1];
              if (segnames["html"].length > obj.ptr.html_segnames + 1) {
                obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1];
              }
              assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames],
                obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]);
            }
          }
          /+ dom structure (marked up & collapsed) +/
          if (opt_action.meta_processing_xml_dom) {
            obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup);
            obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed);
          }
          obj = obj.obj_heading_ancestors(lv_ancestors_txt);
        } else if (obj.metainfo.is_a == "glossary") {
          obj_cite_digits         = ocn_emit(OCNstatus.on);
          obj.metainfo.ocn        = obj_cite_digits.object_number;
          obj.metainfo.identifier = obj_cite_digits.identifier;
        }
        obj = _links(obj);
      }
    }
    /+ optional only one 1~ level +/
    if (the_bibliography_section.length > 1) {
      foreach (ref obj; the_bibliography_section) {
        if (obj.metainfo.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          obj_cite_digits         = ocn_emit(OCNstatus.on);
          obj.metainfo.ocn        = obj_cite_digits.object_number;
          obj.metainfo.identifier = obj_cite_digits.identifier;
          if (obj.metainfo.heading_lev_markup <= 4) {
            segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub;
            if (obj.metainfo.heading_lev_markup == 4) {
              obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1];
              if (segnames["html"].length > obj.ptr.html_segnames + 1) {
                obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1];
              }
              assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames],
                obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]);
            }
          }
          /+ dom structure (marked up & collapsed) +/
          if (opt_action.meta_processing_xml_dom) {
            obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup);
            obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed);
          }
          obj = obj.obj_heading_ancestors(lv_ancestors_txt);
        } else if (obj.metainfo.is_a == "bibliography") {
          obj_cite_digits         = ocn_emit(OCNstatus.on);
          obj.metainfo.ocn        = obj_cite_digits.object_number;
          obj.metainfo.identifier = obj_cite_digits.identifier;
        }
        obj = _links(obj);
      }
    }
    /+ optional only one 1~ level +/
    int ocn_       = obj_cite_digits.object_number;
    int ocn_bkidx_ = 0;
    int ocn_bidx_;
    if (the_bookindex_section.length > 1) {                                        /+ scroll +/
      dom_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup;
      dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup;
      foreach (ref obj; the_bookindex_section) {
        if (obj.metainfo.is_a == "heading") {
          debug(dom) {
          }
          if (obj.metainfo.heading_lev_markup <= 4) {
            segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub;
          }
          obj_cite_digits         = ocn_emit(OCNstatus.on);
          obj.metainfo.ocn        = obj_cite_digits.object_number;
          obj.metainfo.identifier = obj_cite_digits.identifier;
          if (obj.metainfo.heading_lev_markup <= 4) {
            if (obj.metainfo.heading_lev_markup == 4) {
              obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1];
              if (segnames["html"].length > obj.ptr.html_segnames + 1) {
                obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1];
              }
              assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames],
                obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]);
            }
          }
          /+ dom structure (marked up & collapsed) +/
          if (opt_action.meta_processing_xml_dom) {
            obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup);
            obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed);
          }
          obj = obj.obj_heading_ancestors(lv_ancestors_txt);
        } else if (obj.metainfo.is_a == "bookindex") {
          obj_cite_digits                       = ocn_emit(OCNstatus.bkidx);
          obj.metainfo.ocn                      = obj_cite_digits.object_number;
          obj.metainfo.identifier               = obj_cite_digits.identifier;
          obj.metainfo.o_n_book_index           = obj_cite_digits.bkidx;
          obj.metainfo.object_number_type       = OCNtype.bkidx;
        }
        obj = _links(obj);
      }
      /+ TODO assert failure, reinstate
      assert(obj_cite_digit_bkidx == ocn_bidx_
        obj_cite_digit_bkidx ~ " == ocn_" ~ ocn_ ~ "?");
      +/
    }
    /+ optional only one 1~ level +/
    if (the_blurb_section.length > 1) {
      foreach (ref obj; the_blurb_section) {
        if (obj.metainfo.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          obj_cite_digits         = ocn_emit(OCNstatus.on);
          obj.metainfo.ocn        = obj_cite_digits.object_number;
          obj.metainfo.identifier = obj_cite_digits.identifier;
          if (obj.metainfo.heading_lev_markup <= 4) {
            segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub;
            if (obj.metainfo.heading_lev_markup == 4) {
              obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1];
              if (segnames["html"].length > obj.ptr.html_segnames + 1) {
                obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1];
              }
              assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames],
                obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]);
            }
          }
          /+ dom structure (marked up & collapsed) +/
          if (opt_action.meta_processing_xml_dom) {
            obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup);
            obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed);
          }
          obj = obj.obj_heading_ancestors(lv_ancestors_txt);
        } else if (obj.metainfo.is_a == "blurb") {
          obj_cite_digits = ocn_emit(OCNstatus.off);
          obj.metainfo.object_number_off  = obj_cite_digits.off;
          obj.metainfo.object_number_type = OCNtype.non;
        }
        obj = _links(obj);
      }
    }
    if (the_document_body_section.length > 1) {
      auto pairs = get_decendants(
        the_document_head_section ~
        the_document_body_section ~
        the_endnotes_section ~
        the_glossary_section ~
        the_bibliography_section ~
        the_bookindex_section ~
        the_blurb_section
      );
      debug(decendants_tuple) {
        pairs = pairs.sort();
        foreach (pair; pairs) {  // (pair; pairs.sort())
          writeln(pair[0], "..", pair[1]);
        }
      }
      foreach (ref obj; the_document_head_section) {
        if (obj.metainfo.is_a == "heading") {
          foreach (pair; pairs) {
            if (obj.metainfo.ocn == pair[0]) {
              obj.metainfo.last_decendant_ocn = pair[1];
            }
          }
        }
      }
      if (the_document_body_section.length > 1) {
        foreach (ref obj; the_document_body_section) {
          if (obj.metainfo.is_a == "heading") {
            foreach (pair; pairs) {
              if (obj.metainfo.ocn == pair[0]) {
                obj.metainfo.last_decendant_ocn = pair[1];
              }
            }
          }
        }
      }
      if (the_endnotes_section.length > 1) {
        foreach (ref obj; the_endnotes_section) {
          if (obj.metainfo.is_a == "heading") {
            foreach (pair; pairs) {
              if (obj.metainfo.ocn == pair[0]) {
                obj.metainfo.last_decendant_ocn = pair[1];
              }
            }
          }
        }
      }
      if (the_glossary_section.length > 1) {
        foreach (ref obj; the_glossary_section) {
          if (obj.metainfo.is_a == "heading") {
            foreach (pair; pairs) {
              if (obj.metainfo.ocn == pair[0]) {
                obj.metainfo.last_decendant_ocn = pair[1];
              }
            }
          }
        }
      }
      if (the_bibliography_section.length > 1) {
        foreach (ref obj; the_bibliography_section) {
          if (obj.metainfo.is_a == "heading") {
            foreach (pair; pairs) {
              if (obj.metainfo.ocn == pair[0]) {
                obj.metainfo.last_decendant_ocn = pair[1];
              }
            }
          }
        }
      }
      if (the_bookindex_section.length > 1) {
        foreach (ref obj; the_bookindex_section) {
          if (obj.metainfo.is_a == "heading") {
            foreach (pair; pairs) {
              if (obj.metainfo.ocn == pair[0]) {
                obj.metainfo.last_decendant_ocn = pair[1];
              }
            }
          }
        }
      }
      if (the_blurb_section.length > 1) {
        foreach (ref obj; the_blurb_section) {
          if (obj.metainfo.is_a == "heading") {
            foreach (pair; pairs) {
              if (obj.metainfo.ocn == pair[0]) {
                obj.metainfo.last_decendant_ocn = pair[1];
              }
            }
          }
        }
      }
    }
      /+ TODO
        - note create/insert heading object sole purpose eof close all open tags
          sort out:
          - obj.metainfo.dom_structure_markedup_tags_status = dom_structure_markedup_tags_status;
          - obj.metainfo.dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status;
      +/
    comp_obj_heading_                                 = comp_obj_heading_.init;
    comp_obj_heading_.metainfo.is_of_part             = "empty";
    comp_obj_heading_.metainfo.is_of_section          = "empty";
    comp_obj_heading_.metainfo.is_of_type             = "para";
    comp_obj_heading_.metainfo.is_a                   = "heading";
    comp_obj_heading_.metainfo.ocn                    = 0;
    comp_obj_heading_.metainfo.identifier             = "";
    comp_obj_heading_.metainfo.dummy_heading          = true;
    comp_obj_heading_.metainfo.object_number_off      = true;
    comp_obj_heading_.metainfo.object_number_type     = 0;
    comp_obj_heading_.tags.segment_anchor_tag_epub    = "";
    comp_obj_heading_.tags.anchor_tag_html            = "";
    comp_obj_heading_.tags.in_segment_html            = "";
    comp_obj_heading_.tags.html_segment_anchor_tag_is = "";
    comp_obj_heading_.tags.epub_segment_anchor_tag_is = "";
    comp_obj_heading_.metainfo.heading_lev_markup     = 9;
    comp_obj_heading_.metainfo.heading_lev_collapsed  = 9;
    comp_obj_heading_.metainfo.parent_ocn             = 0;
    comp_obj_heading_.metainfo.parent_lev_markup      = 0;
    comp_obj_heading_.metainfo.dom_structure_markedup_tags_status          = dom_structure_markedup_tags_status.dup;
    comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status         = dom_structure_collapsed_tags_status.dup;
    comp_obj_heading_ = comp_obj_heading_.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, 0);
    comp_obj_heading_ = comp_obj_heading_.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, 0);
    comp_obj_heading_ = comp_obj_heading_.obj_heading_ancestors(lv_ancestors_txt);
    // the_dom_tail_section                      ~= comp_obj_heading_; // remove tail for now, decide on later
    ObjGenericComposite[][string] document_the = [
      "head":             the_document_head_section,
      "toc":              the_table_of_contents_section,
      /+ substantive/body: +/
      "body":             the_document_body_section,
      /+ backmatter: +/
      "endnotes":         the_endnotes_section,
      "glossary":         the_glossary_section,
      "bibliography":     the_bibliography_section,
      "bookindex":        the_bookindex_section,
      "blurb":            the_blurb_section,
      /+ dom tail only +/
      "tail":             the_dom_tail_section,
    ];
    string[][string] document_section_keys_sequenced = [
      "scroll": ["head", "toc", "body",],
      "seg":    ["head", "toc", "body",],
      "sql":    ["head", "body",],
      "latex":  ["head", "toc", "body",]
    ];
    if (document_the["endnotes"].length > 1) {
      document_section_keys_sequenced["scroll"] ~= "endnotes";
      document_section_keys_sequenced["seg"]    ~= "endnotes";
      document_section_keys_sequenced["latex"]  ~= "endnotes";
    }
    if (document_the["glossary"].length > 1) {
      document_section_keys_sequenced["scroll"] ~= "glossary";
      document_section_keys_sequenced["seg"]    ~= "glossary";
      document_section_keys_sequenced["sql"]    ~= "glossary";
      document_section_keys_sequenced["latex"]  ~= "glossary";
    }
    if (document_the["bibliography"].length > 1) {
      document_section_keys_sequenced["scroll"] ~= "bibliography";
      document_section_keys_sequenced["seg"]    ~= "bibliography";
      document_section_keys_sequenced["sql"]    ~= "bibliography";
      document_section_keys_sequenced["latex"]  ~= "bibliography";
    }
    if (document_the["bookindex"].length > 1) {
      document_section_keys_sequenced["scroll"] ~= "bookindex";
      document_section_keys_sequenced["seg"]    ~= "bookindex";
      document_section_keys_sequenced["sql"]    ~= "bookindex";
      document_section_keys_sequenced["latex"]  ~= "bookindex";
    }
    if (document_the["blurb"].length > 1) {
      document_section_keys_sequenced["scroll"] ~= "blurb";
      document_section_keys_sequenced["seg"]    ~= "blurb";
      document_section_keys_sequenced["sql"]    ~= "blurb";
      document_section_keys_sequenced["latex"]  ~= "blurb";
    }
    if ((opt_action.html)
    || (opt_action.html_scroll)
    || (opt_action.html_seg)
    || (opt_action.epub)) {
      document_section_keys_sequenced["scroll"] ~= "tail";
      document_section_keys_sequenced["seg"]    ~= "tail";
    }
    string[] segnames_4        = segnames["html"].dup;
    string[] segnames_lv1_to_4 = segnames["epub"].dup;
    debug(segnames) {
      writeln("segnames_lv4:      ", segnames_4);
      writeln("segnames_lv1_to_4: ", segnames_lv1_to_4);
    }
    destroy(the_document_head_section);
    destroy(the_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);
    destroy(segnames);
    destroy(bookindex_unordered_hashes);
    destroy(an_object);
    obj_cite_digits                              = ocn_emit(OCNstatus.reset);
    biblio_arr_json                              = [];
    obj_cite_digit_                              = 0;
    html_segnames_ptr                            = 0;
    html_segnames_ptr_cntr                       = 0;
    content_non_header                           = "8";
    dom_structure_markedup_tags_status           = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
    dom_structure_markedup_tags_status_buffer    = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
    dom_structure_collapsed_tags_status          = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
    dom_structure_collapsed_tags_status_buffer   = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
    
    auto doc_has() {
      struct DocHas_ {
        uint inline_links() {
          return dochas["inline_links"];
        }
        uint inline_notes_reg() {
          return dochas["inline_notes"];
        }
        uint inline_notes_star() {
          return dochas["inline_notes_star"];
        }
        uint codeblocks() {
          return dochas["codeblock"];
        }
        uint tables() {
          return dochas["table"];
        }
        uint blocks() {
          return dochas["block"];
        }
        uint groups() {
          return dochas["group"];
        }
        uint poems() {
          return dochas["poem"];
        }
        uint quotes() {
          return dochas["quote"];
        }
        ulong images() { // TODO not ideal rethink
          return (image_list.to!string.strip("[","]").split(",").length);
        }
        auto imagelist() {
          return image_list;
        }
        auto keys_seq() {
          return docSectKeysSeq!()(document_section_keys_sequenced);
        }
        string[] segnames_lv4() {
          return segnames_4;
        }
        string[] segnames_lv_0_to_4() {
          return segnames_0_to_4;
        }
        string[string][string] tag_associations() {
          return tag_assoc;
        }
      }
      return DocHas_();
    }
    auto t = tuple(
      document_the,
      doc_has,
    );
    return t;
                                                                                /+ post loop markup document/text ↑ +/
  }                                                                             /+ ← closed: abstract doc source +/
                                                                                /+ ↓ abstraction functions +/
  static string[string] object_reset()(string[string] an_object) {
    an_object.remove("body_nugget");
    an_object.remove("substantive");
    an_object.remove("is");
    an_object.remove("attrib");
    an_object.remove("bookindex_nugget");
    return an_object;
  }
  void flow_common_reset_()(
    return ref int[string]     line_occur,
    return ref string[string]  an_object,
    return ref int[string]     obj_type_status,
  ) {
    line_occur["heading"]      = State.off;
    line_occur["para"]         = State.off;
    obj_type_status["heading"] = State.off;
    obj_type_status["para"]    = State.off;
    an_object                  = an_object.object_reset;
  }
  static int[string]         _check_ocn_status_()(
    char[]           line,
    int[string]      obj_type_status,
  ) {
    static auto rgx = Rgx();
    if (!(line.empty)
      && (obj_type_status["ocn_status_off_for_multiple_objects"] == OCN_off_block_status.off)
    ) {
      /+ not multi-line object, check whether object_number is on or turned off +/
      if (line.matchFirst(rgx.object_number_block_marks)) {                      /+ switch off object_number +/
        if (line.matchFirst(rgx.object_number_off_block)) {
          obj_type_status["ocn_status_off_for_multiple_objects"] = OCN_off_block_status.on;
          obj_type_status["ocn_status"]                          = OCNstatus.off;
          debug(ocnoff) {
            writeln(line);
          }
        }
        if (line.matchFirst(rgx.object_number_off_block_dummy_heading)) {
          obj_type_status["ocn_status_off_for_multiple_objects"] = OCN_off_block_status.on;
          obj_type_status["heading_off_for_multiple_objects"]    = Status.on;
          obj_type_status["ocn_status"]                          = OCNstatus.off;
          debug(ocnoff) {
            writeln(line);
          }
        }
      } else {
        if (obj_type_status["ocn_status_off_for_multiple_objects"] == OCN_off_block_status.off) {
          obj_type_status["dummy_heading_status"] = Status.off;
          if (obj_type_status["heading_off_for_multiple_objects"]) {
            obj_type_status["dummy_heading_status"] = Status.on;
          }
          if (line.matchFirst(rgx.object_number_off)) {
            obj_type_status["ocn_status"] = OCNstatus.off;
          } else if (line.matchFirst(rgx.object_number_off_dummy_heading)) {
            obj_type_status["ocn_status"]           = OCNstatus.off;
            obj_type_status["dummy_heading_status"] = Status.on;
          } else {
            obj_type_status["ocn_status"]           = OCNstatus.on;
            obj_type_status["dummy_heading_status"] = Status.off;
          }
        } else {
          obj_type_status["ocn_status"]             = obj_type_status["ocn_status_off_for_multiple_objects"];
        }
      }
    } else if (
      !(line.empty)
      && (obj_type_status["ocn_status_off_for_multiple_objects"] > OCN_off_block_status.off)
    ) {
      if (line.matchFirst(rgx.object_number_off_block_close)) {
        obj_type_status["ocn_status_off_for_multiple_objects"] = OCN_off_block_status.off;
        obj_type_status["ocn_status"]                          = OCNstatus.on;
        obj_type_status["dummy_heading_status"]                = Status.off;
        debug(ocnoff) {
          writeln(line);
        }
      }
    }
    return obj_type_status;
  }
  char[] _doc_header_and_make_substitutions_(CMM)(
    char[]  line,
    CMM     conf_make_meta,
  ) {
    enum Substitute { match, markup, }
    if (conf_make_meta.make.substitute) {
      foreach(substitution_pair; conf_make_meta.make.substitute) {
        line = line.replaceAll(
          regex("\b" ~ substitution_pair[Substitute.match]),
          substitution_pair[Substitute.markup]
        );
      }
    }
    return line;
  }
  char[] _doc_header_and_make_substitutions_fontface_(CMM)(
    char[]  line,
    CMM     conf_make_meta,
  ) {
    enum Substitute { match, markup, }
    if ( conf_make_meta.make.bold) {
      line = line.replaceAll(
        regex("\b" ~ conf_make_meta.make.bold[Substitute.match]),
        conf_make_meta.make.bold[Substitute.markup]
      );
    }
    if (conf_make_meta.make.emphasis) {
      line = line.replaceAll(
        regex("\b" ~ conf_make_meta.make.emphasis[Substitute.match]),
        conf_make_meta.make.emphasis[Substitute.markup]
      );
    }
    if (conf_make_meta.make.italics) {
      line = line.replaceAll(
        regex("\b" ~ conf_make_meta.make.italics[Substitute.match]),
        conf_make_meta.make.italics[Substitute.markup]
      );
    }
    return line;
  }
  void flow_txt_block_start()(
               char[]         line,
    return ref int[string]    obj_type_status,
    return ref uint[string]   dochas,
    return ref string[string] object_number_poem
  ) {
    static auto rgx = Rgx();
    if (auto m = line.matchFirst(rgx.block_curly_code_open)) {
      dochas["codeblock"]++;
      an_object["lang"]              = "";
      an_object["attrib"]            = (m["attrib"]) ? m["attrib"].to!string : "";
      an_object["syntax"]            = (m["syntax"]) ? m["syntax"].to!string : "";
      debug(codecurly) {                              // code (curly) open
        writefln(
          "* [code curly] %s",
          line
        );
      }
      obj_type_status["blocks"]     = TriState.on;
      obj_type_status["code"]       = TriState.on;
      obj_type_status["curly_code"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_curly_poem_open)) {
      dochas["poem"]++;
      an_object["syntax"]            = "";
      an_object["attrib"]            = (m["attrib"]) ? m["attrib"].to!string : "";
      an_object["lang"]              = (m["lang"]) ? m["lang"].to!string : "";
      debug(poem) {                              // poem (curly) open
        writefln(
          "* [poem curly] %s",
          line
        );
      }
      object_number_poem["start"]   = obj_cite_digits.object_number.to!string;
      obj_type_status["blocks"]     = TriState.on;
      obj_type_status["verse_new"]  = State.on;
      obj_type_status["poem"]       = TriState.on;
      obj_type_status["curly_poem"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_curly_group_open)) {
      dochas["group"]++;
      an_object["syntax"]            = "";
      an_object["attrib"]            = (m["attrib"]) ? m["attrib"].to!string : "";
      an_object["lang"]              = (m["lang"]) ? m["lang"].to!string : "";
      debug(group) {                             // group (curly) open
        writefln(
          "* [group curly] %s",
          line
        );
      }
      obj_type_status["blocks"]      = TriState.on;
      obj_type_status["group"]       = TriState.on;
      obj_type_status["curly_group"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_curly_block_open)) {
      dochas["block"]++;
      an_object["syntax"]            = "";
      an_object["attrib"]            = (m["attrib"]) ? m["attrib"].to!string : "";
      an_object["lang"]              = (m["lang"]) ? m["lang"].to!string : "";
      debug(block) {                             // block (curly) open
        writefln(
          "* [block curly] %s",
          line
        );
      }
      obj_type_status["blocks"]      = TriState.on;
      obj_type_status["block"]       = TriState.on;
      obj_type_status["curly_block"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_curly_quote_open)) {
      dochas["quote"]++;
      an_object["syntax"]            = "";
      an_object["attrib"]            = m["attrib"].to!string;
      an_object["lang"]              = m["lang"].to!string;
      debug(quote) {                             // quote (curly) open
        writefln(
          "* [quote curly] %s",
          line
        );
      }
      obj_type_status["blocks"]      = TriState.on;
      obj_type_status["quote"]       = TriState.on;
      obj_type_status["curly_quote"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_curly_table_open)) {           /+ curly table open +/
      debug(table) {                             // table (curly) open
        writefln(
          "* [table curly] %s",
          line
        );
      }
      dochas["table"] ++;
      an_object["table_head"]        = m["attrib"].to!string;
      an_object["block_type"]        = "curly";
      obj_type_status["blocks"]      = TriState.on;
      obj_type_status["table"]       = TriState.on;
      obj_type_status["curly_table"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_curly_table_special_markup)) { /+ table: special table block markup syntax! +/
      dochas["table"]++;
      an_object["table_head"]                       = m["attrib"].to!string;
      an_object["block_type"]                       = "special";
      obj_type_status["blocks"]                     = TriState.on;
      obj_type_status["table"]                      = TriState.on;
      obj_type_status["curly_table_special_markup"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_tic_code_open)) {
      dochas["codeblock"]++;
      an_object["lang"]              = "";
      an_object["attrib"]            = (m["attrib"]) ? m["attrib"].to!string : "";
      an_object["syntax"]            = (m["syntax"]) ? m["syntax"].to!string : "";
      debug(codetic) {                              // code (tic) open
        writefln(
          "* [code tic] %s",
          line
        );
      }
      obj_type_status["blocks"]   = TriState.on;
      obj_type_status["code"]     = TriState.on;
      obj_type_status["tic_code"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_tic_poem_open)) {
      dochas["poem"]++;
      an_object["syntax"]            = "";
      an_object["attrib"]            = (m["attrib"]) ? m["attrib"].to!string : "";
      an_object["lang"]              = (m["lang"]) ? m["lang"].to!string : "";
      debug(poem) {                              // poem (tic) open
        writefln(
          "* [poem tic] %s",
          line
        );
      }
      object_number_poem["start"]  = obj_cite_digits.object_number.to!string;
      obj_type_status["blocks"]    = TriState.on;
      obj_type_status["verse_new"] = State.on;
      obj_type_status["poem"]      = TriState.on;
      obj_type_status["tic_poem"]  = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_tic_group_open)) {
      dochas["group"]++;
      an_object["syntax"]            = "";
      an_object["attrib"]            = (m["attrib"]) ? m["attrib"].to!string : "";
      an_object["lang"]              = (m["lang"]) ? m["lang"].to!string : "";
      debug(group) {                             // group (tic) open
        writefln(
          "* [group tic] %s",
          line
        );
      }
      obj_type_status["blocks"]    = TriState.on;
      obj_type_status["group"]     = TriState.on;
      obj_type_status["tic_group"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_tic_block_open)) {
      dochas["block"]++;
      an_object["syntax"]            = "";
      an_object["attrib"]            = (m["attrib"]) ? m["attrib"].to!string : "";
      an_object["lang"]              = (m["lang"]) ? m["lang"].to!string : "";
      debug(block) {                             // block (tic) open
        writefln(
          "* [block tic] %s",
          line
        );
      }
      obj_type_status["blocks"]    = TriState.on;
      obj_type_status["block"]     = TriState.on;
      obj_type_status["tic_block"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_tic_quote_open)) {
      dochas["quote"]++;
      an_object["syntax"]            = "";
      an_object["attrib"]            = m["attrib"].to!string;
      an_object["lang"]              = m["lang"].to!string;
      debug(quote) {                             // quote (tic) open
        writefln(
          "* [quote tic] %s",
          line
        );
      }
      obj_type_status["blocks"]    = TriState.on;
      obj_type_status["quote"]     = TriState.on;
      obj_type_status["tic_quote"] = TriState.on;
    } else if (auto m = line.matchFirst(rgx.block_tic_table_open)) {             /+ tic table open +/
      debug(table) {                             // table (tic) open
        writefln(
          "* [table tic] %s",
          line
        );
      }
      dochas["table"] ++;
      an_object["table_head"]      = m["attrib"].to!string;
      an_object["block_type"]      = "tic";
      obj_type_status["blocks"]    = TriState.on;
      obj_type_status["table"]     = TriState.on;
      obj_type_status["tic_table"] = TriState.on;
    }
  }
  string[string] flow_txt_block_quote()(
               char[]          line,
               string[string]  an_object,
    return ref int[string]     obj_type_status
  ) {
    static auto rgx = Rgx();
    if (obj_type_status["curly_quote"] == TriState.on) {
      if (line.matchFirst(rgx.block_curly_quote_close)) {
        debug(quote) {                              // quote (curly) close
          writeln(line);
        }
        an_object[an_object_key]       = an_object[an_object_key].stripRight;
        obj_type_status["blocks"]      = TriState.closing;
        obj_type_status["quote"]       = TriState.closing;
        obj_type_status["curly_quote"] = TriState.off;
      } else {
        debug(quote) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string)
      }
    } else if (obj_type_status["tic_quote"] == TriState.on) {
      if (line.matchFirst(rgx.block_tic_close)) {
        debug(quote) {                              // quote (tic) close
          writeln(line);
        }
        an_object[an_object_key]     = an_object[an_object_key].stripRight;
        obj_type_status["blocks"]    = TriState.closing;
        obj_type_status["quote"]     = TriState.closing;
        obj_type_status["tic_quote"] = TriState.off;
      } else {
        debug(quote) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string)
      }
    }
    return an_object;
  }
  string[string] flow_txt_block_group()(
               char[]          line,
               string[string]  an_object,
    return ref int[string]     obj_type_status
  ) {
    static auto rgx = Rgx();
    if (obj_type_status["curly_group"] == State.on) {
      if (line.matchFirst(rgx.block_curly_group_close)) {
        debug(group) {
          writeln(line);
        }
        an_object[an_object_key]       = an_object[an_object_key].stripRight;
        obj_type_status["blocks"]      = TriState.closing;
        obj_type_status["group"]       = TriState.closing;
        obj_type_status["curly_group"] = TriState.off;
      } else {
        debug(group) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build group array (or string)
      }
    } else if (obj_type_status["tic_group"] == TriState.on) {
      if (line.matchFirst(rgx.block_tic_close)) {
        debug(group) {
          writeln(line);
        }
        an_object[an_object_key]     = an_object[an_object_key].stripRight;
        obj_type_status["blocks"]    = TriState.closing;
        obj_type_status["group"]     = TriState.closing;
        obj_type_status["tic_group"] = TriState.off;
      } else {
        debug(group) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build group array (or string)
      }
    }
    return an_object;
  }
  string[string] flow_txt_block_block()(
               char[]          line,
               string[string]  an_object,
    return ref int[string]     obj_type_status
  ) {
    static auto rgx = Rgx();
    if (obj_type_status["curly_block"] == TriState.on) {
      if (line.matchFirst(rgx.block_curly_block_close)) {
        debug(block) {                             // block (curly) close
          writeln(line);
        }
        an_object[an_object_key]       = an_object[an_object_key].stripRight;
        obj_type_status["blocks"]      = TriState.closing;
        obj_type_status["block"]       = TriState.closing;
        obj_type_status["curly_block"] = TriState.off;
      } else {
        debug(block) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build block array (or string)
      }
    } else if (obj_type_status["tic_block"] == TriState.on) {
      if (line.matchFirst(rgx.block_tic_close)) {
        debug(block) {
          writeln(line);
        }
        an_object[an_object_key]     = an_object[an_object_key].stripRight;
        obj_type_status["blocks"]    = TriState.closing;
        obj_type_status["block"]     = TriState.closing;
        obj_type_status["tic_block"] = TriState.off;
      } else {
        debug(block) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build block array (or string)
      }
    }
    return an_object;
  }
  string[string]  flow_txt_block_poem(CMM)(
               char[]          line,
               string[string]  an_object,
    return ref int[string]     obj_type_status,
    return ref int             cntr,
               string[string]  object_number_poem,
               CMM             conf_make_meta,
               string[string]  tag_in_seg,
  ) {
    static auto rgx = Rgx();
    if (obj_type_status["curly_poem"] == TriState.on) {
      if (line.matchFirst(rgx.block_curly_poem_close)) {
        if (an_object_key in an_object
        || processing.length > 0) {
          an_object[an_object_key]                    = "";
          debug(poem) {
            writefln(
              "* [poem curly] %s",
              line
            );
          }
          if (processing.length > 0) {
            an_object[an_object_key] = processing["verse"];
          }
          debug(poem) {
            writeln(__LINE__);
            writefln(
              "* %s %s",
              obj_cite_digits.object_number,
              line
            );
          }
          if (an_object.length > 0) {
            debug(poem) {                             // poem (curly) close
              writeln(
                obj_cite_digits.object_number,
                an_object[an_object_key]
              );
            }
            an_object["is"]                           = "verse";
            auto substantive_obj_misc_tuple
              = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc);
            an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
            anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag];
            comp_obj_block                                 = comp_obj_block.init;
            comp_obj_block.metainfo.is_of_part             = "body";
            comp_obj_block.metainfo.is_of_section          = "body";
            comp_obj_block.metainfo.is_of_type             = "block";
            comp_obj_block.metainfo.is_a                   = "verse";
            comp_obj_block.metainfo.ocn                    = obj_cite_digits.object_number;
            comp_obj_block.metainfo.identifier             = obj_cite_digits.identifier;
            comp_obj_block.metainfo.object_number_off      = obj_cite_digits.off;
            comp_obj_block.metainfo.o_n_book_index         = obj_cite_digits.bkidx;
            comp_obj_block.metainfo.object_number_type     = obj_cite_digits.type;
            comp_obj_block.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"];
            comp_obj_block.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1_to_4"];
            comp_obj_block.text                            = an_object["substantive"];
            comp_obj_block.has.inline_notes_reg            = substantive_obj_misc_tuple[sObj.notes_reg];
            comp_obj_block.has.inline_notes_star           = substantive_obj_misc_tuple[sObj.notes_star];
            comp_obj_block.has.inline_links                = substantive_obj_misc_tuple[sObj.links];
            the_document_body_section                      ~= comp_obj_block;
            tag_assoc                                      = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
          }
          object_reset(an_object);
          processing.remove("verse");
          ++cntr;
        }
        object_number_poem["end"]     = obj_cite_digits.object_number.to!string;
        obj_type_status["blocks"]     = TriState.closing;
        obj_type_status["poem"]       = TriState.closing;
        obj_type_status["curly_poem"] = TriState.off;
      } else {
        processing["verse"] ~= line ~= "\n";
        if (obj_type_status["verse_new"] == State.on) {
          obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]);
          obj_type_status["verse_new"] = State.off;
        } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) {
          processing["verse"] = processing["verse"].stripRight;
          verse_line = TriState.off;
          obj_type_status["verse_new"] = State.on;
        }
        if (obj_type_status["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_digits.object_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,
            tag_in_seg,
            lev_anchor_tag,
            tag_assoc,
            obj_cite_digits,
            cntr,
            heading_ptr-1,
            an_object["is"]
          );
          auto substantive_obj_misc_tuple
            = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc);
          an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
          anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag];
          comp_obj_block                                 = comp_obj_block.init;
          comp_obj_block.metainfo.is_of_part             = "body";
          comp_obj_block.metainfo.is_of_section          = "body";
          comp_obj_block.metainfo.is_of_type             = "block";
          comp_obj_block.metainfo.is_a                   = "verse";
          comp_obj_block.metainfo.ocn                    = obj_cite_digits.object_number;
          comp_obj_block.metainfo.identifier             = obj_cite_digits.identifier;
          comp_obj_block.metainfo.object_number_off      = obj_cite_digits.off;
          comp_obj_block.metainfo.o_n_book_index         = obj_cite_digits.bkidx;
          comp_obj_block.metainfo.object_number_type     = obj_cite_digits.type;
          comp_obj_block.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"];
          comp_obj_block.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1_to_4"];
          comp_obj_block.text                            = an_object["substantive"];
          comp_obj_block.has.inline_notes_reg            = substantive_obj_misc_tuple[sObj.notes_reg];
          comp_obj_block.has.inline_notes_star           = substantive_obj_misc_tuple[sObj.notes_star];
          comp_obj_block.has.inline_links                = substantive_obj_misc_tuple[sObj.links];
          the_document_body_section                      ~= comp_obj_block;
          tag_assoc                                      = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
          object_reset(an_object);
          processing.remove("verse");
          ++cntr;
        }
      }
    } else if (obj_type_status["tic_poem"] == TriState.on) {
      if (auto m = line.matchFirst(rgx.block_tic_close)) { // tic_poem_close
        an_object[an_object_key]="verse";
        debug(poem) {
          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_digits.object_number, line);
          }
          processing.remove("verse");
          an_object["is"]                                = "verse";
          auto substantive_obj_misc_tuple
            = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc);
          an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
          anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag];
          comp_obj_block                                 = comp_obj_block.init;
          comp_obj_block.metainfo.is_of_part             = "body";
          comp_obj_block.metainfo.is_of_section          = "body";
          comp_obj_block.metainfo.is_of_type             = "block";
          comp_obj_block.metainfo.is_a                   = "verse";
          comp_obj_block.metainfo.ocn                    = obj_cite_digits.object_number;
          comp_obj_block.metainfo.identifier             = obj_cite_digits.identifier;
          comp_obj_block.metainfo.object_number_off      = obj_cite_digits.off;
          comp_obj_block.metainfo.o_n_book_index         = obj_cite_digits.bkidx;
          comp_obj_block.metainfo.object_number_type     = obj_cite_digits.type;
          comp_obj_block.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"];
          comp_obj_block.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1_to_4"];
          comp_obj_block.text                            = an_object["substantive"];
          comp_obj_block.has.inline_notes_reg            = substantive_obj_misc_tuple[sObj.notes_reg];
          comp_obj_block.has.inline_notes_star           = substantive_obj_misc_tuple[sObj.notes_star];
          comp_obj_block.has.inline_links                = substantive_obj_misc_tuple[sObj.links];
          the_document_body_section                      ~= comp_obj_block;
          tag_assoc                                      = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
          object_number_poem["end"]                      = obj_cite_digits.object_number.to!string;
          object_reset(an_object);
          processing.remove("verse");
          ++cntr;
        }
        obj_type_status["blocks"]   = TriState.closing;
        obj_type_status["poem"]     = TriState.closing;
        obj_type_status["tic_poem"] = TriState.off;
      } else {
        processing["verse"] ~= line ~= "\n";
        if (obj_type_status["verse_new"] == State.on) {
          obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]);
          obj_type_status["verse_new"] = State.off;
        } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) {
          processing["verse"] = processing["verse"].stripRight;
          obj_type_status["verse_new"] = State.on;
          verse_line = TriState.off;
        }
        if (obj_type_status["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_digits.object_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,
              tag_in_seg,
              lev_anchor_tag,
              tag_assoc,
              obj_cite_digits,
              cntr,
              heading_ptr-1,
              an_object["is"]
            );
          auto substantive_obj_misc_tuple
            = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc);
          an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
          anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag];
          comp_obj_block                                 = comp_obj_block.init;
          comp_obj_block.metainfo.is_of_part             = "body";
          comp_obj_block.metainfo.is_of_section          = "body";
          comp_obj_block.metainfo.is_of_type             = "block";
          comp_obj_block.metainfo.is_a                   = "verse";
          comp_obj_block.metainfo.ocn                    = obj_cite_digits.object_number;
          comp_obj_block.metainfo.identifier             = obj_cite_digits.identifier;
          comp_obj_block.metainfo.object_number_off      = obj_cite_digits.off;
          comp_obj_block.metainfo.o_n_book_index         = obj_cite_digits.bkidx;
          comp_obj_block.metainfo.object_number_type     = obj_cite_digits.type;
          comp_obj_block.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"];
          comp_obj_block.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1_to_4"];
          comp_obj_block.text                            = an_object["substantive"];
          comp_obj_block.has.inline_notes_reg            = substantive_obj_misc_tuple[sObj.notes_reg];
          comp_obj_block.has.inline_notes_star           = substantive_obj_misc_tuple[sObj.notes_star];
          comp_obj_block.has.inline_links                = substantive_obj_misc_tuple[sObj.links];
          the_document_body_section                      ~= comp_obj_block;
          tag_assoc                                      = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
          object_reset(an_object);
          processing.remove("verse");
          ++cntr;
        }
      }
    }
    return an_object;
  }
  void flow_txt_block_code()(
               char[]          line,
    return ref string[string]  an_object,
    return ref int[string]     obj_type_status
  ) {
    static auto rgx = Rgx();
    if (obj_type_status["curly_code"] == TriState.on) {
      if (line.matchFirst(rgx.block_curly_code_close)) {
        debug(codecurly) {                                    // code (curly) close
          writeln(line);
        }
        an_object[an_object_key] = an_object[an_object_key]
          .replaceFirst(rgx.newline_eol_delimiter_only, "")
          .stripRight;
        obj_type_status["blocks"]     = TriState.closing;
        obj_type_status["code"]       = TriState.closing;
        obj_type_status["curly_code"] = TriState.off;
      } else {
        debug(codecurly) {                                    // code (curly) line
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";        // code (curly) line
      }
    } else if (obj_type_status["tic_code"] == TriState.on) {
      if (line.matchFirst(rgx.block_tic_close)) {
        debug(codetic) {                                    // code (tic) close
          writeln(line);
        }
        an_object[an_object_key] = an_object[an_object_key]
          .replaceFirst(rgx.newline_eol_delimiter_only, "")
          .stripRight;
        obj_type_status["blocks"]   = TriState.closing;
        obj_type_status["code"]     = TriState.closing;
        obj_type_status["tic_code"] = TriState.off;
      } else {
        debug(codetic) {                                    // code (tic) line
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";        // code (tic) line
      }
    }
  }
  string[string] flow_txt_block_table(CMM)(
               char[]          line,
               string[string]  an_object,
    return ref int[string]     obj_type_status,
    return ref CMM             conf_make_meta,
  ) {
    static auto rgx = Rgx();
    if (obj_type_status["curly_table"] == TriState.on) {
      if (line.matchFirst(rgx.block_curly_table_close)) {
        debug(table) {                           // table (curly) close
          writeln(line);
        }
        obj_type_status["blocks"]      = TriState.closing;
        obj_type_status["table"]       = TriState.closing;
        obj_type_status["curly_table"] = TriState.off;
      } else {
        debug(table) {                           // table
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";           // build table array (or string)
      }
    } else if (obj_type_status["curly_table_special_markup"] == TriState.on) {
      if (line.empty) {
        obj_type_status["blocks"]                     = TriState.off;
        obj_type_status["table"]                      = TriState.off;
        obj_type_status["curly_table_special_markup"] = TriState.off;
        line.flow_table_closed_make_special_notation_table_(
          an_object,
          the_document_body_section,
          obj_cite_digits,
          comp_obj_heading,
          cntr,
          obj_type_status,
          conf_make_meta,
        );
      } else {
        debug(table) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";
      }
    } else if (obj_type_status["tic_table"] == TriState.on) {
      if (line.matchFirst(rgx.block_tic_close)) {
        debug(table) {                           // table (tic) close
          writeln(line);
        }
        obj_type_status["blocks"]    = TriState.closing;
        obj_type_status["table"]     = TriState.closing;
        obj_type_status["tic_table"] = TriState.off;
      } else {
        debug(table) {                           // table
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";           // build table array (or string)
      }
    }
    return an_object;
  }
  final string biblio_tag_map()(string abr) {
    auto btm = [
      "au"           : "author_raw",
      "ed"           : "editor_raw",
      "ti"           : "fulltitle",
      "lng"          : "language",
      "jo"           : "journal",
      "vol"          : "volume",
      "edn"          : "edition",
      "yr"           : "year",
      "pl"           : "place",
      "pb"           : "publisher",
      "pub"          : "publisher",
      "pg"           : "pages",
      "pgs"          : "pages",
      "sn"           : "short_name"
    ];
    return btm[abr];
  }
  void flow_txt_block_biblio(
    char[]                 line,
    return ref int[string] obj_type_status,
    return ref int         bib_entry,
    return ref string      biblio_entry_str_json,
    return ref string[]    biblio_arr_json
  ) {
    mixin DocReformBiblio;
    auto jsn = BibJsnStr();
    static auto rgx = Rgx();
    if (line.matchFirst(rgx.heading_biblio)
      && obj_type_status["para"]  != State.on
      && obj_type_status["group"] != State.on
      && obj_type_status["block"] != State.on
      && obj_type_status["poem"]  != State.on
      && obj_type_status["table"] != State.on
      && obj_type_status["quote"] != State.on
    ) {
      obj_type_status["glossary_section"] = State.off;
      obj_type_status["biblio_section"]   = TriState.on;
      obj_type_status["blurb_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 (line.matchFirst(rgx.biblio_tags)) {
      debug(biblioblock) {
        writeln(line);
      }
      auto bt = line.match(rgx.biblio_tags);
      bib_entry = State.off;
      st = bt.captures[1].to!string;
      auto header_tag_value=(bt.captures[2]).to!string;
      JSONValue j = parseJSON(biblio_entry_str_json);
      biblio_tag_name = (st.match(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"]
         = header_tag_value.split(rgx.arr_delimiter);
        string tmp;
        biblioAuthorLoop:
        foreach (au; j["author_arr"].array) {
          if (auto x = au.str.match(rgx.name_delimiter)) {
            tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", ";
          } else {
            tmp ~= au.str;
          }
        }
        tmp = tmp.replace(rgx.trailing_comma, "");
        j["author"].str = tmp;
        goto default;
      case "editor_raw": // editor_arr editor (fn sn)
        j["editor_arr"]
          = header_tag_value.split(rgx.arr_delimiter);
        string tmp;
        biblioEditorLoop:
        foreach (ed; j["editor_arr"].array) {
          if (auto x = ed.str.match(rgx.name_delimiter)) {
            tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", ";
          } else {
            tmp ~= ed.str;
          }
        }
        tmp = tmp.replace(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 (line.match(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="";
    }
  }
  void flow_table_closed_make_special_notation_table_(N,CMM)(
               char[]                line,
    return ref string[string]        an_object,
    return ref ObjGenericComposite[] the_document_body_section,
    return ref N                     obj_cite_digits,
    return ref ObjGenericComposite   _comp_obj_heading,
    return ref int                   cntr,
    return ref int[string]           obj_type_status,
    CMM                              conf_make_meta
  ) {
    comp_obj_block = comp_obj_block.init;
    obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]);
    auto comp_obj_location
      = node_construct.node_location_emitter(
        content_non_header,
        tag_in_seg,
        lev_anchor_tag,
        tag_assoc,
        obj_cite_digits,
        cntr,
        heading_ptr-1,
        "table"
      );
    an_object["is"] = "table";
    auto substantive_obj_misc_tuple
      = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, "body_nugget", conf_make_meta, No._new_doc);
    an_object["substantive"]                       = substantive_obj_misc_tuple[sObj.content];
    comp_obj_block.metainfo.ocn                    = obj_cite_digits.object_number;
    comp_obj_block.metainfo.identifier             = obj_cite_digits.identifier;
    comp_obj_block.metainfo.object_number_off      = obj_cite_digits.off;
    comp_obj_block.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"];
    comp_obj_block.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1_to_4"];
    comp_obj_block.metainfo.o_n_book_index         = obj_cite_digits.bkidx;
    comp_obj_block.metainfo.object_number_type     = obj_cite_digits.type;
    comp_obj_block                                 = comp_obj_block.flow_table_instructions(an_object["table_head"]);
    comp_obj_block                                 = comp_obj_block.flow_table_substantive_munge_special(an_object["substantive"]);
    the_document_body_section                      ~= comp_obj_block;
    object_reset(an_object);
    processing.remove("verse");
    ++cntr;
  }
  string[string] flow_block_flag_line_empty_(B,N,CMM,Ts)(
               char[]                   line,
               string[string]           an_object,
               B                        bookindex_extract_hash,
    return ref ObjGenericComposite[]    the_document_body_section,
    return ref string[][string][string] bookindex_unordered_hashes,
    return ref N                        obj_cite_digits,
    return ref ObjGenericComposite      _comp_obj_heading,
    return ref int                      cntr,
    return ref int[string]              obj_type_status,
    string[string]                      object_number_poem,
    CMM                                 conf_make_meta,
    Ts                                  tag_in_seg,
  ) {
    assert(
      line.empty,
      "\nline should be empty:\n  \""
      ~ line ~ "\""
    );
    assert(
      (obj_type_status["blocks"] == TriState.closing),
      "code block status: closed"
    );
    assertions_flag_types_block_status_none_or_closed(obj_type_status);
    if (obj_type_status["quote"] == TriState.closing) {
      obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]);
      an_object["bookindex_nugget"]
        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes
        = bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_digits,
          tag_in_seg
        );
      an_object["is"] = "quote";
      auto comp_obj_location
        = node_construct.node_location_emitter(
          content_non_header,
          tag_in_seg,
          lev_anchor_tag,
          tag_assoc,
          obj_cite_digits,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      auto substantive_obj_misc_tuple
        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc);
      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
      anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag];
      comp_obj_block                                 = comp_obj_block.init;
      comp_obj_block.metainfo.is_of_part             = "body";
      comp_obj_block.metainfo.is_of_section          = "body";
      comp_obj_block.metainfo.is_of_type             = "block";
      comp_obj_block.metainfo.is_a                   = "quote";
      comp_obj_block.metainfo.ocn                    = obj_cite_digits.object_number;
      comp_obj_block.metainfo.identifier             = obj_cite_digits.identifier;
      comp_obj_block.metainfo.object_number_off      = obj_cite_digits.off;
      comp_obj_block.metainfo.o_n_book_index         = obj_cite_digits.bkidx;
      comp_obj_block.metainfo.object_number_type     = obj_cite_digit_type;
      comp_obj_block.metainfo.lang                   = an_object["lang"];
      comp_obj_block.metainfo.attrib                 = an_object["attrib"];
      comp_obj_block.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"];
      comp_obj_block.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1_to_4"];
      comp_obj_block.text                            = an_object["substantive"];
      comp_obj_block.has.inline_notes_reg            = substantive_obj_misc_tuple[sObj.notes_reg];
      comp_obj_block.has.inline_notes_star           = substantive_obj_misc_tuple[sObj.notes_star];
      comp_obj_block.has.inline_links                = substantive_obj_misc_tuple[sObj.links];
      the_document_body_section                      ~= comp_obj_block;
      tag_assoc                                      = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
      obj_type_status["blocks"]                      = TriState.off;
      obj_type_status["quote"]                       = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
      ++cntr;
    } else if (obj_type_status["group"] == TriState.closing) {
      obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]);
      an_object["bookindex_nugget"]
        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes
        = bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_digits,
          tag_in_seg
        );
      an_object["is"] = "group";
      auto comp_obj_location
        = node_construct.node_location_emitter(
          content_non_header,
          tag_in_seg,
          lev_anchor_tag,
          tag_assoc,
          obj_cite_digits,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      auto substantive_obj_misc_tuple
        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc);
      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
      anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag];
      comp_obj_block                                 = comp_obj_block.init;
      comp_obj_block.metainfo.is_of_part             = "body";
      comp_obj_block.metainfo.is_of_section          = "body";
      comp_obj_block.metainfo.is_of_type             = "block";
      comp_obj_block.metainfo.is_a                   = "group";
      comp_obj_block.metainfo.ocn                    = obj_cite_digits.object_number;
      comp_obj_block.metainfo.identifier             = obj_cite_digits.identifier;
      comp_obj_block.metainfo.object_number_off      = obj_cite_digits.off;
      comp_obj_block.metainfo.o_n_book_index         = obj_cite_digits.bkidx;
      comp_obj_block.metainfo.object_number_type     = obj_cite_digits.type;
      comp_obj_block.metainfo.lang                   = an_object["lang"];
      comp_obj_block.metainfo.attrib                 = an_object["attrib"];
      comp_obj_block.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"];
      comp_obj_block.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1_to_4"];
      comp_obj_block.text                            = an_object["substantive"];
      comp_obj_block.has.inline_notes_reg            = substantive_obj_misc_tuple[sObj.notes_reg];
      comp_obj_block.has.inline_notes_star           = substantive_obj_misc_tuple[sObj.notes_star];
      comp_obj_block.has.inline_links                = substantive_obj_misc_tuple[sObj.links];
      the_document_body_section                      ~= comp_obj_block;
      tag_assoc                                      = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc);
      obj_type_status["blocks"]                      = TriState.off;
      obj_type_status["group"]                       = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
      ++cntr;
    } else if (obj_type_status["block"] == TriState.closing) {
      obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]);
      an_object["bookindex_nugget"]
        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes
        = bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_digits,
          tag_in_seg
        );
      an_object["is"] = "block";
      auto comp_obj_location
        = node_construct.node_location_emitter(
          content_non_header,
          tag_in_seg,
          lev_anchor_tag,
          tag_assoc,
          obj_cite_digits,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      auto substantive_obj_misc_tuple
        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc);
      an_object["substantive"]                       = substantive_obj_misc_tuple[sObj.content];
      // anchor_tag                                  = substantive_obj_misc_tuple[sObj.anchor_tag];
      comp_obj_block                                 = comp_obj_block.init;
      comp_obj_block.metainfo.is_of_part             = "body";
      comp_obj_block.metainfo.is_of_section          = "body";
      comp_obj_block.metainfo.is_of_type             = "block";
      comp_obj_block.metainfo.is_a                   = "block";
      comp_obj_block.metainfo.ocn                    = obj_cite_digits.object_number;
      comp_obj_block.metainfo.identifier             = obj_cite_digits.identifier;
      comp_obj_block.metainfo.object_number_off      = obj_cite_digits.off;
      comp_obj_block.metainfo.o_n_book_index         = obj_cite_digits.bkidx;
      comp_obj_block.metainfo.object_number_type     = obj_cite_digit_type;
      comp_obj_block.metainfo.lang                   = an_object["lang"];
      comp_obj_block.metainfo.attrib                 = an_object["attrib"];
      comp_obj_block.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"];
      comp_obj_block.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1_to_4"];
      comp_obj_block.text                            = an_object["substantive"];
      comp_obj_block.has.inline_notes_reg            = substantive_obj_misc_tuple[sObj.notes_reg];
      comp_obj_block.has.inline_notes_star           = substantive_obj_misc_tuple[sObj.notes_star];
      comp_obj_block.has.inline_links                = substantive_obj_misc_tuple[sObj.links];
      the_document_body_section                      ~= comp_obj_block;
      obj_type_status["blocks"]                      = TriState.off;
      obj_type_status["block"]                       = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
      ++cntr;
    } else if (obj_type_status["poem"] == TriState.closing) {
      an_object["bookindex_nugget"]
        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes
        = bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_digits,
          tag_in_seg
        );
      an_object["is"]                           = "verse";
      auto comp_obj_location
        = node_construct.node_location_emitter(
          content_non_header,
          tag_in_seg,
          lev_anchor_tag,
          tag_assoc,
          obj_cite_digits,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      comp_obj_poem_ocn                               = comp_obj_poem_ocn.init;
      comp_obj_poem_ocn.metainfo.is_of_part           = "body";
      comp_obj_poem_ocn.metainfo.is_of_section        = "body";
      comp_obj_poem_ocn.metainfo.is_of_type           = "block";
      comp_obj_poem_ocn.metainfo.is_a                 = "poem";
      comp_obj_poem_ocn.metainfo.ocn                  = obj_cite_digits.object_number;
      comp_obj_poem_ocn.metainfo.identifier           = obj_cite_digits.identifier;
      comp_obj_poem_ocn.metainfo.object_number_off    = obj_cite_digits.off;
      comp_obj_poem_ocn.metainfo.o_n_book_index       = obj_cite_digits.bkidx;
      comp_obj_poem_ocn.metainfo.object_number_type   = obj_cite_digits.type;
      comp_obj_poem_ocn.text                          = "";
      the_document_body_section                       ~= comp_obj_poem_ocn;
      obj_type_status["blocks"]                       = TriState.off;
      obj_type_status["poem"]                         = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
    } else if (obj_type_status["code"] == TriState.closing) {
      obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]);
      an_object["bookindex_nugget"]
        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes
        = bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_digits,
          tag_in_seg
        );
      an_object["is"] = "code";
      auto comp_obj_location
        = node_construct.node_location_emitter(
          content_non_header,
          tag_in_seg,
          lev_anchor_tag,
          tag_assoc,
          obj_cite_digits,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      auto substantive_obj_misc_tuple
        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc);
      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
      anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag];
      comp_obj_code                                 = comp_obj_code.init;
      comp_obj_code.metainfo.is_of_part             = "body";
      comp_obj_code.metainfo.is_of_section          = "body";
      comp_obj_code.metainfo.is_of_type             = "block";
      comp_obj_code.metainfo.is_a                   = "code";
      comp_obj_code.metainfo.ocn                    = obj_cite_digits.object_number;
      comp_obj_code.metainfo.identifier             = obj_cite_digits.identifier;
      comp_obj_code.metainfo.object_number_off      = obj_cite_digits.off;
      comp_obj_code.metainfo.o_n_book_index         = obj_cite_digits.bkidx;
      comp_obj_code.metainfo.object_number_type     = obj_cite_digits.type;
      comp_obj_code.metainfo.syntax                 = an_object["syntax"];
      comp_obj_code.metainfo.attrib                 = an_object["attrib"];
      comp_obj_code.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"];
      comp_obj_code.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1_to_4"];
      comp_obj_code.text                            = an_object["substantive"];
      comp_obj_code.has.inline_notes_reg            = substantive_obj_misc_tuple[sObj.notes_reg];
      comp_obj_code.has.inline_notes_star           = substantive_obj_misc_tuple[sObj.notes_star];
      comp_obj_code.has.inline_links                = substantive_obj_misc_tuple[sObj.links];
      the_document_body_section                     ~= comp_obj_code;
      obj_type_status["blocks"]                     = TriState.off;
      obj_type_status["code"]                       = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
      ++cntr;
    } else if (obj_type_status["table"] == TriState.closing) {
      comp_obj_block = comp_obj_block.init;
      obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]);
      an_object["bookindex_nugget"]
        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes
        = bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_digits,
          tag_in_seg
        );
      an_object["is"] = "table";
      auto comp_obj_location
        = node_construct.node_location_emitter(
          content_non_header,
          tag_in_seg,
          lev_anchor_tag,
          tag_assoc,
          obj_cite_digits,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      auto substantive_obj_misc_tuple
        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc);
      an_object["substantive"]                       = substantive_obj_misc_tuple[sObj.content];
      comp_obj_block                                 = comp_obj_block.init;
      comp_obj_block.metainfo.ocn                    = obj_cite_digits.object_number;
      comp_obj_block.metainfo.identifier             = obj_cite_digits.identifier;
      comp_obj_block.metainfo.object_number_off      = obj_cite_digits.off;
      comp_obj_block.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"];
      comp_obj_block.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1_to_4"];
      comp_obj_block.metainfo.o_n_book_index         = obj_cite_digits.bkidx;
      comp_obj_block.metainfo.object_number_type     = obj_cite_digits.type;
      comp_obj_block                                 = comp_obj_block.flow_table_instructions(an_object["table_head"]);
      comp_obj_block                                 = comp_obj_block.flow_table_substantive_munge(an_object["substantive"]);
      the_document_body_section                      ~= comp_obj_block;
      obj_type_status["blocks"]                      = TriState.off;
      obj_type_status["table"]                       = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
      ++cntr;
    }
    return an_object;
  }
  string[string] flow_book_index_(B)(
               char[]          line,
               string[string]  an_object,
    return ref string          book_idx_tmp,
    return ref int[string]     obj_type_status,
               B               opt_action,
  ) {
    static auto rgx = Rgx();
    if (auto m = line.match(rgx.book_index)) {                                   /+ match book_index +/
      debug(bookindexmatch) {
        writefln(
          "* [bookindex] %s\n",
          m["bookindex"].to!string,
        );
      }
      an_object["bookindex_nugget"] = m.captures[1].to!string;
    } else if (auto m = line.match(rgx.book_index_open))  {                      /+ match open book_index +/
      obj_type_status["book_index"] = State.on;
      if (opt_action.backmatter && opt_action.section_bookindex) {
        book_idx_tmp = m.captures[1].to!string;
        debug(bookindexmatch) {
          writefln(
            "* [bookindex] %s\n",
            book_idx_tmp,
          );
        }
      }
    } else if (obj_type_status["book_index"] == State.on )  {                    /+ book_index flag set +/
      if (auto m = line.match(rgx.book_index_close))  {
        obj_type_status["book_index"] = State.off;
        if (opt_action.backmatter
        && opt_action.section_bookindex) {
          an_object["bookindex_nugget"] = book_idx_tmp ~ m.captures[1].to!string;
          debug(bookindexmatch) {
            writefln(
              "* [bookindex] %s\n",
              book_idx_tmp,
            );
          }
        }
        book_idx_tmp = "";
      } else {
        if (opt_action.backmatter
        && opt_action.section_bookindex) {
          book_idx_tmp ~= line;
        }
      }
    }
    return an_object;
  }
  string[string] flow_heading_found_()(
               char[]                line,
               string[string]        heading_match_str,
               string[]              _make_unmarked_headings,
    return ref Regex!(char)[string]  heading_match_rgx,
    return ref int[string]           obj_type_status
  ) {
    static auto rgx = Rgx();
    if ((_make_unmarked_headings.length > 2)
    && (obj_type_status["make_headings"] == State.off)) {                        /+ headings found +/
      debug(headingsfound) {
        writeln(_make_unmarked_headings);
      }
      debug(headingsfound) {
        writeln(_make_unmarked_headings.length);
        writeln(_make_unmarked_headings);
      }
      switch (_make_unmarked_headings.length) {
      case 7 :
        if (!empty(_make_unmarked_headings[6])) {
          heading_match_str["h_4"]
            = "^(" ~ _make_unmarked_headings[6].to!string ~ ")";
          heading_match_rgx["h_4"]
            = regex(heading_match_str["h_4"]);
        }
        goto case;
      case 6 :
        if (!empty(_make_unmarked_headings[5])) {
          heading_match_str["h_3"]
            = "^(" ~ _make_unmarked_headings[5].to!string ~ ")";
          heading_match_rgx["h_3"]
            = regex(heading_match_str["h_3"]);
        }
        goto case;
      case 5 :
        if (!empty(_make_unmarked_headings[4])) {
          heading_match_str["h_2"]
            = "^(" ~ _make_unmarked_headings[4].to!string ~ ")";
          heading_match_rgx["h_2"]
            = regex(heading_match_str["h_2"]);
        }
        goto case;
      case 4 :
        if (!empty(_make_unmarked_headings[3])) {
          heading_match_str["h_1"]
            = "^(" ~ _make_unmarked_headings[3].to!string ~ ")";
          heading_match_rgx["h_1"]
            = regex(heading_match_str["h_1"]);
        }
        goto case;
      case 3 :
        if (!empty(_make_unmarked_headings[2])) {
          heading_match_str["h_D"]
            = "^(" ~ _make_unmarked_headings[2].to!string ~ ")";
          heading_match_rgx["h_D"]
            = regex(heading_match_str["h_D"]);
        }
        goto case;
      case 2 :
        if (!empty(_make_unmarked_headings[1])) {
          heading_match_str["h_C"]
            = "^(" ~ _make_unmarked_headings[1].to!string ~ ")";
          heading_match_rgx["h_C"]
            = regex(heading_match_str["h_C"]);
        }
        goto case;
      case 1 :
        if (!empty(_make_unmarked_headings[0])) {
          heading_match_str["h_B"]
            = "^(" ~ _make_unmarked_headings[0].to!string ~ ")";
          heading_match_rgx["h_B"]
            = regex(heading_match_str["h_B"]);
        }
        break;
      default:
        break;
      }
      obj_type_status["make_headings"] = State.on;
    }
    return heading_match_str;
  }
  char[] flow_heading_make_set_()(
               char[]                line,
               int[string]           line_occur,
    return ref Regex!(char)[string]  heading_match_rgx,
    return ref int[string]           obj_type_status
  ) {
    if ((obj_type_status["make_headings"] == State.on)
    && ((line_occur["para"] == State.off)
    && (line_occur["heading"] == State.off))
    && ((obj_type_status["para"] == State.off)
    && (obj_type_status["heading"] == State.off))) {                             /+ heading make set +/
      if (line.matchFirst(heading_match_rgx["h_B"])) {
        line = "B~ " ~ line;
        debug(headingsfound) {
          writeln(line);
        }
      }
      if (line.matchFirst(heading_match_rgx["h_C"])) {
        line = "C~ " ~ line;
        debug(headingsfound) {
          writeln(line);
        }
      }
      if (line.matchFirst(heading_match_rgx["h_D"])) {
        line = "D~ " ~ line;
        debug(headingsfound) {
          writeln(line);
        }
      }
      if (line.matchFirst(heading_match_rgx["h_1"])) {
        line = "1~ " ~ line;
        debug(headingsfound) {
          writeln(line);
        }
      }
      if (line.matchFirst(heading_match_rgx["h_2"])) {
        line = "2~ " ~ line;
        debug(headingsfound) {
          writeln(line);
        }
      }
      if (line.matchFirst(heading_match_rgx["h_3"])) {
        line = "3~ " ~ line;
        debug(headingsfound) {
          writeln(line);
        }
      }
      if (line.matchFirst(heading_match_rgx["h_4"])) {
        line = "4~ " ~ line;
        debug(headingsfound) {
          writeln(line);
        }
      }
    }
    return line;
  }
  string[string] flow_heading_matched_(CMM)(
               char[]          line,
               string[string]  an_object,
    return ref int[string]     line_occur,
    return ref string          an_object_key,
    return ref int[string]     lv,
    return ref int[string]     collapsed_lev,
    return ref int[string]     obj_type_status,
    return ref CMM             conf_make_meta,
  ) {
    static auto rgx = Rgx();
    if (auto m = line.match(rgx.heading)) {                                      /+ heading match +/
      ++line_occur["heading"];
      obj_type_status["heading"]            = State.on;
      obj_type_status["para"]               = State.off;
      if (line.match(rgx.heading_seg_and_above)) {
        obj_type_status["glossary_section"] = State.off;
        obj_type_status["biblio_section"]   = State.off;
        obj_type_status["blurb_section"]    = State.off;
      }
      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":                                // Title set
        an_object[an_object_key]=(an_object[an_object_key])
          .replaceFirst(rgx.variable_doc_title,
            (conf_make_meta.meta.title_full ~ ","))
          .replaceFirst(rgx.variable_doc_author,
            conf_make_meta.meta.creator_author);
        collapsed_lev["h0"] = 0;
        an_object["lev_collapsed_number"]
          = collapsed_lev["h0"].to!string;
        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"]
          = collapsed_lev["h1"].to!string;
        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"]
          = collapsed_lev["h2"].to!string;
        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"]
          = collapsed_lev["h3"].to!string;
        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"]
          = collapsed_lev["h4"].to!string;
        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"]
            = collapsed_lev["h5"].to!string;
        } else if (lv["h4"] > State.off) {
          collapsed_lev["h5"] = collapsed_lev["h4"] + 1;
          an_object["lev_collapsed_number"]
            = collapsed_lev["h5"].to!string;
        }
        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"]
            = collapsed_lev["h6"].to!string;
        } else if (lv["h5"] > State.off) {
          collapsed_lev["h6"] = collapsed_lev["h5"] + 1;
          an_object["lev_collapsed_number"]
            = collapsed_lev["h6"].to!string;
        }
        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"]
            = collapsed_lev["h7"].to!string;
        } else if (lv["h6"] > State.off) {
          collapsed_lev["h7"] = collapsed_lev["h6"] + 1;
          an_object["lev_collapsed_number"]
            = collapsed_lev["h7"].to!string;
        }
        lv["lv"] = DocStructMarkupHeading.h_text_4;
        ++lv["h7"];
        goto default;
      default:
        an_object["lev_markup_number"] = lv["lv"].to!string;
      }
      an_object["dummy_heading_status"] = (obj_type_status["dummy_heading_status"] == State.off) ? "f" : "t";
      debug(heading) {
        writeln(line.strip);
      }
    }
    return an_object;
  }
  string[string] flow_para_match_()(
               char[]         line,
               string[string]  an_object,
    return ref string          an_object_key,
    return ref int[string]     indent,
    return ref bool            bullet,
    return ref int[string]     obj_type_status,
    return ref int[string]     line_occur,
  ) {
    static auto rgx = Rgx();
    if (line_occur["para"] == State.off) {
      line = font_faces_line(line);
      /+ para matches +/
      obj_type_status["para"] = State.on;
      an_object[an_object_key] ~= line;
      indent=[
        "hang_position" : 0,
        "base_position" : 0,
      ];
      bullet = false;
      if (auto m = line.matchFirst(rgx.para_indent)) {
        debug(paraindent) {
          writeln(line);
        }
        indent["hang_position"] = (m["indent"]).to!int;
        indent["base_position"] = (m["indent"]).to!int;
      } else if (line.matchFirst(rgx.para_bullet)) {
        debug(parabullet) {
          writeln(line);
        }
        bullet = true;
      } else if (auto m = line.matchFirst(rgx.para_indent_hang)) {
        debug(paraindenthang) {
          writeln(line);
        }
        indent = [
          "hang_position" : (m["hang"]).to!int,
          "base_position" : (m["indent"]).to!int,
        ];
      } else if (auto m = line.matchFirst(rgx.para_bullet_indent)) {
        debug(parabulletindent) {
          writeln(line);
        }
        indent = [
          "hang_position" : (m["indent"]).to!int,
          "base_position" : (m["indent"]).to!int,
        ];
        bullet = true;
      }
      ++line_occur["para"];
    }
    return an_object;
  }
  char[] font_faces_line()(
    char[]  textline,
  ) {
    static auto rgx = Rgx();
    static auto mkup = InlineMarkup();
    if (textline.match(rgx.inline_faces_line)) {
      textline = textline
        .replaceFirst(rgx.inline_emphasis_line,   format(q"┃%s%s%s%s%s%s┃", mkup.emph,       mkup.ff_o, "$1", mkup.ff_c, mkup.emph, "$2"))
        .replaceFirst(rgx.inline_bold_line,       format(q"┃%s%s%s%s%s%s┃", mkup.bold,       mkup.ff_o, "$1", mkup.ff_c, mkup.bold, "$2"))
        .replaceFirst(rgx.inline_underscore_line, format(q"┃%s%s%s%s%s%s┃", mkup.underscore, mkup.ff_o, "$1", mkup.ff_c, mkup.underscore, "$2"))
        .replaceFirst(rgx.inline_italics_line,    format(q"┃%s%s%s%s%s%s┃", mkup.italic,     mkup.ff_o, "$1", mkup.ff_c, mkup.italic, "$2"));
    }
    return textline;
  }
  ObjGenericComposite flow_table_instructions(H)(
    return ref ObjGenericComposite  table_object,
               H                    table_head,
  ) {
    static auto rgx = Rgx();
    table_object.metainfo.is_of_part      = "body";
    table_object.metainfo.is_of_section   = "body";
    table_object.metainfo.is_of_type      = "block";
    table_object.metainfo.is_a            = "table";
    table_object.has.inline_notes_reg     = false;
    table_object.has.inline_notes_star    = false;
    table_object.has.inline_links         = false;
    if (auto m = table_head.matchFirst(rgx.table_head_instructions)) {
      table_object.table.heading
        = ((m["c_heading"].length > 0) && (m["c_heading"] == "h")) ? true : false;
      table_object.table.number_of_columns
        = ((m["c_num"].length > 0) && (m["c_num"].to!int > 0)) ? m["c_num"].to!int : 0;
      foreach (cw; m["c_widths"].matchAll(rgx.table_col_widths)) {
        auto x = cw.hit.matchFirst(rgx.table_col_widths_and_alignment);
        table_object.table.column_widths ~= x["width"].to!int;
        table_object.table.column_aligns ~= (x["align"].empty) ? "" : x["align"];
      }
    }
    return table_object;
  }
  ObjGenericComposite flow_table_array_munge(T)(
    return ref ObjGenericComposite  table_object,
    return ref T                    table_array,
  ) {
    static auto rgx = Rgx();
    static auto mng = InlineMarkup();
    string _table_substantive;
    ulong col_num;
    ulong col_num_;
    ulong col_num_chk = 0;
    foreach(idx_r, row; table_array) {
      debug(table_dev) {
        writeln("row ", idx_r);
      }
      col_num_ = 0;
      if (col_num == 0
      || col_num < row.length) {
        col_num = row.length;
      }
      if (col_num_chk == 0) {
        col_num_chk = col_num;
      } else if (col_num == 1) {
        debug(table_dev) {
          writeln("table note: ");
        }
      } else if (col_num_chk != col_num) {
        debug(table_dev) {
          writeln("warning irregular number of columns: ", col_num_chk, " != ", col_num);
        }
      } else {
      }
      foreach(idx_c, col; row) {
        debug(table_dev) {
          write(idx_c, ", ");
        }
        col_num_ = idx_c;
        _table_substantive ~= col ~ mng.tc_s;
        if (idx_r == 0 && comp_obj_block.table.heading) {
        } else if (col.match(rgx.numeric_col) && idx_r == 1) { // conditions reversed to avoid: gdc compiled program run segfault
          if ((comp_obj_block.table.column_aligns.length > idx_c)
          && (comp_obj_block.table.column_aligns[idx_c].matchFirst(rgx.table_col_align_match))) {
            comp_obj_block.table.column_aligns[idx_c]
              = comp_obj_block.table.column_aligns[idx_c];
          } else if (comp_obj_block.table.column_aligns.length > idx_c) {
            comp_obj_block.table.column_aligns[idx_c] = "r";
          } else {
            comp_obj_block.table.column_aligns ~= "r";
          }
        } else if (idx_r == 1) {
          if ((comp_obj_block.table.column_aligns.length > idx_c)
          && (comp_obj_block.table.column_aligns[idx_c].matchFirst(rgx.table_col_align_match))) {
            comp_obj_block.table.column_aligns[idx_c]
              = comp_obj_block.table.column_aligns[idx_c];
          } else if (comp_obj_block.table.column_aligns.length > idx_c) {
            comp_obj_block.table.column_aligns[idx_c] = "l";
          } else {
            comp_obj_block.table.column_aligns ~= "l";
          }
        }
      }
      debug(table_dev) {
        writeln("");
      }
      if (col_num_chk > 0 && (col_num != col_num_chk)) {
      } else if (col_num == col_num_chk){
      } else {
        col_num_chk = col_num;
      }
      _table_substantive = _table_substantive.replaceFirst(rgx.table_col_separator_nl, "\n");
    }
    if (comp_obj_block.table.number_of_columns != col_num) {
      if (comp_obj_block.table.number_of_columns == 0) {
        comp_obj_block.table.number_of_columns = (col_num).to!int;
      } else {
        debug(table_dev) {
          writeln(comp_obj_block.table.number_of_columns, " != ", col_num);
        }
      }
    }
    if (table_object.table.number_of_columns == 0
    && table_object.table.column_widths.length > 0) {
      writeln(__LINE__, " ERROR");
    }
    if (table_object.table.number_of_columns > 0
    && table_object.table.column_widths.length == 0) {
      double col_w = (100.00 / table_object.table.number_of_columns);
      foreach (i; 0..table_object.table.number_of_columns) {
        table_object.table.column_widths ~= col_w;
      }
    } else if (table_object.table.number_of_columns
    != table_object.table.column_widths.length) {
      debug(table_dev) {
        writeln(m.hit); // further logic required
      }
      if (table_object.table.number_of_columns > table_object.table.column_widths.length) {
        double col_w = (100.00 - (table_object.table.column_widths).sum)
          / (table_object.table.number_of_columns - table_object.table.column_widths.length);
        foreach (i; 0..table_object.table.column_widths.length) {
          table_object.table.column_widths ~= col_w;
        }
        foreach (i; 0..(table_object.table.number_of_columns - table_object.table.column_widths.length)) {
          table_object.table.column_widths ~= col_w;
        }
      } else if (table_object.table.number_of_columns < table_object.table.column_widths.length) {
        writeln(__LINE__, " warning, ERROR");
      }
    }
    if (table_object.table.column_widths.sum > 101
    || table_object.table.column_widths.sum < 95 ) {
      writeln("sum: ", table_object.table.column_widths.sum,
        ", array: ", table_object.table.column_widths,
        ", cols: ", table_object.table.number_of_columns);
      writeln(_table_substantive);
    }
    debug(table_res) {
      writeln("aligns: ", comp_obj_block.table.column_aligns, "\n",
        "no. of columns: ", comp_obj_block.table.number_of_columns, "\n",
        "col widths: ", comp_obj_block.table.column_widths,
          " sum: ", comp_obj_block.table.column_widths.sum, "\n",
        _table_substantive);
    }
    comp_obj_block.text = _table_substantive;
    return table_object;
  }
  ObjGenericComposite flow_table_substantive_munge(T)(
    return ref ObjGenericComposite  table_object,
    return ref T                    table_substantive,
  ) {
    static auto rgx = Rgx();
    static auto munge = ObjInlineMarkupMunge();
    string[] _table_rows = (table_substantive).split(rgx.table_row_delimiter);
    string[] _table_cols;
    string[][] _table;
    foreach(col; _table_rows) {
      _table_cols = col.split(rgx.table_col_delimiter);
      _table ~= _table_cols;
    }
    table_object = table_object.flow_table_array_munge(_table);
    return table_object;
  }
  ObjGenericComposite flow_table_substantive_munge_special(T)(
    return ref ObjGenericComposite  table_object,
    return ref T                    table_substantive,
  ) {
    static auto rgx = Rgx();
    static auto munge = ObjInlineMarkupMunge();
    string[] _table_rows = (table_substantive).split(rgx.table_row_delimiter_special);
    string[] _table_cols;
    string[][] _table;
    foreach(col; _table_rows) {
      _table_cols = col.split(rgx.table_col_delimiter_special);
      _table ~= _table_cols;
    }
    table_object = table_object.flow_table_array_munge(_table);
    return table_object;
  }
                                                                                /+ abstraction functions ↑ +/
                                                                                /+ ↓ abstraction function emitters +/
  pure struct OCNemitter {
    int ocn_digit, ocn_object_number, ocn_on_, ocn_off_, ocn_bkidx, ocn_bkidx_;
    string object_identifier;
    bool ocn_is_off;
    auto ocn_emitter(int ocn_status_flag) {
      OCNset ocn;
      assert(ocn_status_flag <= OCNstatus.reset);
      ocn_object_number = ocn_bkidx = 0;
      object_identifier = "";
      ocn_is_off = false;
      switch(ocn_status_flag) with (OCNstatus) {
      case reset:
        ocn_digit = ocn_on_ = 1;
        object_identifier = "1";
        ocn_is_off = false;
        ocn_off_ = ocn_bkidx_ = 0;
        break;
      case on:
        ocn_digit = ocn_object_number = ++ocn_on_;
        object_identifier = ocn_digit.to!string;
        ocn_is_off = false;
        break;
      case off:
        ocn_digit = 0;
        ocn_off_ = ++ocn_off_;
        object_identifier = "a" ~ ocn_off_.to!string;
        ocn_is_off = true;
        break;
      case bkidx:
        ocn_bkidx = ++ocn_bkidx_;
        break;
      case closing:
        break;
      default:
        ocn_digit = 0;
      }
      assert(ocn_digit >= 0);
      ocn.digit         = ocn_digit;
      ocn.object_number = ocn_object_number; // difference between .object_number and .digit?
      ocn.identifier    = object_identifier;
      ocn.off           = ocn_is_off;
      ocn.bkidx         = ocn_bkidx;
      ocn.type          = ocn_status_flag;
      return ocn;
    }
    invariant() {
    }
  }
                                                                                /+ +/
  static struct ObjInlineMarkupMunge {
    string[string] obj_txt;
    int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus;
    string asterisks_, plus_;
    string obj_txt_out, tail, note;
    static auto rgx = Rgx();
    static auto mkup = InlineMarkup();
    int stage_reset_note_numbers = true;
    private auto initialize_note_numbers() {
      n_foot = 0;
      n_foot_reg = 0;
      n_foot_sp_asterisk = 0;
      n_foot_sp_plus = 0;
    }
    static auto images()(string obj_txt_in) {
      static auto mng = InlineMarkup();
      /+ url matched +/
      obj_txt_in = obj_txt_in.replaceAll(rgx.inline_notes_al_special, ""); // TODO reinstate when special footnotes are implemented
      if (obj_txt_in.match(rgx.smid_image_generic)) {                            /+ images with and without links +/
        debug(images) {
          writeln("Image: ", obj_txt_in);
        }
        if (obj_txt_in.match(rgx.smid_image_with_dimensions)) {
          obj_txt_in = obj_txt_in
            .replaceAll(rgx.smid_image_with_dimensions, ("$1" ~ mkup.img ~ "$2,w$3h$4 " ~ "$5"))
            .replaceAll(rgx.smid_image_delimit, ("$1"
              ~ mkup.lnk_o ~ "$2".strip ~ mkup.lnk_c
              ~ mkup.url_o ~ mkup.url_c));
          debug(images) {
            writeln("IMAGE with size: ", obj_txt_in);
          }
        } else if (obj_txt_in.match(rgx.smid_image)) {
          obj_txt_in = obj_txt_in
            .replaceAll(rgx.smid_image, ("$1" ~ mkup.img ~ "$2,w0h0" ~ "$3"))
            .replaceAll(rgx.smid_image_delimit, ("$1"
              ~ mkup.lnk_o ~ "$2".strip ~ mkup.lnk_c
              ~ mkup.url_o ~ mkup.url_c));
          debug(images) {
            writeln("IMAGE: ", obj_txt_in); // decide on representation
          }
        }
      }
      return obj_txt_in;
    }
    auto footnotes_endnotes_markup_and_number_or_stars()(string obj_txt_in, bool reset_note_numbers) {
      /+ endnotes (regular) +/
      bool flg_notes_reg  = false;
      bool flg_notes_star = false;
      bool flg_notes_plus = false;
      obj_txt_in = obj_txt_in.replaceAll(
        rgx.inline_notes_curly,
        (mkup.en_a_o ~ " $1" ~ mkup.en_a_c)
      );
      if (!(stage_reset_note_numbers) && reset_note_numbers) {
        stage_reset_note_numbers = true;
      }
      if (obj_txt_in.match(rgx.inline_notes_al_gen)) {
        if (auto m = obj_txt_in.matchAll(rgx.inline_text_and_note_al_)) {
          if (stage_reset_note_numbers) {
            n_foot = 0;
            n_foot_reg = 0;
            n_foot_sp_asterisk = 0;
            n_foot_sp_plus = 0;
          }
          stage_reset_note_numbers = false;
          foreach(n; m) {
            if (n.hit.to!string.match(rgx.inline_al_delimiter_open_symbol_star)) {
              flg_notes_star =  true;
              ++n_foot_sp_asterisk;
              asterisks_ = "*";
              n_foot=n_foot_sp_asterisk;
              obj_txt_out ~= n.hit.to!string.replaceFirst(
                rgx.inline_al_delimiter_open_symbol_star,
                (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ")
              ) ~ "\n";
            } else if (n.hit.to!string.match(rgx.inline_al_delimiter_open_symbol_plus)) {
              flg_notes_plus =  true;
              ++n_foot_sp_plus;
              plus_ = "*";
              n_foot=n_foot_sp_plus;
              obj_txt_out ~= n.hit.to!string.replaceFirst(
                rgx.inline_al_delimiter_open_symbol_plus,
                (mkup.en_a_o ~ replicate(plus_, n_foot_sp_plus) ~ " ")
              ) ~ "\n";
            } else if (n.hit.to!string.match(rgx.inline_al_delimiter_open_regular)) {
              flg_notes_reg =  true;
              ++n_foot_reg;
              n_foot=n_foot_reg;
              obj_txt_out ~= n.hit.to!string.replaceFirst(
                rgx.inline_al_delimiter_open_regular,
                (mkup.en_a_o ~ n_foot.to!string ~ " ")
              ) ~ "\n";
            } else {
              obj_txt_out ~= n.hit.to!string ~ "\n";
            }
          }
        }
      } else {
        obj_txt_out = obj_txt_in;
      }
      auto t = tuple(
        obj_txt_out,
        flg_notes_reg,
        flg_notes_star,
        flg_notes_plus,
      );
      return t;
    }
    private auto object_notes_and_links_()(
      string obj_txt_in,
      bool reset_note_numbers=false
    ) {
      obj_txt_out = "";
      bool urls = false;
      bool images_without_dimensions = false;
      tail = "";
      /+ special endnotes +/
      obj_txt_in = obj_txt_in.replaceAll(
        rgx.inline_notes_curly_sp_asterisk,
        (mkup.en_a_o ~ "*" ~ " $1" ~ mkup.en_a_c)
      );
      obj_txt_in
        = obj_txt_in.replaceAll(
          rgx.inline_notes_curly_sp_plus,
          (mkup.en_a_o ~ "+" ~ " $1" ~ mkup.en_a_c)
        );
      /+ image matched +/
      if (obj_txt_in.match(rgx.smid_image_generic)) {
        obj_txt_in = images(obj_txt_in);
        if (obj_txt_in.match(rgx.smid_mod_image_without_dimensions)) {
          images_without_dimensions = true;
        }
      }
      /+ url matched +/
      if (obj_txt_in.match(rgx.smid_inline_url)) {
        urls = true;
        obj_txt_in = obj_txt_in.links_and_images;
      }
      if (auto m = obj_txt_in.match(rgx.para_inline_link_anchor)) {
        obj_txt_in = obj_txt_in
          .replaceAll(rgx.para_inline_link_anchor, "┃$1┃");
      }
      auto ftn = footnotes_endnotes_markup_and_number_or_stars(obj_txt_in, reset_note_numbers);
      obj_txt_out = ftn[0];
      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[1]);
          writeln(m.hit);
        }
      }
      auto t = tuple(
        obj_txt_out,
        ftn[1],
        ftn[2],
        ftn[3],
        urls,
        images_without_dimensions,
      );
      return t;
    }
    auto init() {
      auto t = object_notes_and_links_("");
      return t;
    }
    invariant() {
    }
    auto munge_heading()(
      string obj_txt_in,
      bool reset_note_numbers=false
    ) {
      obj_txt["munge"] = obj_txt_in
       .replaceFirst(rgx.heading, "")
       .replaceFirst(rgx.object_number_off_all, "")
       .strip;
      auto t = object_notes_and_links_(obj_txt["munge"], reset_note_numbers);
      debug(munge) {
        writeln(__LINE__);
        writeln(obj_txt_in);
        writeln(__LINE__);
        writeln(obj_txt["munge"].to!string);
      }
      return t;
    }
    invariant() {
    }
    auto munge_para()(string obj_txt_in) {
      obj_txt["munge"]=(obj_txt_in)
        .replaceFirst(rgx.para_attribs, "")
        .replaceFirst(rgx.object_number_off_all, "");
      auto t = object_notes_and_links_(obj_txt["munge"]);
      debug(munge) {
        writeln(__LINE__);
        writeln(obj_txt_in);
        writeln(__LINE__);
        writeln(obj_txt["munge"].to!string);
      }
      return t;
    }
    string munge_quote()(string obj_txt_in) {
      obj_txt["munge"]=obj_txt_in;
      return obj_txt["munge"];
    }
    invariant() {
    }
    auto munge_group(string obj_txt_in) {
      obj_txt["munge"]=obj_txt_in;
      auto t = object_notes_and_links_(obj_txt["munge"]);
      return t;
    }
    invariant() {
    }
    auto munge_block()(string obj_txt_in) {
      obj_txt["munge"]=obj_txt_in;
      auto t = object_notes_and_links_(obj_txt["munge"]);
      return t;
    }
    invariant() {
    }
    auto munge_verse()(string obj_txt_in) {
      obj_txt["munge"]=obj_txt_in;
      auto t = object_notes_and_links_(obj_txt["munge"]);
      return t;
    }
    invariant() {
    }
    string munge_code()(string obj_txt_in) {
      obj_txt_in = obj_txt_in.replaceAll(rgx.space, mkup.nbsp);
      obj_txt["munge"] = obj_txt_in;
      return obj_txt["munge"];
    }
    invariant() {
    }
    string munge_table()(string obj_txt_in) {
      obj_txt["munge"]=obj_txt_in;
      return obj_txt["munge"];
    }
    invariant() {
    }
    string munge_comment()(string obj_txt_in) {
      obj_txt["munge"]=obj_txt_in;
      return obj_txt["munge"];
    }
    invariant() {
    }
  }
  static struct ObjInlineMarkup {
    static auto rgx = Rgx();
    static auto munge = ObjInlineMarkupMunge();
    string[string] obj_txt;
    static string anchor_tag = "";
    auto obj_inline_markup_and_anchor_tags_and_misc(CMM)(
      string[string]   obj_,
      string           obj_key_,
      CMM              conf_make_meta,
      Flag!"_new_doc"  _new_doc
    ) {
      obj_txt["munge"] = obj_[obj_key_].dup;
      obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`)))
      ? obj_txt["munge"]
      : obj_txt["munge"].strip;
      if (_new_doc) {
        anchor_tag = "";
      }
      auto x = munge.init;
      bool[string] obj_notes_and_links;
      obj_notes_and_links["notes_reg"]           = false;
      obj_notes_and_links["notes_star"]          = false;
      obj_notes_and_links["links"]               = false;
      obj_notes_and_links["image_no_dimensions"] = false;
      if ((obj_["is"] == "para")
        || (obj_["is"] == "heading")
        || (obj_["is"] == "quote")
        || (obj_["is"] == "group")
        || (obj_["is"] == "block")
        || (obj_["is"] == "verse")) {
        obj_txt["munge"] = (obj_txt["munge"]).inline_markup_faces;
        obj_txt["munge"] = (obj_txt["munge"]).links_and_images;
      }
      switch (obj_["is"]) {
      case "heading":
        if (_new_doc) {
          anchor_tag = "";
        }
        obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, conf_make_meta, _new_doc);
        obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"], _new_doc);
        if (auto m = obj_txt["munge"].match(rgx.heading_anchor_tag)) {
          anchor_tag = m.captures[1];
        } else if (obj_["lev"] == "1") {
          writeln("heading anchor tag missing: ", obj_txt["munge"]);
        }
        x = munge.munge_heading(obj_txt["munge"], reset_note_numbers);
        reset_note_numbers=false;
        goto default;
      case "para":
        x = munge.munge_para(obj_txt["munge"]);
        goto default;
      case "group":
        x = munge.munge_group(obj_txt["munge"]);
        goto default;
      case "block":
        x = munge.munge_block(obj_txt["munge"]);
        goto default;
      case "verse":
        x = munge.munge_verse(obj_txt["munge"]);
        goto default;
      case "code":
        obj_txt["munge"] = munge.munge_code(obj_txt["munge"]);
        break;
      case "table":
        obj_txt["munge"] = munge.munge_table(obj_txt["munge"]);
        break;
      case "quote":
        obj_txt["munge"] = munge.munge_quote(obj_txt["munge"]);
        break;
      case "comment":
        obj_txt["munge"] = munge.munge_comment(obj_txt["munge"]);
        break;
      case "doc_end_reset":
        munge.initialize_note_numbers();
        break;
      default:
        /+ para, heading, group, block, verse +/
        obj_txt["munge"]                  = x[0];
        obj_notes_and_links["notes_reg"]  = x[1];
        obj_notes_and_links["notes_star"] = x[2];
        obj_notes_and_links["notes_plus"] = x[3];
        obj_notes_and_links["links"]      = x[4];
        obj_notes_and_links["image_no_dimensions"] = x[5];
        break;
      }
      auto t = tuple(
        obj_txt["munge"],
        anchor_tag,
        obj_notes_and_links["notes_reg"],
        obj_notes_and_links["notes_star"],
        obj_notes_and_links["links"],
        obj_notes_and_links["image_no_dimensions"],
      );
      anchor_tag = "";
      return t;
    }
    invariant() {
    }
    auto _clean_heading_toc_()(
      char[] heading_toc_,
    ) {
     auto m = (cast(char[]) heading_toc_).matchFirst(rgx.heading);
     heading_toc_ = (m.post).replaceAll(
       rgx.inline_notes_curly_gen,
       "");
     return heading_toc_;
    };
    ObjGenericComposite[] flow_table_of_contents_gather_headings(CMM)(
                 string[string]         obj_,
                 CMM                    conf_make_meta,
                 string[string]         tag_in_seg,
                 string                 _anchor_tag,
      return ref string[][string]       lev4_subtoc,
                 ObjGenericComposite[]  the_table_of_contents_section,
    ) {
      ObjGenericComposite comp_obj_toc;
      mixin InternalMarkup;
      static auto mkup = InlineMarkup();
      char[] heading_toc_ = (obj_["substantive"].dup.strip.to!(char[])).replaceAll(rgx.inline_notes_al, "");
      heading_toc_ = _clean_heading_toc_(heading_toc_);
      auto attrib="";
      string toc_txt_, subtoc_txt_;
      int[string] indent;
      if (obj_["lev_markup_number"].to!int > 0) {
        indent=[
          "hang_position" : obj_["lev_markup_number"].to!int,
          "base_position" : obj_["lev_markup_number"].to!int,
        ];
        toc_txt_ = format(
          mkup.lnk_o ~ "%s".strip ~ mkup.lnk_c ~  mkup.url_o ~ "#%s"~  mkup.url_c,
          heading_toc_,
          _anchor_tag,
        );
        toc_txt_= toc_txt_.links_and_images;
        comp_obj_toc                             = comp_obj_toc.init;
        comp_obj_toc.metainfo.is_of_part         = "frontmatter";
        comp_obj_toc.metainfo.is_of_section      = "toc";
        comp_obj_toc.metainfo.is_of_type         = "para";
        comp_obj_toc.metainfo.is_a               = "toc";
        comp_obj_toc.metainfo.ocn                = 0;
        comp_obj_toc.metainfo.identifier         = "";
        comp_obj_toc.metainfo.object_number_off  = true;
        comp_obj_toc.metainfo.object_number_type = 0;
        comp_obj_toc.metainfo.dummy_heading      = (an_object["dummy_heading_status"] == "t") ? true: false;
        comp_obj_toc.attrib.indent_hang          = indent["hang_position"];
        comp_obj_toc.attrib.indent_base          = indent["base_position"];
        comp_obj_toc.attrib.bullet               = false;
        comp_obj_toc.text                        = toc_txt_.to!string.strip;
        comp_obj_toc.has.inline_links            = true;
        the_table_of_contents_section            ~= comp_obj_toc;
      }
      comp_obj_toc                               = comp_obj_toc.init;
      comp_obj_toc.metainfo.is_of_part           = "frontmatter";
      comp_obj_toc.metainfo.is_of_section        = "toc";
      comp_obj_toc.metainfo.is_of_type           = "para";
      comp_obj_toc.metainfo.is_a                 = "toc";
      comp_obj_toc.metainfo.ocn                  = 0;
      comp_obj_toc.metainfo.identifier           = "";
      comp_obj_toc.metainfo.object_number_off    = true;
      comp_obj_toc.metainfo.object_number_type   = 0;
      comp_obj_toc.metainfo.dummy_heading        = (an_object["dummy_heading_status"] == "t") ? true: false;
      comp_obj_toc.attrib.bullet                 = false;
      comp_obj_toc.has.inline_links              = true;
      switch (obj_["lev_markup_number"].to!int) {
      case 0: .. case 3:
        break;
      case 4:
        lev4_subtoc[tag_in_seg["seg_lv4"]] = [];
        break;
      case 5: .. case 7:
        subtoc_txt_ = format(
          mkup.lnk_o ~ "%s".strip ~ mkup.lnk_c ~  mkup.url_o ~ "#%s"~  mkup.url_c,
          heading_toc_,
          _anchor_tag,
        );
        lev4_subtoc[tag_in_seg["seg_lv4"]]
        ~= links_and_images(obj_["lev_markup_number"]
             ~ "~ " ~ subtoc_txt_.to!string.strip
           );
        break;
      default:
        break;
      }
      return the_table_of_contents_section;
    }
    invariant() {
    }
  private:
    static int[] heading_num = [ 0, 0, 0, 0 ];
    static string heading_number_auto_composite = "";
    static string heading_number_auto_composite_segname = "";
    static bool[] auto_heading_numbering = [ true, true, true, true];
    static string _configured_auto_heading_numbering_and_segment_anchor_tags(CMM)(
      string           munge_,
      string[string]   obj_,
      CMM              conf_make_meta,
      bool             _new_doc,
    ) {
      if (_new_doc) {
        heading_num = [ 0, 0, 0, 0 ];
        heading_number_auto_composite = "";
        auto_heading_numbering = [ true, true, true, true];
      }
      if (conf_make_meta.make.auto_num_top_lv) {
        if (obj_["lev_markup_number"].to!int == 0) {
          heading_num[0] = 0;
          heading_num[1] = 0;
          heading_num[2] = 0;
          heading_num[3] = 0;
          heading_number_auto_composite = "";
        }
        /+ auto_num_depth minimum 0
           (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement +/
        if (
          conf_make_meta.make.auto_num_top_lv
          > obj_["lev_markup_number"].to!uint
        ) {
          heading_num[1] = 0;
          heading_num[2] = 0;
          heading_num[3] = 0;
        } else if (
          conf_make_meta.make.auto_num_top_lv
            == obj_["lev_markup_number"].to!uint
        ) {
          auto_heading_numbering[0] =
            (munge_.match(rgx.auto_heading_numbering_off_lv1)) ? false : true;
          if (auto_heading_numbering[0]) {
            heading_num[0] ++;
          }
          heading_num[1] = 0;
          heading_num[2] = 0;
          heading_num[3] = 0;
        } else if (
          conf_make_meta.make.auto_num_top_lv
            == (obj_["lev_markup_number"].to!uint - 1)
        ) {
          auto_heading_numbering[1] =
            (munge_.match(rgx.auto_heading_numbering_off_lv2)) ? false : true;
          if (auto_heading_numbering[0]
          && auto_heading_numbering[1]) {
            heading_num[1] ++;
          }
          heading_num[2] = 0;
          heading_num[3] = 0;
        } else if (
          conf_make_meta.make.auto_num_top_lv
            == (obj_["lev_markup_number"].to!uint - 2)
        ) {
          auto_heading_numbering[2] =
            (munge_.match(rgx.auto_heading_numbering_off_lv3)) ? false : true;
          if (auto_heading_numbering[0]
          && auto_heading_numbering[1]
          && auto_heading_numbering[2]) {
            heading_num[2] ++;
          }
          heading_num[3] = 0;
        } else if (
          conf_make_meta.make.auto_num_top_lv
            == (obj_["lev_markup_number"].to!uint - 3)
        ) {
          auto_heading_numbering[3] =
            (munge_.match(rgx.auto_heading_numbering_off_lv4)) ? false : true;
          if (auto_heading_numbering[0]
          && auto_heading_numbering[1]
          && auto_heading_numbering[2]
          && auto_heading_numbering[3]) {
            heading_num[3] ++;
          }
        }
        if (auto_heading_numbering[0]) {
          if (heading_num[3] > 0) {
            heading_number_auto_composite
              = (conf_make_meta.make.auto_num_depth.to!uint == 3
                && auto_heading_numbering[3])
              ? (format(q"┃%s.%s.%s.%s┃",
                  heading_num[0].to!string,
                  heading_num[1].to!string,
                  heading_num[2].to!string,
                  heading_num[3].to!string
                ))
              : "";
          } else if (heading_num[2] > 0) {
            heading_number_auto_composite
              = ((conf_make_meta.make.auto_num_depth.to!uint >= 2)
                && (conf_make_meta.make.auto_num_depth.to!uint <= 3)
                && auto_heading_numbering[2])
              ? (format(q"┃%s.%s.%s┃",
                  heading_num[0].to!string,
                  heading_num[1].to!string,
                  heading_num[2].to!string
                ))
              : "";
          } else if (heading_num[1] > 0) {
            heading_number_auto_composite
              = ((conf_make_meta.make.auto_num_depth.to!uint >= 1)
                && (conf_make_meta.make.auto_num_depth.to!uint <= 3)
                && auto_heading_numbering[1])
              ? (format(q"┃%s.%s┃",
                  heading_num[0].to!string,
                  heading_num[1].to!string
                ))
              : "";
          } else if (heading_num[0] > 0
            && munge_.match(rgx.auto_heading_numbering_lv1)
          ) {
            heading_number_auto_composite
              = ((conf_make_meta.make.auto_num_depth.to!uint >= 0)
                && (conf_make_meta.make.auto_num_depth.to!uint <= 3)
                && auto_heading_numbering[0])
              ? (format(q"┃%s┃",
                  heading_num[0].to!string
                ))
              : "";
          } else {
            heading_number_auto_composite = "";
          }
        }
        heading_number_auto_composite_segname =
          (heading_number_auto_composite.empty)
            ? ""
            : "seg_" ~ heading_number_auto_composite;
        debug(heading_number_auto) {
          writeln(heading_number_auto_composite);
        }
        if ((!empty(heading_number_auto_composite))
        && (obj_["lev_markup_number"].to!uint >= conf_make_meta.make.auto_num_top_lv)) {
          munge_ = munge_
          .replaceFirst(rgx.heading,
            "$1~$2 " ~ heading_number_auto_composite ~ ". ")
          .replaceFirst(rgx.heading_marker_missing_tag,
            "$1~" ~ heading_number_auto_composite_segname ~ " ");
        }
      }
      return munge_;
    }
    static int heading_num_lev1 = 0;
    static string _make_segment_anchor_tags_if_none_provided()(
      string munge_,
      string lev_,
      bool   _new_doc
    ) {
      if (!(munge_.match(rgx.heading_anchor_tag))) {
        if (munge_.match(rgx.heading_identify_anchor_tag)) {
          if (auto m = munge_.match(rgx.heading_extract_named_anchor_tag)) {
            munge_ = munge_.replaceFirst(
              rgx.heading_marker_missing_tag,
              "$1~" ~ m.captures[1].toLower ~ "_"  ~ m.captures[2] ~ " ");
            if (auto n = munge_.match(rgx.heading_anchor_tag_plus_colon)) {
              auto tag_remunge_ = n.captures[2]
                .replaceAll(rgx.heading_marker_tag_has_colon, "..");
              munge_ = munge_.replaceFirst(rgx.heading_anchor_tag_plus_colon, n.captures[1] ~ tag_remunge_ ~ " ");
            }
          } else if (auto m = munge_.match(rgx.heading_extract_unnamed_anchor_tag)) {
            munge_ = munge_.replaceFirst(
              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"
          if (_new_doc) {
            heading_num_lev1 = 0;
          }
          heading_num_lev1 ++;
          munge_ = munge_.replaceFirst(
            rgx.heading_marker_missing_tag,
            "$1~" ~ "x" ~ heading_num_lev1.to!string ~ " ");
        }
      }
      return munge_;
    }
  }
                                                                                /+ +/
  struct ObjAttributes {
    string[string] _obj_attrib;
    string obj_attributes()(
      string              obj_is_,
      string              obj_raw,
      ObjGenericComposite _comp_obj_heading,
    ) {
      scope(exit) {
        destroy(obj_is_);
        destroy(obj_raw);
        destroy(_comp_obj_heading);
      }
      _obj_attrib["json"] ="{";
      switch (obj_is_) {
      case "heading":
        _obj_attrib["json"] ~= txt_heading(obj_raw);
        break;
      case "para":
        _obj_attrib["json"] ~= txt_para_and_blocks(obj_raw)
        ~ txt_para(obj_raw);
        break;
      case "code":
        _obj_attrib["json"] ~= txt_code(obj_raw);
        break;
      case "group":
        _obj_attrib["json"] ~= txt_para_and_blocks(obj_raw)
        ~ txt_group(obj_raw);
        break;
      case "block":
        _obj_attrib["json"] ~= txt_para_and_blocks(obj_raw)
        ~ txt_block(obj_raw);
        break;
      case "verse":
        _obj_attrib["json"] ~= txt_verse(obj_raw);
        break;
      case "quote":
        _obj_attrib["json"] ~= txt_quote(obj_raw);
        break;
      case "table":
        _obj_attrib["json"] ~= txt_table(obj_raw);
        break;
      case "comment":
        _obj_attrib["json"] ~= txt_comment(obj_raw);
        break;
      default:
        _obj_attrib["json"] ~= txt_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(),
            "; object_number: ", oa_j["object_number"].integer()
          );
        }
      }
      return _obj_attrib["json"];
    }
    invariant() {
    }
    private:
    string _obj_attributes;
    string txt_para_and_blocks()(string obj_txt_in) {
      if (obj_txt_in.matchFirst(rgx.para_bullet)) {
        _obj_attributes =" \"bullet\": \"true\","
        ~ " \"indent_hang\": 0,"
        ~ " \"indent_base\": 0,";
      } else if (auto m = obj_txt_in.matchFirst(rgx.para_bullet_indent)) {
        _obj_attributes =" \"bullet\": \"true\","
        ~ " \"indent_hang\": " ~ m["indent"].to!string ~ ","
        ~ " \"indent_base\": " ~ m["indent"].to!string ~ ",";
      } else if (auto m = obj_txt_in.matchFirst(rgx.para_indent_hang)) {
        _obj_attributes =" \"bullet\": \"false\","
        ~ " \"indent_hang\": " ~ m["hang"].to!string ~ ","
        ~ " \"indent_base\": " ~ m["indent"].to!string ~ ",";
      } else if (auto m = obj_txt_in.matchFirst(rgx.para_indent)) {
        _obj_attributes =" \"bullet\": \"false\","
        ~ " \"indent_hang\": " ~ m["indent"].to!string ~ ","
        ~ " \"indent_base\": " ~ m["indent"].to!string ~ ",";
      } else {
        _obj_attributes =" \"bullet\": \"false\","
        ~ " \"indent_hang\": 0,"
        ~ " \"indent_base\": 0,";
      }
      return _obj_attributes;
    }
    string txt_heading()(string obj_txt_in) {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"para\","
      ~ " \"is\": \"heading\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string txt_para()(string obj_txt_in) {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"para\","
      ~ " \"is\": \"para\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string txt_quote()(string obj_txt_in) {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"quote\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string txt_group()(string obj_txt_in) {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"group\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string txt_block()(string obj_txt_in) {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"block\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string txt_verse()(string obj_txt_in) {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"verse\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string txt_code()(string obj_txt_in) {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"code\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string txt_table()(string obj_txt_in) {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"table\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string txt_comment()(string obj_txt_in) {
      _obj_attributes = " \"use\": \"comment\","
      ~ " \"of\": \"comment\","
      ~ " \"is\": \"comment\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string _set_additional_values_parse_as_json()(
      string              _obj_attrib,
      string              obj_is_,
      ObjGenericComposite _comp_obj_heading,
    ) {
      JSONValue oa_j = parseJSON(_obj_attrib);
      assert(
        (oa_j.type == JSON_TYPE.OBJECT)
      );
      if (obj_is_ == "heading") {
        oa_j.object["object_number"]          = _comp_obj_heading.metainfo.ocn;
        oa_j.object["lev_markup_number"]      = _comp_obj_heading.metainfo.heading_lev_markup;
        oa_j.object["lev_collapsed_number"]   = _comp_obj_heading.metainfo.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_object_number"]     = _comp_obj_heading.metainfo.parent_ocn;
      oa_j.object["parent_lev_markup_number"] = _comp_obj_heading.metainfo.parent_lev_markup;
      _obj_attrib = oa_j.toString();
      return _obj_attrib;
    }
  }
                                                                                /+ +/
  struct BookIndexNuggetHash {
    string main_term, sub_term, sub_term_bits;
    int object_number_offset, object_number_endpoint;
    string[] object_numbers;
    string[][string][string] bi_hash_nugget;
    string[] bi_main_terms_split_arr;
    string[][string][string] bookindex_nugget_hash(N,S)(
      string bookindex_section,
      N      obj_cite_digits,
      S      tag_in_seg,
    ) {
      debug(asserts) {
        static assert(is(typeof(obj_cite_digits.object_number) == int));
      }
      debug(bookindexraw) {
        if (!bookindex_section.empty) {
          writeln(
            "* [bookindex] ",
            "[", obj_cite_digits.object_number.to!string, ": ", tag_in_seg["seg_lv4"], "] ", bookindex_section,
            "  - - - ",
            "[", obj_cite_digits.object_number.to!string, "] ", bookindex_section
          );
        }
      }
      static auto rgx = Rgx();
      if (!bookindex_section.empty) {
        auto bi_main_terms_split_arr
          = bookindex_section.split(rgx.bi_main_terms_split);
        foreach (bi_main_terms_content; bi_main_terms_split_arr) {
          auto bi_main_term_and_rest
            = bi_main_terms_content.split(rgx.bi_main_term_plus_rest_split);
          if (auto m = bi_main_term_and_rest[0].match(
            rgx.bi_term_and_object_numbers_match)
          ) {
            main_term = m.captures[1].strip;
            object_number_offset = m.captures[2].to!int;
            object_number_endpoint=(obj_cite_digits.object_number + object_number_offset);
            object_numbers ~= (obj_cite_digits.object_number.to!string
            ~ "-" ~ object_number_endpoint.to!string);
          } else {
            main_term = bi_main_term_and_rest[0].strip;
            object_numbers ~= obj_cite_digits.object_number.to!string;
          }
          bi_hash_nugget[main_term]["_a"] ~= object_numbers;
          object_numbers = null;
          if (bi_main_term_and_rest.length > 1) {
            auto bi_sub_terms_split_arr
              = bi_main_term_and_rest[1].split(
                rgx.bi_sub_terms_plus_object_number_offset_split
              );
            foreach (sub_terms_bits; bi_sub_terms_split_arr) {
              if (auto m = sub_terms_bits.match(rgx.bi_term_and_object_numbers_match)) {
                sub_term = m.captures[1].strip;
                object_number_offset = m.captures[2].to!int;
                object_number_endpoint=(obj_cite_digits.object_number + object_number_offset);
                object_numbers ~= (obj_cite_digits.object_number.to!string
                ~ " - " ~ object_number_endpoint.to!string);
              } else {
                sub_term = sub_terms_bits.strip;
                object_numbers ~= obj_cite_digits.object_number.to!string;
              }
              if (!empty(sub_term)) {
                bi_hash_nugget[main_term][sub_term] ~= object_numbers;
              }
              object_numbers=null;
            }
          }
        }
      }
      return bi_hash_nugget;
    }
    invariant() {
    }
  }
  struct BookIndexReportIndent {
    int mkn, skn;
    void bookindex_report_indented()(
      string[][string][string] bookindex_unordered_hashes
    ) {
      auto mainkeys
        = bookindex_unordered_hashes.byKey.array.sort().release;
      foreach (mainkey; mainkeys) {
        debug(bookindex1) {
          writeln(mainkey);
        }
        auto subkeys
          = bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
        foreach (subkey; subkeys) {
          debug(bookindex1) {
            writeln("  ", subkey);
            writeln("    ", to!string(
              bookindex_unordered_hashes[mainkey][subkey]
            ));
          }
          ++skn;
        }
        ++mkn;
      }
    }
  }
  struct BookIndexReportSection {
    int  mkn, skn;
    static auto rgx = Rgx();
    static auto munge = ObjInlineMarkupMunge();
    void bookindex_write_section()(
      string[][string][string] bookindex_unordered_hashes
    ) {
      auto mainkeys =
        bookindex_unordered_hashes.byKey.array
        .sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable).release;
      foreach (mainkey; mainkeys) {
        write("_0_1 !┨", mainkey, "┣! ");
        foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
          auto go = ref_.replaceAll(rgx.book_index_go, "$1");
          write(" {", ref_, "}#", go, ", ");
        }
        writeln(" \\\\");
        bookindex_unordered_hashes[mainkey].remove("_a");
        auto subkeys =
          bookindex_unordered_hashes[mainkey].byKey.array
          .sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable).release;
        foreach (subkey; subkeys) {
          write("  ", subkey, ", ");
          foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
            auto go = ref_.replaceAll(rgx.book_index_go, "$1");
            write(" {", ref_, "}#", go, ", ");
          }
          writeln(" \\\\");
          ++skn;
        }
        ++mkn;
      }
    }
    auto bookindex_build_abstraction_section(N,B)(
      string[][string][string] bookindex_unordered_hashes,
      N                        obj_cite_digits,
      B                        opt_action,
    ) {
      debug(asserts) {
        static assert(is(typeof(obj_cite_digits.object_number)             == int));
      }
      mixin DocReformNode;
      mixin InternalMarkup;
      static 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!("toUpper(a) < toUpper(b)", SwapStrategy.stable).release;
      ObjGenericComposite[] 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.backmatter
      && opt_action.section_bookindex)) {
        string bi_tmp;
        string[] bi_tmp_tags;
        {
          comp_obj_heading_                                = comp_obj_heading_.init;
          comp_obj_heading_.metainfo.is_of_part            = "backmatter";
          comp_obj_heading_.metainfo.is_of_section         = "bookindex";
          comp_obj_heading_.metainfo.is_of_type            = "para";
          comp_obj_heading_.metainfo.is_a                  = "heading";
          comp_obj_heading_.text                           = "Book Index";
          comp_obj_heading_.metainfo.ocn                   = 0;
          comp_obj_heading_.metainfo.identifier            = "";
          comp_obj_heading_.metainfo.dummy_heading         = false;
          comp_obj_heading_.metainfo.object_number_off     = true;
          comp_obj_heading_.metainfo.object_number_type    = 0;
          comp_obj_heading_.tags.segment_anchor_tag_epub   = "_part_book_index";
          comp_obj_heading_.tags.anchor_tag_html           = comp_obj_heading_.tags.segment_anchor_tag_epub;
          comp_obj_heading_.tags.in_segment_html           = "bookindex";
          comp_obj_heading_.metainfo.heading_lev_markup    = 1;
          comp_obj_heading_.metainfo.heading_lev_collapsed = 1;
          comp_obj_heading_.metainfo.parent_ocn            = 1;
          comp_obj_heading_.metainfo.parent_lev_markup     = 0;
          comp_obj_heading.has.inline_links                = true;
          bookindex_section                                ~= comp_obj_heading_;
          tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
          tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
          ++mkn;
        }
        {
          comp_obj_heading_                                = comp_obj_heading_.init;
          comp_obj_heading_.metainfo.is_of_part            = "backmatter";
          comp_obj_heading_.metainfo.is_of_section         = "bookindex";
          comp_obj_heading_.metainfo.is_of_type            = "para";
          comp_obj_heading_.metainfo.is_a                  = "heading";
          comp_obj_heading_.text                           = "Index";
          comp_obj_heading_.metainfo.ocn                   = 0;
          comp_obj_heading_.metainfo.identifier            = "";
          comp_obj_heading_.metainfo.dummy_heading         = true;
          comp_obj_heading_.metainfo.object_number_off     = true;
          comp_obj_heading_.metainfo.object_number_type    = 0;
          comp_obj_heading_.tags.segment_anchor_tag_epub   = "bookindex";
          comp_obj_heading_.tags.anchor_tag_html           = comp_obj_heading_.tags.segment_anchor_tag_epub;
          comp_obj_heading_.tags.in_segment_html           = comp_obj_heading_.tags.anchor_tag_html;
          comp_obj_heading_.metainfo.heading_lev_markup    = 4;
          comp_obj_heading_.metainfo.heading_lev_collapsed = 2;
          comp_obj_heading_.metainfo.parent_ocn            = 1;
          comp_obj_heading_.metainfo.parent_lev_markup     = 0;
          comp_obj_heading.has.inline_links                = false;
          comp_obj_heading_.tags.anchor_tags               = ["bookindex"];
          bookindex_section                                ~= comp_obj_heading_;
          tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
          tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
          ++mkn;
        }
        import std.array : appender;
        auto buffer = appender!(char[])();
        string[dchar] transTable = [' ' : "_"];
        foreach (mainkey; mainkeys) {
          bi_tmp_tags = [""];
          bi_tmp = mkup.bold ~ mkup.ff_o ~ mainkey ~ mkup.ff_c ~ mkup.bold ~ " ";
          buffer.clear();
          bi_tmp_tags ~= translate(mainkey, transTable);
          auto bkidx_lnk(string locs) {
            string markup = "";
            if (auto m = locs.matchFirst(rgx.book_index_go)) {
              markup
                = links_and_images("{ " ~ m["link"] ~ " }"
                ~ "#" ~ m["ocn"] ~ ", ");
            } else {
              writeln(__LINE__, ": ", locs);
            }
            return markup;
          }
          foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
            bi_tmp ~= bkidx_lnk(ref_);
          }
          bi_tmp ~= " \\\\\n    ";
          bookindex_unordered_hashes[mainkey].remove("_a");
          auto subkeys =
            bookindex_unordered_hashes[mainkey].byKey.array
            .sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable).release;
          foreach (subkey; subkeys) {
            bi_tmp ~= subkey ~ ", ";
            buffer.clear();
            bi_tmp_tags ~= translate(subkey, transTable);
            foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
              bi_tmp ~= bkidx_lnk(ref_);
            }
            bi_tmp ~= " \\\\\n    ";
            ++skn;
          }
          bi_tmp                                         = bi_tmp.replaceFirst(rgx.trailing_linebreak, "");
          comp_obj_para                                  = comp_obj_para.init;
          comp_obj_para.metainfo.is_of_part              = "backmatter";
          comp_obj_para.metainfo.is_of_section           = "bookindex";
          comp_obj_para.metainfo.is_of_type              = "para";
          comp_obj_para.metainfo.is_a                    = "bookindex";
          comp_obj_para.text                             = bi_tmp.to!string.strip;
          comp_obj_para.metainfo.ocn                     = 0;
          comp_obj_para.metainfo.identifier              = "";
          comp_obj_para.metainfo.object_number_off       = true;
          comp_obj_para.metainfo.object_number_type      = 0;
          comp_obj_para.tags.anchor_tags                 = bi_tmp_tags;
          comp_obj_para.attrib.indent_hang               = 0;
          comp_obj_para.attrib.indent_base               = 1;
          comp_obj_para.attrib.bullet                    = false;
          comp_obj_para.has.inline_links                 = true;
          comp_obj_para.text                             = bi_tmp.to!string.strip;
          bookindex_section                              ~= comp_obj_para;
          ++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_.metainfo.ocn                   = 0;
        comp_obj_heading_.metainfo.identifier            = "";
        comp_obj_heading_.metainfo.dummy_heading         = true;
        comp_obj_heading_.metainfo.object_number_off     = true;
        comp_obj_heading_.metainfo.object_number_type    = 0;
        comp_obj_heading_.metainfo.heading_lev_markup    = 1;
        comp_obj_heading_.metainfo.heading_lev_collapsed = 1;
        comp_obj_heading_.metainfo.parent_ocn            = 1;
        comp_obj_heading_.metainfo.parent_lev_markup     = 0;
        bookindex_section                                ~= comp_obj_heading_;
      }
      auto t = tuple(
        bookindex_section,
        obj_cite_digits
      );
      return t;
    }
  }
                                                                                /+ +/
  struct NotesSection {
    string[string] object_notes;
    int previous_count;
    int mkn;
    static auto rgx = Rgx();
    private auto gather_notes_for_endnote_section(
      ObjGenericComposite[] contents_am,
      string[string]        tag_in_seg,
      int                   cntr,
    ) {
      assert((contents_am[cntr].metainfo.is_a == "para")
      || (contents_am[cntr].metainfo.is_a     == "heading")
      || (contents_am[cntr].metainfo.is_a     == "quote")
      || (contents_am[cntr].metainfo.is_a     == "group")
      || (contents_am[cntr].metainfo.is_a     == "block")
      || (contents_am[cntr].metainfo.is_a     == "verse"));
      assert(cntr >= previous_count);
      assert(
        (contents_am[cntr].text).match(
        rgx.inline_notes_al_regular_number_note)
      );
      mixin InternalMarkup;
      previous_count=cntr;
      static auto mkup = InlineMarkup();
      static auto munge = ObjInlineMarkupMunge();
      foreach(m;
        (contents_am[cntr].text).matchAll(
          rgx.inline_notes_al_regular_number_note)
      ) {
        debug(endnotes_build) {
          writeln(
            "{^", mkup.ff_o, m["num"], ".", mkup.ff_c, "^}"
            ~ mkup.mark_internal_site_lnk,
            tag_in_seg["seg_lv4"],
              ".fnSuffix#noteref_\n  ", m["num"], " ",
            m["note"]); // sometimes need segment name (segmented html & epub)
        }
        // you need anchor for segments at this point ->
        object_notes["anchor"] ~= "note_" ~ m["num"] ~ "』";
        object_notes["notes"]  ~= (tag_in_seg["seg_lv4"].empty)
        ? (links_and_images(
            "{" ~ mkup.superscript  ~ mkup.ff_o ~ m["num"] ~ "." ~ mkup.ff_c  ~ mkup.superscript  ~ "}#noteref_"
            ~ m["num"]) ~ " "
            ~ m["note"] ~ "』"
          )
        : (links_and_images(
            "{" ~ mkup.superscript ~ mkup.ff_o ~ m["num"] ~ "." ~ mkup.ff_c  ~ mkup.superscript ~ "}"
             ~ mkup.mark_internal_site_lnk
             ~ tag_in_seg["seg_lv4"]
             ~ ".fnSuffix#noteref_"
             ~ m["num"]) ~ " "
             ~ m["note"] ~ "』"
          );
      }
      return object_notes;
    }
    private auto gathered_notes() {
      string[][string] endnotes_;
      if (object_notes.length > 1) {
        endnotes_["notes"] = (object_notes["notes"].split(rgx.break_string))[0..$-1];
        endnotes_["anchor"] = (object_notes["anchor"].split(rgx.break_string))[0..$-1];
      } else {
        endnotes_["notes"] = [];
        endnotes_["anchor"] = [];
      }
      return endnotes_;
    }
    private auto endnote_objects(N,O)(
      N              obj_cite_digits,
      O              opt_action,
    ) {
      mixin DocReformNode;
      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.backmatter && opt_action.section_endnotes)) {
        {
          comp_obj_heading_                                = comp_obj_heading_.init;
          comp_obj_heading_.metainfo.is_of_part            = "backmatter";
          comp_obj_heading_.metainfo.is_of_section         = "endnotes";
          comp_obj_heading_.metainfo.is_of_type            = "para";
          comp_obj_heading_.metainfo.is_a                  = "heading";
          comp_obj_heading_.text                           = "Endnotes";
          comp_obj_heading_.metainfo.ocn                   = 0;
          comp_obj_heading_.metainfo.identifier            = "";
          comp_obj_heading_.metainfo.dummy_heading         = false;
          comp_obj_heading_.metainfo.object_number_off     = true;
          comp_obj_heading_.metainfo.object_number_type    = 0;
          comp_obj_heading_.tags.segment_anchor_tag_epub   = "_part_endnotes";
          comp_obj_heading_.tags.anchor_tag_html           = comp_obj_heading_.tags.segment_anchor_tag_epub;
          comp_obj_heading_.tags.in_segment_html           = "endnotes";
          comp_obj_heading_.metainfo.heading_lev_markup    = 1;
          comp_obj_heading_.metainfo.heading_lev_collapsed = 1;
          comp_obj_heading_.metainfo.parent_ocn            = 1;
          comp_obj_heading_.metainfo.parent_lev_markup     = 0;
          the_endnotes_section                             ~= comp_obj_heading_;
          tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
          tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
          ++mkn;
        }
        {
          comp_obj_heading_                                = comp_obj_heading_.init;
          comp_obj_heading_.metainfo.is_of_part            = "backmatter";
          comp_obj_heading_.metainfo.is_of_section         = "endnotes";
          comp_obj_heading_.metainfo.is_of_type            = "para";
          comp_obj_heading_.metainfo.is_a                  = "heading";
          comp_obj_heading_.text                           = "Endnotes";
          comp_obj_heading_.metainfo.ocn                   = 0;
          comp_obj_heading_.metainfo.identifier            = "";
          comp_obj_heading_.metainfo.dummy_heading         = true;
          comp_obj_heading_.metainfo.object_number_off     = true;
          comp_obj_heading_.metainfo.object_number_type    = 0;
          comp_obj_heading_.tags.segment_anchor_tag_epub   = "endnotes";
          comp_obj_heading_.tags.anchor_tag_html           = comp_obj_heading_.tags.segment_anchor_tag_epub;
          comp_obj_heading_.tags.in_segment_html           = comp_obj_heading_.tags.anchor_tag_html;
          comp_obj_heading_.metainfo.heading_lev_markup    = 4;
          comp_obj_heading_.metainfo.heading_lev_collapsed = 2;
          comp_obj_heading_.metainfo.parent_ocn            = 1;
          comp_obj_heading_.metainfo.parent_lev_markup     = 0;
          comp_obj_heading_.tags.anchor_tags               = ["endnotes"];
          the_endnotes_section                             ~= comp_obj_heading_;
          tag_assoc[comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = comp_obj_heading_.tags.in_segment_html;
          tag_assoc[comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = comp_obj_heading_.tags.segment_anchor_tag_epub;
          ++mkn;
        }
      } else {
        comp_obj_heading_                                = comp_obj_heading_.init;
        comp_obj_heading_.metainfo.is_of_part            = "empty";
        comp_obj_heading_.metainfo.is_of_section         = "empty";
        comp_obj_heading_.metainfo.is_of_type            = "para";
        comp_obj_heading_.metainfo.is_a                  = "heading";
        comp_obj_heading_.text                           = "(skip) there are no Endnotes";
        comp_obj_heading_.metainfo.ocn                   = 0;
        comp_obj_heading_.metainfo.identifier            = "";
        comp_obj_heading_.metainfo.dummy_heading         = true;
        comp_obj_heading_.metainfo.object_number_off     = true;
        comp_obj_heading_.metainfo.object_number_type    = 0;
        comp_obj_heading_.metainfo.heading_lev_markup    = 1;
        comp_obj_heading_.metainfo.heading_lev_collapsed = 1;
        comp_obj_heading_.metainfo.parent_ocn            = 1;
        comp_obj_heading_.metainfo.parent_lev_markup     = 0;
        the_endnotes_section                             ~= comp_obj_heading_;
      }
      if (opt_action.backmatter && opt_action.section_endnotes) {
        ObjGenericComposite comp_obj_endnote_;
        comp_obj_endnote_                                = comp_obj_endnote_.init;
        comp_obj_endnote_.metainfo.is_of_part            = "backmatter";
        comp_obj_endnote_.metainfo.is_of_section         = "endnote";
        comp_obj_endnote_.metainfo.is_of_type            = "para";
        comp_obj_endnote_.metainfo.is_a                  = "endnote";
        comp_obj_endnote_.metainfo.ocn                   = 0;
        comp_obj_endnote_.metainfo.identifier            = "";
        // comp_obj_heading_.metainfo.dummy_heading         = false;
        comp_obj_heading_.metainfo.object_number_off     = true; // check
        comp_obj_heading_.metainfo.object_number_type    = 0; // check
        comp_obj_endnote_.attrib.indent_hang             = 0;
        comp_obj_endnote_.attrib.indent_base             = 0;
        comp_obj_endnote_.attrib.bullet                  = false;
        foreach (i, endnote; endnotes_["notes"]) {
          auto     m                                     = endnote.matchFirst(rgx.note_ref);
          string   notenumber                            = m["ref"].to!string;
          string   anchor_tag                            = "note_" ~ notenumber;
          comp_obj_endnote_.tags.anchor_tags             = [ endnotes_["anchor"][i] ];
          comp_obj_endnote_.has.inline_links             = true;
          comp_obj_endnote_.text                         = endnote.inline_markup_faces.strip;
          the_endnotes_section                           ~= comp_obj_endnote_;
        }
      }
      auto t = tuple(the_endnotes_section, obj_cite_digits);
      return t;
    }
  }
                                                                                /+ +/
  struct Bibliography {
    public JSONValue[] flow_bibliography_()(
      return ref string[]    biblio_unsorted_incomplete,
      return ref JSONValue[] bib_arr_json
    ) {
      JSONValue[] biblio_unsorted
        = biblio_make_unsorted_array_of_json_objects(biblio_unsorted_incomplete, bib_arr_json); // TODO lookat returns
      biblio_arr_json = [];
      biblio_unsorted_incomplete = [];
      JSONValue[] biblio_sorted__ = biblio_sort(biblio_unsorted);
      debug(biblio0) {
        biblio_debug(biblio_sorted__);
        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__;
    }
    final private JSONValue[] biblio_make_unsorted_array_of_json_objects()(
      string[]      biblio_unordered,
      JSONValue[]   bib_arr_json
    ) {
      foreach (bibent; biblio_unordered) {
        /+ update bib to include deemed_author, needed for:
          sort_bibliography_array_by_deemed_author_year_title
          either: sort on multiple fields, or; create such sort field
        +/
        JSONValue j = parseJSON(bibent);
        if (!empty(j["fulltitle"].str)) {
          if (!empty(j["author_raw"].str)) {
            j["deemed_author"]=j["author_arr"][0];
          } else if (!empty(j["editor_raw"].str)) {
            j["deemed_author"]=j["editor_arr"][0];
          }
          j["sortby_deemed_author_year_title"] = (
            j["deemed_author"].str ~
             "; " ~
             j["year"].str ~
             "; "  ~
             j["fulltitle"].str
          );
        }
        bib_arr_json ~= j;
      }
      return bib_arr_json.dup;
    }
    final private JSONValue[] biblio_sort()(JSONValue[] biblio_unordered) {
      JSONValue[] biblio_sorted_;
      biblio_sorted_
        = sort!((a, b){
          return ((a["sortby_deemed_author_year_title"].str) < (b["sortby_deemed_author_year_title"].str));
        })(biblio_unordered).array;
      debug(bibliosorted) {
        foreach (j; biblio_sorted_) {
          if (!empty(j["fulltitle"].str)) {
            writeln(j["sortby_deemed_author_year_title"]);
          }
        }
      }
      return biblio_sorted_;
    }
    void biblio_debug()(JSONValue[] biblio_sorted) {
      debug(biblio0) {
        foreach (j; biblio_sorted) {
          if (!empty(j["fulltitle"].str)) {
            writeln(j["sortby_deemed_author_year_title"]);
          }
        }
      }
    }
  }
                                                                                /+ +/
  struct NodeStructureMetadata {
    int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7;
    int obj_cite_digit;
    int[string] p_; // p_ parent_
    static auto rgx = Rgx();
    ObjGenericComposite node_location_emitter(La,Ta,N)(
      string         lev_markup_number,
      string[string] tag_in_seg,
      La             lev_anchor_tag,
      Ta             tag_assoc,
      N              obj_cite_digits,
      int            cntr_,
      int            ptr_,
      string         is_
    ) {
      debug(asserts) {
        static assert(is(typeof(obj_cite_digits.object_number) == int));
      }
      assert(is_ != "heading");
      assert(obj_cite_digits.object_number.to!int >= 0);
      assert(is_ != "heading");                          // should not be necessary
      assert(obj_cite_digits.object_number.to!int >= 0); // should not be necessary
      if (lv7 > State.off) {
        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_4;
        p_["object_number"] = lv7;
      } else if (lv6 > State.off) {
        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3;
        p_["object_number"] = lv6;
      } else if (lv5 > State.off) {
        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2;
        p_["object_number"] = lv5;
      } else {
        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1;
        p_["object_number"] = lv4;
      }
      ObjGenericComposite comp_obj_location;
      comp_obj_location                              = comp_obj_location.init;
      comp_obj_location.metainfo.is_a                = is_;
      comp_obj_location.metainfo.ocn                 = obj_cite_digits.object_number;
      comp_obj_location.metainfo.identifier          = obj_cite_digits.identifier;
      comp_obj_location.tags.anchor_tag_html         = tag_in_seg["seg_lv4"];
      comp_obj_location.tags.segment_anchor_tag_epub = tag_in_seg["seg_lv1_to_4"];
      comp_obj_location.tags.heading_lev_anchor_tag  = lev_anchor_tag;
      comp_obj_location.metainfo.parent_ocn          = p_["object_number"];
      comp_obj_location.metainfo.parent_lev_markup   = p_["lev_markup_number"];
      debug(_node) {
        if (lev_markup_number.match(rgx.levels_numbered_headings)) {
          writeln("x ", _node.to!string);
        } else {
          writeln("- ", _node.to!string);
        }
      }
      assert(comp_obj_location.metainfo.parent_lev_markup >= 4);
      assert(comp_obj_location.metainfo.parent_lev_markup <= 7);
      assert(comp_obj_location.metainfo.parent_ocn >= 0);
      return comp_obj_location;
    }
    invariant() {
    }
    ObjGenericComposite node_emitter_heading(Hd,TaL,TA,N,fNr,fNs,fL)(
      string         _text,
      string         lev_markup_number,
      string         lev_collapsed_number,
      Hd             dummy_heading_status,
      string[string] tag_in_seg,
      TaL            lev_anchor_tag,
      TA             tag_assoc,
      N              obj_cite_digits,
      int            cntr_,
      int            ptr_,
      string[]       lv_ancestors_txt,
      string         is_,
      int            html_segnames_ptr,
      fNr            flag_notes_reg,
      fNs            flag_notes_star,
      fL             flag_links,
    ) {
      debug(asserts) {
        static assert(is(typeof(lev)                                       == string));
        static assert(is(typeof(obj_cite_digits.object_number)             == int));
      }
      assert(is_ == "heading");
      assert((obj_cite_digits.object_number).to!int >= 0);
      assert(
        lev_markup_number.match(rgx.levels_numbered),
        ("not a valid heading level: " ~ lev_markup_number ~ " at " ~ obj_cite_digits.object_number.to!string)
      );
      if (lev_markup_number.match(rgx.levels_numbered)) {
        if (lev_markup_number.to!int == 0) {
          /+ TODO first hit (of two) with this assertion failure, check, fix & reinstate
          assert(obj_cite_digits.object_number.to!int == 1,
            "ERROR header lev markup number is: " ~
            lev_markup_number.to!string ~
            " obj_cite_digits.object_number.to!int should == 1 but is: " ~
             obj_cite_digits.object_number.to!string ~
            "\n" ~ _text);
          +/
        }
      }
      switch (lev_markup_number.to!int) {
      case 0:
        lv = DocStructMarkupHeading.h_sect_A;
        lv0 = obj_cite_digit;
        lv1=0; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
        p_["lev_markup_number"] = 0;
        p_["object_number"] = 0;
        break;
      case 1:
        lv = DocStructMarkupHeading.h_sect_B;
        lv1 = obj_cite_digit;
        lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
        p_["lev_markup_number"]
          = DocStructMarkupHeading.h_sect_A;
        p_["object_number"] = lv0;
        break;
      case 2:
        lv = DocStructMarkupHeading.h_sect_C;
        lv2 = obj_cite_digit;
        lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
        p_["lev_markup_number"]
          = DocStructMarkupHeading.h_sect_B;
        p_["object_number"] = lv1;
        break;
      case 3:
        lv = DocStructMarkupHeading.h_sect_D;
        lv3=obj_cite_digit;
        lv4=0; lv5=0; lv6=0; lv7=0;
        p_["lev_markup_number"]
          = DocStructMarkupHeading.h_sect_C;
        p_["object_number"] = lv2;
        break;
      case 4:
        lv = DocStructMarkupHeading.h_text_1;
        lv4 = obj_cite_digit;
        lv5=0; lv6=0; lv7=0;
        if (lv3 > State.off) {
          p_["lev_markup_number"]
            = DocStructMarkupHeading.h_sect_D;
          p_["object_number"] = lv3;
        } else if (lv2 > State.off) {
          p_["lev_markup_number"]
            = DocStructMarkupHeading.h_sect_C;
          p_["object_number"] = lv2;
        } else if (lv1 > State.off) {
          p_["lev_markup_number"]
            = DocStructMarkupHeading.h_sect_B;
          p_["object_number"] = lv1;
        } else {
          p_["lev_markup_number"]
            = DocStructMarkupHeading.h_sect_A;
          p_["object_number"] = lv0;
        }
        break;
      case 5:
        lv = DocStructMarkupHeading.h_text_2;
        lv5 = obj_cite_digit;
        lv6=0; lv7=0;
        p_["lev_markup_number"]
          = DocStructMarkupHeading.h_text_1;
        p_["object_number"] = lv4;
        break;
      case 6:
        lv = DocStructMarkupHeading.h_text_3;
        lv6 = obj_cite_digit;
        lv7=0;
        p_["lev_markup_number"]
          = DocStructMarkupHeading.h_text_2;
        p_["object_number"] = lv5;
        break;
      case 7:
        lv = DocStructMarkupHeading.h_text_4;
        lv7 = obj_cite_digit;
        p_["lev_markup_number"]
          = DocStructMarkupHeading.h_text_3;
        p_["object_number"] = lv6;
        break;
      default:
        break;
      }
      ObjGenericComposite _comp_obj_heading_;
      _comp_obj_heading_                                  = _comp_obj_heading_.init;
      _comp_obj_heading_.metainfo.is_of_part              = "body";
      _comp_obj_heading_.metainfo.is_of_section           = "body";
      _comp_obj_heading_.metainfo.is_of_type              = "para";
      _comp_obj_heading_.metainfo.is_a                    = "heading";
      _comp_obj_heading_.text                             = _text.to!string.strip;
      _comp_obj_heading_.metainfo.ocn                     = obj_cite_digits.object_number;
      _comp_obj_heading_.metainfo.identifier              = obj_cite_digits.identifier;
      _comp_obj_heading_.metainfo.dummy_heading           = (dummy_heading_status == "t") ? true: false;
      _comp_obj_heading_.metainfo.object_number_off       = obj_cite_digits.off;
      // _comp_obj_heading_.metainfo.o_n_book_index       = obj_cite_digits.bkidx;
      _comp_obj_heading_.metainfo.object_number_type      = obj_cite_digits.type;
      _comp_obj_heading_.tags.segment_anchor_tag_epub     = tag_in_seg["seg_lv1_to_4"];
      _comp_obj_heading_.tags.anchor_tag_html             = tag_in_seg["seg_lv4"];
      _comp_obj_heading_.tags.in_segment_html             = _comp_obj_heading_.tags.anchor_tag_html;
      _comp_obj_heading_.tags.heading_lev_anchor_tag      = lev_anchor_tag;
      _comp_obj_heading_.tags.html_segment_anchor_tag_is  = tag_in_seg["seg_lv4"];
      _comp_obj_heading_.tags.epub_segment_anchor_tag_is  = tag_in_seg["seg_lv1_to_4"];
      _comp_obj_heading_.metainfo.heading_lev_markup      = (!(lev_markup_number.empty) ? lev_markup_number.to!int : 0);
      _comp_obj_heading_.metainfo.heading_lev_collapsed   = (!(lev_collapsed_number.empty) ? lev_collapsed_number.to!int : 0);
      _comp_obj_heading_.metainfo.parent_ocn              = p_["object_number"];
      _comp_obj_heading_.metainfo.parent_lev_markup       = p_["lev_markup_number"];
      _comp_obj_heading_.tags.heading_ancestors_text      = lv_ancestors_txt;
      _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_;
      _comp_obj_heading_.has.inline_notes_reg             = flag_notes_reg;
      _comp_obj_heading_.has.inline_notes_star            = flag_notes_star;
      _comp_obj_heading_.has.inline_links                 = flag_links;
      tag_assoc[_comp_obj_heading_.tags.anchor_tag_html]["seg_lv4"]              = _comp_obj_heading_.tags.in_segment_html;
      tag_assoc[_comp_obj_heading_.tags.segment_anchor_tag_epub]["seg_lv1_to_4"] = _comp_obj_heading_.tags.segment_anchor_tag_epub;
      debug(_node) {
        if (lev_markup_number.match(rgx.levels_numbered_headings)) {
          writeln("* ", _node.to!string);
        }
      }
      debug(nodeheading) {
        if (lev_markup_number.match(rgx.levels_numbered_headings)) {
          writeln("* ", _node.to!string);
        }
      }
      assert(_comp_obj_heading_.metainfo.parent_lev_markup <= 7);
      assert(_comp_obj_heading_.metainfo.parent_ocn >= 0);
      if (lev_markup_number.match(rgx.levels_numbered_headings)) {
        assert(_comp_obj_heading_.metainfo.heading_lev_markup <= 7);
        assert(_comp_obj_heading_.metainfo.ocn >= 0);
        if (_comp_obj_heading_.metainfo.parent_lev_markup > 0) {
          assert(_comp_obj_heading_.metainfo.parent_lev_markup < _comp_obj_heading_.metainfo.heading_lev_markup);
          if (_comp_obj_heading_.metainfo.ocn != 0) {
            assert(_comp_obj_heading_.metainfo.parent_ocn < _comp_obj_heading_.metainfo.ocn);
          }
        }
        if (_comp_obj_heading_.metainfo.heading_lev_markup == 0) {
          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_A);
        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_B) {
          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_A);
        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_C) {
          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_B);
        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_D) {
          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_C);
        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_1) {
          assert(_comp_obj_heading_.metainfo.parent_lev_markup <= DocStructMarkupHeading.h_sect_D);
        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_2) {
          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_1);
        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_3) {
          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_2);
        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_4) {
          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_3);
        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_5) {
        }
      }
      return _comp_obj_heading_;
    }
    invariant() {
    }
  }
                                                                                /+ abstraction functions emitters ↑ +/
                                                                                /+ ↓ abstraction functions assertions +/
  pure void assertions_doc_structure()(
    string[string]  an_object,
    int[string]     lv
  ) {
    if (lv["h3"] > State.off) {
      assert(lv["h0"] > State.off);
      assert(lv["h1"] > State.off);
      assert(lv["h2"] > State.off);
    } else if (lv["h2"] > State.off) {
      assert(lv["h0"] > State.off);
      assert(lv["h1"] > State.off);
      assert(lv["h3"] == State.off);
    } else if (lv["h1"] > State.off) {
      assert(lv["h0"] > State.off);
      assert(lv["h2"] == State.off);
      assert(lv["h3"] == State.off);
    } else if (lv["h0"] > State.off) {
      assert(lv["h1"] == State.off);
      assert(lv["h2"] == State.off);
      assert(lv["h3"] == State.off);
    } else {
      assert(lv["h0"] == State.off);
      assert(lv["h1"] == State.off);
      assert(lv["h2"] == State.off);
      assert(lv["h3"] == State.off);
    }
    if (lv["h7"] > State.off) {
      assert(lv["h4"] > State.off);
      assert(lv["h5"] > State.off);
      assert(lv["h6"] > State.off);
    } else if (lv["h6"] > State.off) {
      assert(lv["h4"] > State.off);
      assert(lv["h5"] > State.off);
      assert(lv["h7"] == State.off);
    } else if (lv["h5"] > State.off) {
      assert(lv["h4"] > State.off);
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    } else if (lv["h4"] > State.off) {
      assert(lv["h5"] == State.off);
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    } else {
      assert(lv["h4"] == State.off);
      assert(lv["h5"] == State.off);
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    }
    if (lv["h0"] == State.off) {
      assert(lv["h1"] == State.off);
      assert(lv["h2"] == State.off);
      assert(lv["h3"] == State.off);
      assert(lv["h4"] == State.off);
      assert(lv["h5"] == State.off);
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    }
    if (lv["h1"] == State.off) {
      assert(lv["h2"] == State.off);
      assert(lv["h3"] == State.off);
    }
    if (lv["h2"] == State.off) {
      assert(lv["h3"] == State.off);
    }
    if (lv["h3"] == State.off) {
    }
    if (lv["h4"] == State.off) {
      assert(lv["h5"] == State.off);
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    }
    if (lv["h5"] == State.off) {
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    }
    if (lv["h6"] == State.off) {
      assert(lv["h7"] == State.off);
    }
    if (lv["h7"] == State.off) {
    }
    switch ((an_object["lev"]).to!string) {
    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;
    }
  }
  pure void assertions_flag_types_block_status_none_or_closed()(int[string] obj_type_status) {
    assert(
      (obj_type_status["code"] == TriState.off)
      || (obj_type_status["code"] == TriState.closing),
      "code block status: off or closing");
    assert(
      (obj_type_status["poem"] == TriState.off)
      || (obj_type_status["poem"] == TriState.closing),
      "poem status: off or closing");
    assert(
      (obj_type_status["table"] == TriState.off)
      || (obj_type_status["table"] == TriState.closing),
      "table status: off or closing");
    assert(
      (obj_type_status["group"] == TriState.off)
      || (obj_type_status["group"] == TriState.closing),
      "group block status: off or closing");
    assert(
      (obj_type_status["block"] == TriState.off)
      || (obj_type_status["block"] == TriState.closing),
      "block status: off or closing");
  }
                                                                                /+ abstraction functions assertions ↑ +/
}                                                                               /+ ← closed: template DocReformDocAbstraction +/
template docSectKeysSeq() {
  auto docSectKeysSeq(string[][string] document_section_keys_sequenced) {
    struct doc_sect_keys_seq {
      string[] scroll() {
        return document_section_keys_sequenced["scroll"];
      }
      string[] seg() {
        return document_section_keys_sequenced["seg"];
      }
      string[] sql() {
        return document_section_keys_sequenced["sql"];
      }
      string[] latex() {
        return document_section_keys_sequenced["latex"];
      }
    }
    return doc_sect_keys_seq();
  }
}