/++
  document abstraction:
  abstraction of sisu markup for downstream processing
  ao_abstract_doc_source.d
+/
template SiSUdocAbstraction() {
  /+ ↓ abstraction imports +/
  import
    ao_defaults,
    ao_object_setter,
    ao_rgx,
    output_hub;
  private import
    std.algorithm,
    std.array,
    std.container,
    std.exception,
    std.file,
    std.getopt,
    std.json,
    std.path,
    std.process,
    std.range,
    std.regex,
    std.stdio,
    std.string,
    std.traits,
    std.typecons,
    std.uni,
    std.utf,
    std.conv : to;
  /+ ↓ abstraction mixins +/
  mixin ObjectSetter;
  mixin InternalMarkup;
  mixin SiSUrgxInit;
  /+ ↓ abstraction struct init +/
  /+ initialize +/
  ObjGenericComposite[][string] the_table_of_contents_section;
  ObjGenericComposite[] the_document_head_section, the_document_body_section, the_bibliography_section, the_glossary_section, the_blurb_section;
  ObjGenericComposite[] the_dom_tail_section;
  string[string] an_object, processing;
  string an_object_key;
  string[] anchor_tags;
  string anchor_tag_;
  string segment_anchor_tag_that_object_belongs_to;
  string segment_anchor_tag_that_object_belongs_to_uri;
  /+ 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
  /+ 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";
  auto obj_im = ObjInlineMarkup();
  auto obj_att = ObjAttributes();
  /+ ocn +/
  int obj_cite_number, obj_cite_number_;
  auto object_citation_number = OCNemitter();
  int[] dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
  int[] dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
  int[] dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
  int[] dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
  enum DomTags { none, open, close, close_and_open, open_still, }
  void heading_ancestors(O)(
    auto return ref O          obj,
    return ref string[]        lv_ancestors,
  ) {
    switch (obj.heading_lev_markup) {
    case 0:
      lv_ancestors[0] = obj.text.to!string;
      foreach(k; 1..8) {
        lv_ancestors[k] = "";
      }
      goto default;
    case 1:
      lv_ancestors[1] = obj.text.to!string;
      foreach(k; 2..8) {
        lv_ancestors[k] = "";
      }
      goto default;
    case 2:
      lv_ancestors[2] = obj.text.to!string;
      foreach(k; 3..8) {
        lv_ancestors[k] = "";
      }
      goto default;
    case 3:
      lv_ancestors[3] = obj.text.to!string;
      foreach(k; 4..8) {
        lv_ancestors[k] = "";
      }
      goto default;
    case 4:
      lv_ancestors[4] = obj.text.to!string;
      foreach(k; 5..8) {
        lv_ancestors[k] = "";
      }
      goto default;
    case 5:
      lv_ancestors[5] = obj.text.to!string;
      foreach(k; 6..8) {
        lv_ancestors[k] = "";
      }
      goto default;
    case 6:
      lv_ancestors[6] = obj.text.to!string;
      lv_ancestors[7] = "";
      goto default;
    case 7:
      lv_ancestors[7] = obj.text.to!string;
      goto default;
    default:
      obj.heading_ancestors_text = lv_ancestors.dup;
    }
  }
  auto dom_set_markup_tags(int[] dom, int lev) {
    foreach (i; 0 .. 8) {
      if (i < lev) {
        if (dom[i] == DomTags.open
           || dom[i] == DomTags.close_and_open
        ) {
          dom[i] = DomTags.open_still;
        } else if (dom[i] == DomTags.close) {
          dom[i] = DomTags.none;
        }
      } else if (i == lev) {
        if (lev  == 0
          && dom[i] == DomTags.open_still
        ) {
          dom[i] = DomTags.close;
        } else if (dom[i] == DomTags.open
          || dom[i] == DomTags.open_still
          || dom[i] == DomTags.close_and_open
        ) {
          dom[i] = DomTags.close_and_open;
        } else {
          dom[i] = DomTags.open;
        }
      } else if (i > lev) {
        if (dom[i] == DomTags.close) {
          dom[i] = DomTags.none;
        } else if (dom[i] == DomTags.open
          || dom[i] == DomTags.open_still
          || dom[i] == DomTags.close_and_open
        ) {
          dom[i] = DomTags.close;
        }
      }
    }
    debug(dom_magic_numbers) {
      writeln("marked up: ", lev, ": ", dom);
    }
    return dom;
  }
  auto dom_set_collapsed_tags(int[] dom, int lev) {
    foreach (i; 0 .. 8) {
      if (i < lev) {
        if (dom[i] == DomTags.open
           || dom[i] == DomTags.close_and_open
        ) {
          dom[i] = DomTags.open_still;
        } else if (dom[i] == DomTags.close) {
          dom[i] = DomTags.none;
        }
      } else if (i == lev) {
        if (lev  == 0
          && dom[i] == DomTags.open_still
        ) {
          dom[i] = DomTags.close;
        } else if (dom[i] == DomTags.open
          || dom[i] == DomTags.open_still
          || dom[i] == DomTags.close_and_open
        ) {
          dom[i] = DomTags.close_and_open;
        } else {
          dom[i] = DomTags.open;
        }
      } else if (i > lev) {
        if (dom[i] == DomTags.close) {
          dom[i] = DomTags.none;
        } else if (dom[i] == DomTags.open
          || dom[i] == DomTags.open_still
          || dom[i] == DomTags.close_and_open
        ) {
          dom[i] = DomTags.close;
        }
      }
    }
    debug(dom_magic_numbers) {
      writeln("collapsed: ", lev, ": ", dom);
    }
    return dom;
  }
  int ocn_emit(int ocn_status_flag) {
    return object_citation_number.ocn_emitter(ocn_status_flag);
  }
  /+ book index variables +/
  string book_idx_tmp;
  string[][string][string] bookindex_unordered_hashes;
  /+ 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_tags, notes_reg, notes_star, links }
  /+ ↓ abstract marked up document +/
  auto SiSUdocAbstraction(Src,Make,Meta,Opt)(
    Src                  markup_sourcefile_content,
    Make                 dochead_make_aa,
    Meta                 dochead_meta_aa,
    Opt                  opt_action_bool,
  ) {
    auto rgx = Rgx();
    debug(asserts) {
      static assert(is(typeof(markup_sourcefile_content) == char[][]));
      static assert(is(typeof(dochead_make_aa)           == string[string][string]));
      static assert(is(typeof(dochead_meta_aa)           == string[string][string]));
      static assert(is(typeof(opt_action_bool)           == bool[string]));
    }
    /+ ↓ abstraction init +/
    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 SiSUrgxInitFlags;
    mixin SiSUnode;
    auto node_para_int_    = node_metadata_para_int;
    auto node_para_str_    = node_metadata_para_str;
    ObjGenericComposite comp_obj_heading_, comp_obj_para, comp_obj_toc;
    line_occur = [
      "heading"  : 0,
      "para"     : 0,
      "glossary" : 0,
      "blurb"    : 0,
    ];
    auto type = flags_type_init;
    string[string] obj_cite_number_poem = [
      "start" : "",
      "end"   : ""
    ];
    string[] lv_ancestors = [ "", "", "", "", "", "", "", "", ];
    int[string] lv = [
      "lv" : State.off,
      "h0" : State.off,
      "h1" : State.off,
      "h2" : State.off,
      "h3" : State.off,
      "h4" : State.off,
      "h5" : State.off,
      "h6" : State.off,
      "h7" : State.off,
      "lev_int_collapsed" : 0,
    ];
    int[string] collapsed_lev = [
      "h0" : State.off,
      "h1" : State.off,
      "h2" : State.off,
      "h3" : State.off,
      "h4" : State.off,
      "h5" : State.off,
      "h6" : State.off,
      "h7" : State.off
    ];
    string[string] heading_match_str = [
      "h_A": "^(none)",
      "h_B": "^(none)",
      "h_C": "^(none)",
      "h_D": "^(none)",
      "h_1": "^(none)",
      "h_2": "^(none)",
      "h_3": "^(none)",
      "h_4": "^(none)"
    ];
    auto heading_match_rgx = [
      "h_A": regex(r"^(none)"),
      "h_B": regex(r"^(none)"),
      "h_C": regex(r"^(none)"),
      "h_D": regex(r"^(none)"),
      "h_1": regex(r"^(none)"),
      "h_2": regex(r"^(none)"),
      "h_3": regex(r"^(none)"),
      "h_4": regex(r"^(none)")
    ];
    string _anchor_tag;
    string toc_txt_;
    an_object["glossary_nugget"] = "";
    an_object["blurb_nugget"] = "";
    comp_obj_heading_                       = comp_obj_heading_.init;
    comp_obj_heading_.use                   = "frontmatter";
    comp_obj_heading_.is_of                 = "para";
    comp_obj_heading_.is_a                  = "heading";
    comp_obj_heading_.text                  = "Table of Contents";
    comp_obj_heading_.ocn                   = 0;
    comp_obj_heading_.obj_cite_number       = "";
    comp_obj_heading_.segment_anchor_tag    = "toc";
    comp_obj_heading_.marked_up_level       = "1";
    comp_obj_heading_.heading_lev_markup    = 4;
    comp_obj_heading_.heading_lev_collapsed = 1;
    comp_obj_heading_.parent_ocn            = 1;
    comp_obj_heading_.parent_lev_markup     = 0;
    comp_obj_heading_.ptr_html_segnames     = html_segnames_ptr;
    comp_obj_heading_.anchor_tags           = ["toc"];
    auto toc_head                           = comp_obj_heading_;
    html_segnames_ptr_cntr++;
    the_table_of_contents_section = [
      "seg": [toc_head],
      "scroll": [toc_head],
    ];
    auto mkup = InlineMarkup();
    auto munge = ObjInlineMarkupMunge();
    auto note_section = NotesSection();
    auto bookindex_extract_hash = BookIndexNuggetHash();
    string[][string] lev4_subtoc;
    string[] html_segnames=["toc"];
    /+ abstraction init ↑ +/
    /+ ↓ loop markup document/text line by line +/
    srcDocLoop:
    foreach (line; markup_sourcefile_content) {
      /+ ↓ markup document/text line by line +/
      /+ scope +/
      scope(exit) {
      }
      scope(failure) {
        stderr.writefln(
          "%s\n%s\n%s:%s failed here:\n  line: %s",
          __MODULE__, __FUNCTION__,
          __FILE__, __LINE__,
          line,
        );
      }
      line = (line).replaceAll(rgx.true_dollar, "$$$$");
        // dollar represented as $$ needed to stop submatching on $
        // (substitutions using ${identifiers} must take into account (i.e. happen earlier))
      debug(source) {                                  // source lines
        writeln(line);
      }
      debug(srclines) {
        if (!line.empty) {                             // source lines, not empty
          writefln(
            "* %s",
            line
          );
        }
      }
      if (!line.empty) {
        _check_ocn_status_(line, type);
      }
      if (type["code"] == TriState.on) {
        /+ block object: code +/
        _code_block_(line, an_object, type);
        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 +/
        if (line.matchFirst(rgx.heading_biblio)
        || (type["biblio_section"] == State.on
        && (!(line.matchFirst(rgx.heading_blurb_glossary)))
        && (!(line.matchFirst(rgx.heading)))
        && (!(line.matchFirst(rgx.comment))))) {
          /+ within section (block object): biblio +/
          type["glossary_section"] = State.off;
          type["biblio_section"] = State.on;
          type["blurb_section"] = State.off;
          if (opt_action_bool["backmatter"] && opt_action_bool["section_biblio"]) {
            _biblio_block_(line, type, bib_entry, biblio_entry_str_json, biblio_arr_json);
            debug(bibliobuild) {
              writeln("-  ", biblio_entry_str_json);
              writeln("-> ", biblio_arr_json.length);
            }
          }
          continue;
        } else if (line.matchFirst(rgx.heading_glossary)
        || (type["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);
          }
          // _glossary_block_(line, type);
          type["glossary_section"] = State.on;
          type["biblio_section"] = State.off;
          type["blurb_section"] = State.off;
          if (opt_action_bool["backmatter"] && opt_action_bool["section_glossary"]) {
            indent=[
              "hang_position" : 0,
              "base_position" : 0,
            ];
            bullet = false;
            type["para"] = State.on;
            line_occur["para"] = State.off;
            an_object_key="glossary_nugget"; //
            if (line.matchFirst(rgx.heading_glossary)) {
              comp_obj_heading_                       = comp_obj_heading_.init;
              comp_obj_heading_.use                   = "backmatter";
              comp_obj_heading_.is_of                 = "para";
              comp_obj_heading_.is_a                  = "heading";
              comp_obj_heading_.text                  = "Glossary";
              comp_obj_heading_.ocn                   = 0;
              comp_obj_heading_.obj_cite_number       = "";
              comp_obj_heading_.marked_up_level       = "B";
              comp_obj_heading_.heading_lev_markup    = 1;
              comp_obj_heading_.heading_lev_collapsed = 1;
              comp_obj_heading_.parent_ocn            = 1;
              comp_obj_heading_.parent_lev_markup     = 0;
              the_glossary_section                    ~= comp_obj_heading_;
              comp_obj_heading_                       = comp_obj_heading_.init;
              comp_obj_heading_.use                   = "backmatter";
              comp_obj_heading_.is_of                 = "para";
              comp_obj_heading_.is_a                  = "heading";
              comp_obj_heading_.text                  = "Glossary";
              comp_obj_heading_.ocn                   = 0;
              comp_obj_heading_.obj_cite_number       = "";
              comp_obj_heading_.segment_anchor_tag    = "glossary";
              comp_obj_heading_.marked_up_level       = "1";
              comp_obj_heading_.heading_lev_markup    = 4;
              comp_obj_heading_.heading_lev_collapsed = 2;
              comp_obj_heading_.parent_ocn            = 1;
              comp_obj_heading_.parent_lev_markup     = 0;
              comp_obj_heading_.anchor_tags           = ["glossary"];
              the_glossary_section                    ~= comp_obj_heading_;
            } else {
              _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
              comp_obj_para                       = comp_obj_para.init;
              comp_obj_para.use                   = "backmatter";
              comp_obj_para.is_of                 = "para";
              comp_obj_para.is_a                  = "glossary";
              comp_obj_para.text                  = line.to!string.strip;
              comp_obj_para.ocn                   = 0;
              comp_obj_para.obj_cite_number       = "";
              comp_obj_para.indent_hang           = indent["hang_position"];
              comp_obj_para.indent_base           = indent["base_position"];
              comp_obj_para.bullet                = bullet;
              the_glossary_section                ~= comp_obj_para;
            }
            type["ocn_status"] = TriState.off;
          }
          continue;
        } else if (line.matchFirst(rgx.heading_blurb)
        || (type["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);
          }
          type["glossary_section"] = State.off;
          type["biblio_section"] = State.off;
          type["blurb_section"] = State.on;
          if (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"]) {
            indent=[
              "hang_position" : 0,
              "base_position" : 0,
            ];
            bullet = false;
            type["para"] = State.on;
            line_occur["para"] = State.off;
            an_object_key="blurb_nugget";
            if (line.matchFirst(rgx.heading_blurb)) {
              comp_obj_heading_                       = comp_obj_heading_.init;
              comp_obj_heading_.use                   = "backmatter";
              comp_obj_heading_.is_of                 = "para";
              comp_obj_heading_.is_a                  = "heading";
              comp_obj_heading_.text                  = "Blurb";
              comp_obj_heading_.ocn                   = 0;
              comp_obj_heading_.obj_cite_number       = "";
              comp_obj_heading_.marked_up_level       = "B";
              comp_obj_heading_.heading_lev_markup    = 1;
              comp_obj_heading_.heading_lev_collapsed = 1;
              comp_obj_heading_.parent_ocn            = 1;
              comp_obj_heading_.parent_lev_markup     = 0;
              the_blurb_section                       ~= comp_obj_heading_;
              comp_obj_heading_                       = comp_obj_heading_.init;
              comp_obj_heading_.use                   = "backmatter";
              comp_obj_heading_.is_of                 = "para";
              comp_obj_heading_.is_a                  = "heading";
              comp_obj_heading_.text                  = "Blurb";
              comp_obj_heading_.ocn                   = 0;
              comp_obj_heading_.obj_cite_number       = "";
              comp_obj_heading_.segment_anchor_tag    = "blurb";
              comp_obj_heading_.marked_up_level       = "1";
              comp_obj_heading_.heading_lev_markup    = 4;
              comp_obj_heading_.heading_lev_collapsed = 2;
              comp_obj_heading_.parent_ocn            = 1;
              comp_obj_heading_.parent_lev_markup     = 0;
              comp_obj_heading_.anchor_tags           = ["blurb"];
              the_blurb_section                       ~= comp_obj_heading_;
            } else if (line.matchFirst(rgx.heading)
            && (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"])) {
              comp_obj_heading_                       = comp_obj_heading_.init;
              comp_obj_heading_.use                   = "backmatter";
              comp_obj_heading_.is_of                 = "para";
              comp_obj_heading_.is_a                  = "heading";
              comp_obj_heading_.text                  = line.to!string;
              comp_obj_heading_.ocn                   = 0;
              comp_obj_heading_.obj_cite_number       = "";
              comp_obj_heading_.segment_anchor_tag    = "blurb";
              comp_obj_heading_.marked_up_level       = an_object["lev"].to!string;
              comp_obj_heading_.heading_lev_markup    = an_object["lev_markup_number"].to!int;    // make int, remove need to conv
              comp_obj_heading_.heading_lev_collapsed = an_object["lev_collapsed_number"].to!int; // make int, remove need to conv
              comp_obj_heading_.parent_ocn            = 1;
              comp_obj_heading_.parent_lev_markup     = 0;
              the_blurb_section                   ~= comp_obj_heading_;
            } else {
              _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
              comp_obj_para                       = comp_obj_para.init;
              comp_obj_para.use                   = "backmatter";
              comp_obj_para.is_of                 = "para";
              comp_obj_para.is_a                  = "blurb";
              comp_obj_para.text                  = line.to!string.strip;
              comp_obj_para.ocn                   = 0;
              comp_obj_para.obj_cite_number       = "";
              comp_obj_para.indent_hang           = indent["hang_position"];
              comp_obj_para.indent_base           = indent["base_position"];
              comp_obj_para.bullet                = bullet;
              the_blurb_section                   ~= comp_obj_para;
            }
            type["ocn_status"] = TriState.off;
          }
          continue;
        /+ within block object: group +/
        } else if (type["group"] == TriState.on) {
          /+ within block object: group +/
          _group_block_(line, an_object, type);
          continue;
        } else if (type["block"] == TriState.on) {
          /+ within block object: block +/
          _block_block_(line, an_object, type);
          continue;
        } else if (type["poem"] == TriState.on) {
          /+ within block object: poem +/
          _poem_block_(line, an_object, type, cntr, obj_cite_number_poem, dochead_make_aa);
          continue;
        } else if (type["quote"] == TriState.on) {
          /+ within block object: quote +/
          _quote_block_(line, an_object, type);
          continue;
        } else if (type["table"] == TriState.on) {
          /+ within block object: table +/
          _table_block_(line, an_object, type);
          continue;
        } else {
          /+ not within a block group +/
          assert(
            (type["blocks"] == TriState.off)
            || (type["blocks"] == TriState.closing),
            "block status: none or closed"
          );
          assertions_flag_types_block_status_none_or_closed(type);
          if (line.matchFirst(rgx.block_open)) {
            if (line.matchFirst(rgx.block_poem_open)) {
              /+ poem to verse exceptions! +/
              object_reset(an_object);
              processing.remove("verse");
              obj_cite_number_poem["start"] = obj_cite_number.to!string;
            }
            _start_block_(line, type, obj_cite_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"
            );
            assert(
              (type["blocks"] == TriState.off)
              || (type["blocks"] == TriState.closing),
              "code block status: none or closed"
            );
            if (type["blocks"] == TriState.closing) {
              // blocks closed, unless followed by book index
              debug(check) {                           // block
                writeln(__LINE__);
                writeln(line);
              }
              assert(
                line.matchFirst(rgx.book_index)
                || line.matchFirst(rgx.book_index_open)
                || type["book_index"] == State.on
              );
            }
            if (line.matchFirst(rgx.book_index)
            || line.matchFirst(rgx.book_index_open)
            || type["book_index"] == State.on )  {
              /+ book_index +/
              _book_index_(line, book_idx_tmp, an_object, type, opt_action_bool);
            } else {
              /+ not book_index +/
              an_object_key="body_nugget";
              if (auto m = matchFirst(line, rgx.comment)) {
                /+ matched comment +/
                debug(comment) {
                  writeln(line);
                }
                an_object[an_object_key] ~= line ~= "\n";
                comp_obj_comment                   = comp_obj_comment.init;
                comp_obj_comment.use               = "comment";
                comp_obj_comment.is_of             = "comment";
                comp_obj_comment.is_a              = "comment";
                comp_obj_comment.text              = an_object[an_object_key].strip;
                the_document_body_section          ~= comp_obj_comment;
                _common_reset_(line_occur, an_object, type);
                processing.remove("verse");
                ++cntr;
              } else if (((line_occur["para"] == State.off)
              && (line_occur["heading"] == State.off))
              && ((type["para"] == State.off)
              && (type["heading"] == State.off))) {
                /+ heading or para but neither flag nor line exists +/
                if ((dochead_make_aa["make"]["headings"].length > 2)
                && (type["make_headings"] == State.off)) {
                  /+ heading found +/
                  _heading_found_(line, dochead_make_aa["make"]["headings"], heading_match_str, heading_match_rgx, type);
                }
                if ((type["make_headings"] == State.on)
                && ((line_occur["para"] == State.off)
                && (line_occur["heading"] == State.off))
                && ((type["para"] == State.off)
                && (type["heading"] == State.off))) {
                  /+ heading make set +/
                  _heading_make_set_(line, line_occur, heading_match_rgx, type);
                }
                /+ TODO node info: all headings identified at this point,
                   - extract node info here??
                   - how long can it wait?
                   - should be incorporated in composite objects
                   - should happen before endnote links set (they need to be moved down?)
                  // node_construct.node_emitter_heading segment anchor tag
                +/
                if (line.matchFirst(rgx.heading)) {
                  /+ heading match +/
                  _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa);
                } else if (line_occur["para"] == State.off) {
                  /+ para match +/
                  an_object_key="body_nugget";
                  _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
                }
              } 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(line);
                }
                an_object[an_object_key] ~= " " ~ line;
                ++line_occur["para"];
              }
            }
          } else if (type["blocks"] == TriState.closing) {
            /+ line empty, with blocks flag +/
            _block_flag_line_empty_(
              bookindex_extract_hash,
              line,
              an_object,
              the_document_body_section,
              bookindex_unordered_hashes,
              obj_cite_number,
              comp_obj_heading,
              cntr,
              type,
              obj_cite_number_poem,
              dochead_make_aa
            );
          } else {
            /+ line.empty, post contents, empty variables: +/
            assert(
              line.empty,
              "line should be empty"
            );
            assert(
              (type["blocks"] == State.off),
              "code block status: none"
            );
            if ((type["heading"] == State.on)
            && (line_occur["heading"] > State.off)) {
              /+ heading object (current line empty) +/
              obj_cite_number = (an_object["lev_markup_number"].to!int == 0)
              ? (ocn_emit(3))
              : (obj_cite_number = ocn_emit(type["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, dochead_make_aa);
              an_object["substantive"] = substantive_object_and_anchor_tags_tuple[sObj.content];
              anchor_tags = substantive_object_and_anchor_tags_tuple[sObj.anchor_tags];
              if (an_object["lev_markup_number"].to!int == 4) {
                segment_anchor_tag_that_object_belongs_to = anchor_tags[0];
                segment_anchor_tag_that_object_belongs_to_uri = anchor_tags[0] ~ ".fnSuffix";
                anchor_tag_ = anchor_tags[0];
              } else if (an_object["lev_markup_number"].to!int > 4) {
                segment_anchor_tag_that_object_belongs_to = anchor_tag_;
                segment_anchor_tag_that_object_belongs_to_uri = anchor_tag_ ~ ".fnSuffix#" ~ obj_cite_number.to!string;
              } else if (an_object["lev_markup_number"].to!int < 4) {
                segment_anchor_tag_that_object_belongs_to = "";
                segment_anchor_tag_that_object_belongs_to_uri = "";
              }
              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_number, segment_anchor_tag_that_object_belongs_to);
              /+ (incrementally build toc) table of contents here! +/
              _anchor_tag=to!string(obj_cite_number);
              the_table_of_contents_section = obj_im.table_of_contents_gather_headings(
                an_object,
                dochead_make_aa,
                segment_anchor_tag_that_object_belongs_to,
                _anchor_tag,
                lev4_subtoc,
                the_table_of_contents_section,
              );
              if (an_object["lev_markup_number"] == "4") {
                html_segnames ~= segment_anchor_tag_that_object_belongs_to;
                html_segnames_ptr = html_segnames_ptr_cntr;
                html_segnames_ptr_cntr++;
              }
              auto comp_obj_heading =
                node_construct.node_emitter_heading(
                  an_object["substantive"],                     // string
                  an_object["lev"],                             // string
                  an_object["lev_markup_number"],               // string
                  an_object["lev_collapsed_number"],            // string
                  segment_anchor_tag_that_object_belongs_to,    // string
                  obj_cite_number,                              // int
                  cntr,                                         // int
                  heading_ptr,                                  // int
                  lv_ancestors,                                 // string[]
                  an_object["is"],                              // string
                  html_segnames_ptr,                            // int
                  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(segment_anchor_tag_that_object_belongs_to);
              }
              the_document_body_section ~= comp_obj_heading;
              // track previous heading and make assertions
              debug(objectrelated1) { // check
                writeln(line);
              }
              _common_reset_(line_occur, an_object, type);
              an_object.remove("lev");
              an_object.remove("lev_markup_number");
              processing.remove("verse");
              ++cntr;
            } else if ((type["para"] == State.on)
            && (line_occur["para"] > State.off)) {
              /+ paragraph object (current line empty) +/
              obj_cite_number = ocn_emit(type["ocn_status"]);
              an_object["bookindex_nugget"] =
                ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
              bookindex_unordered_hashes =
                bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_number, segment_anchor_tag_that_object_belongs_to);
              an_object["is"] = "para";
              auto comp_obj_heading =
                node_construct.node_location_emitter(
                  content_non_header,
                  segment_anchor_tag_that_object_belongs_to,
                  obj_cite_number,
                  cntr,
                  heading_ptr-1,
                  an_object["is"],
                );
              auto substantive_obj_misc_tuple =
                obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa);
              an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
              anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags];
              comp_obj_para                       = comp_obj_para.init;
              comp_obj_para.use                   = "body";
              comp_obj_para.is_of                 = "para";
              comp_obj_para.is_a                  = "para";
              comp_obj_para.text                  = an_object["substantive"].to!string.strip;
              comp_obj_para.ocn                   = obj_cite_number;
              comp_obj_para.obj_cite_number       = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
              comp_obj_para.indent_hang           = indent["hang_position"];
              comp_obj_para.indent_base           = indent["base_position"];
              comp_obj_para.bullet                = bullet;
              comp_obj_para.anchor_tags           = anchor_tags;
              comp_obj_para.inline_notes_reg      = substantive_obj_misc_tuple[sObj.notes_reg];
              comp_obj_para.inline_notes_star     = substantive_obj_misc_tuple[sObj.notes_star];
              comp_obj_para.inline_links          = substantive_obj_misc_tuple[sObj.links];
              the_document_body_section           ~= comp_obj_para;
              _common_reset_(line_occur, an_object, type);
              indent=[
                "hang_position" : 0,
                "base_position" : 0,
              ];
              bullet = false;
              processing.remove("verse");
              ++cntr;
            } else {
              assert(
                line == null,
                "line variable should be empty, should not occur"
              );
              // check what happens when paragraph separated by 2 newlines
            }
          } // 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].is_a == "para")
          || (the_document_body_section[$-1].is_a == "heading")
          || (the_document_body_section[$-1].is_a == "group"))
        && (the_document_body_section.length > previous_length)) {
          if ((the_document_body_section[$-1].is_a == "heading")
          && (the_document_body_section[$-1].heading_lev_markup < 5)) {
            type["biblio_section"] = State.off;
            type["glossary_section"] = State.off;
            type["blurb_section"] = State.off;
          }
          previous_length = the_document_body_section.length.to!int;
          if ((the_document_body_section[$-1].text).match(
            rgx.inline_notes_delimiter_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,
              segment_anchor_tag_that_object_belongs_to,
              to!int(the_document_body_section.length-1),
            );
          }
        }
      }
    } /+ ← closed: loop markup document/text line by line +/
    /+ ↓ post loop markup document/text +/
    auto en_tuple =
      note_section.endnote_objects(obj_cite_number, opt_action_bool);
    static assert(!isTypeTuple!(en_tuple));
    auto the_endnotes_section = en_tuple[0];
    obj_cite_number = en_tuple[1];
    debug(endnotes) {
      writefln(
        "%s %s",
        __LINE__,
        the_endnotes_section.length
      );
      foreach (o; the_endnotes_section) {
        writeln(o);
      }
    }
    if (an_object["glossary_nugget"].length == 0) {
      comp_obj_heading_                       = comp_obj_heading_.init;
      comp_obj_heading_.use                   = "empty";
      comp_obj_heading_.is_of                 = "para";
      comp_obj_heading_.is_a                  = "heading";
      comp_obj_heading_.text                  = "(skip) there is no Glossary section";
      comp_obj_heading_.ocn                   = 0;
      comp_obj_heading_.obj_cite_number       = "";
      comp_obj_heading_.marked_up_level       = "B";
      comp_obj_heading_.heading_lev_markup    = 1;
      comp_obj_heading_.heading_lev_collapsed = 1;
      comp_obj_heading_.parent_ocn            = 1;
      comp_obj_heading_.parent_lev_markup     = 0;
      the_glossary_section                    ~= comp_obj_heading_;
    } else {
      writeln("gloss");
    }
    debug(glossary) {
      foreach (gloss; the_glossary_section) {
        writeln(gloss.text);
      }
    }
    auto biblio_unsorted_incomplete = biblio_arr_json.dup;
    auto biblio = Bibliography();
    auto biblio_ordered =
      biblio._bibliography_(biblio_unsorted_incomplete, bib_arr_json);
    if (biblio_ordered.length > 0) {
      comp_obj_heading_                       = comp_obj_heading_.init;
      comp_obj_heading_.use                   = "backmatter";
      comp_obj_heading_.is_of                 = "para";
      comp_obj_heading_.is_a                  = "heading";
      comp_obj_heading_.text                  = "Bibliography";
      comp_obj_heading_.ocn                   = 0;
      comp_obj_heading_.obj_cite_number       = "";
      comp_obj_heading_.marked_up_level       = "B";
      comp_obj_heading_.heading_lev_markup    = 1;
      comp_obj_heading_.heading_lev_collapsed = 1;
      comp_obj_heading_.parent_ocn            = 1;
      comp_obj_heading_.parent_lev_markup     = 0;
      the_bibliography_section                ~= comp_obj_heading_;
      // ---
      comp_obj_heading_                       = comp_obj_heading_.init;
      comp_obj_heading_.use                   = "backmatter";
      comp_obj_heading_.is_of                 = "para";
      comp_obj_heading_.is_a                  = "heading";
      comp_obj_heading_.text                  = "Bibliography";
      comp_obj_heading_.ocn                   = 0;
      comp_obj_heading_.obj_cite_number       = "";
      comp_obj_heading_.segment_anchor_tag    = "bibliography";
      comp_obj_heading_.marked_up_level       = "1";
      comp_obj_heading_.heading_lev_markup    = 4;
      comp_obj_heading_.heading_lev_collapsed = 2;
      comp_obj_heading_.parent_ocn            = 1;
      comp_obj_heading_.parent_lev_markup     = 0;
      comp_obj_heading_.anchor_tags           = ["bibliography"];
      the_bibliography_section                ~= comp_obj_heading_;
    } else {
      comp_obj_heading_                       = comp_obj_heading_.init;
      comp_obj_heading_.use                   = "empty";
      comp_obj_heading_.is_of                 = "para";
      comp_obj_heading_.is_a                  = "heading";
      comp_obj_heading_.text                  = "(skip) there is no Bibliography";
      comp_obj_heading_.ocn                   = 0;
      comp_obj_heading_.obj_cite_number       = "";
      comp_obj_heading_.marked_up_level       = "B";
      comp_obj_heading_.heading_lev_markup    = 1;
      comp_obj_heading_.heading_lev_collapsed = 1;
      comp_obj_heading_.parent_ocn            = 1;
      comp_obj_heading_.parent_lev_markup     = 0;
      the_bibliography_section                ~= comp_obj_heading_;
    }
    string out_;
    foreach (entry; biblio_ordered) {
      out_ = format(
        "%s \"%s\"%s%s%s%s%s%s%s%s%s.",
        ((entry["author"].str.empty) ? entry["editor"].str : entry["author"].str),
        entry["fulltitle"].str,
        ((entry["journal"].str.empty) ? "" : ", /{" ~ entry["journal"].str ~ "}/"),
        ((entry["volume"].str.empty) ? "" : ", " ~ entry["volume"].str),
        ((entry["in"].str.empty) ? "" : ", " ~ entry["in"].str),
        ((!(entry["author"].str.empty) && (!(entry["editor"].str.empty))) ? entry["editor"].str : ""),
        ", " ~ entry["year"].str,
        ((entry["pages"].str.empty) ? "" : ", " ~ entry["pages"].str),
        ((entry["publisher"].str.empty) ? "" : ", " ~ entry["publisher"].str),
        ((entry["place"].str.empty) ? "" : ", " ~ entry["place"].str),
        ((entry["url"].str.empty) ? "" : ", [" ~ entry["url"].str ~ "]"),
      );
      comp_obj_para                       = comp_obj_para.init;
      comp_obj_para.use                   = "backmatter";
      comp_obj_para.is_of                 = "para";
      comp_obj_para.is_a                  = "bibliography";
      comp_obj_para.text                  = out_.to!string.strip;
      comp_obj_para.ocn                   = 0;
      comp_obj_para.obj_cite_number       = "";
      comp_obj_para.indent_hang           = 0;
      comp_obj_para.indent_base           = 1;
      comp_obj_para.bullet                = bullet;
      comp_obj_para.anchor_tags           = anchor_tags;
      the_bibliography_section            ~= comp_obj_para;
    }
    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_number,
        opt_action_bool,
      );
    destroy(bookindex_unordered_hashes);
    static assert(!isTypeTuple!(bi_tuple));
    auto the_bookindex_section = bi_tuple[0];
    obj_cite_number = bi_tuple[1];
    debug(bookindex) {
      foreach (bi_entry; the_bookindex_section["seg"]) {
        writeln(bi_entry);
      }
    }
    if (an_object["blurb_nugget"].length == 0) {
      comp_obj_heading_                       = comp_obj_heading_.init;
      comp_obj_heading_.use                   = "empty";
      comp_obj_heading_.is_of                 = "para";
      comp_obj_heading_.is_a                  = "heading";
      comp_obj_heading_.text                  = "(skip) there is no Blurb section";
      comp_obj_heading_.ocn                   = 0;
      comp_obj_para.obj_cite_number           = "";
      comp_obj_heading_.segment_anchor_tag    = "";
      comp_obj_heading_.marked_up_level       = "B";
      comp_obj_heading_.heading_lev_markup    = 1;
      comp_obj_heading_.heading_lev_collapsed = 1;
      comp_obj_heading_.parent_ocn            = 1;
      comp_obj_heading_.parent_lev_markup     = 0;
      the_blurb_section                       ~= comp_obj_heading_;
    }
    debug(blurb) {
      foreach (blurb; the_blurb_section) {
        writeln(blurb.text);
      }
    }
    indent=[
      "hang_position" : 1,
      "base_position" : 1,
    ];
    comp_obj_toc                       = comp_obj_toc.init;
    comp_obj_toc.use                   = "frontmatter";
    comp_obj_toc.is_of                 = "para";
    comp_obj_toc.is_a                  = "toc";
    comp_obj_toc.ocn                   = 0;
    comp_obj_toc.obj_cite_number       = "";
    comp_obj_toc.indent_hang           = indent["hang_position"];
    comp_obj_toc.indent_base           = indent["base_position"];
    comp_obj_toc.bullet                = false;
    if (the_endnotes_section.length > 1) {
      toc_txt_ = format(
        "{ %s }%s%s%s",
        "Endnotes",
        mkup.mark_internal_site_lnk,
        "endnotes",               // segment_anchor_tag_that_object_belongs_to
        ".fnSuffix",
      );
      toc_txt_= munge.url_links(toc_txt_);
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.inline_links               = true;
      the_table_of_contents_section["seg"]    ~= comp_obj_toc;
    }
    if (the_glossary_section.length > 1) {
      toc_txt_ = format(
        "{ %s }%s%s%s",
        "Glossary",
        mkup.mark_internal_site_lnk,
        "glossary",               // segment_anchor_tag_that_object_belongs_to
        ".fnSuffix",
      );
      toc_txt_= munge.url_links(toc_txt_);
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.inline_links               = true;
      the_table_of_contents_section["seg"]    ~= comp_obj_toc;
      toc_txt_ = format(
        "{ %s }#%s",
        "Glossary",
        "glossary",               // _anchor_tag
      );
      toc_txt_= munge.url_links(toc_txt_);
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.inline_links               = true;
      the_table_of_contents_section["scroll"] ~= comp_obj_toc;
    }
    if (the_bibliography_section.length > 1){
      toc_txt_ = format(
        "{ %s }%s%s%s",
        "Bibliography",
        mkup.mark_internal_site_lnk,
        "bibliography",           // segment_anchor_tag_that_object_belongs_to
        ".fnSuffix",
      );
      toc_txt_= munge.url_links(toc_txt_);
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.inline_links               = true;
      the_table_of_contents_section["seg"]    ~= comp_obj_toc;
    
      toc_txt_ = format(
        "{ %s }#%s",
        "Bibliography",
        "bibliography",           // _anchor_tag
      );
      toc_txt_= munge.url_links(toc_txt_);
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.inline_links               = true;
      the_table_of_contents_section["scroll"] ~= comp_obj_toc;
    }
    if (the_bookindex_section["seg"].length > 1) {
      toc_txt_ = format(
        "{ %s }%s%s%s",
        "Book Index",
        mkup.mark_internal_site_lnk,
        "bookindex",              // segment_anchor_tag_that_object_belongs_to
        ".fnSuffix",
      );
      toc_txt_= munge.url_links(toc_txt_);
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.inline_links               = true;
      the_table_of_contents_section["seg"]    ~= comp_obj_toc;
    }
    if (the_bookindex_section["scroll"].length > 1) {
      toc_txt_ = format(
        "{ %s }#%s",
        "Book Index",
        "bookindex",              // _anchor_tag
      );
      toc_txt_= munge.url_links(toc_txt_);
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.inline_links               = true;
      the_table_of_contents_section["scroll"] ~= comp_obj_toc;
    }
    if (the_blurb_section.length > 1) {
      toc_txt_ = format(
        "{ %s }%s%s%s",
        "Blurb",
        mkup.mark_internal_site_lnk,
        "blurb",                  // segment_anchor_tag_that_object_belongs_to
        ".fnSuffix",
      );
      toc_txt_= munge.url_links(toc_txt_);
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      comp_obj_toc.inline_links               = true;
      the_table_of_contents_section["seg"]    ~= comp_obj_toc;
      toc_txt_ = format(
        "{ %s }#%s",
        "Blurb",
        "blurb",                  // _anchor_tag
      );
      toc_txt_= munge.url_links(toc_txt_);
      comp_obj_toc.inline_links               = true;
      comp_obj_toc.text                       = toc_txt_.to!string.strip;
      the_table_of_contents_section["scroll"] ~= comp_obj_toc;
    }
    debug(toc) {
      writefln(
        "%s %s",
        __LINE__,
        the_table_of_contents_section["seg"].length
      );
      foreach (toc_linked_heading; the_table_of_contents_section["seg"]) {
        writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text);
      }
    }
    debug(tocscroll) {
      writefln(
        "%s %s",
        __LINE__,
        the_table_of_contents_section["seg"].length
      );
      foreach (toc_linked_heading; the_table_of_contents_section["scroll"]) {
        writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text);
      }
    }
    the_document_head_section ~= the_document_body_section[0];
    the_document_body_section=the_document_body_section[1..$];
    if (the_endnotes_section.length > 1) {
      html_segnames ~= "endnotes";
      html_segnames_ptr = html_segnames_ptr_cntr;
      foreach (ref section; the_endnotes_section) {
        if (section.heading_lev_markup == 4) {
          section.ptr_html_segnames = html_segnames_ptr;
          break;
        }
      }
      html_segnames_ptr_cntr++;
    }
    if (the_glossary_section.length > 1) {
      html_segnames ~= "glossary";
      html_segnames_ptr = html_segnames_ptr_cntr;
      foreach (ref section; the_glossary_section) {
        if (section.heading_lev_markup == 4) {
          section.ptr_html_segnames = html_segnames_ptr;
          break;
        }
      }
      html_segnames_ptr_cntr++;
    }
    if (the_bibliography_section.length > 1) {
      html_segnames ~= "bibliography";
      html_segnames_ptr = html_segnames_ptr_cntr;
      foreach (ref section; the_bibliography_section) {
        if (section.heading_lev_markup == 4) {
          section.ptr_html_segnames = html_segnames_ptr;
          break;
        }
      }
      html_segnames_ptr_cntr++;
    }
    if (the_bookindex_section["scroll"].length > 1) {
      html_segnames ~= "bookindex";
      html_segnames_ptr = html_segnames_ptr_cntr;
      foreach (ref section; the_bookindex_section["scroll"]) {
        if (section.heading_lev_markup == 4) {
          section.ptr_html_segnames = html_segnames_ptr;
          break;
        }
      }
      foreach (ref section; the_bookindex_section["seg"]) {
        if (section.heading_lev_markup == 4) {
          section.ptr_html_segnames = html_segnames_ptr;
          break;
        }
      }
      html_segnames_ptr_cntr++;
    }
    if (the_blurb_section.length > 1) {
      html_segnames ~= "blurb";
      html_segnames_ptr = html_segnames_ptr_cntr;
      foreach (ref section; the_blurb_section) {
        if (section.heading_lev_markup == 4) {
          section.ptr_html_segnames = html_segnames_ptr;
          break;
        }
      }
      html_segnames_ptr_cntr++;
    }
    string[] _images;
    auto extract_images(S)(S content_block) {
      string[] images_;
      if (auto m = content_block.matchAll(rgx.image)) {
        images_ ~= m.captures[1];
      }
      return images_;
    }
    foreach (ref obj; the_document_head_section) {
      if (obj.is_a == "heading") {
        debug(dom) {
          writeln(obj.text);
        }
        if ((opt_action_bool["html"])
        || (opt_action_bool["html_scroll"])
        || (opt_action_bool["html_seg"])
        || (opt_action_bool["epub"])) {
          obj.dom_markedup =
            dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
          obj.dom_collapsed =
            dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
        }
        heading_ancestors(obj, lv_ancestors);
      }
    }
    if (the_table_of_contents_section["scroll"].length > 1) {
      dom_markedup_buffer = dom_markedup.dup;
      dom_collapsed_buffer = dom_collapsed.dup;
      foreach (ref obj; the_table_of_contents_section["scroll"]) {
        if (obj.is_a == "heading") {
          if (obj.heading_lev_markup == 4) {
            obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
          }
          if ((opt_action_bool["html"])
          || (opt_action_bool["html_scroll"])
          || (opt_action_bool["html_seg"])
          || (opt_action_bool["epub"])) {
            obj.dom_markedup =
              dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
            obj.dom_collapsed =
              dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
          }
          heading_ancestors(obj, lv_ancestors);
        }
      }
      dom_markedup = dom_markedup_buffer.dup;
      dom_collapsed = dom_collapsed_buffer.dup;
      foreach (ref obj; the_table_of_contents_section["seg"]) {
        if (obj.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          if (obj.heading_lev_markup == 4) {
            obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
          }
          if ((opt_action_bool["html"])
          || (opt_action_bool["html_scroll"])
          || (opt_action_bool["html_seg"])
          || (opt_action_bool["epub"])) {
            obj.dom_markedup =
              dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
            obj.dom_collapsed =
              dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
          }
          heading_ancestors(obj, lv_ancestors);
        }
      }
    }
    /+ multiple 1~ levels, loop through document body +/
    if (the_document_body_section.length > 1) {
      foreach (ref obj; the_document_body_section) {
        if (obj.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          if (obj.heading_lev_markup == 4) {
            obj.lev4_subtoc = lev4_subtoc[obj.segment_anchor_tag];
            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
            if (html_segnames.length > obj.ptr_html_segnames + 1) {
              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
            }
            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
          }
          if ((opt_action_bool["html"])
          || (opt_action_bool["html_scroll"])
          || (opt_action_bool["html_seg"])
          || (opt_action_bool["epub"])) {
            obj.dom_markedup =
              dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
            obj.dom_collapsed =
              dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
          }
          heading_ancestors(obj, lv_ancestors);
        } else if (obj.is_a == "para") {
           _images ~= extract_images(obj.text);
        }
      }
    }
    auto images=uniq(_images.sort());
    /+ optional only one 1~ level +/
    if (the_endnotes_section.length > 1) {
      dom_markedup_buffer = dom_markedup.dup;
      dom_collapsed_buffer = dom_collapsed.dup;
      dom_markedup = dom_markedup_buffer.dup;
      dom_collapsed = dom_collapsed_buffer.dup;
      foreach (ref obj; the_endnotes_section) {
        if (obj.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          if (obj.heading_lev_markup == 4) {
            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
            if (html_segnames.length > obj.ptr_html_segnames + 1) {
              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
            }
            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
          }
          if ((opt_action_bool["html"])
          || (opt_action_bool["html_scroll"])
          || (opt_action_bool["html_seg"])
          || (opt_action_bool["epub"])) {
            obj.dom_markedup =
              dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
            obj.dom_collapsed =
              dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
          }
          heading_ancestors(obj, lv_ancestors);
        }
      }
    }
    /+ optional only one 1~ level +/
    if (the_glossary_section.length > 1) {
      foreach (ref obj; the_glossary_section) {
        if (obj.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          if (obj.heading_lev_markup == 4) {
            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
            if (html_segnames.length > obj.ptr_html_segnames + 1) {
              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
            }
            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
          }
          if ((opt_action_bool["html"])
          || (opt_action_bool["html_scroll"])
          || (opt_action_bool["html_seg"])
          || (opt_action_bool["epub"])) {
            obj.dom_markedup =
              dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
            obj.dom_collapsed =
              dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
          }
          heading_ancestors(obj, lv_ancestors);
        }
      }
    }
    /+ optional only one 1~ level +/
    if (the_bibliography_section.length > 1) {
      foreach (ref obj; the_bibliography_section) {
        if (obj.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          if (obj.heading_lev_markup == 4) {
            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
            if (html_segnames.length > obj.ptr_html_segnames + 1) {
              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
            }
            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
          }
          if ((opt_action_bool["html"])
          || (opt_action_bool["html_scroll"])
          || (opt_action_bool["html_seg"])
          || (opt_action_bool["epub"])) {
            obj.dom_markedup =
              dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
            obj.dom_collapsed =
              dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
          }
          heading_ancestors(obj, lv_ancestors);
        }
      }
    }
    /+ optional only one 1~ level +/
    if (the_bookindex_section["scroll"].length > 1) {
      dom_markedup_buffer = dom_markedup.dup;
      dom_collapsed_buffer = dom_collapsed.dup;
      foreach (ref obj; the_bookindex_section["scroll"]) {
        if (obj.is_a == "heading") {
          debug(dom) {
          // writeln(obj.text);
          }
          if (obj.heading_lev_markup == 4) {
            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
            if (html_segnames.length > obj.ptr_html_segnames + 1) {
              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
            }
            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
          }
          if ((opt_action_bool["html"])
          || (opt_action_bool["html_scroll"])
          || (opt_action_bool["html_seg"])
          || (opt_action_bool["epub"])) {
            obj.dom_markedup =
              dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
            obj.dom_collapsed =
              dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
          }
          heading_ancestors(obj, lv_ancestors);
        }
      }
      dom_markedup = dom_markedup_buffer.dup;
      dom_collapsed = dom_collapsed_buffer.dup;
      foreach (ref obj; the_bookindex_section["seg"]) {
        if (obj.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          if (obj.heading_lev_markup == 4) {
            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
            if (html_segnames.length > obj.ptr_html_segnames + 1) {
              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
            }
            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
          }
          if ((opt_action_bool["html"])
          || (opt_action_bool["html_scroll"])
          || (opt_action_bool["html_seg"])
          || (opt_action_bool["epub"])) {
            obj.dom_markedup =
              dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
            obj.dom_collapsed =
              dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
          }
          heading_ancestors(obj, lv_ancestors);
        }
      }
    }
    /+ optional only one 1~ level +/
    if (the_blurb_section.length > 1) {
      foreach (ref obj; the_blurb_section) {
        if (obj.is_a == "heading") {
          debug(dom) {
            writeln(obj.text);
          }
          if (obj.heading_lev_markup == 4) {
            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
            if (html_segnames.length > obj.ptr_html_segnames + 1) {
              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
            }
            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
          }
          if ((opt_action_bool["html"])
          || (opt_action_bool["html_scroll"])
          || (opt_action_bool["html_seg"])
          || (opt_action_bool["epub"])) {
            obj.dom_markedup =
              dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup;
            obj.dom_collapsed =
              dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup;
          }
          heading_ancestors(obj, lv_ancestors);
        }
      }
      /+ TODO
        - note create/insert heading object sole purpose eof close all open tags
          sort out:
          - obj.dom_markedup = dom_markedup;
          - obj.dom_collapsed = dom_collapsed;
      +/
      dom_markedup = dom_set_markup_tags(dom_markedup, 0);
      dom_collapsed = dom_set_collapsed_tags(dom_collapsed, 0);
      comp_obj_heading_                       = comp_obj_heading_.init;
      comp_obj_heading_.use                   = "empty";
      comp_obj_heading_.is_of                 = "para";
      comp_obj_heading_.is_a                  = "heading";
      // comp_obj_heading_.text                  = "(skip) this is the DOM tail";
      comp_obj_heading_.ocn                   = 0;
      comp_obj_para.obj_cite_number           = "";
      comp_obj_heading_.segment_anchor_tag    = "";
      comp_obj_heading_.marked_up_level       = "";
      comp_obj_heading_.heading_lev_markup    = 9;
      comp_obj_heading_.heading_lev_collapsed = 9;
      comp_obj_heading_.parent_ocn            = 0;
      comp_obj_heading_.parent_lev_markup     = 0;
      comp_obj_heading_.dom_markedup          = dom_markedup.dup;
      comp_obj_heading_.dom_collapsed         = dom_collapsed.dup;
      the_dom_tail_section                    ~= comp_obj_heading_;
    }
    auto document_the = [
      "head":             the_document_head_section,
      "toc_seg":          the_table_of_contents_section["seg"],
      "toc_scroll":       the_table_of_contents_section["scroll"],
      /+ substantive/body: +/
      "body":             the_document_body_section,
      /+ backmatter: +/
      "endnotes":         the_endnotes_section,
      "glossary":         the_glossary_section,
      "bibliography":     the_bibliography_section,
      "bookindex_scroll": the_bookindex_section["scroll"],
      "bookindex_seg":    the_bookindex_section["seg"],
      "blurb":            the_blurb_section,
      /+ dom tail only +/
      "tail":             the_dom_tail_section,
    ];
    string[][string] document_section_keys_sequenced = [
      "seg":    ["head", "toc_seg", "body",],
      "scroll": ["head", "toc_scroll", "body",]
    ];
    if (document_the["endnotes"].length > 1) {
      document_section_keys_sequenced["seg"]    ~= "endnotes";
      document_section_keys_sequenced["scroll"] ~= "endnotes";
    }
    if (document_the["glossary"].length > 1) {
      document_section_keys_sequenced["seg"]    ~= "glossary";
      document_section_keys_sequenced["scroll"] ~= "glossary";
    }
    if (document_the["bibliography"].length > 1) {
      document_section_keys_sequenced["seg"]    ~= "bibliography";
      document_section_keys_sequenced["scroll"] ~= "bibliography";
    }
    if (document_the["bookindex_seg"].length > 1) {
      document_section_keys_sequenced["seg"]    ~= "bookindex_seg";
    }
    if (document_the["bookindex_scroll"].length > 1) {
      document_section_keys_sequenced["scroll"] ~= "bookindex_scroll";
    }
    if (document_the["blurb"].length > 1) {
      document_section_keys_sequenced["seg"]    ~= "blurb";
      document_section_keys_sequenced["scroll"] ~= "blurb";
    }
    if ((opt_action_bool["html"])
    || (opt_action_bool["html_scroll"])
    || (opt_action_bool["html_seg"])
    || (opt_action_bool["epub"])) {
      document_section_keys_sequenced["seg"]    ~= "tail";
      document_section_keys_sequenced["scroll"] ~= "tail";
    }
    auto segnames = html_segnames.dup;
    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(html_segnames);
    destroy(bookindex_unordered_hashes);
    destroy(an_object);
    biblio_arr_json = [];
    obj_cite_number=0;
    obj_cite_number_=0;
    html_segnames_ptr=0;
    html_segnames_ptr_cntr=0;
    content_non_header = "8";
    dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
    dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
    dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
    dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,];
    auto t = tuple(
      document_the,
      document_section_keys_sequenced,
      segnames,
      images,
    );
    return t;
    /+ post loop markup document/text ↑ +/
  } /+ ← closed: abstract doc source +/
  /+ ↓ abstraction functions +/
  auto object_reset(O)(ref O an_object) {
    debug(asserts) {
      static assert(is(typeof(an_object) == string[string]));
    }
    an_object.remove("body_nugget");
    an_object.remove("substantive");
    an_object.remove("is");
    an_object.remove("attrib");
    an_object.remove("bookindex_nugget");
  }
  auto _common_reset_(L,O,T)(
    return ref L line_occur,
    return ref O an_object,
    return ref T type
  ) {
    debug(asserts) {
      static assert(is(typeof(line_occur) == int[string]));
      static assert(is(typeof(an_object)  == string[string]));
      static assert(is(typeof(type)       == int[string]));
    }
    line_occur["heading"] = State.off;
    line_occur["para"]    = State.off;
    type["heading"]       = State.off;
    type["para"]          = State.off;
    object_reset(an_object);
  }
  void _check_ocn_status_(L,T)(
    L            line,
    return ref T type
  ) {
    debug(asserts) {
      static assert(is(typeof(line) == char[]));
      static assert(is(typeof(type) == int[string]));
    }
    auto rgx = Rgx();
    if ((!line.empty) && (type["ocn_status_multi_obj"] == TriState.off)) {
      /+ not multi-line object, check whether obj_cite_number is on or turned off +/
      if (line.matchFirst(rgx.obj_cite_number_block_marks)) {
        /+ switch off obj_cite_number +/
        if (line.matchFirst(rgx.obj_cite_number_off_block)) {
          type["ocn_status_multi_obj"] = TriState.on;
          debug(ocnoff) {
            writeln(line);
          }
        }
        if (line.matchFirst(rgx.obj_cite_number_off_block_dh)) {
          type["ocn_status_multi_obj"] = TriState.closing;
          debug(ocnoff) {
            writeln(line);
          }
        }
      } else {
        if (type["ocn_status_multi_obj"] == TriState.off) {
          if (line.matchFirst(rgx.obj_cite_number_off)) {
            type["ocn_status"] = TriState.on;
          } else if (line.matchFirst(rgx.obj_cite_number_off_dh)) {
            type["ocn_status"] = TriState.closing;
          } else {
            type["ocn_status"] = TriState.off;
          }
        } else {
          type["ocn_status"] =
            type["ocn_status_multi_obj"];
        }
      }
    } else if ((!line.empty) && (type["ocn_status_multi_obj"] > TriState.off)) {
      if (line.matchFirst(rgx.obj_cite_number_off_block_close)) {
        type["ocn_status_multi_obj"] = TriState.off;
        type["ocn_status"] = TriState.off;
        debug(ocnoff) {
          writeln(line);
        }
      }
    }
  }
  void _start_block_(L,T,N)(
    L            line,
    return ref T type,
    N            obj_cite_number_poem
  ) {
    debug(asserts) {
      static assert(is(typeof(line)                 == char[]));
      static assert(is(typeof(type)                 == int[string]));
      static assert(is(typeof(obj_cite_number_poem) == string[string]));
    }
    auto rgx = Rgx();
    if (line.matchFirst(rgx.block_curly_code_open)) {
      /+ curly code open +/
      debug(code) {                              // code (curly) open
        writefln(
          "* [code curly] %s",
          line
        );
      }
      type["blocks"] = TriState.on;
      type["code"] = TriState.on;
      type["curly_code"] = TriState.on;
    } else if (line.matchFirst(rgx.block_curly_poem_open)) {
      /+ curly poem open +/
      debug(poem) {                              // poem (curly) open
        writefln(
          "* [poem curly] %s",
          line
        );
      }
      obj_cite_number_poem["start"] =
        obj_cite_number.to!string;
      type["blocks"] = TriState.on;
      type["verse_new"] = State.on;
      type["poem"] = TriState.on;
      type["curly_poem"] = TriState.on;
    } else if (line.matchFirst(rgx.block_curly_group_open)) {
      /+ curly group open +/
      debug(group) {                             // group (curly) open
        writefln(
          "* [group curly] %s",
          line
        );
      }
      type["blocks"] = TriState.on;
      type["group"] = TriState.on;
      type["curly_group"] = TriState.on;
    } else if (line.matchFirst(rgx.block_curly_block_open)) {
      /+ curly block open +/
      debug(block) {                             // block (curly) open
        writefln(
          "* [block curly] %s",
          line
        );
      }
      type["blocks"] = TriState.on;
      type["block"] = TriState.on;
      type["curly_block"] = TriState.on;
    } else if (line.matchFirst(rgx.block_curly_quote_open)) {
      /+ curly quote open +/
      debug(quote) {                             // quote (curly) open
        writefln(
          "* [quote curly] %s",
          line
        );
      }
      type["blocks"] = TriState.on;
      type["quote"] = TriState.on;
      type["curly_quote"] = TriState.on;
    } else if (line.matchFirst(rgx.block_curly_table_open)) {
      /+ curly table open +/
      debug(table) {                             // table (curly) open
        writefln(
          "* [table curly] %s",
          line
        );
      }
      type["blocks"]      = TriState.on;
      type["table"]       = TriState.on;
      type["curly_table"] = TriState.on;
    } else if (line.matchFirst(rgx.block_tic_code_open)) {
      /+ tic code open +/
      debug(code) {                              // code (tic) open
        writefln(
          "* [code tic] %s",
          line
        );
      }
      type["blocks"] = TriState.on;
      type["code"] = TriState.on;
      type["tic_code"] = TriState.on;
    } else if (line.matchFirst(rgx.block_tic_poem_open)) {
      /+ tic poem open +/
      debug(poem) {                              // poem (tic) open
        writefln(
          "* [poem tic] %s",
          line
        );
      }
      obj_cite_number_poem["start"] = obj_cite_number.to!string;
      type["blocks"] = TriState.on;
      type["verse_new"] = State.on;
      type["poem"] = TriState.on;
      type["tic_poem"] = TriState.on;
    } else if (line.matchFirst(rgx.block_tic_group_open)) {
      /+ tic group open +/
      debug(group) {                             // group (tic) open
        writefln(
          "* [group tic] %s",
          line
        );
      }
      type["blocks"] = TriState.on;
      type["group"] = TriState.on;
      type["tic_group"] = TriState.on;
    } else if (line.matchFirst(rgx.block_tic_block_open)) {
      /+ tic block open +/
      debug(block) {                             // block (tic) open
        writefln(
          "* [block tic] %s",
          line
        );
      }
      type["blocks"] = TriState.on;
      type["block"] = TriState.on;
      type["tic_block"] = TriState.on;
    } else if (line.matchFirst(rgx.block_tic_quote_open)) {
      /+ tic quote open +/
      debug(quote) {                             // quote (tic) open
        writefln(
          "* [quote tic] %s",
          line
        );
      }
      type["blocks"] = TriState.on;
      type["quote"] = TriState.on;
      type["tic_quote"] = TriState.on;
    } else if (line.matchFirst(rgx.block_tic_table_open)) {
      /+ tic table open +/
      debug(table) {                             // table (tic) open
        writefln(
          "* [table tic] %s",
          line
        );
      }
      type["blocks"]    = TriState.on;
      type["table"]     = TriState.on;
      type["tic_table"] = TriState.on;
    }
  }
  void _code_block_(L,O,T)(
    return ref L line,
    return ref O an_object,
    return ref T type
  ) {
    debug(asserts) {
      static assert(is(typeof(line)      == char[]));
      static assert(is(typeof(an_object) == string[string]));
      static assert(is(typeof(type)      == int[string]));
    }
    auto rgx = Rgx();
    if (type["curly_code"] == TriState.on) {
      if (line.matchFirst(rgx.block_curly_code_close)) {
        debug(code) {                                    // code (curly) close
          writeln(line);
        }
        type["blocks"] = TriState.closing;
        type["code"] = TriState.closing;
        type["curly_code"] = TriState.off;
      } else {
        debug(code) {                                    // code (curly) line
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";        // code (curly) line
      }
    } else if (type["tic_code"] == TriState.on) {
      if (line.matchFirst(rgx.block_tic_close)) {
        debug(code) {                                    // code (tic) close
          writeln(line);
        }
        type["blocks"] = TriState.closing;
        type["code"] = TriState.closing;
        type["tic_code"] = TriState.off;
      } else {
        debug(code) {                                    // code (tic) line
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";        // code (tic) line
      }
    }
  }
  final string biblio_tag_map(A)(A abr) {
    debug(asserts) {
      static assert(is(typeof(abr) == string));
    }
    auto btm = [
      "au"                               : "author_raw",
      "ed"                               : "editor_raw",
      "ti"                               : "fulltitle",
      "lng"                              : "language",
      "jo"                               : "journal",
      "vol"                              : "volume",
      "edn"                              : "edition",
      "yr"                               : "year",
      "pl"                               : "place",
      "pb"                               : "publisher",
      "pub"                              : "publisher",
      "pg"                               : "pages",
      "pgs"                              : "pages",
      "sn"                               : "short_name"
    ];
    return btm[abr];
  }
  void _biblio_block_(
    char[]                 line,
    return ref int[string] type,
    return ref int         bib_entry,
    return ref string      biblio_entry_str_json,
    return ref string[]    biblio_arr_json
  ) {
    mixin SiSUbiblio;
    auto jsn = BibJsnStr();
    auto rgx = Rgx();
    if (line.matchFirst(rgx.heading_biblio)) {
      type["biblio_section"] = TriState.on;
      type["blurb_section"] = State.off;
      type["glossary_section"] = State.off;
    }
    if (line.empty) {
      debug {
        debug(biblioblock) {
          writeln("---");
        }
        debug(biblioblockinclude) {
          writeln(biblio_entry_str_json.length);
        }
      }
      if ((bib_entry == State.off)
      && (biblio_entry_str_json.empty)) {
        bib_entry = State.on;
        biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr;
      } else if (!(biblio_entry_str_json.empty)) {
        bib_entry = State.off;
        if (!(biblio_entry_str_json == jsn.biblio_entry_tags_jsonstr)) {
          auto biblio_entry = parseJSON(biblio_entry_str_json);
          if (biblio_entry["fulltitle"].str.empty) {
            writeln("check problem entry (Title missing): ", biblio_entry_str_json);
          } else if ((biblio_entry["author_raw"].str.empty) && (biblio_entry["editor_raw"].str.empty)) {
            writeln("check problem entry (No author and no editor): ", biblio_entry_str_json);
          } else {
            biblio_arr_json ~= biblio_entry_str_json;
          }
          biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr;
        }
      } else { // CHECK ERROR
        writeln("?? 2. ERROR ", biblio_entry_str_json, "??");
        biblio_entry_str_json = "";
      }
    } else if (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 _group_block_(L,O,T)(
    return ref L line,
    return ref O an_object,
    return ref T type
  ) {
    debug(asserts) {
      static assert(is(typeof(line)      == char[]));
      static assert(is(typeof(an_object) == string[string]));
      static assert(is(typeof(type)      == int[string]));
    }
    auto rgx = Rgx();
    if (type["curly_group"] == State.on) {
      if (line.matchFirst(rgx.block_curly_group_close)) {
        debug(group) {
          writeln(line);
        }
        type["blocks"]      = TriState.closing;
        type["group"]       = TriState.closing;
        type["curly_group"] = TriState.off;
      } else {
        debug(group) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build group array (or string)
      }
    } else if (type["tic_group"] == TriState.on) {
      if (line.matchFirst(rgx.block_tic_close)) {
        debug(group) {
          writeln(line);
        }
        type["blocks"]    = TriState.closing;
        type["group"]     = TriState.closing;
        type["tic_group"] = TriState.off;
      } else {
        debug(group) {                              // group
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build group array (or string)
      }
    }
  }
  void _block_block_(L,O,T)(
    return ref L line,
    return ref O an_object,
    return ref T type
  ) {
    debug(asserts) {
      static assert(is(typeof(line)      == char[]));
      static assert(is(typeof(an_object) == string[string]));
      static assert(is(typeof(type)      == int[string]));
    }
    auto rgx = Rgx();
    if (type["curly_block"] == TriState.on) {
      if (line.matchFirst(rgx.block_curly_block_close)) {
        debug(block) {                             // block (curly) close
          writeln(line);
        }
        type["blocks"]      = TriState.closing;
        type["block"]       = TriState.closing;
        type["curly_block"] = TriState.off;
      } else {
        debug(block) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build block array (or string)
      }
    } else if (type["tic_block"] == TriState.on) {
      if (line.matchFirst(rgx.block_tic_close)) {
        debug(block) {
          writeln(line);
        }
        type["blocks"]    = TriState.closing;
        type["block"]     = TriState.closing;
        type["tic_block"] = TriState.off;
      } else {
        debug(block) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build block array (or string)
      }
    }
  }
  void _poem_block_(L,O,T,C,N,Ma)(
    L     line,
    return ref O an_object,
    return ref T type,
    return ref C cntr,
    N            obj_cite_number_poem,
    Ma           dochead_make_aa,
  ) {
    debug(asserts) {
      static assert(is(typeof(line)                 == char[]));
      static assert(is(typeof(an_object)            == string[string]));
      static assert(is(typeof(type)                 == int[string]));
      static assert(is(typeof(cntr)                 == int));
      static assert(is(typeof(obj_cite_number_poem) == string[string]));
      static assert(is(typeof(dochead_make_aa)      == string[string][string]));
    }
    auto rgx = Rgx();
    if (type["curly_poem"] == TriState.on) {
      if (line.matchFirst(rgx.block_curly_poem_close)) {
        an_object[an_object_key]="verse";
        debug(poem) {                               // poem (curly) close
          writefln(
            "* [poem curly] %s",
            line
          );
        }
        if (processing.length > 0) {
          an_object[an_object_key] = processing["verse"];
        }
        debug(poem) {                               // poem (curly) close
          writeln(__LINE__);
          writefln(
            "* %s %s",
            obj_cite_number,
            line
          );
        }
        if (an_object.length > 0) {
          debug(poem) {                             // poem (curly) close
            writeln(
              obj_cite_number,
              an_object[an_object_key]
            );
          }
          an_object["is"] = "verse";
          auto substantive_obj_misc_tuple =
            obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa);
          an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
          anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags];
          comp_obj_block                            = comp_obj_block.init;
          comp_obj_block.use                        = "body";
          comp_obj_block.is_of                      = "block";
          comp_obj_block.is_a                       = "verse";
          comp_obj_block.ocn                        = obj_cite_number;
          comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
          comp_obj_block.text                       = an_object["substantive"];
          comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg];
          comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star];
          comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links];
          the_document_body_section                 ~= comp_obj_block;
          object_reset(an_object);
          processing.remove("verse");
          ++cntr;
        }
        obj_cite_number_poem["end"] =
          obj_cite_number.to!string;
        type["blocks"] = TriState.closing;
        type["poem"] = TriState.closing;
        type["curly_poem"] = TriState.off;
      } else {
        processing["verse"] ~= line ~= "\n";
        if (type["verse_new"] == State.on) {
          obj_cite_number =
            ocn_emit(type["ocn_status"]);
          type["verse_new"] = State.off;
        } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) {
          verse_line = TriState.off;
          type["verse_new"] = State.on;
        }
        if (type["verse_new"] == State.on) {
          verse_line=1;
          an_object[an_object_key] = processing["verse"];
          debug(poem) {                          // poem verse
            writefln(
              "* %s curly\n%s",
              obj_cite_number,
              an_object[an_object_key]
            );
          }
          processing.remove("verse");
          an_object["is"] = "verse";
          auto comp_obj_location = node_construct.node_location_emitter(
            content_non_header,
            segment_anchor_tag_that_object_belongs_to,
            obj_cite_number,
            cntr,
            heading_ptr-1,
            an_object["is"]
          );
          auto substantive_obj_misc_tuple =
            obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa);
          an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
          anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags];
          comp_obj_block                            = comp_obj_block.init;
          comp_obj_block.use                        = "body";
          comp_obj_block.is_of                      = "block";
          comp_obj_block.is_a                       = "verse";
          comp_obj_block.ocn                        = obj_cite_number;
          comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
          comp_obj_block.text                       = an_object["substantive"];
          comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg];
          comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star];
          comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links];
          the_document_body_section                 ~= comp_obj_block;
          object_reset(an_object);
          processing.remove("verse");
          ++cntr;
        }
      }
    } else if (type["tic_poem"] == TriState.on) {
      if (auto m = line.matchFirst(rgx.block_tic_close)) { // tic_poem_close
        an_object[an_object_key]="verse";
        debug(poem) {                                       // poem (curly) close
          writefln(
            "* [poem tic] %s",
            line
          );
        }
        if (processing.length > 0) {
          an_object[an_object_key] = processing["verse"];
        }
        if (an_object.length > 0) {
          debug(poem) {                                     // poem (tic) close
            writeln(__LINE__);
            writeln(obj_cite_number, line);
          }
          processing.remove("verse");
          an_object["is"] = "verse";
          auto substantive_obj_misc_tuple =
            obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa);
          an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
          anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags];
          comp_obj_block                            = comp_obj_block.init;
          comp_obj_block.use                        = "body";
          comp_obj_block.is_of                      = "block";
          comp_obj_block.is_a                       = "verse";
          comp_obj_block.ocn                        = obj_cite_number;
          comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
          comp_obj_block.text                       = an_object["substantive"];
          comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg];
          comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star];
          comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links];
          the_document_body_section                 ~= comp_obj_block;
          obj_cite_number_poem["end"]               = obj_cite_number.to!string;
          object_reset(an_object);
          processing.remove("verse");
          ++cntr;
        }
        type["blocks"] = TriState.closing;
        type["poem"] = TriState.closing;
        type["tic_poem"] = TriState.off;
      } else {
        processing["verse"] ~= line ~= "\n";
        if (type["verse_new"] == State.on) {
          obj_cite_number =
            ocn_emit(type["ocn_status"]);
          type["verse_new"] = State.off;
        } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) {
          type["verse_new"] = State.on;
          verse_line = TriState.off;
        }
        if (type["verse_new"] == State.on) {
          verse_line=1;
          an_object[an_object_key] = processing["verse"];
          debug(poem) {                            // poem (tic) close
            writefln(
              "* %s tic\n%s",
              obj_cite_number,
              an_object[an_object_key]
            );
          }
          processing.remove("verse");
          an_object["is"] = "verse";
          auto comp_obj_location =
            node_construct.node_location_emitter(
              content_non_header,
              segment_anchor_tag_that_object_belongs_to,
              obj_cite_number,
              cntr,
              heading_ptr-1,
              an_object["is"]
            );
          auto substantive_obj_misc_tuple =
            obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa);
          an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
          anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags];
          comp_obj_block                            = comp_obj_block.init;
          comp_obj_block.use                        = "body";
          comp_obj_block.is_of                      = "block";
          comp_obj_block.is_a                       = "verse";
          comp_obj_block.ocn                        = obj_cite_number;
          comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
          comp_obj_block.text                       = an_object["substantive"];
          comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg];
          comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star];
          comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links];
          the_document_body_section                 ~= comp_obj_block;
          object_reset(an_object);
          processing.remove("verse");
          ++cntr;
        }
      }
    }
  }
  void _quote_block_(L,O,T)(
    return ref L line,
    return ref O an_object,
    return ref T type
  ) {
    debug(asserts) {
      static assert(is(typeof(line)      == char[]));
      static assert(is(typeof(an_object) == string[string]));
      static assert(is(typeof(type)      == int[string]));
    }
    auto rgx = Rgx();
    if (type["curly_quote"] == TriState.on) {
      if (line.matchFirst(rgx.block_curly_quote_close)) {
        debug(quote) {                              // quote (curly) close
          writeln(line);
        }
        type["blocks"]      = TriState.closing;
        type["quote"]       = TriState.closing;
        type["curly_quote"] = TriState.off;
      } else {
        debug(quote) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string)
      }
    } else if (type["tic_quote"] == TriState.on) {
      if (line.matchFirst(rgx.block_tic_close)) {
        debug(quote) {                              // quote (tic) close
          writeln(line);
        }
        type["blocks"]    = TriState.closing;
        type["quote"]     = TriState.closing;
        type["tic_quote"] = TriState.off;
      } else {
        debug(quote) {
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string)
      }
    }
  }
  void _table_block_(L,O,T)(
    return ref L line,
    return ref O an_object,
    return ref T type
  ) {
    debug(asserts) {
      static assert(is(typeof(line)      == char[]));
      static assert(is(typeof(an_object) == string[string]));
      static assert(is(typeof(type)      == int[string]));
    }
    auto rgx = Rgx();
    if (type["curly_table"] == TriState.on) {
      if (line.matchFirst(rgx.block_curly_table_close)) {
        debug(table) {                           // table (curly) close
          writeln(line);
        }
        type["blocks"] = TriState.closing;
        type["table"] = TriState.closing;
        type["curly_table"] = TriState.off;
      } else {
        debug(table) {                           // table
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";           // build table array (or string)
      }
    } else if (type["tic_table"] == TriState.on) {
      if (line.matchFirst(rgx.block_tic_close)) {
        debug(table) {                           // table (tic) close
          writeln(line);
        }
        type["blocks"] = TriState.closing;
        type["table"] = TriState.closing;
        type["tic_table"] = TriState.off;
      } else {
        debug(table) {                           // table
          writeln(line);
        }
        an_object[an_object_key] ~= line ~= "\n";           // build table array (or string)
      }
    }
  }
  void _block_flag_line_empty_(B)(
    B                                   bookindex_extract_hash,
    char[]                              line,
    return ref string[string]           an_object,
    return ref ObjGenericComposite[]    the_document_body_section,
    return ref string[][string][string] bookindex_unordered_hashes,
    return ref int                      obj_cite_number,
    return ref ObjGenericComposite      _comp_obj_heading,
    return ref int                      cntr,
    return ref int[string]              type,
    string[string]                      obj_cite_number_poem,
    string[string][string]              dochead_make_aa,
  ) {
    // line.empty, post contents, empty variables ---------------
    assert(
      line.empty,
      "line should be empty"
    );
    assert(
      (type["blocks"] == TriState.closing),
      "code block status: closed"
    );
    assertions_flag_types_block_status_none_or_closed(type);
    if (type["group"] == TriState.closing) {
      obj_cite_number =
        ocn_emit(type["ocn_status"]);
      an_object["bookindex_nugget"] =
        ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes =
        bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_number,
          segment_anchor_tag_that_object_belongs_to
        );
      an_object["is"] = "group";
      auto comp_obj_location =
        node_construct.node_location_emitter(
          content_non_header,
          segment_anchor_tag_that_object_belongs_to,
          obj_cite_number,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      auto substantive_obj_misc_tuple =
        obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa);
      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
      anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags];
      comp_obj_block                            = comp_obj_block.init;
      comp_obj_block.use                        = "body";
      comp_obj_block.is_of                      = "block";
      comp_obj_block.is_a                       = "group";
      comp_obj_block.ocn                        = obj_cite_number;
      comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
      comp_obj_block.text                       = an_object["substantive"];
      comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg];
      comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star];
      comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links];
      the_document_body_section                 ~= comp_obj_block;
      type["blocks"]                            = TriState.off;
      type["group"]                             = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
      ++cntr;
    } else if (type["block"] == TriState.closing) {
      obj_cite_number = ocn_emit(type["ocn_status"]);
      an_object["bookindex_nugget"] =
        ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes =
        bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_number,
          segment_anchor_tag_that_object_belongs_to
        );
      an_object["is"] = "block";
      auto comp_obj_location =
        node_construct.node_location_emitter(
          content_non_header,
          segment_anchor_tag_that_object_belongs_to,
          obj_cite_number,
          cntr,
          heading_ptr-1,
          an_object["is"]
         );
      auto substantive_obj_misc_tuple =
        obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa);
      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
      anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags];
      comp_obj_block                            = comp_obj_block.init;
      comp_obj_block.use                        = "body";
      comp_obj_block.is_of                      = "block";
      comp_obj_block.is_a                       = "block";
      comp_obj_block.ocn                        = obj_cite_number;
      comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
      comp_obj_block.text                       = an_object["substantive"];
      comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg];
      comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star];
      comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links];
      the_document_body_section                 ~= comp_obj_block;
      type["blocks"]                            = TriState.off;
      type["block"]                             = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
      ++cntr;
    } else if (type["code"] == TriState.closing) {
      obj_cite_number =
        ocn_emit(type["ocn_status"]);
      an_object["bookindex_nugget"] =
        ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes =
        bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_number,
          segment_anchor_tag_that_object_belongs_to
        );
      an_object["is"] = "code";
      auto comp_obj_location =
        node_construct.node_location_emitter(
          content_non_header,
          segment_anchor_tag_that_object_belongs_to,
          obj_cite_number,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      auto substantive_obj_misc_tuple =
        obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa);
      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
      anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags];
      comp_obj_code                             = comp_obj_code.init;
      comp_obj_code.use                         = "body";
      comp_obj_code.is_of                       = "block";
      comp_obj_code.is_a                        = "code";
      comp_obj_code.ocn                         = obj_cite_number;
      comp_obj_code.obj_cite_number             = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
      comp_obj_code.text                        = an_object["substantive"];
      comp_obj_code.inline_notes_reg            = substantive_obj_misc_tuple[sObj.notes_reg];
      comp_obj_code.inline_notes_star           = substantive_obj_misc_tuple[sObj.notes_star];
      comp_obj_code.inline_links                = substantive_obj_misc_tuple[sObj.links];
      the_document_body_section                 ~= comp_obj_code;
      type["blocks"]                            = TriState.off;
      type["code"]                              = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
      ++cntr;
    } else if (type["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_number,
          segment_anchor_tag_that_object_belongs_to
        );
      an_object["is"] = "verse"; // check also
      auto comp_obj_location =
        node_construct.node_location_emitter(
          content_non_header,
          segment_anchor_tag_that_object_belongs_to,
          obj_cite_number,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      comp_obj_poem_ocn                         = comp_obj_poem_ocn.init;
      comp_obj_poem_ocn.use                     = "body";
      comp_obj_poem_ocn.is_of                   = "block";
      comp_obj_poem_ocn.is_a                    = "poem";
      comp_obj_poem_ocn.ocn                     = obj_cite_number;
      comp_obj_poem_ocn.obj_cite_number         = (obj_cite_number_poem["start"], obj_cite_number_poem["end"]);
      comp_obj_poem_ocn.text                    = ""; // an_object["substantive"];
      the_document_body_section                 ~= comp_obj_poem_ocn;
      type["blocks"]                            = TriState.off;
      type["poem"]                              = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
    } else if (type["quote"] == TriState.closing) {
      obj_cite_number =
        ocn_emit(type["ocn_status"]);
      an_object["bookindex_nugget"] =
        ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes =
        bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_number,
          segment_anchor_tag_that_object_belongs_to
        );
      an_object["is"] = "quote";
      auto comp_obj_location =
        node_construct.node_location_emitter(
          content_non_header,
          segment_anchor_tag_that_object_belongs_to,
          obj_cite_number,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      auto substantive_obj_misc_tuple =
        obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa); // ...
      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; // ...
      anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags];
      comp_obj_block                            = comp_obj_block.init;
      comp_obj_block.use                        = "body";
      comp_obj_block.is_of                      = "block";
      comp_obj_block.is_a                       = "quote";
      comp_obj_block.ocn                        = obj_cite_number;
      comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
      comp_obj_block.text                       = an_object["substantive"];
      comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg];
      comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star];
      comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links];
      the_document_body_section                 ~= comp_obj_block;
      object_reset(an_object);
      processing.remove("verse");
      ++cntr;
      type["blocks"] = TriState.off;
      type["quote"] = TriState.off;
    } else if (type["table"] == TriState.closing) {
      obj_cite_number =
        ocn_emit(type["ocn_status"]);
      an_object["bookindex_nugget"] =
        ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
      bookindex_unordered_hashes =
        bookindex_extract_hash.bookindex_nugget_hash(
          an_object["bookindex_nugget"],
          obj_cite_number,
          segment_anchor_tag_that_object_belongs_to
        );
      an_object["is"] = "table";
      auto comp_obj_location =
        node_construct.node_location_emitter(
          content_non_header,
          segment_anchor_tag_that_object_belongs_to,
          obj_cite_number,
          cntr,
          heading_ptr-1,
          an_object["is"]
        );
      auto substantive_obj_misc_tuple =
        obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa);
      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content];
      anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags];
      comp_obj_block                            = comp_obj_block.init;
      comp_obj_block.use                        = "body";
      comp_obj_block.is_of                      = "block";
      comp_obj_block.is_a                       = "table";
      comp_obj_block.ocn                        = obj_cite_number;
      comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
      comp_obj_block.text                       = an_object["substantive"];
      comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg];
      comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star];
      comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links];
      the_document_body_section                 ~= comp_obj_block;
      type["blocks"]                            = TriState.off;
      type["table"]                             = TriState.off;
      object_reset(an_object);
      processing.remove("verse");
      ++cntr;
    }
  }
  auto _book_index_(L,I,O,T,B)(
    L      line,
    return ref I  book_idx_tmp,
    return ref O  an_object,
    return ref T  type,
    B             opt_action_bool,
  ) {
    debug(asserts) {
      static assert(is(typeof(line)            == char[]));
      static assert(is(typeof(book_idx_tmp)    == string));
      static assert(is(typeof(an_object)       == string[string]));
      static assert(is(typeof(type)            == int[string]));
      static assert(is(typeof(opt_action_bool) == bool[string]));
    }
    auto rgx = Rgx();
    if (auto m = line.match(rgx.book_index)) {
      /+ match book_index +/
      debug(bookindexmatch) {                       // book index
        writefln(
          "* [bookindex] %s\n",
          m.captures[1].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 +/
      type["book_index"] = State.on;
      if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) {
        book_idx_tmp = m.captures[1].to!string;
        debug(bookindexmatch) {                       // book index
          writefln(
            "* [bookindex] %s\n",
            book_idx_tmp,
          );
        }
      }
    } else if (type["book_index"] == State.on )  {
      /+ book_index flag set +/
      if (auto m = line.match(rgx.book_index_close))  {
        type["book_index"] = State.off;
        if (opt_action_bool["backmatter"]
        && opt_action_bool["section_bookindex"]) {
          an_object["bookindex_nugget"] = book_idx_tmp ~ m.captures[1].to!string;
          debug(bookindexmatch) {                     // book index
            writefln(
              "* [bookindex] %s\n",
              book_idx_tmp,
            );
          }
        }
        book_idx_tmp = "";
      } else {
        if (opt_action_bool["backmatter"]
        && opt_action_bool["section_bookindex"]) {
          book_idx_tmp ~= line;
        }
      }
    }
  }
  auto _heading_found_(L,X,H,R,T)(
    L     line,
    X     dochead_make_identify_unmarked_headings,
    return ref H heading_match_str,
    return ref R heading_match_rgx,
    return ref T type
  ) {
    debug(asserts) {
      static assert(is(typeof(line)                                    == char[]));
      static assert(is(typeof(dochead_make_identify_unmarked_headings) == string));
      static assert(is(typeof(heading_match_str)                       == string[string]));
      static assert(is(typeof(heading_match_rgx)                       == Regex!(char)[string]));
      static assert(is(typeof(type)                                    == int[string]));
    }
    auto rgx = Rgx();
    if ((dochead_make_identify_unmarked_headings.length > 2)
    && (type["make_headings"] == State.off)) {
      /+ headings found +/
      debug(headingsfound) {
        writeln(dochead_make_identify_unmarked_headings);
      }
      char[][] make_headings_spl =
        (cast(char[]) dochead_make_identify_unmarked_headings)
          .split(rgx.make_heading_delimiter);
      debug(headingsfound) {
        writeln(make_headings_spl.length);
        writeln(make_headings_spl);
      }
      switch (make_headings_spl.length) {
      case 7 :
        if (!empty(make_headings_spl[6])) {
          heading_match_str["h_4"] =
            "^(" ~ make_headings_spl[6].to!string ~ ")";
          heading_match_rgx["h_4"] =
            regex(heading_match_str["h_4"]);
        }
        goto case;
      case 6 :
        if (!empty(make_headings_spl[5])) {
          heading_match_str["h_3"] =
            "^(" ~ make_headings_spl[5].to!string ~ ")";
          heading_match_rgx["h_3"] =
            regex(heading_match_str["h_3"]);
        }
        goto case;
      case 5 :
        if (!empty(make_headings_spl[4])) {
          heading_match_str["h_2"] =
            "^(" ~ make_headings_spl[4].to!string ~ ")";
          heading_match_rgx["h_2"] =
            regex(heading_match_str["h_2"]);
        }
        goto case;
      case 4 :
        if (!empty(make_headings_spl[3])) {
          heading_match_str["h_1"] =
            "^(" ~ make_headings_spl[3].to!string ~ ")";
          heading_match_rgx["h_1"] =
            regex(heading_match_str["h_1"]);
        }
        goto case;
      case 3 :
        if (!empty(make_headings_spl[2])) {
          heading_match_str["h_D"] =
            "^(" ~ make_headings_spl[2].to!string ~ ")";
          heading_match_rgx["h_D"] =
            regex(heading_match_str["h_D"]);
        }
        goto case;
      case 2 :
        if (!empty(make_headings_spl[1])) {
          heading_match_str["h_C"] =
            "^(" ~ make_headings_spl[1].to!string ~ ")";
          heading_match_rgx["h_C"] =
            regex(heading_match_str["h_C"]);
        }
        goto case;
      case 1 :
        if (!empty(make_headings_spl[0])) {
          heading_match_str["h_B"] =
            "^(" ~ make_headings_spl[0].to!string ~ ")";
          heading_match_rgx["h_B"] =
            regex(heading_match_str["h_B"]);
        }
        break;
      default:
        break;
      }
      type["make_headings"] = State.on;
    }
  }
  auto _heading_make_set_(L,C,R,T)(
    L     line,
    C     line_occur,
    return ref R heading_match_rgx,
    return ref T type
  ) {
    debug(asserts) {
      static assert(is(typeof(line)              == char[]));
      static assert(is(typeof(line_occur)        == int[string]));
      static assert(is(typeof(heading_match_rgx) == Regex!(char)[string]));
      static assert(is(typeof(type)              == int[string]));
    }
    if ((type["make_headings"] == State.on)
    && ((line_occur["para"] == State.off)
    && (line_occur["heading"] == State.off))
    && ((type["para"] == State.off)
    && (type["heading"] == State.off))) {
      /+ heading make set +/
      if (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);
        }
      }
    }
  }
  auto _heading_matched_(L,C,O,K,Lv,Lc,T,Me)(
    return ref L  line,
    return ref C  line_occur,
    return ref O  an_object,
    return ref K  an_object_key,
    return ref Lv lv,
    return ref Lc collapsed_lev,
    return ref T  type,
    return ref Me dochead_meta_aa,
  ) {
    debug(asserts) {
      static assert(is(typeof(line)            == char[]));
      static assert(is(typeof(line_occur)      == int[string]));
      static assert(is(typeof(an_object)       == string[string]));
      static assert(is(typeof(an_object_key)   == string));
      static assert(is(typeof(lv)              == int[string]));
      static assert(is(typeof(collapsed_lev)   == int[string]));
      static assert(is(typeof(type)            == int[string]));
      static assert(is(typeof(dochead_meta_aa) == string[string][string]));
    }
    auto rgx = Rgx();
    if (auto m = line.match(rgx.heading)) {
      /+ heading match +/
      type["heading"] = State.on;
      if (line.match(rgx.heading_seg_and_above)) {
        type["biblio_section"] = State.off;
        type["glossary_section"] = State.off;
        type["blurb_section"] = State.off;
      }
      type["para"] = State.off;
      ++line_occur["heading"];
      an_object[an_object_key] ~= line ~= "\n";
      an_object["lev"] ~= m.captures[1];
      assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels
      switch (an_object["lev"]) {
      case "A":
        an_object[an_object_key]=(an_object[an_object_key])
          .replaceFirst(rgx.variable_doc_title,
            (dochead_meta_aa["title"]["full"] ~ ","))
          .replaceFirst(rgx.variable_doc_author,
            dochead_meta_aa["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;
      }
      debug(heading) {                         // heading
        writeln(line.strip);
      }
    }
  }
  void _para_match_(L,O,K,I,B,T,C)(
    return ref L  line,
    return ref O  an_object,
    return ref K  an_object_key,
    return ref I  indent,
    return ref B  bullet,
    return ref T  type,
    return ref C  line_occur,
  ) {
    debug(asserts) {
      static assert(is(typeof(line)          == char[]));
      static assert(is(typeof(an_object)     == string[string]));
      static assert(is(typeof(an_object_key) == string));
      static assert(is(typeof(indent)        == int[string]));
      static assert(is(typeof(bullet)        == bool));
      static assert(is(typeof(type)          == int[string]));
      static assert(is(typeof(line_occur)    == int[string]));
    }
    auto rgx = Rgx();
    if (line_occur["para"] == State.off) {
      line = font_faces_line(line);
      /+ para matches +/
      type["para"] = State.on;
      an_object[an_object_key] ~= line;        // body_nugget
      indent=[
        "hang_position" : 0,
        "base_position" : 0,
      ];
      bullet = false;
      if (auto m = line.matchFirst(rgx.para_indent)) {
        debug(paraindent) {                    // para indent
          writeln(line);
        }
        indent["hang_position"] = (m.captures[1]).to!int;
        indent["base_position"] = 0;
      } else if (line.matchFirst(rgx.para_bullet)) {
        debug(parabullet) {                    // para bullet
          writeln(line);
        }
        bullet = true;
      } else if (auto m = line.matchFirst(rgx.para_indent_hang)) {
        debug(paraindenthang) {                // para indent hang
          writeln(line);
        }
        indent=[
          "hang_position" : (m.captures[1]).to!int,
          "base_position" : (m.captures[2]).to!int,
        ];
      } else if (auto m = line.matchFirst(rgx.para_bullet_indent)) {
        debug(parabulletindent) {              // para bullet indent
          writeln(line);
        }
        indent=[
          "hang_position" : (m.captures[1]).to!int,
          "base_position" : 0,
        ];
        bullet = true;
      }
      ++line_occur["para"];
    }
  }
  auto font_faces_line(T)(
    return ref T  textline,
  ) {
    auto rgx = Rgx();
    if (textline.match(rgx.inline_faces_line)) {
      textline = (textline)
        .replaceFirst(rgx.inline_emphasis_line,   ("*{$1}*$2"))
        .replaceFirst(rgx.inline_bold_line,       ("!{$1}!$2"))
        .replaceFirst(rgx.inline_underscore_line, ("_{$1}_$2"))
        .replaceFirst(rgx.inline_italics_line,    ("/{$1}/$2"));
    }
    return textline;
  }
  /+ abstraction functions ↑ +/
  /+ ↓ abstraction function emitters +/
  struct OCNemitter {
    int obj_cite_number, obj_cite_number_;
    int ocn_emitter(int ocn_status_flag)
    in { assert(ocn_status_flag <= 3); }
    body {
      if (ocn_status_flag == 3) {
        obj_cite_number = obj_cite_number_ = 1;
      } else {
        obj_cite_number=(ocn_status_flag == 0)
        ? ++obj_cite_number_
        : 0;
      }
      assert(obj_cite_number >= 0);
      return obj_cite_number;
    }
    invariant() {
    }
  }
  /+ +/
  struct ObjInlineMarkupMunge {
    string[string] obj_txt;
    int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus;
    string asterisks_;
    string obj_txt_out, tail, note;
    auto rgx = Rgx();
    auto mkup = InlineMarkup();
    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;
    }
    string url_links(Ot)(Ot obj_txt_in) {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
      /+ url matched +/
      if (obj_txt_in.match(rgx.inline_url_generic)) {
        /+ link: naked url: http://url +/
        if (obj_txt_in.match(rgx.inline_link_naked_url)) {
          obj_txt_in = (obj_txt_in).replaceAll(
              rgx.inline_link_naked_url,
              ("$1"
                ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c
                ~  mkup.url_o ~ "$2" ~  mkup.url_c
                ~ "$3")            // ("$1{ $2 }$2$3")
            );
        }
        /+ link with helper for endnote including the url:
             {~^ link which includes url as footnote }http://url
           maps to:
             { link which includes url as footnote }http://url~{ { http://url }http://url }~
        +/
        if (obj_txt_in.match(rgx.inline_link_endnote_url_helper)) {
          obj_txt_in = (obj_txt_in).replaceAll(
            rgx.inline_link_endnote_url_helper_punctuated,
            (mkup.lnk_o ~ "$1" ~ mkup.lnk_c
              ~ mkup.url_o ~ "$2" ~ mkup.url_c
              ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c
              ~ mkup.url_o ~ "$2" ~ mkup.url_c
              ~  " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3")
          );
          obj_txt_in = (obj_txt_in).replaceAll(
            rgx.inline_link_endnote_url_helper,
            (mkup.lnk_o ~ "$1" ~ mkup.lnk_c
              ~ mkup.url_o ~ "$2" ~ mkup.url_c
              ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c
              ~ mkup.url_o ~ "$2" ~ mkup.url_c
              ~  " }~") // ("{ $1 }$2~{ { $2 }$2 }~")
          );
        }
        /+ link with regular markup:
           { linked text or image }http://url
        +/
        if (obj_txt_in.match(rgx.inline_link_markup_regular)) {
          obj_txt_in = (obj_txt_in).replaceAll(
            rgx.inline_link_markup_regular,
            ("$1"
              ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c
              ~  mkup.url_o ~ "$3" ~  mkup.url_c
              ~ "$4")            // ("$1{ $2 }$3$4")
          );
        }
      }
      return obj_txt_in;
    }
    auto footnotes_endnotes_markup_and_number_or_stars(Ot)(Ot obj_txt_in, bool reset_note_numbers) {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
      /+ endnotes (regular) +/
      bool flg_notes_reg  = false;
      bool flg_notes_star = 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_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 ~ to!string(n_foot) ~ " ")
              ) ~ "\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,
      );
      return t;
    }
    private auto object_notes_and_links_(Ot)(Ot obj_txt_in, bool reset_note_numbers=false)
    in {
      debug(asserts) {
        assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      obj_txt_out = "";
      bool urls = 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)
      );
      /+ url matched +/
      if (obj_txt_in.match(rgx.inline_url)) {
        urls = true;
        obj_txt_in = url_links(obj_txt_in);
      }
      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.captures[1]);
          writeln(m.hit);
        }
      }
      auto t = tuple(
        obj_txt_out,
        ftn[1],
        ftn[2],
        urls,
      );
      return t;
    }
    auto init()
    in { }
    body {
      auto t = object_notes_and_links_("");
      return t;
    }
    invariant() {
    }
    auto munge_heading(Ot)(Ot obj_txt_in, bool reset_note_numbers=false)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      obj_txt["munge"]=(obj_txt_in)
       .replaceFirst(rgx.heading, "")
       .replaceFirst(rgx.obj_cite_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(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      obj_txt["munge"]=(obj_txt_in)
        .replaceFirst(rgx.para_attribs, "")
        .replaceFirst(rgx.obj_cite_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;
    }
    auto munge_group(string obj_txt_in)
    in { }
    body {
      obj_txt["munge"]=obj_txt_in;
      auto t = object_notes_and_links_(obj_txt["munge"]);
      return t;
    }
    invariant() {
    }
    auto munge_block(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      obj_txt["munge"]=obj_txt_in;
      auto t = object_notes_and_links_(obj_txt["munge"]);
      return t;
    }
    invariant() {
    }
    auto munge_verse(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      obj_txt["munge"]=obj_txt_in;
      auto t = object_notes_and_links_(obj_txt["munge"]);
      return t;
    }
    invariant() {
    }
    string munge_code(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      obj_txt_in = (obj_txt_in).replaceAll(rgx.two_spaces, mkup.nbsp ~ mkup.nbsp);
      obj_txt["munge"] = obj_txt_in;
      return obj_txt["munge"];
    }
    invariant() {
    }
    string munge_table(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      obj_txt["munge"]=obj_txt_in;
      return obj_txt["munge"];
    }
    invariant() {
    }
    string munge_quote(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      obj_txt["munge"]=obj_txt_in;
      return obj_txt["munge"];
    }
    invariant() {
    }
    string munge_comment(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      obj_txt["munge"]=obj_txt_in;
      return obj_txt["munge"];
    }
    invariant() {
    }
  }
  struct ObjInlineMarkup {
    auto rgx = Rgx();
    auto munge = ObjInlineMarkupMunge();
    string[string] obj_txt;
    auto obj_inline_markup_and_anchor_tags_and_misc(O,K,Ma)(
      O  obj_,
      K  obj_key_,
      Ma dochead_make_aa
    )
    in {
      debug(asserts) {
        static assert(is(typeof(obj_)            == string[string]));
        static assert(is(typeof(obj_key_)        == string));
        static assert(is(typeof(dochead_make_aa) == string[string][string]));
      }
    }
    body {
      obj_txt["munge"] = obj_[obj_key_].dup;
      obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`)))
      ? obj_txt["munge"]
      : strip(obj_txt["munge"]);
      static __gshared string[] anchor_tags_ = [];
      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;
      switch (obj_["is"]) {
      case "heading":
        static __gshared string anchor_tag = "";
        // TODO WORK ON, you still need to ensure that level 1 anchor_tags are unique
        obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, dochead_make_aa);
        obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"]);
        if (auto m = obj_txt["munge"].match(rgx.heading_anchor_tag)) {
          anchor_tag = m.captures[1];
          anchor_tags_ ~= anchor_tag;
        } else if (obj_["lev"] == "1") {
          writeln("heading anchor tag missing: ", obj_txt["munge"]);
        }
        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["links"]      = x[3];
        break;
      }
      auto t = tuple(
        obj_txt["munge"],
        anchor_tags_,
        obj_notes_and_links["notes_reg"],
        obj_notes_and_links["notes_star"],
        obj_notes_and_links["links"],
      );
      anchor_tags_=[];
      return t;
    }
    invariant() {
    }
    auto _clean_heading_toc_(Toc)(
      Toc heading_toc_,
    ) {
     debug(asserts) {
       static assert(is(typeof(heading_toc_) == char[]));
     }
     auto m = (cast(char[]) heading_toc_).matchFirst(rgx.heading);
     heading_toc_ = (m.post).replaceAll(
       rgx.inline_notes_curly_gen,
       "");
     return heading_toc_;
    };
    auto table_of_contents_gather_headings(O,Ma,Ts,Ta,X,Toc)(
      O            obj_,
      Ma           dochead_make_aa,
      Ts           segment_anchor_tag_that_object_belongs_to,
      Ta           _anchor_tag,
      return ref X lev4_subtoc,
      Toc          the_table_of_contents_section,
    )
    in {
      debug(asserts) {
        static assert(is(typeof(obj_)                                      == string[string]));
        static assert(is(typeof(dochead_make_aa)                           == string[string][string]));
        static assert(is(typeof(segment_anchor_tag_that_object_belongs_to) == string));
        static assert(is(typeof(_anchor_tag)                               == string));
        static assert(is(typeof(lev4_subtoc)                               == string[][string]));
        static assert(is(typeof(the_table_of_contents_section)             == ObjGenericComposite[][string]));
      }
    }
    body {
      ObjGenericComposite comp_obj_toc;
      mixin InternalMarkup;
      auto mkup = InlineMarkup();
      char[] heading_toc_ = (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(
          "{ %s }#%s",
          heading_toc_,
          _anchor_tag,
        );
        toc_txt_= munge.url_links(toc_txt_);
        comp_obj_toc                       = comp_obj_toc.init;
        comp_obj_toc.use                   = "frontmatter";
        comp_obj_toc.is_of                 = "para";
        comp_obj_toc.is_a                  = "toc";
        comp_obj_toc.ocn                   = 0;
        comp_obj_toc.obj_cite_number       = "";
        comp_obj_toc.indent_hang           = indent["hang_position"];
        comp_obj_toc.indent_base           = indent["base_position"];
        comp_obj_toc.bullet                = false;
        comp_obj_toc.text                  = toc_txt_.to!string.strip;
        comp_obj_toc.inline_links          = true;
        the_table_of_contents_section["scroll"] ~= comp_obj_toc;
      } else {
        indent=[
          "hang_position" : 0,
          "base_position" : 0,
        ];
        comp_obj_toc                       = comp_obj_toc.init;
        comp_obj_toc.use                   = "frontmatter";
        comp_obj_toc.is_of                 = "para";
        comp_obj_toc.is_a                  = "toc";
        comp_obj_toc.ocn                   = 0;
        comp_obj_toc.obj_cite_number       = "";
        comp_obj_toc.indent_hang           = indent["hang_position"];
        comp_obj_toc.indent_base           = indent["base_position"];
        comp_obj_toc.bullet                = false;
        comp_obj_toc.text                  = "Table of Contents";
        comp_obj_toc.inline_links          = true;
        the_table_of_contents_section["scroll"] ~= comp_obj_toc;
      }
      comp_obj_toc                       = comp_obj_toc.init;
      comp_obj_toc.use                   = "frontmatter";
      comp_obj_toc.is_of                 = "para";
      comp_obj_toc.is_a                  = "toc";
      comp_obj_toc.ocn                   = 0;
      comp_obj_toc.obj_cite_number       = "";
      comp_obj_toc.bullet                = false;
      comp_obj_toc.inline_links          = true;
      switch (obj_["lev_markup_number"].to!int) {
      case 0:
        indent=[
          "hang_position" : 0,
          "base_position" : 0,
        ];
        toc_txt_ = "{ Table of Contents }" ~ mkup.mark_internal_site_lnk ~ "toc.fnSuffix";
        toc_txt_= munge.url_links(toc_txt_);
        comp_obj_toc.indent_hang             = indent["hang_position"];
        comp_obj_toc.indent_base             = indent["base_position"];
        comp_obj_toc.text                    = toc_txt_.to!string.strip;
        comp_obj_toc.inline_links            = true;
        the_table_of_contents_section["seg"] ~= comp_obj_toc;
        break;
      case 1: .. case 3:
        indent=[
          "hang_position" : obj_["lev_markup_number"].to!int,
          "base_position" : obj_["lev_markup_number"].to!int,
        ];
        toc_txt_ = format(
          "%s",
          heading_toc_,
        );
        toc_txt_= munge.url_links(toc_txt_);
        comp_obj_toc.indent_hang             = indent["hang_position"];
        comp_obj_toc.indent_base             = indent["base_position"];
        comp_obj_toc.text                    = toc_txt_.to!string.strip;
        comp_obj_toc.inline_links            = true;
        the_table_of_contents_section["seg"] ~= comp_obj_toc;
        break;
      case 4:
        toc_txt_ = format(
          "{ %s }%s%s%s",
          heading_toc_,
          mkup.mark_internal_site_lnk,
          segment_anchor_tag_that_object_belongs_to,
          ".fnSuffix",
        );
        lev4_subtoc[segment_anchor_tag_that_object_belongs_to] = [];
        toc_txt_= munge.url_links(toc_txt_);
        indent=[
          "hang_position" : obj_["lev_markup_number"].to!int,
          "base_position" : obj_["lev_markup_number"].to!int,
        ];
        comp_obj_toc.indent_hang             = indent["hang_position"];
        comp_obj_toc.indent_base             = indent["base_position"];
        comp_obj_toc.text                    = toc_txt_.to!string.strip;
        comp_obj_toc.inline_links            = true;
        the_table_of_contents_section["seg"] ~= comp_obj_toc;
        break;
      case 5: .. case 7:
        toc_txt_ = format(
          "{ %s }%s%s%s#%s",
          heading_toc_,
          mkup.mark_internal_site_lnk,
          segment_anchor_tag_that_object_belongs_to,
          ".fnSuffix",
          _anchor_tag,
        );
        subtoc_txt_ = format(
          "{ %s }#%s",
          heading_toc_,
          _anchor_tag,
        );
        lev4_subtoc[segment_anchor_tag_that_object_belongs_to]
        ~= obj_["lev_markup_number"] ~ "~ " ~ subtoc_txt_.to!string.strip;
        toc_txt_= munge.url_links(toc_txt_);
        indent=[
          "hang_position" : obj_["lev_markup_number"].to!int,
          "base_position" : obj_["lev_markup_number"].to!int,
        ];
        comp_obj_toc.indent_hang             = indent["hang_position"];
        comp_obj_toc.indent_base             = indent["base_position"];
        comp_obj_toc.text                    = toc_txt_.to!string.strip;
        comp_obj_toc.inline_links            = true;
        the_table_of_contents_section["seg"] ~= comp_obj_toc;
        break;
      default:
        break;
      }
      return the_table_of_contents_section;
    }
    invariant() {
    }
  private:
    static string _configured_auto_heading_numbering_and_segment_anchor_tags(M,O,Ma)(
      M  munge_,
      O  obj_,
      Ma dochead_make_aa
    ) {
      debug(asserts) {
        static assert(is(typeof(munge_)          == string));
        static assert(is(typeof(obj_)            == string[string]));
        static assert(is(typeof(dochead_make_aa) == string[string][string]));
      }
      if (dochead_make_aa["make"]["num_top"].length > 0) {
        static __gshared int heading_num_top_level=9;
        static __gshared int heading_num_depth=2;
        static __gshared int heading_num_0 = 0;
        static __gshared int heading_num_1 = 0;
        static __gshared int heading_num_2 = 0;
        static __gshared int heading_num_3 = 0;
        static __gshared string heading_number_auto_composite = "";
        if (heading_num_top_level==9) {
          if (dochead_make_aa["make"]["num_depth"].length > 0) {
            heading_num_depth = dochead_make_aa["make"]["num_depth"].to!uint;
          }
          switch (dochead_make_aa["make"]["num_top"]) {
          case "A":
            break;
          case "B":
            heading_num_top_level=1;
            break;
          case "C":
            heading_num_top_level=2;
            break;
          case "D":
            heading_num_top_level=3;
            break;
          case "1":
            heading_num_top_level=4;
            break;
          case "2":
            heading_num_top_level=5;
            break;
          case "3":
            heading_num_top_level=6;
            break;
          case "4":
            heading_num_top_level=7;
            break;
          default:
            break;
          }
        }
        /+ num_depth minimum 0 (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement +/
        if (
          heading_num_top_level
          > obj_["lev_markup_number"].to!uint
        ) {
          heading_num_0 = 0;
          heading_num_1 = 0;
          heading_num_2 = 0;
          heading_num_3 = 0;
        } else if (
          heading_num_top_level
          == obj_["lev_markup_number"].to!uint
        ) {
          heading_num_0 ++;
          heading_num_1 = 0;
          heading_num_2 = 0;
          heading_num_3 = 0;
        } else if (
          heading_num_top_level
          == (obj_["lev_markup_number"].to!uint - 1)
        ) {
          heading_num_1 ++;
          heading_num_2 = 0;
          heading_num_3 = 0;
        } else if (
          heading_num_top_level
          == (obj_["lev_markup_number"].to!uint - 2)
        ) {
          heading_num_2 ++;
          heading_num_3 = 0;
        } else if (
          heading_num_top_level
          == (obj_["lev_markup_number"].to!uint - 3)
        ) {
          heading_num_3 ++;
        }
        if (heading_num_3 > 0) {
          heading_number_auto_composite =
            (heading_num_depth == 3)
            ? ( 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 =
            ((heading_num_depth >= 2)
            && (heading_num_depth <= 3))
            ?  ( 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 =
            ((heading_num_depth >= 1)
            && (heading_num_depth <= 3))
            ? ( heading_num_0.to!string ~ "."
                 ~ heading_num_1.to!string
               )
            : "";
        } else if (heading_num_0 > 0) {
          heading_number_auto_composite =
            ((heading_num_depth >= 0)
            && (heading_num_depth <= 3))
            ?  (heading_num_0.to!string)
            : "";
        } else {
          heading_number_auto_composite = "";
        }
        debug(heading_number_auto) {
          writeln(heading_number_auto_composite);
        }
        if (!(munge_.match(rgx.heading_anchor_tag))
        && !empty(heading_number_auto_composite)) {
          munge_=(munge_)
          .replaceFirst(rgx.heading,
            "$1~$2 " ~ heading_number_auto_composite ~ ". ")
          .replaceFirst(rgx.heading_marker_missing_tag,
            "$1~" ~ heading_number_auto_composite ~ " ");
        }
      }
      return munge_;
    }
  
  
    static string _make_segment_anchor_tags_if_none_provided(M,Lv)(M munge_, Lv lev_) {
      debug(asserts) {
        static assert(is(typeof(munge_) == string));
        static assert(is(typeof(lev_)   == string));
      }
      if (!(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] ~ " ");
          } 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"
          static __gshared int heading_num_lev1 = 0;
          heading_num_lev1 ++;
          munge_=(munge_).replaceFirst(
            rgx.heading_marker_missing_tag,
            "$1~" ~ "x" ~ heading_num_lev1.to!string ~ " ");
        }
      }
      return munge_;
    }
    unittest {
      string txt_lev="1";
      string txt_in, txt_out;
  
      txt_in = "1~copyright Copyright";
      txt_out ="1~copyright Copyright";
      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
  
      txt_in = "1~ 6. Writing Copyright Licenses";
      txt_out ="1~s6 6. Writing Copyright Licenses";
      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
  
      txt_in= "1~ 1. Reinforcing trends";
      txt_out= "1~s1 1. Reinforcing trends";
      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
  
      txt_in= "1~ 11 SCIENCE AS A COMMONS";
      txt_out= "1~s11 11 SCIENCE AS A COMMONS";
      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
  
      txt_in= "1~ Chapter 1";
      txt_out="1~chapter_1 Chapter 1";
      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
  
      txt_in= "1~ Chapter 1.";
      txt_out="1~chapter_1 Chapter 1.";
      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
  
      txt_in= "1~ Chapter 1: Done";
      txt_out="1~chapter_1 Chapter 1: Done";
      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
  
      txt_in=  "1~ Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment";
      txt_out= "1~chapter_11 Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment";
      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
  
      txt_in= "1~ CHAPTER I.";
      txt_out="1~x1 CHAPTER I.";
      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
  
      txt_in= "1~ CHAPTER II.";
      txt_out="1~x2 CHAPTER II.";
      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out);
    }
  }
  /+ +/
  struct ObjAttributes {
    string[string] _obj_attrib;
    string obj_attributes(Oi,OR,OH)(
      Oi obj_is_,
      OR obj_raw,
      OH _comp_obj_heading,
    )
    in {
      debug(asserts) {
        static assert(is(typeof(obj_is_)           == string));
        static assert(is(typeof(obj_raw)           == string));
        static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite));
      }
    }
    body {
      scope(exit) {
        destroy(obj_is_);
        destroy(obj_raw);
        destroy(_comp_obj_heading);
      }
      _obj_attrib["json"] ="{";
      switch (obj_is_) {
      case "heading":
        _obj_attrib["json"] ~= _heading(obj_raw);
        break;
      case "para":
        _obj_attrib["json"] ~= _para_and_blocks(obj_raw)
        ~ _para(obj_raw);
        break;
      case "code":
        _obj_attrib["json"] ~= _code(obj_raw);
        break;
      case "group":
        _obj_attrib["json"] ~= _para_and_blocks(obj_raw)
        ~ _group(obj_raw);
        break;
      case "block":
        _obj_attrib["json"] ~= _para_and_blocks(obj_raw)
        ~ _block(obj_raw);
        break;
      case "verse":
        _obj_attrib["json"] ~= _verse(obj_raw);
        break;
      case "quote":
        _obj_attrib["json"] ~= _quote(obj_raw);
        break;
      case "table":
        _obj_attrib["json"] ~= _table(obj_raw);
        break;
      case "comment":
        _obj_attrib["json"] ~= _comment(obj_raw);
        break;
      default:
        _obj_attrib["json"] ~= _para(obj_raw);
        break;
      }
      _obj_attrib["json"] ~=" }";
      _obj_attrib["json"]=_set_additional_values_parse_as_json(_obj_attrib["json"], obj_is_, _comp_obj_heading);
      debug(structattrib) {
        if (oa_j["is"].str() == "heading") {
          writeln(_obj_attrib["json"]);
          writeln(
            "is: ", oa_j["is"].str(),
            "; obj_cite_number: ", oa_j["obj_cite_number"].integer()
          );
        }
      }
      return _obj_attrib["json"];
    }
    invariant() {
    }
    private:
    string _obj_attributes;
    string _para_and_blocks(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      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.captures[1].to!string ~ ","
        ~ " \"indent_base\": " ~ m.captures[1].to!string ~ ",";
      } else if (auto m = obj_txt_in.matchFirst(rgx.para_indent_hang)) {
        _obj_attributes =" \"bullet\": \"false\","
        ~ " \"indent_hang\": " ~ m.captures[1].to!string ~ ","
        ~ " \"indent_base\": " ~  m.captures[2].to!string ~ ",";
      } else if (auto m = obj_txt_in.matchFirst(rgx.para_indent)) {
        _obj_attributes =" \"bullet\": \"false\","
        ~ " \"indent_hang\": " ~ m.captures[1].to!string ~ ","
        ~ " \"indent_base\": " ~ m.captures[1].to!string ~ ",";
      } else {
        _obj_attributes =" \"bullet\": \"false\","
        ~ " \"indent_hang\": 0,"
        ~ " \"indent_base\": 0,";
      }
      return _obj_attributes;
    }
    string _heading(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"para\","
      ~ " \"is\": \"heading\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string _para(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"para\","
      ~ " \"is\": \"para\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string _group(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"group\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string _block(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"block\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string _verse(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"verse\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string _code(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"code\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string _table(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"table\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string _quote(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      _obj_attributes = " \"use\": \"content\","
      ~ " \"of\": \"block\","
      ~ " \"is\": \"quote\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string _comment(Ot)(Ot obj_txt_in)
    in {
      debug(asserts) {
        static assert(is(typeof(obj_txt_in) == string));
      }
    }
    body {
      _obj_attributes = " \"use\": \"comment\","
      ~ " \"of\": \"comment\","
      ~ " \"is\": \"comment\"";
      return _obj_attributes;
    }
    invariant() {
    }
    string _set_additional_values_parse_as_json(OA,Oi,OH)(
      OA _obj_attrib,
      Oi obj_is_,
      OH _comp_obj_heading,
    ) {
      debug(asserts) {
        static assert(is(typeof(_obj_attrib)       == string));
        static assert(is(typeof(obj_is_)           == string));
        static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite));
      }
      JSONValue oa_j = parseJSON(_obj_attrib);
      assert(
        (oa_j.type == JSON_TYPE.OBJECT)
      );
      if (obj_is_ == "heading") {
        oa_j.object["obj_cite_number"] = _comp_obj_heading.ocn;
        oa_j.object["lev_markup_number"] = _comp_obj_heading.heading_lev_markup;
        oa_j.object["lev_collapsed_number"] = _comp_obj_heading.heading_lev_collapsed;
        oa_j.object["heading_ptr"] =
          _comp_obj_heading.ptr_heading;
        oa_j.object["doc_object_ptr"] =
          _comp_obj_heading.ptr_doc_object;
      }
      oa_j.object["parent_obj_cite_number"] = _comp_obj_heading.parent_ocn;
      oa_j.object["parent_lev_markup_number"] = _comp_obj_heading.parent_lev_markup;
      _obj_attrib = oa_j.toString();
      return _obj_attrib;
    }
  }
  /+ +/
  struct BookIndexNuggetHash {
    string main_term, sub_term, sub_term_bits;
    int obj_cite_number_offset, obj_cite_number_endpoint;
    string[] obj_cite_numbers;
    string[][string][string] bi;
    string[][string][string] hash_nugget;
    string[] bi_main_terms_split_arr;
    string[][string][string] bookindex_nugget_hash(BI,N,S)(
      BI bookindex_section,
      N  obj_cite_number,
      S  segment_anchor_tag,
    )
    in {
      debug(asserts) {
        static assert(is(typeof(bookindex_section) == string));
        static assert(is(typeof(obj_cite_number)   == int));
      }
      debug(bookindexraw) {
        if (!bookindex_section.empty) {
          writeln(
            "* [bookindex] ",
            "[", obj_cite_number.to!string, ": ", segment_anchor_tag, "] ", bookindex_section
          );
        }
      }
    }
    body {
      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_obj_cite_numbers_match)
          ) {
            main_term = m.captures[1].strip;
            obj_cite_number_offset = m.captures[2].to!int;
            obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset);
            obj_cite_numbers ~= (obj_cite_number.to!string ~ "-" ~ to!string(obj_cite_number_endpoint)
            ~ ":" ~ segment_anchor_tag);
          } else {
            main_term = bi_main_term_and_rest[0].strip;
            obj_cite_numbers ~= obj_cite_number.to!string
            ~ ":" ~ segment_anchor_tag;
          }
          bi[main_term]["_a"] ~= obj_cite_numbers;
          obj_cite_numbers=null;
          if (bi_main_term_and_rest.length > 1) {
            auto bi_sub_terms_split_arr =
              bi_main_term_and_rest[1].split(
                rgx.bi_sub_terms_plus_obj_cite_number_offset_split
              );
            foreach (sub_terms_bits; bi_sub_terms_split_arr) {
              if (auto m = sub_terms_bits.match(rgx.bi_term_and_obj_cite_numbers_match)) {
                sub_term = m.captures[1].strip;
                obj_cite_number_offset = m.captures[2].to!int;
                obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset);
                obj_cite_numbers ~= (obj_cite_number.to!string ~ " - " ~ to!string(obj_cite_number_endpoint)
                ~ ":" ~ segment_anchor_tag);
              } else {
                sub_term = sub_terms_bits.strip;
                obj_cite_numbers ~= to!string(obj_cite_number)
                ~ ":" ~ segment_anchor_tag;
              }
              if (!empty(sub_term)) {
                bi[main_term][sub_term] ~= obj_cite_numbers;
              }
              obj_cite_numbers=null;
            }
          }
        }
      }
      hash_nugget = bi;
      return hash_nugget;
    }
    invariant() {
    }
  }
  struct BookIndexReportIndent {
    int mkn, skn;
    auto bookindex_report_indented(BI)(
      BI bookindex_unordered_hashes
    ) {
      debug(asserts) {
        static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string]));
      }
      auto mainkeys=
        bookindex_unordered_hashes.byKey.array.sort().release;
      foreach (mainkey; mainkeys) {
        debug(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;
    auto rgx = Rgx();
    auto munge = ObjInlineMarkupMunge();
    auto bookindex_write_section(BI)(
      BI bookindex_unordered_hashes
    ) {
      debug(asserts) {
        static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string]));
      }
      auto mainkeys=bookindex_unordered_hashes.byKey.array.sort().release;
      foreach (mainkey; mainkeys) {
        write("_0_1 !{", mainkey, "}! ");
        foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
          auto go = (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().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(BI,N,B)(
      BI bookindex_unordered_hashes,
      N  obj_cite_number,
      B  opt_action_bool,
    ) {
      debug(asserts) {
        static assert(is(typeof(bookindex_unordered_hashes)                == string[][string][string]));
        static assert(is(typeof(obj_cite_number)                           == int));
        static assert(is(typeof(opt_action_bool)                           == bool[string]));
      }
      mixin SiSUnode;
      mixin InternalMarkup;
      auto mkup = InlineMarkup();
      string type_is;
      string lev;
      int heading_lev_markup, heading_lev_collapsed;
      string attrib;
      int[string] indent;
      auto mainkeys =
        bookindex_unordered_hashes.byKey.array.sort().release;
      ObjGenericComposite[][string] bookindex_section;
      ObjGenericComposite comp_obj_heading_, comp_obj_para;
      auto node_para_int_ = node_metadata_para_int;
      auto node_para_str_ = node_metadata_para_str;
      if ((mainkeys.length > 0)
      && (opt_action_bool["backmatter"]
      && opt_action_bool["section_bookindex"])) {
        string bi_tmp_seg, bi_tmp_scroll;
        string[] bi_tmp_tags;
        comp_obj_heading_                       = comp_obj_heading_.init;
        comp_obj_heading_.use                   = "backmatter";
        comp_obj_heading_.is_of                 = "para";
        comp_obj_heading_.is_a                  = "heading";
        comp_obj_heading_.text                  = "Book Index";
        comp_obj_heading_.ocn                   = 0;
        comp_obj_heading_.obj_cite_number       = "";
        comp_obj_heading_.marked_up_level       = "B";
        comp_obj_heading_.heading_lev_markup    = 1;
        comp_obj_heading_.heading_lev_collapsed = 1;
        comp_obj_heading_.parent_ocn            = 1;
        comp_obj_heading_.parent_lev_markup     = 0;
        comp_obj_heading.inline_links           = true;
        bookindex_section["scroll"]             ~= comp_obj_heading_;
        bookindex_section["seg"]                ~= comp_obj_heading_;
        ++obj_cite_number;
        ++mkn;
        comp_obj_heading_                       = comp_obj_heading_.init;
        comp_obj_heading_.use                   = "backmatter";
        comp_obj_heading_.is_of                 = "para";
        comp_obj_heading_.is_a                  = "heading";
        comp_obj_heading_.text                  = "Index";
        comp_obj_heading_.ocn                   = 0;
        comp_obj_heading_.obj_cite_number       = "";
        comp_obj_heading_.segment_anchor_tag    = "bookindex";
        comp_obj_heading_.marked_up_level       = "1";
        comp_obj_heading_.heading_lev_markup    = 4;
        comp_obj_heading_.heading_lev_collapsed = 2;
        comp_obj_heading_.parent_ocn            = 1;
        comp_obj_heading_.parent_lev_markup     = 0;
        comp_obj_heading.inline_links           = false;
        comp_obj_heading_.anchor_tags           = ["bookindex"];
        bookindex_section["scroll"]             ~= comp_obj_heading_;
        bookindex_section["seg"]                ~= comp_obj_heading_;
        ++obj_cite_number;
        ++mkn;
        import std.array : appender;
        auto buffer = appender!(char[])();
        string[dchar] transTable = [' ' : "_"];
        foreach (mainkey; mainkeys) {
          bi_tmp_tags = [""];
          bi_tmp_scroll = "!{" ~ mainkey ~ "}! ";
          buffer.clear();
          bi_tmp_tags ~= translate(mainkey, transTable);
          bi_tmp_seg = "!{" ~ mainkey ~ "}! ";
          auto bkidx_lnk_seg(string locs) {
            string markup = "";
            if (auto m = locs.matchFirst(rgx.book_index_go_seg)) {
              markup =
                munge.url_links("{ " ~ m["link"] ~ " }"
                ~ mkup.mark_internal_site_lnk ~ m["seg"] ~ ".fnSuffix"
                ~ "#" ~ m["ocn"] ~ ", ");
            } else {
              writeln(__LINE__, ": ", locs);
            }
            return markup;
          }
          auto bkidx_lnk_scroll(string locs) {
            string markup = "";
            if (auto m = locs.matchFirst(rgx.book_index_go)) {
              markup =
                munge.url_links("{ " ~ m["link"] ~ " }"
                ~ mkup.mark_internal_site_lnk
                ~ "#" ~ m["ocn"] ~ ", ");
            } else {
              writeln(__LINE__, ": ", locs);
            }
            return markup;
          }
          foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
            bi_tmp_scroll ~= bkidx_lnk_scroll(ref_);
            bi_tmp_seg ~= bkidx_lnk_seg(ref_);
          }
          bi_tmp_scroll ~= " \\\\\n    ";
          bi_tmp_seg ~= " \\\\\n    ";
          bookindex_unordered_hashes[mainkey].remove("_a");
          auto subkeys =
            bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
          foreach (subkey; subkeys) {
            bi_tmp_scroll ~= subkey ~ ", ";
            buffer.clear();
            bi_tmp_tags ~= translate(subkey, transTable);
            bi_tmp_seg ~= subkey ~ ", ";
            foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
              bi_tmp_scroll ~= bkidx_lnk_scroll(ref_);
              bi_tmp_seg ~= bkidx_lnk_seg(ref_);
            }
            bi_tmp_scroll ~= " \\\\\n    ";
            bi_tmp_seg ~= " \\\\\n    ";
            ++skn;
          }
          bi_tmp_scroll                       = (bi_tmp_scroll).replaceFirst(rgx.trailing_linebreak, "");
          bi_tmp_seg                          = (bi_tmp_seg).replaceFirst(rgx.trailing_linebreak, "");
          comp_obj_para                       = comp_obj_para.init;
          comp_obj_para.use                   = "backmatter";
          comp_obj_para.is_of                 = "para";
          comp_obj_para.is_a                  = "bookindex";
          comp_obj_para.text                  = bi_tmp_scroll.to!string.strip;
          comp_obj_para.ocn                   = obj_cite_number;
          comp_obj_para.obj_cite_number       = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
          comp_obj_para.anchor_tags           = bi_tmp_tags;
          comp_obj_para.indent_hang           = 0;
          comp_obj_para.indent_base           = 1;
          comp_obj_para.bullet                = false;
          comp_obj_para.inline_links          = true;
          bookindex_section["scroll"]         ~= comp_obj_para;
          comp_obj_para.text                  = bi_tmp_seg.to!string.strip;
          bookindex_section["seg"]            ~= comp_obj_para;
          ++obj_cite_number;
          ++mkn;
        }
      } else {                              // no book index, (figure out what to do here)
        comp_obj_heading_                       = comp_obj_heading_.init;
        comp_obj_heading_.text                  = "(skip) there is no Book Index";
        comp_obj_heading_.ocn                   = 0;
        comp_obj_heading_.obj_cite_number       = "";
        comp_obj_heading_.marked_up_level       = "B";
        comp_obj_heading_.heading_lev_markup    = 1;
        comp_obj_heading_.heading_lev_collapsed = 1;
        comp_obj_heading_.parent_ocn            = 1;
        comp_obj_heading_.parent_lev_markup     = 0;
        bookindex_section["scroll"]             ~= comp_obj_heading_;
        bookindex_section["seg"]                ~= comp_obj_heading_;
      }
      auto t = tuple(bookindex_section, obj_cite_number);
      return t;
    }
  }
  /+ +/
  struct NotesSection {
    string[string] object_notes;
    int previous_count;
    int mkn;
    auto rgx = Rgx();
    private auto gather_notes_for_endnote_section(
      ObjGenericComposite[] contents_am,
      string                segment_anchor_tag_that_object_belongs_to,
      int                   cntr,
    )
    in {
      assert((contents_am[cntr].is_a == "para")
      || (contents_am[cntr].is_a == "heading")
      || (contents_am[cntr].is_a == "group"));
      assert(cntr >= previous_count);
      previous_count=cntr;
      assert(
        (contents_am[cntr].text).match(
        rgx.inline_notes_delimiter_al_regular_number_note)
      );
    }
    body {
      mixin InternalMarkup;
      auto mkup = InlineMarkup();
      auto munge = ObjInlineMarkupMunge();
      foreach(
        m;
        (contents_am[cntr].text).matchAll(
          rgx.inline_notes_delimiter_al_regular_number_note
        )
      ) {
        debug(endnotes_build) {
          writeln(
            "{^{", m.captures[1], ".}^}"
            ~ mkup.mark_internal_site_lnk,
            segment_anchor_tag_that_object_belongs_to,
              ".fnSuffix#noteref_\n  ", m.captures[1], " ",
            m.captures[2]); // sometimes need segment name (segmented html & epub)
        }
        // TODO NEXT you need anchor for segments at this point ->
        object_notes["anchor"] ~= "note_" ~ m.captures[1] ~ "』";
        object_notes["notes"] ~= (segment_anchor_tag_that_object_belongs_to.empty)
        ? (munge.url_links(
            "{^{" ~ m.captures[1] ~ ".}^}#noteref_"
            ~ m.captures[1]) ~ " "
            ~ m.captures[2] ~ "』"
          )
        : (munge.url_links(
            "{^{" ~ m.captures[1] ~ ".}^}"
             ~ mkup.mark_internal_site_lnk
             ~ segment_anchor_tag_that_object_belongs_to
             ~ ".fnSuffix#noteref_"
             ~ m.captures[1]) ~ " "
             ~ m.captures[2] ~ "』"
          );
      }
      return object_notes;
    }
    private auto gathered_notes()
    in {
    }
    body {
      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(
      int            obj_cite_number,
      bool[string]   opt_action_bool,
    )
    in {
    }
    body {
      mixin SiSUnode;
      ObjGenericComposite[] the_endnotes_section;
      auto endnotes_ = gathered_notes();
      string type_is;
      string lev, lev_markup_number, lev_collapsed_number;
      string attrib;
      int[string] indent;
      ObjGenericComposite comp_obj_heading_;
      if ((endnotes_["notes"].length > 0)
      && (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"])) {
        comp_obj_heading_                       = comp_obj_heading_.init;
        comp_obj_heading_.use                   = "backmatter";
        comp_obj_heading_.is_of                 = "para";
        comp_obj_heading_.is_a                  = "heading";
        comp_obj_heading_.text                  = "Endnotes";
        comp_obj_heading_.ocn                   = 0;
        comp_obj_heading_.obj_cite_number       = "";
        comp_obj_heading_.marked_up_level       = "B";
        comp_obj_heading_.heading_lev_markup    = 1;
        comp_obj_heading_.heading_lev_collapsed = 1;
        comp_obj_heading_.parent_ocn            = 1;
        comp_obj_heading_.parent_lev_markup     = 0;
        the_endnotes_section                    ~= comp_obj_heading_;
        ++obj_cite_number;
        ++mkn;
        comp_obj_heading_                       = comp_obj_heading_.init;
        comp_obj_heading_.use                   = "backmatter";
        comp_obj_heading_.is_of                 = "para";
        comp_obj_heading_.is_a                  = "heading";
        comp_obj_heading_.text                  = "Endnotes";
        comp_obj_heading_.ocn                   = 0;
        comp_obj_heading_.obj_cite_number       = "";
        comp_obj_heading_.segment_anchor_tag    = "endnotes";
        comp_obj_heading_.marked_up_level       = "1";
        comp_obj_heading_.heading_lev_markup    = 4;
        comp_obj_heading_.heading_lev_collapsed = 2;
        comp_obj_heading_.parent_ocn            = 1;
        comp_obj_heading_.parent_lev_markup     = 0;
        comp_obj_heading_.anchor_tags           = ["endnotes"];
        the_endnotes_section                    ~= comp_obj_heading_;
        ++obj_cite_number;
        ++mkn;
      } else {
        comp_obj_heading_                       = comp_obj_heading_.init;
        comp_obj_heading_.use                   = "empty";
        comp_obj_heading_.is_of                 = "para";
        comp_obj_heading_.is_a                  = "heading";
        comp_obj_heading_.text                  = "(skip) there are no Endnotes";
        comp_obj_heading_.ocn                   = 0;
        comp_obj_heading_.obj_cite_number       = "";
        comp_obj_heading_.marked_up_level       = "B";
        comp_obj_heading_.heading_lev_markup    = 1;
        comp_obj_heading_.heading_lev_collapsed = 1;
        comp_obj_heading_.parent_ocn            = 1;
        comp_obj_heading_.parent_lev_markup     = 0;
        the_endnotes_section                    ~= comp_obj_heading_;
      }
      if (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"]) {
        ObjGenericComposite comp_obj_endnote_;
        comp_obj_endnote_                       = comp_obj_endnote_.init;
        comp_obj_endnote_.use                   = "backmatter";
        comp_obj_endnote_.is_of                 = "para";
        comp_obj_endnote_.is_a                  = "endnote";
        comp_obj_endnote_.ocn                   = 0;
        comp_obj_heading_.obj_cite_number       = "";
        comp_obj_endnote_.indent_hang           = 0;
        comp_obj_endnote_.indent_base           = 0;
        comp_obj_endnote_.bullet                = false;
        foreach (i, endnote; endnotes_["notes"]) {
          auto     m                            = endnote.matchFirst(rgx.note_ref);
          string   notenumber                   = m.captures[1].to!string;
          string   anchor_tag                   = "note_" ~ notenumber;
          comp_obj_endnote_.anchor_tags         = [ endnotes_["anchor"][i] ];
          comp_obj_endnote_.inline_links        = true;
          comp_obj_endnote_.text                = endnote.strip;
          the_endnotes_section                  ~= comp_obj_endnote_;
        }
      }
      auto t = tuple(the_endnotes_section, obj_cite_number);
      return t;
    }
  }
  /+ +/
  struct Bibliography {
    public JSONValue[] _bibliography_(Bi,BJ)(
      return ref Bi biblio_unsorted_incomplete,
      return ref BJ bib_arr_json
    )
    in {
      debug(asserts) {
        static assert(is(typeof(biblio_unsorted_incomplete) == string[]));
        static assert(is(typeof(bib_arr_json)               == JSONValue[]));
      }
   }
    body {
      JSONValue[] biblio_unsorted =
        _biblio_unsorted_complete_(biblio_unsorted_incomplete, bib_arr_json);
      biblio_arr_json = [];
      biblio_unsorted_incomplete = [];
      JSONValue[] biblio_sorted__ = biblio_sort(biblio_unsorted);
      biblio_debug(biblio_sorted__);
      debug(biblio0) {
        writeln("---");
        writeln("unsorted incomplete: ", biblio_unsorted_incomplete.length);
        writeln("json:                ", bib_arr_json.length);
        writeln("unsorted:            ", biblio_unsorted.length);
        writeln("sorted:              ", biblio_sorted__.length);
        int cntr;
        int[7] x;
        while (cntr < x.length) {
          writeln(cntr, ": ", biblio_sorted__[cntr]["fulltitle"]);
          cntr++;
        }
      }
      return biblio_sorted__;
    }
    final private JSONValue[] _biblio_unsorted_complete_(Bi,BJ)(
      Bi            biblio_unordered,
      return ref BJ bib_arr_json
    ) {
      debug(asserts) {
        static assert(is(typeof(biblio_unordered) == string[]));
        static assert(is(typeof(bib_arr_json)     == JSONValue[]));
      }
      foreach (bibent; biblio_unordered) {
        // update bib to include deemed_author, needed for:
        // sort_bibliography_array_by_deemed_author_year_title
        // either: sort on multiple fields, or; create such sort field
        JSONValue j = parseJSON(bibent);
        if (!empty(j["fulltitle"].str)) {
          if (!empty(j["author_raw"].str)) {
            j["deemed_author"]=j["author_arr"][0];
          } else if (!empty(j["editor_raw"].str)) {
            j["deemed_author"]=j["editor_arr"][0];
          }
          j["sortby_deemed_author_year_title"] = (
            j["deemed_author"].str ~
             "; " ~
             j["year"].str ~
             "; "  ~
             j["fulltitle"].str
          );
        }
        bib_arr_json ~= j;
      }
      JSONValue[] biblio_unsorted_array_of_json_objects =
        bib_arr_json.dup;
        destroy(bib_arr_json);
      return biblio_unsorted_array_of_json_objects;
    }
    final private JSONValue[] biblio_sort(BJ)(BJ biblio_unordered) {
      debug(asserts) {
        static assert(is(typeof(biblio_unordered) == JSONValue[]));
      }
      JSONValue[] biblio_sorted_;
      biblio_sorted_ =
        sort!((a, b){
          return ((a["sortby_deemed_author_year_title"].str) < (b["sortby_deemed_author_year_title"].str));
        })(biblio_unordered).array;
      debug(bibliosorted) {
        foreach (j; biblio_sorted_) {
          if (!empty(j["fulltitle"].str)) {
            writeln(j["sortby_deemed_author_year_title"]);
          }
        }
      }
      return biblio_sorted_;
    }
    void biblio_debug(BJ)(BJ biblio_sorted) {
      debug(asserts) {
        static assert(is(typeof(biblio_sorted) == JSONValue[]));
      }
      debug(biblio0) {
        foreach (j; biblio_sorted) {
          if (!empty(j["fulltitle"].str)) {
            writeln(j["sortby_deemed_author_year_title"]);
          }
        }
      }
    }
  }
  /+ +/
  struct NodeStructureMetadata {
    int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7;
    int obj_cite_number;
    int[string] p_; // p_ parent_
    auto rgx = Rgx();
    ObjGenericComposite node_location_emitter(Lv,Ta,N,C,P,I)(
      Lv lev_markup_number,
      Ta segment_anchor_tag,
      N  obj_cite_number_,
      C  cntr_,
      P  ptr_,
      I  is_
    )
    in {
      debug(asserts) {
        static assert(is(typeof(lev_markup_number)  == string));
        static assert(is(typeof(segment_anchor_tag) == string));
        static assert(is(typeof(obj_cite_number_)   == int));
        static assert(is(typeof(cntr_)              == int));
        static assert(is(typeof(ptr_)               == int));
        static assert(is(typeof(is_)                == string));
      }
      assert(is_ != "heading");
      assert(obj_cite_number_.to!int >= 0);
    }
    body {
      assert(is_ != "heading"); // should not be necessary
      assert(obj_cite_number_.to!int >= 0); // should not be necessary
      int obj_cite_number = obj_cite_number_.to!int;
      if (lv7 > State.off) {
        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_4;
        p_["obj_cite_number"] = lv7;
      } else if (lv6 > State.off) {
        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3;
        p_["obj_cite_number"] = lv6;
      } else if (lv5 > State.off) {
        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2;
        p_["obj_cite_number"] = lv5;
      } else {
        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1;
        p_["obj_cite_number"] = lv4;
      }
      ObjGenericComposite comp_obj_location;
      comp_obj_location                       = comp_obj_location.init;
      comp_obj_location.is_a                  = is_;
      comp_obj_location.ocn                   = obj_cite_number_;
      comp_obj_location.segment_anchor_tag    = segment_anchor_tag.to!string;
      comp_obj_location.parent_ocn            = p_["obj_cite_number"];
      comp_obj_location.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.parent_lev_markup >= 4);
      assert(comp_obj_location.parent_lev_markup <= 7);
      assert(comp_obj_location.parent_ocn >= 0);
      return comp_obj_location;
    }
    invariant() {
    }
    ObjGenericComposite node_emitter_heading(T,L,Lm,Lc,Ta,N,C,P,LA,I,PSn,fNr,fNs,fL)(
      T   _text,
      L   lev,
      Lm  lev_markup_number,
      Lc  lev_collapsed_number,
      Ta  segment_anchor_tag,
      N   obj_cite_number_,
      C   cntr_,
      P   ptr_,
      LA  lv_ancestors,
      I   is_,
      PSn html_segnames_ptr,
      fNr flag_notes_reg,
      fNs flag_notes_star,
      fL  flag_links,
    )
    in {
      debug(asserts) {
        static assert(is(typeof(_text)                == string));
        static assert(is(typeof(lev)                  == string));
        static assert(is(typeof(lev_markup_number)    == string));
        static assert(is(typeof(lev_collapsed_number) == string));
        static assert(is(typeof(segment_anchor_tag)   == string));
        static assert(is(typeof(obj_cite_number_)     == int));
        static assert(is(typeof(cntr_)                == int));
        static assert(is(typeof(ptr_)                 == int));
        static assert(is(typeof(lv_ancestors)         == string[]));
        static assert(is(typeof(is_)                  == string));
        static assert(is(typeof(html_segnames_ptr)    == int));
      }
      assert(is_ == "heading");
      assert(to!int(obj_cite_number_) >= 0);
      assert(
        lev_markup_number.match(rgx.levels_numbered),
        ("not a valid heading level: " ~ lev_markup_number ~ " at " ~ obj_cite_number_.to!string)
      );
      if (lev_markup_number.match(rgx.levels_numbered)) {
        if (lev_markup_number.to!int == 0) {
          assert(obj_cite_number_.to!int == 1);
        }
      }
    }
    body {
      int obj_cite_number = obj_cite_number_.to!int;
      switch (lev_markup_number.to!int) {
      case 0:
        lv = DocStructMarkupHeading.h_sect_A;
        lv0 = obj_cite_number;
        lv1=0; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
        p_["lev_markup_number"] = 0;
        p_["obj_cite_number"] = 0;
        break;
      case 1:
        lv = DocStructMarkupHeading.h_sect_B;
        lv1 = obj_cite_number;
        lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
        p_["lev_markup_number"] =
          DocStructMarkupHeading.h_sect_A;
        p_["obj_cite_number"] = lv0;
        break;
      case 2:
        lv = DocStructMarkupHeading.h_sect_C;
        lv2 = obj_cite_number;
        lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
        p_["lev_markup_number"] =
          DocStructMarkupHeading.h_sect_B;
        p_["obj_cite_number"] = lv1;
        break;
      case 3:
        lv = DocStructMarkupHeading.h_sect_D;
        lv3=obj_cite_number;
        lv4=0; lv5=0; lv6=0; lv7=0;
        p_["lev_markup_number"] =
          DocStructMarkupHeading.h_sect_C;
        p_["obj_cite_number"] = lv2;
        break;
      case 4:
        lv = DocStructMarkupHeading.h_text_1;
        lv4 = obj_cite_number;
        lv5=0; lv6=0; lv7=0;
        if (lv3 > State.off) {
          p_["lev_markup_number"] =
            DocStructMarkupHeading.h_sect_D;
          p_["obj_cite_number"] = lv3;
        } else if (lv2 > State.off) {
          p_["lev_markup_number"] =
            DocStructMarkupHeading.h_sect_C;
          p_["obj_cite_number"] = lv2;
        } else if (lv1 > State.off) {
          p_["lev_markup_number"] =
            DocStructMarkupHeading.h_sect_B;
          p_["obj_cite_number"] = lv1;
        } else {
          p_["lev_markup_number"] =
            DocStructMarkupHeading.h_sect_A;
          p_["obj_cite_number"] = lv0;
        }
        break;
      case 5:
        lv = DocStructMarkupHeading.h_text_2;
        lv5 = obj_cite_number;
        lv6=0; lv7=0;
        p_["lev_markup_number"] =
          DocStructMarkupHeading.h_text_1;
        p_["obj_cite_number"] = lv4;
        break;
      case 6:
        lv = DocStructMarkupHeading.h_text_3;
        lv6 = obj_cite_number;
        lv7=0;
        p_["lev_markup_number"] =
          DocStructMarkupHeading.h_text_2;
        p_["obj_cite_number"] = lv5;
        break;
      case 7:
        lv = DocStructMarkupHeading.h_text_4;
        lv7 = obj_cite_number;
        p_["lev_markup_number"] =
          DocStructMarkupHeading.h_text_3;
        p_["obj_cite_number"] = lv6;
        break;
      default:
        break;
      }
      ObjGenericComposite _comp_obj_heading_;
      _comp_obj_heading_                           = _comp_obj_heading_.init;
      _comp_obj_heading_.use                       = "body";
      _comp_obj_heading_.is_of                     = "para";
      _comp_obj_heading_.is_a                      = "heading";
      _comp_obj_heading_.text                      = _text.to!string.strip;
      _comp_obj_heading_.ocn                       = obj_cite_number_;
      _comp_obj_heading_.obj_cite_number           = (obj_cite_number==0) ? "" : obj_cite_number.to!string;
      _comp_obj_heading_.segment_anchor_tag        = segment_anchor_tag.to!string;
      _comp_obj_heading_.marked_up_level           = lev;
      _comp_obj_heading_.heading_lev_markup        = (!(lev_markup_number.empty) ? lev_markup_number.to!int : 0);
      _comp_obj_heading_.heading_lev_collapsed     = (!(lev_collapsed_number.empty) ? lev_collapsed_number.to!int : 0);
      _comp_obj_heading_.parent_ocn                = p_["obj_cite_number"];
      _comp_obj_heading_.parent_lev_markup         = p_["lev_markup_number"];
      _comp_obj_heading_.heading_ancestors_text    = lv_ancestors;
      _comp_obj_heading_.ptr_doc_object            = cntr_;
      _comp_obj_heading_.ptr_html_segnames         = ((lev_markup_number == "4") ? html_segnames_ptr : 0);
      _comp_obj_heading_.ptr_heading               = ptr_;
      _comp_obj_heading_.inline_notes_reg          = flag_notes_reg;
      _comp_obj_heading_.inline_notes_star         = flag_notes_star;
      _comp_obj_heading_.inline_links              = flag_links;
      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_.parent_lev_markup <= 7);
      assert(_comp_obj_heading_.parent_ocn >= 0);
      if (lev_markup_number.match(rgx.levels_numbered_headings)) {
        assert(_comp_obj_heading_.heading_lev_markup <= 7);
        assert(_comp_obj_heading_.ocn >= 0);
        if (_comp_obj_heading_.parent_lev_markup > 0) {
          assert(_comp_obj_heading_.parent_lev_markup < _comp_obj_heading_.heading_lev_markup);
          if (_comp_obj_heading_.ocn != 0) {
            assert(_comp_obj_heading_.parent_ocn < _comp_obj_heading_.ocn);
          }
        }
        if (_comp_obj_heading_.heading_lev_markup == 0) {
          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A);
        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_B) {
          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A);
        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_C) {
          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_B);
        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_D) {
          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_C);
        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_1) {
          assert(_comp_obj_heading_.parent_lev_markup <= DocStructMarkupHeading.h_sect_D);
        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_2) {
          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_1);
        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_3) {
          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_2);
        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_4) {
          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_3);
        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_5) {
        }
      }
      return _comp_obj_heading_;
    }
    invariant() {
    }
  }
  /+ abstraction functions emitters ↑ +/
  /+ ↓ abstraction functions assertions +/
  auto assertions_doc_structure(O,Lv)(
    O  an_object,
    Lv lv
  ) {
    debug(asserts) {
      static assert(is(typeof(an_object) == string[string]));
      static assert(is(typeof(lv)        == int[string]));
    }
    if (lv["h3"] > State.off) {
      assert(lv["h0"] > State.off);
      assert(lv["h1"] > State.off);
      assert(lv["h2"] > State.off);
    } else if (lv["h2"] > State.off) {
      assert(lv["h0"] > State.off);
      assert(lv["h1"] > State.off);
      assert(lv["h3"] == State.off);
    } else if (lv["h1"] > State.off) {
      assert(lv["h0"] > State.off);
      assert(lv["h2"] == State.off);
      assert(lv["h3"] == State.off);
    } else if (lv["h0"] > State.off) {
      assert(lv["h1"] == State.off);
      assert(lv["h2"] == State.off);
      assert(lv["h3"] == State.off);
    } else {
      assert(lv["h0"] == State.off);
      assert(lv["h1"] == State.off);
      assert(lv["h2"] == State.off);
      assert(lv["h3"] == State.off);
    }
    if (lv["h7"] > State.off) {
      assert(lv["h4"] > State.off);
      assert(lv["h5"] > State.off);
      assert(lv["h6"] > State.off);
    } else if (lv["h6"] > State.off) {
      assert(lv["h4"] > State.off);
      assert(lv["h5"] > State.off);
      assert(lv["h7"] == State.off);
    } else if (lv["h5"] > State.off) {
      assert(lv["h4"] > State.off);
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    } else if (lv["h4"] > State.off) {
      assert(lv["h5"] == State.off);
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    } else {
      assert(lv["h4"] == State.off);
      assert(lv["h5"] == State.off);
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    }
    if (lv["h0"] == State.off) {
      assert(lv["h1"] == State.off);
      assert(lv["h2"] == State.off);
      assert(lv["h3"] == State.off);
      assert(lv["h4"] == State.off);
      assert(lv["h5"] == State.off);
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    }
    if (lv["h1"] == State.off) {
      assert(lv["h2"] == State.off);
      assert(lv["h3"] == State.off);
    }
    if (lv["h2"] == State.off) {
      assert(lv["h3"] == State.off);
    }
    if (lv["h3"] == State.off) {
    }
    if (lv["h4"] == State.off) {
      assert(lv["h5"] == State.off);
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    }
    if (lv["h5"] == State.off) {
      assert(lv["h6"] == State.off);
      assert(lv["h7"] == State.off);
    }
    if (lv["h6"] == State.off) {
      assert(lv["h7"] == State.off);
    }
    if (lv["h7"] == State.off) {
    }
    switch ((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;
    }
  }
  auto assertions_flag_types_block_status_none_or_closed(T)(T type) {
    debug(asserts) {
      static assert(is(typeof(type) == int[string]));
    }
    assert(
      (type["code"] == TriState.off)
      || (type["code"] == TriState.closing),
      "code block status: off or closing");
    assert(
      (type["poem"] == TriState.off)
      || (type["poem"] == TriState.closing),
      "poem status: off or closing");
    assert(
      (type["table"] == TriState.off)
      || (type["table"] == TriState.closing),
      "table status: off or closing");
    assert(
      (type["group"] == TriState.off)
      || (type["group"] == TriState.closing),
      "group block status: off or closing");
    assert(
      (type["block"] == TriState.off)
      || (type["block"] == TriState.closing),
      "block status: off or closing");
  }
  /+ abstraction functions assertions ↑ +/
} /+ ← closed: template SiSUdocAbstraction +/