From a9a46fca7397aaa357bfdc2b98e181617bb6887b Mon Sep 17 00:00:00 2001
From: Ralph Amissah <ralph@amissah.com>
Date: Mon, 1 May 2017 18:46:11 -0400
Subject: xmls work particularly with epub output

---
 src/sdp/abstraction.d            |   9 +-
 src/sdp/ao_abstract_doc_source.d | 149 ++++++++++++++++++++----------
 src/sdp/output_epub3.d           | 190 +++++++++++++++++++++++----------------
 src/sdp/output_html.d            |   4 +-
 src/sdp/output_xmls.d            | 112 ++++++++++++-----------
 src/sdp/output_xmls_css.d        |   8 +-
 6 files changed, 293 insertions(+), 179 deletions(-)

(limited to 'src/sdp')

diff --git a/src/sdp/abstraction.d b/src/sdp/abstraction.d
index d6124a0..51b76d6 100644
--- a/src/sdp/abstraction.d
+++ b/src/sdp/abstraction.d
@@ -37,7 +37,7 @@ template SiSUabstraction() {
   mixin outputHub;
   enum headBody { header, body_content, insert_filelist }
   enum makeMeta { make, meta }
-  enum docAbst  { doc_abstraction, section_keys, segnames, images }
+  enum docAbst  { doc_abstraction, section_keys, segnames, segnames_0_4, images }
   auto rgx = Rgx();
   auto SiSUabstraction(Fn,O,E)(Fn fn_src, O opts, E env){
     auto sdl_root_configuration = ConfigHub!()("conf.sdl", env);
@@ -69,10 +69,11 @@ template SiSUabstraction() {
       opts
     );
     static assert(!isTypeTuple!(da));
-    static assert(da.length==4);
+    static assert(da.length==5);
     auto doc_abstraction = da[docAbst.doc_abstraction]; // head ~ toc ~ body ~ endnotes_seg ~ glossary ~ bibliography ~ bookindex ~blurb;
     auto _document_section_keys_sequenced = da[docAbst.section_keys];
     string[] _doc_html_segnames = da[docAbst.segnames];
+    string[] _doc_epub_segnames_0_4 = da[docAbst.segnames_0_4];
     auto _images = da[docAbst.images];
     struct DocumentMatters {
       auto keys_seq() {
@@ -84,6 +85,10 @@ template SiSUabstraction() {
         string[] _k = _doc_html_segnames;
         return _k;
       }
+      string[] segnames_lv_0_to_4() {
+        string[] _k = _doc_epub_segnames_0_4;
+        return _k;
+      }
       auto dochead_make() {
         string[string][string] _k = _make_and_meta[makeMeta.make];
         return _k;
diff --git a/src/sdp/ao_abstract_doc_source.d b/src/sdp/ao_abstract_doc_source.d
index f7eca53..f231af6 100644
--- a/src/sdp/ao_abstract_doc_source.d
+++ b/src/sdp/ao_abstract_doc_source.d
@@ -346,6 +346,7 @@ template SiSUdocAbstraction() {
     auto bookindex_extract_hash = BookIndexNuggetHash();
     string[][string] lev4_subtoc;
     string[] html_segnames=["toc"];
+    int cnt1 = 1; int cnt2 = 1; int cnt3 = 1;
     /+ abstraction init ↑ +/
     /+ ↓ loop markup document/text line by line +/
     srcDocLoop:
@@ -435,6 +436,7 @@ template SiSUdocAbstraction() {
               comp_obj_heading_.text                  = "Glossary";
               comp_obj_heading_.ocn                   = 0;
               comp_obj_heading_.obj_cite_number       = "";
+              comp_obj_heading_.segment_anchor_tag    = "_part_glossary";
               comp_obj_heading_.marked_up_level       = "B";
               comp_obj_heading_.heading_lev_markup    = 1;
               comp_obj_heading_.heading_lev_collapsed = 1;
@@ -503,6 +505,7 @@ template SiSUdocAbstraction() {
               comp_obj_heading_.text                  = "Blurb";
               comp_obj_heading_.ocn                   = 0;
               comp_obj_heading_.obj_cite_number       = "";
+              comp_obj_heading_.segment_anchor_tag    = "_part_blurb";
               comp_obj_heading_.marked_up_level       = "B";
               comp_obj_heading_.heading_lev_markup    = 1;
               comp_obj_heading_.heading_lev_collapsed = 1;
@@ -744,8 +747,28 @@ template SiSUdocAbstraction() {
                 segment_anchor_tag_that_object_belongs_to = anchor_tag_;
                 segment_anchor_tag_that_object_belongs_to_uri = anchor_tag_ ~ ".fnSuffix#" ~ obj_cite_number.to!string;
               } else if (an_object["lev_markup_number"].to!int < 4) {
-                segment_anchor_tag_that_object_belongs_to = "";
-                segment_anchor_tag_that_object_belongs_to_uri = "";
+              string segn;
+                switch (an_object["lev_markup_number"].to!int) {
+                case 0:
+                  segn = "_the_title";
+                  goto default;
+                case 1:
+                  segn = "_part_" ~ cnt1.to!string;
+                  ++cnt1;
+                  goto default;
+                case 2:
+                  segn = "_part_" ~  cnt1.to!string ~ "_" ~ cnt2.to!string;
+                  ++cnt2;
+                  goto default;
+                case 3:
+                  segn =  "_part_" ~  cnt1.to!string ~ "_" ~ cnt2.to!string ~ "_" ~ cnt3.to!string;
+                  ++cnt3;
+                  goto default;
+                default:
+                  segment_anchor_tag_that_object_belongs_to = segn;
+                  segment_anchor_tag_that_object_belongs_to_uri = segn ~ ".fnSuffix";
+                  break;
+                }
               }
               an_object["bookindex_nugget"] =
                 ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : "";
@@ -949,6 +972,7 @@ template SiSUdocAbstraction() {
       comp_obj_heading_.text                  = "Bibliography";
       comp_obj_heading_.ocn                   = 0;
       comp_obj_heading_.obj_cite_number       = "";
+      comp_obj_heading_.segment_anchor_tag    = "_part_bibliography";
       comp_obj_heading_.marked_up_level       = "B";
       comp_obj_heading_.heading_lev_markup    = 1;
       comp_obj_heading_.heading_lev_collapsed = 1;
@@ -1264,11 +1288,15 @@ template SiSUdocAbstraction() {
       }
       return images_;
     }
+    string[] segnames_0_4;
     foreach (ref obj; the_document_head_section) {
       if (obj.is_a == "heading") {
         debug(dom) {
           writeln(obj.text);
         }
+        if (obj.heading_lev_markup <= 4) {
+          segnames_0_4 ~= obj.segment_anchor_tag;
+        }
         if ((opt_action_bool["html"])
         || (opt_action_bool["html_scroll"])
         || (opt_action_bool["html_seg"])
@@ -1286,9 +1314,12 @@ template SiSUdocAbstraction() {
       dom_collapsed_buffer = dom_collapsed.dup;
       foreach (ref obj; the_table_of_contents_section["scroll"]) {
         if (obj.is_a == "heading") {
-          if (obj.heading_lev_markup == 4) {
-            obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+          if (obj.heading_lev_markup <= 4) {
+            segnames_0_4 ~= obj.segment_anchor_tag;
+            if (obj.heading_lev_markup == 4) {
+              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+              assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+            }
           }
           if ((opt_action_bool["html"])
           || (opt_action_bool["html_scroll"])
@@ -1309,9 +1340,12 @@ template SiSUdocAbstraction() {
           debug(dom) {
             writeln(obj.text);
           }
-          if (obj.heading_lev_markup == 4) {
-            obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
-            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+          if (obj.heading_lev_markup <= 4) {
+            segnames_0_4 ~= obj.segment_anchor_tag;
+            if (obj.heading_lev_markup == 4) {
+              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+              assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
+            }
           }
           if ((opt_action_bool["html"])
           || (opt_action_bool["html_scroll"])
@@ -1333,13 +1367,16 @@ template SiSUdocAbstraction() {
           debug(dom) {
             writeln(obj.text);
           }
-          if (obj.heading_lev_markup == 4) {
-            obj.lev4_subtoc = lev4_subtoc[obj.segment_anchor_tag];
-            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-            if (html_segnames.length > obj.ptr_html_segnames + 1) {
-              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+          if (obj.heading_lev_markup <= 4) {
+            segnames_0_4 ~= obj.segment_anchor_tag;
+            if (obj.heading_lev_markup == 4) {
+              obj.lev4_subtoc = lev4_subtoc[obj.segment_anchor_tag];
+              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+              if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+              }
+              assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
             }
-            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
           }
           if ((opt_action_bool["html"])
           || (opt_action_bool["html_scroll"])
@@ -1368,12 +1405,15 @@ template SiSUdocAbstraction() {
           debug(dom) {
             writeln(obj.text);
           }
-          if (obj.heading_lev_markup == 4) {
-            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-            if (html_segnames.length > obj.ptr_html_segnames + 1) {
-              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+          if (obj.heading_lev_markup <= 4) {
+            segnames_0_4 ~= obj.segment_anchor_tag;
+            if (obj.heading_lev_markup == 4) {
+              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+              if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+              }
+              assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
             }
-            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
           }
           if ((opt_action_bool["html"])
           || (opt_action_bool["html_scroll"])
@@ -1395,12 +1435,15 @@ template SiSUdocAbstraction() {
           debug(dom) {
             writeln(obj.text);
           }
-          if (obj.heading_lev_markup == 4) {
-            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-            if (html_segnames.length > obj.ptr_html_segnames + 1) {
-              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+          if (obj.heading_lev_markup <= 4) {
+            segnames_0_4 ~= obj.segment_anchor_tag;
+            if (obj.heading_lev_markup == 4) {
+              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+              if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+              }
+              assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
             }
-            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
           }
           if ((opt_action_bool["html"])
           || (opt_action_bool["html_scroll"])
@@ -1422,12 +1465,15 @@ template SiSUdocAbstraction() {
           debug(dom) {
             writeln(obj.text);
           }
-          if (obj.heading_lev_markup == 4) {
-            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-            if (html_segnames.length > obj.ptr_html_segnames + 1) {
-              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+          if (obj.heading_lev_markup <= 4) {
+            segnames_0_4 ~= obj.segment_anchor_tag;
+            if (obj.heading_lev_markup == 4) {
+              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+              if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+              }
+              assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
             }
-            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
           }
           if ((opt_action_bool["html"])
           || (opt_action_bool["html_scroll"])
@@ -1450,12 +1496,15 @@ template SiSUdocAbstraction() {
         if (obj.is_a == "heading") {
           debug(dom) {
           }
-          if (obj.heading_lev_markup == 4) {
-            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-            if (html_segnames.length > obj.ptr_html_segnames + 1) {
-              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+          if (obj.heading_lev_markup <= 4) {
+            segnames_0_4 ~= obj.segment_anchor_tag;
+            if (obj.heading_lev_markup == 4) {
+              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+              if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+              }
+              assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
             }
-            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
           }
           if ((opt_action_bool["html"])
           || (opt_action_bool["html_scroll"])
@@ -1476,12 +1525,15 @@ template SiSUdocAbstraction() {
           debug(dom) {
             writeln(obj.text);
           }
-          if (obj.heading_lev_markup == 4) {
-            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-            if (html_segnames.length > obj.ptr_html_segnames + 1) {
-              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+          if (obj.heading_lev_markup <= 4) {
+            segnames_0_4 ~= obj.segment_anchor_tag;
+            if (obj.heading_lev_markup == 4) {
+              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+              if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+              }
+              assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
             }
-            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
           }
           if ((opt_action_bool["html"])
           || (opt_action_bool["html_scroll"])
@@ -1503,12 +1555,15 @@ template SiSUdocAbstraction() {
           debug(dom) {
             writeln(obj.text);
           }
-          if (obj.heading_lev_markup == 4) {
-            obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
-            if (html_segnames.length > obj.ptr_html_segnames + 1) {
-              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+          if (obj.heading_lev_markup <= 4) {
+            segnames_0_4 ~= obj.segment_anchor_tag;
+            if (obj.heading_lev_markup == 4) {
+              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1];
+              if (html_segnames.length > obj.ptr_html_segnames + 1) {
+                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1];
+              }
+              assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
             }
-            assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]);
           }
           if ((opt_action_bool["html"])
           || (opt_action_bool["html_scroll"])
@@ -1621,6 +1676,7 @@ template SiSUdocAbstraction() {
       document_the,
       docSectKeysSeq!()(document_section_keys_sequenced),
       segnames,
+      segnames_0_4,
       images,
     );
     return t;
@@ -2633,7 +2689,6 @@ template SiSUdocAbstraction() {
       auto substantive_obj_misc_tuple =
         obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa);
       an_object["substantive"]                  = substantive_obj_misc_tuple[sObj.content];
-      anchor_tags                               = substantive_obj_misc_tuple[sObj.anchor_tags];
       comp_obj_block                            = comp_obj_block.init;
       comp_obj_block.use                        = "body";
       comp_obj_block.is_of                      = "block";
@@ -2675,7 +2730,7 @@ template SiSUdocAbstraction() {
       comp_obj_poem_ocn.is_a                    = "poem";
       comp_obj_poem_ocn.ocn                     = obj_cite_number;
       comp_obj_poem_ocn.obj_cite_number         = (obj_cite_number_poem["start"], obj_cite_number_poem["end"]);
-      comp_obj_poem_ocn.text                    = ""; // an_object["substantive"];
+      comp_obj_poem_ocn.text                    = "";
       the_document_body_section                 ~= comp_obj_poem_ocn;
       type["blocks"]                            = TriState.off;
       type["poem"]                              = TriState.off;
@@ -4631,6 +4686,7 @@ template SiSUdocAbstraction() {
         comp_obj_heading_.text                  = "Book Index";
         comp_obj_heading_.ocn                   = 0;
         comp_obj_heading_.obj_cite_number       = "";
+        comp_obj_heading_.segment_anchor_tag    = "_part_book_index";
         comp_obj_heading_.marked_up_level       = "B";
         comp_obj_heading_.heading_lev_markup    = 1;
         comp_obj_heading_.heading_lev_collapsed = 1;
@@ -4852,6 +4908,7 @@ template SiSUdocAbstraction() {
         comp_obj_heading_.text                  = "Endnotes";
         comp_obj_heading_.ocn                   = 0;
         comp_obj_heading_.obj_cite_number       = "";
+        comp_obj_heading_.segment_anchor_tag    = "_part_endnotes";
         comp_obj_heading_.marked_up_level       = "B";
         comp_obj_heading_.heading_lev_markup    = 1;
         comp_obj_heading_.heading_lev_collapsed = 1;
diff --git a/src/sdp/output_epub3.d b/src/sdp/output_epub3.d
index 3df1992..074808c 100644
--- a/src/sdp/output_epub3.d
+++ b/src/sdp/output_epub3.d
@@ -122,10 +122,24 @@ template outputEPub3() {
   string epub3_oebps_toc_nav_xhtml(D,I)(D doc_abstraction, I doc_matters) {
     enum DomTags { none, open, close, close_and_open, open_still, }
     auto markup = InlineMarkup();
-    string toc ="<nav epub:type=\"toc\" id=\"toc\">\n";
+    auto rgx = Rgx();
+    string toc =format("<html xmlns=\"http://www.w3.org/1999/xhtml\"
+      xmlns:epub=\"http://www.idpf.org/2007/ops\">
+  <head>
+    <title>%s</title>
+  </head>
+  <body>
+    <section epub:type=\"frontmatter toc\">
+      <header>
+        <h1>Contents</h1>
+      </header>
+      <nav epub:type=\"toc\" id=\"toc\">\n",
+      doc_matters.dochead_meta["title"]["full"],
+    );
     foreach (sect; doc_matters.keys_seq.seg) {
       foreach (obj; doc_abstraction[sect]) {
         if (obj.is_a == "heading") {
+          string _txt = obj.text.replaceAll(rgx.inline_notes_al_gen, "").strip;
           foreach_reverse (n; 0 .. 7) {
             string k = n.to!string;
             switch (obj.dom_collapsed[n]) {
@@ -135,10 +149,12 @@ template outputEPub3() {
               break;
             case DomTags.close_and_open :
               toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "</li>" ~ "\n";
-              if  (obj.dom_markedup[n] < 4) {
+              if  (obj.heading_lev_markup < 4) {
                 toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n"
                 ~ markup.indent_by_spaces_provided((n + 2), "  ")
-                ~ "<span class=\"navhd\">" ~ obj.text ~ "</span>" ~ "\n";
+                ~ "<a href=\"" ~ obj.segment_anchor_tag ~ ".xhtml" ~ "\">"
+                ~ _txt
+                ~ "</a>" ~ "\n";
               } else {
                 string hashtag =(obj.heading_lev_markup == 4)
                 ? ""
@@ -146,15 +162,18 @@ template outputEPub3() {
                 toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n"
                 ~ markup.indent_by_spaces_provided((n + 2), "  ")
                 ~ "<a href=\"" ~ obj.segment_anchor_tag ~ ".xhtml" ~ hashtag ~ "\">"
-                ~ obj.text
+                ~ _txt
                 ~ "</a>" ~ "\n";
               }
               break;
             case DomTags.open :
               toc ~= markup.indent_by_spaces_provided(n, "  ") ~ "<ol>" ~ "\n";
-              if  (obj.dom_markedup[n] < 4) {
-                toc ~= markup.indent_by_spaces_provided(n, "  ")
-                ~ "<li><span class=\"navhd\">" ~ obj.text ~ "</span>" ~ "\n";
+              if  (obj.heading_lev_markup < 4) {
+                toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n"
+                ~ markup.indent_by_spaces_provided((n + 2), "  ")
+                ~ "<a href=\"" ~ obj.segment_anchor_tag ~ ".xhtml" ~ "\">"
+                ~ _txt
+                ~ "</a>" ~ "\n";
               } else {
                 string hashtag =(obj.heading_lev_markup == 4)
                 ? ""
@@ -162,7 +181,7 @@ template outputEPub3() {
                 toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n"
                 ~ markup.indent_by_spaces_provided((n + 2), "  ")
                 ~ "<a href=\"" ~ obj.segment_anchor_tag ~ ".xhtml" ~ hashtag ~ "\">"
-                ~ obj.text
+                ~ _txt
                 ~ "</a>" ~ "\n";
               }
               break;
@@ -173,77 +192,85 @@ template outputEPub3() {
         }
       }
     }
-    toc ~="</nav>\n";
+    toc ~="</nav>
+      </section>
+    </body>
+  </html>\n";
     return toc;
   }
   string epub2_oebps_toc_ncx(D,I)(D doc_abstraction, I doc_matters) {
     int counter = 0;
     string uuid = "18275d951861c77f78acd05672c9906924c59f18a2e0ba06dad95959693e9bd8"; // TODO shared elsewhere
     auto markup = InlineMarkup();
+    auto rgx = Rgx();
     enum DomTags { none, open, close, close_and_open, open_still, }
     string toc = format(q"¶<?xml version='1.0' encoding='utf-8'?>
   <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
-    <head>
-      <!-- four required metadata items (for all NCX documents,
-        (including the relaxed constraints of OPS 2.0) -->
-      <title>%s%s</title>
-      <link rel="stylesheet" href="css/epub.css" type="text/css" id="main-css" />
-      <meta name="dtb:uid" content="urn:uuid:%s" />
-      <!-- <meta name="epub-creator" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> -->
-      <meta name="dtb:depth" content="%s" />
-      <meta name="dtb:totalPageCount" content="0" />
-      <meta name="dtb:maxPageNumber" content="0" />
-    </head>
-    <docTitle>
-      <text>%s</text>
-    </docTitle>
-    <docAuthor>
-      <text>%s</text>
-    </docAuthor>
-    <navMap>¶",
-      doc_matters.dochead_meta["title"]["full"],                                                               // title
-      (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : " by " ~ doc_matters.dochead_meta["creator"]["author"], // author
-      uuid,                                                                                        // uuid
-      "3",                                                                                         // content depth
-      doc_matters.dochead_meta["title"]["full"],                                                               // title
-      (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : doc_matters.dochead_meta["creator"]["author"],          // author
+  <head>
+    <!-- four required metadata items (for all NCX documents,
+      (including the relaxed constraints of OPS 2.0) -->
+    <title>%s%s</title>
+    <link rel="stylesheet" href="css/epub.css" type="text/css" id="main-css" />
+    <meta name="dtb:uid" content="urn:uuid:%s" />
+    <!-- <meta name="epub-creator" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> -->
+    <meta name="dtb:depth" content="%s" />
+    <meta name="dtb:totalPageCount" content="0" />
+    <meta name="dtb:maxPageNumber" content="0" />
+  </head>
+  <docTitle>
+    <text>%s</text>
+  </docTitle>
+  <docAuthor>
+    <text>%s</text>
+  </docAuthor>
+  <navMap>¶",
+      doc_matters.dochead_meta["title"]["full"],                          // title
+      (doc_matters.dochead_meta["creator"]["author"].empty) ? ""
+        : " by " ~ doc_matters.dochead_meta["creator"]["author"],         // author
+      uuid,                                                               // uuid
+      "3",                                                                // content depth
+      doc_matters.dochead_meta["title"]["full"],                          // title
+      (doc_matters.dochead_meta["creator"]["author"].empty) ? ""
+        : doc_matters.dochead_meta["creator"]["author"],                  // author
     );
     foreach (sect; doc_matters.keys_seq.seg) {
       foreach (obj; doc_abstraction[sect]) {
         if (obj.is_a == "heading") {
+          string _txt = obj.text.replaceAll(rgx.inline_notes_al_gen, "").strip;
+          string hashtag =(obj.heading_lev_markup <= 4) ? "" : ("#" ~ obj.ocn.to!string);
           foreach_reverse (k; 0 .. 7) {
             switch (obj.dom_markedup[k]) {
             case DomTags.close :
-              // writeln(markup.indent_by_spaces_provided(k), "</", k, ">"); // --debug dom tags
-  toc ~= "</navPoint>";
+              toc ~= "\n    </navPoint>";
               break;
             case DomTags.close_and_open :
-              // writeln(markup.indent_by_spaces_provided(k), "</", k, ">"); // --debug dom tags
-              // writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text); // --debug dom tags
               ++counter;
-  toc ~= "</navPoint>";
-  toc ~= format(q"¶<navPoint class="chapter" id="navpoint" playOrder="%s">
-  <navLabel>
-    <text>%s</text>
-  </navLabel>
-  <content src="%s" />¶",
-  counter,
-  obj.text,
-  obj.segment_anchor_tag,   // lev < 4 [no link]; lev == 4 [filename] markup.xhtml; lev > 4 [filename#ocn] (links done in segment_anchor_tag)
-  );
+              toc ~= "\n    </navPoint>";
+              toc ~= format(q"¶
+    <navPoint class="chapter" id="navpoint" playOrder="%s">
+      <navLabel>
+        <text>%s</text>
+      </navLabel>
+      <content src="%s.xhtml%s" />¶",
+                counter,
+                _txt,
+                obj.segment_anchor_tag,
+                hashtag,
+              );
               break;
             case DomTags.open :
-              // writeln(markup.indent_by_spaces_provided(k), "<", k, ">", obj.text); // --debug dom tags
               ++counter;
-  toc ~= format(q"¶<navPoint class="chapter" id="navpoint" playOrder="%s">
-  <navLabel>
-    <text>%s</text>
-  </navLabel>
-  <content src="%s" />¶",
-  counter,
-  obj.text,
-  obj.segment_anchor_tag,   // lev < 4 [no link]; lev == 4 [filename] markup.xhtml; lev > 4 [filename#ocn] (fix links in segment_anchor_tag)
-  );
+              toc ~= format(q"¶
+    <navPoint class="chapter" id="navpoint" playOrder="%s">
+      <navLabel>
+        <text>%s</text>
+      </navLabel>
+      <content src="%s.xhtml%s" />¶",
+                counter,
+                _txt,
+                obj.segment_anchor_tag,
+                hashtag,
+              );
               break;
             default :
               break;
@@ -271,6 +298,7 @@ template outputEPub3() {
     string[] top_level_headings = ["","","",""];
     string[string] oepbs_content_parts;
     string suffix = ".xhtml";
+    string[] doc_parts_;
     foreach (part; doc_matters.keys_seq.seg) {
       foreach (obj; doc_abstraction[part]) {
         string _txt = xhtml_format.special_characters(obj, obj.text);
@@ -298,23 +326,23 @@ template outputEPub3() {
               top_level_headings[3] = "";
               goto default;
             default:
-              auto t = xhtml_format.heading_seg(obj, suffix);
-              top_level_headings[obj.heading_lev_markup] = t[0];
+              doc_parts_ ~= obj.segment_anchor_tag;
+              doc_epub3[obj.segment_anchor_tag] ~= xhtml_format.epub3_seg_head(doc_matters);
+              auto t = xhtml_format.heading_seg(obj, _txt, suffix, "epub");
+              doc_epub3[obj.segment_anchor_tag] ~= t[0];
+              doc_epub3_endnotes[obj.segment_anchor_tag] ~= t[1];
               break;
             }
             break;
           case 4:
             segment_filename = obj.segment_anchor_tag;
-            doc_epub3[segment_filename] ~= xhtml_format.epub3_seg_head(doc_matters.dochead_meta);
-            foreach (top_level_heading; top_level_headings) {
-              doc_epub3[segment_filename] ~= top_level_heading;
-            }
-            auto t = xhtml_format.heading_seg(obj, _txt, suffix);
+            doc_epub3[segment_filename] ~= xhtml_format.epub3_seg_head(doc_matters);
+            auto t = xhtml_format.heading_seg(obj, _txt, suffix, "epub");
             doc_epub3[segment_filename] ~= t[0];
             doc_epub3_endnotes[segment_filename] ~= t[1];
             break;
           case 5: .. case 7:
-            auto t = xhtml_format.heading_seg(obj, _txt, suffix);
+            auto t = xhtml_format.heading_seg(obj, _txt, suffix, "epub");
             doc_epub3[segment_filename] ~= t[0];
             doc_epub3_endnotes[segment_filename] ~= t[1];
             break;
@@ -337,7 +365,9 @@ template outputEPub3() {
             case "para":
               switch (obj.is_a) {
               case "toc":
-                doc_epub3[segment_filename] ~= xhtml_format.toc_seg(obj, _txt);
+                auto t = xhtml_format.para_seg(obj, _txt, suffix);
+                doc_epub3[segment_filename] ~= t[0];
+                doc_epub3_endnotes[segment_filename] ~= t[1];
                 break;
               default:
                 if ((doc_matters.opt_action_bool["debug"])) {
@@ -467,35 +497,41 @@ template outputEPub3() {
           }
         }
         if (obj.is_a == "heading") {
-          if (obj.heading_lev_markup == 4) {
-            oepbs_content_parts["manifest_documents"] ~= format(q"¶      <item id="%s.xhtml" href="%s.xhtml" media-type="application/xhtml+xml" />
+          if (obj.heading_lev_markup <= 4) {
+            oepbs_content_parts["manifest_documents"] ~=
+              format(q"¶      <item id="%s.xhtml" href="%s.xhtml" media-type="application/xhtml+xml" />
   ¶",
               obj.segment_anchor_tag,
               obj.segment_anchor_tag,
             );
-            oepbs_content_parts["spine"] ~= format(q"¶    <itemref idref="%s.xhtml" linear="yes" />
+            oepbs_content_parts["spine"] ~=
+              format(q"¶    <itemref idref="%s.xhtml" linear="yes" />
   ¶",
               obj.segment_anchor_tag,
             );
-            oepbs_content_parts["guide"] ~= format(q"¶      <reference type="%s" href="%s" />
+            oepbs_content_parts["guide"] ~=
+              format(q"¶      <reference type="%s" href="%s" />
   ¶",
               obj.segment_anchor_tag,
               obj.segment_anchor_tag,
             );
           } else if (obj.heading_lev_markup > 4) {
-            oepbs_content_parts["manifest_documents"] ~= format(q"¶      <item id="%s.xhtml#%s" href="%s.xhtml#%s" media-type="application/xhtml+xml" />
+            oepbs_content_parts["manifest_documents"] ~=
+              format(q"¶      <item id="%s.xhtml#%s" href="%s.xhtml#%s" media-type="application/xhtml+xml" />
   ¶",
               obj.segment_anchor_tag,
               obj.obj_cite_number,
               obj.segment_anchor_tag,
               obj.obj_cite_number,
             );
-            oepbs_content_parts["spine"] ~= format(q"¶    <itemref idref="%s.xhtml#%s" linear="yes" />
+            oepbs_content_parts["spine"] ~=
+              format(q"¶    <itemref idref="%s.xhtml#%s" linear="yes" />
   ¶",
               obj.segment_anchor_tag,
               obj.obj_cite_number,
             );
-            oepbs_content_parts["guide"] ~= format(q"¶      <reference type="%s#%s" href="%s#%s" />
+            oepbs_content_parts["guide"] ~=
+              format(q"¶      <reference type="%s#%s" href="%s#%s" />
   ¶",
               obj.segment_anchor_tag,
               obj.obj_cite_number,
@@ -521,6 +557,7 @@ template outputEPub3() {
       oebps_toc_nav_xhtml,
       oebps_toc_ncx,
       oebps_content_opf,
+      doc_parts_,
     );
   }
   void epub3_write_output_files(M,D,E,Mt,Mic,Otnx,Otn,Oc)(
@@ -532,8 +569,8 @@ template outputEPub3() {
     Otnx oebps_toc_nav_xhtml,
     Otn  oebps_toc_ncx,
     Oc   oebps_content_opf,
+    string[] doc_parts_,
   ) {
-    auto css = SiSUcss();
     debug(asserts) {
       static assert(is(typeof(doc_epub3)              == string[][string]));
       static assert(is(typeof(mimetypes)              == string));
@@ -567,7 +604,7 @@ template outputEPub3() {
         }
       }
       { /+ OEBPS/[segments].xhtml (the document contents) +/
-        foreach (seg_filename; doc_matters.segnames) {
+        foreach (seg_filename; doc_matters.segnames_lv_0_to_4) {
           string fn = pth_epub3.fn_oebps_content_xhtml(doc_matters.source_filename, seg_filename);
           /+ add zip archive file members (with their content) +/
           auto zip_arc_member_file = new ArchiveMember();
@@ -717,6 +754,7 @@ template outputEPub3() {
         }
       }
       { /+ OEBPS/epub.css +/
+        auto css = SiSUcss();
         debug(epub_output) {
           fn_dbg = pth_epub3.dbg_fn_oebps_css(doc_matters.source_filename);
           File(fn_dbg, "w").writeln(css.epub_css);
@@ -727,7 +765,7 @@ template outputEPub3() {
         // add OEBPS/content.opf to zip archive
         zip_arc_member_file.name = fn;
         auto zip_data = new OutBuffer();
-        zip_data.write(oebps_content_opf.dup); // cast as: char[]
+        zip_data.write(css.epub_css.dup); // cast as: char[]
         zip_arc_member_file.expandedData = zip_data.toBytes();
         zip.addMember(zip_arc_member_file);
         /+ create the zip file +/
diff --git a/src/sdp/output_html.d b/src/sdp/output_html.d
index 509ae43..048d6e9 100644
--- a/src/sdp/output_html.d
+++ b/src/sdp/output_html.d
@@ -169,7 +169,7 @@ template outputHTML() {
         }
       }
     }
-    doc = xhtml_format.html_scroll_head(doc_matters.dochead_meta) ~ doc_html ~ xhtml_format.tail;
+    doc = xhtml_format.html_scroll_head(doc_matters) ~ doc_html ~ xhtml_format.tail;
     scroll_write_output(doc_matters, doc);
   }
   void scroll_write_output(M,C)(
@@ -244,7 +244,7 @@ template outputHTML() {
             break;
           case 4:
             segment_filename = obj.segment_anchor_tag;
-            doc_html[segment_filename] ~= xhtml_format.html_seg_head(doc_matters.dochead_meta);
+            doc_html[segment_filename] ~= xhtml_format.html_seg_head(doc_matters);
             foreach (top_level_heading; top_level_headings) {
               // writeln(top_level_heading);
               doc_html[segment_filename] ~= top_level_heading;
diff --git a/src/sdp/output_xmls.d b/src/sdp/output_xmls.d
index 347409e..78ee414 100644
--- a/src/sdp/output_xmls.d
+++ b/src/sdp/output_xmls.d
@@ -72,12 +72,9 @@ template outputXHTMLs() {
       }
       return tags;
     }
-    auto html_scroll_head(Me)(
-      Me dochead_meta,
+    auto html_scroll_head(Dm)(
+      Dm doc_matters,
     ) {
-      debug(asserts) {
-        static assert(is(typeof(dochead_meta) == string[string][string]));
-      }
       string o;
       o = format(q"¶<!DOCTYPE html>
     <html>
@@ -105,19 +102,17 @@ template outputXHTMLs() {
       <link href="../../css/html.css" rel="stylesheet" />
       <link href="../../../css/html.css" rel="stylesheet" />
     </head>
-    <body lang="en">
+    <body lang="%s">
     <a name="top" id="top"></a>¶",
-    dochead_meta["title"]["full"],
-    (dochead_meta["creator"]["author"].empty) ? "" : ", " ~ dochead_meta["creator"]["author"],
-    );
+        doc_matters.dochead_meta["title"]["full"],
+        (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : ", " ~ doc_matters.dochead_meta["creator"]["author"],
+        doc_matters.language,
+      );
       return o;
     }
-    auto html_seg_head(Me)(
-      Me dochead_meta,
+    auto html_seg_head(Dm)(
+      Dm doc_matters,
     ) {
-      debug(asserts) {
-        static assert(is(typeof(dochead_meta) == string[string][string]));
-      }
       string o;
       o = format(q"¶<!DOCTYPE html>
     <html>
@@ -145,57 +140,69 @@ template outputXHTMLs() {
       <link href="../../css/html.css" rel="stylesheet" />
       <link href="../../../css/html.css" rel="stylesheet" />
     </head>
-    <body lang="en">
+    <body lang="%s">
     <a name="top" id="top"></a>¶",
-    dochead_meta["title"]["full"],
-    (dochead_meta["creator"]["author"].empty) ? "" : ", " ~ dochead_meta["creator"]["author"],
-    );
+        doc_matters.dochead_meta["title"]["full"],
+        (doc_matters.dochead_meta["creator"]["author"].empty) ? ""
+          : ", " ~ doc_matters.dochead_meta["creator"]["author"],
+        doc_matters.language,
+      );
       return o;
     }
-    auto epub3_seg_head(Me)(
-      Me dochead_meta,
+    auto epub3_seg_head(Dm)(
+      Dm doc_matters,
     ) {
-      debug(asserts) {
-        static assert(is(typeof(dochead_meta) == string[string][string]));
-      }
-      string html_simple = format(q"¶<!DOCTYPE html>
+      string html_base = format(q"¶<!DOCTYPE html>
     <html>¶",
     );
+      string html_simple = format(q"¶<!DOCTYPE html>
+    <html
+      xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:epub="http://www.idpf.org/2007/ops"
+      lang="%s" xml:lang="%s">¶",
+        doc_matters.language,
+        doc_matters.language,
+      );
       string html_strict = format(q"¶<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-    <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">¶",
-    );
+    <html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:epub="http://www.idpf.org/2007/ops"
+      lang="%s" xml:lang="%s">¶",
+        doc_matters.language,
+        doc_matters.language,
+      );
       string o;
       o = format(q"¶%s
     <head>
-      <meta charset="utf-8">
-        <title>
-          %s%s
-        </title>
-        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
-        <meta name="dc.title" content="Title" />
-        <meta name="dc.author" content="Author" />
-        <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" />
-        <meta name="dc.date" content="year" />
-        <meta name="dc.date.created" content="year" />
-        <meta name="dc.date.issued" content="year" />
-        <meta name="dc.date.available" content="year" />
-        <meta name="dc.date.valid" content="year" />
-        <meta name="dc.date.modified" content="year" />
-        <meta name="dc.language" content="US" />
-        <meta name="dc.rights" content="Copyright: Copyright (C) year holder" />
-        <meta name="generator" content="sdp [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" />
-      </meta>
+      <title>
+        %s%s
+      </title>
+      <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+      <meta name="dc.title" content="%s" />
+      <meta name="dc.author" content="%s" />
+      <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" />
+      <meta name="dc.date" content="year" />
+      <meta name="dc.date.created" content="year" />
+      <meta name="dc.date.issued" content="year" />
+      <meta name="dc.date.available" content="year" />
+      <meta name="dc.date.valid" content="year" />
+      <meta name="dc.date.modified" content="year" />
+      <meta name="dc.language" content="US" />
+      <meta name="dc.rights" content="Copyright: Copyright (C) year holder" />
+      <meta name="generator" content="sdp [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" />
       <link rel="generator" href="http://www.sisudoc.org/" />
       <link rel="shortcut icon" href="../_sisu/image/rb7.ico" />
       <link rel="stylesheet" href="css/epub.css" type="text/css" id="main-css" />
     </head>
-    <body lang="en">
+    <body lang="%s">
     <a name="top" id="top"></a>¶",
-    html_strict,
-    dochead_meta["title"]["full"],
-    (dochead_meta["creator"]["author"].empty) ? "" : ", " ~ dochead_meta["creator"]["author"],
-    );
+        html_simple,
+        doc_matters.dochead_meta["title"]["full"],
+        (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : ", " ~ doc_matters.dochead_meta["creator"]["author"],
+        doc_matters.dochead_meta["title"]["full"],
+        (doc_matters.dochead_meta["creator"]["author"].empty) ? "" : ", " ~ doc_matters.dochead_meta["creator"]["author"],
+        doc_matters.language,
+      );
       return o;
     }
     auto tail() {
@@ -357,10 +364,12 @@ template outputXHTMLs() {
     auto heading(O)(
       auto return ref const O    obj,
       string                     _txt,
+      string                     _type="html",
     ) {
       auto tags = _xhtml_anchor_tags(obj.anchor_tags);
       string _horizontal_rule = "<hr />";
-      if  (obj.heading_lev_markup == 0) {
+      if ((_type != "html")
+      || (obj.heading_lev_markup == 0 || obj.heading_lev_markup > 4)) {
         _horizontal_rule = "";
       }
       string o;
@@ -414,11 +423,12 @@ template outputXHTMLs() {
       auto return ref const O    obj,
       string                     _txt,
       string                     _suffix = ".html",
+      string                     _type = "html",
     ) {
       auto t = inline_markup_seg(obj, _txt, _suffix);
       _txt = t[0];
       string[] _endnotes = t[1];
-      string o = heading(obj, _txt);
+      string o = heading(obj, _txt, _type);
       auto u = tuple(
         o,
         _endnotes,
diff --git a/src/sdp/output_xmls_css.d b/src/sdp/output_xmls_css.d
index 8d7c0ff..c746b16 100644
--- a/src/sdp/output_xmls_css.d
+++ b/src/sdp/output_xmls_css.d
@@ -848,8 +848,12 @@ template SiSUcss() {
     color: #000000;
     background-color: #f9f9aa;
   }
+  /* in toc no list numbering */
+  nav#toc ol {
+    list-style-type: none;
+  }
 ";
-    struct _CSS {
+    struct _css {
       auto html_css() {
         string _css = "/* SiSU css html stylesheet */\n" ~ css_shared;
         return _css;
@@ -859,6 +863,6 @@ template SiSUcss() {
         return _css;
       }
     }
-    return _CSS();
+    return _css();
   }
 }
-- 
cgit v1.2.3