/++
  document abstraction:
  abstraction of sisu markup for downstream processing
  ao_abstract_doc_source.d
+/
template SiSUdocAbstraction() {
  private:
  struct Abstraction {
    /+ ↓ abstraction imports +/
    import
      ao_defaults,                  // sdp/ao_defaults.d
      ao_object_setter,             // sdp/ao_object_setter.d
      ao_rgx;                       // sdp/ao_rgx.d
    /+ ↓ abstraction mixins +/
    mixin ObjectSetter;
    mixin InternalMarkup;
    /+ ↓ abstraction struct init +/
    /+ initialize +/
    auto rgx = Rgx();
    ObjComposite[][string] the_table_of_contents_section;
    ObjComposite[] the_document_head_section, the_document_body_section, the_bibliography_section, the_glossary_section, the_blurb_section;
    string[string] an_object, processing;
    string an_object_key;
    string[] anchor_tags;
    string segment_anchor_tag_that_object_belongs_to;
    auto set_abstract_object = ObjectAbstractSet();
    auto note_section = NotesSection();
    /+ enum +/
    enum State { off, on }
    enum TriState { off, on, closing } // make aware, possibility of third state
    enum DocStructMarkupHeading {
      h_sect_A,
      h_sect_B,
      h_sect_C,
      h_sect_D,
      h_text_1,
      h_text_2,
      h_text_3,
      h_text_4,
      h_text_5, // extra level, drop
      content_non_header
    } // header section A-D; header text 1-4
    enum DocStructCollapsedHeading { lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7 } // not yet used
    /+ biblio variables +/
    string biblio_tag_name, biblio_tag_entry, st;
    string[] biblio_arr_json;
    string biblio_entry_str_json;
    JSONValue[] bib_arr_json;
    int bib_entry;
    /+ counters +/
    long cntr, previous_count, previous_length;
    int[string] line_occur;
    int verse_line, heading_ptr;
    string[] html_segnames=[];
    uint html_segnames_ptr=0;
    uint html_segnames_ptr_cntr=0;
    /+ 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 obj_cite_number_emit(int obj_cite_number_status_flag) {
      return object_citation_number.obj_cite_number_emitter(obj_cite_number_status_flag);
    }
    /+ book index variables +/
    string book_idx_tmp;
    string[][string][string] bookindex_unordered_hashes;
    auto bookindex_extract_hash = BookIndexNuggetHash();
    string[][string][string] bkidx_hash(
      string bookindex_section,
      int obj_cite_number
    ) {
      return bookindex_extract_hash.bookindex_nugget_hash(bookindex_section, obj_cite_number);
    }
    /+ node +/
    string[string][string] _node;
    auto node_construct = NodeStructureMetadata();
    /+ ↓ abstract marked up document +/
    auto abstract_doc_source(
      char[][]               markup_sourcefile_content,
      string[string][string] dochead_make_aa,
      string[string][string] dochead_meta_aa,
      bool[string]           opt_action_bool,
    ) {
      /+ ↓ 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);
      }
      auto node_ = node_metadata;
      line_occur = [
        "heading"  : 0,
        "para"     : 0,
        "glossary" : 0,
        "blurb"    : 0,
      ];
      auto type = flags_type_init;
      string[string] obj_cite_number_poem = [
        "start" : "",
        "end"   : ""
      ];
      int[string] lv = [
        "lv" : State.off,
        "h0" : State.off,
        "h1" : State.off,
        "h2" : State.off,
        "h3" : State.off,
        "h4" : State.off,
        "h5" : State.off,
        "h6" : State.off,
        "h7" : State.off,
        "lev_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"] = "";
      node_["object"]["is"]                       = "heading";
      node_["object"]["obj_cite_number"]          = "0";
      node_["object"]["segment_anchor_tag"]       = "toc";
      node_["object"]["parent_obj_cite_number"]   = "1";
      node_["object"]["parent_lev_markup_number"] = "0";
      auto toc_head =
        set_abstract_object.contents_heading(
          "Table of Contents", // nugget/object
          "",                  // attrib
          0,                   // obj_cite_number
          ["toc"],             // anchor tag
          "1",                 // lev
          4,                   // lev_int_markup
          2,                   // lev_int_collapsed
          node_,
        );
      the_table_of_contents_section = [
        "seg": [toc_head],
        "scroll": [toc_head],
      ];
      auto mkup = InlineMarkup();
      auto munge = ObjInlineMarkupMunge();
      /+ 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 = replaceAll(line, rgx.true_dollar, "$$$$");
          // dollar represented as $$ needed to stop submatching on $
          // (substitutions using ${identifiers} must take into account (i.e. happen earlier))
        debug(source) {                                  // source lines
          writeln(line);
        }
        debug(srclines) {
          if (!line.empty) {                             // source lines, not empty
            writefln(
              "* %s",
              line
            );
          }
        }
        if (!line.empty) {
          _check_obj_cite_number_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) +/
          if ((matchFirst(line, rgx.heading_biblio)
          || (type["biblio_section"] == State.on
          && (!matchFirst(line, rgx.heading_blurb_glossary))))
          && (!matchFirst(line, rgx.heading))
          && (!matchFirst(line, rgx.comment))) {
            /+ within section (block object): biblio +/
            type["glossary_section"] = State.off;
            type["biblio_section"] = State.on;
            type["blurb_section"] = State.off;
            if (opt_action_bool["backmatter"] && opt_action_bool["section_biblio"]) {
              _biblio_block_(line, type, bib_entry, biblio_entry_str_json, biblio_arr_json); //
              debug(bibliobuild) {
                writeln("-  ", biblio_entry_str_json);
                writeln("-> ", biblio_arr_json.length);
              }
            }
            continue;
          } else if ((matchFirst(line, rgx.heading_glossary)
          || (type["glossary_section"] == State.on
          && (!matchFirst(line, rgx.heading_biblio_blurb))))
          && (!matchFirst(line, rgx.heading))
          && (!matchFirst(line, rgx.comment))) {
            /+ within section (block object): glossary +/
            debug(glossary) {
              writeln(__LINE__);
              writeln(line);
            }
            // _glossary_block_(line, type);
            type["glossary_section"] = State.on;
            type["biblio_section"] = State.off;
            type["blurb_section"] = State.off;
            if (opt_action_bool["backmatter"] && opt_action_bool["section_glossary"]) {
              indent=[
                "hang_position" : 0,
                "base_position" : 0,
              ];
              bullet = false;
              type["para"] = State.on;
              line_occur["para"] = State.off;
              an_object_key="glossary_nugget"; //
              if (matchFirst(line, rgx.heading_glossary)) {
                node_["object"]["is"]                       = "heading";
                node_["object"]["obj_cite_number"]          = "0";
                node_["object"]["segment_anchor_tag"]       = "glossary";
                node_["object"]["parent_obj_cite_number"]   = "1";
                node_["object"]["parent_lev_markup_number"] = "0";
                the_glossary_section ~=
                  set_abstract_object.contents_heading(
                    "Glossary",       // nugget/object
                    "",               // attrib
                    0,                // obj_cite_number
                    [""],             // anchor tag
                    "B",              // lev
                    1,                // lev_int_markup
                    1,                // lev_int_collapsed
                    node_,
                  );
                node_["object"]["is"]                       = "heading";
                node_["object"]["obj_cite_number"]          = "0";
                node_["object"]["segment_anchor_tag"]       = "glossary";
                node_["object"]["parent_obj_cite_number"]   = "1";
                node_["object"]["parent_lev_markup_number"] = "0";
                the_glossary_section ~=
                  set_abstract_object.contents_heading(
                    "Glossary",       // nugget/object
                    "",               // attrib
                    0,                // obj_cite_number
                    ["glossary"],     // anchor tag
                    "1",              // lev
                    4,                // lev_int_markup
                    2,                // lev_int_collapsed
                    node_,
                  );
              // } else if (matchFirst(line, rgx.heading)) {
              //   _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa); // levels?
              } else {
                _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
                the_glossary_section ~=
                  set_abstract_object.contents_para(
                    "para",                    // an_object["is"],
                    to!string(line),           // an_object["substantive"],
                    "",                        // attrib
                    0,                         // obj_cite_number,
                    indent,
                    bullet
                  );
              }
              type["obj_cite_number_status"] = TriState.off;
            }
            continue;
          } else if ((matchFirst(line, rgx.heading_blurb)
          || (type["blurb_section"] == State.on
          && (!matchFirst(line, rgx.heading_biblio_glossary))))
          && (!matchFirst(line, rgx.heading))
          && (!matchFirst(line, rgx.comment))) {
            /+ within section (block object): blurb +/
            debug(blurb) {
              writeln(__LINE__);
              writeln(line);
            }
            // _blurb_block_(line, type);
            type["glossary_section"] = State.off;
            type["biblio_section"] = State.off;
            type["blurb_section"] = State.on;
            if (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"]) {
              indent=[
                "hang_position" : 0,
                "base_position" : 0,
              ];
              bullet = false;
              type["para"] = State.on;
              line_occur["para"] = State.off;
              an_object_key="blurb_nugget";
              if (matchFirst(line, rgx.heading_blurb)) {
                node_["object"]["is"]                       = "heading";
                node_["object"]["obj_cite_number"]          = "0";
                node_["object"]["segment_anchor_tag"]       = "blurb";
                node_["object"]["parent_obj_cite_number"]   = "1";
                node_["object"]["parent_lev_markup_number"] = "0";
                the_blurb_section ~=
                  set_abstract_object.contents_heading(
                    "Blurb",          // nugget/object
                    "",               // attrib
                    0,                // obj_cite_number
                    [""],             // anchor tag
                    "B",              // lev
                    1,                // lev_int_markup
                    1,                // lev_int_collapsed
                    node_,
                  );
                node_["object"]["is"]                       = "heading";
                node_["object"]["obj_cite_number"]          = "0";
                node_["object"]["segment_anchor_tag"]       = "blurb";
                node_["object"]["parent_obj_cite_number"]   = "1";
                node_["object"]["parent_lev_markup_number"] = "0";
                the_blurb_section ~=
                  set_abstract_object.contents_heading(
                    "Blurb",          // nugget/object
                    "",               // attrib
                    0,                // obj_cite_number
                    ["blurb"],        // anchor tag
                    "1",              // lev
                    4,                // lev_int_markup
                    2,                // lev_int_collapsed
                    node_,
                  );
              } else if ((matchFirst(line, rgx.heading))
              && (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"])) {
                _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa); // levels?
                node_["object"]["is"]                       = "heading";
                node_["object"]["obj_cite_number"]          = "0";
                node_["object"]["segment_anchor_tag"]       = "blurb";
                node_["object"]["parent_obj_cite_number"]   = "1";
                node_["object"]["parent_lev_markup_number"] = "0";
                the_blurb_section ~=
                  set_abstract_object.contents_heading(
                    to!string(line),           //  an_object["substantive"],
                    "",                        // attrib
                    0,                         // obj_cite_number
                    [""],                      // anchor tag
                    to!string(an_object["lev"]),
                    to!int(an_object["lev_markup_number"]),
                    to!int(an_object["lev_collapsed_number"]),
                    node_,
                  );
              } else {
                _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
                the_blurb_section ~=
                  set_abstract_object.contents_para(
                    "para",                    // an_object["is"],
                    to!string(line),           //  an_object["substantive"],
                    "",                        // attrib
                    obj_cite_number,
                    indent,
                    bullet
                  );
              }
              type["obj_cite_number_status"] = TriState.off;
            }
            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;
          /+ 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["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 (matchFirst(line, rgx.block_open)) {
              if (matchFirst(line, (rgx.block_poem_open))) {
                /+ poem to verse exceptions! +/
                object_reset(an_object);
                processing.remove("verse");
                obj_cite_number_poem["start"] = to!string(obj_cite_number);
              }
              _start_block_(line, type, obj_cite_number_poem);
              continue;
            } 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(
                  matchFirst(line, rgx.book_index)
                  || matchFirst(line, rgx.book_index_open)
                  || type["book_index"] == State.on
                );
              }
              if ((matchFirst(line, rgx.book_index))
              || (matchFirst(line, rgx.book_index_open))
              || (type["book_index"] == State.on ))  {
                /+ book_index +/
                _book_index_(line, book_idx_tmp, an_object, type, opt_action_bool);
              } 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";
                  the_document_body_section ~=
                    set_abstract_object.contents_comment(strip(an_object[an_object_key]));
                  _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 (matchFirst(line, rgx.heading)) {
                    /+ heading match +/
                    _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa);
                  } else if (line_occur["para"] == State.off) {
                    /+ para match +/
                    an_object_key="body_nugget";
                    _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur);
                  }
                } else if (line_occur["heading"] > State.off) {
                  /+ heading +/
                  debug(heading) {                         // 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_(
                line,
                an_object,
                the_document_body_section,
                bookindex_unordered_hashes,
                obj_cite_number,
                _node,
                cntr,
                type,
                obj_cite_number_poem,
                dochead_make_aa
              ); // watch
            } else {
              /+ line empty +/
              /+ 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 = obj_cite_number_emit(type["obj_cite_number_status"]);
                an_object["bookindex_nugget"] =
                  ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
                bookindex_unordered_hashes =
                  bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
                an_object["is"] = "heading";
                an_object_key="body_nugget";
                auto substantive_object_and_anchor_tags_tuple =
                  obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); // tuple this with anchor tags?
                an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
                anchor_tags = substantive_object_and_anchor_tags_tuple[1];
                if (to!int(an_object["lev_markup_number"]) == 4) {
                  segment_anchor_tag_that_object_belongs_to = anchor_tags[0];
                } else if (to!int(an_object["lev_markup_number"]) < 4) {
                  segment_anchor_tag_that_object_belongs_to = "";
                }
                _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,
                  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++;
                }
                _node =
                  node_construct.node_emitter_heading(
                    an_object["lev_markup_number"],
                    an_object["lev_collapsed_number"],
                    segment_anchor_tag_that_object_belongs_to,
                    obj_cite_number,
                    cntr,
                    heading_ptr,
                    an_object["is"],
                    html_segnames_ptr,
                  ); // heading
                an_object["attrib"] =
                  obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
                ++heading_ptr;
                debug(segments) {
                  writeln(an_object["lev_markup_number"]);
                  writeln(segment_anchor_tag_that_object_belongs_to);
                }
                the_document_body_section ~=
                  set_abstract_object.contents_heading(
                    an_object["substantive"],
                    an_object["attrib"],
                    obj_cite_number,
                    anchor_tags,
                    to!string(an_object["lev"]),
                    to!int(an_object["lev_markup_number"]),
                    to!int(an_object["lev_collapsed_number"]),
                    _node,
                  );
                // 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 = obj_cite_number_emit(type["obj_cite_number_status"]);
                an_object["bookindex_nugget"] =
                  ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
                bookindex_unordered_hashes =
                  bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
                an_object["is"] = "para";
                _node =
                  node_construct.node_emitter(
                    content_non_header,
                    segment_anchor_tag_that_object_belongs_to,
                    obj_cite_number,
                    cntr,
                    heading_ptr-1,
                    an_object["is"],
                  );
                auto substantive_object_and_anchor_tags_tuple =
                  obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); // ...
                an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
                anchor_tags = substantive_object_and_anchor_tags_tuple[1];
                an_object["attrib"] =
                  obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
                the_document_body_section ~=
                  set_abstract_object.contents_para(
                    an_object["is"],
                    an_object["substantive"],
                    an_object["attrib"],
                    obj_cite_number,
                    indent,
                    bullet
                  );
                _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_attrib.lev_int_markup < 5)) {
              type["biblio_section"] = State.off;
              type["glossary_section"] = State.off;
              type["blurb_section"] = State.off;
            }
            previous_length = the_document_body_section.length;
            if (
              match(the_document_body_section[$-1].object,
              rgx.inline_notes_delimiter_al_regular_number_note)
            ) {
              previous_count=the_document_body_section.length -1;
              note_section.gather_notes_for_endnote_section(
                the_document_body_section,
                segment_anchor_tag_that_object_belongs_to,
                the_document_body_section.length-1,
              );
            }
          }
        }
      } /+ ← closed: loop markup document/text line by line +/
      /+ ↓ post loop markup document/text +/
      debug(objectrelated2) { // check
        writeln(line);
      }
      /+
        Backmatter:
        - endnotes
        - glossary
        - bibliography / references
        - book index
        - blurb
      +/
      // TODO FIGURE OUT, you need this possibility
      // obj_im.obj_inline_markup_and_anchor_tags("doc_end_reset", an_object_key, "", dochead_make_aa);
      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["seg"].length
        );
        foreach (o; the_endnotes_section["seg"]) {
          writeln(o);
        }
      }
      if (an_object["glossary_nugget"].length == 0) {
        writeln("no gloss");
        node_["object"]["is"]                       = "heading";
        node_["object"]["obj_cite_number"]          = "0";
        node_["object"]["segment_anchor_tag"]       = "glossary";
        node_["object"]["parent_obj_cite_number"]   = "1";
        node_["object"]["parent_lev_markup_number"] = "0";
        the_glossary_section ~=
          set_abstract_object.contents_heading(
            "(skip) there is no Glossary section",   // nugget/object
            "",               // attrib
            0,                // obj_cite_number
            [""],             // anchor tag
            "B",              // lev
            1,                // lev_int_markup
            1,                // lev_int_collapsed
            node_,
          );
      } else {
        writeln("gloss");
      }
      debug(glossary) {
        foreach (gloss; the_glossary_section) {
          writeln(gloss.object);
        }
      }
      auto biblio_unsorted_incomplete = biblio_arr_json.dup;
      // destroy(biblio_arr_json);
      auto biblio = Bibliography();
      auto biblio_ordered =
        biblio._bibliography_(biblio_unsorted_incomplete, bib_arr_json);
      if (biblio_ordered.length > 0) {
        node_["object"]["is"]                       = "heading";
        node_["object"]["obj_cite_number"]          = "0";
        node_["object"]["segment_anchor_tag"]       = "bibliography";
        node_["object"]["parent_obj_cite_number"]   = "1";
        node_["object"]["parent_lev_markup_number"] = "0";
        the_bibliography_section ~=
          set_abstract_object.contents_heading(
            "Bibliography",   // nugget/object
            "",               // attrib
            0,                // obj_cite_number
            [""],             // anchor tag
            "B",              // lev
            1,                // lev_int_markup
            1,                // lev_int_collapsed
            node_,
          );
        node_["object"]["is"]                       = "heading";
        node_["object"]["obj_cite_number"]          = "0";
        node_["object"]["segment_anchor_tag"]       = "bibliography";
        node_["object"]["parent_obj_cite_number"]   = "1";
        node_["object"]["parent_lev_markup_number"] = "0";
        the_bibliography_section ~=
          set_abstract_object.contents_heading(
            "Bibliography",   // nugget/object
            "",               // attrib
            0,                // obj_cite_number
            ["bibliography"], // anchor tag
            "1",              // lev
            4,                // lev_int_markup
            2,                // lev_int_collapsed
            node_,
          );
      } else {
        node_["object"]["is"]                       = "heading";
        node_["object"]["obj_cite_number"]          = "0";
        node_["object"]["segment_anchor_tag"]       = "bibliography";
        node_["object"]["parent_obj_cite_number"]   = "1";
        node_["object"]["parent_lev_markup_number"] = "0";
        the_bibliography_section ~=
          set_abstract_object.contents_heading(
            "(skip) there is no Bibliography",   // nugget/object
            "",               // attrib
            0,                // obj_cite_number
            [""],             // anchor tag
            "B",              // lev
            1,                // lev_int_markup
            1,                // lev_int_collapsed
            node_,
          );
      }
      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 ~ "]"),
        );
        the_bibliography_section ~=
          set_abstract_object.contents_para(
            "bibliography",
            out_,                                                // nugget/object
            "",                                                  // attrib
            0,                                                   // obj_cite_number
            ([ "hang_position" : 0, "base_position" : 1, ]),     // indent
            false
          );
      }
      debug(bibliosection) {
        foreach (o; the_bibliography_section) {
          writeln(o.object);
        }
      }
      auto bi = BookIndexReportSection();
      auto bi_tuple =
        bi.bookindex_build_section(
          bookindex_unordered_hashes,
          obj_cite_number,
          segment_anchor_tag_that_object_belongs_to,
          opt_action_bool,
        );
      static assert(!isTypeTuple!(bi_tuple));
      auto the_bookindex_section = bi_tuple[0];
      obj_cite_number = bi_tuple[1];
      debug(bookindex) {                         // bookindex
        foreach (bi_entry; the_bookindex_section["seg"]) {
          writeln(bi_entry);
        }
      }
      if (an_object["blurb_nugget"].length == 0) {
        writeln("no blurb");
        node_["object"]["is"]                       = "heading";
        node_["object"]["obj_cite_number"]          = "0";
        node_["object"]["segment_anchor_tag"]       = "blurb";
        node_["object"]["parent_obj_cite_number"]   = "1";
        node_["object"]["parent_lev_markup_number"] = "0";
        the_blurb_section ~=
          set_abstract_object.contents_heading(
            "(skip) there is no Blurb section",   // nugget/object
            "",               // attrib
            0,                // obj_cite_number
            [""],             // anchor tag
            "B",              // lev
            1,                // lev_int_markup
            1,                // lev_int_collapsed
            node_,
          );
      } else {
        writeln("blurb");
      }
      debug(blurb) {
        foreach (blurb; the_blurb_section) {
          writeln(blurb.object);
        }
      }
      
      indent=[
        "hang_position" : 1,
        "base_position" : 1,
      ];
      if (the_endnotes_section["seg"].length > 1) {
        toc_txt_ = format(
          "{ %s }../%s.fn_suffix",
          "Endnotes",
          "endnotes",            // segment_anchor_tag_that_object_belongs_to
        );
        toc_txt_= munge.url_links(toc_txt_);
        the_table_of_contents_section["seg"] ~=
          set_abstract_object.contents_toc(
            "toc",
            toc_txt_,
            "",                   // attrib
            0,
            indent,
            false
          );
      }
      if (the_endnotes_section["scroll"].length > 1) {
        toc_txt_ = format(
          "{ %s }#%s",
          "Endnotes",
          "endnotes",            // _anchor_tag
        );
        toc_txt_= munge.url_links(toc_txt_);
        the_table_of_contents_section["scroll"] ~=
          set_abstract_object.contents_toc(
            "toc",
            toc_txt_,
            "",                  // attrib
            0,
            indent,
            false
          );
      }
      if (the_glossary_section.length > 1) {
        toc_txt_ = format(
          "{ %s }../%s.fn_suffixs",
          "Glossary",
          "glossary",  // segment_anchor_tag_that_object_belongs_to
        );
        toc_txt_= munge.url_links(toc_txt_);
        the_table_of_contents_section["seg"] ~=
          set_abstract_object.contents_toc(
            "toc",
            toc_txt_,
            "",                   // attrib
            0,
            indent,
            false
          );
        toc_txt_ = format(
          "{ %s }#%s",
          "Glossary",
          "glossary",            // _anchor_tag
        );
        toc_txt_= munge.url_links(toc_txt_);
        the_table_of_contents_section["scroll"] ~=
          set_abstract_object.contents_toc(
            "toc",
            toc_txt_,
            "",                   // attrib
            0,
            indent,
            false
          );
      }
      if (the_bibliography_section.length > 1){
        toc_txt_ = format(
          "{ %s }../%s.fn_suffix",
          "Bibliography",
          "bibliography",        // segment_anchor_tag_that_object_belongs_to
        );
        toc_txt_= munge.url_links(toc_txt_);
        the_table_of_contents_section["seg"] ~=
          set_abstract_object.contents_toc(
            "toc",
            toc_txt_,
            "",                   // attrib
            0,
            indent,
            false
          );
        toc_txt_ = format(
          "{ %s }#%s",
          "Bibliography",
          "bibliography",          // _anchor_tag
        );
        toc_txt_= munge.url_links(toc_txt_);
        the_table_of_contents_section["scroll"] ~=
          set_abstract_object.contents_toc(
            "toc",
            toc_txt_,
            "",                   // attrib
            0,
            indent,
            false
          );
      }
      if (the_bookindex_section["seg"].length > 1) {
        toc_txt_ = format(
          "{ %s }../%s.fn_suffix",
          "Book Index",
          "bookindex",          // segment_anchor_tag_that_object_belongs_to
        );
        toc_txt_= munge.url_links(toc_txt_);
        the_table_of_contents_section["seg"] ~=
          set_abstract_object.contents_toc(
            "toc",
            toc_txt_,
            "",                   // attrib
            0,
            indent,
            false
          );
      }
      if (the_bookindex_section["scroll"].length > 1) {
        toc_txt_ = format(
          "{ %s }#%s",
          "Book Index",
          "bookindex",            // _anchor_tag
        );
        toc_txt_= munge.url_links(toc_txt_);
        the_table_of_contents_section["scroll"] ~=
          set_abstract_object.contents_toc(
            "toc",
            toc_txt_,
            "",                   // attrib
            0,
            indent,
            false
          );
      }
      if (the_blurb_section.length > 1) {
        toc_txt_ = format(
          "{ %s }../%s.fn_suffix",
          "Blurb",
          "blurb",                // segment_anchor_tag_that_object_belongs_to
        );
        toc_txt_= munge.url_links(toc_txt_);
        the_table_of_contents_section["seg"] ~=
          set_abstract_object.contents_toc(
            "toc",
            toc_txt_,
            "",                   // attrib
            0,
            indent,
            false
          );
        toc_txt_ = format(
          "{ %s }#%s",
          "Blurb",
          "blurb",                // _anchor_tag
        );
        toc_txt_= munge.url_links(toc_txt_);
        the_table_of_contents_section["scroll"] ~=
          set_abstract_object.contents_toc(
            "toc",
            toc_txt_,
            "",                   // attrib
            0,
            indent,
            false
          );
      }
      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.para_attrib.indent_start), toc_linked_heading.object);
        }
      }
      the_document_head_section ~= the_document_body_section[0];
      the_document_body_section=the_document_body_section[1..$];
      auto document_the = [
        "head":             the_document_head_section,
        "toc_seg":          the_table_of_contents_section["seg"],
        "toc_scroll":       the_table_of_contents_section["scroll"],
        "body":             the_document_body_section,
        "endnotes_seg":     the_endnotes_section["seg"],
        "endnotes_scroll":  the_endnotes_section["scroll"],
        "glossary":         the_glossary_section,
        "bibliography":     the_bibliography_section,
        "bookindex_scroll": the_bookindex_section["scroll"],
        "bookindex_seg":    the_bookindex_section["seg"],
        "blurb":            the_blurb_section,
      ];
      auto t = tuple(
        document_the,
        html_segnames,
      );
      return t;
      /+ post loop markup document/text ↑ +/
    } /+ ← closed: abstract doc source +/
    /+ ↓ abstraction functions +/
    auto object_reset(ref string[string] an_object) {
      an_object.remove("body_nugget");
      an_object.remove("substantive");
      an_object.remove("is");
      an_object.remove("attrib");
      an_object.remove("bookindex_nugget");
    }
    auto _common_reset_(
      ref int[string] line_occur,
      ref string[string] an_object,
      ref int[string] type
    ) {
      line_occur["heading"] = State.off;
      line_occur["para"]= State.off;
      type["heading"] = State.off;
      type["para"] = State.off;
      object_reset(an_object);
    }
    void _check_obj_cite_number_status_(
      char[] line,
      ref int[string] type
    ) {
      if ((!line.empty) && (type["obj_cite_number_status_multi_obj"] == TriState.off)) {
        /+ not multi-line object, check whether obj_cite_number is on or turned off +/
        if (matchFirst(line, rgx.obj_cite_number_block_marks)) {
          /+ switch off obj_cite_number +/
          if (matchFirst(line, rgx.obj_cite_number_off_block)) {
            type["obj_cite_number_status_multi_obj"] = TriState.on;
            debug(ocnoff) {
              writeln(line);
            }
          }
          if (matchFirst(line, rgx.obj_cite_number_off_block_dh)) {
            type["obj_cite_number_status_multi_obj"] = TriState.closing;
            debug(ocnoff) {
              writeln(line);
            }
          }
        } else {
          if (type["obj_cite_number_status_multi_obj"] == TriState.off) {
            if (matchFirst(line, rgx.obj_cite_number_off)) {
              type["obj_cite_number_status"] = TriState.on;
            } else if (matchFirst(line, rgx.obj_cite_number_off_dh)) {
              type["obj_cite_number_status"] = TriState.closing;
            } else {
              type["obj_cite_number_status"] = TriState.off;
            }
          } else {
            type["obj_cite_number_status"] =
              type["obj_cite_number_status_multi_obj"];
          }
        }
      } else if ((!line.empty) && (type["obj_cite_number_status_multi_obj"] > TriState.off)) {
        if (matchFirst(line, rgx.obj_cite_number_off_block_close)) {
          type["obj_cite_number_status_multi_obj"] = TriState.off;
          type["obj_cite_number_status"] = TriState.off;
          debug(ocnoff) {
            writeln(line);
          }
        }
      }
    }
    void _start_block_(
      char[] line,
      ref int[string] type,
      string[string] obj_cite_number_poem
    ) {
      if (matchFirst(line, rgx.block_curly_code_open)) {
        /+ curly code open +/
        debug(code) {                              // code (curly) open
          writefln(
            "* [code curly] %s",
            line
          );
        }
        type["blocks"] = TriState.on;
        type["code"] = TriState.on;
        type["curly_code"] = TriState.on;
      } else if (matchFirst(line, rgx.block_curly_poem_open)) {
        /+ curly poem open +/
        debug(poem) {                              // poem (curly) open
          writefln(
            "* [poem curly] %s",
            line
          );
        }
        obj_cite_number_poem["start"] =
          to!string(obj_cite_number);
        type["blocks"] = TriState.on;
        type["verse_new"] = State.on;
        type["poem"] = TriState.on;
        type["curly_poem"] = TriState.on;
      } else if (matchFirst(line, rgx.block_curly_group_open)) {
        /+ curly group open +/
        debug(group) {                             // group (curly) open
          writefln(
            "* [group curly] %s",
            line
          );
        }
        type["blocks"] = TriState.on;
        type["group"] = TriState.on;
        type["curly_group"] = TriState.on;
      } else if (matchFirst(line, rgx.block_curly_block_open)) {
        /+ curly block open +/
        debug(block) {                             // block (curly) open
          writefln(
            "* [block curly] %s",
            line
          );
        }
        type["blocks"] = TriState.on;
        type["block"] = TriState.on;
        type["curly_block"] = TriState.on;
      } else if (matchFirst(line, rgx.block_curly_quote_open)) {
        /+ curly quote open +/
        debug(quote) {                             // quote (curly) open
          writefln(
            "* [quote curly] %s",
            line
          );
        }
        type["blocks"] = TriState.on;
        type["quote"] = TriState.on;
        type["curly_quote"] = TriState.on;
      } else if (matchFirst(line, rgx.block_curly_table_open)) {
        /+ curly table open +/
        debug(table) {                             // table (curly) open
          writefln(
            "* [table curly] %s",
            line
          );
        }
        type["blocks"] = TriState.on;
        type["table"] = TriState.on;
        type["curly_table"] = TriState.on;
      } else if (matchFirst(line, rgx.block_tic_code_open)) {
        /+ tic code open +/
        debug(code) {                              // code (tic) open
          writefln(
            "* [code tic] %s",
            line
          );
        }
        type["blocks"] = TriState.on;
        type["code"] = TriState.on;
        type["tic_code"] = TriState.on;
      } else if (matchFirst(line, rgx.block_tic_poem_open)) {
        /+ tic poem open +/
        debug(poem) {                              // poem (tic) open
          writefln(
            "* [poem tic] %s",
            line
          );
        }
        obj_cite_number_poem["start"] = to!string(obj_cite_number);
        type["blocks"] = TriState.on;
        type["verse_new"] = State.on;
        type["poem"] = TriState.on;
        type["tic_poem"] = TriState.on;
      } else if (matchFirst(line, rgx.block_tic_group_open)) {
        /+ tic group open +/
        debug(group) {                             // group (tic) open
          writefln(
            "* [group tic] %s",
            line
          );
        }
        type["blocks"] = TriState.on;
        type["group"] = TriState.on;
        type["tic_group"] = TriState.on;
      } else if (matchFirst(line, rgx.block_tic_block_open)) {
        /+ tic block open +/
        debug(block) {                             // block (tic) open
          writefln(
            "* [block tic] %s",
            line
          );
        }
        type["blocks"] = TriState.on;
        type["block"] = TriState.on;
        type["tic_block"] = TriState.on;
      } else if (matchFirst(line, rgx.block_tic_quote_open)) {
        /+ tic quote open +/
        debug(quote) {                             // quote (tic) open
          writefln(
            "* [quote tic] %s",
            line
          );
        }
        type["blocks"] = TriState.on;
        type["quote"] = TriState.on;
        type["tic_quote"] = TriState.on;
      } else if (matchFirst(line, rgx.block_tic_table_open)) {
        /+ tic table open +/
        debug(table) {                             // table (tic) open
          writefln(
            "* [table tic] %s",
            line
          );
        }
        type["blocks"] = TriState.on;
        type["table"] = TriState.on;
        type["tic_table"] = TriState.on;
      }
    }
    void _code_block_(
      char[] line,
      ref string[string] an_object,
      ref int[string] type
    ) {
      if (type["curly_code"] == TriState.on) {
        if (matchFirst(line, rgx.block_curly_code_close)) {
          debug(code) {                              // code (curly) close
            writeln(line);
          }
          type["blocks"] = TriState.closing;
          type["code"] = TriState.closing;
          type["curly_code"] = TriState.off;
        } else {
          debug(code) {                              // code (curly) line
            writeln(line);
          }
          an_object[an_object_key] ~= line ~= "\n";          // code (curly) line
        }
      } else if (type["tic_code"] == TriState.on) {
        if (matchFirst(line, rgx.block_tic_close)) {
          debug(code) {                              // code (tic) close
            writeln(line);
          }
          type["blocks"] = TriState.closing;
          type["code"] = TriState.closing;
          type["tic_code"] = TriState.off;
        } else {
          debug(code) {                              // code (tic) line
            writeln(line);
          }
          an_object[an_object_key] ~= line ~= "\n";          // code (tic) line
        }
      }
    }
    final string biblio_tag_map(string abr) {
      auto btm = [
        "au"                               : "author_raw",
        "ed"                               : "editor_raw",
        "ti"                               : "fulltitle",
        "lng"                              : "language",
        "jo"                               : "journal",
        "vol"                              : "volume",
        "edn"                              : "edition",
        "yr"                               : "year",
        "pl"                               : "place",
        "pb"                               : "publisher",
        "pub"                              : "publisher",
        "pg"                               : "pages",
        "pgs"                              : "pages",
        "sn"                               : "short_name"
      ];
      return btm[abr];
    }
    void _biblio_block_(
      char[] line,
      ref int[string] type,
      ref int bib_entry,
      ref string biblio_entry_str_json,
      ref string[] biblio_arr_json
    ) {
      if (matchFirst(line, rgx.heading_biblio)) {
        type["biblio_section"] = TriState.on;
        type["blurb_section"] = State.off;
        type["glossary_section"] = State.off;
      }
      if (line.empty) {
        debug {
          debug(biblioblock) {
            writeln("---");
          }
          debug(biblioblockinclude) {
            writeln(biblio_entry_str_json.length);
          }
        }
        if ((bib_entry == State.off)
        && (biblio_entry_str_json.empty)) {
          bib_entry = State.on;
          biblio_entry_str_json = biblio_entry_tags_jsonstr;
        } else if (!(biblio_entry_str_json.empty)) {
          bib_entry = State.off;
          if (!(biblio_entry_str_json == 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 = biblio_entry_tags_jsonstr;
          }
        } else { // CHECK ERROR
          writeln("?? 2. ERROR ", biblio_entry_str_json, "??");
          biblio_entry_str_json = "";
        }
      } else if (matchFirst(line, rgx.biblio_tags)) {
        debug(biblioblock) {
          writeln(line);
        }
        auto bt = match(line, rgx.biblio_tags);
        bib_entry = State.off;
        st=to!string(bt.captures[1]);
        auto header_tag_value=to!string(bt.captures[2]);
        JSONValue j = parseJSON(biblio_entry_str_json);
        biblio_tag_name = (match(st, rgx.biblio_abbreviations))
          ? (biblio_tag_map(st))
          : st;
        j.object[biblio_tag_name] = header_tag_value;
        debug(bibliounsortedcheckduplicates) {
          writeln(biblio_tag_name, ": ", header_tag_value);
          writeln("--");
        }
        switch (biblio_tag_name) {
        case "author_raw": // author_arr author (fn sn)
          j["author_arr"] =
            split(header_tag_value, rgx.arr_delimiter);
          string tmp;
          biblioAuthorLoop:
          foreach (au; j["author_arr"].array) {
            if (auto x = match(au.str, rgx.name_delimiter)) {
              tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", ";
            } else {
              tmp ~= au.str;
            }
          }
          tmp = replace(tmp, rgx.trailing_comma, "");
          j["author"].str = tmp;
          goto default;
        case "editor_raw": // editor_arr editor (fn sn)
          j["editor_arr"] =
            split(header_tag_value, rgx.arr_delimiter);
          string tmp;
          biblioEditorLoop:
          foreach (ed; j["editor_arr"].array) {
            if (auto x = match(ed.str, rgx.name_delimiter)) {
              tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", ";
            } else {
              tmp ~= ed.str;
            }
          }
          tmp = replace(tmp, rgx.trailing_comma, "");
          j["editor"].str = tmp;
          goto default;
        case "fulltitle": // title & subtitle
          goto default;
        default:
          break;
        }
        auto s = j.toString();
        debug(biblio1) {
          writefln(
            "* %s: %s\n%s",
            biblio_tag_name,
            biblio_tag_entry,
            j[biblio_tag_name]
          );
        }
        if ((match(line, rgx.comment))) {
          writeln("ERROR", line, "COMMENT");
          writeln("ERROR", s, "%%");
        }
        if (!(match(line, rgx.comment))) {
          debug(biblioblockinclude) {
            writeln(line);
          }
          biblio_entry_str_json = s;
        } else {
          biblio_entry_str_json = "";
        }
        header_tag_value="";
      }
    }
    void _poem_block_(
      char[] line,
      ref string[string] an_object,
      ref int[string] type,
      ref long cntr,
      string[string] obj_cite_number_poem,
      string[string][string] dochead_make_aa,
    ) {
      if (type["curly_poem"] == TriState.on) {
        if (matchFirst(line, rgx.block_curly_poem_close)) {
          an_object[an_object_key]="verse"; // check that this is as you please
          debug(poem) {                            // poem (curly) close
            writefln(
              "* [poem curly] %s",
              line
            );
          }
          if (processing.length > 0) {
            an_object[an_object_key] = processing["verse"];
          }
          debug(poem) {                            // poem (curly) close
            writeln(__LINE__);
            writefln(
              "* %s %s",
              obj_cite_number,
              line
            );
          }
          if (an_object.length > 0) {
            debug(poem) {                            // poem (curly) close
              writeln(
                obj_cite_number,
                an_object[an_object_key]
              );
            }
            an_object["is"] = "verse";
            auto substantive_object_and_anchor_tags_tuple =
              obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
            an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
            anchor_tags = substantive_object_and_anchor_tags_tuple[1];
            an_object["attrib"] =
              obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
            the_document_body_section ~=
              set_abstract_object.contents_block(
                an_object["is"],
                an_object["substantive"],
                an_object["attrib"],
                obj_cite_number
              );
            object_reset(an_object);
            processing.remove("verse");
            ++cntr;
          }
          obj_cite_number_poem["end"] =
            to!string(obj_cite_number);
          type["blocks"] = TriState.closing;
          type["poem"] = TriState.closing;
          type["curly_poem"] = TriState.off;
        } else {
          processing["verse"] ~= line ~= "\n";
          if (type["verse_new"] == State.on) {
            obj_cite_number =
              obj_cite_number_emit(type["obj_cite_number_status"]);
            type["verse_new"] = State.off;
          } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) {
            verse_line = TriState.off;
            type["verse_new"] = State.on;
          }
          if (type["verse_new"] == State.on) {
            verse_line=1;
            an_object[an_object_key] = processing["verse"];
            debug(poem) {                          // poem verse
              writefln(
                "* %s curly\n%s",
                obj_cite_number,
                an_object[an_object_key]
              );
            }
            processing.remove("verse");
            an_object["is"] = "verse";
            _node = node_construct.node_emitter(
              content_non_header,
              segment_anchor_tag_that_object_belongs_to,
              obj_cite_number,
              cntr,
              heading_ptr-1,
              an_object["is"]
            );
            auto substantive_object_and_anchor_tags_tuple =
              obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
            an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
            anchor_tags = substantive_object_and_anchor_tags_tuple[1];
            an_object["attrib"] =
              obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
            the_document_body_section ~=
              set_abstract_object.contents_block(
                an_object["is"],
                an_object["substantive"],
                an_object["attrib"],
                obj_cite_number
              );
            object_reset(an_object);
            processing.remove("verse");
            ++cntr;
          }
        }
      } else if (type["tic_poem"] == TriState.on) {
        if (auto m = matchFirst(line, rgx.block_tic_close)) { // tic_poem_close
          an_object[an_object_key]="verse"; // check that this is as you please
          debug(poem) {                            // poem (curly) close
            writefln(
              "* [poem tic] %s",
              line
            );
          }
          if (processing.length > 0) {       // needs looking at
            an_object[an_object_key] = processing["verse"];
          }
          if (an_object.length > 0) {
            debug(poem) {                            // poem (tic) close
              writeln(__LINE__);
              writeln(obj_cite_number, line);
            }
            processing.remove("verse");
            an_object["is"] = "verse";
            auto substantive_object_and_anchor_tags_tuple =
              obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
            an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
            anchor_tags = substantive_object_and_anchor_tags_tuple[1];
            an_object["attrib"] =
              obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
            the_document_body_section ~=
              set_abstract_object.contents_block(
                an_object["is"],
                an_object["substantive"],
                an_object["attrib"],
                obj_cite_number
              );
            obj_cite_number_poem["end"] = to!string(obj_cite_number);
            object_reset(an_object);
            processing.remove("verse");
            ++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 =
              obj_cite_number_emit(type["obj_cite_number_status"]);
            type["verse_new"] = State.off;
          } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) {
            type["verse_new"] = State.on;
            verse_line = TriState.off;
          }
          if (type["verse_new"] == State.on) {
            verse_line=1;
            an_object[an_object_key] = processing["verse"];
            debug(poem) {                            // poem (tic) close
              writefln(
                "* %s tic\n%s",
                obj_cite_number,
                an_object[an_object_key]
              );
            }
            processing.remove("verse");
            an_object["is"] = "verse";
            _node =
              node_construct.node_emitter(
                content_non_header,
                segment_anchor_tag_that_object_belongs_to,
                obj_cite_number,
                cntr,
                heading_ptr-1,
                an_object["is"]
              );
            auto substantive_object_and_anchor_tags_tuple =
              obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
            an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
            anchor_tags = substantive_object_and_anchor_tags_tuple[1];
            an_object["attrib"] =
              obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
            the_document_body_section ~=
              set_abstract_object.contents_block(
                an_object["is"],
                an_object["substantive"],
                an_object["attrib"],
                obj_cite_number
              );
            object_reset(an_object);
            processing.remove("verse");
            ++cntr;
          }
        }
      }
    }
    void _group_block_(
      char[] line,
      ref string[string] an_object,
      ref int[string] type
    ) {
      if (type["curly_group"] == State.on) {
        if (matchFirst(line, rgx.block_curly_group_close)) {
          debug(group) {                           // group (curly) close
            writeln(line);
          }
          type["blocks"] = TriState.closing;
          type["group"] = TriState.closing;
          type["curly_group"] = TriState.off;
        } else {
          debug(group) {                           // group
            writeln(line);
          }
          an_object[an_object_key] ~= line ~= "\n";           // build group array (or string)
        }
      } else if (type["tic_group"] == TriState.on) {
        if (matchFirst(line, rgx.block_tic_close)) {
          debug(group) {                           // group (tic) close
            writeln(line);
          }
          type["blocks"] = TriState.closing;
          type["group"] = TriState.closing;
          type["tic_group"] = TriState.off;
        } else {
          debug(group) {                           // group
            writeln(line);
          }
          an_object[an_object_key] ~= line ~= "\n";           // build group array (or string)
        }
      }
    }
    void _block_block_(
      char[] line,
      ref string[string] an_object,
      ref int[string] type
    ) {
      if (type["curly_block"] == TriState.on) {
        if (matchFirst(line, rgx.block_curly_block_close)) {
          debug(block) {                           // block (curly) close
            writeln(line);
          }
          type["blocks"] = TriState.closing;
          type["block"] = TriState.closing;
          type["curly_block"] = TriState.off;
        } else {
          debug(block) {                           // block
            writeln(line);
          }
          an_object[an_object_key] ~= line ~= "\n";           // build block array (or string)
        }
      } else if (type["tic_block"] == TriState.on) {
        if (matchFirst(line, rgx.block_tic_close)) {
          debug(block) {                           // block (tic) close
            writeln(line);
          }
          type["blocks"] = TriState.closing;
          type["block"] = TriState.closing;
          type["tic_block"] = TriState.off;
        } else {
          debug(block) {                           // block
            writeln(line);
          }
          an_object[an_object_key] ~= line ~= "\n";           // build block array (or string)
        }
      }
    }
    void _quote_block_(
      char[] line,
      ref string[string] an_object,
      ref int[string] type
    ) {
      if (type["curly_quote"] == TriState.on) {
        if (matchFirst(line, rgx.block_curly_quote_close)) {
          debug(quote) {                           // quote (curly) close
            writeln(line);
          }
          type["blocks"] = TriState.closing;
          type["quote"] = TriState.closing;
          type["curly_quote"] = TriState.off;
        } else {
          debug(quote) {                           // quote
            writeln(line);
          }
          an_object[an_object_key] ~= line ~= "\n";           // build quote array (or string)
        }
      } else if (type["tic_quote"] == TriState.on) {
        if (matchFirst(line, rgx.block_tic_close)) {
          debug(quote) {                           // quote (tic) close
            writeln(line);
          }
          type["blocks"] = TriState.closing;
          type["quote"] = TriState.closing;
          type["tic_quote"] = TriState.off;
        } else {
          debug(quote) {                           // quote
            writeln(line);
          }
          an_object[an_object_key] ~= line ~= "\n";           // build quote array (or string)
        }
      }
    }
    void _table_block_(
      char[] line,
      ref string[string] an_object,
      ref int[string] type
    ) {
      if (type["curly_table"] == TriState.on) {
        if (matchFirst(line, rgx.block_curly_table_close)) {
          debug(table) {                           // table (curly) close
            writeln(line);
          }
          type["blocks"] = TriState.closing;
          type["table"] = TriState.closing;
          type["curly_table"] = TriState.off;
        } else {
          debug(table) {                           // table
            writeln(line);
          }
          an_object[an_object_key] ~= line ~= "\n";           // build table array (or string)
        }
      } else if (type["tic_table"] == TriState.on) {
        if (matchFirst(line, rgx.block_tic_close)) {
          debug(table) {                           // table (tic) close
            writeln(line);
          }
          type["blocks"] = TriState.closing;
          type["table"] = TriState.closing;
          type["tic_table"] = TriState.off;
        } else {
          debug(table) {                           // table
            writeln(line);
          }
          an_object[an_object_key] ~= line ~= "\n";           // build table array (or string)
        }
      }
    }
    void _block_flag_line_empty_(
      char[] line,
      ref string[string] an_object,
      ref ObjComposite[] the_document_body_section,
      ref string[][string][string] bookindex_unordered_hashes,
      ref int obj_cite_number,
      ref string[string][string] _node,
      ref long cntr,
      ref int[string] type,
      string[string] obj_cite_number_poem,
      string[string][string] dochead_make_aa,
    ) {
      // line.empty, post contents, empty variables ---------------
      assert(
        line.empty,
        "line should be empty"
      );
      assert(
        (type["blocks"] == TriState.closing),
        "code block status: closed"
      );
      assertions_flag_types_block_status_none_or_closed(type);
      if (type["code"] == TriState.closing) {
        obj_cite_number =
          obj_cite_number_emit(type["obj_cite_number_status"]);
        an_object["bookindex_nugget"] =
          ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
        bookindex_unordered_hashes =
          bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
        an_object["is"] = "code";
        _node =
          node_construct.node_emitter(
            content_non_header,
            segment_anchor_tag_that_object_belongs_to,
            obj_cite_number,
            cntr,
            heading_ptr-1,
            an_object["is"]
          );
        auto substantive_object_and_anchor_tags_tuple =
          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
        an_object["attrib"] =
          obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
        the_document_body_section ~=
          set_abstract_object.contents_block_code(
            an_object["is"],
            an_object["substantive"],
            an_object["attrib"],
            obj_cite_number
          );
        object_reset(an_object);
        processing.remove("verse");
        ++cntr;
        type["blocks"] = TriState.off;
        type["code"] = TriState.off;
      } else if (type["poem"] == TriState.closing) {
        an_object["bookindex_nugget"] =
          ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
        bookindex_unordered_hashes =
          bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
        an_object["is"] = "verse"; // check also
        _node =
          node_construct.node_emitter(
            content_non_header,
            segment_anchor_tag_that_object_belongs_to,
            obj_cite_number,
            cntr,
            heading_ptr-1,
            an_object["is"]
          );
        the_document_body_section ~=
          set_abstract_object.contents_block_obj_cite_number_string(
            "poem",
            "",
            (obj_cite_number_poem["start"], obj_cite_number_poem["end"]),
            _node
          ); // bookindex
        object_reset(an_object);
        processing.remove("verse");
        type["blocks"] = TriState.off;
        type["poem"] = TriState.off;
      } else if (type["table"] == TriState.closing) {
        obj_cite_number =
          obj_cite_number_emit(type["obj_cite_number_status"]);
        an_object["bookindex_nugget"] =
          ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
        bookindex_unordered_hashes =
          bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
        an_object["is"] = "table";
        _node =
          node_construct.node_emitter(
            content_non_header,
            segment_anchor_tag_that_object_belongs_to,
            obj_cite_number,
            cntr,
            heading_ptr-1,
            an_object["is"]
          );
        auto substantive_object_and_anchor_tags_tuple =
          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
        an_object["attrib"] =
          obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
        the_document_body_section ~=
          set_abstract_object.contents_block(
            an_object["is"],
            an_object["substantive"],
            an_object["attrib"],
            obj_cite_number
          );
        object_reset(an_object);
        processing.remove("verse");
        ++cntr;
        type["blocks"] = TriState.off;
        type["table"] = TriState.off;
      } else if (type["group"] == TriState.closing) {
        obj_cite_number =
          obj_cite_number_emit(type["obj_cite_number_status"]);
        an_object["bookindex_nugget"] =
          ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
        bookindex_unordered_hashes =
          bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
        an_object["is"] = "group";
        _node =
          node_construct.node_emitter(
            content_non_header,
            segment_anchor_tag_that_object_belongs_to,
            obj_cite_number,
            cntr,
            heading_ptr-1,
            an_object["is"]
          );
        auto substantive_object_and_anchor_tags_tuple =
          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
        an_object["attrib"] =
          obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
        the_document_body_section ~=
          set_abstract_object.contents_block(
            an_object["is"],
            an_object["substantive"],
            an_object["attrib"],
            obj_cite_number
          );
        object_reset(an_object);
        processing.remove("verse");
        ++cntr;
        type["blocks"] = TriState.off;
        type["group"] = TriState.off;
      } else if (type["block"] == TriState.closing) {
        obj_cite_number = obj_cite_number_emit(type["obj_cite_number_status"]);
        an_object["bookindex_nugget"] =
          ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
        bookindex_unordered_hashes =
          bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
        an_object["is"] = "block";
        _node =
          node_construct.node_emitter(
            content_non_header,
            segment_anchor_tag_that_object_belongs_to,
            obj_cite_number,
            cntr,
            heading_ptr-1,
            an_object["is"]
           );
        auto substantive_object_and_anchor_tags_tuple =
          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
        an_object["attrib"] =
          obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
        the_document_body_section ~=
          set_abstract_object.contents_block(
            an_object["is"],
            an_object["substantive"],
            an_object["attrib"],
            obj_cite_number
          );
        object_reset(an_object);
        processing.remove("verse");
        ++cntr;
        type["blocks"] = TriState.off;
        type["block"] = TriState.off;
      } else if (type["quote"] == TriState.closing) {
        obj_cite_number =
          obj_cite_number_emit(type["obj_cite_number_status"]);
        an_object["bookindex_nugget"] =
          ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
        bookindex_unordered_hashes =
          bkidx_hash(an_object["bookindex_nugget"], obj_cite_number);
        an_object["is"] = "quote";
        _node =
          node_construct.node_emitter(
            content_non_header,
            segment_anchor_tag_that_object_belongs_to,
            obj_cite_number,
            cntr,
            heading_ptr-1,
            an_object["is"]
          );
        auto substantive_object_and_anchor_tags_tuple =
          obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa);
        an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0];
        anchor_tags = substantive_object_and_anchor_tags_tuple[1];
        an_object["attrib"] =
          obj_att.obj_attributes(an_object["is"], an_object[an_object_key], _node);
        the_document_body_section ~=
          set_abstract_object.contents_block(
            an_object["is"],
            an_object["substantive"],
            an_object["attrib"],
            obj_cite_number
          );
        object_reset(an_object);
        processing.remove("verse");
        ++cntr;
        type["blocks"] = TriState.off;
        type["quote"] = TriState.off;
      }
    }
    auto _book_index_(
      char[]             line,
      ref string         book_idx_tmp,
      ref string[string] an_object,
      ref int[string]    type,
      bool[string]       opt_action_bool,
    ) {
      if (auto m = match(line, rgx.book_index)) {
        /+ match book_index +/
        debug(bookindexmatch) {                       // book index
          writefln(
            "* [bookindex] %s\n",
            to!string(m.captures[1]),
          );
        }
        an_object["bookindex_nugget"] = to!string(m.captures[1]);
      } else if (auto m = match(line, rgx.book_index_open))  {
        /+ match open book_index +/
        type["book_index"] = State.on;
        if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) {
          book_idx_tmp = to!string(m.captures[1]);
          debug(bookindexmatch) {                       // book index
            writefln(
              "* [bookindex] %s\n",
              book_idx_tmp,
            );
          }
        }
      } else if (type["book_index"] == State.on )  {
        /+ book_index flag set +/
        if (auto m = match(line, rgx.book_index_close))  {
          type["book_index"] = State.off;
          if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) {
            an_object["bookindex_nugget"] = book_idx_tmp ~ to!string(m.captures[1]);
            debug(bookindexmatch) {                     // book index
              writefln(
                "* [bookindex] %s\n",
                book_idx_tmp,
              );
            }
          }
          book_idx_tmp = "";
        } else {
          if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) {
            book_idx_tmp ~= line;
          }
        }
      }
    }
    auto _heading_found_(
      char[] line,
      string dochead_make_identify_unmarked_headings,
      ref string[string] heading_match_str,
      ref Regex!(char)[string] heading_match_rgx,
      ref int[string] type
    ) {
      if ((dochead_make_identify_unmarked_headings.length > 2)
      && (type["make_headings"] == State.off)) {
        /+ headings found +/
        debug(headingsfound) {
          writeln(dochead_make_identify_unmarked_headings);
        }
        char[][] make_headings_spl =
          split(
            cast(char[]) dochead_make_identify_unmarked_headings,
            rgx.make_heading_delimiter);
        debug(headingsfound) {
          writeln(make_headings_spl.length);
          writeln(make_headings_spl);
        }
        switch (make_headings_spl.length) {
        case 7 :
          if (!empty(make_headings_spl[6])) {
            heading_match_str["h_4"] =
              "^(" ~ to!string(make_headings_spl[6]) ~ ")";
            heading_match_rgx["h_4"] =
              regex(heading_match_str["h_4"]);
          }
          goto case;
        case 6 :
          if (!empty(make_headings_spl[5])) {
            heading_match_str["h_3"] =
              "^(" ~ to!string(make_headings_spl[5]) ~ ")";
            heading_match_rgx["h_3"] =
              regex(heading_match_str["h_3"]);
          }
          goto case;
        case 5 :
          if (!empty(make_headings_spl[4])) {
            heading_match_str["h_2"] =
              "^(" ~ to!string(make_headings_spl[4]) ~ ")";
            heading_match_rgx["h_2"] =
              regex(heading_match_str["h_2"]);
          }
          goto case;
        case 4 :
          if (!empty(make_headings_spl[3])) {
            heading_match_str["h_1"] =
              "^(" ~ to!string(make_headings_spl[3]) ~ ")";
            heading_match_rgx["h_1"] =
              regex(heading_match_str["h_1"]);
          }
          goto case;
        case 3 :
          if (!empty(make_headings_spl[2])) {
            heading_match_str["h_D"] =
              "^(" ~ to!string(make_headings_spl[2]) ~ ")";
            heading_match_rgx["h_D"] =
              regex(heading_match_str["h_D"]);
          }
          goto case;
        case 2 :
          if (!empty(make_headings_spl[1])) {
            heading_match_str["h_C"] =
              "^(" ~ to!string(make_headings_spl[1]) ~ ")";
            heading_match_rgx["h_C"] =
              regex(heading_match_str["h_C"]);
          }
          goto case;
        case 1 :
          if (!empty(make_headings_spl[0])) {
            heading_match_str["h_B"] =
              "^(" ~ to!string(make_headings_spl[0]) ~ ")";
            heading_match_rgx["h_B"] =
              regex(heading_match_str["h_B"]);
          }
          break;
        default:
          break;
        }
        type["make_headings"] = State.on;
      }
    }
    auto _heading_make_set_(
      ref char[] line,
      ref int[string] line_occur,
      ref Regex!(char)[string] heading_match_rgx,
      ref int[string] type
    ) {
      if ((type["make_headings"] == State.on)
      && ((line_occur["para"] == State.off)
      && (line_occur["heading"] == State.off))
      && ((type["para"] == State.off)
      && (type["heading"] == State.off))) {
        /+ heading make set +/
        if (matchFirst(line, heading_match_rgx["h_B"])) {
          line = "B~ " ~ line;
          debug(headingsfound) {
            writeln(line);
          }
        }
        if (matchFirst(line, heading_match_rgx["h_C"])) {
          line = "C~ " ~ line;
          debug(headingsfound) {
            writeln(line);
          }
        }
        if (matchFirst(line, heading_match_rgx["h_D"])) {
          line = "D~ " ~ line;
          debug(headingsfound) {
            writeln(line);
          }
        }
        if (matchFirst(line, heading_match_rgx["h_1"])) {
          line = "1~ " ~ line;
          debug(headingsfound) {
            writeln(line);
          }
        }
        if (matchFirst(line, heading_match_rgx["h_2"])) {
          line = "2~ " ~ line;
          debug(headingsfound) {
            writeln(line);
          }
        }
        if (matchFirst(line, heading_match_rgx["h_3"])) {
          line = "3~ " ~ line;
          debug(headingsfound) {
            writeln(line);
          }
        }
        if (matchFirst(line, heading_match_rgx["h_4"])) {
          line = "4~ " ~ line;
          debug(headingsfound) {
            writeln(line);
          }
        }
      }
    }
    auto _heading_matched_(
      char[] line,
      ref int[string] line_occur,
      ref string[string] an_object,
      ref string an_object_key,
      ref int[string] lv,
      ref int[string] collapsed_lev,
      ref int[string] type,
      ref string[string][string] dochead_meta_aa
    ) {
      if (auto m = match(line, rgx.heading)) {
        /+ heading match +/
        type["heading"] = State.on;
        if (match(line, rgx.heading_seg_and_above)) {
          type["biblio_section"] = State.off;
          type["glossary_section"] = State.off;
          type["blurb_section"] = State.off;
        }
        type["para"] = State.off;
        ++line_occur["heading"];
        an_object[an_object_key] ~= line ~= "\n";
        an_object["lev"] ~= m.captures[1];
        assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels
        switch (an_object["lev"]) {
        case "A":
          an_object[an_object_key]=replaceFirst(an_object[an_object_key],
            rgx.variable_doc_title, (dochead_meta_aa["title"]["full"] ~ ","));
          an_object[an_object_key]=replaceFirst(an_object[an_object_key],
            rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]);
          collapsed_lev["h0"] = 1;
          an_object["lev_collapsed_number"] =
            to!string(collapsed_lev["h0"]);
          lv["lv"] = DocStructMarkupHeading.h_sect_A;
          ++lv["h0"];
          lv["h1"] = State.off;
          lv["h2"] = State.off;
          lv["h3"] = State.off;
          lv["h4"] = State.off;
          lv["h5"] = State.off;
          lv["h6"] = State.off;
          lv["h7"] = State.off;
          goto default;
        case "B":
          collapsed_lev["h1"] = collapsed_lev["h0"] + 1;
          an_object["lev_collapsed_number"] =
            to!string(collapsed_lev["h1"]);
          lv["lv"] = DocStructMarkupHeading.h_sect_B;
          ++lv["h1"];
          lv["h2"] = State.off;
          lv["h3"] = State.off;
          lv["h4"] = State.off;
          lv["h5"] = State.off;
          lv["h6"] = State.off;
          lv["h7"] = State.off;
          goto default;
        case "C":
          collapsed_lev["h2"] = collapsed_lev["h1"] + 1;
          an_object["lev_collapsed_number"] =
            to!string(collapsed_lev["h2"]);
          lv["lv"] = DocStructMarkupHeading.h_sect_C;
          ++lv["h2"];
          lv["h3"] = State.off;
          lv["h4"] = State.off;
          lv["h5"] = State.off;
          lv["h6"] = State.off;
          lv["h7"] = State.off;
          goto default;
        case "D":
          collapsed_lev["h3"] = collapsed_lev["h2"] + 1;
          an_object["lev_collapsed_number"] =
            to!string(collapsed_lev["h3"]);
          lv["lv"] = DocStructMarkupHeading.h_sect_D;
          ++lv["h3"];
          lv["h4"] = State.off;
          lv["h5"] = State.off;
          lv["h6"] = State.off;
          lv["h7"] = State.off;
          goto default;
        case "1":
          if (lv["h3"] > State.off) {
            collapsed_lev["h4"] = collapsed_lev["h3"] + 1;
          } else if (lv["h2"] > State.off) {
            collapsed_lev["h4"] = collapsed_lev["h2"] + 1;
          } else if (lv["h1"] > State.off) {
            collapsed_lev["h4"] = collapsed_lev["h1"] + 1;
          } else if (lv["h0"] > State.off) {
            collapsed_lev["h4"] = collapsed_lev["h0"] + 1;
          }
          an_object["lev_collapsed_number"] =
            to!string(collapsed_lev["h4"]);
          lv["lv"] = DocStructMarkupHeading.h_text_1;
          ++lv["h4"];
          lv["h5"] = State.off;
          lv["h6"] = State.off;
          lv["h7"] = State.off;
          goto default;
        case "2":
          if (lv["h5"] > State.off) {
            an_object["lev_collapsed_number"] =
              to!string(collapsed_lev["h5"]);
          } else if (lv["h4"] > State.off) {
            collapsed_lev["h5"] = collapsed_lev["h4"] + 1;
            an_object["lev_collapsed_number"] =
              to!string(collapsed_lev["h5"]);
          }
          lv["lv"] = DocStructMarkupHeading.h_text_2;
          ++lv["h5"];
          lv["h6"] = State.off;
          lv["h7"] = State.off;
          goto default;
        case "3":
          if (lv["h6"] > State.off) {
            an_object["lev_collapsed_number"] =
              to!string(collapsed_lev["h6"]);
          } else if (lv["h5"] > State.off) {
            collapsed_lev["h6"] = collapsed_lev["h5"] + 1;
            an_object["lev_collapsed_number"] =
              to!string(collapsed_lev["h6"]);
          }
          lv["lv"] = DocStructMarkupHeading.h_text_3;
          ++lv["h6"];
          lv["h7"] = State.off;
          goto default;
        case "4":
          if (lv["h7"] > State.off) {
            an_object["lev_collapsed_number"] =
              to!string(collapsed_lev["h7"]);
          } else if (lv["h6"] > State.off) {
            collapsed_lev["h7"] = collapsed_lev["h6"] + 1;
            an_object["lev_collapsed_number"] =
              to!string(collapsed_lev["h7"]);
          }
          lv["lv"] = DocStructMarkupHeading.h_text_4;
          ++lv["h7"];
          goto default;
        default:
          an_object["lev_markup_number"] = to!string(lv["lv"]);
        }
        debug(heading) {                         // heading
          writeln(strip(line));
        }
      }
    }
    auto _para_match_(
      char[] line,
      ref string[string] an_object,
      ref string an_object_key,
      ref int[string] indent,
      ref bool bullet,
      ref int[string] type,
      ref int[string] line_occur,
    ) {
      if (line_occur["para"] == State.off) {
        /+ para matches +/
        type["para"] = State.on;
        an_object[an_object_key] ~= line; // body_nugget
        indent=[
          "hang_position" : 0,
          "base_position" : 0,
        ];
        bullet = false;
        if (auto m = matchFirst(line, rgx.para_indent)) {
          debug(paraindent) {                    // para indent
            writeln(line);
          }
          indent["hang_position"] = to!int(m.captures[1]);
          indent["base_position"] = 0;
        } else if (matchFirst(line, rgx.para_bullet)) {
          debug(parabullet) {                    // para bullet
            writeln(line);
          }
          bullet = true;
        } else if (auto m = matchFirst(line, rgx.para_indent_hang)) {
          debug(paraindenthang) {                // para indent hang
            writeln(line);
          }
          indent=[
            "hang_position" : to!int(m.captures[1]),
            "base_position" : to!int(m.captures[2]),
          ];
        } else if (auto m = matchFirst(line, rgx.para_bullet_indent)) {
          debug(parabulletindent) {              // para bullet indent
            writeln(line);
          }
          indent=[
            "hang_position" : to!int(m.captures[1]),
            "base_position" : 0,
          ];
          bullet = true;
        }
        ++line_occur["para"];
      }
    }
    /+ abstraction functions ↑ +/
    /+ ↓ abstraction function emitters +/
    struct OCNemitter {
      int obj_cite_number, obj_cite_number_;
      int obj_cite_number_emitter(int obj_cite_number_status_flag)
      in { assert(obj_cite_number_status_flag <= 2); }
      body {
        obj_cite_number=(obj_cite_number_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();
      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(string obj_txt_in) {
        /+ url matched +/
        if (auto m = matchAll(obj_txt_in, rgx.inline_url)) {
          /+ link: naked url: http://url +/
          if (match(obj_txt_in, rgx.inline_link_naked_url)) {
            obj_txt_in =
              replaceAll(
                obj_txt_in,
                rgx.inline_link_naked_url,
                ("$1" ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~  mkup.url_o ~ "$2" ~  mkup.url_c ~ "$3")            // ("$1{ $2 }$2$3")
              );
          }
          /+ link with helper for endnote including the url:
               {~^ link which includes url as footnote }http://url
             maps to:
               { link which includes url as footnote }http://url~{ { http://url }http://url }~
          +/
          if (match(obj_txt_in, rgx.inline_link_endnote_url_helper)) {
            obj_txt_in =
              replaceAll(
                obj_txt_in,
                rgx.inline_link_endnote_url_helper_punctuated,
                (mkup.lnk_o ~ " $1 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~  " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3")
              );
            obj_txt_in =
              replaceAll(
                obj_txt_in,
                rgx.inline_link_endnote_url_helper,
                (mkup.lnk_o ~ " $1 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~  " }~")   // ("{ $1 }$2~{ { $2 }$2 }~")
              );
          }
          /+ link with regular markup:
             { linked text or image }http://url
          +/
          if (match(obj_txt_in, rgx.inline_link_markup_regular)) {
            obj_txt_in =
              replaceAll(
                obj_txt_in,
                rgx.inline_link_markup_regular,
                ("$1" ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~  mkup.url_o ~ "$3" ~  mkup.url_c ~ "$4")            // ("$1{ $2 }$3$4")
              );
          }
        }
        return obj_txt_in;
      }
      string footnotes_endnotes_markup_and_number_or_stars(string obj_txt_in) {
        /+ endnotes (regular) +/
        obj_txt_in =
          replaceAll(
            obj_txt_in,
            rgx.inline_notes_curly,
            (mkup.en_a_o ~ " $1" ~ mkup.en_a_c)
          );
        if (match(obj_txt_in, rgx.inline_notes_al_gen)) {
          if (auto m = matchAll(obj_txt_in, rgx.inline_text_and_note_al_)) {
            foreach(n; m) {
              if (match(to!string(n.hit), rgx.inline_al_delimiter_open_symbol_star)) {
                ++n_foot_sp_asterisk;
                asterisks_ = "*";
                n_foot=n_foot_sp_asterisk;
                obj_txt_out ~=
                  (replaceFirst(
                    to!string(n.hit),
                    rgx.inline_al_delimiter_open_symbol_star,
                    (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ")
                  ) ~ "\n");
              } else if (match(to!string(n.hit), rgx.inline_al_delimiter_open_regular)) {
                ++n_foot_reg;
                n_foot=n_foot_reg;
                obj_txt_out ~=
                  (replaceFirst(
                    to!string(n.hit),
                    rgx.inline_al_delimiter_open_regular,
                    (mkup.en_a_o ~ to!string(n_foot) ~ " ")
                  ) ~ "\n");
              } else {
                obj_txt_out ~= to!string(n.hit) ~ "\n";
              }
            }
          }
        } else {
          obj_txt_out = obj_txt_in;
        }
        return obj_txt_out;
      }
      private auto object_notes_(string obj_txt_in)
      in { }
      body {
        obj_txt_out = "";
        tail = "";
        /+ special endnotes +/
        obj_txt_in = replaceAll(
          obj_txt_in,
          rgx.inline_notes_curly_sp_asterisk,
          (mkup.en_a_o ~ "*" ~ " $1" ~ mkup.en_a_c)
        );
        obj_txt_in =
          replaceAll(
            obj_txt_in,
            rgx.inline_notes_curly_sp_plus,
            (mkup.en_a_o ~ "+" ~ " $1" ~ mkup.en_a_c)
          );
        /+ url matched +/
        if (auto m = matchAll(obj_txt_in, rgx.inline_url)) {
          obj_txt_in = url_links(obj_txt_in);
        }
        obj_txt_out = footnotes_endnotes_markup_and_number_or_stars(obj_txt_in);
        debug(footnotes) {
          writeln(obj_txt_out, tail);
        }
        obj_txt_out = obj_txt_out ~ tail;
        debug(footnotesdone) {
          foreach(m; matchAll(obj_txt_out,
          (mkup.en_a_o ~ `\s*(.+?)` ~ mkup.en_a_c))) {
            writeln(m.captures[1]);
            writeln(m.hit);
          }
        }
        return obj_txt_out;
      }
      string para(string obj_txt_in)
      in { }
      body {
        auto rgx = Rgx();
        obj_txt["munge"]=obj_txt_in;
        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.para_attribs, "");
        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.obj_cite_number_off_all, "");
        obj_txt["munge"]=object_notes_(obj_txt["munge"]);
        debug(munge) {
          writeln(__LINE__);
          writeln(obj_txt_in);
          writeln(__LINE__);
          writeln(to!string(obj_txt["munge"]));
        }
        return obj_txt["munge"];
      }
      string heading(string obj_txt_in)
      in { }
      body {
        auto rgx = Rgx();
        obj_txt["munge"]=obj_txt_in;
        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.heading, "");
        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.obj_cite_number_off_all, "");
        obj_txt["munge"]=strip(obj_txt["munge"]);
        obj_txt["munge"]=object_notes_(obj_txt["munge"]);
        debug(munge) {
          writeln(__LINE__);
          writeln(obj_txt_in);
          writeln(__LINE__);
          writeln(to!string(obj_txt["munge"]));
        }
        return obj_txt["munge"];
      }
      invariant() {
      }
      /+ revisit +/
      string code(string obj_txt_in)
      in { }
      body {
        obj_txt["munge"]=obj_txt_in;
        return obj_txt["munge"];
      }
      invariant() {
      }
      string group(string obj_txt_in)
      in { }
      body {
        obj_txt["munge"]=obj_txt_in;
        obj_txt["munge"]=object_notes_(obj_txt["munge"]);
        return obj_txt["munge"];
      }
      invariant() {
      }
      string block(string obj_txt_in)
      in { }
      body {
        obj_txt["munge"]=obj_txt_in;
        obj_txt["munge"]=object_notes_(obj_txt["munge"]);
        return obj_txt["munge"];
      }
      invariant() {
      }
      string verse(string obj_txt_in)
      in { }
      body {
        obj_txt["munge"]=obj_txt_in;
        obj_txt["munge"]=object_notes_(obj_txt["munge"]);
        return obj_txt["munge"];
      }
      invariant() {
      }
      string quote(string obj_txt_in)
      in { }
      body {
        obj_txt["munge"]=obj_txt_in;
        return obj_txt["munge"];
      }
      invariant() {
      }
      string table(string obj_txt_in)
      in { }
      body {
        obj_txt["munge"]=obj_txt_in;
        return obj_txt["munge"];
      }
      invariant() {
      }
      string comment(string obj_txt_in)
      in { }
      body {
        obj_txt["munge"]=obj_txt_in;
        return obj_txt["munge"];
      }
      invariant() {
      }
    }
    struct ObjInlineMarkup {
      auto munge = ObjInlineMarkupMunge();
      string[string] obj_txt;
      auto obj_inline_markup_and_anchor_tags(
        string[string] obj_,
        string obj_key_,
        string[string][string] dochead_make_aa
      )
      in { }
      body {
        obj_txt["munge"]=obj_[obj_key_].dup;
        obj_txt["munge"]=(match(obj_["is"], ctRegex!(`verse|code`)))
        ? obj_txt["munge"]
        : strip(obj_txt["munge"]);
        static __gshared string[] anchor_tags_ = [];
        switch (obj_["is"]) {
        case "heading":
          static __gshared string anchor_tag = "";
          // TODO WORK ON, you still need to ensure that level 1 anchor_tags are unique
          obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, dochead_make_aa);
          obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"]);
          if (auto m = match(obj_txt["munge"], rgx.heading_anchor_tag)) {
            anchor_tag = m.captures[1];
            anchor_tags_ ~=anchor_tag;
          } else if (obj_["lev"] == "1") {
            writeln("heading anchor tag missing: ", obj_txt["munge"]);
          }
          obj_txt["munge"]=munge.heading(obj_txt["munge"]);
          break;
        case "para":
          obj_txt["munge"]=munge.para(obj_txt["munge"]);
          break;
        case "code":
          obj_txt["munge"]=munge.code(obj_txt["munge"]);
          break;
        case "group":
          obj_txt["munge"]=munge.group(obj_txt["munge"]);
          break;
        case "block":
          obj_txt["munge"]=munge.block(obj_txt["munge"]);
          break;
        case "verse":
          obj_txt["munge"]=munge.verse(obj_txt["munge"]);
          break;
        case "quote":
          obj_txt["munge"]=munge.quote(obj_txt["munge"]);
          break;
        case "table":
          obj_txt["munge"]=munge.table(obj_txt["munge"]);
          break;
        case "comment":
          obj_txt["munge"]=munge.comment(obj_txt["munge"]);
          break;
        case "doc_end_reset":
          munge.initialize_note_numbers();
          break;
        default:
          break;
        }
        auto t = tuple(
         obj_txt["munge"],
         anchor_tags_,
        );
        anchor_tags_=[];
        return t;
      }
      invariant() {
      }
      auto _clean_heading_toc_(
        char[] heading_toc_,
      ) {
       auto m = matchFirst(cast(char[]) heading_toc_, rgx.heading);
       heading_toc_ =
         replaceAll(
           m.post,
           rgx.inline_notes_curly_gen,
           ("")
         );
       return heading_toc_;
      };
      auto table_of_contents_gather_headings(
        string[string] obj_,
        string[string][string] dochead_make_aa,
        string segment_anchor_tag_that_object_belongs_to,
        string _anchor_tag,
        ObjComposite[][string] the_table_of_contents_section,
      )
      in { }
      body {
        char[] heading_toc_ = to!(char[])(obj_["body_nugget"].dup.strip);
        heading_toc_ = _clean_heading_toc_(heading_toc_);
        auto attrib="";
        string toc_txt_;
        int[string] indent;
        auto set_abstract_object = ObjectAbstractSet();
        if (to!int(obj_["lev_markup_number"]) > 0) {
          toc_txt_ = format(
            "{ %s }#%s",
            heading_toc_,
            _anchor_tag,
          );
          toc_txt_= munge.url_links(toc_txt_);
          indent=[
            "hang_position" : to!int(obj_["lev_markup_number"]),
            "base_position" : to!int(obj_["lev_markup_number"]),
          ];
          toc_txt_ = format(
            "{ %s }#%s",
            heading_toc_,
            _anchor_tag,
          );
          toc_txt_= munge.url_links(toc_txt_);
          the_table_of_contents_section["scroll"] ~=
            set_abstract_object.contents_toc(
              "toc",
              toc_txt_,
              "",                   // attrib
              0,
              indent,
              false
            );
        } else {
          indent=[
            "hang_position" : 0,
            "base_position" : 0,
          ];
          the_table_of_contents_section["scroll"] ~=
            set_abstract_object.contents_toc(
              "toc",
              "Table of Contents",
              "",                   // attrib
              0,
              indent,
              false
            );
        }
        switch (to!int(obj_["lev_markup_number"])) {
        case 0:
          indent=[
            "hang_position" : 0,
            "base_position" : 0,
          ];
          toc_txt_ = "{ Table of Contents }../toc.fn_suffix";
          toc_txt_= munge.url_links(toc_txt_);
          the_table_of_contents_section["seg"] ~=
            set_abstract_object.contents_toc(
              "toc",
              toc_txt_,
              "",                   // attrib
              0,
              indent,
              false
            );
          break;
        case 1: .. case 3:
          indent=[
            "hang_position" : to!int(obj_["lev_markup_number"]),
            "base_position" : to!int(obj_["lev_markup_number"]),
          ];
          toc_txt_ = format(
            "%s",
            heading_toc_,
          );
          toc_txt_= munge.url_links(toc_txt_);
          the_table_of_contents_section["seg"] ~=
            set_abstract_object.contents_toc(
              "toc",
              toc_txt_,
              "",                   // attrib
              0,
              indent,
              false
            );
          break;
        case 4:
          toc_txt_ = format(
            "{ %s }../%s.fn_suffix",
            heading_toc_,
            segment_anchor_tag_that_object_belongs_to,
          );
          toc_txt_= munge.url_links(toc_txt_);
          indent=[
            "hang_position" : to!int(obj_["lev_markup_number"]),
            "base_position" : to!int(obj_["lev_markup_number"]),
          ];
          the_table_of_contents_section["seg"] ~=
            set_abstract_object.contents_toc(
              "toc",
              toc_txt_,
              "",                   // attrib
              0,
              indent,
              false
            );
          break;
        case 5: .. case 7:
          toc_txt_ = format(
            "{ %s }../%s.fn_suffix#%s",
            heading_toc_,
            segment_anchor_tag_that_object_belongs_to,
            _anchor_tag,
          );
          toc_txt_= munge.url_links(toc_txt_);
          indent=[
            "hang_position" : to!int(obj_["lev_markup_number"]),
            "base_position" : to!int(obj_["lev_markup_number"]),
          ];
          the_table_of_contents_section["seg"] ~=
            set_abstract_object.contents_toc(
              "toc",
              toc_txt_,
              "",                   // attrib
              0,
              indent,
              false
            );
          break;
        default:
          break;
        }
        return the_table_of_contents_section;
      }
      invariant() {
      }
    private:
      static string _configured_auto_heading_numbering_and_segment_anchor_tags(
        string munge_,
        string[string] obj_,
        string[string][string]
        dochead_make_aa
      ) {
        if (dochead_make_aa["make"]["num_top"].length > 0) {
          if (!(match(munge_, rgx.heading_anchor_tag))) {
            static __gshared uint heading_num_top_level=9;
            static __gshared uint heading_num_depth=2;
            static __gshared uint heading_num_0 = 0;
            static __gshared uint heading_num_1 = 0;
            static __gshared uint heading_num_2 = 0;
            static __gshared uint heading_num_3 = 0;
            static __gshared string heading_number_auto_composite = "";
            if (heading_num_top_level==9) {
              if (dochead_make_aa["make"]["num_depth"].length > 0) {
                heading_num_depth = to!uint(dochead_make_aa["make"]["num_depth"]);
              }
              switch (dochead_make_aa["make"]["num_top"]) {
              case "A":
                break;
              case "B":
                heading_num_top_level=1;
                break;
              case "C":
                heading_num_top_level=2;
                break;
              case "D":
                heading_num_top_level=3;
                break;
              case "1":
                heading_num_top_level=4;
                break;
              case "2":
                heading_num_top_level=5;
                break;
              case "3":
                heading_num_top_level=6;
                break;
              case "4":
                heading_num_top_level=7;
                break;
              default:
                break;
              }
            }
            /+ num_depth minimum 0 (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement +/
            if (heading_num_top_level > to!uint(obj_["lev_markup_number"])) {
              heading_num_0 = 0;
              heading_num_1 = 0;
              heading_num_2 = 0;
              heading_num_3 = 0;
            } else if (heading_num_top_level == to!uint(obj_["lev_markup_number"])) {
              heading_num_0 ++;
              heading_num_1 = 0;
              heading_num_2 = 0;
              heading_num_3 = 0;
            } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 1)) {
              heading_num_1 ++;
              heading_num_2 = 0;
              heading_num_3 = 0;
            } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 2)) {
              heading_num_2 ++;
              heading_num_3 = 0;
            } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 3)) {
              heading_num_3 ++;
            }
            if (heading_num_3 > 0) {
              heading_number_auto_composite =
                (heading_num_depth == 3)
                ? ( to!string(heading_num_0) ~ "." ~
                      to!string(heading_num_1) ~ "." ~
                      to!string(heading_num_2) ~ "." ~
                      to!string(heading_num_3)
                    )
                : "";
            } else if (heading_num_2 > 0) {
              heading_number_auto_composite =
                ((heading_num_depth >= 2)
                && (heading_num_depth <= 3))
                ?  ( to!string(heading_num_0) ~ "." ~
                      to!string(heading_num_1) ~ "." ~
                      to!string(heading_num_2)
                    )
                : "";
            } else if (heading_num_1 > 0) {
              heading_number_auto_composite =
                ((heading_num_depth >= 1)
                && (heading_num_depth <= 3))
                ? ( to!string(heading_num_0) ~ "." ~
                      to!string(heading_num_1)
                    )
                : "";
            } else if (heading_num_0 > 0) {
              heading_number_auto_composite =
                ((heading_num_depth >= 0)
                && (heading_num_depth <= 3))
                ?  (to!string(heading_num_0))
                : "";
            } else {
              heading_number_auto_composite = "";
            }
            debug(heading_number_auto) {
              writeln(heading_number_auto_composite);
            }
            if (!empty(heading_number_auto_composite)) {
              munge_=replaceFirst(munge_, rgx.heading,
                "$1~$2 " ~ heading_number_auto_composite ~ ". ");
              munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
                "$1~" ~ heading_number_auto_composite ~ " ");
            }
          }
        }
        return munge_;
      }
    
    
      static string _make_segment_anchor_tags_if_none_provided(string munge_, string lev_) {
        if (!(match(munge_, rgx.heading_anchor_tag))) { // if (anchor_tags_.length == 0) {
          if (match(munge_, rgx.heading_identify_anchor_tag)) {
            if (auto m = match(munge_, rgx.heading_extract_named_anchor_tag)) {
              munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
                "$1~" ~ toLower(m.captures[1]) ~ "_"  ~ m.captures[2] ~ " ");
            } else if (auto m = match(munge_, rgx.heading_extract_unnamed_anchor_tag)) {
              munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
                "$1~" ~ "s" ~ m.captures[1] ~ " ");
            }
          } else if (lev_ == "1") { // (if not successful) manufacture a unique anchor tag for lev=="1"
            static __gshared uint heading_num_lev1 = 0;
            heading_num_lev1 ++;
            munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
              "$1~" ~ "x" ~ to!string(heading_num_lev1) ~ " ");
          }
        }
        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(
        string obj_is_,
        string obj_raw,
        string[string][string] _node
      )
      in { }
      body {
        scope(exit) {
          destroy(obj_is_);
          destroy(obj_raw);
          destroy(_node);
        }
        _obj_attrib.remove("json");
        _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_, _node);
        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(string obj_txt_in)
      in { }
      body {
        auto rgx = Rgx();
        if (matchFirst(obj_txt_in, rgx.para_bullet)) {
          _obj_attributes =" \"bullet\": \"true\","
          ~ " \"indent_start\": 0,"
          ~ " \"indent_rest\": 0,";
        } else if (auto m = matchFirst(obj_txt_in, rgx.para_bullet_indent)) {
          _obj_attributes =" \"bullet\": \"true\","
          ~ " \"indent_start\": " ~ to!string(m.captures[1]) ~ ","
          ~ " \"indent_rest\": " ~ to!string(m.captures[1]) ~ ",";
        } else if (auto m = matchFirst(obj_txt_in, rgx.para_indent_hang)) {
          _obj_attributes =" \"bullet\": \"false\","
          ~ " \"indent_start\": " ~ to!string(m.captures[1]) ~ ","
          ~ " \"indent_rest\": " ~  to!string(m.captures[2]) ~ ",";
        } else if (auto m = matchFirst(obj_txt_in, rgx.para_indent)) {
          _obj_attributes =" \"bullet\": \"false\","
          ~ " \"indent_start\": " ~ to!string(m.captures[1]) ~ ","
          ~ " \"indent_rest\": " ~ to!string(m.captures[1]) ~ ",";
        } else {
          _obj_attributes =" \"bullet\": \"false\","
          ~ " \"indent_start\": 0,"
          ~ " \"indent_rest\": 0,";
        }
        return _obj_attributes;
      }
      string _para(string obj_txt_in)
      in { }
      body {
        _obj_attributes = " \"use\": \"content\","
        ~ " \"of\": \"para\","
        ~ " \"is\": \"para\"";
        return _obj_attributes;
      }
      invariant() {
      }
      string _heading(string obj_txt_in)
      in { }
      body {
        _obj_attributes = " \"use\": \"content\","
        ~ " \"of\": \"para\","
        ~ " \"is\": \"heading\"";
        return _obj_attributes;
      }
      invariant() {
      }
      string _code(string obj_txt_in)
      in { }
      body {
        _obj_attributes = " \"use\": \"content\","
        ~ " \"of\": \"block\","
        ~ " \"is\": \"code\"";
        return _obj_attributes;
      }
      invariant() {
      }
      string _group(string obj_txt_in)
      in { }
      body {
        _obj_attributes = " \"use\": \"content\","
        ~ " \"of\": \"block\","
        ~ " \"is\": \"group\"";
        return _obj_attributes;
      }
      invariant() {
      }
      string _block(string obj_txt_in)
      in { }
      body {
        _obj_attributes = " \"use\": \"content\","
        ~ " \"of\": \"block\","
        ~ " \"is\": \"block\"";
        return _obj_attributes;
      }
      invariant() {
      }
      string _verse(string obj_txt_in)
      in { }
      body {
        _obj_attributes = " \"use\": \"content\","
        ~ " \"of\": \"block\","
        ~ " \"is\": \"verse\"";
        return _obj_attributes;
      }
      invariant() {
      }
      string _quote(string obj_txt_in)
      in { }
      body {
        _obj_attributes = " \"use\": \"content\","
        ~ " \"of\": \"block\","
        ~ " \"is\": \"quote\"";
        return _obj_attributes;
      }
      invariant() {
      }
      string _table(string obj_txt_in)
      in { }
      body {
        _obj_attributes = " \"use\": \"content\","
        ~ " \"of\": \"block\","
        ~ " \"is\": \"table\"";
        return _obj_attributes;
      }
      invariant() {
      }
      string _comment(string obj_txt_in)
      in { }
      body {
        _obj_attributes = " \"use\": \"comment\","
        ~ " \"of\": \"comment\","
        ~ " \"is\": \"comment\"";
        return _obj_attributes;
      }
      invariant() {
      }
      string _set_additional_values_parse_as_json(
        string _obj_attrib,
        string obj_is_,
        string[string][string] _node
      ) {                                                  //
        JSONValue oa_j = parseJSON(_obj_attrib);
        assert(
          (oa_j.type == JSON_TYPE.OBJECT)
        );
        if (obj_is_ == "heading") {
          oa_j.object["obj_cite_number"] = _node["object"]["obj_cite_number"];
          oa_j.object["lev_markup_number"] = _node["heading"]["lev_markup_number"];
          oa_j.object["lev_collapsed_number"] = _node["heading"]["lev_collapsed_number"];
          oa_j.object["heading_ptr"] =
            _node["object"]["heading_ptr"]; // check
          oa_j.object["doc_object_ptr"] =
            _node["object"]["doc_object_ptr"]; // check
        }
        oa_j.object["parent_obj_cite_number"] = _node["object"]["parent_obj_cite_number"];
        oa_j.object["parent_lev_markup_number"] = _node["object"]["parent_lev_markup_number"];
        _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(
        string bookindex_section,
        int obj_cite_number
      )
      in {
        debug(bookindexraw) {
          if (!bookindex_section.empty) {
            writeln(
              "* [bookindex] ",
              "[", to!string(obj_cite_number), "] ", bookindex_section
            );
          }
        }
      }
      body {
        auto rgx = Rgx();
        if (!bookindex_section.empty) {
          auto bi_main_terms_split_arr =
            split(bookindex_section, rgx.bi_main_terms_split);
          foreach (bi_main_terms_content; bi_main_terms_split_arr) {
            auto bi_main_term_and_rest =
              split(bi_main_terms_content, rgx.bi_main_term_plus_rest_split);
            if (auto m = match(
              bi_main_term_and_rest[0],
              rgx.bi_term_and_obj_cite_numbers_match)
            ) {
              main_term = strip(m.captures[1]);
              obj_cite_number_offset = to!int(m.captures[2]);
              obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset);
              obj_cite_numbers ~= (to!string(obj_cite_number) ~ "-" ~ to!string(obj_cite_number_endpoint));
            } else {
              main_term = strip(bi_main_term_and_rest[0]);
              obj_cite_numbers ~= to!string(obj_cite_number);
            }
            bi[main_term]["_a"] ~= obj_cite_numbers;
            obj_cite_numbers=null;
            if (bi_main_term_and_rest.length > 1) {
              auto bi_sub_terms_split_arr =
                split(
                  bi_main_term_and_rest[1],
                  rgx.bi_sub_terms_plus_obj_cite_number_offset_split
                );
              foreach (sub_terms_bits; bi_sub_terms_split_arr) {
                if (auto m = match(sub_terms_bits, rgx.bi_term_and_obj_cite_numbers_match)) {
                  sub_term = strip(m.captures[1]);
                  obj_cite_number_offset = to!int(m.captures[2]);
                  obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset);
                  obj_cite_numbers ~= (to!string(obj_cite_number) ~ " - " ~ to!string(obj_cite_number_endpoint));
                } else {
                  sub_term = strip(sub_terms_bits);
                  obj_cite_numbers ~= to!string(obj_cite_number);
                }
                if (!empty(sub_term)) {
                  bi[main_term][sub_term] ~= obj_cite_numbers;
                }
                obj_cite_numbers=null;
              }
            }
          }
        }
        hash_nugget = bi;
        return hash_nugget;
      }
      invariant() {
      }
    }
    struct BookIndexReportIndent {
      int mkn, skn;
      auto bookindex_report_indented(
        string[][string][string] bookindex_unordered_hashes
      ) {
        auto mainkeys=
          bookindex_unordered_hashes.byKey.array.sort().release;
        foreach (mainkey; mainkeys) {
          debug(bookindex) {
            writeln(mainkey);
          }
          auto subkeys=
            bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
          foreach (subkey; subkeys) {
            debug(bookindex) {
              writeln("  ", subkey);
              writeln("    ", to!string(
                bookindex_unordered_hashes[mainkey][subkey]
              ));
            }
            ++skn;
          }
          ++mkn;
        }
      }
    }
    struct BookIndexReportSection {
      int mkn, skn;
      auto rgx = Rgx();
      auto munge = ObjInlineMarkupMunge();
      auto bookindex_write_section(
        string[][string][string] bookindex_unordered_hashes
      ) {
        auto mainkeys=bookindex_unordered_hashes.byKey.array.sort().release;
        foreach (mainkey; mainkeys) {
          write("_0_1 !{", mainkey, "}! ");
          foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
            auto go = replaceAll(ref_, rgx.book_index_go, "$1");
            write(" {", ref_, "}#", go, ", ");
          }
          writeln(" \\\\");
          bookindex_unordered_hashes[mainkey].remove("_a");
          auto subkeys=
            bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
          foreach (subkey; subkeys) {
            write("  ", subkey, ", ");
            foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
              auto go = replaceAll(ref_, rgx.book_index_go, "$1");
              write(" {", ref_, "}#", go, ", ");
            }
            writeln(" \\\\");
            ++skn;
          }
          ++mkn;
        }
      }
      auto bookindex_build_section(
        string[][string][string] bookindex_unordered_hashes,
        int                      obj_cite_number,
        string                   segment_anchor_tag_that_object_belongs_to,
        bool[string]             opt_action_bool,
      ) {
        mixin SiSUnode;
        string type;
        string lev;
        int lev_int_markup, lev_int_collapsed;
        string attrib;
        int[string] indent;
        auto set_abstract_object = ObjectAbstractSet();
        auto mainkeys =
          bookindex_unordered_hashes.byKey.array.sort().release;
        ObjComposite[][string] bookindex_section;
        auto node_ = node_metadata;
        if ((mainkeys.length > 0)
        && (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"])) {
          string bi_tmp_seg, bi_tmp_scroll;
          attrib="";
          lev="B";
          lev_int_markup=1;
          lev_int_collapsed=1;
          node_["object"]["is"]                       = "heading";
          node_["object"]["obj_cite_number"]          = "0";
          node_["object"]["segment_anchor_tag"]       = "bookindex";
          node_["object"]["parent_obj_cite_number"]   = "1";
          node_["object"]["parent_lev_markup_number"] = "0";
          bookindex_section["scroll"] ~=
            set_abstract_object.contents_heading(
              "Book Index",
              attrib,
              obj_cite_number,
              [],
              to!string(lev),
              lev_int_markup,
              lev_int_collapsed,
              node_,
            );
          bookindex_section["seg"] ~=
            set_abstract_object.contents_heading(
              "Book Index",
              attrib,
              obj_cite_number,
              [],
              to!string(lev),
              lev_int_markup,
              lev_int_collapsed,
              node_,
            );
          ++obj_cite_number;
          ++mkn;
          // 1~ Index
          attrib="";
          lev="1";
          lev_int_markup=4;
          lev_int_collapsed=2;
          node_["object"]["is"]                       = "heading";
          node_["object"]["obj_cite_number"]          = "0";
          node_["object"]["segment_anchor_tag"]       = "bookindex";
          node_["object"]["parent_obj_cite_number"]   = "1";
          node_["object"]["parent_lev_markup_number"] = "0";
          bookindex_section["scroll"] ~=
            set_abstract_object.contents_heading(
              "Index",
              attrib,
              obj_cite_number,
              ["book_index"],
              to!string(lev),
              lev_int_markup,
              lev_int_collapsed,
              node_,
            );
          bookindex_section["seg"] ~=
            set_abstract_object.contents_heading(
              "Index",
              attrib,
              obj_cite_number,
              ["book_index"],
              to!string(lev),
              lev_int_markup,
              lev_int_collapsed,
              node_,
            );
          ++obj_cite_number;
          ++mkn;
          foreach (mainkey; mainkeys) {
            bi_tmp_scroll = "!{" ~ mainkey ~ "}! ";
            bi_tmp_seg = "!{" ~ mainkey ~ "}! ";
            foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
              auto go = replaceAll(ref_, rgx.book_index_go, "$1");
              bi_tmp_scroll ~= munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ");
              bi_tmp_seg ~= (segment_anchor_tag_that_object_belongs_to.empty)
              ? munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ")
              : munge.url_links(" {" ~ ref_ ~ "}../" ~ segment_anchor_tag_that_object_belongs_to ~ ".fn_suffix#" ~ go ~ ", ");
            }
            bi_tmp_scroll ~= " \\\\\n    ";
            bi_tmp_seg ~= " \\\\\n    ";
            bookindex_unordered_hashes[mainkey].remove("_a");
            auto subkeys =
              bookindex_unordered_hashes[mainkey].byKey.array.sort().release;
            foreach (subkey; subkeys) {
              bi_tmp_scroll ~= subkey ~ ", ";
              bi_tmp_seg ~= subkey ~ ", ";
              foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
                auto go = replaceAll(ref_, rgx.book_index_go, "$1");
                bi_tmp_scroll ~= munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ");
                bi_tmp_seg ~= (segment_anchor_tag_that_object_belongs_to.empty)
                ? munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ")
                : munge.url_links(" {" ~ ref_ ~ "}../" ~ segment_anchor_tag_that_object_belongs_to ~ ".fn_suffix#" ~ go ~ ", ");
              }
              bi_tmp_scroll ~= " \\\\\n    ";
              bi_tmp_seg ~= " \\\\\n    ";
              ++skn;
            }
            bi_tmp_scroll = replaceFirst(bi_tmp_scroll, rgx.trailing_linebreak, "");
            bi_tmp_seg = replaceFirst(bi_tmp_seg, rgx.trailing_linebreak, "");
            type="para";
            attrib="";
            indent=[
              "hang_position" : 0,
              "base_position" : 1,
            ];
            bookindex_section["scroll"] ~=
              set_abstract_object.contents_para(
                type,
                bi_tmp_scroll,
                attrib,
                obj_cite_number,
                indent,
                false
              );
            bookindex_section["seg"] ~=
              set_abstract_object.contents_para(
                type,
                bi_tmp_seg,
                attrib,
                obj_cite_number,
                indent,
                false
              );
            ++obj_cite_number;
            ++mkn;
          }
        } else {                              // no book index, (figure out what to do here)
          node_["object"]["is"]                       = "heading";
          node_["object"]["obj_cite_number"]          = "0";
          node_["object"]["segment_anchor_tag"]       = "bookindex";
          node_["object"]["parent_obj_cite_number"]   = "1";
          node_["object"]["parent_lev_markup_number"] = "0";
          bookindex_section["scroll"] ~=
            set_abstract_object.contents_heading(
              "(skip) there is no Book Index",
              "",                             // attrib,
              0,
              [""],
              "B",
              1,
              1,
              node_,
            );
          bookindex_section["seg"] ~=
            set_abstract_object.contents_heading(
              "(skip) there is no Book Index",
              "",                             // attrib,
              0,
              [""],
              "B",
              1,
              1,
              node_,
            );
        }
        auto t = tuple(bookindex_section, obj_cite_number);
        return t;
      }
    }
    struct NotesSection {
      string[string] object_notes;
      long previous_count;
      int mkn;
      auto rgx = Rgx();
      private auto gather_notes_for_endnote_section(
        ObjComposite[] contents_am,
        string         segment_anchor_tag_that_object_belongs_to,
        ulong          cntr,
      )
      in {
        // endnotes/ footnotes for
        // doc objects other than paragraphs & headings
        // various forms of grouped text
        assert((contents_am[cntr].is_a == "para")
        || (contents_am[cntr].is_a == "heading")
        || (contents_am[cntr].is_a == "group"));
        assert(cntr >= previous_count);
        previous_count=cntr;
        assert(
          match(contents_am[cntr].object,
          rgx.inline_notes_delimiter_al_regular_number_note)
        );
      }
      body {
        auto munge = ObjInlineMarkupMunge();
        foreach(
          m;
          matchAll(
            contents_am[cntr].object,
            rgx.inline_notes_delimiter_al_regular_number_note
          )
        ) {
          debug(endnotes_build) {
            writeln(
              "{^{", m.captures[1], ".}^}../", segment_anchor_tag_that_object_belongs_to, ".fn_suffix#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["seg"] ~= (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] ~ ".}^}../" ~ segment_anchor_tag_that_object_belongs_to ~ ".fn_suffix#noteref_" ~
              m.captures[1]) ~ " " ~ m.captures[2] ~ "』"
            );
          object_notes["scroll"] ~=
            munge.url_links(
              "{^{" ~ m.captures[1] ~ ".}^}#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_["seg"] = (split(object_notes["seg"], rgx.break_string))[0..$-1];
          endnotes_["scroll"] = (split(object_notes["scroll"], rgx.break_string))[0..$-1];
          endnotes_["anchor"] = (split(object_notes["anchor"], rgx.break_string))[0..$-1];
        } else {
          endnotes_["seg"] = [];
          endnotes_["scroll"] = [];
          endnotes_["anchor"] = [];
        }
        return endnotes_;
      }
      private auto endnote_objects(
        int            obj_cite_number,
        bool[string]   opt_action_bool,
      )
      in {
      }
      body {
        mixin SiSUnode;
        auto set_abstract_object = ObjectAbstractSet();
        ObjComposite[][string] the_endnotes_section;
        auto endnotes_ = gathered_notes();
        string type;
        string lev, lev_markup_number, lev_collapsed_number;
        string attrib;
        int[string] indent;
        auto node_ = node_metadata;
        if ((endnotes_["seg"].length > 0)
        && (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"])) {
          attrib="";
          lev="B";
          lev_markup_number="1";
          lev_collapsed_number="1";
          node_["object"]["is"]                       = "heading";
          node_["object"]["obj_cite_number"]          = "0";
          node_["object"]["segment_anchor_tag"]       = "endnotes";
          node_["object"]["parent_obj_cite_number"]   = "1";
          node_["object"]["parent_lev_markup_number"] = "0";
          the_endnotes_section["seg"] ~=
            set_abstract_object.contents_heading(
              "Endnotes",
              attrib,
              obj_cite_number,
              [],
              to!string(lev),
              to!int(lev_markup_number),
              to!int(lev_collapsed_number),
              node_,
            );
          the_endnotes_section["scroll"] ~=
            set_abstract_object.contents_heading(
              "Endnotes",
              attrib,
              obj_cite_number,
              [],
              to!string(lev),
              to!int(lev_markup_number),
              to!int(lev_collapsed_number),
              node_,
            );
          ++obj_cite_number;
          ++mkn;
          attrib="";
          lev="1";
          lev_markup_number="4";
          lev_collapsed_number="2";
          node_["object"]["is"]                       = "heading";
          node_["object"]["obj_cite_number"]          = "0";
          node_["object"]["segment_anchor_tag"]       = "endnotes";
          node_["object"]["parent_obj_cite_number"]   = "1";
          node_["object"]["parent_lev_markup_number"] = "0";
          the_endnotes_section["seg"] ~=
            set_abstract_object.contents_heading(
              "Endnotes",
              attrib,
              obj_cite_number,
              ["endnotes"],
              to!string(lev),
              to!int(lev_markup_number),
              to!int(lev_collapsed_number),
              node_,
            );
          the_endnotes_section["scroll"] ~=
            set_abstract_object.contents_heading(
              "Endnotes",
              attrib,
              obj_cite_number,
              ["endnotes"],
              to!string(lev),
              to!int(lev_markup_number),
              to!int(lev_collapsed_number),
              node_,
            );
          ++obj_cite_number;
          ++mkn;
        } else {
          node_["object"]["is"]                       = "heading";
          node_["object"]["obj_cite_number"]          = "0";
          node_["object"]["segment_anchor_tag"]       = "endnotes";
          node_["object"]["parent_obj_cite_number"]   = "1";
          node_["object"]["parent_lev_markup_number"] = "0";
          the_endnotes_section["seg"] ~=
            set_abstract_object.contents_heading(
              "(skip) there are no Endnotes",
              "",                             // attrib,
              0,
              [""],
              "B",
              1,
              1,
              node_,
            );
          the_endnotes_section["scroll"] ~=
            set_abstract_object.contents_heading(
              "(skip) there are no Endnotes",
              "",                             // attrib,
              0,
              [""],
              "B",
              1,
              1,
              node_,
            );
        }
        if (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"]) {
          foreach (i, endnote; endnotes_["seg"]) {
            attrib="";
            the_endnotes_section["seg"] ~=
              set_abstract_object.contents_endnote(endnote, endnotes_["anchor"][i]);
          }
          foreach (i, endnote; endnotes_["scroll"]) {
            attrib="";
            the_endnotes_section["scroll"] ~=
              set_abstract_object.contents_endnote(endnote, endnotes_["anchor"][i]);
          }
        }
        auto t = tuple(the_endnotes_section, obj_cite_number);
        return t;
      }
    }
    struct Bibliography {
      public JSONValue[] _bibliography_(
        ref string[] biblio_unsorted_incomplete,
        ref JSONValue[] bib_arr_json
      )
      in { }
      body {
        JSONValue[] biblio_unsorted =
          _biblio_unsorted_complete_(biblio_unsorted_incomplete, bib_arr_json);
        JSONValue[] biblio_sorted__ = biblio_sort(biblio_unsorted);
        biblio_debug(biblio_sorted__);
        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_(
        string[] biblio_unordered,
        ref JSONValue[] bib_arr_json
      ) {
        foreach (bibent; biblio_unordered) {
          // update bib to include deemed_author, needed for:
          // sort_bibliography_array_by_deemed_author_year_title
          // either: sort on multiple fields, or; create such sort field
          JSONValue j = parseJSON(bibent);
          if (!empty(j["fulltitle"].str)) {
            if (!empty(j["author_raw"].str)) {
              j["deemed_author"]=j["author_arr"][0];
            } else if (!empty(j["editor_raw"].str)) {
              j["deemed_author"]=j["editor_arr"][0];
            }
            j["sortby_deemed_author_year_title"] = (
              j["deemed_author"].str ~
               "; " ~
               j["year"].str ~
               "; "  ~
               j["fulltitle"].str
            );
          }
          bib_arr_json ~= j;
        }
        JSONValue[] biblio_unsorted_array_of_json_objects =
          bib_arr_json.dup;
        return biblio_unsorted_array_of_json_objects;
      }
      final private JSONValue[] biblio_sort(JSONValue[] biblio_unordered) {
        JSONValue[] biblio_sorted_;
        biblio_sorted_ =
          sort!((a, b){
            return ((a["sortby_deemed_author_year_title"].str) < (b["sortby_deemed_author_year_title"].str));
          })(biblio_unordered).array;
        debug(bibliosorted) {
          foreach (j; biblio_sorted_) {
            if (!empty(j["fulltitle"].str)) {
              writeln(j["sortby_deemed_author_year_title"]);
            }
          }
        }
        return biblio_sorted_;
      }
      void biblio_debug(JSONValue[] biblio_sorted) {
        debug(biblio0) {
          foreach (j; biblio_sorted) {
            if (!empty(j["fulltitle"].str)) {
              writeln(j["sortby_deemed_author_year_title"]);
            }
          }
        }
      }
    }
    struct NodeStructureMetadata {
      int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7;
      int obj_cite_number;
      int[string] p_; // p_ parent_
      string[string][string] _node;
      string[string][string] node_emitter(
        string lev_markup_number,
        string segment_anchor_tag,
        int    obj_cite_number_,
        long   cntr_,
        int    ptr_,
        string is_
      )
      in {
        auto rgx = Rgx();
        assert(is_ != "heading");
        assert(to!int(obj_cite_number_) >= 0);
      }
      body {
        assert(is_ != "heading"); // should not be necessary
        assert(to!int(obj_cite_number_) >= 0); // should not be necessary
        int obj_cite_number=to!int(obj_cite_number_);
        if (lv7 > State.off) {
          p_["lev_markup_number"] = DocStructMarkupHeading.h_text_4;
          p_["obj_cite_number"] = lv7;
        } else if (lv6 > State.off) {
          p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3;
          p_["obj_cite_number"] = lv6;
        } else if (lv5 > State.off) {
          p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2;
          p_["obj_cite_number"] = lv5;
        } else {
          p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1;
          p_["obj_cite_number"] = lv4;
        }
        auto _node = [
          "object" : [
            "is"                         : is_,
            "heading_ptr"                : to!string(ptr_),
            "doc_object_ptr"             : to!string(cntr_),
            "obj_cite_number"            : to!string(obj_cite_number_),
            "segment_anchor_tag"         : to!string(segment_anchor_tag),
            "parent_obj_cite_number"     : to!string(p_["obj_cite_number"]),
            "parent_lev_markup_number"   : to!string(p_["lev_markup_number"]),
          ],
          "heading" : [
            "html_segnames_ptr"          : "",
            "lev_markup_number"          : "",
            "lev_collapsed_number"       : "",
            // "ancestors"                  : "",
            // "open_headings_to_close"     : "",
          ]
        ];
        debug(node) {
          if (match(lev_markup_number, rgx.levels_numbered_headings)) {
            writeln("x ", to!string(_node));
          } else {
            writeln("- ", to!string(_node));
          }
        }
        assert(to!int(_node["object"]["parent_lev_markup_number"]) >= 4);
        assert(to!int(_node["object"]["parent_lev_markup_number"]) <= 7);
        assert(to!int(_node["object"]["parent_obj_cite_number"]) >= 0);      // hmm, perhaps
        return _node;
      }
      invariant() {
      }
      string[string][string] node_emitter_heading(
        string lev_markup_number,
        string lev_collapsed_number,
        string segment_anchor_tag,
        int    obj_cite_number_,
        long   cntr_,
        int    ptr_,
        string is_,
        uint html_segnames_ptr,
      )
      in {
        auto rgx = Rgx();
        assert(is_ == "heading");
        assert(to!int(obj_cite_number_) >= 0);
        assert(
          match(lev_markup_number, rgx.levels_numbered),
          ("not a valid heading level: " ~ lev_markup_number ~ " at " ~ to!string(obj_cite_number_))
        );
        if (match(lev_markup_number, rgx.levels_numbered)) {
          if (to!int(lev_markup_number) == 0) {
            assert(to!int(obj_cite_number_) == 1);
          }
        }
      }
      body {
        auto rgx = Rgx();
        int obj_cite_number = to!int(obj_cite_number_);
        switch (to!int(lev_markup_number)) { // switch (to!string(lv)) {
        case 0:
          lv = DocStructMarkupHeading.h_sect_A;
          lv0 = obj_cite_number;
          lv1=0; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
          p_["lev_markup_number"] = 0;
          p_["obj_cite_number"] = 0;
          break;
        case 1:
          lv = DocStructMarkupHeading.h_sect_B;
          lv1 = obj_cite_number;
          lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
          p_["lev_markup_number"] =
            DocStructMarkupHeading.h_sect_A;
          p_["obj_cite_number"] = lv0;
          break;
        case 2:
          lv = DocStructMarkupHeading.h_sect_C;
          lv2 = obj_cite_number;
          lv3=0; lv4=0; lv5=0; lv6=0; lv7=0;
          p_["lev_markup_number"] =
            DocStructMarkupHeading.h_sect_B;
          p_["obj_cite_number"] = lv1;
          break;
        case 3:
          lv = DocStructMarkupHeading.h_sect_D;
          lv3=obj_cite_number;
          lv4=0; lv5=0; lv6=0; lv7=0;
          p_["lev_markup_number"] =
            DocStructMarkupHeading.h_sect_C;
          p_["obj_cite_number"] = lv2;
          break;
        case 4:
          lv = DocStructMarkupHeading.h_text_1;
          lv4 = obj_cite_number;
          lv5=0; lv6=0; lv7=0;
          if (lv3 > State.off) {
            p_["lev_markup_number"] =
              DocStructMarkupHeading.h_sect_D;
            p_["obj_cite_number"] = lv3;
          } else if (lv2 > State.off) {
            p_["lev_markup_number"] =
              DocStructMarkupHeading.h_sect_C;
            p_["obj_cite_number"] = lv2;
          } else if (lv1 > State.off) {
            p_["lev_markup_number"] =
              DocStructMarkupHeading.h_sect_B;
            p_["obj_cite_number"] = lv1;
          } else {
            p_["lev_markup_number"] =
              DocStructMarkupHeading.h_sect_A;
            p_["obj_cite_number"] = lv0;
          }
          break;
        case 5:
          lv = DocStructMarkupHeading.h_text_2;
          lv5 = obj_cite_number;
          lv6=0; lv7=0;
          p_["lev_markup_number"] =
            DocStructMarkupHeading.h_text_1;
          p_["obj_cite_number"] = lv4;
          break;
        case 6:
          lv = DocStructMarkupHeading.h_text_3;
          lv6 = obj_cite_number;
          lv7=0;
          p_["lev_markup_number"] =
            DocStructMarkupHeading.h_text_2;
          p_["obj_cite_number"] = lv5;
          break;
        case 7:
          lv = DocStructMarkupHeading.h_text_4;
          lv7 = obj_cite_number;
          p_["lev_markup_number"] =
            DocStructMarkupHeading.h_text_3;
          p_["obj_cite_number"] = lv6;
          break;
        default:
          break;
        }
        auto _node = [
          "object" : [
            "is"                         : is_,
            "heading_ptr"                : to!string(ptr_),
            "doc_object_ptr"             : to!string(cntr_),
            "obj_cite_number"            : to!string(obj_cite_number_),
            "segment_anchor_tag"         : to!string(segment_anchor_tag),
            "parent_obj_cite_number"     : to!string(p_["obj_cite_number"]),
            "parent_lev_markup_number"   : to!string(p_["lev_markup_number"]),
          ],
          "heading" : [
            "html_segnames_ptr"          : ((lev_markup_number == "4") ? (to!string(html_segnames_ptr)) : ""),
            "lev_markup_number"          : to!string(lev_markup_number),
            "lev_collapsed_number"       : to!string(lev_collapsed_number),
            // "ancestors"                  : to!string(ancestors),
            // "open_headings_to_close"     : to!string(open_headings_to_close),
          ]
        ];
        debug(node) {
          if (match(lev_markup_number, rgx.levels_numbered_headings)) {
            writeln("* ", to!string(_node));
          }
        }
        debug(nodeheading) {
          if (match(lev_markup_number, rgx.levels_numbered_headings)) {
            writeln("* ", to!string(_node));
          }
        }
        assert(to!int(_node["object"]["parent_lev_markup_number"]) <= 7);
        assert(to!int(_node["object"]["parent_obj_cite_number"]) >= 0);
        if (match(lev_markup_number, rgx.levels_numbered_headings)) {
          assert(to!int(_node["heading"]["lev_markup_number"]) <= 7);
          assert(to!int(_node["object"]["obj_cite_number"]) >= 0);
          if (to!int(_node["object"]["parent_lev_markup_number"]) > 0) {
            assert(to!int(_node["object"]["parent_lev_markup_number"]) < to!int(_node["heading"]["lev_markup_number"]));
            if (to!int(_node["object"]["obj_cite_number"]) != 0) {
              assert(to!int(_node["object"]["parent_obj_cite_number"]) < to!int(_node["object"]["obj_cite_number"]));
            }
          }
          if (to!int(_node["heading"]["lev_markup_number"]) == 0) {
            assert(to!int(_node["object"]["parent_lev_markup_number"]) == DocStructMarkupHeading.h_sect_A);
          } else if  (to!int(_node["heading"]["lev_markup_number"]) == DocStructMarkupHeading.h_sect_B) {
            assert(to!int(_node["object"]["parent_lev_markup_number"]) == DocStructMarkupHeading.h_sect_A);
          } else if  (to!int(_node["heading"]["lev_markup_number"]) == DocStructMarkupHeading.h_sect_C) {
            assert(to!int(_node["object"]["parent_lev_markup_number"]) == DocStructMarkupHeading.h_sect_B);
          } else if  (to!int(_node["heading"]["lev_markup_number"]) == DocStructMarkupHeading.h_sect_D) {
            assert(to!int(_node["object"]["parent_lev_markup_number"]) == DocStructMarkupHeading.h_sect_C);
          } else if  (to!int(_node["heading"]["lev_markup_number"]) == DocStructMarkupHeading.h_text_1) {
            assert(to!int(_node["object"]["parent_lev_markup_number"]) <= DocStructMarkupHeading.h_sect_D);
          } else if  (to!int(_node["heading"]["lev_markup_number"]) == DocStructMarkupHeading.h_text_2) {
            assert(to!int(_node["object"]["parent_lev_markup_number"]) == DocStructMarkupHeading.h_text_1);
          } else if  (to!int(_node["heading"]["lev_markup_number"]) == DocStructMarkupHeading.h_text_3) {
            assert(to!int(_node["object"]["parent_lev_markup_number"]) == DocStructMarkupHeading.h_text_2);
          } else if  (to!int(_node["heading"]["lev_markup_number"]) == DocStructMarkupHeading.h_text_4) {
            assert(to!int(_node["object"]["parent_lev_markup_number"]) == DocStructMarkupHeading.h_text_3);
          } else if  (to!int(_node["heading"]["lev_markup_number"]) == DocStructMarkupHeading.h_text_5) {
          }
        }
        return _node;
      }
      invariant() {
      }
    }
    /+ abstraction functions emitters ↑ +/
    /+ ↓ abstraction functions assertions +/
    auto assertions_doc_structure(
      string[string] an_object,
      int[string] lv
    ) {
      if (lv["h3"] > State.off) {
        assert(lv["h0"] > State.off);
        assert(lv["h1"] > State.off);
        assert(lv["h2"] > State.off);
      } else if (lv["h2"] > State.off) {
        assert(lv["h0"] > State.off);
        assert(lv["h1"] > State.off);
        assert(lv["h3"] == State.off);
      } else if (lv["h1"] > State.off) {
        assert(lv["h0"] > State.off);
        assert(lv["h2"] == State.off);
        assert(lv["h3"] == State.off);
      } else if (lv["h0"] > State.off) {
        assert(lv["h1"] == State.off);
        assert(lv["h2"] == State.off);
        assert(lv["h3"] == State.off);
      } else {
        assert(lv["h0"] == State.off);
        assert(lv["h1"] == State.off);
        assert(lv["h2"] == State.off);
        assert(lv["h3"] == State.off);
      }
      if (lv["h7"] > State.off) {
        assert(lv["h4"] > State.off);
        assert(lv["h5"] > State.off);
        assert(lv["h6"] > State.off);
      } else if (lv["h6"] > State.off) {
        assert(lv["h4"] > State.off);
        assert(lv["h5"] > State.off);
        assert(lv["h7"] == State.off);
      } else if (lv["h5"] > State.off) {
        assert(lv["h4"] > State.off);
        assert(lv["h6"] == State.off);
        assert(lv["h7"] == State.off);
      } else if (lv["h4"] > State.off) {
        assert(lv["h5"] == State.off);
        assert(lv["h6"] == State.off);
        assert(lv["h7"] == State.off);
      } else {
        assert(lv["h4"] == State.off);
        assert(lv["h5"] == State.off);
        assert(lv["h6"] == State.off);
        assert(lv["h7"] == State.off);
      }
      if (lv["h0"] == State.off) {
        assert(lv["h1"] == State.off);
        assert(lv["h2"] == State.off);
        assert(lv["h3"] == State.off);
        assert(lv["h4"] == State.off);
        assert(lv["h5"] == State.off);
        assert(lv["h6"] == State.off);
        assert(lv["h7"] == State.off);
      }
      if (lv["h1"] == State.off) {
        assert(lv["h2"] == State.off);
        assert(lv["h3"] == State.off);
      }
      if (lv["h2"] == State.off) {
        assert(lv["h3"] == State.off);
      }
      if (lv["h3"] == State.off) {
      }
      if (lv["h4"] == State.off) {
        assert(lv["h5"] == State.off);
        assert(lv["h6"] == State.off);
        assert(lv["h7"] == State.off);
      }
      if (lv["h5"] == State.off) {
        assert(lv["h6"] == State.off);
        assert(lv["h7"] == State.off);
      }
      if (lv["h6"] == State.off) {
        assert(lv["h7"] == State.off);
      }
      if (lv["h7"] == State.off) {
      }
      switch (to!string(an_object["lev"])) {
      case "A":
        if (lv["h0"] == State.off) {
          assert(lv["h1"] == State.off);
          assert(lv["h2"] == State.off);
          assert(lv["h3"] == State.off);
          assert(lv["h4"] == State.off);
          assert(lv["h5"] == State.off);
          assert(lv["h6"] == State.off);
          assert(lv["h7"] == State.off);
        } else {                       // (lv["h0"] > State.off)
          assert(lv["h0"] == State.off,"error should not enter level A a second time");
        }
        break;
      case "B":
        if (lv["h1"] == State.off) {
          assert(lv["h0"] > State.off);
          assert(lv["h2"] == State.off);
          assert(lv["h3"] == State.off);
        } else {                       // (lv["h1"] > State.off)
          assert(lv["h0"] > State.off);
          assert(lv["h1"] > State.off);
        }
        break;
      case "C":
        if (lv["h2"] == State.off) {
          assert(lv["h0"] > State.off);
          assert(lv["h1"] > State.off);
          assert(lv["h3"] == State.off);
        } else {                       // (lv["h2"] > State.off)
          assert(lv["h0"] > State.off);
          assert(lv["h1"] > State.off);
          assert(lv["h2"] > State.off);
        }
        break;
      case "D":
        if (lv["h3"] == State.off) {
          assert(lv["h0"] > State.off);
          assert(lv["h1"] > State.off);
          assert(lv["h2"] > State.off);
        } else {                      // (lv["h3"] > State.off)
          assert(lv["h0"] > State.off);
          assert(lv["h1"] > State.off);
          assert(lv["h2"] > State.off);
          assert(lv["h3"] > State.off);
        }
        break;
      case "1":
        if (lv["h4"] == State.off) {
          assert(lv["h0"] > State.off);
        } else {                      // (lv["h4"] > State.off)
          assert(lv["h0"] > State.off);
          assert(lv["h4"] > State.off);
        }
        break;
      case "2":
        if (lv["h5"] == State.off) {
          assert(lv["h0"] > State.off);
          assert(lv["h4"] > State.off);
        } else {                      // (lv["h5"] > State.off)
          assert(lv["h0"] > State.off);
          assert(lv["h4"] > State.off);
          assert(lv["h5"] > State.off);
        }
        break;
      case "3":
        if (lv["h6"] == State.off) {
          assert(lv["h0"] > State.off);
          assert(lv["h4"] > State.off);
          assert(lv["h5"] > State.off);
        } else {                      // (lv["h6"] > State.off)
          assert(lv["h0"] > State.off);
          assert(lv["h4"] > State.off);
          assert(lv["h5"] > State.off);
          assert(lv["h6"] > State.off);
        }
        break;
      case "4":
        if (lv["h7"] == State.off) {
          assert(lv["h0"] > State.off);
          assert(lv["h4"] > State.off);
          assert(lv["h5"] > State.off);
          assert(lv["h6"] > State.off);
        } else {                      // (lv["h7"] > State.off)
          assert(lv["h0"] > State.off);
          assert(lv["h4"] > State.off);
          assert(lv["h5"] > State.off);
          assert(lv["h6"] > State.off);
          assert(lv["h7"] > State.off);
        }
        break;
      default:
        break;
      }
    }
    auto assertions_flag_types_block_status_none_or_closed(int[string] type) {
      assert(
        (type["code"] == TriState.off)
        || (type["code"] == TriState.closing),
        "code block status: off or closing");
      assert(
        (type["poem"] == TriState.off)
        || (type["poem"] == TriState.closing),
        "poem status: off or closing");
      assert(
        (type["table"] == TriState.off)
        || (type["table"] == TriState.closing),
        "table status: off or closing");
      assert(
        (type["group"] == TriState.off)
        || (type["group"] == TriState.closing),
        "group block status: off or closing");
      assert(
        (type["block"] == TriState.off)
        || (type["block"] == TriState.closing),
        "block status: off or closing");
    }
    /+ abstraction functions assertions ↑ +/
  } /+ ← closed: struct Abstraction +/
} /+ ← closed: template SiSUdocAbstraction +/