From d542315e97260128706af55652964f18e9fdc4bb Mon Sep 17 00:00:00 2001
From: Ralph Amissah <ralph.amissah@gmail.com>
Date: Sun, 23 Jun 2019 14:01:43 -0400
Subject: harvests reorganized; adjustments: output, paths

---
 org/default_misc.org                           |   2 +-
 org/default_paths.org                          | 180 ++++-
 org/doc_reform.org                             | 855 +---------------------
 org/output_harvest_metadata.org                | 970 +++++++++++++++++++++++++
 src/doc_reform/doc_reform.d                    |  10 +
 src/doc_reform/meta/defaults.d                 |   2 +-
 src/doc_reform/meta/metadoc_harvest.d          |   7 +-
 src/doc_reform/meta/metadoc_harvests_authors.d | 143 +++-
 src/doc_reform/meta/metadoc_harvests_topics.d  | 143 +++-
 src/doc_reform/output/paths_output.d           | 154 +++-
 src/doc_reform/source/paths_source.d           |  13 +
 11 files changed, 1531 insertions(+), 948 deletions(-)
 create mode 100644 org/output_harvest_metadata.org

diff --git a/org/default_misc.org b/org/default_misc.org
index 18bacfa..7090c02 100644
--- a/org/default_misc.org
+++ b/org/default_misc.org
@@ -148,7 +148,7 @@ template DocReformHarvest() {
         string   uid                  = "";
         string   date_published       = "";
         string[] topic_register_arr   = [];
-        string   path_html_seg        = "";
+        string   path_html_segtoc     = "";
         string   path_html_scroll     = "";
         string   path_epub            = "";
         string   url_html_seg         = "";
diff --git a/org/default_paths.org b/org/default_paths.org
index 7bf838e..dba021f 100644
--- a/org/default_paths.org
+++ b/org/default_paths.org
@@ -252,6 +252,19 @@ template PathMatters() {
             }
             return _uid;
           }
+          string doc_uid_out() {
+            string _uid;
+            if (is_pod && !(pod_name_with_path.empty)) {
+              if (pod_name_with_path.baseName == filename_base) {
+                _uid = filename_base ~ "." ~ lng;
+              } else {
+                _uid = pod_name_with_path.baseName ~ mkup.sep ~ filename_base ~ "." ~ lng;
+              }
+            } else {
+              _uid = "_" ~ filename_base ~ "." ~ lng;
+            }
+            return _uid;
+          }
           string docname_composite_unique_per_src_doc() {
             string _fn;
             if (pod_name_with_path.baseName == filename_base) {
@@ -938,13 +951,12 @@ import doc_reform.meta.rgx;
 template DocReformOutPaths() {
   auto DocReformOutPaths(Po,Lng)(
     Po  output_pth_root,
-    Lng lng,
+    Lng lng = "",
   ) {
     struct _PathsStruct {
       string output_root() {
         return (output_pth_root.length > 0)
-        ? output_pth_root
-        : "sisugen";
+        ? output_pth_root : "";
       }
       string output_base() {
         return asNormalizedPath(output_root.chainPath(lng)).array;
@@ -960,8 +972,7 @@ template DocReformOutPathSQLite() {
     struct _PathsStruct {
       string output_root() {
         return (output_pth_root.length > 0)
-        ? output_pth_root
-        : "sisugen";
+        ? output_pth_root : "";
       }
       string output_base() {
         return asNormalizedPath(output_root).array;
@@ -1057,31 +1068,38 @@ template DocReformPathsUrl() {
 #+END_SRC
 
 ** _html_                                                               :html:
+*** relative
 
 #+name: template_paths_html
 #+BEGIN_SRC d
-template DocReformPathsHTML() {
+template DocReformDocRootTreeHTML() {
   mixin DocReformRgxInit;
   static auto rgx = Rgx();
-  auto DocReformPathsHTML(Po,Lng)(
-    Po  output_pth_root,
-    Lng lng,
-  ) {
-    auto out_pth = DocReformOutPaths!()(output_pth_root, lng);
+  auto DocReformDocRootTreeHTML(Lng)(Lng lng) {
+    auto lng_pth = DocReformOutPaths!()("", lng);
     string base_dir = "html";
     string suffix = ".html";
     struct _PathsStruct {
       string base_filename(string fn_src) {
         return fn_src.baseName.stripExtension;
       }
+      string base_filename_scroll(string fn_src) {
+        return base_filename(fn_src) ~ "." ~ lng;
+      }
+      string base_filename_seg(string fn_src) {
+        return base_filename(fn_src) ~ "." ~ lng;
+      }
+      string docroot() {
+        return asNormalizedPath(lng_pth.output_root).array;
+      }
       string base() {
-        return asNormalizedPath((out_pth.output_base).chainPath(base_dir)).array;
+        return asNormalizedPath((lng).chainPath(base_dir)).array;
       }
       string image() {
-        return asNormalizedPath((out_pth.output_root).chainPath("image")).array;
+        return asNormalizedPath("image").array;
       }
       string css() {
-        return asNormalizedPath((out_pth.output_root).chainPath("css")).array;
+        return asNormalizedPath("css").array;
       }
       string fn_seg_css() {
         return asNormalizedPath(css.chainPath("html_seg.css")).array;
@@ -1090,19 +1108,19 @@ template DocReformPathsHTML() {
         return asNormalizedPath(css.chainPath("html_scroll.css")).array;
       }
       string seg(string fn_src) {
-        return asNormalizedPath(base.chainPath(base_filename(fn_src))).array;
+        return asNormalizedPath(base.chainPath(base_filename_seg(fn_src))).array;
       }
       string fn_scroll(string fn_src) {
-        return asNormalizedPath(base.chainPath(base_filename(fn_src) ~ suffix)).array;
+        return asNormalizedPath(base.chainPath(base_filename_scroll(fn_src) ~ suffix)).array;
       }
       string fn_seg(string fn_src, string seg_filename) {
         return asNormalizedPath(seg(fn_src).chainPath(seg_filename ~ suffix)).array;
       }
       string tail_seg(string fn_src) {
-        return lng ~ "/html/" ~ base_filename(fn_src);
+        return lng ~ "/html/" ~ base_filename_seg(fn_src);
       }
       string tail_fn_scroll(string fn_src) {
-        return lng ~ "/html/" ~ base_filename(fn_src) ~ suffix;
+        return lng ~ "/html/" ~ base_filename_scroll(fn_src) ~ suffix;
       }
       string tail_fn_seg(string fn_src, string seg_filename) {
         return lng ~ "/html/" ~ seg(fn_src) ~ "/" ~ seg_filename ~ suffix;
@@ -1113,6 +1131,126 @@ template DocReformPathsHTML() {
 }
 #+END_SRC
 
+*** absolute
+
+#+name: template_paths_html
+#+BEGIN_SRC d
+template DocReformPathsHTML() {
+  mixin DocReformRgxInit;
+  static auto rgx = Rgx();
+  auto DocReformPathsHTML(Po,Lng)(
+    Po  root_pth,
+    Lng lng,
+  ) {
+    auto doc_tree = DocReformDocRootTreeHTML!()(lng);
+    string base_dir = "html";
+    string suffix = ".html";
+    struct _PathsStruct {
+      string docroot() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.docroot)).array;
+      }
+      string harvest(string fn_harvest) {
+        return docroot ~ "/" ~ fn_harvest;
+      }
+      string base() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.base)).array;
+      }
+      string image() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.image)).array;
+      }
+      string css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.css)).array;
+      }
+      string fn_seg_css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_seg_css)).array;
+      }
+      string fn_scroll_css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_scroll_css)).array;
+      }
+      string seg(string fn_src) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.seg(fn_src))).array;
+      }
+      string fn_scroll(string fn_src) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_scroll(fn_src))).array;
+      }
+      string fn_seg(string fn_src, string seg_filename) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_seg(fn_src, seg_filename))).array;
+      }
+      string tail_seg(string fn_src) {
+        return doc_tree.tail_seg(fn_src);
+      }
+      string tail_fn_scroll(string fn_src) {
+        return doc_tree.tail_fn_scroll(fn_src);
+      }
+      string tail_fn_seg(string fn_src, string seg_filename) {
+        return doc_tree.tail_fn_seg(fn_src, seg_filename);
+      }
+    }
+    return _PathsStruct();
+  }
+}
+#+END_SRC
+
+*** urls
+
+#+name: template_paths_html
+#+BEGIN_SRC d
+template DocReformUrlPathsHTML() {
+  mixin DocReformRgxInit;
+  static auto rgx = Rgx();
+  auto DocReformUrlPathsHTML(Po,Lng)(
+    Po  root_pth,
+    Lng lng,
+  ) {
+    auto doc_tree = DocReformDocRootTreeHTML!()(lng);
+    string base_dir = "html";
+    string suffix = ".html";
+    struct _PathsStruct {
+      string docroot() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.docroot)).array;
+      }
+      string harvest(string fn_harvest) {
+        return docroot ~ "/" ~ fn_harvest;
+      }
+      string base() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.base)).array;
+      }
+      string image() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.image)).array;
+      }
+      string css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.css)).array;
+      }
+      string fn_seg_css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_seg_css)).array;
+      }
+      string fn_scroll_css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_scroll_css)).array;
+      }
+      string seg(string fn_src) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.seg(fn_src))).array;
+      }
+      string fn_scroll(string fn_src) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_scroll(fn_src))).array;
+      }
+      string fn_seg(string fn_src, string seg_filename) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_seg(fn_src, seg_filename))).array;
+      }
+      string tail_seg(string fn_src) {
+        return doc_tree.tail_seg(fn_src);
+      }
+      string tail_fn_scroll(string fn_src) {
+        return doc_tree.tail_fn_scroll(fn_src);
+      }
+      string tail_fn_seg(string fn_src, string seg_filename) {
+        return doc_tree.tail_fn_seg(fn_src, seg_filename);
+      }
+    }
+    return _PathsStruct();
+  }
+}
+#+END_SRC
+
 ** _epub_                                                               :epub:
 
 #+name: template_paths_epub
