From 0079c34ce7a524d4b93ed56191b5e7cf6a380975 Mon Sep 17 00:00:00 2001
From: Ralph Amissah <ralph@amissah.com>
Date: Tue, 1 Nov 2016 10:06:47 -0400
Subject: 0.8.0 the document parts (& org babel tangle)

---
 org/ao_abstract_doc_source.org     | 849 ++++++++++++++++++++++++++-----------
 org/ao_conf_make_meta.org          |  29 +-
 org/ao_defaults.org                |  23 +-
 org/ao_output_debugs.org           |   5 +-
 org/ao_read_source_files.org       |   4 +-
 org/output.org                     | 114 ++---
 org/sdp.org                        |  26 +-
 src/sdp.d                          |  24 +-
 src/sdp/ao_abstract_doc_source.d   | 524 ++++++++++++++++++-----
 src/sdp/ao_conf_make_meta_native.d |   2 +-
 src/sdp/ao_conf_make_meta_sdlang.d |  27 +-
 src/sdp/ao_defaults.d              |   3 +-
 src/sdp/ao_object_setter.d         |   4 +-
 src/sdp/ao_output_debugs.d         |   5 +-
 src/sdp/ao_read_source_files.d     |   2 +-
 src/sdp/ao_rgx.d                   |  20 +-
 src/sdp/output_html.d              |  90 ++--
 src/sdp/output_hub.d               |  20 +-
 views/version.txt                  |   2 +-
 19 files changed, 1275 insertions(+), 498 deletions(-)

diff --git a/org/ao_abstract_doc_source.org b/org/ao_abstract_doc_source.org
index 7aa8a0a..0efc339 100644
--- a/org/ao_abstract_doc_source.org
+++ b/org/ao_abstract_doc_source.org
@@ -44,7 +44,10 @@ mixin InternalMarkup;
 #+BEGIN_SRC d
 /+ initialize +/
 auto rgx = Rgx();
-ObjComposite[] contents_the_objects;
+ObjComposite[] the_document_head_section;
+ObjComposite[][string] the_table_of_contents_section;
+ObjComposite[] the_document_body_section;
+ObjComposite[] the_bibliography_section;
 string[string] an_object, processing;
 string[] anchor_tags;
 string segment_object_belongs_to;