@@ -1131,7 +1269,7 @@ template DocReformPathsEPUB() {
         return asNormalizedPath((out_pth.output_base).chainPath(base_dir)).array;
       }
       string base_filename(string fn_src) {
-        return fn_src.baseName.stripExtension;
+        return fn_src.baseName.stripExtension ~ "." ~ lng;
       }
       string epub_file(string fn_src) {
         return asNormalizedPath(base.chainPath(base_filename(fn_src) ~ ".epub")).array;
@@ -1235,12 +1373,12 @@ template DocReformPathsODT() {
         return asNormalizedPath((out_pth.output_base).chainPath(base_dir)).array;
       }
       string odt_file() {
-        return asNormalizedPath(base_pth.chainPath(doc_matters.src.filename_base ~ ".odt")).array;
+        return asNormalizedPath(base_pth.chainPath(doc_matters.src.doc_uid_out ~ ".odt")).array;
       }
       string dirtop(string type) {
         return (type == "zip")
         ? "".chainPath("").array
-        : asNormalizedPath(base_pth.chainPath(doc_matters.src.filename_base)).array;
+        : asNormalizedPath(base_pth.chainPath(doc_matters.src.doc_uid_out)).array;
       }
       string mimetype(string type="fs") {
         assert(type == "zip" || "fs");
diff --git a/org/doc_reform.org b/org/doc_reform.org
index 4d39e53..798d680 100644
--- a/org/doc_reform.org
+++ b/org/doc_reform.org
@@ -124,6 +124,16 @@ void main(string[] args) {
     if (_opt_action.harvest_authors) {
       DocReformMetaDocHarvestsAuthors!()(hvst.harvests, _opt_action);
     }
+    if (!(_opt_action.quiet)) {
+      import doc_reform.output.paths_output;
+      auto out_pth = DocReformPathsHTML!()(_opt_action.output_dir_set, "");
+      if (_opt_action.harvest_authors) {
+        writeln("- ", out_pth.harvest("authors.html"));
+      }
+      if (_opt_action.harvest_topics) {
+        writeln("- ", out_pth.harvest("topics.html"));
+      }
+    }
   }
 }
 #+END_SRC
@@ -1184,6 +1194,12 @@ if ((_opt_action.debug_do)
 ) {
   writeln("step4 commence → (doc_matters)");
 }
+#+END_SRC
+
+**** DocumentMatters struct {
+
+#+NAME: doc_reform_each_file_do_document_matters
+#+BEGIN_SRC d
 struct DocumentMatters {
 #+END_SRC
 
@@ -1397,845 +1413,6 @@ struct DocumentMattersAbridged {
 }
 #+END_SRC
 
-* 3. document abstraction _summary_         :module:doc_reform:metadoc_summary:
-** 0. module template metadoc summary
-- document summary from abstraction
-
-#+BEGIN_SRC d :tangle "../src/doc_reform/meta/metadoc_summary.d"
-module doc_reform.meta.metadoc_summary;
-template DocReformMetaDocSummary() {
-  void DocReformMetaDocSummary(S,T)(
-    const S  doc_abstraction,
-          T  doc_matters,
-  ) {
-    <<metadoc_summary_imports>>
-    mixin InternalMarkup;
-    <<metadoc_summary_initialize>>
-    if (doc_matters.opt.action.verbose) {
-      <<meta_metadoc_summary_document>>
-    }
-  }
-}
-#+END_SRC
-
-** init
-*** imports
-
-#+name: metadoc_summary_imports
-#+BEGIN_SRC d
-import
-  doc_reform.meta.defaults,
-  doc_reform.meta.rgx;
-import
-  std.array,
-  std.exception,
-  std.regex,
-  std.stdio,
-  std.string,
-  std.traits,
-  std.typecons,
-  std.uni,
-  std.utf,
-  std.conv : to;
-#+END_SRC
-
-*** initialize                                                     :report:
-
-#+name: metadoc_summary_initialize
-#+BEGIN_SRC d
-auto markup = InlineMarkup();
-#+END_SRC
-
-** (last ocn)
-
-#+name: meta_metadoc_summary_document
-#+BEGIN_SRC d
-string[string] check = [
-  "last_object_number" : "NA [debug \"checkdoc\" not run]",
-  "last_object_number_body"  : "0",
-  "last_object_number_book_index" : "0",
-];
-foreach (k; doc_matters.has.keys_seq.seg) {
-  foreach (obj; doc_abstraction[k]) {
-    if (obj.metainfo.is_of_part != "empty") {
-      if (!empty(obj.metainfo.object_number)) {
-        if (k == "body") {
-          check["last_object_number_body"] = obj.metainfo.object_number;
-        }
-        if (!(obj.metainfo.object_number.empty)) {
-          check["last_object_number"] = obj.metainfo.object_number;
-        }
-      }
-      if (k == "bookindex") {
-        if (obj.metainfo.object_number_type == 2) {
-          check["last_object_number_book_index"] = obj.metainfo.object_number_book_index;
-        }
-      }
-    }
-  }
-}
-#+END_SRC
-
-** document summary
-
-#+name: meta_metadoc_summary_document
-#+BEGIN_SRC d
-auto min_repeat_number = 66;
-auto char_repeat_number = (doc_matters.conf_make_meta.meta.title_full.length
-  + doc_matters.conf_make_meta.meta.creator_author.length + 4);
-char_repeat_number = (char_repeat_number > min_repeat_number)
-? char_repeat_number
-: min_repeat_number;
-writefln(
-  "%s\n\"%s\", %s\n%s\n%s\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%s",
-  markup.repeat_character_by_number_provided("-", char_repeat_number),
-  doc_matters.conf_make_meta.meta.title_full,
-  doc_matters.conf_make_meta.meta.creator_author,
-  doc_matters.src.filename,
-  markup.repeat_character_by_number_provided("-", char_repeat_number),
-  "- toc arr length:",
-  to!int(doc_abstraction["toc"].length),
-  "- doc_abstraction arr length:",
-  to!int(doc_abstraction["body"].length),
-  "  doc body last obj on.#:",
-  to!int(check["last_object_number_body"]),
-  "  - number of tables:",
-  doc_matters.has.tables,
-  "  - number of codeblocks:",
-  doc_matters.has.codeblocks,
-  "  - number of poems:",
-  doc_matters.has.poems,
-  "  - number of blocks:",
-  doc_matters.has.blocks,
-  "  - number of groups:",
-  doc_matters.has.groups,
-  "  - number of images:",
-  doc_matters.has.images,
-  "- endnotes length:",                                // subtract headings
-  (doc_abstraction["endnotes"].length > 2)
-  ? (to!int(doc_abstraction["endnotes"].length - 2))
-  : 0,
-  "- glossary length:",
-  (doc_abstraction["glossary"].length > 1)
-  ? (to!int(doc_abstraction["glossary"].length))
-  : 0,
-  "- biblio length:",
-  (doc_abstraction["bibliography"].length > 1)
-  ? (to!int(doc_abstraction["bibliography"].length))
-  : 0,
-  "- bookindex length:",
-  (doc_abstraction["bookindex"].length > 1)
-  ? (to!int(doc_abstraction["bookindex"].length))
-  : 0,
-  "  book idx last obj on.#:",
-  to!int(check["last_object_number_book_index"]),
-  "- blurb length:",
-  (doc_abstraction["blurb"].length > 1)
-  ? (to!int(doc_abstraction["blurb"].length))
-  : 0,
-  "* last obj on.#:",
-  to!int(check["last_object_number"]),
-  "number of segments:",
-  (doc_matters.has.segnames_lv4.length > 1)
-  ? (to!int(doc_matters.has.segnames_lv4.length))
-  : 0,
-  markup.repeat_character_by_number_provided("-", min_repeat_number),
-);
-#+END_SRC
-
-** 0. module template metadoc harvest
-
-#+BEGIN_SRC d :tangle "../src/doc_reform/meta/metadoc_harvest.d"
-module doc_reform.meta.metadoc_harvest;
-template DocReformMetaDocHarvest() {
-  auto DocReformMetaDocHarvest(T,H)(
-    T  doc_matters,
-    H  hvst,
-  ) {
-    <<metadoc_harvest_imports>>
-    mixin InternalMarkup;
-    <<metadoc_harvest_initialize>>
-    <<meta_metadoc_harvest>>
-  }
-}
-#+END_SRC
-
-** init
-*** imports
-
-#+name: metadoc_harvest_imports
-#+BEGIN_SRC d
-import
-  doc_reform.meta.defaults,
-  doc_reform.meta.rgx;
-import
-  std.array,
-  std.exception,
-  std.regex,
-  std.stdio,
-  std.string,
-  std.traits,
-  std.typecons,
-  std.uni,
-  std.utf,
-  std.conv : to;
-#+END_SRC
-
-*** initialize                                                     :report:
-
-#+name: metadoc_harvest_initialize
-#+BEGIN_SRC d
-auto markup = InlineMarkup();
-#+END_SRC
-
-** harvest summary
-
-#+name: meta_metadoc_harvest_summary
-#+BEGIN_SRC d
-auto min_repeat_number = 66;
-auto char_repeat_number = (doc_matters.conf_make_meta.meta.title_full.length
-  + doc_matters.conf_make_meta.meta.creator_author.length + 4);
-char_repeat_number = (char_repeat_number > min_repeat_number)
-? char_repeat_number
-: min_repeat_number;
-writefln(
-  "%s\n\"%s\", %s\n%s\n%s\n%s",
-  markup.repeat_character_by_number_provided("-", char_repeat_number),
-  doc_matters.conf_make_meta.meta.title_full,
-  doc_matters.conf_make_meta.meta.creator_author,
-  doc_matters.src.filename,
-  doc_matters.conf_make_meta.meta.classify_topic_register_arr,
-  markup.repeat_character_by_number_provided("-", char_repeat_number),
-);
-#+END_SRC
-
-** return harvest
-
-#+name: meta_metadoc_harvest
-#+BEGIN_SRC d
-import doc_reform.output.paths_output;
-auto pth_html                   = DocReformPathsHTML!()(doc_matters.output_path, doc_matters.src.language);
-hvst.harvest.title              = doc_matters.conf_make_meta.meta.title_full;
-hvst.harvest.author             = doc_matters.conf_make_meta.meta.creator_author;
-hvst.harvest.author_surname     = doc_matters.conf_make_meta.meta.creator_author_surname;
-hvst.harvest.author_surname_fn  = doc_matters.conf_make_meta.meta.creator_author_surname_fn;
-hvst.harvest.author_arr         = doc_matters.conf_make_meta.meta.creator_author_arr;
-hvst.harvest.language_original  = doc_matters.conf_make_meta.meta.original_language;
-hvst.harvest.language           = doc_matters.src.language;
-hvst.harvest.uid                = doc_matters.src.doc_uid;
-hvst.harvest.date_published     = doc_matters.conf_make_meta.meta.date_published;
-hvst.harvest.topic_register_arr = doc_matters.conf_make_meta.meta.classify_topic_register_arr;
-hvst.harvest.path_html_scroll   = pth_html.fn_scroll(doc_matters.src.filename);
-hvst.harvest.path_html_seg      = pth_html.fn_seg(doc_matters.src.filename, "toc");
-return hvst.harvest;
-#+END_SRC
-
-** 0. module template metadoc harvest topics
-*** 0. module template metadoc harvest topics template
-
-#+BEGIN_SRC d :tangle "../src/doc_reform/meta/metadoc_harvests_topics.d"
-module doc_reform.meta.metadoc_harvests_topics;
-  import
-    std.algorithm,
-    std.array,
-    std.exception,
-    std.regex,
-    std.stdio,
-    std.string,
-    std.conv : to;
-  import
-    doc_reform.meta.defaults,
-    doc_reform.meta.rgx;
-  mixin DocReformHarvest;
-  mixin InternalMarkup;
-  mixin DocReformRgxInit;
-template DocReformMetaDocHarvestsTopics() {
-  auto mkup = InlineMarkup();
-  void DocReformMetaDocHarvestsTopics(H,O)(
-    H  hvst,
-    O  _opt_action,
-  ) {
-      <<harvested_topics>>
-<<harvested_topics_html_head_1>>
-<<harvested_html_head>>
-<<harvested_topics_html_head_2>>
-      <<harvested_topics_html>>
-      topics
-<<harvested_html_bottom>>
-    <<harvested_topics_html_write>>
-  }
-}
-#+END_SRC
-
-*** order topic register
-
-#+NAME: harvested_topics
-#+BEGIN_SRC d
-auto min_repeat_number = 42;
-string[] _document_topic_register;
-string[] _topic_register;
-string[] _sub_topic_register;
-string[] topics = [];
-string _auth = "";
-foreach(k, doc_harvest; hvst.harvests) {
-  _topic_register = [];
-  foreach(topic; doc_harvest.topic_register_arr.sort) {
-    _sub_topic_register = [];
-    string _spaces;
-    string[] subject_tree = topic.split(mkup.sep);
-    switch (subject_tree.length) {
-    case 1:
-      hvst.subject_trees[subject_tree[0]]["_a"]["_a"]["_a"] ~= doc_harvest;
-      break;
-    case 2:
-      hvst.subject_trees[subject_tree[0]][subject_tree[1]]["_a"]["_a"] ~= doc_harvest;
-      break;
-    case 3:
-      hvst.subject_trees[subject_tree[0]][subject_tree[1]][subject_tree[2]]["_a"] ~= doc_harvest;
-      break;
-    case 4:
-      hvst.subject_trees[subject_tree[0]][subject_tree[1]][subject_tree[2]][subject_tree[3]] ~= doc_harvest;
-      break;
-    default:
-      break;
-    }
-    _topic_register ~= _sub_topic_register.join("\n");
-  }
-  auto char_repeat_number = (doc_harvest.title.length
-    + doc_harvest.author.length + 16);
-  char_repeat_number = (char_repeat_number > min_repeat_number)
-  ? char_repeat_number
-  : min_repeat_number;
-  _document_topic_register ~= format(
-    "\"%s\", %s%s\n%s",
-    doc_harvest.title,
-    doc_harvest.author,
-    (doc_harvest.date_published.length > 0) ? " (" ~ doc_harvest.date_published ~ ")" : "",
-    _topic_register.sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable).release.join("\n"),
-  );
-}
-#+END_SRC
-
-*** harvested topics html head
-
-#+NAME: harvested_topics_html_head_1
-#+BEGIN_SRC d
-      topics ~= format(q"┃<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>Metadata Harvest - Topics</title>
-#+END_SRC
-
-*** harvested topics html head
-
-#+NAME: harvested_topics_html_head_2
-#+BEGIN_SRC d
-</head>
-<body lang="en" xml:lang="en">
-<a name="top" id="top"></a>
-<a name="up" id="up"></a>
-<a name="start" id="start"></a>
-<h1>Metadata Harvest - Topics (output organised by language &amp; filetype)</h1>
-<p>[<a href="../../index.html">&nbsp;HOME&nbsp;</a>] also see <a href="authors.html">Metadata Harvest - Authors</a></p>
-<p><a href="#A">A</a>,&nbsp;<a href="#B">B</a>,&nbsp;<a href="#C">C</a>,&nbsp;<a href="#D">D</a>,&nbsp;<a href="#E">E</a>,&nbsp;<a href="#F">F</a>,&nbsp;<a href="#G">G</a>,&nbsp;<a href="#H">H</a>,&nbsp;<a href="#I">I</a>,&nbsp;<a href="#J">J</a>,&nbsp;<a href="#K">K</a>,&nbsp;<a href="#L">L</a>,&nbsp;<a href="#M">M</a>,&nbsp;<a href="#N">N</a>,&nbsp;<a href="#O">O</a>,&nbsp;<a href="#P">P</a>,&nbsp;<a href="#Q">Q</a>,&nbsp;<a href="#R">R</a>,&nbsp;<a href="#S">S</a>,&nbsp;<a href="#T">T</a>,&nbsp;<a href="#U">U</a>,&nbsp;<a href="#V">V</a>,&nbsp;<a href="#W">W</a>,&nbsp;<a href="#X">X</a>,&nbsp;<a href="#Y">Y</a>,&nbsp;<a href="#Z">Z</a>,&nbsp;
-<p></p>
-<hr />
-<p class="tiny"><a href="../../en/manifest/topics.html">English</a>&nbsp;&nbsp;&nbsp;</p>
-<hr />
-┃") ~ "\n";
-#+END_SRC
-
-*** harvested topics html
-
-#+NAME: harvested_topics_html
-#+BEGIN_SRC d
-char _prev_k = "_".to!char;
-int _kn;
-foreach(k0;
-  hvst.subject_trees.keys
-  .sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable)
-) {
-  if (k0.toUpper.to!(char[])[0] != _prev_k) {
-    topics ~= format(q"┃<p class="letter"><a name="%s">%s</a></p><p class="book_index_lev1"><a name="a"></a></p>┃",
-      k0.toUpper.to!(char[])[0],
-      k0.toUpper.to!(char[])[0],
-    );
-    _prev_k = k0.toUpper.to!(char[])[0];
-  }
-  if (k0 != "_a") {
-    topics ~= format(q"┃<p class="lev0"><a name="%s">%s</a></p>┃",
-      k0, k0,) ~ "\n";
-    if (_opt_action.very_verbose) {
-      writeln("", k0);
-    }
-    if ("_a" in hvst.subject_trees[k0]) {
-      foreach (t_a_;
-        hvst.subject_trees[k0]["_a"]["_a"]["_a"]
-        .multiSort!("toUpper(a.title) < toUpper(b.title)", "a.author < b.author", SwapStrategy.unstable)
-      ) {
-        _auth = [];
-        if (t_a_.author_arr.length < 2) {
-          _auth = format(q"┃ <a href="authors.html#%s">%s</a>┃",
-            t_a_.author_surname,
-            t_a_.author,
-          );
-        } else {
-          foreach (a; t_a_.author_arr) {
-            _auth ~= format(q"┃ <a href="authors.html#%s">%s</a>,┃",
-              t_a_.author_surname,
-              a,
-            );
-          }
-        }
-        topics ~= format(q"┃<p class="work"><a href="%s">"%s"</a> -%s┃",
-          "url",
-          t_a_.title,
-          _auth,
-        ) ~ "\n";
-        if (_opt_action.very_verbose) {
-          writeln("- ", t_a_.title, " - ", t_a_.author);
-        }
-      }
-    }
-    foreach(k1;
-      hvst.subject_trees[k0].keys
-      .sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable)
-    ) {
-      if (k1 != "_a") {
-        topics ~= format(q"┃<p class="lev1"><a name="%s">%s</a></p>┃",
-          k1, k1,) ~ "\n";
-        if (_opt_action.very_verbose) {
-          writeln("  ", k1);
-        }
-        if ("_a" in hvst.subject_trees[k0][k1]) {
-          foreach (t_a_;
-            hvst.subject_trees[k0][k1]["_a"]["_a"]
-            .multiSort!("toUpper(a.title) < toUpper(b.title)", "a.author < b.author", SwapStrategy.unstable)
-          ) {
-            _auth = [];
-            if (t_a_.author_arr.length < 2) {
-              _auth = format(q"┃ <a href="authors.html#%s">%s</a>┃",
-                t_a_.author_surname,
-                t_a_.author,
-              );
-            } else {
-              foreach (a; t_a_.author_arr) {
-                _auth ~= format(q"┃ <a href="authors.html#%s">%s</a>,┃",
-                  t_a_.author_surname,
-                  a,
-                );
-              }
-            }
-            topics ~= format(q"┃<p class="work"><a href="%s">%s</a> -%s┃",
-              "url",
-              t_a_.title,
-              _auth,
-            ) ~ "\n";
-            if (_opt_action.very_verbose) {
-              writeln("  - ", t_a_.title, " - ", t_a_.author);
-            }
-          }
-        }
-      }
-      foreach(k2;
-        hvst.subject_trees[k0][k1].keys
-        .sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable)
-      ) {
-        if (k2 != "_a") {
-          topics ~= format(q"┃<p class="lev2"><a name="%s">%s</a></p>┃",
-            k2, k2,) ~ "\n";
-          if (_opt_action.very_verbose) {
-            writeln("    ", k2);
-          }
-          if ("_a" in hvst.subject_trees[k0][k1][k2]) {
-            foreach (t_a_;
-              hvst.subject_trees[k0][k1][k2]["_a"]
-              .multiSort!("toUpper(a.title) < toUpper(b.title)", "a.author < b.author", SwapStrategy.unstable)
-            ) {
-              _auth = [];
-              if (t_a_.author_arr.length < 2) {
-                _auth = format(q"┃ <a href="authors.html#%s">%s</a>┃",
-                  t_a_.author_surname,
-                  t_a_.author,
-                );
-              } else {
-                foreach (a; t_a_.author_arr) {
-                  _auth ~= format(q"┃ <a href="authors.html#%s">%s</a>,┃",
-                    t_a_.author_surname,
-                    a,
-                  );
-                }
-              }
-              topics ~= format(q"┃<p class="work"><a href="%s">%s</a> -%s┃",
-                "url",
-                t_a_.title,
-                _auth,
-              ) ~ "\n";
-              if (_opt_action.very_verbose) {
-                writeln("    - ", t_a_.title, " - ", t_a_.author);
-              }
-            }
-          }
-        }
-        foreach(k3;
-          hvst.subject_trees[k0][k1][k2].keys
-          .sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable)
-        ) {
-          if (k3 != "_a") {
-            topics ~= format(q"┃<p class="lev3"><a name="%s">%s</a></p>┃",
-              k3, k3,) ~ "\n";
-            if (_opt_action.very_verbose) {
-              writeln("      ", k3);
-            }
-            {
-              foreach (t_a_;
-                hvst.subject_trees[k0][k1][k2][k3]
-                .multiSort!("toUpper(a.title) < toUpper(b.title)", "a.author < b.author", SwapStrategy.unstable)
-              ) {
-                _auth = [];
-                if (t_a_.author_arr.length < 2) {
-                  _auth = format(q"┃<a href="authors.html#%s">%s</a>┃",
-                    t_a_.author_surname,
-                    t_a_.author,
-                  );
-                } else {
-                  foreach (a; t_a_.author_arr) {
-                    _auth ~= format(q"┃ <a href="authors.html#%s">%s</a>,┃",
-                      t_a_.author_surname,
-                      a,
-                    );
-                  }
-                }
-                topics ~= format(q"┃ <p class="work"><a href="%s">%s</a> -%s┃",
-                  "url",
-                  t_a_.title,
-                  _auth,
-                ) ~ "\n";
-                if (_opt_action.very_verbose) {
-                  writeln("      - ", t_a_.title, " - ", t_a_.author);
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-}
-#+END_SRC
-
-*** harvested topics write
-
-#+NAME: harvested_topics_html_write
-#+BEGIN_SRC d
-try {
-  auto f = File("topics.html", "w");
-  foreach (o; topics) {
-    f.writeln(o);
-  }
-} catch (ErrnoException ex) {
-  // Handle error
-}
-#+END_SRC
-
-** 0. module template metadoc harvests authors
-*** 0. module template metadoc harvest authors
-
-#+BEGIN_SRC d :tangle "../src/doc_reform/meta/metadoc_harvests_authors.d"
-module doc_reform.meta.metadoc_harvests_authors;
-  import
-    std.algorithm,
-    std.array,
-    std.exception,
-    std.regex,
-    std.stdio,
-    std.string,
-    std.conv : to;
-  import
-    doc_reform.meta.defaults,
-    doc_reform.meta.rgx;
-  mixin DocReformHarvest;
-  mixin InternalMarkup;
-  mixin DocReformRgxInit;
-template DocReformMetaDocHarvestsAuthors() {
-  auto mkup = InlineMarkup();
-  void DocReformMetaDocHarvestsAuthors(H,O)(
-    H  harvests,
-    O  _opt_action,
-  ) {
-<<harvested_authors_html_head_1>>
-<<harvested_html_head>>
-<<harvested_authors_html_head_2>>
-      authors
-<<harvested_html_bottom>>
-    <<harvested_authors_html_write>>
-  }
-}
-#+END_SRC
-
-*** harvested authors html head
-
-#+NAME: harvested_authors_html_head_1
-#+BEGIN_SRC d
-      string[] authors = [];
-      authors ~= format(q"┃
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>Metadata Harvest - Authors</title>
-#+END_SRC
-
-*** harvested authors html head
-
-#+NAME: harvested_authors_html_head_2
-#+BEGIN_SRC d
-</head>
-<body lang="en" xml:lang="en">
-<a name="top" id="top"></a>
-<a name="up" id="up"></a>
-<a name="start" id="start"></a>
-<h1>Metadata Harvest - Authors (output organised by language &amp; filetype)</h1>
-<p>[<a href="../../index.html">&nbsp;HOME&nbsp;</a>] also see <a href="topics.html">Metadata Harvest - Topics</a></p>
-<p></p>
-<hr />
-<p class="tiny"><a href="../../en/manifest/authors.html">English</a>&nbsp;&nbsp;&nbsp;</p>
-<hr />
-<p><a href="#A">A</a>,&nbsp;<a href="#B">B</a>,&nbsp;<a href="#C">C</a>,&nbsp;<a href="#D">D</a>,&nbsp;<a href="#E">E</a>,&nbsp;<a href="#F">F</a>,&nbsp;<a href="#G">G</a>,&nbsp;<a href="#H">H</a>,&nbsp;<a href="#I">I</a>,&nbsp;<a href="#J">J</a>,&nbsp;<a href="#K">K</a>,&nbsp;<a href="#L">L</a>,&nbsp;<a href="#M">M</a>,&nbsp;<a href="#N">N</a>,&nbsp;<a href="#O">O</a>,&nbsp;<a href="#P">P</a>,&nbsp;<a href="#Q">Q</a>,&nbsp;<a href="#R">R</a>,&nbsp;<a href="#S">S</a>,&nbsp;<a href="#T">T</a>,&nbsp;<a href="#U">U</a>,&nbsp;<a href="#V">V</a>,&nbsp;<a href="#W">W</a>,&nbsp;<a href="#X">X</a>,&nbsp;<a href="#Y">Y</a>,&nbsp;<a href="#Z">Z</a>,&nbsp;
-┃") ~ "\n";
-      string[string] _au;
-      string[] _auth_date_title;
-      string[] _author_date_title;
-      string _prev_auth = "";
-      char _prev_k = "_".to!char;
-      foreach(doc_harvest;
-        harvests
-        .multiSort!(
-          "toUpper(a.author_surname_fn) < toUpper(b.author_surname_fn)",
-          "a.date_published < b.date_published",
-          "a.title < b.title",
-          SwapStrategy.unstable
-        )
-      ) {
-        if (doc_harvest.author_surname_fn != _prev_auth) {
-          _au[doc_harvest.author_surname_fn]
-          = format(q"┃<p class="author"><a name="%s">%s</a></p> <p class="publication">%s "<a href="%s">%s</a>" [%s]</p>┃",
-            doc_harvest.author_surname,
-            doc_harvest.author_surname_fn,
-            (doc_harvest.date_published.length > 0)
-              ? doc_harvest.date_published : "",
-            "url",
-            doc_harvest.title,
-            doc_harvest.language,
-          );
-          _prev_auth = doc_harvest.author_surname_fn;
-        } else {
-          _au[doc_harvest.author_surname_fn]
-          ~= format(q"┃<p class="publication">%s "<a href="%s">%s</a>" [%s]</p>┃",
-            (doc_harvest.date_published.length > 0)
-              ? doc_harvest.date_published : "",
-            "url",
-            doc_harvest.title,
-            doc_harvest.language,
-          );
-        }
-        _author_date_title ~= format(q"┃%s %s "%s" [%s]┃",
-          doc_harvest.author_surname_fn,
-          (doc_harvest.date_published.length > 0)
-            ? "(" ~ doc_harvest.date_published ~ ")" : "",
-          doc_harvest.title,
-          doc_harvest.language,
-        );
-      }
-      foreach (k; _au.keys.sort) {
-        if (k.toUpper.to!(char[])[0] != _prev_k) {
-          authors ~= format(q"┃<p class="letter"><a name="%s">%s</a></p><p class="book_index_lev1"><a name="a"></a></p>┃",
-            k.toUpper.to!(char[])[0],
-            k.toUpper.to!(char[])[0],
-          );
-          _prev_k = k.toUpper.to!(char[])[0];
-        }
-        authors ~= _au[k];
-      }
-#+END_SRC
-
-*** harvested authors write
-
-#+NAME: harvested_authors_html_write
-#+BEGIN_SRC d
-try {
-  auto f = File("authors.html", "w");
-  foreach (o; authors) {
-    f.writeln(o);
-  }
-} catch (ErrnoException ex) {
-  // Handle error
-}
-if (_opt_action.verbose
-  || _opt_action.very_verbose
-) {
-  foreach(_adt; _author_date_title.sort) {
-    writeln(_adt);
-  }
-}
-#+END_SRC
-
-** harvested authors & topics shared html
-*** harvested html head
-
-#+NAME: harvested_html_head
-#+BEGIN_SRC d
-<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
-<meta name="dc.title" content= "metadata harvest, Authors & Topics - information Structuring Universe, Structured information Serialised Units" />
-<meta name="dc.subject" content= "document structuring, ebook, publishing, PDF, LaTeX, XML, ODF, SQL, postgresql, sqlite, electronic book, electronic publishing, electronic document, electronic citation, data structure, citation systems, granular search, digital library" />
-<meta name="generator" content="doc_reform" />
-<link rel="generator" href="http://sisudoc.org" />
-<link href="../../_sisu/css/harvest.css" rel="stylesheet">
-<style TYPE="text/css">
-/* DocReform harvest css default stylesheet */
-  body {
-    color: black;
-    background: #ffffff;
-    background-color: #ffffff;
-  }
-  a:link {
-    color: #003399;
-    text-decoration: none;
-  }
-  a:visited {
-    color: #003399;
-    text-decoration: none;
-  }
-  a:hover {
-    color: #000000;
-    background-color: #f9f9aa;
-  }
-  a:hover img {
-    background-color: #ffffff;
-  }
-  a:active {
-    color: #003399;
-    text-decoration: underline;
-  }
-
-  .norm, .bold {
-    line-height: 150%%;
-    margin-left: 1em;
-    margin-right: 2em;
-    margin-top: 10px;
-    margin-bottom: 0px;
-    text-indent: 0mm;
-  }
-  p, h0, h1, h2, h3, h4, h5, h6, h7 {
-    display: block;
-    font-family: verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman;
-    font-size: 100%%;
-    font-weight: normal;
-    line-height: 150%%;
-    /* text-align: justify; */
-    margin-left: 1em;
-    text-indent: 0mm;
-    margin-top: 2px;
-    margin-bottom: 2px;
-    margin-right: 6px;
-    text-align: left;
-  }
-  h1 {
-    font-size: 120%%;
-    font-weight: bold;
-    color: white;
-    background: #000088;
-    margin-left: 0em;
-  }
-  p.work {
-    font-size: 80%%;
-    margin-left: 5em;
-    margin-top: 0px;
-    margin-bottom: 0px;
-    margin-right: 6px;
-    text-align: left;
-  }
-  p.author {
-    font-size: 100%%;
-    margin-left: 2em;
-    margin-top: 0px;
-    margin-bottom: 0px;
-    margin-right: 6px;
-    text-align: left;
-  }
-  p.publication {
-    font-size: 80%%;
-    margin-left: 4em;
-    margin-top: 0px;
-    margin-bottom: 0px;
-    margin-right: 6px;
-    text-align: left;
-  }
-  p.letter {
-    font-weight: bold;
-    font-size: 60%%;
-    margin-left: 1em;
-    margin-top: 0px;
-    margin-bottom: 0px;
-    margin-right: 6px;
-    text-align: left;
-    color: white;
-    background: #880000;
-  }
-  p.lev0 {
-    font-size: 120%%;
-    margin-left: 1em;
-    color: white;
-    background: #000000;
-  }
-
-  p.lev1 {
-    font-size: 110%%;
-    margin-left: 2em;
-    color: white;
-    background: #444444;
-  }
-  p.lev2 {
-    font-size: 100%%;
-    margin-left: 3em;
-    background: #888888;
-  }
-  p.lev3 {
-    font-size: 90%%;
-    margin-left: 4em;
-    background: #bbbbbb;
-  }
-  p.lev4 {
-    font-size: 80%%;
-    margin-left: 5em;
-    background: #eeeeee;
-  }
-  p.lev5 {
-    font-size: 80%%;
-    margin-left: 6em;
-  }
-</style>
-<link rel="shortcut icon" href="../_sisu/image/rb7.ico" />
-#+END_SRC
-
-*** harvested html bottom
-
-#+NAME: harvested_html_bottom
-#+BEGIN_SRC d
-      ~= format(q"┃
-<hr />
-<a name="bottom" id="bottom"></a>
-<a name="down" id="down"></a>
-<a name="end" id="end"></a>
-<a name="finish" id="finish"></a>
-<a name="stop" id="stop"></a>
-<a name="credits"></a>
-</body>
-</html>
-┃") ~ "\n";
-#+END_SRC
-
 * __END__
 dev notes
 
diff --git a/org/output_harvest_metadata.org b/org/output_harvest_metadata.org
new file mode 100644
index 0000000..059b3d3
--- /dev/null
+++ b/org/output_harvest_metadata.org
@@ -0,0 +1,970 @@
+#+TITLE:       metadata (multidocument) harvests
+#+DESCRIPTION: documents - structuring, various output representations & search
+#+FILETAGS:    :doc_reform:hub:
+#+AUTHOR:      Ralph Amissah
+#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
+#+COPYRIGHT:   Copyright (C) 2015 - 2019 Ralph Amissah
+#+LANGUAGE:    en
+#+STARTUP:     indent content hideblocks hidestars
+#+OPTIONS:     H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
+#+OPTIONS:     TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc
+#+OPTIONS:     author:nil email:nil creator:nil timestamp:nil
+#+PROPERTY:    header-args :results silent :padline no :exports code :cache no :noweb yes
+#+EXPORT_SELECT_TAGS:  export
+#+EXPORT_EXCLUDE_TAGS: noexport
+#+TAGS: assert(a) class(c) debug(d) mixin(m) doc_reform(s) tangle(T) template(t) WEB(W) noexport(n)
+
+* document abstraction _summary_         :module:doc_reform:metadoc_summary:
+** 0. module template metadoc summary
+- document summary from abstraction
+
+#+BEGIN_SRC d :tangle "../src/doc_reform/meta/metadoc_summary.d"
+module doc_reform.meta.metadoc_summary;
+template DocReformMetaDocSummary() {
+  void DocReformMetaDocSummary(S,T)(
+    const S  doc_abstraction,
+          T  doc_matters,
+  ) {
+    <<metadoc_summary_imports>>
+    mixin InternalMarkup;
+    <<metadoc_summary_initialize>>
+    if (doc_matters.opt.action.verbose) {
+      <<meta_metadoc_summary_document>>
+    }
+  }
+}
+#+END_SRC
+
+** init
+*** imports
+
+#+name: metadoc_summary_imports
+#+BEGIN_SRC d
+import
+  doc_reform.meta.defaults,
+  doc_reform.meta.rgx;
+import
+  std.array,
+  std.exception,
+  std.regex,
+  std.stdio,
+  std.string,
+  std.traits,
+  std.typecons,
+  std.uni,
+  std.utf,
+  std.conv : to;
+#+END_SRC
+
+*** initialize                                                     :report:
+
+#+name: metadoc_summary_initialize
+#+BEGIN_SRC d
+auto markup = InlineMarkup();
+#+END_SRC
+
+** (last ocn)
+
+#+name: meta_metadoc_summary_document
+#+BEGIN_SRC d
+string[string] check = [
+  "last_object_number" : "NA [debug \"checkdoc\" not run]",
+  "last_object_number_body"  : "0",
+  "last_object_number_book_index" : "0",
+];
+foreach (k; doc_matters.has.keys_seq.seg) {
+  foreach (obj; doc_abstraction[k]) {
+    if (obj.metainfo.is_of_part != "empty") {
+      if (!empty(obj.metainfo.object_number)) {
+        if (k == "body") {
+          check["last_object_number_body"] = obj.metainfo.object_number;
+        }
+        if (!(obj.metainfo.object_number.empty)) {
+          check["last_object_number"] = obj.metainfo.object_number;
+        }
+      }
+      if (k == "bookindex") {
+        if (obj.metainfo.object_number_type == 2) {
+          check["last_object_number_book_index"] = obj.metainfo.object_number_book_index;
+        }
+      }
+    }
+  }
+}
+#+END_SRC
+
+** document summary
+
+#+name: meta_metadoc_summary_document
+#+BEGIN_SRC d
+auto min_repeat_number = 66;
+auto char_repeat_number = (doc_matters.conf_make_meta.meta.title_full.length
+  + doc_matters.conf_make_meta.meta.creator_author.length + 4);
+char_repeat_number = (char_repeat_number > min_repeat_number)
+? char_repeat_number
+: min_repeat_number;
+writefln(
+  "%s\n\"%s\", %s\n%s\n%s\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%s",
+  markup.repeat_character_by_number_provided("-", char_repeat_number),
+  doc_matters.conf_make_meta.meta.title_full,
+  doc_matters.conf_make_meta.meta.creator_author,
+  doc_matters.src.filename,
+  markup.repeat_character_by_number_provided("-", char_repeat_number),
+  "- toc arr length:",
+  to!int(doc_abstraction["toc"].length),
+  "- doc_abstraction arr length:",
+  to!int(doc_abstraction["body"].length),
+  "  doc body last obj on.#:",
+  to!int(check["last_object_number_body"]),
+  "  - number of tables:",
+  doc_matters.has.tables,
+  "  - number of codeblocks:",
+  doc_matters.has.codeblocks,
+  "  - number of poems:",
+  doc_matters.has.poems,
+  "  - number of blocks:",
+  doc_matters.has.blocks,
+  "  - number of groups:",
+  doc_matters.has.groups,
+  "  - number of images:",
+  doc_matters.has.images,
+  "- endnotes length:",                                // subtract headings
+  (doc_abstraction["endnotes"].length > 2)
+  ? (to!int(doc_abstraction["endnotes"].length - 2))
+  : 0,
+  "- glossary length:",
+  (doc_abstraction["glossary"].length > 1)
+  ? (to!int(doc_abstraction["glossary"].length))
+  : 0,
+  "- biblio length:",
+  (doc_abstraction["bibliography"].length > 1)
+  ? (to!int(doc_abstraction["bibliography"].length))
+  : 0,
+  "- bookindex length:",
+  (doc_abstraction["bookindex"].length > 1)
+  ? (to!int(doc_abstraction["bookindex"].length))
+  : 0,
+  "  book idx last obj on.#:",
+  to!int(check["last_object_number_book_index"]),
+  "- blurb length:",
+  (doc_abstraction["blurb"].length > 1)
+  ? (to!int(doc_abstraction["blurb"].length))
+  : 0,
+  "* last obj on.#:",
+  to!int(check["last_object_number"]),
+  "number of segments:",
+  (doc_matters.has.segnames_lv4.length > 1)
+  ? (to!int(doc_matters.has.segnames_lv4.length))
+  : 0,
+  markup.repeat_character_by_number_provided("-", min_repeat_number),
+);
+#+END_SRC
+
+** 0. module template metadoc harvest
+
+#+BEGIN_SRC d :tangle "../src/doc_reform/meta/metadoc_harvest.d"
+module doc_reform.meta.metadoc_harvest;
+template DocReformMetaDocHarvest() {
+  auto DocReformMetaDocHarvest(T,H)(
+    T  doc_matters,
+    H  hvst,
+  ) {
+    <<metadoc_harvest_imports>>
+    mixin InternalMarkup;
+    <<metadoc_harvest_initialize>>
+    <<meta_metadoc_harvest>>
+  }
+}
+#+END_SRC
+
+** init
+*** imports
+
+#+name: metadoc_harvest_imports
+#+BEGIN_SRC d
+import
+  doc_reform.meta.defaults,
+  doc_reform.meta.rgx;
+import
+  std.array,
+  std.exception,
+  std.regex,
+  std.stdio,
+  std.string,
+  std.traits,
+  std.typecons,
+  std.uni,
+  std.utf,
+  std.conv : to;
+#+END_SRC
+
+*** initialize                                                     :report:
+
+#+name: metadoc_harvest_initialize
+#+BEGIN_SRC d
+auto markup = InlineMarkup();
+#+END_SRC
+
+** harvest summary
+
+#+name: meta_metadoc_harvest_summary
+#+BEGIN_SRC d
+auto min_repeat_number = 66;
+auto char_repeat_number = (doc_matters.conf_make_meta.meta.title_full.length
+  + doc_matters.conf_make_meta.meta.creator_author.length + 4);
+char_repeat_number = (char_repeat_number > min_repeat_number)
+? char_repeat_number
+: min_repeat_number;
+writefln(
+  "%s\n\"%s\", %s\n%s\n%s\n%s",
+  markup.repeat_character_by_number_provided("-", char_repeat_number),
+  doc_matters.conf_make_meta.meta.title_full,
+  doc_matters.conf_make_meta.meta.creator_author,
+  doc_matters.src.filename,
+  doc_matters.conf_make_meta.meta.classify_topic_register_arr,
+  markup.repeat_character_by_number_provided("-", char_repeat_number),
+);
+#+END_SRC
+
+** return harvest
+
+#+name: meta_metadoc_harvest
+#+BEGIN_SRC d
+import doc_reform.output.paths_output;
+auto pth_html_abs               = DocReformPathsHTML!()(doc_matters.output_path, doc_matters.src.language);
+auto pth_html_rel               = DocReformDocRootTreeHTML!()(doc_matters.src.language);
+hvst.harvest.title              = doc_matters.conf_make_meta.meta.title_full;
+hvst.harvest.author             = doc_matters.conf_make_meta.meta.creator_author;
+hvst.harvest.author_surname     = doc_matters.conf_make_meta.meta.creator_author_surname;
+hvst.harvest.author_surname_fn  = doc_matters.conf_make_meta.meta.creator_author_surname_fn;
+hvst.harvest.author_arr         = doc_matters.conf_make_meta.meta.creator_author_arr;
+hvst.harvest.language_original  = doc_matters.conf_make_meta.meta.original_language;
+hvst.harvest.language           = doc_matters.src.language;
+hvst.harvest.uid                = doc_matters.src.doc_uid;
+hvst.harvest.date_published     = doc_matters.conf_make_meta.meta.date_published;
+hvst.harvest.topic_register_arr = doc_matters.conf_make_meta.meta.classify_topic_register_arr;
+hvst.harvest.path_html_scroll   = pth_html_rel.fn_scroll(doc_matters.src.filename);
+hvst.harvest.path_html_segtoc   = pth_html_rel.fn_seg(doc_matters.src.filename, "toc");
+return hvst.harvest;
+#+END_SRC
+
+** 0. module template metadoc harvest topics
+*** 0. module template metadoc harvest topics template
+
+#+BEGIN_SRC d :tangle "../src/doc_reform/meta/metadoc_harvests_topics.d"
+module doc_reform.meta.metadoc_harvests_topics;
+  import
+    std.algorithm,
+    std.array,
+    std.exception,
+    std.regex,
+    std.stdio,
+    std.string,
+    std.conv : to;
+  import
+    doc_reform.meta.defaults,
+    doc_reform.meta.rgx;
+  mixin DocReformHarvest;
+  mixin InternalMarkup;
+  mixin DocReformRgxInit;
+template DocReformMetaDocHarvestsTopics() {
+  auto mkup = InlineMarkup();
+  void DocReformMetaDocHarvestsTopics(H,O)(
+    H  hvst,
+    O  _opt_action,
+  ) {
+      <<harvested_topics>>
+<<harvested_html_themes>>
+<<harvested_topics_html_head_1>>
+<<harvested_html_head>>
+<<harvested_topics_html_head_2>>
+<<harvested_topics_html_head_theme>>
+      <<harvested_topics_html>>
+      topics
+<<harvested_html_bottom>>
+    <<harvested_topics_html_write>>
+  }
+}
+#+END_SRC
+
+*** order topic register
+
+#+NAME: harvested_topics
+#+BEGIN_SRC d
+auto min_repeat_number = 42;
+string[] _document_topic_register;
+string[] _topic_register;
+string[] _sub_topic_register;
+string[] topics = [];
+string _auth = "";
+foreach(k, doc_harvest; hvst.harvests) {
+  _topic_register = [];
+  foreach(topic; doc_harvest.topic_register_arr.sort) {
+    _sub_topic_register = [];
+    string _spaces;
+    string[] subject_tree = topic.split(mkup.sep);
+    switch (subject_tree.length) {
+    case 1:
+      hvst.subject_trees[subject_tree[0]]["_a"]["_a"]["_a"] ~= doc_harvest;
+      break;
+    case 2:
+      hvst.subject_trees[subject_tree[0]][subject_tree[1]]["_a"]["_a"] ~= doc_harvest;
+      break;
+    case 3:
+      hvst.subject_trees[subject_tree[0]][subject_tree[1]][subject_tree[2]]["_a"] ~= doc_harvest;
+      break;
+    case 4:
+      hvst.subject_trees[subject_tree[0]][subject_tree[1]][subject_tree[2]][subject_tree[3]] ~= doc_harvest;
+      break;
+    default:
+      break;
+    }
+    _topic_register ~= _sub_topic_register.join("\n");
+  }
+  auto char_repeat_number = (doc_harvest.title.length
+    + doc_harvest.author.length + 16);
+  char_repeat_number = (char_repeat_number > min_repeat_number)
+  ? char_repeat_number
+  : min_repeat_number;
+  _document_topic_register ~= format(
+    "\"%s\", %s%s\n%s",
+    doc_harvest.title,
+    doc_harvest.author,
+    (doc_harvest.date_published.length > 0) ? " (" ~ doc_harvest.date_published ~ ")" : "",
+    _topic_register.sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable).release.join("\n"),
+  );
+}
+#+END_SRC
+
+*** harvested topics html head
+
+#+NAME: harvested_topics_html_head_1
+#+BEGIN_SRC d
+      topics ~= format(q"┃<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Metadata Harvest - Topics</title>
+#+END_SRC
+
+*** harvested topics html head
+
+#+NAME: harvested_topics_html_head_2
+#+BEGIN_SRC d
+</head>
+<body lang="en" xml:lang="en">
+<a name="top" id="top"></a>
+<a name="up" id="up"></a>
+<a name="start" id="start"></a>
+<h1>Metadata Harvest - Topics (output organised by language &amp; filetype)</h1>
+<p>[<a href="../../index.html">&nbsp;HOME&nbsp;</a>] also see <a href="authors.html">Metadata Harvest - Authors</a></p>
+<p><a href="#A">A</a>,&nbsp;<a href="#B">B</a>,&nbsp;<a href="#C">C</a>,&nbsp;<a href="#D">D</a>,&nbsp;<a href="#E">E</a>,&nbsp;<a href="#F">F</a>,&nbsp;<a href="#G">G</a>,&nbsp;<a href="#H">H</a>,&nbsp;<a href="#I">I</a>,&nbsp;<a href="#J">J</a>,&nbsp;<a href="#K">K</a>,&nbsp;<a href="#L">L</a>,&nbsp;<a href="#M">M</a>,&nbsp;<a href="#N">N</a>,&nbsp;<a href="#O">O</a>,&nbsp;<a href="#P">P</a>,&nbsp;<a href="#Q">Q</a>,&nbsp;<a href="#R">R</a>,&nbsp;<a href="#S">S</a>,&nbsp;<a href="#T">T</a>,&nbsp;<a href="#U">U</a>,&nbsp;<a href="#V">V</a>,&nbsp;<a href="#W">W</a>,&nbsp;<a href="#X">X</a>,&nbsp;<a href="#Y">Y</a>,&nbsp;<a href="#Z">Z</a>,&nbsp;
+<p></p>
+<hr />
+<p class="tiny"><a href="../../en/manifest/topics.html">English</a>&nbsp;&nbsp;&nbsp;</p>
+<hr />
+#+END_SRC
+
+*** harvested topics html head theme insert
+
+#+NAME: harvested_topics_html_head_theme
+#+BEGIN_SRC d
+┃",
+  _opt_action.css_theme_default ? theme_light_0 : theme_dark_0,
+  _opt_action.css_theme_default ? theme_light_1 : theme_dark_1,
+) ~ "\n";
+#+END_SRC
+
+*** harvested topics html
+
+#+NAME: harvested_topics_html
+#+BEGIN_SRC d
+char _prev_k = "_".to!char;
+int _kn;
+foreach(k0;
+  hvst.subject_trees.keys
+  .sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable)
+) {
+  if (k0.toUpper.to!(char[])[0] != _prev_k) {
+    topics ~= format(q"┃<p class="letter"><a name="%s">%s</a></p><p class="book_index_lev1"><a name="a"></a></p>┃",
+      k0.toUpper.to!(char[])[0],
+      k0.toUpper.to!(char[])[0],
+    );
+    _prev_k = k0.toUpper.to!(char[])[0];
+  }
+  if (k0 != "_a") {
+    topics ~= format(q"┃<p class="lev0"><a name="%s">%s</a></p>┃",
+      k0, k0,) ~ "\n";
+    if (_opt_action.very_verbose) {
+      writeln("", k0);
+    }
+    if ("_a" in hvst.subject_trees[k0]) {
+      foreach (t_a_;
+        hvst.subject_trees[k0]["_a"]["_a"]["_a"]
+        .multiSort!("toUpper(a.title) < toUpper(b.title)", "a.author < b.author", SwapStrategy.unstable)
+      ) {
+        _auth = [];
+        if (t_a_.author_arr.length < 2) {
+          _auth = format(q"┃ <a href="authors.html#%s">%s</a>┃",
+            t_a_.author_surname,
+            t_a_.author,
+          );
+        } else {
+          foreach (a; t_a_.author_arr) {
+            _auth ~= format(q"┃ <a href="authors.html#%s">%s</a>,┃",
+              t_a_.author_surname,
+              a,
+            );
+          }
+        }
+        topics ~= format(q"┃<p class="work"><a href="%s">"%s"</a> -%s┃",
+          t_a_.path_html_segtoc,
+          t_a_.title,
+          _auth,
+        ) ~ "\n";
+        if (_opt_action.very_verbose) {
+          writeln("- ", t_a_.title, " - ", t_a_.author);
+        }
+      }
+    }
+    foreach(k1;
+      hvst.subject_trees[k0].keys
+      .sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable)
+    ) {
+      if (k1 != "_a") {
+        topics ~= format(q"┃<p class="lev1"><a name="%s">%s</a></p>┃",
+          k1, k1,) ~ "\n";
+        if (_opt_action.very_verbose) {
+          writeln("  ", k1);
+        }
+        if ("_a" in hvst.subject_trees[k0][k1]) {
+          foreach (t_a_;
+            hvst.subject_trees[k0][k1]["_a"]["_a"]
+            .multiSort!("toUpper(a.title) < toUpper(b.title)", "a.author < b.author", SwapStrategy.unstable)
+          ) {
+            _auth = [];
+            if (t_a_.author_arr.length < 2) {
+              _auth = format(q"┃ <a href="authors.html#%s">%s</a>┃",
+                t_a_.author_surname,
+                t_a_.author,
+              );
+            } else {
+              foreach (a; t_a_.author_arr) {
+                _auth ~= format(q"┃ <a href="authors.html#%s">%s</a>,┃",
+                  t_a_.author_surname,
+                  a,
+                );
+              }
+            }
+            topics ~= format(q"┃<p class="work"><a href="%s">%s</a> -%s┃",
+              t_a_.path_html_segtoc,
+              t_a_.title,
+              _auth,
+            ) ~ "\n";
+            if (_opt_action.very_verbose) {
+              writeln("  - ", t_a_.title, " - ", t_a_.author);
+            }
+          }
+        }
+      }
+      foreach(k2;
+        hvst.subject_trees[k0][k1].keys
+        .sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable)
+      ) {
+        if (k2 != "_a") {
+          topics ~= format(q"┃<p class="lev2"><a name="%s">%s</a></p>┃",
+            k2, k2,) ~ "\n";
+          if (_opt_action.very_verbose) {
+            writeln("    ", k2);
+          }
+          if ("_a" in hvst.subject_trees[k0][k1][k2]) {
+            foreach (t_a_;
+              hvst.subject_trees[k0][k1][k2]["_a"]
+              .multiSort!("toUpper(a.title) < toUpper(b.title)", "a.author < b.author", SwapStrategy.unstable)
+            ) {
+              _auth = [];
+              if (t_a_.author_arr.length < 2) {
+                _auth = format(q"┃ <a href="authors.html#%s">%s</a>┃",
+                  t_a_.author_surname,
+                  t_a_.author,
+                );
+              } else {
+                foreach (a; t_a_.author_arr) {
+                  _auth ~= format(q"┃ <a href="authors.html#%s">%s</a>,┃",
+                    t_a_.author_surname,
+                    a,
+                  );
+                }
+              }
+              topics ~= format(q"┃<p class="work"><a href="%s">%s</a> -%s┃",
+                t_a_.path_html_segtoc,
+                t_a_.title,
+                _auth,
+              ) ~ "\n";
+              if (_opt_action.very_verbose) {
+                writeln("    - ", t_a_.title, " - ", t_a_.author);
+              }
+            }
+          }
+        }
+        foreach(k3;
+          hvst.subject_trees[k0][k1][k2].keys
+          .sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable)
+        ) {
+          if (k3 != "_a") {
+            topics ~= format(q"┃<p class="lev3"><a name="%s">%s</a></p>┃",
+              k3, k3,) ~ "\n";
+            if (_opt_action.very_verbose) {
+              writeln("      ", k3);
+            }
+            {
+              foreach (t_a_;
+                hvst.subject_trees[k0][k1][k2][k3]
+                .multiSort!("toUpper(a.title) < toUpper(b.title)", "a.author < b.author", SwapStrategy.unstable)
+              ) {
+                _auth = [];
+                if (t_a_.author_arr.length < 2) {
+                  _auth = format(q"┃<a href="authors.html#%s">%s</a>┃",
+                    t_a_.author_surname,
+                    t_a_.author,
+                  );
+                } else {
+                  foreach (a; t_a_.author_arr) {
+                    _auth ~= format(q"┃ <a href="authors.html#%s">%s</a>,┃",
+                      t_a_.author_surname,
+                      a,
+                    );
+                  }
+                }
+                topics ~= format(q"┃ <p class="work"><a href="%s">%s</a> -%s┃",
+                  t_a_.path_html_segtoc,
+                  t_a_.title,
+                  _auth,
+                ) ~ "\n";
+                if (_opt_action.very_verbose) {
+                  writeln("      - ", t_a_.title, " - ", t_a_.author);
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+#+END_SRC
+
+*** harvested topics write
+
+#+NAME: harvested_topics_html_write
+#+BEGIN_SRC d
+import doc_reform.output.paths_output;
+auto out_pth = DocReformPathsHTML!()(_opt_action.output_dir_set, "");
+try {
+  auto f       = File(out_pth.harvest("topics.html"), "w");
+  foreach (o; topics) {
+    f.writeln(o);
+  }
+} catch (ErrnoException ex) {
+  // Handle error
+}
+#+END_SRC
+
+** 0. module template metadoc harvests authors
+*** 0. module template metadoc harvest authors
+
+#+BEGIN_SRC d :tangle "../src/doc_reform/meta/metadoc_harvests_authors.d"
+module doc_reform.meta.metadoc_harvests_authors;
+  import
+    std.algorithm,
+    std.array,
+    std.exception,
+    std.regex,
+    std.stdio,
+    std.string,
+    std.conv : to;
+  import
+    doc_reform.meta.defaults,
+    doc_reform.meta.rgx;
+  mixin DocReformHarvest;
+  mixin InternalMarkup;
+  mixin DocReformRgxInit;
+template DocReformMetaDocHarvestsAuthors() {
+  auto mkup = InlineMarkup();
+  void DocReformMetaDocHarvestsAuthors(H,O)(
+    H  harvests,
+    O  _opt_action,
+  ) {
+<<harvested_html_themes>>
+<<harvested_authors_html_head_1>>
+<<harvested_html_head>>
+<<harvested_authors_html_head_2>>
+<<harvested_authors_html_head_theme>>
+      authors
+<<harvested_html_bottom>>
+    <<harvested_authors_html_write>>
+  }
+}
+#+END_SRC
+
+*** harvested authors html head
+
+#+NAME: harvested_authors_html_head_1
+#+BEGIN_SRC d
+      string[] authors = [];
+      authors ~= format(q"┃
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Metadata Harvest - Authors</title>
+#+END_SRC
+
+*** harvested authors html head
+
+#+NAME: harvested_authors_html_head_2
+#+BEGIN_SRC d
+</head>
+<body lang="en" xml:lang="en">
+<a name="top" id="top"></a>
+<a name="up" id="up"></a>
+<a name="start" id="start"></a>
+<h1>Metadata Harvest - Authors (output organised by language &amp; filetype)</h1>
+<p>[<a href="../../index.html">&nbsp;HOME&nbsp;</a>] also see <a href="topics.html">Metadata Harvest - Topics</a></p>
+<p></p>
+<hr />
+<p class="tiny"><a href="../../en/manifest/authors.html">English</a>&nbsp;&nbsp;&nbsp;</p>
+<hr />
+<p><a href="#A">A</a>,&nbsp;<a href="#B">B</a>,&nbsp;<a href="#C">C</a>,&nbsp;<a href="#D">D</a>,&nbsp;<a href="#E">E</a>,&nbsp;<a href="#F">F</a>,&nbsp;<a href="#G">G</a>,&nbsp;<a href="#H">H</a>,&nbsp;<a href="#I">I</a>,&nbsp;<a href="#J">J</a>,&nbsp;<a href="#K">K</a>,&nbsp;<a href="#L">L</a>,&nbsp;<a href="#M">M</a>,&nbsp;<a href="#N">N</a>,&nbsp;<a href="#O">O</a>,&nbsp;<a href="#P">P</a>,&nbsp;<a href="#Q">Q</a>,&nbsp;<a href="#R">R</a>,&nbsp;<a href="#S">S</a>,&nbsp;<a href="#T">T</a>,&nbsp;<a href="#U">U</a>,&nbsp;<a href="#V">V</a>,&nbsp;<a href="#W">W</a>,&nbsp;<a href="#X">X</a>,&nbsp;<a href="#Y">Y</a>,&nbsp;<a href="#Z">Z</a>,&nbsp;
+#+END_SRC
+
+*** harvested authors html theme inserts
+
+#+NAME: harvested_authors_html_head_theme
+#+BEGIN_SRC d
+┃",
+  _opt_action.css_theme_default ? theme_light_0 : theme_dark_0,
+  _opt_action.css_theme_default ? theme_light_1 : theme_dark_1,
+) ~ "\n";
+      string[string] _au;
+      string[] _auth_date_title;
+      string[] _author_date_title;
+      string _prev_auth = "";
+      char _prev_k = "_".to!char;
+      foreach(doc_harvest;
+        harvests
+        .multiSort!(
+          "toUpper(a.author_surname_fn) < toUpper(b.author_surname_fn)",
+          "a.date_published < b.date_published",
+          "a.title < b.title",
+          SwapStrategy.unstable
+        )
+      ) {
+        if (doc_harvest.author_surname_fn != _prev_auth) {
+          _au[doc_harvest.author_surname_fn]
+          = format(q"┃<p class="author"><a name="%s">%s</a></p> <p class="publication">%s "<a href="%s">%s</a>" [%s]</p>┃",
+            doc_harvest.author_surname,
+            doc_harvest.author_surname_fn,
+            (doc_harvest.date_published.length > 0)
+              ? doc_harvest.date_published : "",
+            doc_harvest.path_html_segtoc,
+            doc_harvest.title,
+            doc_harvest.language,
+          );
+          _prev_auth = doc_harvest.author_surname_fn;
+        } else {
+          _au[doc_harvest.author_surname_fn]
+          ~= format(q"┃<p class="publication">%s "<a href="%s">%s</a>" [%s]</p>┃",
+            (doc_harvest.date_published.length > 0)
+              ? doc_harvest.date_published : "",
+            doc_harvest.path_html_segtoc,
+            doc_harvest.title,
+            doc_harvest.language,
+          );
+        }
+        _author_date_title ~= format(q"┃%s %s "%s" [%s]┃",
+          doc_harvest.author_surname_fn,
+          (doc_harvest.date_published.length > 0)
+            ? "(" ~ doc_harvest.date_published ~ ")" : "",
+          doc_harvest.title,
+          doc_harvest.language,
+        );
+      }
+      foreach (k; _au.keys.sort) {
+        if (k.toUpper.to!(char[])[0] != _prev_k) {
+          authors ~= format(q"┃<p class="letter"><a name="%s">%s</a></p><p class="book_index_lev1"><a name="a"></a></p>┃",
+            k.toUpper.to!(char[])[0],
+            k.toUpper.to!(char[])[0],
+          );
+          _prev_k = k.toUpper.to!(char[])[0];
+        }
+        authors ~= _au[k];
+      }
+#+END_SRC
+
+*** harvested authors write
+
+#+NAME: harvested_authors_html_write
+#+BEGIN_SRC d
+import doc_reform.output.paths_output;
+auto out_pth = DocReformPathsHTML!()(_opt_action.output_dir_set, "");
+try {
+  auto f       = File(out_pth.harvest("authors.html"), "w");
+  foreach (o; authors) {
+    f.writeln(o);
+  }
+} catch (ErrnoException ex) {
+  // Handle error
+}
+if (_opt_action.verbose
+  || _opt_action.very_verbose
+) {
+  foreach(_adt; _author_date_title.sort) {
+    writeln(_adt);
+  }
+}
+#+END_SRC
+
+** harvested authors & topics shared html
+*** themes
+**** head
+
+#+NAME: harvested_html_themes
+#+BEGIN_SRC d
+string theme_dark_0 = format(q"┃
+  body {
+    color: #CCCCCC;
+    background: #000000;
+    background-color: #000000;
+  }
+  a:link {
+    color: #FFFFFF;
+    text-decoration: none;
+  }
+  a:visited {
+    color: #999999;
+    text-decoration: none;
+  }
+  a:hover {
+    color: #000000;
+    background-color: #555555;
+  }
+  a:hover img {
+    background-color: #000000;
+  }
+  a:active {
+    color: #888888;
+    text-decoration: underline;
+  }
+┃");
+string theme_light_0 = format(q"┃
+  body {
+    color: black;
+    background: #ffffff;
+    background-color: #ffffff;
+  }
+  a:link {
+    color: #003399;
+    text-decoration: none;
+  }
+  a:visited {
+    color: #003399;
+    text-decoration: none;
+  }
+  a:hover {
+    color: #000000;
+    background-color: #f9f9aa;
+  }
+  a:hover img {
+    background-color: #ffffff;
+  }
+  a:active {
+    color: #003399;
+    text-decoration: underline;
+  }
+┃");
+#+END_SRC
+
+**** levels
+
+#+NAME: harvested_html_themes
+#+BEGIN_SRC d
+string theme_dark_1 = format(q"┃
+  h1 {
+    color: white;
+    background: #000000;
+  }
+  p.letter {
+    color: white;
+    background: #333333;
+  }
+  p.lev0 {
+    color: white;
+    background: #000000;
+  }
+  p.lev1 {
+    color: white;
+    background: #333333;
+  }
+  p.lev2 {
+    background: #555555;
+  }
+  p.lev3 {
+    background: #777777;
+  }
+  p.lev4 {
+    background: #aaaaaa;
+  }
+  p.lev5 {
+  }
+┃");
+string theme_light_1 = format(q"┃
+  h1 {
+    color: white;
+    background: #000088;
+  }
+  p.letter {
+    color: white;
+    background: #880000;
+  }
+  p.lev0 {
+    color: white;
+    background: #000000;
+  }
+  p.lev1 {
+    color: white;
+    background: #444444;
+  }
+  p.lev2 {
+    background: #888888;
+  }
+  p.lev3 {
+    background: #bbbbbb;
+  }
+  p.lev4 {
+    background: #eeeeee;
+  }
+  p.lev5 {
+  }
+┃");
+#+END_SRC
+
+*** harvested html head
+
+#+NAME: harvested_html_head
+#+BEGIN_SRC d
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+<meta name="dc.title" content= "metadata harvest, Authors & Topics - information Structuring Universe, Structured information Serialised Units" />
+<meta name="dc.subject" content= "document structuring, ebook, publishing, PDF, LaTeX, XML, ODF, SQL, postgresql, sqlite, electronic book, electronic publishing, electronic document, electronic citation, data structure, citation systems, granular search, digital library" />
+<meta name="generator" content="doc_reform" />
+<link rel="generator" href="http://sisudoc.org" />
+<link href="../../_sisu/css/harvest.css" rel="stylesheet">
+<style TYPE="text/css">
+/* DocReform harvest css default stylesheet */%s
+  .norm, .bold {
+    line-height: 150%%;
+    margin-left: 1em;
+    margin-right: 2em;
+    margin-top: 10px;
+    margin-bottom: 0px;
+    text-indent: 0mm;
+  }
+  p, h0, h1, h2, h3, h4, h5, h6, h7 {
+    display: block;
+    font-family: verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman;
+    font-size: 100%%;
+    font-weight: normal;
+    line-height: 150%%;
+    /* text-align: justify; */
+    margin-left: 1em;
+    text-indent: 0mm;
+    margin-top: 2px;
+    margin-bottom: 2px;
+    margin-right: 6px;
+    text-align: left;
+  }
+  h0, h1, h2, h3, h4, h5, h6, h7 { text-shadow: .2em .2em .3em #999999; }
+  h1 {
+    font-size: 120%%;
+    font-weight: bold;
+    color: white;
+    background: #000088;
+    margin-left: 0em;
+  }
+  p.work {
+    font-size: 80%%;
+    margin-left: 5em;
+    margin-top: 0px;
+    margin-bottom: 0px;
+    margin-right: 6px;
+    text-align: left;
+  }
+  p.author {
+    font-size: 100%%;
+    margin-left: 2em;
+    margin-top: 0px;
+    margin-bottom: 0px;
+    margin-right: 6px;
+    text-align: left;
+  }
+  p.publication {
+    font-size: 80%%;
+    margin-left: 4em;
+    margin-top: 0px;
+    margin-bottom: 0px;
+    margin-right: 6px;
+    text-align: left;
+  }
+  p.letter {
+    font-weight: bold;
+    font-size: 60%%;
+    margin-left: 1em;
+    margin-top: 0px;
+    margin-bottom: 0px;
+    margin-right: 6px;
+    text-align: left;
+  }
+  p.lev0 {
+    font-size: 120%%;
+    margin-left: 1em;
+  }
+  p.lev1 {
+    font-size: 110%%;
+    margin-left: 2em;
+  }
+  p.lev2 {
+    font-size: 100%%;
+    margin-left: 3em;
+  }
+  p.lev3 {
+    font-size: 90%%;
+    margin-left: 4em;
+  }
+  p.lev4 {
+    font-size: 80%%;
+    margin-left: 5em;
+  }
+  p.lev5 {
+    font-size: 80%%;
+    margin-left: 6em;
+  }%s
+</style>
+<link rel="shortcut icon" href="../_sisu/image/rb7.ico" />
+#+END_SRC
+
+*** harvested html bottom
+
+#+NAME: harvested_html_bottom
+#+BEGIN_SRC d
+      ~= format(q"┃
+<hr />
+<a name="bottom" id="bottom"></a>
+<a name="down" id="down"></a>
+<a name="end" id="end"></a>
+<a name="finish" id="finish"></a>
+<a name="stop" id="stop"></a>
+<a name="credits"></a>
+</body>
+</html>
+┃") ~ "\n";
+#+END_SRC
diff --git a/src/doc_reform/doc_reform.d b/src/doc_reform/doc_reform.d
index d48851b..0fa326d 100755
--- a/src/doc_reform/doc_reform.d
+++ b/src/doc_reform/doc_reform.d
@@ -804,5 +804,15 @@ void main(string[] args) {
     if (_opt_action.harvest_authors) {
       DocReformMetaDocHarvestsAuthors!()(hvst.harvests, _opt_action);
     }
+    if (!(_opt_action.quiet)) {
+      import doc_reform.output.paths_output;
+      auto out_pth = DocReformPathsHTML!()(_opt_action.output_dir_set, "");
+      if (_opt_action.harvest_authors) {
+        writeln("- ", out_pth.harvest("authors.html"));
+      }
+      if (_opt_action.harvest_topics) {
+        writeln("- ", out_pth.harvest("topics.html"));
+      }
+    }
   }
 }
diff --git a/src/doc_reform/meta/defaults.d b/src/doc_reform/meta/defaults.d
index 4a4ae8f..ace121b 100644
--- a/src/doc_reform/meta/defaults.d
+++ b/src/doc_reform/meta/defaults.d
@@ -101,7 +101,7 @@ template DocReformHarvest() {
         string   uid                  = "";
         string   date_published       = "";
         string[] topic_register_arr   = [];
-        string   path_html_seg        = "";
+        string   path_html_segtoc     = "";
         string   path_html_scroll     = "";
         string   path_epub            = "";
         string   url_html_seg         = "";
diff --git a/src/doc_reform/meta/metadoc_harvest.d b/src/doc_reform/meta/metadoc_harvest.d
index 2a83814..83c6d35 100644
--- a/src/doc_reform/meta/metadoc_harvest.d
+++ b/src/doc_reform/meta/metadoc_harvest.d
@@ -21,7 +21,8 @@ template DocReformMetaDocHarvest() {
     mixin InternalMarkup;
     auto markup = InlineMarkup();
     import doc_reform.output.paths_output;
-    auto pth_html                   = DocReformPathsHTML!()(doc_matters.output_path, doc_matters.src.language);
+    auto pth_html_abs               = DocReformPathsHTML!()(doc_matters.output_path, doc_matters.src.language);
+    auto pth_html_rel               = DocReformDocRootTreeHTML!()(doc_matters.src.language);
     hvst.harvest.title              = doc_matters.conf_make_meta.meta.title_full;
     hvst.harvest.author             = doc_matters.conf_make_meta.meta.creator_author;
     hvst.harvest.author_surname     = doc_matters.conf_make_meta.meta.creator_author_surname;
@@ -32,8 +33,8 @@ template DocReformMetaDocHarvest() {
     hvst.harvest.uid                = doc_matters.src.doc_uid;
     hvst.harvest.date_published     = doc_matters.conf_make_meta.meta.date_published;
     hvst.harvest.topic_register_arr = doc_matters.conf_make_meta.meta.classify_topic_register_arr;
-    hvst.harvest.path_html_scroll   = pth_html.fn_scroll(doc_matters.src.filename);
-    hvst.harvest.path_html_seg      = pth_html.fn_seg(doc_matters.src.filename, "toc");
+    hvst.harvest.path_html_scroll   = pth_html_rel.fn_scroll(doc_matters.src.filename);
+    hvst.harvest.path_html_segtoc   = pth_html_rel.fn_seg(doc_matters.src.filename, "toc");
     return hvst.harvest;
   }
 }
diff --git a/src/doc_reform/meta/metadoc_harvests_authors.d b/src/doc_reform/meta/metadoc_harvests_authors.d
index d780221..950d1ff 100644
--- a/src/doc_reform/meta/metadoc_harvests_authors.d
+++ b/src/doc_reform/meta/metadoc_harvests_authors.d
@@ -19,21 +19,33 @@ template DocReformMetaDocHarvestsAuthors() {
     H  harvests,
     O  _opt_action,
   ) {
-      string[] authors = [];
-      authors ~= format(q"┃
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>Metadata Harvest - Authors</title>
-<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
-<meta name="dc.title" content= "metadata harvest, Authors & Topics - information Structuring Universe, Structured information Serialised Units" />
-<meta name="dc.subject" content= "document structuring, ebook, publishing, PDF, LaTeX, XML, ODF, SQL, postgresql, sqlite, electronic book, electronic publishing, electronic document, electronic citation, data structure, citation systems, granular search, digital library" />
-<meta name="generator" content="doc_reform" />
-<link rel="generator" href="http://sisudoc.org" />
-<link href="../../_sisu/css/harvest.css" rel="stylesheet">
-<style TYPE="text/css">
-/* DocReform harvest css default stylesheet */
+string theme_dark_0 = format(q"┃
+  body {
+    color: #CCCCCC;
+    background: #000000;
+    background-color: #000000;
+  }
+  a:link {
+    color: #FFFFFF;
+    text-decoration: none;
+  }
+  a:visited {
+    color: #999999;
+    text-decoration: none;
+  }
+  a:hover {
+    color: #000000;
+    background-color: #555555;
+  }
+  a:hover img {
+    background-color: #000000;
+  }
+  a:active {
+    color: #888888;
+    text-decoration: underline;
+  }
+┃");
+string theme_light_0 = format(q"┃
   body {
     color: black;
     background: #ffffff;
@@ -58,7 +70,80 @@ template DocReformMetaDocHarvestsAuthors() {
     color: #003399;
     text-decoration: underline;
   }
-
+┃");
+string theme_dark_1 = format(q"┃
+  h1 {
+    color: white;
+    background: #000000;
+  }
+  p.letter {
+    color: white;
+    background: #333333;
+  }
+  p.lev0 {
+    color: white;
+    background: #000000;
+  }
+  p.lev1 {
+    color: white;
+    background: #333333;
+  }
+  p.lev2 {
+    background: #555555;
+  }
+  p.lev3 {
+    background: #777777;
+  }
+  p.lev4 {
+    background: #aaaaaa;
+  }
+  p.lev5 {
+  }
+┃");
+string theme_light_1 = format(q"┃
+  h1 {
+    color: white;
+    background: #000088;
+  }
+  p.letter {
+    color: white;
+    background: #880000;
+  }
+  p.lev0 {
+    color: white;
+    background: #000000;
+  }
+  p.lev1 {
+    color: white;
+    background: #444444;
+  }
+  p.lev2 {
+    background: #888888;
+  }
+  p.lev3 {
+    background: #bbbbbb;
+  }
+  p.lev4 {
+    background: #eeeeee;
+  }
+  p.lev5 {
+  }
+┃");
+      string[] authors = [];
+      authors ~= format(q"┃
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Metadata Harvest - Authors</title>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+<meta name="dc.title" content= "metadata harvest, Authors & Topics - information Structuring Universe, Structured information Serialised Units" />
+<meta name="dc.subject" content= "document structuring, ebook, publishing, PDF, LaTeX, XML, ODF, SQL, postgresql, sqlite, electronic book, electronic publishing, electronic document, electronic citation, data structure, citation systems, granular search, digital library" />
+<meta name="generator" content="doc_reform" />
+<link rel="generator" href="http://sisudoc.org" />
+<link href="../../_sisu/css/harvest.css" rel="stylesheet">
+<style TYPE="text/css">
+/* DocReform harvest css default stylesheet */%s
   .norm, .bold {
     line-height: 150%%;
     margin-left: 1em;
@@ -81,6 +166,7 @@ template DocReformMetaDocHarvestsAuthors() {
     margin-right: 6px;
     text-align: left;
   }
+  h0, h1, h2, h3, h4, h5, h6, h7 { text-shadow: .2em .2em .3em #999999; }
   h1 {
     font-size: 120%%;
     font-weight: bold;
@@ -120,41 +206,31 @@ template DocReformMetaDocHarvestsAuthors() {
     margin-bottom: 0px;
     margin-right: 6px;
     text-align: left;
-    color: white;
-    background: #880000;
   }
   p.lev0 {
     font-size: 120%%;
     margin-left: 1em;
-    color: white;
-    background: #000000;
   }
-
   p.lev1 {
     font-size: 110%%;
     margin-left: 2em;
-    color: white;
-    background: #444444;
   }
   p.lev2 {
     font-size: 100%%;
     margin-left: 3em;
-    background: #888888;
   }
   p.lev3 {
     font-size: 90%%;
     margin-left: 4em;
-    background: #bbbbbb;
   }
   p.lev4 {
     font-size: 80%%;
     margin-left: 5em;
-    background: #eeeeee;
   }
   p.lev5 {
     font-size: 80%%;
     margin-left: 6em;
-  }
+  }%s
 </style>
 <link rel="shortcut icon" href="../_sisu/image/rb7.ico" />
 </head>
@@ -169,7 +245,10 @@ template DocReformMetaDocHarvestsAuthors() {
 <p class="tiny"><a href="../../en/manifest/authors.html">English</a>&nbsp;&nbsp;&nbsp;</p>
 <hr />
 <p><a href="#A">A</a>,&nbsp;<a href="#B">B</a>,&nbsp;<a href="#C">C</a>,&nbsp;<a href="#D">D</a>,&nbsp;<a href="#E">E</a>,&nbsp;<a href="#F">F</a>,&nbsp;<a href="#G">G</a>,&nbsp;<a href="#H">H</a>,&nbsp;<a href="#I">I</a>,&nbsp;<a href="#J">J</a>,&nbsp;<a href="#K">K</a>,&nbsp;<a href="#L">L</a>,&nbsp;<a href="#M">M</a>,&nbsp;<a href="#N">N</a>,&nbsp;<a href="#O">O</a>,&nbsp;<a href="#P">P</a>,&nbsp;<a href="#Q">Q</a>,&nbsp;<a href="#R">R</a>,&nbsp;<a href="#S">S</a>,&nbsp;<a href="#T">T</a>,&nbsp;<a href="#U">U</a>,&nbsp;<a href="#V">V</a>,&nbsp;<a href="#W">W</a>,&nbsp;<a href="#X">X</a>,&nbsp;<a href="#Y">Y</a>,&nbsp;<a href="#Z">Z</a>,&nbsp;
-┃") ~ "\n";
+┃",
+  _opt_action.css_theme_default ? theme_light_0 : theme_dark_0,
+  _opt_action.css_theme_default ? theme_light_1 : theme_dark_1,
+) ~ "\n";
       string[string] _au;
       string[] _auth_date_title;
       string[] _author_date_title;
@@ -191,7 +270,7 @@ template DocReformMetaDocHarvestsAuthors() {
             doc_harvest.author_surname_fn,
             (doc_harvest.date_published.length > 0)
               ? doc_harvest.date_published : "",
-            "url",
+            doc_harvest.path_html_segtoc,
             doc_harvest.title,
             doc_harvest.language,
           );
@@ -201,7 +280,7 @@ template DocReformMetaDocHarvestsAuthors() {
           ~= format(q"┃<p class="publication">%s "<a href="%s">%s</a>" [%s]</p>┃",
             (doc_harvest.date_published.length > 0)
               ? doc_harvest.date_published : "",
-            "url",
+            doc_harvest.path_html_segtoc,
             doc_harvest.title,
             doc_harvest.language,
           );
@@ -236,8 +315,10 @@ template DocReformMetaDocHarvestsAuthors() {
 </body>
 </html>
 ┃") ~ "\n";
+    import doc_reform.output.paths_output;
+    auto out_pth = DocReformPathsHTML!()(_opt_action.output_dir_set, "");
     try {
-      auto f = File("authors.html", "w");
+      auto f       = File(out_pth.harvest("authors.html"), "w");
       foreach (o; authors) {
         f.writeln(o);
       }
diff --git a/src/doc_reform/meta/metadoc_harvests_topics.d b/src/doc_reform/meta/metadoc_harvests_topics.d
index f0aed57..a5a481c 100644
--- a/src/doc_reform/meta/metadoc_harvests_topics.d
+++ b/src/doc_reform/meta/metadoc_harvests_topics.d
@@ -62,19 +62,33 @@ template DocReformMetaDocHarvestsTopics() {
           _topic_register.sort!("toUpper(a) < toUpper(b)", SwapStrategy.unstable).release.join("\n"),
         );
       }
-      topics ~= format(q"┃<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>Metadata Harvest - Topics</title>
-<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
-<meta name="dc.title" content= "metadata harvest, Authors & Topics - information Structuring Universe, Structured information Serialised Units" />
-<meta name="dc.subject" content= "document structuring, ebook, publishing, PDF, LaTeX, XML, ODF, SQL, postgresql, sqlite, electronic book, electronic publishing, electronic document, electronic citation, data structure, citation systems, granular search, digital library" />
-<meta name="generator" content="doc_reform" />
-<link rel="generator" href="http://sisudoc.org" />
-<link href="../../_sisu/css/harvest.css" rel="stylesheet">
-<style TYPE="text/css">
-/* DocReform harvest css default stylesheet */
+string theme_dark_0 = format(q"┃
+  body {
+    color: #CCCCCC;
+    background: #000000;
+    background-color: #000000;
+  }
+  a:link {
+    color: #FFFFFF;
+    text-decoration: none;
+  }
+  a:visited {
+    color: #999999;
+    text-decoration: none;
+  }
+  a:hover {
+    color: #000000;
+    background-color: #555555;
+  }
+  a:hover img {
+    background-color: #000000;
+  }
+  a:active {
+    color: #888888;
+    text-decoration: underline;
+  }
+┃");
+string theme_light_0 = format(q"┃
   body {
     color: black;
     background: #ffffff;
@@ -99,7 +113,78 @@ template DocReformMetaDocHarvestsTopics() {
     color: #003399;
     text-decoration: underline;
   }
-
+┃");
+string theme_dark_1 = format(q"┃
+  h1 {
+    color: white;
+    background: #000000;
+  }
+  p.letter {
+    color: white;
+    background: #333333;
+  }
+  p.lev0 {
+    color: white;
+    background: #000000;
+  }
+  p.lev1 {
+    color: white;
+    background: #333333;
+  }
+  p.lev2 {
+    background: #555555;
+  }
+  p.lev3 {
+    background: #777777;
+  }
+  p.lev4 {
+    background: #aaaaaa;
+  }
+  p.lev5 {
+  }
+┃");
+string theme_light_1 = format(q"┃
+  h1 {
+    color: white;
+    background: #000088;
+  }
+  p.letter {
+    color: white;
+    background: #880000;
+  }
+  p.lev0 {
+    color: white;
+    background: #000000;
+  }
+  p.lev1 {
+    color: white;
+    background: #444444;
+  }
+  p.lev2 {
+    background: #888888;
+  }
+  p.lev3 {
+    background: #bbbbbb;
+  }
+  p.lev4 {
+    background: #eeeeee;
+  }
+  p.lev5 {
+  }
+┃");
+      topics ~= format(q"┃<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Metadata Harvest - Topics</title>
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+<meta name="dc.title" content= "metadata harvest, Authors & Topics - information Structuring Universe, Structured information Serialised Units" />
+<meta name="dc.subject" content= "document structuring, ebook, publishing, PDF, LaTeX, XML, ODF, SQL, postgresql, sqlite, electronic book, electronic publishing, electronic document, electronic citation, data structure, citation systems, granular search, digital library" />
+<meta name="generator" content="doc_reform" />
+<link rel="generator" href="http://sisudoc.org" />
+<link href="../../_sisu/css/harvest.css" rel="stylesheet">
+<style TYPE="text/css">
+/* DocReform harvest css default stylesheet */%s
   .norm, .bold {
     line-height: 150%%;
     margin-left: 1em;
@@ -122,6 +207,7 @@ template DocReformMetaDocHarvestsTopics() {
     margin-right: 6px;
     text-align: left;
   }
+  h0, h1, h2, h3, h4, h5, h6, h7 { text-shadow: .2em .2em .3em #999999; }
   h1 {
     font-size: 120%%;
     font-weight: bold;
@@ -161,41 +247,31 @@ template DocReformMetaDocHarvestsTopics() {
     margin-bottom: 0px;
     margin-right: 6px;
     text-align: left;
-    color: white;
-    background: #880000;
   }
   p.lev0 {
     font-size: 120%%;
     margin-left: 1em;
-    color: white;
-    background: #000000;
   }
-
   p.lev1 {
     font-size: 110%%;
     margin-left: 2em;
-    color: white;
-    background: #444444;
   }
   p.lev2 {
     font-size: 100%%;
     margin-left: 3em;
-    background: #888888;
   }
   p.lev3 {
     font-size: 90%%;
     margin-left: 4em;
-    background: #bbbbbb;
   }
   p.lev4 {
     font-size: 80%%;
     margin-left: 5em;
-    background: #eeeeee;
   }
   p.lev5 {
     font-size: 80%%;
     margin-left: 6em;
-  }
+  }%s
 </style>
 <link rel="shortcut icon" href="../_sisu/image/rb7.ico" />
 </head>
@@ -210,7 +286,10 @@ template DocReformMetaDocHarvestsTopics() {
 <hr />
 <p class="tiny"><a href="../../en/manifest/topics.html">English</a>&nbsp;&nbsp;&nbsp;</p>
 <hr />
-┃") ~ "\n";
+┃",
+  _opt_action.css_theme_default ? theme_light_0 : theme_dark_0,
+  _opt_action.css_theme_default ? theme_light_1 : theme_dark_1,
+) ~ "\n";
       char _prev_k = "_".to!char;
       int _kn;
       foreach(k0;
@@ -250,7 +329,7 @@ template DocReformMetaDocHarvestsTopics() {
                 }
               }
               topics ~= format(q"┃<p class="work"><a href="%s">"%s"</a> -%s┃",
-                "url",
+                t_a_.path_html_segtoc,
                 t_a_.title,
                 _auth,
               ) ~ "\n";
@@ -289,7 +368,7 @@ template DocReformMetaDocHarvestsTopics() {
                     }
                   }
                   topics ~= format(q"┃<p class="work"><a href="%s">%s</a> -%s┃",
-                    "url",
+                    t_a_.path_html_segtoc,
                     t_a_.title,
                     _auth,
                   ) ~ "\n";
@@ -329,7 +408,7 @@ template DocReformMetaDocHarvestsTopics() {
                       }
                     }
                     topics ~= format(q"┃<p class="work"><a href="%s">%s</a> -%s┃",
-                      "url",
+                      t_a_.path_html_segtoc,
                       t_a_.title,
                       _auth,
                     ) ~ "\n";
@@ -369,7 +448,7 @@ template DocReformMetaDocHarvestsTopics() {
                         }
                       }
                       topics ~= format(q"┃ <p class="work"><a href="%s">%s</a> -%s┃",
-                        "url",
+                        t_a_.path_html_segtoc,
                         t_a_.title,
                         _auth,
                       ) ~ "\n";
@@ -396,8 +475,10 @@ template DocReformMetaDocHarvestsTopics() {
 </body>
 </html>
 ┃") ~ "\n";
+    import doc_reform.output.paths_output;
+    auto out_pth = DocReformPathsHTML!()(_opt_action.output_dir_set, "");
     try {
-      auto f = File("topics.html", "w");
+      auto f       = File(out_pth.harvest("topics.html"), "w");
       foreach (o; topics) {
         f.writeln(o);
       }
diff --git a/src/doc_reform/output/paths_output.d b/src/doc_reform/output/paths_output.d
index c11d31e..795da4c 100644
--- a/src/doc_reform/output/paths_output.d
+++ b/src/doc_reform/output/paths_output.d
@@ -10,13 +10,12 @@ import doc_reform.meta.rgx;
 template DocReformOutPaths() {
   auto DocReformOutPaths(Po,Lng)(
     Po  output_pth_root,
-    Lng lng,
+    Lng lng = "",
   ) {
     struct _PathsStruct {
       string output_root() {
         return (output_pth_root.length > 0)
-        ? output_pth_root
-        : "sisugen";
+        ? output_pth_root : "";
       }
       string output_base() {
         return asNormalizedPath(output_root.chainPath(lng)).array;
@@ -32,8 +31,7 @@ template DocReformOutPathSQLite() {
     struct _PathsStruct {
       string output_root() {
         return (output_pth_root.length > 0)
-        ? output_pth_root
-        : "sisugen";
+        ? output_pth_root : "";
       }
       string output_base() {
         return asNormalizedPath(output_root).array;
@@ -114,28 +112,34 @@ template DocReformPathsUrl() {
     return _UrlPathsStruct();
   }
 }
-template DocReformPathsHTML() {
+template DocReformDocRootTreeHTML() {
   mixin DocReformRgxInit;
   static auto rgx = Rgx();
-  auto DocReformPathsHTML(Po,Lng)(
-    Po  output_pth_root,
-    Lng lng,
-  ) {
-    auto out_pth = DocReformOutPaths!()(output_pth_root, lng);
+  auto DocReformDocRootTreeHTML(Lng)(Lng lng) {
+    auto lng_pth = DocReformOutPaths!()("", lng);
     string base_dir = "html";
     string suffix = ".html";
     struct _PathsStruct {
       string base_filename(string fn_src) {
         return fn_src.baseName.stripExtension;
       }
+      string base_filename_scroll(string fn_src) {
+        return base_filename(fn_src) ~ "." ~ lng;
+      }
+      string base_filename_seg(string fn_src) {
+        return base_filename(fn_src) ~ "." ~ lng;
+      }
+      string docroot() {
+        return asNormalizedPath(lng_pth.output_root).array;
+      }
       string base() {
-        return asNormalizedPath((out_pth.output_base).chainPath(base_dir)).array;
+        return asNormalizedPath((lng).chainPath(base_dir)).array;
       }
       string image() {
-        return asNormalizedPath((out_pth.output_root).chainPath("image")).array;
+        return asNormalizedPath("image").array;
       }
       string css() {
-        return asNormalizedPath((out_pth.output_root).chainPath("css")).array;
+        return asNormalizedPath("css").array;
       }
       string fn_seg_css() {
         return asNormalizedPath(css.chainPath("html_seg.css")).array;
@@ -144,19 +148,19 @@ template DocReformPathsHTML() {
         return asNormalizedPath(css.chainPath("html_scroll.css")).array;
       }
       string seg(string fn_src) {
-        return asNormalizedPath(base.chainPath(base_filename(fn_src))).array;
+        return asNormalizedPath(base.chainPath(base_filename_seg(fn_src))).array;
       }
       string fn_scroll(string fn_src) {
-        return asNormalizedPath(base.chainPath(base_filename(fn_src) ~ suffix)).array;
+        return asNormalizedPath(base.chainPath(base_filename_scroll(fn_src) ~ suffix)).array;
       }
       string fn_seg(string fn_src, string seg_filename) {
         return asNormalizedPath(seg(fn_src).chainPath(seg_filename ~ suffix)).array;
       }
       string tail_seg(string fn_src) {
-        return lng ~ "/html/" ~ base_filename(fn_src);
+        return lng ~ "/html/" ~ base_filename_seg(fn_src);
       }
       string tail_fn_scroll(string fn_src) {
-        return lng ~ "/html/" ~ base_filename(fn_src) ~ suffix;
+        return lng ~ "/html/" ~ base_filename_scroll(fn_src) ~ suffix;
       }
       string tail_fn_seg(string fn_src, string seg_filename) {
         return lng ~ "/html/" ~ seg(fn_src) ~ "/" ~ seg_filename ~ suffix;
@@ -165,6 +169,114 @@ template DocReformPathsHTML() {
     return _PathsStruct();
   }
 }
+template DocReformPathsHTML() {
+  mixin DocReformRgxInit;
+  static auto rgx = Rgx();
+  auto DocReformPathsHTML(Po,Lng)(
+    Po  root_pth,
+    Lng lng,
+  ) {
+    auto doc_tree = DocReformDocRootTreeHTML!()(lng);
+    string base_dir = "html";
+    string suffix = ".html";
+    struct _PathsStruct {
+      string docroot() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.docroot)).array;
+      }
+      string harvest(string fn_harvest) {
+        return docroot ~ "/" ~ fn_harvest;
+      }
+      string base() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.base)).array;
+      }
+      string image() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.image)).array;
+      }
+      string css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.css)).array;
+      }
+      string fn_seg_css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_seg_css)).array;
+      }
+      string fn_scroll_css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_scroll_css)).array;
+      }
+      string seg(string fn_src) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.seg(fn_src))).array;
+      }
+      string fn_scroll(string fn_src) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_scroll(fn_src))).array;
+      }
+      string fn_seg(string fn_src, string seg_filename) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_seg(fn_src, seg_filename))).array;
+      }
+      string tail_seg(string fn_src) {
+        return doc_tree.tail_seg(fn_src);
+      }
+      string tail_fn_scroll(string fn_src) {
+        return doc_tree.tail_fn_scroll(fn_src);
+      }
+      string tail_fn_seg(string fn_src, string seg_filename) {
+        return doc_tree.tail_fn_seg(fn_src, seg_filename);
+      }
+    }
+    return _PathsStruct();
+  }
+}
+template DocReformUrlPathsHTML() {
+  mixin DocReformRgxInit;
+  static auto rgx = Rgx();
+  auto DocReformUrlPathsHTML(Po,Lng)(
+    Po  root_pth,
+    Lng lng,
+  ) {
+    auto doc_tree = DocReformDocRootTreeHTML!()(lng);
+    string base_dir = "html";
+    string suffix = ".html";
+    struct _PathsStruct {
+      string docroot() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.docroot)).array;
+      }
+      string harvest(string fn_harvest) {
+        return docroot ~ "/" ~ fn_harvest;
+      }
+      string base() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.base)).array;
+      }
+      string image() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.image)).array;
+      }
+      string css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.css)).array;
+      }
+      string fn_seg_css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_seg_css)).array;
+      }
+      string fn_scroll_css() {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_scroll_css)).array;
+      }
+      string seg(string fn_src) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.seg(fn_src))).array;
+      }
+      string fn_scroll(string fn_src) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_scroll(fn_src))).array;
+      }
+      string fn_seg(string fn_src, string seg_filename) {
+        return asNormalizedPath(root_pth.chainPath(doc_tree.fn_seg(fn_src, seg_filename))).array;
+      }
+      string tail_seg(string fn_src) {
+        return doc_tree.tail_seg(fn_src);
+      }
+      string tail_fn_scroll(string fn_src) {
+        return doc_tree.tail_fn_scroll(fn_src);
+      }
+      string tail_fn_seg(string fn_src, string seg_filename) {
+        return doc_tree.tail_fn_seg(fn_src, seg_filename);
+      }
+    }
+    return _PathsStruct();
+  }
+}
 template DocReformPathsEPUB() {
   mixin DocReformRgxInit;
   static auto rgx = Rgx();
@@ -179,7 +291,7 @@ template DocReformPathsEPUB() {
         return asNormalizedPath((out_pth.output_base).chainPath(base_dir)).array;
       }
       string base_filename(string fn_src) {
-        return fn_src.baseName.stripExtension;
+        return fn_src.baseName.stripExtension ~ "." ~ lng;
       }
       string epub_file(string fn_src) {
         return asNormalizedPath(base.chainPath(base_filename(fn_src) ~ ".epub")).array;
@@ -277,12 +389,12 @@ template DocReformPathsODT() {
         return asNormalizedPath((out_pth.output_base).chainPath(base_dir)).array;
       }
       string odt_file() {
-        return asNormalizedPath(base_pth.chainPath(doc_matters.src.filename_base ~ ".odt")).array;
+        return asNormalizedPath(base_pth.chainPath(doc_matters.src.doc_uid_out ~ ".odt")).array;
       }
       string dirtop(string type) {
         return (type == "zip")
         ? "".chainPath("").array
-        : asNormalizedPath(base_pth.chainPath(doc_matters.src.filename_base)).array;
+        : asNormalizedPath(base_pth.chainPath(doc_matters.src.doc_uid_out)).array;
       }
       string mimetype(string type="fs") {
         assert(type == "zip" || "fs");
diff --git a/src/doc_reform/source/paths_source.d b/src/doc_reform/source/paths_source.d
index bf4ee55..408d227 100644
--- a/src/doc_reform/source/paths_source.d
+++ b/src/doc_reform/source/paths_source.d
@@ -199,6 +199,19 @@ template PathMatters() {
             }
             return _uid;
           }
+          string doc_uid_out() {
+            string _uid;
+            if (is_pod && !(pod_name_with_path.empty)) {
+              if (pod_name_with_path.baseName == filename_base) {
+                _uid = filename_base ~ "." ~ lng;
+              } else {
+                _uid = pod_name_with_path.baseName ~ mkup.sep ~ filename_base ~ "." ~ lng;
+              }
+            } else {
+              _uid = "_" ~ filename_base ~ "." ~ lng;
+            }
+            return _uid;
+          }
           string docname_composite_unique_per_src_doc() {
             string _fn;
             if (pod_name_with_path.baseName == filename_base) {
-- 
cgit v1.2.3