@@ -109,7 +112,10 @@ scope(success) {
 scope(failure) {
 }
 scope(exit) {
-  destroy(contents_the_objects);
+  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);
@@ -226,21 +232,13 @@ if (!line.empty) {
 
 #+name: abs_in_loop_body_00_code_block
 #+BEGIN_SRC d
-if (type["code"] == TriState.on) {
-  /+ block object: code +/
-  _code_block_(line, an_object, type);
-  continue;
+/+ block object: code +/
+_code_block_(line, an_object, type);
+continue;
 #+END_SRC
 
 **** non code objects (other blocks or regular text) [+4]          :non_code:
 
-#+name: abs_in_loop_body_00_non_code_block
-#+BEGIN_SRC d
-} else if (!matchFirst(line, rgx.skip_from_regular_parse)) {
-  /+ object other than "code block" object
-     (includes regular text paragraph, headings & blocks other than code) +/
-#+END_SRC
-
 ***** within block group [+1]                                  :block:active:
 ****** within block group: biblio                                    :biblio:
 
@@ -312,15 +310,9 @@ if ((matchFirst(line, rgx.heading_biblio)
 
 ***** not identified as being within block group (could still be, or not) [+3]
 
-#+name: abs_in_loop_body_non_code_obj
-#+BEGIN_SRC d
-} else {
-  /+ not within a block group +/
-#+END_SRC
-
 ****** assert
 
-#+name: abs_in_loop_body_open_block_obj
+#+name: abs_in_loop_body_open_block_obj_assert
 #+BEGIN_SRC d
 assert(
   (type["blocks"] == TriState.off)
@@ -334,170 +326,170 @@ assertions_flag_types_block_status_none_or_closed(type);
 
 #+name: abs_in_loop_body_open_block_obj
 #+BEGIN_SRC d
-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;
+if (matchFirst(line, (rgx.block_poem_open))) {
+  /+ poem to verse exceptions! +/
+  object_reset(an_object);
+  processing.remove("verse");
+  obj_cite_number_poem["start"] = to!string(obj_cite_number);
+}
+_start_block_(line, type, obj_cite_number_poem);
+continue;
 #+END_SRC
 
 ****** line not empty [+2]
-
-#+name: abs_in_loop_body_not_block_obj
-#+BEGIN_SRC d
-} else if (!line.empty) {
-  /+ line not empty +/
-  /+ non blocks (headings, paragraphs) & closed blocks +/
-#+END_SRC
-
 ******* asserts                                                      :assert:
 
 #+name: abs_in_loop_body_not_block_obj
 #+BEGIN_SRC d
+assert(
+  !line.empty,
+  "line tested, line not empty surely"
+);
+assert(
+  (type["blocks"] == TriState.off)
+  || (type["blocks"] == TriState.closing),
+  "code block status: none or closed"
+);
+if (type["blocks"] == TriState.closing) {
+  // blocks closed, unless followed by book index
+  debug(check) {                           // block
+    writeln(__LINE__);
+    writeln(line);
+  }
   assert(
-    !line.empty,
-    "line tested, line not empty surely"
-  );
-  assert(
-    (type["blocks"] == TriState.off)
-    || (type["blocks"] == TriState.closing),
-    "code block status: none or closed"
+    matchFirst(line, rgx.book_index)
+    || matchFirst(line, rgx.book_index_open)
+    || type["book_index"] == State.on
   );
-  if (type["blocks"] == TriState.closing) {
-    // blocks closed, unless followed by book index
-    debug(check) {                           // block
-      writeln(__LINE__);
-      writeln(line);
-    }
-    assert(
-      matchFirst(line, rgx.book_index)
-      || matchFirst(line, rgx.book_index_open)
-      || type["book_index"] == State.on
-    );
-  }
+}
 #+END_SRC
 
 ******* book index                                                :bookindex:
 
 #+name: abs_in_loop_body_not_block_obj
 #+BEGIN_SRC d
-  if ((matchFirst(line, rgx.book_index))
-  || (matchFirst(line, rgx.book_index_open))
-  || (type["book_index"] == State.on ))  {
-    /+ book_index +/
-    _book_index_(line, book_idx_tmp, an_object, type);
+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);
 #+END_SRC
 
 ******* not book index [+1]
 
 #+name: abs_in_loop_body_not_block_obj
 #+BEGIN_SRC d
-  } else {
-    /+ not book_index +/
+} else {
+  /+ not book_index +/
 #+END_SRC
 
 ******** matched: comment                                     :comment:match:
 
 #+name: abs_in_loop_body_not_block_obj
 #+BEGIN_SRC d
-    if (auto m = matchFirst(line, rgx.comment)) {
-      /+ matched comment +/
-      debug(comment) {
-        writeln(line);
-      }
-      an_object["obj"] ~= line ~= "\n";
-      contents_the_objects ~=
-        set_abstract_object.contents_comment(strip(an_object["obj"]));
-      _header_set_common_(line_occur, an_object, type);
-      processing.remove("verse");
-      ++counter;
+  if (auto m = matchFirst(line, rgx.comment)) {
+    /+ matched comment +/
+    debug(comment) {
+      writeln(line);
+    }
+    an_object["obj"] ~= line ~= "\n";
+    the_document_body_section ~=
+      set_abstract_object.contents_comment(strip(an_object["obj"]));
+    _common_reset_(line_occur, an_object, type);
+    processing.remove("verse");
+    ++counter;
 #+END_SRC
 
 ******** flag not set & line not exist: heading or para   :heading:paragraph:
 
 #+name: abs_in_loop_body_not_block_obj
 #+BEGIN_SRC d
-    } else if (((line_occur["para"] == State.off)
+  } 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 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);
-      }
-      if (matchFirst(line, rgx.heading)) {
-        /+ heading match +/
-        _heading_matched_(line, line_occur, an_object, lv, collapsed_lev, type, dochead_meta_aa);
-      } else if (line_occur["para"] == State.off) {
-        /+ para match +/
-        _para_match_(line, an_object, indent, bullet, type, line_occur);
-      }
+      /+ 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, lv, collapsed_lev, type, dochead_meta_aa);
+    } else if (line_occur["para"] == State.off) {
+      /+ para match +/
+      _para_match_(line, an_object, indent, bullet, type, line_occur);
+    }
 #+END_SRC
 
 ******** line exist: heading                                        :heading:
 
 #+name: abs_in_loop_body_not_block_obj
 #+BEGIN_SRC d
-    } else if (line_occur["heading"] > State.off) {
-      /+ heading +/
-      debug(heading) {                         // heading
-        writeln(line);
-      }
-      an_object["obj"] ~= line ~= "\n";
-      ++line_occur["heading"];
+  } else if (line_occur["heading"] > State.off) {
+    /+ heading +/
+    debug(heading) {                         // heading
+      writeln(line);
+    }
+    an_object["obj"] ~= line ~= "\n";
+    ++line_occur["heading"];
 #+END_SRC
 
 ******** line exist: para                                              :para:
 
 #+name: abs_in_loop_body_not_block_obj
 #+BEGIN_SRC d
-    } else if (line_occur["para"] > State.off) {
-      /+ paragraph +/
-      debug(para) {
-        writeln(line);
-      }
-      an_object["obj"] ~= line;
-      ++line_occur["para"];
+  } else if (line_occur["para"] > State.off) {
+    /+ paragraph +/
+    debug(para) {
+      writeln(line);
     }
+    an_object["obj"] ~= line;
+    ++line_occur["para"];
   }
+}
 #+END_SRC
 
 ****** line empty, with block flag
 
-#+name: abs_in_loop_body_not_block_obj
+#+name: abs_in_loop_body_not_block_obj_line_empty_blocks_flags
 #+BEGIN_SRC d
-} else if (type["blocks"] == TriState.closing) {
-  /+ line empty, with blocks flag +/
-  _block_flag_line_empty_(line, an_object, contents_the_objects, bookindex_unordered_hashes, obj_cite_number, _node, counter, type, obj_cite_number_poem, dochead_make_aa); // watch
+_block_flag_line_empty_(
+  line,
+  an_object,
+  the_document_body_section,
+  bookindex_unordered_hashes,
+  obj_cite_number,
+  _node,
+  counter,
+  type,
+  obj_cite_number_poem,
+  dochead_make_aa
+); // watch
 #+END_SRC
 
 ****** line empty [+1]
 
-#+name: abs_in_loop_body_not_block_obj
-#+BEGIN_SRC d
-} else {
-  /+ line empty +/
-#+END_SRC
-
 ******* assert line empty                                            :assert:
 
 #+name: abs_in_loop_body_not_block_obj_line_empty
 #+BEGIN_SRC d
-/+ line.empty, post contents, empty variables: +/
 assert(
   line.empty,
   "line should be empty"
@@ -530,6 +522,13 @@ if ((type["heading"] == State.on)
   } else if (to!int(an_object["lev_markup_number"]) < 4) {
     segment_object_belongs_to = "";
   }
+  the_table_of_contents_section = obj_im.table_of_contents_gather_headings(
+    an_object,
+    dochead_make_aa,
+    segment_object_belongs_to,
+    obj_cite_number,
+    the_table_of_contents_section,
+  );
   _node =
     node_construct.node_emitter_heading(
       an_object["lev_markup_number"],
@@ -547,7 +546,7 @@ if ((type["heading"] == State.on)
     writeln(an_object["lev_markup_number"]);
     writeln(segment_object_belongs_to);
   }
-  contents_the_objects ~=
+  the_document_body_section ~=
     set_abstract_object.contents_heading(
       an_object["substantive"],
       an_object["attrib"],
@@ -564,7 +563,7 @@ if ((type["heading"] == State.on)
     // writeln(contents_am[counter]["obj_cite_number"], " ", contents_am[counter]["obj"]);
     // writeln(m.hit, "\n");
   }
-  _header_set_common_(line_occur, an_object, type);
+  _common_reset_(line_occur, an_object, type);
   an_object.remove("lev");
   an_object.remove("lev_markup_number");
   // an_object["lev_markup_number"]="9";
@@ -599,7 +598,7 @@ if ((type["heading"] == State.on)
   anchor_tags = substantive_object_and_anchor_tags_tuple[1];
   an_object["attrib"] =
     obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-  contents_the_objects ~=
+  the_document_body_section ~=
     set_abstract_object.contents_para(
       an_object["is"],
       an_object["substantive"],
@@ -608,16 +607,11 @@ if ((type["heading"] == State.on)
       indent,
       bullet
     );
-  // contents_the_objects ~=
-  //   set_abstract_object.contents_para(
-  //     an_object,
-  //     obj_cite_number,
-  //     indent,
-  //     bullet
-  //   );
-  _header_set_common_(line_occur, an_object, type);
-  indent["hang_position"] = "0";
-  indent["base_position"] = "0";
+  _common_reset_(line_occur, an_object, type);
+  indent=[
+    "hang_position" : "0",
+    "base_position" : "0",
+  ];
   bullet = false;
   processing.remove("verse");
   ++counter;
@@ -632,29 +626,22 @@ if ((type["heading"] == State.on)
 
 *** close non code objects (regular text)
 
-#+name: abs_in_loop_body_00_closed
-#+BEGIN_SRC d
-    } // close else for line empty
-  } // close else for not the above
-} // close after non code, other blocks or regular text
-#+END_SRC
-
 *** regular text objects                                     :text:paragraph:
 
 #+name: abs_in_loop_body_01
 #+BEGIN_SRC d
-/+ unless (contents_the_objects.length == 0) ? +/
-if (contents_the_objects.length > 0) {
-  if (((contents_the_objects[$-1].is_a == "para")
-  || (contents_the_objects[$-1].is_a == "heading"))
+/+ 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"))
   && (counter-1 > previous_count)) {
-    if (match(contents_the_objects[$-1].object,
+    if (match(the_document_body_section[$-1].object,
     rgx.inline_notes_delimiter_al_regular_number_note)) {
-      previous_count=contents_the_objects.length -1;
+      previous_count=the_document_body_section.length -1;
       note_section.gather_notes_for_endnote_section(
-        contents_the_objects,
+        the_document_body_section,
         segment_object_belongs_to,
-        contents_the_objects.length -1
+        the_document_body_section.length -1
       );
     }
   }
@@ -680,28 +667,71 @@ debug(objectrelated2) { // check
 // obj_im.obj_inline_markup_and_anchor_tags("doc_end_reset", "", dochead_make_aa);
 #+END_SRC
 
-*** [#B] endnotes                                                  :endnotes:
+*** document sections
+**** DONE [#B] toc, table of contents section (scroll & seg)       :contents:
+
+#+name: abs_post
+#+BEGIN_SRC d
+debug(toc) {
+  writefln(
+    "%s %s",
+    __LINE__,
+    the_table_of_contents_section["seg"].length
+  );
+  foreach (toc_linked_heading; the_table_of_contents_section["seg"]) {
+    writeln(toc_linked_heading.object);
+  }
+}
+#+END_SRC
+
+**** DONE endnotes section (scroll & seg)                          :endnotes:
 
 #+name: abs_post
 #+BEGIN_SRC d
 auto en_tuple =
   note_section.endnote_objects(obj_cite_number);
 static assert(!isTypeTuple!(en_tuple));
-auto endnotes_section = en_tuple[0];
+auto the_endnotes_section = en_tuple[0];
 obj_cite_number = en_tuple[1];
 debug(endnotes) {
   writefln(
     "%s %s",
     __LINE__,
-    endnotes_section.length
+    the_endnotes_section["seg"].length
   );
-  foreach (n; endnotes_section) {
-    writeln(n);
+  foreach (o; the_endnotes_section["seg"]) {
+    writeln(o);
   }
 }
 #+END_SRC
 
-*** [#B] bibliography                                          :bibliography:
+**** glossary section?
+
+**** TODO [#B] bibliography section (objects)                  :bibliography:
+
+#+name: abs_post
+#+BEGIN_SRC d
+the_bibliography_section ~=
+  set_abstract_object.contents_heading(
+    "Bibliography",   // nugget/object
+    "",               // attrib
+    0,                // obj_cite_number
+    [""],             // anchor tag
+    "B",              // lev
+    1,                // lev_markup_number
+    1,                // lev_collapsed_number
+  );
+the_bibliography_section ~=
+  set_abstract_object.contents_heading(
+    "Bibliography",   // nugget/object
+    "",               // attrib
+    0,                // obj_cite_number
+    ["bibliography"], // anchor tag
+    "1",              // lev
+    4,                // lev_markup_number
+    2,                // lev_collapsed_number
+  );
+#+END_SRC
 
 #+name: abs_post
 #+BEGIN_SRC d
@@ -712,51 +742,126 @@ auto biblio_ordered =
   biblio._bibliography_(biblio_unsorted_incomplete, bib_arr_json);
 #+END_SRC
 
-*** [#B] bookindex                                               :book:index:
+***** format biblio string
+
+#+name: abs_post
+#+BEGIN_SRC d
+string out_;
+foreach (entry; biblio_ordered) {
+  out_ = format(
+    "%s \"%s\"%s%s%s%s%s%s%s%s%s.",
+    ((entry["author"].str.empty) ? entry["editor"].str : entry["author"].str),
+    entry["fulltitle"].str,
+    ((entry["journal"].str.empty) ? "" : ", /{" ~ entry["journal"].str ~ "}/"),
+    ((entry["volume"].str.empty) ? "" : ", " ~ entry["volume"].str),
+    ((entry["in"].str.empty) ? "" : ", " ~ entry["in"].str),
+    ((!(entry["author"].str.empty) && (!(entry["editor"].str.empty))) ? entry["editor"].str : ""),
+    ", " ~ entry["year"].str,
+    ((entry["pages"].str.empty) ? "" : ", " ~ entry["pages"].str),
+    ((entry["publisher"].str.empty) ? "" : ", " ~ entry["publisher"].str),
+    ((entry["place"].str.empty) ? "" : ", " ~ entry["place"].str),
+    ((entry["url"].str.empty) ? "" : ", [" ~ entry["url"].str ~ "]"),
+  );
+  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
+    );
+}
+#+END_SRC
+
+#+name: abs_post
+#+BEGIN_SRC d
+debug(bibliosection) {
+  foreach (o; the_bibliography_section) {
+    writeln(o.object);
+  }
+}
+#+END_SRC
+
+***** bibliography components
+
+auto biblio_entry_tags_jsonstr =  `{
+  "is"                   : "",
+  "sortby_deemed_author_year_title"  : "",
+  "deemed_author"                    : "",
+  "author_raw"                       : "",
+  "author"                           : "",
+  "author_arr"                       : [ "" ],
+  "editor_raw"                       : "",
+  "editor"                           : "",
+  "editor_arr"                       : [ "" ],
+  "title"                            : "",
+  "subtitle"                         : "",
+  "fulltitle"                        : "",
+  "language"                         : "",
+  "trans"                            : "",
+  "src"                              : "",
+  "journal"                          : "",
+  "in"                               : "",
+  "volume"                           : "",
+  "edition"                          : "",
+  "year"                             : "",
+  "place"                            : "",
+  "publisher"                        : "",
+  "url"                              : "",
+  "pages"                            : "",
+  "note"                             : "",
+  "short_name"                       : "",
+  "id"                               : ""
+}`; // is: book, article, magazine, newspaper, blog, other
+
+**** DONE [#B] bookindex section (scroll & seg)                  :book:index:
 
 #+name: abs_post
 #+BEGIN_SRC d
 auto bi = BookIndexReportSection();
 auto bi_tuple =
-  bi.bookindex_build_section(bookindex_unordered_hashes, obj_cite_number, segment_object_belongs_to);
+  bi.bookindex_build_section(
+    bookindex_unordered_hashes,
+    obj_cite_number,
+    segment_object_belongs_to
+  );
 static assert(!isTypeTuple!(bi_tuple));
-auto bookindex_section = bi_tuple[0];
+auto the_bookindex_section = bi_tuple[0];
 obj_cite_number = bi_tuple[1];
 debug(bookindex) {                         // bookindex
-  foreach (bi_entry; bookindex_section) {
+  foreach (bi_entry; the_bookindex_section["seg"]) {
     writeln(bi_entry);
   }
 }
 #+END_SRC
 
-*** [#B] document                                                  :document:
+*** [#B] the document                                              :document:
 
 #+name: abs_post
 #+BEGIN_SRC d
-auto document_the =
-  contents_the_objects ~ endnotes_section ~ bookindex_section;
+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, // TODO
+  "bibliography":    the_bibliography_section,
+  "bookindex_scroll": the_bookindex_section["scroll"],
+  "bookindex_seg":    the_bookindex_section["seg"],
+];
 #+END_SRC
 
 *** misc heading
 
 #+name: abs_post
-destroy(contents_the_objects);
-destroy(endnotes_section);
-destroy(bookindex_section);
-// struct Document {
-//   char content;
-//   char head_make;
-//   char head_meta;
-//   char bookindex_section;
-//   char biblio;
-// }
-// struct Document {
-//   char content;
-//   char head_make;
-//   char head_meta;
-//   char bookindex_section;
-//   char biblio;
-// }
+destroy(the_document_body_section);
+destroy(the_endnotes_section);
+destroy(the_bookindex_section);
 #+END_SRC
 
 *** [#A] return document tuple                                 :return:tuple:
@@ -793,12 +898,11 @@ auto object_reset(ref string[string] an_object) {
 
 #+name: abs_functions_header_set_common
 #+BEGIN_SRC d
-auto _header_set_common_(
+auto _common_reset_(
   ref int[string] line_occur,
   ref string[string] an_object,
   ref int[string] type
 ) {
-  // line_occur["header"] = State.off;
   line_occur["heading"] = State.off;
   line_occur["para"]= State.off;
   type["heading"] = State.off;
@@ -1331,7 +1435,7 @@ void _poem_block_(
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         an_object["attrib"] =
           obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-        contents_the_objects ~=
+        the_document_body_section ~=
           set_abstract_object.contents_block(
             an_object["is"],
             an_object["substantive"],
@@ -1353,7 +1457,7 @@ void _poem_block_(
         obj_cite_number =
           obj_cite_number_emit(type["obj_cite_number_status"]);
         type["verse_new"] = State.off;
-      } else if (matchFirst(line, rgx.line_delimiter_only)) {
+      } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) {
         verse_line = TriState.off;
         type["verse_new"] = State.on;
       }
@@ -1383,7 +1487,7 @@ void _poem_block_(
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         an_object["attrib"] =
           obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-        contents_the_objects ~=
+        the_document_body_section ~=
           set_abstract_object.contents_block(
             an_object["is"],
             an_object["substantive"],
@@ -1420,7 +1524,7 @@ void _poem_block_(
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         an_object["attrib"] =
           obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-        contents_the_objects ~=
+        the_document_body_section ~=
           set_abstract_object.contents_block(
             an_object["is"],
             an_object["substantive"],
@@ -1441,7 +1545,7 @@ void _poem_block_(
         obj_cite_number =
           obj_cite_number_emit(type["obj_cite_number_status"]);
         type["verse_new"] = State.off;
-      } else if (matchFirst(line, rgx.line_delimiter_only)) {
+      } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) {
         type["verse_new"] = State.on;
         verse_line = TriState.off;
       }
@@ -1472,7 +1576,7 @@ void _poem_block_(
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         an_object["attrib"] =
           obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-        contents_the_objects ~=
+        the_document_body_section ~=
           set_abstract_object.contents_block(
             an_object["is"],
             an_object["substantive"],
@@ -1659,7 +1763,7 @@ void _table_block_(
 void _block_flag_line_empty_(
   char[] line,
   ref string[string] an_object,
-  ref ObjComposite[] contents_the_objects,
+  ref ObjComposite[] the_document_body_section,
   ref string[][string][string] bookindex_unordered_hashes,
   ref int obj_cite_number,
   ref string _node,
@@ -1701,7 +1805,7 @@ void _block_flag_line_empty_(
     anchor_tags = substantive_object_and_anchor_tags_tuple[1];
     an_object["attrib"] =
       obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-    contents_the_objects ~=
+    the_document_body_section ~=
       set_abstract_object.contents_block_code(
         an_object["is"],
         an_object["substantive"],
@@ -1730,7 +1834,7 @@ void _block_flag_line_empty_(
         an_object["is"]
         // "verse"
       );
-    contents_the_objects ~=
+    the_document_body_section ~=
       set_abstract_object.contents_block_obj_cite_number_string(
         "poem",
         "",
@@ -1765,7 +1869,7 @@ void _block_flag_line_empty_(
     anchor_tags = substantive_object_and_anchor_tags_tuple[1];
     an_object["attrib"] =
       obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-    contents_the_objects ~=
+    the_document_body_section ~=
       set_abstract_object.contents_block(
         an_object["is"],
         an_object["substantive"],
@@ -1800,7 +1904,7 @@ void _block_flag_line_empty_(
     anchor_tags = substantive_object_and_anchor_tags_tuple[1];
     an_object["attrib"] =
       obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-    contents_the_objects ~=
+    the_document_body_section ~=
       set_abstract_object.contents_block(
         an_object["is"],
         an_object["substantive"],
@@ -1834,7 +1938,7 @@ void _block_flag_line_empty_(
     anchor_tags = substantive_object_and_anchor_tags_tuple[1];
     an_object["attrib"] =
       obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-    contents_the_objects ~=
+    the_document_body_section ~=
       set_abstract_object.contents_block(
         an_object["is"],
         an_object["substantive"],
@@ -1869,7 +1973,7 @@ void _block_flag_line_empty_(
     anchor_tags = substantive_object_and_anchor_tags_tuple[1];
     an_object["attrib"] =
       obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-    contents_the_objects ~=
+    the_document_body_section ~=
       set_abstract_object.contents_block(
         an_object["is"],
         an_object["substantive"],
@@ -2114,8 +2218,10 @@ auto _heading_matched_(
     assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels
     switch (an_object["lev"]) {
     case "A":
-      an_object["obj"]=replaceFirst(an_object["obj"], rgx.variable_doc_title, dochead_meta_aa["title"]["main"]);
-      an_object["obj"]=replaceFirst(an_object["obj"], rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]);
+      an_object["obj"]=replaceFirst(an_object["obj"],
+        rgx.variable_doc_title, (dochead_meta_aa["title"]["full"] ~ ","));
+      an_object["obj"]=replaceFirst(an_object["obj"],
+        rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]);
       collapsed_lev["h0"] = 1;
       an_object["lev_collapsed_number"] =
         to!string(collapsed_lev["h0"]);
@@ -2265,8 +2371,10 @@ auto _para_match_(
       }
       type["para"] = State.on;
       an_object["obj"] ~= line;
-      indent["hang_position"] = "0";
-      indent["base_position"] = "0";
+      indent=[
+        "hang_position" : "0",
+        "base_position" : "0",
+      ];
       bullet = true;
     } else if (auto m = matchFirst(line, rgx.para_indent_hang)) {
       debug(paraindenthang) {                // para indent hang
@@ -2274,8 +2382,10 @@ auto _para_match_(
       }
       type["para"] = State.on;
       an_object["obj"] ~= line;
-      indent["hang_position"] = to!string(m.captures[1]);
-      indent["base_position"] = to!string(m.captures[2]);
+      indent=[
+        "hang_position" : to!string(m.captures[1]),
+        "base_position" : to!string(m.captures[2]),
+      ];
       bullet = false;
     } else if (auto m = matchFirst(line, rgx.para_bullet_indent)) {
       debug(parabulletindent) {              // para bullet indent
@@ -2283,15 +2393,19 @@ auto _para_match_(
       }
       type["para"] = State.on;
       an_object["obj"] ~= line;
-      indent["hang_position"] = to!string(m.captures[1]);
-      indent["base_position"] = "0";
+      indent=[
+        "hang_position" : to!string(m.captures[1]),
+        "base_position" : "0",
+      ];
       bullet = true;
     } else {
       // !line.empty
       type["para"] = State.on;
       an_object["obj"] ~= line;
-      indent["hang_position"] = "0";
-      indent["base_position"] = "0";
+      indent=[
+        "hang_position" : "0",
+        "base_position" : "0",
+      ];
       bullet = false;
     }
     ++line_occur["para"];
@@ -2423,6 +2537,7 @@ struct ObjInlineMarkupMunge {
     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__);
@@ -2527,7 +2642,10 @@ struct ObjInlineMarkup {
 
 #+name: ao_emitters_obj_inline_markup_and_anchor_tags
 #+BEGIN_SRC d
-  auto obj_inline_markup_and_anchor_tags(string[string] obj_, string[string][string] dochead_make_aa)
+  auto obj_inline_markup_and_anchor_tags(
+    string[string] obj_,
+    string[string][string] dochead_make_aa
+  )
   in { }
   body {
     obj_txt["munge"]=obj_["obj"].dup;
@@ -2590,6 +2708,156 @@ struct ObjInlineMarkup {
   }
 #+END_SRC
 
+***** table of contents objects                         :markup:inline:
+
+#+name: ao_emitters_obj_inline_markup_table_of_contents
+#+BEGIN_SRC d
+  auto _clean_heading_toc_(
+    char[] heading_toc_,
+  ) {
+   auto m = matchFirst(cast(char[]) heading_toc_, rgx.heading);
+   heading_toc_ = m.post;
+   return heading_toc_;
+  };
+  auto table_of_contents_gather_headings(
+    string[string] obj_,
+    string[string][string] dochead_make_aa,
+    string segment_object_belongs_to,
+    int obj_cite_number,
+    ObjComposite[][string] the_table_of_contents_section,
+  )
+  in { }
+  body {
+    char[] heading_toc_ = to!(char[])(obj_["obj"].dup.strip);
+    heading_toc_ = _clean_heading_toc_(heading_toc_);
+    auto attrib="";
+    string toc_txt_;
+    string[string] indent;
+    auto set_abstract_object = ObjectAbstractSet();
+    if (to!int(obj_["lev_markup_number"]) > 0) {
+      toc_txt_ = format(
+        "{ %s }#%s",
+        heading_toc_,
+        obj_cite_number,
+      );
+      indent=[
+        "hang_position" : obj_["lev_markup_number"],
+        "base_position" : obj_["lev_markup_number"],
+      ];
+      toc_txt_ = format(
+        "{ %s }#%s",
+        heading_toc_,
+        obj_cite_number,
+      );
+      the_table_of_contents_section["scroll"] ~=
+        set_abstract_object.contents_para(
+          "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_para(
+          "toc",
+          "Table of Contents",
+          "",                   // attrib
+          0,
+          indent,
+          false
+        );
+    }
+    switch (to!int(obj_["lev_markup_number"])) {
+    case 0:
+      indent=[
+        "hang_position" : "0",
+        "base_position" : "0",
+      ];
+      the_table_of_contents_section["seg"] ~=
+        set_abstract_object.contents_para(
+          "toc",
+          "{ Table of Contents }../toc.fn_suffix",
+          "",                   // attrib
+          0,
+          indent,
+          false
+        );
+      break;
+    case 1: .. case 3:
+      indent=[
+        "hang_position" : obj_["lev_markup_number"],
+        "base_position" : obj_["lev_markup_number"],
+      ];
+      toc_txt_ = format(
+        "%s",
+        heading_toc_,
+      );
+      the_table_of_contents_section["seg"] ~=
+        set_abstract_object.contents_para(
+          "toc",
+          toc_txt_,
+          "",                   // attrib
+          0,
+          indent,
+          false
+        );
+      break;
+    case 4:
+      toc_txt_ = format(
+        "{ %s }../%s.fn_suffix",
+        heading_toc_,
+        segment_object_belongs_to,
+      );
+      indent=[
+        "hang_position" : obj_["lev_markup_number"],
+        "base_position" : obj_["lev_markup_number"],
+      ];
+      the_table_of_contents_section["seg"] ~=
+        set_abstract_object.contents_para(
+          "toc",
+          toc_txt_,
+          "",                   // attrib
+          0,
+          indent,
+          false
+        );
+      break;
+    case 5: .. case 7:
+      toc_txt_ = format(
+        "{ %s }../%s.fn_suffix#%s",
+        heading_toc_,
+        segment_object_belongs_to,
+        obj_cite_number,
+      );
+      indent=[
+        "hang_position" : obj_["lev_markup_number"],
+        "base_position" : obj_["lev_markup_number"],
+      ];
+      the_table_of_contents_section["seg"] ~=
+        set_abstract_object.contents_para(
+          "toc",
+          toc_txt_,
+          "",                   // attrib
+          0,
+          indent,
+          false
+        );
+      break;
+    default:
+      break;
+    }
+    return the_table_of_contents_section;
+  }
+  invariant() {
+  }
+#+END_SRC
+
 ***** private:
 
 #+name: ao_emitters_obj_inline_markup_private
@@ -3271,15 +3539,25 @@ struct BookIndexReportSection {
     auto set_abstract_object = ObjectAbstractSet();
     auto mainkeys =
       bookindex_unordered_hashes.byKey.array.sort().release;
-    string bi_tmp;
-    ObjComposite[] bookindex_section;
+    string bi_tmp_seg, bi_tmp_scroll;
+    ObjComposite[][string] bookindex_section;
     // writeln(mainkeys.length);
     // B~ Book Index
     attrib="";
     lev="B";
     lev_markup_number="1";
     lev_collapsed_number="1";
-    bookindex_section ~=
+    bookindex_section["scroll"] ~=
+      set_abstract_object.contents_heading(
+        "Book Index",
+        attrib,
+        obj_cite_number,
+        [],
+        to!string(lev),
+        to!int(lev_markup_number),
+        to!int(lev_collapsed_number)
+      );
+    bookindex_section["seg"] ~=
       set_abstract_object.contents_heading(
         "Book Index",
         attrib,
@@ -3296,7 +3574,17 @@ struct BookIndexReportSection {
     lev="1";
     lev_markup_number="4";
     lev_collapsed_number="2";
-    bookindex_section ~=
+    bookindex_section["scroll"] ~=
+      set_abstract_object.contents_heading(
+        "Index",
+        attrib,
+        obj_cite_number,
+        ["book_index"],
+        to!string(lev),
+        to!int(lev_markup_number),
+        to!int(lev_collapsed_number)
+      );
+    bookindex_section["seg"] ~=
       set_abstract_object.contents_heading(
         "Index",
         attrib,
@@ -3309,35 +3597,43 @@ struct BookIndexReportSection {
     ++obj_cite_number;
     ++mkn;
     foreach (mainkey; mainkeys) {
-      bi_tmp = "!{" ~ mainkey ~ "}! ";
+      bi_tmp_scroll = "!{" ~ mainkey ~ "}! ";
+      bi_tmp_seg = "!{" ~ mainkey ~ "}! ";
       // bi_tmp = "_0_1 !{" ~ mainkey ~ "}! ";
       foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
         auto go = replaceAll(ref_, rgx.book_index_go, "$1");
-        bi_tmp ~= (segment_object_belongs_to.empty)
+        bi_tmp_scroll ~= (" {" ~ ref_ ~ "}#" ~ go ~ ", ");
+        bi_tmp_seg ~= (segment_object_belongs_to.empty)
         ? (" {" ~ ref_ ~ "}#" ~ go ~ ", ")
-        : (" {" ~ ref_ ~ "}[../" ~ segment_object_belongs_to ~ ".fn_suffix]#" ~ go ~ ", ");
+        : (" {" ~ ref_ ~ "}../" ~ segment_object_belongs_to ~ ".fn_suffix#" ~ go ~ ", ");
       }
-      bi_tmp ~= " \\\\\n    ";
+      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 ~= subkey ~ ", ";
+        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 ~= (segment_object_belongs_to.empty)
+          bi_tmp_scroll ~= (" {" ~ ref_ ~ "}#" ~ go ~ ", ");
+          bi_tmp_seg ~= (segment_object_belongs_to.empty)
           ? (" {" ~ ref_ ~ "}#" ~ go ~ ", ")
-          : (" {" ~ ref_ ~ "}[../" ~ segment_object_belongs_to ~ ".fn_suffix]#" ~ go ~ ", ");
+          : (" {" ~ ref_ ~ "}../" ~ segment_object_belongs_to ~ ".fn_suffix#" ~ go ~ ", ");
         }
-        bi_tmp ~= " \\\\\n    ";
+        bi_tmp_scroll ~= " \\\\\n    ";
+        bi_tmp_seg ~= " \\\\\n    ";
         ++skn;
       }
-      bi_tmp = replaceFirst(bi_tmp, rgx.trailing_linebreak, "");
+      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";
-      indent["base_position"] = "1";
-      attrib="";
+      indent=[
+        "hang_position" : "0",
+        "base_position" : "1",
+      ];
       // bookindex_section ~=
       //   set_abstract_object.contents_para(
       //     obj,
@@ -3345,10 +3641,19 @@ struct BookIndexReportSection {
       //     indent,
       //     false
       //   );
-      bookindex_section ~=
+      bookindex_section["scroll"] ~=
         set_abstract_object.contents_para(
           type,
-          bi_tmp,
+          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,
@@ -3374,7 +3679,7 @@ struct BookIndexReportSection {
 #+name: ao_emitters_endnotes
 #+BEGIN_SRC d
 struct NotesSection {
-  string object_notes;
+  string[string] object_notes;
   long previous_count;
   int mkn;
   auto rgx = Rgx();
@@ -3408,15 +3713,22 @@ struct NotesSection {
     rgx.inline_notes_delimiter_al_regular_number_note)) {
       debug(endnotes_build) {
         writeln(
-          "{^{", m.captures[1], ".}^}[../", segment_object_belongs_to, ".fn_suffix]#noteref_\n  ", m.captures[1], " ",
+          "{^{", m.captures[1], ".}^}../", segment_object_belongs_to, ".fn_suffix#noteref_\n  ", m.captures[1], " ",
           m.captures[2]); // sometimes need segment name (segmented html & epub)
         // writeln("{^{", m.captures[1], ".}^}#", contents_am[counter]["obj_cite_number"], " ", m.captures[2]);
       }
-      object_notes ~= (segment_object_belongs_to.empty)
+      // TODO NEXT you need anchor for segments at this point ->
+      object_notes["seg"] ~=
+        "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~
+        m.captures[1] ~ " " ~ m.captures[2] ~ "』";
+      object_notes["seg"] ~= (segment_object_belongs_to.empty)
       ? ("{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~
         m.captures[1] ~ " " ~ m.captures[2] ~ "』")
-      : ("{^{" ~ m.captures[1] ~ ".}^}[../" ~ segment_object_belongs_to ~ ".fn_suffix]#noteref_" ~
+      : ("{^{" ~ m.captures[1] ~ ".}^}../" ~ segment_object_belongs_to ~ ".fn_suffix#noteref_" ~
         m.captures[1] ~ " " ~ m.captures[2] ~ "』");
+      object_notes["scroll"] ~=
+        "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~
+        m.captures[1] ~ " " ~ m.captures[2] ~ "』";
     }
     return object_notes;
   }
@@ -3430,9 +3742,13 @@ struct NotesSection {
   in {
   }
   body {
-    string[] endnotes_;
+    string[][string] endnotes_;
     if (object_notes.length > 1) {
-      endnotes_ = (split(object_notes, rgx.break_string))[0..$-1];
+      endnotes_["seg"] = (split(object_notes["seg"], rgx.break_string))[0..$-1];
+      endnotes_["scroll"] = (split(object_notes["scroll"], rgx.break_string))[0..$-1];
+    } else {
+      endnotes_["seg"] = [];
+      endnotes_["scroll"] = [];
     }
     return endnotes_;
   }
@@ -3447,7 +3763,7 @@ struct NotesSection {
   }
   body {
     auto set_abstract_object = ObjectAbstractSet();
-    ObjComposite[] endnotes_section;
+    ObjComposite[][string] the_endnotes_section;
     auto endnotes_ = gathered_notes();
     // auto endnotes_ = (split(object_notes, rgx.break_string))[0..$-1];
     string type;
@@ -3459,7 +3775,17 @@ struct NotesSection {
     lev="B";
     lev_markup_number="1";
     lev_collapsed_number="1";
-    endnotes_section ~=
+    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)
+      );
+    the_endnotes_section["scroll"] ~=
       set_abstract_object.contents_heading(
         "Endnotes",
         attrib,
@@ -3476,7 +3802,17 @@ struct NotesSection {
     lev="1";
     lev_markup_number="4";
     lev_collapsed_number="2";
-    endnotes_section ~=
+    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)
+      );
+    the_endnotes_section["scroll"] ~=
       set_abstract_object.contents_heading(
         "Endnotes",
         attrib,
@@ -3488,7 +3824,7 @@ struct NotesSection {
       );
     ++obj_cite_number;
     ++mkn;
-    foreach (endnote; endnotes_) {
+    foreach (endnote; endnotes_["seg"]) {
       attrib="";
       // endnotes ~=
       //   set_abstract_object.contents_para(
@@ -3497,13 +3833,15 @@ struct NotesSection {
       //     indent,
       //     false
       //   );
-      endnotes_section ~=
-        set_abstract_object.contents_endnote(
-          endnote,
-        );
-      ++mkn;
+      the_endnotes_section["seg"] ~=
+        set_abstract_object.contents_endnote(endnote);
+    }
+    foreach (endnote; endnotes_["scroll"]) {
+      attrib="";
+      the_endnotes_section["scroll"] ~=
+        set_abstract_object.contents_endnote(endnote);
     }
-    auto t = tuple(endnotes_section, obj_cite_number);
+    auto t = tuple(the_endnotes_section, obj_cite_number);
     return t;
   }
 #+END_SRC
@@ -4264,8 +4602,8 @@ auto contents_para(
   object_set.obj_cite_number          = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
   object_set.para_attrib.indent_start = 0; // indent["hang_position"];
   object_set.para_attrib.indent_rest  = 0; // indent["base_position"];
-  object_set.para_attrib.bullet       = false;
-  // object_set.node_structure.node               = _node;
+  object_set.para_attrib.bullet       = false; // bullet;
+  // object_set.node_structure.node   = _node;
   return object_set;
 }
 #+END_SRC
@@ -4389,13 +4727,31 @@ template SiSUdocAbstraction() {
       foreach (line; markup_sourcefile_content) {
         /+ ↓ markup document/text line by line +/
         <<abs_in_loop_body_00>>
-        <<abs_in_loop_body_00_code_block>>
-        <<abs_in_loop_body_00_non_code_block>>
+        if (type["code"] == TriState.on) {
+          <<abs_in_loop_body_00_code_block>>
+        } else if (!matchFirst(line, rgx.skip_from_regular_parse)) {
+          /+ object other than "code block" object
+             (includes regular text paragraph, headings & blocks other than code) +/
           <<abs_in_loop_body_non_code_obj>>
-            <<abs_in_loop_body_open_block_obj>>
-            <<abs_in_loop_body_not_block_obj>>
+          } else {
+            /+ not within a block group +/
+            <<abs_in_loop_body_open_block_obj_assert>>
+            if (matchFirst(line, rgx.block_open)) {
+              <<abs_in_loop_body_open_block_obj>>
+            } else if (!line.empty) {
+              /+ line not empty +/
+              /+ non blocks (headings, paragraphs) & closed blocks +/
+              <<abs_in_loop_body_not_block_obj>>
+            } else if (type["blocks"] == TriState.closing) {
+              /+ line empty, with blocks flag +/
+              <<abs_in_loop_body_not_block_obj_line_empty_blocks_flags>>
+            } else {
+              /+ line empty +/
+              /+ line.empty, post contents, empty variables: +/
               <<abs_in_loop_body_not_block_obj_line_empty>>
-        <<abs_in_loop_body_00_closed>>
+            } // close else for line empty
+          } // close else for not the above
+        } // close after non code, other blocks or regular text
         <<abs_in_loop_body_01>>
       } /+ ← closed: loop markup document/text line by line +/
       /+ ↓ post loop markup document/text +/
@@ -4424,6 +4780,7 @@ template SiSUdocAbstraction() {
     <<ao_emitters_obj_inline_markup_munge>>
     <<ao_emitters_obj_inline_markup>>
     <<ao_emitters_obj_inline_markup_and_anchor_tags>>
+    <<ao_emitters_obj_inline_markup_table_of_contents>>
     <<ao_emitters_obj_inline_markup_private>>
     <<ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags>>
     <<ao_emitters_obj_inline_markup_close>>
diff --git a/org/ao_conf_make_meta.org b/org/ao_conf_make_meta.org
index b6fcb92..fa3c88d 100644
--- a/org/ao_conf_make_meta.org
+++ b/org/ao_conf_make_meta.org
@@ -491,7 +491,7 @@ private auto headerNativeToAA(in char[] src_header) {
   auto dochead_meta = meta_aa;
   auto set_header = HeaderDocMetadataAndMakeNativeToAA();
   char[][] source_header_arr =
-    split(cast(char[]) src_header, rgx.line_delimiter);
+    split(cast(char[]) src_header, rgx.newline_eol_delimiter);
   foreach(header_line; source_header_arr) {
     if (auto m = matchFirst(header_line, rgx.comment)) {
       /+ matched comment +/
@@ -573,7 +573,7 @@ final private auto headerMakeSDLang(in string src_header) {
 #+BEGIN_SRC d
 private auto headerSDLangGet(in char[] src_header) {
   char[][] source_header_arr =
-    split(cast(char[]) src_header, rgx.line_delimiter);
+    split(cast(char[]) src_header, rgx.newline_eol_delimiter);
   char[] header_clean;
   // TODO
   foreach(header_line; source_header_arr) {
@@ -604,6 +604,31 @@ private auto headerSDLangGet(in char[] src_header) {
 private auto headerSDLangToAAmake(Tag header_sdlang, string[string][string] dochead_make) {
   dochead_make = sdlangToAAmake(dochead_make, header_sdlang);
   auto dochead_meta = sdlangToAAmake(meta_aa, header_sdlang);
+  if (dochead_meta["title"]["main"].empty) {
+    dochead_meta["title"]["main"] =
+      to!string(header_sdlang.maybe.tags["title"][0].values[0]); // test that this exists
+  }
+  if (!(dochead_meta["title"]["subtitle"].empty)
+  && (dochead_meta["title"]["sub"].empty)) {
+    dochead_meta["title"]["sub"] ~= dochead_meta["title"]["subtitle"];
+  }
+  dochead_meta["title"].remove("subtitle");
+  if (dochead_meta["title"]["sub"].empty) {
+    dochead_meta["title"]["full"] ~= dochead_meta["title"]["main"];
+  } else {
+    dochead_meta["title"]["full"] ~= format(
+      "%s - %s",
+      dochead_meta["title"]["main"],
+      dochead_meta["title"]["sub"],
+    );
+  }
+  dochead_meta["creator"]["author_raw"] = dochead_meta["creator"]["author"];
+  string[] authors_arr;
+  auto authors_raw_arr = split(dochead_meta["creator"]["author"], rgx.arr_delimiter);
+  foreach (author_raw; authors_raw_arr) {
+    authors_arr ~= replace(author_raw, rgx.raw_author_munge, "$2 $1");
+  }
+  dochead_meta["creator"]["author"] = join(authors_arr, ", ").chomp.chomp;
   auto t = tuple(dochead_make, dochead_meta);
   static assert(t.length==2);
   return t;
diff --git a/org/ao_defaults.org b/org/ao_defaults.org
index 3758a2f..2677f78 100644
--- a/org/ao_defaults.org
+++ b/org/ao_defaults.org
@@ -157,7 +157,8 @@ template SiSUregisters() {
         "language"          : "",
         "main"              : "",
         "note"              : "",
-        "sub"               : ""
+        "sub"               : "",
+        "subtitle"          : ""
       ]
     ];
     return meta_;
@@ -529,13 +530,14 @@ static name_delimiter            = ctRegex!(`^([^,]+)[ ]*,[ ]+(.+?)$`);
 static book_index_go             = ctRegex!("([0-9]+)(?:-[0-9]+)?");
 static trailing_comma            = ctRegex!(",[ ]*$");
 static trailing_linebreak        = ctRegex!(",[ ]{1,2}\\\\\\\\\n[ ]{4}$","m");
-static line_delimiter            = ctRegex!("\n");
-static line_delimiter_ws_strip   = ctRegex!("[ ]*\n[ ]*");
-static line_delimiter_only       = ctRegex!("^\n");
-static para_delimiter            = ctRegex!("\n[ ]*\n+");
-static levels_markup             = ctRegex!(`^[A-D1-4]$`);
-static levels_numbered           = ctRegex!(`^[0-9]$`);
-static levels_numbered_headings  = ctRegex!(`^[0-7]$`);
+static newline_eol_delimiter     = ctRegex!("\n");
+static newline_eol_strip_preceeding = ctRegex!("[ ]*\n");
+static newline_eol_delimiter_only   = ctRegex!("^\n");
+static line_delimiter_ws_strip      = ctRegex!("[ ]*\n[ ]*");
+static para_delimiter               = ctRegex!("\n[ ]*\n+");
+static levels_markup                = ctRegex!(`^[A-D1-4]$`);
+static levels_numbered              = ctRegex!(`^[0-9]$`);
+static levels_numbered_headings     = ctRegex!(`^[0-7]$`);
 #+END_SRC
 
 ** filename (and path) matching (including markup insert file) :insert:file:path:filename:
@@ -581,7 +583,8 @@ static native_header_sub                = ctRegex!(`^[ ]*:(?P<subheader>[a-z_]+)
 // static native_header_sub                = ctRegex!(`^[ ]+:([a-z_]+):\s`);
 static native_header_meta_title         = ctRegex!(`^@title:\s`, "m");
 static variable_doc_title               = ctRegex!(`@title`);
-static variable_doc_author              = ctRegex!(`@author`);
+static variable_doc_author              = ctRegex!(`@author|@creator`);
+static raw_author_munge                 = ctRegex!(`(\S.+?),\s+(.+)`,"i");
 #+END_SRC
 
 ** subheader                                                :native:subheader:
@@ -607,7 +610,7 @@ static native_subhead_make              = ctRegex!(`^(?:cover_image|home_button_
 #+BEGIN_SRC d
 /+ heading & paragraph operators +/
 static heading_a          = ctRegex!(`^:?[A][~] `, "m");
-static heading            = ctRegex!(`^:?([A-D1-4])[~]([a-z0-9_.-]*[?]?) `);
+static heading            = ctRegex!(`^:?([A-D1-4])[~]([a-z0-9_.-]*[?]?)\s+`,"i");
 static heading_marker     = ctRegex!(`^:?([A-D1-4])[~]`);
 static heading_anchor_tag = ctRegex!(`^:?[A-D1-4][~]([a-z0-9_.-]+) `,"i");
 static heading_identify_anchor_tag = ctRegex!(`^:?[A-D1-4][~]\s+(?:(?:(?:chapter|article|section|clause)\s+[0-9.]+)|(?:[0-9]+))`,"i"); // unless dob.obj =~/^:?[A-D1-4]~\s+(?:|(?:chapter|article|section|clause)\s+)([0-9.]+)/i
diff --git a/org/ao_output_debugs.org b/org/ao_output_debugs.org
index 3322373..7cbe476 100644
--- a/org/ao_output_debugs.org
+++ b/org/ao_output_debugs.org
@@ -460,7 +460,10 @@ debug(checkdoc) {
 #+name: ao_output_debugs_summary
 #+BEGIN_SRC d
 writefln(
-  "%s\n%s\n%s%s\n%s%s\n%s%s\n%s:%s",
+  "%s\n\"%s\", %s\n%s\n%s\n%s%s\n%s%s\n%s%s\n%s:%s",
+  "-------------------------------",
+  dochead_meta["title"]["full"],
+  dochead_meta["creator"]["author"],
   "-------------------------------",
   fn_src,
   "length contents array: ",
diff --git a/org/ao_read_source_files.org b/org/ao_read_source_files.org
index 8aab5c9..66b91a8 100644
--- a/org/ao_read_source_files.org
+++ b/org/ao_read_source_files.org
@@ -184,7 +184,7 @@ catch (ErrnoException ex) {
 // }
 }
 
-** document header & content, array.length == 2                       :array:
+** [#A] document header & content, array.length == 2                  :array:
 
 here you split document header and body, an array.length == 2
 split is on first match of level A~ (which is required)
@@ -211,7 +211,7 @@ final private char[][] header0Content1(in string src_text) {
 #+BEGIN_SRC d
 final private char[][] markupSourceLineArray(in char[] src_text) {
   char[][] source_line_arr =
-    split(cast(char[]) src_text, rgx.line_delimiter);
+    split(cast(char[]) src_text, rgx.newline_eol_strip_preceeding);
   return source_line_arr;
 }
 #+END_SRC
diff --git a/org/output.org b/org/output.org
index 1dd19a8..1c9902a 100644
--- a/org/output.org
+++ b/org/output.org
@@ -20,22 +20,6 @@
 **** html functions
 ***** html
 
-#+name: output_html
-#+BEGIN_SRC d
-auto html_toc(O)(
-  auto ref const O         obj,
-) {
-  string o;
-  o = format(q"◎<h%s class="toc"><a href="#%s">%s</a></h%s>◎",
-  obj.heading_attrib.lev_markup_number,
-  obj.obj_cite_number,
-  obj.object,
-  obj.heading_attrib.lev_markup_number
-  );
-  return o;
-}
-#+END_SRC
-
 ***** heading
 
 #+name: output_html
@@ -146,6 +130,7 @@ auto scroll_tail() {
 #+BEGIN_SRC d
 void scroll(C)(
   auto ref const C         contents,
+  string[]                 document_parts,
   string[][string][string] bookindex_unordered_hashes,
   JSONValue[]              biblio,
   string[string][string]   dochead_make,
@@ -157,47 +142,48 @@ void scroll(C)(
   string[] toc;
   string[] body_;
   string[] doc;
-  foreach (obj; contents) {
-    if (obj.use == "content") {
-      switch (obj.is_a) {
-      case "heading":
-        toc ~= html_toc(obj);
-        body_ ~= html_heading(obj);
-        break;
-      case "para":
-        body_ ~= html_para(obj);
-        break;
-      case "verse":
-        body_ ~= html_para(obj);
-        // body_ ~= html_verse(obj);
-        break;
-      case "group":
-        body_ ~= html_para(obj);
-        // body_ ~= html_group(obj);
-        break;
-      case "block":
-        body_ ~= html_para(obj);
-        // body_ ~= html_block(obj);
-        break;
-      case "quote":
-        body_ ~= html_para(obj);
-        // body_ ~= html_quote(obj);
-        break;
-      case "table":
-        body_ ~= html_para(obj);
-        // body_ ~= html_table(obj);
-        break;
-      case "code":
-        body_ ~= html_para(obj);
-        // body_ ~= html_code(obj);
-        break;
-      default:
-        body_ ~= html_para(obj);
-        break;
+  foreach (part; document_parts) {
+    foreach (obj; contents[part]) {
+      if (obj.use == "content") {
+        switch (obj.is_a) {
+        case "heading":
+          body_ ~= html_heading(obj);
+          break;
+        case "para":
+          body_ ~= html_para(obj);
+          break;
+        case "verse":
+          body_ ~= html_para(obj);
+          // body_ ~= html_verse(obj);
+          break;
+        case "group":
+          body_ ~= html_para(obj);
+          // body_ ~= html_group(obj);
+          break;
+        case "block":
+          body_ ~= html_para(obj);
+          // body_ ~= html_block(obj);
+          break;
+        case "quote":
+          body_ ~= html_para(obj);
+          // body_ ~= html_quote(obj);
+          break;
+        case "table":
+          body_ ~= html_para(obj);
+          // body_ ~= html_table(obj);
+          break;
+        case "code":
+          body_ ~= html_para(obj);
+          // body_ ~= html_code(obj);
+          break;
+        default:
+          body_ ~= html_para(obj);
+          break;
+        }
       }
     }
   }
-  doc = scroll_head ~ toc ~ body_ ~ scroll_tail;
+  doc = scroll_head ~ body_ ~ scroll_tail;
   auto m = matchFirst(fn_src, rgx.src_fn);
   auto fn = m["fn_base"] ~ ".html";
   auto pth_html = "en/html";
@@ -1555,6 +1541,7 @@ template SiSUoutputHub() {
       bool[string]             opt_action_bool
     ) {
       auto rgx = Rgx();
+      string[] document_parts;
       if (opt_action_bool["source"]) {
         writeln("sisupod source");
       }
@@ -1569,8 +1556,25 @@ template SiSUoutputHub() {
       if (opt_action_bool["html"]) {
         mixin SiSUoutputHTML;
         auto html=SDPoutputHTML();
+        document_parts = [
+          "head",
+          "toc_scroll",
+          "body",
+          "endnotes_scroll",
+          "bibliography",
+          "bookindex_scroll"
+        ];
         html.css_write;
-        html.scroll(contents, bookindex_unordered_hashes, biblio, dochead_make, dochead_meta, fn_src, opt_action_bool);
+        html.scroll(
+          contents,
+          document_parts,
+          bookindex_unordered_hashes,
+          biblio,
+          dochead_make,
+          dochead_meta,
+          fn_src,
+          opt_action_bool
+        );
       }
       if (opt_action_bool["epub"]) {
         writeln("epub processing");
diff --git a/org/sdp.org b/org/sdp.org
index 97d1498..28c9b92 100644
--- a/org/sdp.org
+++ b/org/sdp.org
@@ -24,7 +24,7 @@ struct Version {
   int minor;
   int patch;
 }
-enum ver = Version(0, 7, 3);
+enum ver = Version(0, 8, 0);
 #+END_SRC
 
 * sdp.d   sisu document parser                                       :sdp.d:
@@ -364,10 +364,10 @@ string[string][string] dochead_meta = header_make_and_meta_tuple[1];
 /+ ↓ document abstraction: process document, return abstraction as tuple +/
 auto t = abs.abstract_doc_source(content_body, dochead_make, dochead_meta);
 static assert(!isTypeTuple!(t));
-auto doc_ao_contents = t[0]; // contents ~ endnotes ~ bookindex;
+auto doc_ao_contents = t[0]; // head ~ toc ~ contents ~ endnotes_seg ~ [glossary] ~ bibliography ~ bookindex;
 // static assert(!isIterable!(doc_ao_contents));
-auto doc_ao_bookindex_unordered_hashes = t[1];
-auto doc_ao_biblio = t[2];
+auto doc_ao_bookindex_unordered_hashes = t[1]; // redundant?
+auto doc_ao_biblio = t[2];                     // redundant?
 // destroy(t);
 #+END_SRC
 
@@ -377,10 +377,18 @@ auto doc_ao_biblio = t[2];
 #+BEGIN_SRC d
 /+ ↓ debugs +/
 debug(checkdoc) { // checkbook & dumpdoc
+  auto doc_ao_contents_view = (
+    doc_ao_contents["head"] ~
+    doc_ao_contents["toc_seg"] ~
+    doc_ao_contents["body"] ~
+    doc_ao_contents["endnotes_seg"] ~
+    doc_ao_contents["bibliography"] ~
+    doc_ao_contents["bookindex_seg"]
+  );
   dbg.abstract_doc_source_debugs(
-    doc_ao_contents,
-    doc_ao_bookindex_unordered_hashes,
-    doc_ao_biblio,
+    doc_ao_contents_view,
+    doc_ao_bookindex_unordered_hashes, // redundant?
+    doc_ao_biblio,                     // redundant?
     dochead_make,
     dochead_meta,
     fn_src,
@@ -396,8 +404,8 @@ debug(checkdoc) { // checkbook & dumpdoc
 /+ ↓ output hub +/
 output.hub(
   doc_ao_contents,
-  doc_ao_bookindex_unordered_hashes,
-  doc_ao_biblio,
+  doc_ao_bookindex_unordered_hashes, // redundant?
+  doc_ao_biblio,                     // redundant?
   dochead_make,
   dochead_meta,
   fn_src,
diff --git a/src/sdp.d b/src/sdp.d
index 3370433..6a0d48c 100755
--- a/src/sdp.d
+++ b/src/sdp.d
@@ -199,17 +199,25 @@ void main(string[] args) {
       /+ ↓ document abstraction: process document, return abstraction as tuple +/
       auto t = abs.abstract_doc_source(content_body, dochead_make, dochead_meta);
       static assert(!isTypeTuple!(t));
-      auto doc_ao_contents = t[0]; // contents ~ endnotes ~ bookindex;
+      auto doc_ao_contents = t[0]; // head ~ toc ~ contents ~ endnotes_seg ~ [glossary] ~ bibliography ~ bookindex;
       // static assert(!isIterable!(doc_ao_contents));
-      auto doc_ao_bookindex_unordered_hashes = t[1];
-      auto doc_ao_biblio = t[2];
+      auto doc_ao_bookindex_unordered_hashes = t[1]; // redundant?
+      auto doc_ao_biblio = t[2];                     // redundant?
       // destroy(t);
       /+ ↓ debugs +/
       debug(checkdoc) { // checkbook & dumpdoc
+        auto doc_ao_contents_view = (
+          doc_ao_contents["head"] ~
+          doc_ao_contents["toc_seg"] ~
+          doc_ao_contents["body"] ~
+          doc_ao_contents["endnotes_seg"] ~
+          doc_ao_contents["bibliography"] ~
+          doc_ao_contents["bookindex_seg"]
+        );
         dbg.abstract_doc_source_debugs(
-          doc_ao_contents,
-          doc_ao_bookindex_unordered_hashes,
-          doc_ao_biblio,
+          doc_ao_contents_view,
+          doc_ao_bookindex_unordered_hashes, // redundant?
+          doc_ao_biblio,                     // redundant?
           dochead_make,
           dochead_meta,
           fn_src,
@@ -219,8 +227,8 @@ void main(string[] args) {
       /+ ↓ output hub +/
       output.hub(
         doc_ao_contents,
-        doc_ao_bookindex_unordered_hashes,
-        doc_ao_biblio,
+        doc_ao_bookindex_unordered_hashes, // redundant?
+        doc_ao_biblio,                     // redundant?
         dochead_make,
         dochead_meta,
         fn_src,
diff --git a/src/sdp/ao_abstract_doc_source.d b/src/sdp/ao_abstract_doc_source.d
index 074fbc5..683b748 100644
--- a/src/sdp/ao_abstract_doc_source.d
+++ b/src/sdp/ao_abstract_doc_source.d
@@ -17,7 +17,10 @@ template SiSUdocAbstraction() {
     /+ ↓ abstraction struct init +/
     /+ initialize +/
     auto rgx = Rgx();
-    ObjComposite[] contents_the_objects;
+    ObjComposite[] the_document_head_section;
+    ObjComposite[][string] the_table_of_contents_section;
+    ObjComposite[] the_document_body_section;
+    ObjComposite[] the_bibliography_section;
     string[string] an_object, processing;
     string[] anchor_tags;
     string segment_object_belongs_to;
@@ -83,7 +86,10 @@ template SiSUdocAbstraction() {
       scope(failure) {
       }
       scope(exit) {
-        destroy(contents_the_objects);
+        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);
@@ -272,9 +278,9 @@ template SiSUdocAbstraction() {
                     writeln(line);
                   }
                   an_object["obj"] ~= line ~= "\n";
-                  contents_the_objects ~=
+                  the_document_body_section ~=
                     set_abstract_object.contents_comment(strip(an_object["obj"]));
-                  _header_set_common_(line_occur, an_object, type);
+                  _common_reset_(line_occur, an_object, type);
                   processing.remove("verse");
                   ++counter;
                 } else if (((line_occur["para"] == State.off)
@@ -295,6 +301,13 @@ template SiSUdocAbstraction() {
                     /+ 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, lv, collapsed_lev, type, dochead_meta_aa);
@@ -320,7 +333,18 @@ template SiSUdocAbstraction() {
               }
             } else if (type["blocks"] == TriState.closing) {
               /+ line empty, with blocks flag +/
-              _block_flag_line_empty_(line, an_object, contents_the_objects, bookindex_unordered_hashes, obj_cite_number, _node, counter, type, obj_cite_number_poem, dochead_make_aa); // watch
+              _block_flag_line_empty_(
+                line,
+                an_object,
+                the_document_body_section,
+                bookindex_unordered_hashes,
+                obj_cite_number,
+                _node,
+                counter,
+                type,
+                obj_cite_number_poem,
+                dochead_make_aa
+              ); // watch
             } else {
               /+ line empty +/
               /+ line.empty, post contents, empty variables: +/
@@ -350,6 +374,13 @@ template SiSUdocAbstraction() {
                 } else if (to!int(an_object["lev_markup_number"]) < 4) {
                   segment_object_belongs_to = "";
                 }
+                the_table_of_contents_section = obj_im.table_of_contents_gather_headings(
+                  an_object,
+                  dochead_make_aa,
+                  segment_object_belongs_to,
+                  obj_cite_number,
+                  the_table_of_contents_section,
+                );
                 _node =
                   node_construct.node_emitter_heading(
                     an_object["lev_markup_number"],
@@ -367,7 +398,7 @@ template SiSUdocAbstraction() {
                   writeln(an_object["lev_markup_number"]);
                   writeln(segment_object_belongs_to);
                 }
-                contents_the_objects ~=
+                the_document_body_section ~=
                   set_abstract_object.contents_heading(
                     an_object["substantive"],
                     an_object["attrib"],
@@ -384,7 +415,7 @@ template SiSUdocAbstraction() {
                   // writeln(contents_am[counter]["obj_cite_number"], " ", contents_am[counter]["obj"]);
                   // writeln(m.hit, "\n");
                 }
-                _header_set_common_(line_occur, an_object, type);
+                _common_reset_(line_occur, an_object, type);
                 an_object.remove("lev");
                 an_object.remove("lev_markup_number");
                 // an_object["lev_markup_number"]="9";
@@ -413,7 +444,7 @@ template SiSUdocAbstraction() {
                 anchor_tags = substantive_object_and_anchor_tags_tuple[1];
                 an_object["attrib"] =
                   obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-                contents_the_objects ~=
+                the_document_body_section ~=
                   set_abstract_object.contents_para(
                     an_object["is"],
                     an_object["substantive"],
@@ -422,16 +453,11 @@ template SiSUdocAbstraction() {
                     indent,
                     bullet
                   );
-                // contents_the_objects ~=
-                //   set_abstract_object.contents_para(
-                //     an_object,
-                //     obj_cite_number,
-                //     indent,
-                //     bullet
-                //   );
-                _header_set_common_(line_occur, an_object, type);
-                indent["hang_position"] = "0";
-                indent["base_position"] = "0";
+                _common_reset_(line_occur, an_object, type);
+                indent=[
+                  "hang_position" : "0",
+                  "base_position" : "0",
+                ];
                 bullet = false;
                 processing.remove("verse");
                 ++counter;
@@ -445,18 +471,18 @@ template SiSUdocAbstraction() {
             } // close else for line empty
           } // close else for not the above
         } // close after non code, other blocks or regular text
-        /+ unless (contents_the_objects.length == 0) ? +/
-        if (contents_the_objects.length > 0) {
-          if (((contents_the_objects[$-1].is_a == "para")
-          || (contents_the_objects[$-1].is_a == "heading"))
+        /+ 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"))
           && (counter-1 > previous_count)) {
-            if (match(contents_the_objects[$-1].object,
+            if (match(the_document_body_section[$-1].object,
             rgx.inline_notes_delimiter_al_regular_number_note)) {
-              previous_count=contents_the_objects.length -1;
+              previous_count=the_document_body_section.length -1;
               note_section.gather_notes_for_endnote_section(
-                contents_the_objects,
+                the_document_body_section,
                 segment_object_belongs_to,
-                contents_the_objects.length -1
+                the_document_body_section.length -1
               );
             }
           }
@@ -475,39 +501,116 @@ template SiSUdocAbstraction() {
       +/
       // TODO FIGURE OUT, you need this possibility
       // obj_im.obj_inline_markup_and_anchor_tags("doc_end_reset", "", dochead_make_aa);
+      debug(toc) {
+        writefln(
+          "%s %s",
+          __LINE__,
+          the_table_of_contents_section["seg"].length
+        );
+        foreach (toc_linked_heading; the_table_of_contents_section["seg"]) {
+          writeln(toc_linked_heading.object);
+        }
+      }
       auto en_tuple =
         note_section.endnote_objects(obj_cite_number);
       static assert(!isTypeTuple!(en_tuple));
-      auto endnotes_section = en_tuple[0];
+      auto the_endnotes_section = en_tuple[0];
       obj_cite_number = en_tuple[1];
       debug(endnotes) {
         writefln(
           "%s %s",
           __LINE__,
-          endnotes_section.length
+          the_endnotes_section["seg"].length
+        );
+        foreach (o; the_endnotes_section["seg"]) {
+          writeln(o);
+        }
+      }
+      the_bibliography_section ~=
+        set_abstract_object.contents_heading(
+          "Bibliography",   // nugget/object
+          "",               // attrib
+          0,                // obj_cite_number
+          [""],             // anchor tag
+          "B",              // lev
+          1,                // lev_markup_number
+          1,                // lev_collapsed_number
+        );
+      the_bibliography_section ~=
+        set_abstract_object.contents_heading(
+          "Bibliography",   // nugget/object
+          "",               // attrib
+          0,                // obj_cite_number
+          ["bibliography"], // anchor tag
+          "1",              // lev
+          4,                // lev_markup_number
+          2,                // lev_collapsed_number
         );
-        foreach (n; endnotes_section) {
-          writeln(n);
-        }
-      }
       auto biblio_unsorted_incomplete = biblio_arr_json.dup;
       // destroy(biblio_arr_json);
       auto biblio = Bibliography();
       auto biblio_ordered =
         biblio._bibliography_(biblio_unsorted_incomplete, bib_arr_json);
+      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_object_belongs_to);
+        bi.bookindex_build_section(
+          bookindex_unordered_hashes,
+          obj_cite_number,
+          segment_object_belongs_to
+        );
       static assert(!isTypeTuple!(bi_tuple));
-      auto bookindex_section = bi_tuple[0];
+      auto the_bookindex_section = bi_tuple[0];
       obj_cite_number = bi_tuple[1];
       debug(bookindex) {                         // bookindex
-        foreach (bi_entry; bookindex_section) {
+        foreach (bi_entry; the_bookindex_section["seg"]) {
           writeln(bi_entry);
         }
       }
-      auto document_the =
-        contents_the_objects ~ endnotes_section ~ bookindex_section;
+      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, // TODO
+        "bibliography":    the_bibliography_section,
+        "bookindex_scroll": the_bookindex_section["scroll"],
+        "bookindex_seg":    the_bookindex_section["seg"],
+      ];
       auto t = tuple(
         document_the,
         bookindex_unordered_hashes,
@@ -524,12 +627,11 @@ template SiSUdocAbstraction() {
       an_object.remove("attrib");
       an_object.remove("bookindex");
     }
-    auto _header_set_common_(
+    auto _common_reset_(
       ref int[string] line_occur,
       ref string[string] an_object,
       ref int[string] type
     ) {
-      // line_occur["header"] = State.off;
       line_occur["heading"] = State.off;
       line_occur["para"]= State.off;
       type["heading"] = State.off;
@@ -944,7 +1046,7 @@ template SiSUdocAbstraction() {
             anchor_tags = substantive_object_and_anchor_tags_tuple[1];
             an_object["attrib"] =
               obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-            contents_the_objects ~=
+            the_document_body_section ~=
               set_abstract_object.contents_block(
                 an_object["is"],
                 an_object["substantive"],
@@ -966,7 +1068,7 @@ template SiSUdocAbstraction() {
             obj_cite_number =
               obj_cite_number_emit(type["obj_cite_number_status"]);
             type["verse_new"] = State.off;
-          } else if (matchFirst(line, rgx.line_delimiter_only)) {
+          } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) {
             verse_line = TriState.off;
             type["verse_new"] = State.on;
           }
@@ -996,7 +1098,7 @@ template SiSUdocAbstraction() {
             anchor_tags = substantive_object_and_anchor_tags_tuple[1];
             an_object["attrib"] =
               obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-            contents_the_objects ~=
+            the_document_body_section ~=
               set_abstract_object.contents_block(
                 an_object["is"],
                 an_object["substantive"],
@@ -1033,7 +1135,7 @@ template SiSUdocAbstraction() {
             anchor_tags = substantive_object_and_anchor_tags_tuple[1];
             an_object["attrib"] =
               obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-            contents_the_objects ~=
+            the_document_body_section ~=
               set_abstract_object.contents_block(
                 an_object["is"],
                 an_object["substantive"],
@@ -1054,7 +1156,7 @@ template SiSUdocAbstraction() {
             obj_cite_number =
               obj_cite_number_emit(type["obj_cite_number_status"]);
             type["verse_new"] = State.off;
-          } else if (matchFirst(line, rgx.line_delimiter_only)) {
+          } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) {
             type["verse_new"] = State.on;
             verse_line = TriState.off;
           }
@@ -1085,7 +1187,7 @@ template SiSUdocAbstraction() {
             anchor_tags = substantive_object_and_anchor_tags_tuple[1];
             an_object["attrib"] =
               obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-            contents_the_objects ~=
+            the_document_body_section ~=
               set_abstract_object.contents_block(
                 an_object["is"],
                 an_object["substantive"],
@@ -1242,7 +1344,7 @@ template SiSUdocAbstraction() {
     void _block_flag_line_empty_(
       char[] line,
       ref string[string] an_object,
-      ref ObjComposite[] contents_the_objects,
+      ref ObjComposite[] the_document_body_section,
       ref string[][string][string] bookindex_unordered_hashes,
       ref int obj_cite_number,
       ref string _node,
@@ -1284,7 +1386,7 @@ template SiSUdocAbstraction() {
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         an_object["attrib"] =
           obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-        contents_the_objects ~=
+        the_document_body_section ~=
           set_abstract_object.contents_block_code(
             an_object["is"],
             an_object["substantive"],
@@ -1313,7 +1415,7 @@ template SiSUdocAbstraction() {
             an_object["is"]
             // "verse"
           );
-        contents_the_objects ~=
+        the_document_body_section ~=
           set_abstract_object.contents_block_obj_cite_number_string(
             "poem",
             "",
@@ -1348,7 +1450,7 @@ template SiSUdocAbstraction() {
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         an_object["attrib"] =
           obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-        contents_the_objects ~=
+        the_document_body_section ~=
           set_abstract_object.contents_block(
             an_object["is"],
             an_object["substantive"],
@@ -1383,7 +1485,7 @@ template SiSUdocAbstraction() {
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         an_object["attrib"] =
           obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-        contents_the_objects ~=
+        the_document_body_section ~=
           set_abstract_object.contents_block(
             an_object["is"],
             an_object["substantive"],
@@ -1417,7 +1519,7 @@ template SiSUdocAbstraction() {
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         an_object["attrib"] =
           obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-        contents_the_objects ~=
+        the_document_body_section ~=
           set_abstract_object.contents_block(
             an_object["is"],
             an_object["substantive"],
@@ -1452,7 +1554,7 @@ template SiSUdocAbstraction() {
         anchor_tags = substantive_object_and_anchor_tags_tuple[1];
         an_object["attrib"] =
           obj_att.obj_attributes(an_object["is"], an_object["obj"], _node);
-        contents_the_objects ~=
+        the_document_body_section ~=
           set_abstract_object.contents_block(
             an_object["is"],
             an_object["substantive"],
@@ -1672,8 +1774,10 @@ template SiSUdocAbstraction() {
         assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels
         switch (an_object["lev"]) {
         case "A":
-          an_object["obj"]=replaceFirst(an_object["obj"], rgx.variable_doc_title, dochead_meta_aa["title"]["main"]);
-          an_object["obj"]=replaceFirst(an_object["obj"], rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]);
+          an_object["obj"]=replaceFirst(an_object["obj"],
+            rgx.variable_doc_title, (dochead_meta_aa["title"]["full"] ~ ","));
+          an_object["obj"]=replaceFirst(an_object["obj"],
+            rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]);
           collapsed_lev["h0"] = 1;
           an_object["lev_collapsed_number"] =
             to!string(collapsed_lev["h0"]);
@@ -1817,8 +1921,10 @@ template SiSUdocAbstraction() {
           }
           type["para"] = State.on;
           an_object["obj"] ~= line;
-          indent["hang_position"] = "0";
-          indent["base_position"] = "0";
+          indent=[
+            "hang_position" : "0",
+            "base_position" : "0",
+          ];
           bullet = true;
         } else if (auto m = matchFirst(line, rgx.para_indent_hang)) {
           debug(paraindenthang) {                // para indent hang
@@ -1826,8 +1932,10 @@ template SiSUdocAbstraction() {
           }
           type["para"] = State.on;
           an_object["obj"] ~= line;
-          indent["hang_position"] = to!string(m.captures[1]);
-          indent["base_position"] = to!string(m.captures[2]);
+          indent=[
+            "hang_position" : to!string(m.captures[1]),
+            "base_position" : to!string(m.captures[2]),
+          ];
           bullet = false;
         } else if (auto m = matchFirst(line, rgx.para_bullet_indent)) {
           debug(parabulletindent) {              // para bullet indent
@@ -1835,15 +1943,19 @@ template SiSUdocAbstraction() {
           }
           type["para"] = State.on;
           an_object["obj"] ~= line;
-          indent["hang_position"] = to!string(m.captures[1]);
-          indent["base_position"] = "0";
+          indent=[
+            "hang_position" : to!string(m.captures[1]),
+            "base_position" : "0",
+          ];
           bullet = true;
         } else {
           // !line.empty
           type["para"] = State.on;
           an_object["obj"] ~= line;
-          indent["hang_position"] = "0";
-          indent["base_position"] = "0";
+          indent=[
+            "hang_position" : "0",
+            "base_position" : "0",
+          ];
           bullet = false;
         }
         ++line_occur["para"];
@@ -1963,6 +2075,7 @@ template SiSUdocAbstraction() {
         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__);
@@ -2054,7 +2167,10 @@ template SiSUdocAbstraction() {
     struct ObjInlineMarkup {
       auto munge = ObjInlineMarkupMunge();
       string[string] obj_txt;
-      auto obj_inline_markup_and_anchor_tags(string[string] obj_, string[string][string] dochead_make_aa)
+      auto obj_inline_markup_and_anchor_tags(
+        string[string] obj_,
+        string[string][string] dochead_make_aa
+      )
       in { }
       body {
         obj_txt["munge"]=obj_["obj"].dup;
@@ -2115,6 +2231,150 @@ template SiSUdocAbstraction() {
       }
       invariant() {
       }
+      auto _clean_heading_toc_(
+        char[] heading_toc_,
+      ) {
+       auto m = matchFirst(cast(char[]) heading_toc_, rgx.heading);
+       heading_toc_ = m.post;
+       return heading_toc_;
+      };
+      auto table_of_contents_gather_headings(
+        string[string] obj_,
+        string[string][string] dochead_make_aa,
+        string segment_object_belongs_to,
+        int obj_cite_number,
+        ObjComposite[][string] the_table_of_contents_section,
+      )
+      in { }
+      body {
+        char[] heading_toc_ = to!(char[])(obj_["obj"].dup.strip);
+        heading_toc_ = _clean_heading_toc_(heading_toc_);
+        auto attrib="";
+        string toc_txt_;
+        string[string] indent;
+        auto set_abstract_object = ObjectAbstractSet();
+        if (to!int(obj_["lev_markup_number"]) > 0) {
+          toc_txt_ = format(
+            "{ %s }#%s",
+            heading_toc_,
+            obj_cite_number,
+          );
+          indent=[
+            "hang_position" : obj_["lev_markup_number"],
+            "base_position" : obj_["lev_markup_number"],
+          ];
+          toc_txt_ = format(
+            "{ %s }#%s",
+            heading_toc_,
+            obj_cite_number,
+          );
+          the_table_of_contents_section["scroll"] ~=
+            set_abstract_object.contents_para(
+              "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_para(
+              "toc",
+              "Table of Contents",
+              "",                   // attrib
+              0,
+              indent,
+              false
+            );
+        }
+        switch (to!int(obj_["lev_markup_number"])) {
+        case 0:
+          indent=[
+            "hang_position" : "0",
+            "base_position" : "0",
+          ];
+          the_table_of_contents_section["seg"] ~=
+            set_abstract_object.contents_para(
+              "toc",
+              "{ Table of Contents }../toc.fn_suffix",
+              "",                   // attrib
+              0,
+              indent,
+              false
+            );
+          break;
+        case 1: .. case 3:
+          indent=[
+            "hang_position" : obj_["lev_markup_number"],
+            "base_position" : obj_["lev_markup_number"],
+          ];
+          toc_txt_ = format(
+            "%s",
+            heading_toc_,
+          );
+          the_table_of_contents_section["seg"] ~=
+            set_abstract_object.contents_para(
+              "toc",
+              toc_txt_,
+              "",                   // attrib
+              0,
+              indent,
+              false
+            );
+          break;
+        case 4:
+          toc_txt_ = format(
+            "{ %s }../%s.fn_suffix",
+            heading_toc_,
+            segment_object_belongs_to,
+          );
+          indent=[
+            "hang_position" : obj_["lev_markup_number"],
+            "base_position" : obj_["lev_markup_number"],
+          ];
+          the_table_of_contents_section["seg"] ~=
+            set_abstract_object.contents_para(
+              "toc",
+              toc_txt_,
+              "",                   // attrib
+              0,
+              indent,
+              false
+            );
+          break;
+        case 5: .. case 7:
+          toc_txt_ = format(
+            "{ %s }../%s.fn_suffix#%s",
+            heading_toc_,
+            segment_object_belongs_to,
+            obj_cite_number,
+          );
+          indent=[
+            "hang_position" : obj_["lev_markup_number"],
+            "base_position" : obj_["lev_markup_number"],
+          ];
+          the_table_of_contents_section["seg"] ~=
+            set_abstract_object.contents_para(
+              "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) {
@@ -2639,15 +2899,25 @@ template SiSUdocAbstraction() {
         auto set_abstract_object = ObjectAbstractSet();
         auto mainkeys =
           bookindex_unordered_hashes.byKey.array.sort().release;
-        string bi_tmp;
-        ObjComposite[] bookindex_section;
+        string bi_tmp_seg, bi_tmp_scroll;
+        ObjComposite[][string] bookindex_section;
         // writeln(mainkeys.length);
         // B~ Book Index
         attrib="";
         lev="B";
         lev_markup_number="1";
         lev_collapsed_number="1";
-        bookindex_section ~=
+        bookindex_section["scroll"] ~=
+          set_abstract_object.contents_heading(
+            "Book Index",
+            attrib,
+            obj_cite_number,
+            [],
+            to!string(lev),
+            to!int(lev_markup_number),
+            to!int(lev_collapsed_number)
+          );
+        bookindex_section["seg"] ~=
           set_abstract_object.contents_heading(
             "Book Index",
             attrib,
@@ -2664,7 +2934,17 @@ template SiSUdocAbstraction() {
         lev="1";
         lev_markup_number="4";
         lev_collapsed_number="2";
-        bookindex_section ~=
+        bookindex_section["scroll"] ~=
+          set_abstract_object.contents_heading(
+            "Index",
+            attrib,
+            obj_cite_number,
+            ["book_index"],
+            to!string(lev),
+            to!int(lev_markup_number),
+            to!int(lev_collapsed_number)
+          );
+        bookindex_section["seg"] ~=
           set_abstract_object.contents_heading(
             "Index",
             attrib,
@@ -2677,35 +2957,43 @@ template SiSUdocAbstraction() {
         ++obj_cite_number;
         ++mkn;
         foreach (mainkey; mainkeys) {
-          bi_tmp = "!{" ~ mainkey ~ "}! ";
+          bi_tmp_scroll = "!{" ~ mainkey ~ "}! ";
+          bi_tmp_seg = "!{" ~ mainkey ~ "}! ";
           // bi_tmp = "_0_1 !{" ~ mainkey ~ "}! ";
           foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
             auto go = replaceAll(ref_, rgx.book_index_go, "$1");
-            bi_tmp ~= (segment_object_belongs_to.empty)
+            bi_tmp_scroll ~= (" {" ~ ref_ ~ "}#" ~ go ~ ", ");
+            bi_tmp_seg ~= (segment_object_belongs_to.empty)
             ? (" {" ~ ref_ ~ "}#" ~ go ~ ", ")
-            : (" {" ~ ref_ ~ "}[../" ~ segment_object_belongs_to ~ ".fn_suffix]#" ~ go ~ ", ");
+            : (" {" ~ ref_ ~ "}../" ~ segment_object_belongs_to ~ ".fn_suffix#" ~ go ~ ", ");
           }
-          bi_tmp ~= " \\\\\n    ";
+          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 ~= subkey ~ ", ";
+            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 ~= (segment_object_belongs_to.empty)
+              bi_tmp_scroll ~= (" {" ~ ref_ ~ "}#" ~ go ~ ", ");
+              bi_tmp_seg ~= (segment_object_belongs_to.empty)
               ? (" {" ~ ref_ ~ "}#" ~ go ~ ", ")
-              : (" {" ~ ref_ ~ "}[../" ~ segment_object_belongs_to ~ ".fn_suffix]#" ~ go ~ ", ");
+              : (" {" ~ ref_ ~ "}../" ~ segment_object_belongs_to ~ ".fn_suffix#" ~ go ~ ", ");
             }
-            bi_tmp ~= " \\\\\n    ";
+            bi_tmp_scroll ~= " \\\\\n    ";
+            bi_tmp_seg ~= " \\\\\n    ";
             ++skn;
           }
-          bi_tmp = replaceFirst(bi_tmp, rgx.trailing_linebreak, "");
+          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";
-          indent["base_position"] = "1";
-          attrib="";
+          indent=[
+            "hang_position" : "0",
+            "base_position" : "1",
+          ];
           // bookindex_section ~=
           //   set_abstract_object.contents_para(
           //     obj,
@@ -2713,10 +3001,19 @@ template SiSUdocAbstraction() {
           //     indent,
           //     false
           //   );
-          bookindex_section ~=
+          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,
+              bi_tmp_seg,
               attrib,
               obj_cite_number,
               indent,
@@ -2730,7 +3027,7 @@ template SiSUdocAbstraction() {
       }
     }
     struct NotesSection {
-      string object_notes;
+      string[string] object_notes;
       long previous_count;
       int mkn;
       auto rgx = Rgx();
@@ -2758,15 +3055,22 @@ template SiSUdocAbstraction() {
         rgx.inline_notes_delimiter_al_regular_number_note)) {
           debug(endnotes_build) {
             writeln(
-              "{^{", m.captures[1], ".}^}[../", segment_object_belongs_to, ".fn_suffix]#noteref_\n  ", m.captures[1], " ",
+              "{^{", m.captures[1], ".}^}../", segment_object_belongs_to, ".fn_suffix#noteref_\n  ", m.captures[1], " ",
               m.captures[2]); // sometimes need segment name (segmented html & epub)
             // writeln("{^{", m.captures[1], ".}^}#", contents_am[counter]["obj_cite_number"], " ", m.captures[2]);
           }
-          object_notes ~= (segment_object_belongs_to.empty)
+          // TODO NEXT you need anchor for segments at this point ->
+          object_notes["seg"] ~=
+            "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~
+            m.captures[1] ~ " " ~ m.captures[2] ~ "』";
+          object_notes["seg"] ~= (segment_object_belongs_to.empty)
           ? ("{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~
             m.captures[1] ~ " " ~ m.captures[2] ~ "』")
-          : ("{^{" ~ m.captures[1] ~ ".}^}[../" ~ segment_object_belongs_to ~ ".fn_suffix]#noteref_" ~
+          : ("{^{" ~ m.captures[1] ~ ".}^}../" ~ segment_object_belongs_to ~ ".fn_suffix#noteref_" ~
             m.captures[1] ~ " " ~ m.captures[2] ~ "』");
+          object_notes["scroll"] ~=
+            "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~
+            m.captures[1] ~ " " ~ m.captures[2] ~ "』";
         }
         return object_notes;
       }
@@ -2774,9 +3078,13 @@ template SiSUdocAbstraction() {
       in {
       }
       body {
-        string[] endnotes_;
+        string[][string] endnotes_;
         if (object_notes.length > 1) {
-          endnotes_ = (split(object_notes, rgx.break_string))[0..$-1];
+          endnotes_["seg"] = (split(object_notes["seg"], rgx.break_string))[0..$-1];
+          endnotes_["scroll"] = (split(object_notes["scroll"], rgx.break_string))[0..$-1];
+        } else {
+          endnotes_["seg"] = [];
+          endnotes_["scroll"] = [];
         }
         return endnotes_;
       }
@@ -2785,7 +3093,7 @@ template SiSUdocAbstraction() {
       }
       body {
         auto set_abstract_object = ObjectAbstractSet();
-        ObjComposite[] endnotes_section;
+        ObjComposite[][string] the_endnotes_section;
         auto endnotes_ = gathered_notes();
         // auto endnotes_ = (split(object_notes, rgx.break_string))[0..$-1];
         string type;
@@ -2797,7 +3105,17 @@ template SiSUdocAbstraction() {
         lev="B";
         lev_markup_number="1";
         lev_collapsed_number="1";
-        endnotes_section ~=
+        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)
+          );
+        the_endnotes_section["scroll"] ~=
           set_abstract_object.contents_heading(
             "Endnotes",
             attrib,
@@ -2814,7 +3132,17 @@ template SiSUdocAbstraction() {
         lev="1";
         lev_markup_number="4";
         lev_collapsed_number="2";
-        endnotes_section ~=
+        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)
+          );
+        the_endnotes_section["scroll"] ~=
           set_abstract_object.contents_heading(
             "Endnotes",
             attrib,
@@ -2826,7 +3154,7 @@ template SiSUdocAbstraction() {
           );
         ++obj_cite_number;
         ++mkn;
-        foreach (endnote; endnotes_) {
+        foreach (endnote; endnotes_["seg"]) {
           attrib="";
           // endnotes ~=
           //   set_abstract_object.contents_para(
@@ -2835,13 +3163,15 @@ template SiSUdocAbstraction() {
           //     indent,
           //     false
           //   );
-          endnotes_section ~=
-            set_abstract_object.contents_endnote(
-              endnote,
-            );
-          ++mkn;
+          the_endnotes_section["seg"] ~=
+            set_abstract_object.contents_endnote(endnote);
+        }
+        foreach (endnote; endnotes_["scroll"]) {
+          attrib="";
+          the_endnotes_section["scroll"] ~=
+            set_abstract_object.contents_endnote(endnote);
         }
-        auto t = tuple(endnotes_section, obj_cite_number);
+        auto t = tuple(the_endnotes_section, obj_cite_number);
         return t;
       }
     }
diff --git a/src/sdp/ao_conf_make_meta_native.d b/src/sdp/ao_conf_make_meta_native.d
index 1242565..0fdee40 100644
--- a/src/sdp/ao_conf_make_meta_native.d
+++ b/src/sdp/ao_conf_make_meta_native.d
@@ -278,7 +278,7 @@ template SiSUheaderExtractNative() {
       auto dochead_meta = meta_aa;
       auto set_header = HeaderDocMetadataAndMakeNativeToAA();
       char[][] source_header_arr =
-        split(cast(char[]) src_header, rgx.line_delimiter);
+        split(cast(char[]) src_header, rgx.newline_eol_delimiter);
       foreach(header_line; source_header_arr) {
         if (auto m = matchFirst(header_line, rgx.comment)) {
           /+ matched comment +/
diff --git a/src/sdp/ao_conf_make_meta_sdlang.d b/src/sdp/ao_conf_make_meta_sdlang.d
index 3855e7c..a53cbd7 100644
--- a/src/sdp/ao_conf_make_meta_sdlang.d
+++ b/src/sdp/ao_conf_make_meta_sdlang.d
@@ -211,7 +211,7 @@ template SiSUheaderExtractSDLang() {
     }
     private auto headerSDLangGet(in char[] src_header) {
       char[][] source_header_arr =
-        split(cast(char[]) src_header, rgx.line_delimiter);
+        split(cast(char[]) src_header, rgx.newline_eol_delimiter);
       char[] header_clean;
       // TODO
       foreach(header_line; source_header_arr) {
@@ -236,6 +236,31 @@ template SiSUheaderExtractSDLang() {
     private auto headerSDLangToAAmake(Tag header_sdlang, string[string][string] dochead_make) {
       dochead_make = sdlangToAAmake(dochead_make, header_sdlang);
       auto dochead_meta = sdlangToAAmake(meta_aa, header_sdlang);
+      if (dochead_meta["title"]["main"].empty) {
+        dochead_meta["title"]["main"] =
+          to!string(header_sdlang.maybe.tags["title"][0].values[0]); // test that this exists
+      }
+      if (!(dochead_meta["title"]["subtitle"].empty)
+      && (dochead_meta["title"]["sub"].empty)) {
+        dochead_meta["title"]["sub"] ~= dochead_meta["title"]["subtitle"];
+      }
+      dochead_meta["title"].remove("subtitle");
+      if (dochead_meta["title"]["sub"].empty) {
+        dochead_meta["title"]["full"] ~= dochead_meta["title"]["main"];
+      } else {
+        dochead_meta["title"]["full"] ~= format(
+          "%s - %s",
+          dochead_meta["title"]["main"],
+          dochead_meta["title"]["sub"],
+        );
+      }
+      dochead_meta["creator"]["author_raw"] = dochead_meta["creator"]["author"];
+      string[] authors_arr;
+      auto authors_raw_arr = split(dochead_meta["creator"]["author"], rgx.arr_delimiter);
+      foreach (author_raw; authors_raw_arr) {
+        authors_arr ~= replace(author_raw, rgx.raw_author_munge, "$2 $1");
+      }
+      dochead_meta["creator"]["author"] = join(authors_arr, ", ").chomp.chomp;
       auto t = tuple(dochead_make, dochead_meta);
       static assert(t.length==2);
       return t;
diff --git a/src/sdp/ao_defaults.d b/src/sdp/ao_defaults.d
index 8db42e2..d9f0b18 100644
--- a/src/sdp/ao_defaults.d
+++ b/src/sdp/ao_defaults.d
@@ -138,7 +138,8 @@ template SiSUregisters() {
         "language"          : "",
         "main"              : "",
         "note"              : "",
-        "sub"               : ""
+        "sub"               : "",
+        "subtitle"          : ""
       ]
     ];
     return meta_;
diff --git a/src/sdp/ao_object_setter.d b/src/sdp/ao_object_setter.d
index 35ad0ff..4996452 100644
--- a/src/sdp/ao_object_setter.d
+++ b/src/sdp/ao_object_setter.d
@@ -92,8 +92,8 @@ template ObjectSetter() {
       object_set.obj_cite_number          = (obj_cite_number==0) ? "" : to!string(obj_cite_number);
       object_set.para_attrib.indent_start = 0; // indent["hang_position"];
       object_set.para_attrib.indent_rest  = 0; // indent["base_position"];
-      object_set.para_attrib.bullet       = false;
-      // object_set.node_structure.node               = _node;
+      object_set.para_attrib.bullet       = false; // bullet;
+      // object_set.node_structure.node   = _node;
       return object_set;
     }
     auto contents_endnote(
diff --git a/src/sdp/ao_output_debugs.d b/src/sdp/ao_output_debugs.d
index 1de30fc..7ff68ce 100644
--- a/src/sdp/ao_output_debugs.d
+++ b/src/sdp/ao_output_debugs.d
@@ -379,7 +379,10 @@ template SiSUoutputDebugs() {
           }
         }
         writefln(
-          "%s\n%s\n%s%s\n%s%s\n%s%s\n%s:%s",
+          "%s\n\"%s\", %s\n%s\n%s\n%s%s\n%s%s\n%s%s\n%s:%s",
+          "-------------------------------",
+          dochead_meta["title"]["full"],
+          dochead_meta["creator"]["author"],
           "-------------------------------",
           fn_src,
           "length contents array: ",
diff --git a/src/sdp/ao_read_source_files.d b/src/sdp/ao_read_source_files.d
index 3ceedd0..793a45a 100644
--- a/src/sdp/ao_read_source_files.d
+++ b/src/sdp/ao_read_source_files.d
@@ -93,7 +93,7 @@ template SiSUmarkupRaw() {
     }
     final private char[][] markupSourceLineArray(in char[] src_text) {
       char[][] source_line_arr =
-        split(cast(char[]) src_text, rgx.line_delimiter);
+        split(cast(char[]) src_text, rgx.newline_eol_strip_preceeding);
       return source_line_arr;
     }
     auto markupSourceReadIn(in string fn_src) {
diff --git a/src/sdp/ao_rgx.d b/src/sdp/ao_rgx.d
index f65abb5..81a06b9 100644
--- a/src/sdp/ao_rgx.d
+++ b/src/sdp/ao_rgx.d
@@ -15,13 +15,14 @@ template RgxInit() {
     static book_index_go             = ctRegex!("([0-9]+)(?:-[0-9]+)?");
     static trailing_comma            = ctRegex!(",[ ]*$");
     static trailing_linebreak        = ctRegex!(",[ ]{1,2}\\\\\\\\\n[ ]{4}$","m");
-    static line_delimiter            = ctRegex!("\n");
-    static line_delimiter_ws_strip   = ctRegex!("[ ]*\n[ ]*");
-    static line_delimiter_only       = ctRegex!("^\n");
-    static para_delimiter            = ctRegex!("\n[ ]*\n+");
-    static levels_markup             = ctRegex!(`^[A-D1-4]$`);
-    static levels_numbered           = ctRegex!(`^[0-9]$`);
-    static levels_numbered_headings  = ctRegex!(`^[0-7]$`);
+    static newline_eol_delimiter     = ctRegex!("\n");
+    static newline_eol_strip_preceeding = ctRegex!("[ ]*\n");
+    static newline_eol_delimiter_only   = ctRegex!("^\n");
+    static line_delimiter_ws_strip      = ctRegex!("[ ]*\n[ ]*");
+    static para_delimiter               = ctRegex!("\n[ ]*\n+");
+    static levels_markup                = ctRegex!(`^[A-D1-4]$`);
+    static levels_numbered              = ctRegex!(`^[0-9]$`);
+    static levels_numbered_headings     = ctRegex!(`^[0-7]$`);
     static src_pth                   = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])$`);
     static src_fn                    =
       ctRegex!(`^([a-zA-Z0-9._-]+/)*(?P<fn_src>(?P<fn_base>[a-zA-Z0-9._-]+)[.](?P<fn_src_suffix>ss[tm]))$`);
@@ -49,7 +50,8 @@ template RgxInit() {
     // static native_header_sub                = ctRegex!(`^[ ]+:([a-z_]+):\s`);
     static native_header_meta_title         = ctRegex!(`^@title:\s`, "m");
     static variable_doc_title               = ctRegex!(`@title`);
-    static variable_doc_author              = ctRegex!(`@author`);
+    static variable_doc_author              = ctRegex!(`@author|@creator`);
+    static raw_author_munge                 = ctRegex!(`(\S.+?),\s+(.+)`,"i");
     /+ head +/
     static native_subhead_creator           = ctRegex!(`^(?:author|translator|illustrator)$`, "m");
     static native_subhead_title             = ctRegex!(`^(?:main|sub(?:title)?|full|language|edition|note)$`, "m");
@@ -63,7 +65,7 @@ template RgxInit() {
     static native_subhead_make              = ctRegex!(`^(?:cover_image|home_button_image|home_button_text|footer|headings|num_top|num_depth|breaks|substitute|bold|italics|emphasis|texpdf_font|css)$`, "m");
     /+ heading & paragraph operators +/
     static heading_a          = ctRegex!(`^:?[A][~] `, "m");
-    static heading            = ctRegex!(`^:?([A-D1-4])[~]([a-z0-9_.-]*[?]?) `);
+    static heading            = ctRegex!(`^:?([A-D1-4])[~]([a-z0-9_.-]*[?]?)\s+`,"i");
     static heading_marker     = ctRegex!(`^:?([A-D1-4])[~]`);
     static heading_anchor_tag = ctRegex!(`^:?[A-D1-4][~]([a-z0-9_.-]+) `,"i");
     static heading_identify_anchor_tag = ctRegex!(`^:?[A-D1-4][~]\s+(?:(?:(?:chapter|article|section|clause)\s+[0-9.]+)|(?:[0-9]+))`,"i"); // unless dob.obj =~/^:?[A-D1-4]~\s+(?:|(?:chapter|article|section|clause)\s+)([0-9.]+)/i
diff --git a/src/sdp/output_html.d b/src/sdp/output_html.d
index 38eadf0..dc19e6c 100644
--- a/src/sdp/output_html.d
+++ b/src/sdp/output_html.d
@@ -1,17 +1,5 @@
 template SiSUoutputHTML() {
   struct SDPoutputHTML {
-    auto html_toc(O)(
-      auto ref const O         obj,
-    ) {
-      string o;
-      o = format(q"◎<h%s class="toc"><a href="#%s">%s</a></h%s>◎",
-      obj.heading_attrib.lev_markup_number,
-      obj.obj_cite_number,
-      obj.object,
-      obj.heading_attrib.lev_markup_number
-      );
-      return o;
-    }
     auto html_heading(O)(
       auto ref const O         obj,
     ) {
@@ -100,6 +88,7 @@ template SiSUoutputHTML() {
     }
     void scroll(C)(
       auto ref const C         contents,
+      string[]                 document_parts,
       string[][string][string] bookindex_unordered_hashes,
       JSONValue[]              biblio,
       string[string][string]   dochead_make,
@@ -111,47 +100,48 @@ template SiSUoutputHTML() {
       string[] toc;
       string[] body_;
       string[] doc;
-      foreach (obj; contents) {
-        if (obj.use == "content") {
-          switch (obj.is_a) {
-          case "heading":
-            toc ~= html_toc(obj);
-            body_ ~= html_heading(obj);
-            break;
-          case "para":
-            body_ ~= html_para(obj);
-            break;
-          case "verse":
-            body_ ~= html_para(obj);
-            // body_ ~= html_verse(obj);
-            break;
-          case "group":
-            body_ ~= html_para(obj);
-            // body_ ~= html_group(obj);
-            break;
-          case "block":
-            body_ ~= html_para(obj);
-            // body_ ~= html_block(obj);
-            break;
-          case "quote":
-            body_ ~= html_para(obj);
-            // body_ ~= html_quote(obj);
-            break;
-          case "table":
-            body_ ~= html_para(obj);
-            // body_ ~= html_table(obj);
-            break;
-          case "code":
-            body_ ~= html_para(obj);
-            // body_ ~= html_code(obj);
-            break;
-          default:
-            body_ ~= html_para(obj);
-            break;
+      foreach (part; document_parts) {
+        foreach (obj; contents[part]) {
+          if (obj.use == "content") {
+            switch (obj.is_a) {
+            case "heading":
+              body_ ~= html_heading(obj);
+              break;
+            case "para":
+              body_ ~= html_para(obj);
+              break;
+            case "verse":
+              body_ ~= html_para(obj);
+              // body_ ~= html_verse(obj);
+              break;
+            case "group":
+              body_ ~= html_para(obj);
+              // body_ ~= html_group(obj);
+              break;
+            case "block":
+              body_ ~= html_para(obj);
+              // body_ ~= html_block(obj);
+              break;
+            case "quote":
+              body_ ~= html_para(obj);
+              // body_ ~= html_quote(obj);
+              break;
+            case "table":
+              body_ ~= html_para(obj);
+              // body_ ~= html_table(obj);
+              break;
+            case "code":
+              body_ ~= html_para(obj);
+              // body_ ~= html_code(obj);
+              break;
+            default:
+              body_ ~= html_para(obj);
+              break;
+            }
           }
         }
       }
-      doc = scroll_head ~ toc ~ body_ ~ scroll_tail;
+      doc = scroll_head ~ body_ ~ scroll_tail;
       auto m = matchFirst(fn_src, rgx.src_fn);
       auto fn = m["fn_base"] ~ ".html";
       auto pth_html = "en/html";
diff --git a/src/sdp/output_hub.d b/src/sdp/output_hub.d
index e7c0c9e..336e7b3 100644
--- a/src/sdp/output_hub.d
+++ b/src/sdp/output_hub.d
@@ -14,6 +14,7 @@ template SiSUoutputHub() {
       bool[string]             opt_action_bool
     ) {
       auto rgx = Rgx();
+      string[] document_parts;
       if (opt_action_bool["source"]) {
         writeln("sisupod source");
       }
@@ -28,8 +29,25 @@ template SiSUoutputHub() {
       if (opt_action_bool["html"]) {
         mixin SiSUoutputHTML;
         auto html=SDPoutputHTML();
+        document_parts = [
+          "head",
+          "toc_scroll",
+          "body",
+          "endnotes_scroll",
+          "bibliography",
+          "bookindex_scroll"
+        ];
         html.css_write;
-        html.scroll(contents, bookindex_unordered_hashes, biblio, dochead_make, dochead_meta, fn_src, opt_action_bool);
+        html.scroll(
+          contents,
+          document_parts,
+          bookindex_unordered_hashes,
+          biblio,
+          dochead_make,
+          dochead_meta,
+          fn_src,
+          opt_action_bool
+        );
       }
       if (opt_action_bool["epub"]) {
         writeln("epub processing");
diff --git a/views/version.txt b/views/version.txt
index 077a941..4ac5253 100644
--- a/views/version.txt
+++ b/views/version.txt
@@ -4,4 +4,4 @@ struct Version {
   int minor;
   int patch;
 }
-enum ver = Version(0, 7, 3);
+enum ver = Version(0, 8, 0);
-- 
cgit v1.2.3