From 6f27312b0e61932d820b991a15c44845ff2cee75 Mon Sep 17 00:00:00 2001
From: Ralph Amissah <ralph@amissah.com>
Date: Sun, 26 Feb 2017 18:27:08 -0500
Subject: 0.13.5 defaults regex reorganised; some work on (x)html output

---
 org/ao_conf_make_meta.org          |   2 +-
 org/ao_doc_abstraction.org         | 274 +++++++++++------
 org/defaults.org                   |  51 ++--
 org/output.org                     | 606 +++++++++++++++++++++++++++----------
 org/sdp.org                        |   2 +-
 src/sdp/ao_abstract_doc_source.d   | 157 +++++-----
 src/sdp/ao_conf_make_meta_sdlang.d |   2 +-
 src/sdp/ao_rgx.d                   |  50 ++-
 src/sdp/output_epub.d              |  66 ++--
 src/sdp/output_html.d              | 289 ++++++++++--------
 src/sdp/output_hub.d               |   4 +-
 src/sdp/output_rgx.d               |  37 +++
 src/sdp/output_xhtmls.d            | 212 ++++++++++++-
 src/sdp/source_sisupod.d           |   8 +-
 views/version.txt                  |   2 +-
 15 files changed, 1221 insertions(+), 541 deletions(-)
 create mode 100644 src/sdp/output_rgx.d

diff --git a/org/ao_conf_make_meta.org b/org/ao_conf_make_meta.org
index 040df50..398b369 100644
--- a/org/ao_conf_make_meta.org
+++ b/org/ao_conf_make_meta.org
@@ -375,7 +375,7 @@ private auto headerSDLangToAAmake(Tag,Ma)(Tag header_sdlang, Ma dochead_make) {
   string[] authors_arr;
   auto authors_raw_arr = split(dochead_meta["creator"]["author"], rgx.arr_delimiter);
   foreach (author_raw; authors_raw_arr) {
-    authors_arr ~= replace(author_raw, rgx.raw_author_munge, "$2 $1");
+    authors_arr ~= (author_raw).replace(rgx.raw_author_munge, "$2 $1");
   }
   dochead_meta["creator"]["author"] = join(authors_arr, ", ").chomp.chomp;
   auto t = tuple(dochead_make, dochead_meta);
diff --git a/org/ao_doc_abstraction.org b/org/ao_doc_abstraction.org
index 338fae8..fce5c90 100644
--- a/org/ao_doc_abstraction.org
+++ b/org/ao_doc_abstraction.org
@@ -532,7 +532,7 @@ scope(failure) {
     line,
   );
 }
-line = replaceAll(line, rgx.true_dollar, "$$$$");
+line = (line).replaceAll(rgx.true_dollar, "$$$$");
   // dollar represented as $$ needed to stop submatching on $
   // (substitutions using ${identifiers} must take into account (i.e. happen earlier))
 debug(source) {                                  // source lines
@@ -2577,7 +2577,7 @@ void _biblio_block_(
           tmp ~= au.str;
         }
       }
-      tmp = replace(tmp, rgx.trailing_comma, "");
+      tmp = (tmp).replace(rgx.trailing_comma, "");
       j["author"].str = tmp;
       goto default;
     case "editor_raw": // editor_arr editor (fn sn)
@@ -2592,7 +2592,7 @@ void _biblio_block_(
           tmp ~= ed.str;
         }
       }
-      tmp = replace(tmp, rgx.trailing_comma, "");
+      tmp = (tmp).replace(rgx.trailing_comma, "");
       j["editor"].str = tmp;
       goto default;
     case "fulltitle": // title & subtitle
@@ -3550,10 +3550,11 @@ auto _heading_matched_(L,C,O,K,Lv,Lc,T,Me)(
     assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels
     switch (an_object["lev"]) {
     case "A":
-      an_object[an_object_key]=replaceFirst(an_object[an_object_key],
-        rgx.variable_doc_title, (dochead_meta_aa["title"]["full"] ~ ","));
-      an_object[an_object_key]=replaceFirst(an_object[an_object_key],
-        rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]);
+      an_object[an_object_key]=(an_object[an_object_key])
+        .replaceFirst(rgx.variable_doc_title,
+          (dochead_meta_aa["title"]["full"] ~ ","))
+        .replaceFirst(rgx.variable_doc_author,
+          dochead_meta_aa["creator"]["author"]);
       collapsed_lev["h0"] = 0;
       an_object["lev_collapsed_number"] =
         to!string(collapsed_lev["h0"]);
@@ -3674,7 +3675,7 @@ auto _heading_matched_(L,C,O,K,Lv,Lc,T,Me)(
 
 #+name: abs_functions_para
 #+BEGIN_SRC d
-auto _para_match_(L,O,K,I,B,T,C)(
+void _para_match_(L,O,K,I,B,T,C)(
   return ref L  line,
   return ref O  an_object,
   return ref K  an_object_key,
@@ -3764,6 +3765,8 @@ struct OCNemitter {
 
 ***** object inline markup munge                          :markup:inline:
 
+****** 0. struct, inline markup munge
+
 #+name: ao_emitters_obj_inline_markup_munge
 #+BEGIN_SRC d
 struct ObjInlineMarkupMunge {
@@ -3780,17 +3783,21 @@ struct ObjInlineMarkupMunge {
     n_foot_sp_asterisk = 0;
     n_foot_sp_plus = 0;
   }
-  string url_links(Ot)(Ot obj_txt_in, string suffix = ".html") {
+#+END_SRC
+
+****** url links
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
+  string url_links(Ot)(Ot obj_txt_in) {
     debug(asserts){
       static assert(is(typeof(obj_txt_in) == string));
     }
     /+ url matched +/
-    if (match(obj_txt_in, rgx.inline_url)) {
+    if (match(obj_txt_in, rgx.inline_url_generic)) {
       /+ link: naked url: http://url +/
       if (match(obj_txt_in, rgx.inline_link_naked_url)) {
-        obj_txt_in =
-          replaceAll(
-            obj_txt_in,
+        obj_txt_in = (obj_txt_in).replaceAll(
             rgx.inline_link_naked_url,
             ("$1"
               ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c
@@ -3804,44 +3811,44 @@ struct ObjInlineMarkupMunge {
            { link which includes url as footnote }http://url~{ { http://url }http://url }~
       +/
       if (match(obj_txt_in, rgx.inline_link_endnote_url_helper)) {
-        obj_txt_in =
-          replaceAll(
-            obj_txt_in,
-            rgx.inline_link_endnote_url_helper_punctuated,
-            (mkup.lnk_o ~ "$1" ~ mkup.lnk_c
-              ~ mkup.url_o ~ "$2" ~ mkup.url_c
-              ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c
-              ~ mkup.url_o ~ "$2" ~ mkup.url_c
-              ~  " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3")
-          );
-        obj_txt_in =
-          replaceAll(
-            obj_txt_in,
-            rgx.inline_link_endnote_url_helper,
-            (mkup.lnk_o ~ "$1" ~ mkup.lnk_c
-              ~ mkup.url_o ~ "$2" ~ mkup.url_c
-              ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c
-              ~ mkup.url_o ~ "$2" ~ mkup.url_c
-              ~  " }~") // ("{ $1 }$2~{ { $2 }$2 }~")
-          );
+        obj_txt_in = (obj_txt_in).replaceAll(
+          rgx.inline_link_endnote_url_helper_punctuated,
+          (mkup.lnk_o ~ "$1" ~ mkup.lnk_c
+            ~ mkup.url_o ~ "$2" ~ mkup.url_c
+            ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c
+            ~ mkup.url_o ~ "$2" ~ mkup.url_c
+            ~  " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3")
+        );
+        obj_txt_in = (obj_txt_in).replaceAll(
+          rgx.inline_link_endnote_url_helper,
+          (mkup.lnk_o ~ "$1" ~ mkup.lnk_c
+            ~ mkup.url_o ~ "$2" ~ mkup.url_c
+            ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c
+            ~ mkup.url_o ~ "$2" ~ mkup.url_c
+            ~  " }~") // ("{ $1 }$2~{ { $2 }$2 }~")
+        );
       }
       /+ link with regular markup:
          { linked text or image }http://url
       +/
       if (match(obj_txt_in, rgx.inline_link_markup_regular)) {
-        obj_txt_in =
-          replaceAll(
-            obj_txt_in,
-            rgx.inline_link_markup_regular,
-            ("$1"
-              ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c
-              ~  mkup.url_o ~ "$3" ~  mkup.url_c
-              ~ "$4")            // ("$1{ $2 }$3$4")
-          );
+        obj_txt_in = (obj_txt_in).replaceAll(
+          rgx.inline_link_markup_regular,
+          ("$1"
+            ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c
+            ~  mkup.url_o ~ "$3" ~  mkup.url_c
+            ~ "$4")            // ("$1{ $2 }$3$4")
+        );
       }
     }
     return obj_txt_in;
   }
+#+END_SRC
+
+****** footnotes endnotes markup
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   auto footnotes_endnotes_markup_and_number_or_stars(Ot)(Ot obj_txt_in, bool reset_note_numbers) {
     debug(asserts){
       static assert(is(typeof(obj_txt_in) == string));
@@ -3849,12 +3856,10 @@ struct ObjInlineMarkupMunge {
     /+ endnotes (regular) +/
     bool flg_notes_reg  = false;
     bool flg_notes_star = false;
-    obj_txt_in =
-      replaceAll(
-        obj_txt_in,
-        rgx.inline_notes_curly,
-        (mkup.en_a_o ~ " $1" ~ mkup.en_a_c)
-      );
+    obj_txt_in = (obj_txt_in).replaceAll(
+      rgx.inline_notes_curly,
+      (mkup.en_a_o ~ " $1" ~ mkup.en_a_c)
+    );
     if (!(stage_reset_note_numbers) && reset_note_numbers) {
       stage_reset_note_numbers = true;
     }
@@ -3873,22 +3878,18 @@ struct ObjInlineMarkupMunge {
             ++n_foot_sp_asterisk;
             asterisks_ = "*";
             n_foot=n_foot_sp_asterisk;
-            obj_txt_out ~=
-              (replaceFirst(
-                to!string(n.hit),
-                rgx.inline_al_delimiter_open_symbol_star,
-                (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ")
-              ) ~ "\n");
+            obj_txt_out ~= (to!string(n.hit)).replaceFirst(
+              rgx.inline_al_delimiter_open_symbol_star,
+              (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ")
+            ) ~ "\n";
           } else if (match(to!string(n.hit), rgx.inline_al_delimiter_open_regular)) {
             flg_notes_reg =  true;
             ++n_foot_reg;
             n_foot=n_foot_reg;
-            obj_txt_out ~=
-              (replaceFirst(
-                to!string(n.hit),
-                rgx.inline_al_delimiter_open_regular,
-                (mkup.en_a_o ~ to!string(n_foot) ~ " ")
-              ) ~ "\n");
+            obj_txt_out ~= (to!string(n.hit)).replaceFirst(
+              rgx.inline_al_delimiter_open_regular,
+              (mkup.en_a_o ~ to!string(n_foot) ~ " ")
+            ) ~ "\n";
           } else {
             obj_txt_out ~= to!string(n.hit) ~ "\n";
           }
@@ -3904,6 +3905,12 @@ struct ObjInlineMarkupMunge {
     );
     return t;
   }
+#+END_SRC
+
+****** object notes and links
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   private auto object_notes_and_links_(Ot)(Ot obj_txt_in, bool reset_note_numbers=false)
   in {
     debug(asserts){
@@ -3960,6 +3967,18 @@ struct ObjInlineMarkupMunge {
   }
   invariant() {
   }
+#+END_SRC
+
+****** para
+- paragraph text without other identification until two new lines
+- general markup
+  - paragraph attributes
+  - font faces (bold, italics, underscore etc.)
+  - footnotes/endnotes
+  - links
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   auto para(Ot)(Ot obj_txt_in)
   in {
     debug(asserts){
@@ -3967,9 +3986,9 @@ struct ObjInlineMarkupMunge {
     }
   }
   body {
-    obj_txt["munge"]=obj_txt_in;
-    obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.para_attribs, "");
-    obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.obj_cite_number_off_all, "");
+    obj_txt["munge"]=(obj_txt_in)
+      .replaceFirst(rgx.para_attribs, "")
+      .replaceFirst(rgx.obj_cite_number_off_all, "");
     auto t = object_notes_and_links_(obj_txt["munge"]);
     debug(munge) {
       writeln(__LINE__);
@@ -3979,6 +3998,14 @@ struct ObjInlineMarkupMunge {
     }
     return t;
   }
+#+END_SRC
+
+****** heading
+- identified text by heading level marker followed by text until two new lines
+- general markup
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   auto heading(Ot)(Ot obj_txt_in, bool reset_note_numbers=false)
   in {
     debug(asserts){
@@ -3986,10 +4013,10 @@ struct ObjInlineMarkupMunge {
     }
   }
   body {
-    obj_txt["munge"]=obj_txt_in;
-    obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.heading, "");
-    obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.obj_cite_number_off_all, "");
-    obj_txt["munge"]=strip(obj_txt["munge"]);
+    obj_txt["munge"]=(obj_txt_in)
+     .replaceFirst(rgx.heading, "")
+     .replaceFirst(rgx.obj_cite_number_off_all, "")
+     .strip;
     auto t = object_notes_and_links_(obj_txt["munge"], reset_note_numbers);
     debug(munge) {
       writeln(__LINE__);
@@ -4001,7 +4028,16 @@ struct ObjInlineMarkupMunge {
   }
   invariant() {
   }
-  /+ revisit +/
+#+END_SRC
+
+****** code
+- newlines
+- indentation
+- possibly identify syntax for coloring
+- no general markup
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   string code(Ot)(Ot obj_txt_in)
   in {
     debug(asserts){
@@ -4014,6 +4050,19 @@ struct ObjInlineMarkupMunge {
   }
   invariant() {
   }
+#+END_SRC
+
+****** group
+- group block identified by open an close tags
+- general markup
+  - paragraph attributes
+  - font faces (bold, italics, underscore etc.)
+  - footnotes/endnotes
+  - links
+- newlines detected and kept?
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   auto group(string obj_txt_in)
   in { }
   body {
@@ -4023,6 +4072,19 @@ struct ObjInlineMarkupMunge {
   }
   invariant() {
   }
+#+END_SRC
+
+****** block
+- group block identified by open an close tags
+- general markup
+  - paragraph attributes
+  - font faces (bold, italics, underscore etc.)
+  - footnotes/endnotes
+  - links
+- newlines detected and kept?
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   auto block(Ot)(Ot obj_txt_in)
   in {
     debug(asserts){
@@ -4036,6 +4098,19 @@ struct ObjInlineMarkupMunge {
   }
   invariant() {
   }
+#+END_SRC
+
+****** verse (poem)
+- sub part of poem block which is identified by open an close tags, separated from other verse by double newline
+- newlines
+- indentation
+- what part of general markup?
+  - font faces (bold, italics, underscore etc.)
+  - footnotes/endnotes
+  - links?
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   auto verse(Ot)(Ot obj_txt_in)
   in {
     debug(asserts){
@@ -4049,6 +4124,12 @@ struct ObjInlineMarkupMunge {
   }
   invariant() {
   }
+#+END_SRC
+
+****** quote
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   string quote(Ot)(Ot obj_txt_in)
   in {
     debug(asserts){
@@ -4061,6 +4142,14 @@ struct ObjInlineMarkupMunge {
   }
   invariant() {
   }
+#+END_SRC
+
+****** table
+- table block identified by open an close tags
+- table markup
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   string table(Ot)(Ot obj_txt_in)
   in {
     debug(asserts){
@@ -4073,6 +4162,12 @@ struct ObjInlineMarkupMunge {
   }
   invariant() {
   }
+#+END_SRC
+
+****** comment
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
   string comment(Ot)(Ot obj_txt_in)
   in {
     debug(asserts){
@@ -4085,6 +4180,12 @@ struct ObjInlineMarkupMunge {
   }
   invariant() {
   }
+#+END_SRC
+
+****** 0. close
+
+#+name: ao_emitters_obj_inline_markup_munge
+#+BEGIN_SRC d
 }
 #+END_SRC
 
@@ -4200,12 +4301,9 @@ struct ObjInlineMarkup {
      static assert(is(typeof(heading_toc_) == char[]));
    }
    auto m = matchFirst(cast(char[]) heading_toc_, rgx.heading);
-   heading_toc_ =
-     replaceAll(
-       m.post,
-       rgx.inline_notes_curly_gen,
-       ("")
-     );
+   heading_toc_ = (m.post).replaceAll(
+     rgx.inline_notes_curly_gen,
+     "");
    return heading_toc_;
   };
   auto table_of_contents_gather_headings(O,Ma,Ts,Ta,X,Toc)(
@@ -4491,10 +4589,11 @@ private:
           writeln(heading_number_auto_composite);
         }
         if (!empty(heading_number_auto_composite)) {
-          munge_=replaceFirst(munge_, rgx.heading,
-            "$1~$2 " ~ heading_number_auto_composite ~ ". ");
-          munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
-            "$1~" ~ heading_number_auto_composite ~ " ");
+          munge_=(munge_)
+            .replaceFirst(rgx.heading,
+              "$1~$2 " ~ heading_number_auto_composite ~ ". ")
+            .replaceFirst(rgx.heading_marker_missing_tag,
+              "$1~" ~ heading_number_auto_composite ~ " ");
         }
       }
     }
@@ -4521,16 +4620,19 @@ private:
     if (!(match(munge_, rgx.heading_anchor_tag))) { // if (anchor_tags_.length == 0) {
       if (match(munge_, rgx.heading_identify_anchor_tag)) {
         if (auto m = match(munge_, rgx.heading_extract_named_anchor_tag)) {
-          munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
+          munge_=(munge_).replaceFirst(
+            rgx.heading_marker_missing_tag,
             "$1~" ~ toLower(m.captures[1]) ~ "_"  ~ m.captures[2] ~ " ");
         } else if (auto m = match(munge_, rgx.heading_extract_unnamed_anchor_tag)) {
-          munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
+          munge_=(munge_).replaceFirst(
+            rgx.heading_marker_missing_tag,
             "$1~" ~ "s" ~ m.captures[1] ~ " ");
         }
       } else if (lev_ == "1") { // (if not successful) manufacture a unique anchor tag for lev=="1"
         static __gshared int heading_num_lev1 = 0;
         heading_num_lev1 ++;
-        munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
+        munge_=(munge_).replaceFirst(
+          rgx.heading_marker_missing_tag,
           "$1~" ~ "x" ~ to!string(heading_num_lev1) ~ " ");
       }
     }
@@ -5094,7 +5196,7 @@ struct BookIndexReportSection {
     foreach (mainkey; mainkeys) {
       write("_0_1 !{", mainkey, "}! ");
       foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
-        auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+        auto go = (ref_).replaceAll(rgx.book_index_go, "$1");
         write(" {", ref_, "}#", go, ", ");
       }
       writeln(" \\\\");
@@ -5104,7 +5206,7 @@ struct BookIndexReportSection {
       foreach (subkey; subkeys) {
         write("  ", subkey, ", ");
         foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
-          auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+          auto go = (ref_).replaceAll(rgx.book_index_go, "$1");
           write(" {", ref_, "}#", go, ", ");
         }
         writeln(" \\\\");
@@ -5239,8 +5341,8 @@ struct BookIndexReportSection {
           bi_tmp_seg ~= " \\\\\n    ";
           ++skn;
         }
-        bi_tmp_scroll                       = replaceFirst(bi_tmp_scroll, rgx.trailing_linebreak, "");
-        bi_tmp_seg                          = replaceFirst(bi_tmp_seg, rgx.trailing_linebreak, "");
+        bi_tmp_scroll                       = (bi_tmp_scroll).replaceFirst(rgx.trailing_linebreak, "");
+        bi_tmp_seg                          = (bi_tmp_seg).replaceFirst(rgx.trailing_linebreak, "");
         comp_obj_para                       = comp_obj_para.init;
         comp_obj_para.use                   = "backmatter";
         comp_obj_para.is_of                 = "para";
@@ -6106,7 +6208,7 @@ auto assertions_flag_types_block_status_none_or_closed(T)(T type) {
 }
 #+END_SRC
 
-* 2. Object Setter                                          :abstract:object:
+* 2. Object Setter (Set Abstract Object)                    :abstract:object:
 
 set abstracted objects for downstream processing
 
diff --git a/org/defaults.org b/org/defaults.org
index 616921b..5ba63df 100644
--- a/org/defaults.org
+++ b/org/defaults.org
@@ -585,20 +585,6 @@ static levels_numbered                                = ctRegex!(`^[0-9]$`);
 static levels_numbered_headings                       = ctRegex!(`^[0-7]$`);
 #+END_SRC
 
-*** filename (and path) matching (including markup insert file) :insert:file:path:filename:
-
-#+name: ao_rgx
-#+BEGIN_SRC d
-static src_pth                                        = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])$`);
-static src_fn                                         =
-  ctRegex!(`^([a-zA-Z0-9._-]+/)*(?P<fn_src>(?P<fn_base>[a-zA-Z0-9._-]+)[.](?P<fn_src_suffix>ss[tm]))$`);
-static src_fn_master                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssm)$`);
-static src_fn_text                                    = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]sst)$`);
-static src_fn_insert                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssi)$`);
-static src_fn_find_inserts                            = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[im])$`);
-static insert_src_fn_ssi_or_sst                       = ctRegex!(`^<<\s*(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`);
-#+END_SRC
-
 *** comments                                                      :comment:
 
 #+name: ao_rgx
@@ -672,7 +658,7 @@ static para_bullet                                    = ctRegex!(`^_[*] `);
 static para_bullet_indent                             = ctRegex!(`^_([1-9])[*] `);
 static para_indent                                    = ctRegex!(`^_([1-9]) `);
 static para_indent_hang                               = ctRegex!(`^_([0-9])_([0-9]) `);
-static para_attribs                                   = ctRegex!(`^_(([0-9])(_([0-9]))?|_([1-9])?[*]) `);
+static para_attribs                                   = ctRegex!(`^_(?:(?:[0-9])(?:_([0-9]))?|(?:[1-9])?[*]) `);
 #+END_SRC
 
 *** blocked markup                                              :block:tic:
@@ -764,8 +750,9 @@ static note_ref                                       = ctRegex!(`^\S+?noteref_(
 
 #+name: ao_rgx
 #+BEGIN_SRC d
-static inline_url                                      = ctRegex!(`((?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+)`, "mg");
-static inline_link_naked_url                           = ctRegex!(`(?P<before>^|[ ])(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!]?(?:[ ]|$))`, "mg");
+static inline_url_generic                              = ctRegex!(`(?:^|[}(\[ ])(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_]`, "mg");
+static inline_url                                      = ctRegex!(`((?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_]\S*)`, "mg");
+static inline_link_naked_url                           = ctRegex!(`(?P<before>^|[ ])(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!'"]?(?:[ ]|$))`, "mg");
 static inline_link_markup_regular                      = ctRegex!(`(?P<before>^|[ ])\{\s*(?P<content>.+?)\s*\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!]?(?:[ ]|$))`, "mg");
 static inline_link_endnote_url_helper_punctuated       = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!]?(?:[ ]|$))`, "mg");
 static inline_link_endnote_url_helper                  = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+)`, "mg");
@@ -1028,12 +1015,12 @@ http://dlang.org/phobos/std_regex.html
 *** 0. code template:                                                 :rgx:
 
 #+name: tangle_ao_rgx
-#+BEGIN_SRC d :tangle ../src/sdp/ao_rgx.d
+#+BEGIN_SRC d :tangle ../src/sdp/output_rgx.d
 /++
   regex: regular expressions used in sisu document parser
 +/
 template SiSUoutputRgxInit() {
-  private import output_defaults;
+  private import defaults;
   struct Rgx {
     <<prgmkup_rgx>>
   }
@@ -1167,6 +1154,21 @@ template SiSUlanguageCodes() {
 #+END_SRC
 
 ** 1. ctRegex                                                        :regex:
+
+*** filename (and path) matching (including markup insert file) :insert:file:path:filename:
+
+#+name: prgmkup_rgx
+#+BEGIN_SRC d
+static src_pth                                        = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])$`);
+static src_fn                                         =
+  ctRegex!(`^([a-zA-Z0-9._-]+/)*(?P<fn_src>(?P<fn_base>[a-zA-Z0-9._-]+)[.](?P<fn_src_suffix>ss[tm]))$`);
+static src_fn_master                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssm)$`);
+static src_fn_text                                    = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]sst)$`);
+static src_fn_insert                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssi)$`);
+static src_fn_find_inserts                            = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[im])$`);
+static insert_src_fn_ssi_or_sst                       = ctRegex!(`^<<\s*(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`);
+#+END_SRC
+
 *** inline (internal program) markup footnotes endnotes   :inline:footnote:
 
 #+name: prgmkup_rgx
@@ -1187,6 +1189,17 @@ static inline_text_and_note_al                        = ctRegex!(`(?P<text>.+?)
 static inline_text_and_note_al_                       = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|$))`, "mg");
 #+END_SRC
 
+#+name: prgmkup_rgx
+#+BEGIN_SRC d
+/+ inline markup footnotes endnotes +/
+static inline_link                                    = ctRegex!(`┥(.+?)┝┤(.+?)├`, "mg");
+static inline_a_url                                   = ctRegex!(`(┤)(\S+?)(├)`, "mg");
+static fn_suffix                                      = ctRegex!(`\.fnSuffix`, "mg");
+static inline_link_fn_suffix                          = ctRegex!(`¤(.+?)(\.fnSuffix)`, "mg");
+static inline_seg_link                                = ctRegex!(`(¤)(?:.+?)\.fnSuffix`, "mg");
+static mark_internal_site_lnk                         = ctRegex!(`¤`, "mg");
+#+END_SRC
+
 * +set colors for terminal+ (unused)                          :colors:terminal:
 
 #+name: ao_ansi_colors
diff --git a/org/output.org b/org/output.org
index b77449d..8ad43d9 100644
--- a/org/output.org
+++ b/org/output.org
@@ -45,10 +45,10 @@ template outputHub() {
     output_xhtmls,
     source_sisupod;
   import
-    ao_rgx,
+    output_rgx,
     output_xhtmls;
   void outputHub(D,I)(D doc_abstraction, I doc_matters) {
-    mixin SiSUrgxInit;
+    mixin SiSUoutputRgxInit;
     auto rgx = Rgx();
     if ((doc_matters.opt_action_bool["verbose"])) {
       writeln(doc_matters.keys_seq_seg);
@@ -131,9 +131,10 @@ private import
   std.typecons,
   std.uni,
   std.utf,
-  defaults;
+  std.conv : to;
 import
-  ao_rgx,
+  defaults,
+  output_rgx,
   output_xhtmls;
 #+END_SRC
 
@@ -148,6 +149,7 @@ template SiSUpod() {
     try {
       <<source_sisupod_mkdirs>>
       <<source_sisupod_copy>>
+      <<source_sisupod_zip>>
     }
     catch (ErrnoException ex) {
       // Handle error
@@ -163,7 +165,7 @@ template SiSUpod() {
 debug(asserts){
   // static assert(is(typeof(doc_matters) == tuple));
 }
-mixin SiSUrgxInit;
+mixin SiSUoutputRgxInit;
 mixin SiSUpaths;
 auto pth_sisupod = SiSUpodPaths();
 mixin SiSUlanguageCodes;
@@ -255,11 +257,14 @@ foreach (image; doc_matters.image_list) {
 ** text [#C]                                                          :text:
 ** xml offspring (xhtml html epub)                                     :xml:
 *** format xhtml objects                                           :format:
-**** xhtml common template                                      :template:
+**** 0. xhtml common template                                   :template:
 
 #+BEGIN_SRC d :tangle ../src/sdp/output_xhtmls.d
 template outputXHTMLs() {
+  <<output_imports>>
+  mixin SiSUoutputRgxInit;
   struct outputXHTMLs {
+    auto rgx = Rgx();
     <<xhtml_format_objects>>
 <<xhtml_format_objects_code>>
   }
@@ -390,6 +395,168 @@ auto tail() {
 }
 #+END_SRC
 
+**** inline markup
+***** links
+
+#+name: xhtml_format_objects
+#+BEGIN_SRC d
+auto inline_links(O)(
+  auto return ref const O obj,
+  string                  _txt,
+  string                  _suffix    = ".html",
+  string                  seg_scroll = "seg",
+) {
+  if (obj.inline_links) {
+    if ((seg_scroll == "scroll")
+    && match(_txt, rgx.mark_internal_site_lnk)) {
+      _txt = (_txt).replaceAll(
+        rgx.inline_seg_link,
+        "$1");
+    }
+    _txt = (_txt).replaceAll(
+      rgx.inline_link_fn_suffix,
+      ("$1" ~ _suffix));
+    _txt = (_txt).replaceAll(
+      rgx.inline_link,
+      ("<a href=\"$2\">$1</a>"));
+    _txt = (_txt).replaceAll(
+      rgx.mark_internal_site_lnk,
+      ""
+    );
+  }
+  debug(markup_links) {
+    if ( match(_txt, rgx.inline_link)) {
+      writeln(__LINE__,
+        " (missed) markup link identified (",
+        obj.inline_links,
+        "): ", obj.is_a, ": ",
+        obj.text
+      );
+    }
+  }
+  debug(markup) {
+    if ( match(_txt, rgx.inline_link)) {
+      writeln(__LINE__,
+        " (missed) markup link identified (",
+        obj.inline_links,
+        "): ", obj.is_a, ": ",
+        obj.text
+      );
+    }
+  }
+  return _txt;
+}
+#+END_SRC
+
+***** notes scroll
+
+#+name: xhtml_format_objects
+#+BEGIN_SRC d
+auto inline_notes_scroll(O)(
+  auto return ref const O         obj,
+  string                  _txt,
+) {
+  if (obj.inline_notes_reg) {
+    _txt = (_txt).replaceAll(
+      rgx.inline_notes_delimiter_al_regular_number_note,
+      ("<a href=\"#note_$1\"><note id=\"noteref_$1\">&nbsp;<sup>$1</sup>&nbsp;</note></a>")
+    );
+  }
+  debug(markup_endnotes) {
+    if (match(_txt, rgx.inline_notes_delimiter_al_regular_number_note)) {
+      writeln(__LINE__, " (missed) markup endnote: ", obj.is_a, ": ", obj.text);
+    }
+  }
+  debug(markup) {
+    if (match(_txt, rgx.inline_notes_delimiter_al_regular_number_note)) {
+      writeln(__LINE__, " (missed) markup endnote: ", obj.is_a, ": ", obj.text);
+    }
+  }
+  // if (obj.inline_notes_star) {
+  //   _txt = replaceAll(
+  //     _txt,
+  //     rgx.inline_notes_delimiter_al_regular_number_note,
+  //     ("<a href=\"#note_$1\"><note id=\"noteref_$1\">&nbsp;<sup>$1</sup>&nbsp;</note></a>")
+  //   );
+  // }
+  return _txt;
+}
+#+END_SRC
+
+***** notes seg
+
+#+name: xhtml_format_objects
+#+BEGIN_SRC d
+auto inline_notes_seg(O)(
+  auto return ref const O     obj,
+  string                      _txt,
+) {
+  string[] _endnotes;
+  if (obj.inline_notes_reg) {
+    /+ need markup for text, and separated footnote +/
+    foreach(m; matchAll(_txt, rgx.inline_notes_delimiter_al_regular_number_note)) {
+      _endnotes ~= format(
+        "%s%s%s%s\n  %s%s%s%s%s\n  %s\n%s",
+        "<p class=\"endnote\">",
+        "<a href=\"#noteref_",
+        m.captures[1],
+        "\">",
+        "<note id=\"note_",
+        m.captures[1],
+        "\">&nbsp;<sup>",
+        m.captures[1],
+        ".</sup></note></a>",
+        m.captures[2],
+        "</p>"
+      );
+    }
+    _txt = (_txt).replaceAll(
+      rgx.inline_notes_delimiter_al_regular_number_note,
+      ("<a href=\"#note_$1\"><note id=\"noteref_$1\">&nbsp;<sup>$1</sup>&nbsp;</note></a>")
+    );
+  } else if (match(_txt, rgx.inline_notes_delimiter_al_regular_number_note)) {
+    debug(markup) {
+      writeln(__LINE__, " endnote: ", obj.is_a, ": ", obj.text);
+    }
+  }
+  auto t = tuple(
+    _txt,
+    _endnotes,
+  );
+  return t;
+}
+#+END_SRC
+
+***** inline markup scroll
+
+#+name: xhtml_format_objects
+#+BEGIN_SRC d
+auto inline_markup_scroll(O)(
+  auto return ref const O  obj,
+  string                   _suffix = ".html",
+) {
+  string _txt = obj.text;
+  _txt = inline_links(obj, _txt, _suffix, "scroll");
+  _txt = inline_notes_scroll(obj, _txt);
+  return _txt;
+}
+#+END_SRC
+
+***** inline markup seg
+
+#+name: xhtml_format_objects
+#+BEGIN_SRC d
+auto inline_markup_seg(O)(
+  auto return ref const O  obj,
+  string                   _suffix = ".html",
+) {
+  string _txt = obj.text;
+  _txt = inline_links(obj, _txt, _suffix, "seg");
+  auto t = inline_notes_seg(obj, _txt);
+  return t;
+}
+#+END_SRC
+
 **** toc
 
 #+name: xhtml_format_objects
@@ -413,11 +580,13 @@ auto toc(O)(
 #+END_SRC
 
 **** heading
+***** heading
 
 #+name: xhtml_format_objects
 #+BEGIN_SRC d
 auto heading(O)(
   auto return ref const O    obj,
+  string                     _txt,
 ) {
   auto tags = _xhtml_anchor_tags(obj.anchor_tags);
   string o;
@@ -431,7 +600,7 @@ auto heading(O)(
       obj.heading_lev_markup,
       obj.is_a,
       tags,
-      obj.text,
+      _txt,
       obj.heading_lev_markup,
     );
   } else {
@@ -449,7 +618,7 @@ auto heading(O)(
     obj.obj_cite_number,
     obj.obj_cite_number,
     tags,
-    obj.text,
+    _txt,
     obj.heading_lev_markup,
     );
   }
@@ -457,12 +626,49 @@ auto heading(O)(
 }
 #+END_SRC
 
+***** scroll
+
+#+name: xhtml_format_objects
+#+BEGIN_SRC d
+auto heading_scroll(O)(
+  auto return ref const O    obj,
+  string                     _suffix = ".html",
+) {
+  auto tags = _xhtml_anchor_tags(obj.anchor_tags);
+  string _txt = inline_markup_scroll(obj, _suffix); // issue
+  string o = heading(obj, _txt);
+  return o;
+}
+#+END_SRC
+
+***** seg
+
+#+name: xhtml_format_objects
+#+BEGIN_SRC d
+auto heading_seg(O)(
+  auto return ref const O    obj,
+  string                     _suffix = ".html",
+) {
+  auto t = inline_markup_seg(obj, _suffix);
+  string _txt = t[0];
+  string[] _endnotes = t[1];
+  string o = heading(obj, _txt);
+  auto u = tuple(
+    o,
+    _endnotes,
+  );
+  return u;
+}
+#+END_SRC
+
 **** para
+***** para
 
 #+name: xhtml_format_objects
 #+BEGIN_SRC d
 auto para(O)(
   auto return ref const O    obj,
+  string                     _txt,
 ) {
   auto tags = _xhtml_anchor_tags(obj.anchor_tags);
   string o;
@@ -476,7 +682,7 @@ auto para(O)(
       obj.indent_hang,
       obj.indent_base,
       tags,
-      obj.text
+      _txt
     );
   } else {
     o = format(q"¶  <div class="substance">
@@ -492,13 +698,48 @@ auto para(O)(
       obj.indent_base,
       obj.obj_cite_number,
       tags,
-      obj.text
+      _txt
     );
   }
   return o;
 }
 #+END_SRC
 
+***** scroll
+
+#+name: xhtml_format_objects
+#+BEGIN_SRC d
+auto para_scroll(O)(
+  auto return ref const O    obj,
+  string                     _suffix = ".html",
+) {
+  auto tags = _xhtml_anchor_tags(obj.anchor_tags);
+  string _txt = inline_markup_scroll(obj, _suffix); // issue
+  string o = para(obj, _txt);
+  return o;
+}
+#+END_SRC
+
+***** seg
+
+#+name: xhtml_format_objects
+#+BEGIN_SRC d
+auto para_seg(O)(
+  auto return ref const O    obj,
+  string                     _suffix = ".html",
+) {
+  auto t = inline_markup_seg(obj, _suffix);
+  string _txt = to!string(t[0]);
+  string[] _endnotes = t[1];
+  string o = para(obj, _txt);
+  auto u = tuple(
+    o,
+    _endnotes,
+  );
+  return u;
+}
+#+END_SRC
+
 **** nugget
 
 #+name: xhtml_format_objects
@@ -612,11 +853,12 @@ void scroll(D,I)(
   auto return ref const D    doc_abstraction,
   auto return ref I          doc_matters,
 ) {
-  mixin SiSUrgxInit;
+  mixin SiSUoutputRgxInit;
   auto xhtml_format = outputXHTMLs();
   auto rgx = Rgx();
   string[] doc_html;
   string[] doc;
+  string suffix = ".html";
   foreach (part; doc_matters.keys_seq_scroll) {
     foreach (obj; doc_abstraction[part]) {
       switch (obj.use) {
@@ -625,10 +867,10 @@ void scroll(D,I)(
         case "para":
           switch (obj.is_a) {
           case "heading":
-            doc_html ~= xhtml_format.heading(obj);
+            doc_html ~= xhtml_format.heading_scroll(obj, suffix);
             break;
           case "toc":
-            doc_html ~= xhtml_format.toc(obj);
+            doc_html ~= xhtml_format.para_scroll(obj, suffix);
             break;
           default:
             if ((doc_matters.opt_action_bool["debug"])) {
@@ -649,10 +891,10 @@ void scroll(D,I)(
         case "para":
           switch (obj.is_a) {
           case "heading":
-            doc_html ~= xhtml_format.heading(obj);
+            doc_html ~= xhtml_format.heading_scroll(obj, suffix);
             break;
           case "para":
-            doc_html ~= xhtml_format.para(obj);
+            doc_html ~= xhtml_format.para_scroll(obj, suffix);
             break;
           default:
             if ((doc_matters.opt_action_bool["debug"])) {
@@ -678,7 +920,7 @@ void scroll(D,I)(
             doc_html ~= xhtml_format.nugget(obj);
             break;
           case "table":
-            doc_html ~= xhtml_format.para(obj); //
+            doc_html ~= xhtml_format.para_scroll(obj, suffix);
             break;
           case "code":
             doc_html ~= xhtml_format.code(obj);
@@ -702,22 +944,22 @@ void scroll(D,I)(
         case "para":
           switch (obj.is_a) {
           case "heading":
-            doc_html ~= xhtml_format.heading(obj);
+            doc_html ~= xhtml_format.heading_scroll(obj, suffix);
             break;
           case "endnote":
-            doc_html ~= xhtml_format.endnote(obj);
+            doc_html ~= xhtml_format.para_scroll(obj, suffix);
             break;
           case "glossary":
-            doc_html ~= xhtml_format.para(obj);
+            doc_html ~= xhtml_format.para_scroll(obj, suffix);
             break;
           case "bibliography":
-            doc_html ~= xhtml_format.para(obj);
+            doc_html ~= xhtml_format.para_scroll(obj, suffix);
             break;
           case "bookindex":
-            doc_html ~= xhtml_format.para(obj);
+            doc_html ~= xhtml_format.para_scroll(obj, suffix);
             break;
           case "blurb":
-            doc_html ~= xhtml_format.para(obj);
+            doc_html ~= xhtml_format.para_scroll(obj, suffix);
             break;
           default:
             if ((doc_matters.opt_action_bool["debug"])) {
@@ -738,6 +980,8 @@ void scroll(D,I)(
       default:
         if ((doc_matters.opt_action_bool["debug"])) {
           writeln(__FILE__, ":", __LINE__, ": ", obj.use);
+          writeln(__FILE__, ":", __LINE__, ": ", obj.is_a);
+          writeln(__FILE__, ":", __LINE__, ": ", obj.text);
         }
         break;
       }
@@ -786,13 +1030,15 @@ void seg(D,I)(
   auto return ref const D    doc_abstraction,
   auto return ref I          doc_matters,
 ) {
-  mixin SiSUrgxInit;
+  mixin SiSUoutputRgxInit;
   auto rgx = Rgx();
   auto xhtml_format = outputXHTMLs();
   string[][string] doc_html;
+  string[][string] doc_html_endnotes;
   string[] doc;
   string segment_filename;
   string[] top_level_headings = ["","","",""];
+  string suffix = ".html";
   foreach (part; doc_matters.keys_seq_seg) {
     foreach (obj; doc_abstraction[part]) {
       if (obj.is_a == "heading") {                            // all headings: frontmatter, body & backmatter
@@ -819,7 +1065,8 @@ void seg(D,I)(
             top_level_headings[3] = "";
             goto default;
           default:
-            top_level_headings[obj.heading_lev_markup] = xhtml_format.heading(obj);
+            auto t = xhtml_format.heading_seg(obj, suffix);
+            top_level_headings[obj.heading_lev_markup] = t[0];
             break;
           }
           break;
@@ -829,10 +1076,14 @@ void seg(D,I)(
           foreach (top_level_heading; top_level_headings) {
             doc_html[segment_filename] ~= top_level_heading;
           }
-          doc_html[segment_filename] ~= xhtml_format.heading(obj);
+          auto t = xhtml_format.heading_seg(obj, suffix);
+          doc_html[segment_filename] ~= to!string(t[0]);
+          doc_html_endnotes[segment_filename] ~= t[1];
           break;
         case 5: .. case 7:
-          doc_html[segment_filename] ~= xhtml_format.heading(obj);
+          auto t = xhtml_format.heading_seg(obj, suffix);
+          doc_html[segment_filename] ~= to!string(t[0]);
+          doc_html_endnotes[segment_filename] ~= t[1];
           break;
         case 8: .. case 9: // unused numbers, if remain check
           if ((doc_matters.opt_action_bool["debug"])) {
@@ -853,7 +1104,8 @@ void seg(D,I)(
           case "para":
             switch (obj.is_a) {
             case "toc":
-              doc_html[segment_filename] ~= xhtml_format.toc(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_html[segment_filename] ~= to!string(t[0]);
               break;
             default:
               if ((doc_matters.opt_action_bool["debug"])) {
@@ -874,7 +1126,9 @@ void seg(D,I)(
           case "para":
             switch (obj.is_a) {
             case "para":
-              doc_html[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_html[segment_filename] ~= to!string(t[0]);
+              doc_html_endnotes[segment_filename] ~= t[1];
               break;
             default:
               if ((doc_matters.opt_action_bool["debug"])) {
@@ -900,7 +1154,9 @@ void seg(D,I)(
               doc_html[segment_filename] ~= xhtml_format.nugget(obj);
               break;
             case "table":
-              doc_html[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_html[segment_filename] ~= t[0];
+              doc_html_endnotes[segment_filename] ~= t[1];
               break;
             case "code":
               doc_html[segment_filename] ~= xhtml_format.code(obj);
@@ -924,19 +1180,28 @@ void seg(D,I)(
           case "para":
             switch (obj.is_a) {
             case "endnote":
-              doc_html[segment_filename] ~= xhtml_format.endnote(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_html[segment_filename] ~= t[0];
               break;
             case "glossary":
-              doc_html[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_html[segment_filename] ~= t[0];
+              doc_html_endnotes[segment_filename] ~= t[1];
               break;
             case "bibliography":
-              doc_html[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_html[segment_filename] ~= t[0];
+              doc_html_endnotes[segment_filename] ~= t[1];
               break;
             case "bookindex":
-              doc_html[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_html[segment_filename] ~= t[0];
+              doc_html_endnotes[segment_filename] ~= t[1];
               break;
             case "blurb":
-              doc_html[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_html[segment_filename] ~= t[0];
+              doc_html_endnotes[segment_filename] ~= t[1];
               break;
             default:
               if ((doc_matters.opt_action_bool["debug"])) {
@@ -963,7 +1228,7 @@ void seg(D,I)(
       }
     }
   }
-  seg_write_output(doc_matters, doc_html);
+  seg_write_output(doc_matters, doc_html, doc_html_endnotes);
 }
 #+END_SRC
 
@@ -971,14 +1236,15 @@ void seg(D,I)(
 
 #+name: output_html_seg
 #+BEGIN_SRC d
-void seg_write_output(M,C)(
+void seg_write_output(M,D,E)(
   M doc_matters,
-  C doc_html,
+  D doc_html,
+  E doc_html_endnotes,
 ) {
   debug(asserts){
     static assert(is(typeof(doc_html)      == string[][string]));
   }
-  mixin SiSUrgxInit;
+  mixin SiSUoutputRgxInit;
   auto rgx = Rgx();
   mixin SiSUpaths;
   auto pth_html = HtmlPaths();
@@ -993,6 +1259,9 @@ void seg_write_output(M,C)(
       foreach (docseg; doc_html[seg_filename]) {
         f.writeln(docseg);
       }
+      foreach (docseg; doc_html_endnotes[seg_filename]) {
+        f.writeln(docseg);
+      }
       f.writeln(xhtml_format.tail); // needed for each lev4
     }
   }
@@ -1127,403 +1396,403 @@ auto html_css() {
   p.i8 {padding-left: 8em;}
   p.i9 {padding-left: 9em;}
   /* hanging indent */
-  p.h0i0 {
+  p[indent=\"h0i0\"] {
     padding-left: 0em;
     text-indent:  0em;
   }
-  p.h0i1 {
+  p[indent=\"h0i1\"] {
     padding-left: 1em;
     text-indent: -1em;
   }
-  p.h0i2 {
+  p[indent=\"h0i2\"] {
     padding-left: 2em;
     text-indent: -2em;
   }
-  p.h0i3 {
+  p[indent=\"h0i3\"] {
     padding-left: 3em;
     text-indent: -3em;
   }
-  p.h0i4 {
+  p[indent=\"h0i4\"] {
     padding-left: 4em;
     text-indent: -4em;
   }
-  p.h0i5 {
+  p[indent=\"h0i5\"] {
     padding-left: 5em;
     text-indent: -5em;
   }
-  p.h0i6 {
+  p[indent=\"h0i6\"] {
     padding-left: 6em;
     text-indent: -6em;
   }
-  p.h0i7 {
+  p[indent=\"h0i7\"] {
     padding-left: 7em;
     text-indent: -7em;
   }
-  p.h0i8 {
+  p[indent=\"h0i8\"] {
     padding-left: 8em;
     text-indent: -8em;
   }
-  p.h0i9 {
+  p[indent=\"h0i9\"] {
     padding-left: 9em;
     text-indent: -9em;
   }
-  p.h1i0 {
+  p[indent=\"h1i0\"] {
     padding-left: 0em;
     text-indent:  1em;
   }
-  p.h1i1 {
+  p[indent=\"h1i1\"] {
     padding-left: 1em;
     text-indent:  0em;
   }
-  p.h1i2 {
+  p[indent=\"h1i2\"] {
     padding-left: 2em;
     text-indent: -1em;
   }
-  p.h1i3 {
+  p[indent=\"h1i3\"] {
     padding-left: 3em;
     text-indent: -2em;
   }
-  p.h1i4 {
+  p[indent=\"h1i4\"] {
     padding-left: 4em;
     text-indent: -3em;
   }
-  p.h1i5 {
+  p[indent=\"h1i5\"] {
     padding-left: 5em;
     text-indent: -4em;
   }
-  p.h1i6 {
+  p[indent=\"h1i6\"] {
     padding-left: 6em;
     text-indent: -5em;
   }
-  p.h1i7 {
+  p[indent=\"h1i7\"] {
     padding-left: 7em;
     text-indent: -6em;
   }
-  p.h1i8 {
+  p[indent=\"h1i8\"] {
     padding-left: 8em;
     text-indent: -7em;
   }
-  p.h1i9 {
+  p[indent=\"h1i9\"] {
     padding-left: 9em;
     text-indent: -8em;
   }
-  p.h2i0 {
+  p[indent=\"h2i0\"] {
     padding-left: 0em;
     text-indent:  2em;
   }
-  p.h2i1 {
+  p[indent=\"h2i1\"] {
     padding-left: 1em;
     text-indent:  1em;
   }
-  p.h2i2 {
+  p[indent=\"h2i2\"] {
     padding-left: 2em;
     text-indent:  0em;
   }
-  p.h2i3 {
+  p[indent=\"h2i3\"] {
     padding-left: 3em;
     text-indent: -1em;
   }
-  p.h2i4 {
+  p[indent=\"h2i4\"] {
     padding-left: 4em;
     text-indent: -2em;
   }
-  p.h2i5 {
+  p[indent=\"h2i5\"] {
     padding-left: 5em;
     text-indent: -3em;
   }
-  p.h2i6 {
+  p[indent=\"h2i6\"] {
     padding-left: 6em;
     text-indent: -4em;
   }
-  p.h2i7 {
+  p[indent=\"h2i7\"] {
     padding-left: 7em;
     text-indent: -5em;
   }
-  p.h2i8 {
+  p[indent=\"h2i8\"] {
     padding-left: 8em;
     text-indent: -6em;
   }
-  p.h2i9 {
+  p[indent=\"h2i9\"] {
     padding-left: 9em;
     text-indent: -7em;
   }
-  p.h3i0 {
+  p[indent=\"h3i0\"] {
     padding-left: 0em;
     text-indent:  3em;
   }
-  p.h3i1 {
+  p[indent=\"h3i1\"] {
     padding-left: 1em;
     text-indent:  2em;
   }
-  p.h3i2 {
+  p[indent=\"h3i2\"] {
     padding-left: 2em;
     text-indent:  1em;
   }
-  p.h3i3 {
+  p[indent=\"h3i3\"] {
     padding-left: 3em;
     text-indent:  0em;
   }
-  p.h3i4 {
+  p[indent=\"h3i4\"] {
     padding-left: 4em;
     text-indent: -1em;
   }
-  p.h3i5 {
+  p[indent=\"h3i5\"] {
     padding-left: 5em;
     text-indent: -2em;
   }
-  p.h3i6 {
+  p[indent=\"h3i6\"] {
     padding-left: 6em;
     text-indent: -3em;
   }
-  p.h3i7 {
+  p[indent=\"h3i7\"] {
     padding-left: 7em;
     text-indent: -4em;
   }
-  p.h3i8 {
+  p[indent=\"h3i8\"] {
     padding-left: 8em;
     text-indent: -5em;
   }
-  p.h3i9 {
+  p[indent=\"h3i9\"] {
     padding-left: 9em;
     text-indent: -6em;
   }
-  p.h4i0 {
+  p[indent=\"h4i0\"] {
     padding-left: 0em;
     text-indent:  4em;
   }
-  p.h4i1 {
+  p[indent=\"h4i1\"] {
     padding-left: 1em;
     text-indent:  3em;
   }
-  p.h4i2 {
+  p[indent=\"h4i2\"] {
     padding-left: 2em;
     text-indent:  2em;
   }
-  p.h4i3 {
+  p[indent=\"h4i3\"] {
     padding-left: 3em;
     text-indent:  1em;
   }
-  p.h4i4 {
+  p[indent=\"h4i4\"] {
     padding-left: 4em;
     text-indent:  0em;
   }
-  p.h4i5 {
+  p[indent=\"h4i5\"] {
     padding-left: 5em;
     text-indent: -1em;
   }
-  p.h4i6 {
+  p[indent=\"h4i6\"] {
     padding-left: 6em;
     text-indent: -2em;
   }
-  p.h4i7 {
+  p[indent=\"h4i7\"] {
     padding-left: 7em;
     text-indent: -3em;
   }
-  p.h4i8 {
+  p[indent=\"h4i8\"] {
     padding-left: 8em;
     text-indent: -4em;
   }
-  p.h4i9 {
+  p[indent=\"h4i9\"] {
     padding-left: 9em;
     text-indent: -5em;
   }
-  p.h5i0 {
+  p[indent=\"h5i0\"] {
     padding-left: 0em;
     text-indent:  5em;
   }
-  p.h5i1 {
+  p[indent=\"h5i1\"] {
     padding-left: 1em;
     text-indent:  4em;
   }
-  p.h5i2 {
+  p[indent=\"h5i2\"] {
     padding-left: 2em;
     text-indent:  3em;
   }
-  p.h5i3 {
+  p[indent=\"h5i3\"] {
     padding-left: 3em;
     text-indent:  2em;
   }
-  p.h5i4 {
+  p[indent=\"h5i4\"] {
     padding-left: 4em;
     text-indent:  1em;
   }
-  p.h5i5 {
+  p[indent=\"h5i5\"] {
     padding-left: 5em;
     text-indent:  0em;
   }
-  p.h5i6 {
+  p[indent=\"h5i6\"] {
     padding-left: 6em;
     text-indent: -1em;
   }
-  p.h5i7 {
+  p[indent=\"h5i7\"] {
     padding-left: 7em;
     text-indent: -2em;
   }
-  p.h5i8 {
+  p[indent=\"h5i8\"] {
     padding-left: 8em;
     text-indent: -3em;
   }
-  p.h5i9 {
+  p[indent=\"h5i9\"] {
     padding-left: 9em;
     text-indent: -4em;
   }
-  p.h6i0 {
+  p[indent=\"h6i0\"] {
     padding-left: 0em;
     text-indent:  6em;
   }
-  p.h6i1 {
+  p[indent=\"h6i1\"] {
     padding-left: 1em;
     text-indent:  5em;
   }
-  p.h6i2 {
+  p[indent=\"h6i2\"] {
     padding-left: 2em;
     text-indent:  4em;
   }
-  p.h6i3 {
+  p[indent=\"h6i3\"] {
     padding-left: 3em;
     text-indent:  3em;
   }
-  p.h6i4 {
+  p[indent=\"h6i4\"] {
     padding-left: 4em;
     text-indent:  2em;
   }
-  p.h6i5 {
+  p[indent=\"h6i5\"] {
     padding-left: 5em;
     text-indent:  1em;
   }
-  p.h6i6 {
+  p[indent=\"h6i6\"] {
     padding-left: 6em;
     text-indent:  0em;
   }
-  p.h6i7 {
+  p[indent=\"h6i7\"] {
     padding-left: 7em;
     text-indent: -1em;
   }
-  p.h6i8 {
+  p[indent=\"h6i8\"] {
     padding-left: 8em;
     text-indent: -2em;
   }
-  p.h6i9 {
+  p[indent=\"h6i9\"] {
     padding-left: 9em;
     text-indent: -3em;
   }
-  p.h7i0 {
+  p[indent=\"h7i0\"] {
     padding-left: 0em;
     text-indent:  7em;
   }
-  p.h7i1 {
+  p[indent=\"h7i1\"] {
     padding-left: 1em;
     text-indent:  6em;
   }
-  p.h7i2 {
+  p[indent=\"h7i2\"] {
     padding-left: 2em;
     text-indent:  5em;
   }
-  p.h7i3 {
+  p[indent=\"h7i3\"] {
     padding-left: 3em;
     text-indent:  4em;
   }
-  p.h7i4 {
+  p[indent=\"h7i4\"] {
     padding-left: 4em;
     text-indent:  3em;
   }
-  p.h7i5 {
+  p[indent=\"h7i5\"] {
     padding-left: 5em;
     text-indent:  2em;
   }
-  p.h7i6 {
+  p[indent=\"h7i6\"] {
     padding-left: 6em;
     text-indent:  1em;
   }
-  p.h7i7 {
+  p[indent=\"h7i7\"] {
     padding-left: 7em;
     text-indent:  0em;
   }
-  p.h7i8 {
+  p[indent=\"h7i8\"] {
     padding-left: 8em;
     text-indent: -1em;
   }
-  p.h7i9 {
+  p[indent=\"h7i9\"] {
     padding-left: 9em;
     text-indent: -2em;
   }
-  p.h8i0 {
+  p[indent=\"h8i0\"] {
     padding-left: 0em;
     text-indent:  8em;
   }
-  p.h8i1 {
+  p[indent=\"h8i1\"] {
     padding-left: 1em;
     text-indent:  7em;
   }
-  p.h8i2 {
+  p[indent=\"h8i2\"] {
     padding-left: 2em;
     text-indent:  6em;
   }
-  p.h8i3 {
+  p[indent=\"h8i3\"] {
     padding-left: 3em;
     text-indent:  5em;
   }
-  p.h8i4 {
+  p[indent=\"h8i4\"] {
     padding-left: 4em;
     text-indent:  4em;
   }
-  p.h8i5 {
+  p[indent=\"h8i5\"] {
     padding-left: 5em;
     text-indent:  3em;
   }
-  p.h8i6 {
+  p[indent=\"h8i6\"] {
     padding-left: 6em;
     text-indent:  2em;
   }
-  p.h8i7 {
+  p[indent=\"h8i7\"] {
     padding-left: 7em;
     text-indent:  1em;
   }
-  p.h8i8 {
+  p[indent=\"h8i8\"] {
     padding-left: 8em;
     text-indent:  0em;
   }
-  p.h8i9 {
+  p[indent=\"h8i9\"] {
     padding-left: 9em;
     text-indent: -1em;
   }
-  p.h9i0 {
+  p[indent=\"h9i0\"] {
     padding-left: 0em;
     text-indent:  9em;
   }
-  p.h9i1 {
+  p[indent=\"h9i1\"] {
     padding-left: 1em;
     text-indent:  8em;
   }
-  p.h9i2 {
+  p[indent=\"h9i2\"] {
     padding-left: 2em;
     text-indent:  7em;
   }
-  p.h9i3 {
+  p[indent=\"h9i3\"] {
     padding-left: 3em;
     text-indent:  6em;
   }
-  p.h9i4 {
+  p[indent=\"h9i4\"] {
     padding-left: 4em;
     text-indent:  5em;
   }
-  p.h9i5 {
+  p[indent=\"h9i5\"] {
     padding-left: 5em;
     text-indent:  4em;
   }
-  p.h9i6 {
+  p[indent=\"h9i6\"] {
     padding-left: 6em;
     text-indent:  3em;
   }
-  p.h9i7 {
+  p[indent=\"h9i7\"] {
     padding-left: 7em;
     text-indent:  2em;
   }
-  p.h9i8 {
+  p[indent=\"h9i8\"] {
     padding-left: 8em;
     text-indent:  1em;
   }
-  p.h9i9 {
+  p[indent=\"h9i9\"] {
     padding-left: 9em;
     text-indent:  0em;
   }
@@ -2498,11 +2767,12 @@ void outputEPub(D,I)(
   auto return ref const D    doc_abstraction,
   auto return ref I          doc_matters,
 ) {
-  mixin SiSUrgxInit;
+  mixin SiSUoutputRgxInit;
   auto xhtml_format = outputXHTMLs();
   auto rgx = Rgx();
   // string[] toc;
   string[][string] doc_epub;
+  string[][string] doc_epub_endnotes;
   string[] doc;
   string segment_filename;
   string[] top_level_headings = ["","","",""];
@@ -2510,6 +2780,7 @@ void outputEPub(D,I)(
   auto meta_inf_container_xml = epub_container_xml;
   auto oebps_toc_ncx = epub_oebps_toc(doc_abstraction, doc_matters);
   auto oebps_content_opf = epub_oebps_content(doc_abstraction, doc_matters);
+  string suffix = ".xhtml";
   foreach (part; doc_matters.keys_seq_seg) {
     foreach (obj; doc_abstraction[part]) {
       if (obj.is_a == "heading") {
@@ -2536,7 +2807,8 @@ void outputEPub(D,I)(
             top_level_headings[3] = "";
             goto default;
           default:
-            top_level_headings[obj.heading_lev_markup] = xhtml_format.heading(obj);
+            auto t = xhtml_format.heading_seg(obj, suffix);
+            top_level_headings[obj.heading_lev_markup] = t[0];
             break;
           }
           break;
@@ -2546,10 +2818,14 @@ void outputEPub(D,I)(
           foreach (top_level_heading; top_level_headings) {
             doc_epub[segment_filename] ~= top_level_heading;
           }
-          doc_epub[segment_filename] ~= xhtml_format.heading(obj);
+          auto t = xhtml_format.heading_seg(obj, suffix);
+          doc_epub[segment_filename] ~= t[0];
+          doc_epub_endnotes[segment_filename] ~= t[1];
           break;
         case 5: .. case 7:
-          doc_epub[segment_filename] ~= xhtml_format.heading(obj);
+          auto t = xhtml_format.heading_seg(obj, suffix);
+          doc_epub[segment_filename] ~= t[0];
+          doc_epub_endnotes[segment_filename] ~= t[1];
           break;
         case 8: .. case 9: // unused numbers, if remain check
           if ((doc_matters.opt_action_bool["debug"])) {
@@ -2591,7 +2867,9 @@ void outputEPub(D,I)(
           case "para":
             switch (obj.is_a) {
             case "para":
-              doc_epub[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_epub[segment_filename] ~= t[0];
+              doc_epub_endnotes[segment_filename] ~= t[1];
               break;
             default:
               if ((doc_matters.opt_action_bool["debug"])) {
@@ -2617,7 +2895,9 @@ void outputEPub(D,I)(
               doc_epub[segment_filename] ~= xhtml_format.nugget(obj);
               break;
             case "table":
-              doc_epub[segment_filename] ~= xhtml_format.para(obj); //
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_epub[segment_filename] ~= t[0];
+              doc_epub_endnotes[segment_filename] ~= t[1];
               break;
             case "code":
               doc_epub[segment_filename] ~= xhtml_format.code(obj);
@@ -2641,19 +2921,28 @@ void outputEPub(D,I)(
           case "para":
             switch (obj.is_a) {
             case "endnote":
-              doc_epub[segment_filename] ~= xhtml_format.endnote(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_epub[segment_filename] ~= t[0];
               break;
             case "glossary":
-              doc_epub[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_epub[segment_filename] ~= t[0];
+              doc_epub_endnotes[segment_filename] ~= t[1];
               break;
             case "bibliography":
-              doc_epub[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_epub[segment_filename] ~= t[0];
+              doc_epub_endnotes[segment_filename] ~= t[1];
               break;
             case "bookindex":
-              doc_epub[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_epub[segment_filename] ~= t[0];
+              doc_epub_endnotes[segment_filename] ~= t[1];
               break;
             case "blurb":
-              doc_epub[segment_filename] ~= xhtml_format.para(obj);
+              auto t = xhtml_format.para_seg(obj, suffix);
+              doc_epub[segment_filename] ~= t[0];
+              doc_epub_endnotes[segment_filename] ~= t[1];
               break;
             default:
               if ((doc_matters.opt_action_bool["debug"])) {
@@ -2683,6 +2972,7 @@ void outputEPub(D,I)(
   epub_write_output_files(
     doc_matters,
     doc_epub,
+    doc_epub_endnotes,
     mimetypes,
     meta_inf_container_xml,
     oebps_toc_ncx,
@@ -2695,13 +2985,14 @@ void outputEPub(D,I)(
 
 #+name: output_epub_xhtml_seg
 #+BEGIN_SRC d
-void epub_write_output_files(C,EpD,Mt,Mic,Ot,Oc)(
-  C   doc_matters,
-  EpD doc_epub,
-  Mt  mimetypes,
-  Mic meta_inf_container_xml,
-  Ot  oebps_toc_ncx,
-  Oc  oebps_content_opf,
+void epub_write_output_files(M,D,E,Mt,Mic,Ot,Oc)(
+  M    doc_matters,
+  D    doc_epub,
+  E    doc_epub_endnotes,
+  Mt   mimetypes,
+  Mic  meta_inf_container_xml,
+  Ot   oebps_toc_ncx,
+  Oc   oebps_content_opf,
 ) {
   debug(asserts){
     static assert(is(typeof(doc_epub)               == string[][string]));
@@ -2730,6 +3021,9 @@ void epub_write_output_files(C,EpD,Mt,Mic,Ot,Oc)(
       foreach (docseg; doc_epub[seg_filename]) {
         f.writeln(docseg);
       }
+      foreach (docseg; doc_epub_endnotes[seg_filename]) {
+        f.writeln(docseg);
+      }
       f.writeln(xhtml_format.tail); // needed for each lev4
     }
     /+ mimetypes +/
diff --git a/org/sdp.org b/org/sdp.org
index 2318ee7..3700bfc 100644
--- a/org/sdp.org
+++ b/org/sdp.org
@@ -23,7 +23,7 @@ struct Version {
   int minor;
   int patch;
 }
-enum ver = Version(0, 13, 4);
+enum ver = Version(0, 13, 5);
 #+END_SRC
 
 * 1. sdp (sisu document parser)                                         :sdp:
diff --git a/src/sdp/ao_abstract_doc_source.d b/src/sdp/ao_abstract_doc_source.d
index ef64f0b..6690a9f 100644
--- a/src/sdp/ao_abstract_doc_source.d
+++ b/src/sdp/ao_abstract_doc_source.d
@@ -362,7 +362,7 @@ template SiSUdocAbstraction() {
           line,
         );
       }
-      line = replaceAll(line, rgx.true_dollar, "$$$$");
+      line = (line).replaceAll(rgx.true_dollar, "$$$$");
         // dollar represented as $$ needed to stop submatching on $
         // (substitutions using ${identifiers} must take into account (i.e. happen earlier))
       debug(source) {                                  // source lines
@@ -1965,7 +1965,7 @@ template SiSUdocAbstraction() {
             tmp ~= au.str;
           }
         }
-        tmp = replace(tmp, rgx.trailing_comma, "");
+        tmp = (tmp).replace(rgx.trailing_comma, "");
         j["author"].str = tmp;
         goto default;
       case "editor_raw": // editor_arr editor (fn sn)
@@ -1980,7 +1980,7 @@ template SiSUdocAbstraction() {
             tmp ~= ed.str;
           }
         }
-        tmp = replace(tmp, rgx.trailing_comma, "");
+        tmp = (tmp).replace(rgx.trailing_comma, "");
         j["editor"].str = tmp;
         goto default;
       case "fulltitle": // title & subtitle
@@ -2876,10 +2876,11 @@ template SiSUdocAbstraction() {
       assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels
       switch (an_object["lev"]) {
       case "A":
-        an_object[an_object_key]=replaceFirst(an_object[an_object_key],
-          rgx.variable_doc_title, (dochead_meta_aa["title"]["full"] ~ ","));
-        an_object[an_object_key]=replaceFirst(an_object[an_object_key],
-          rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]);
+        an_object[an_object_key]=(an_object[an_object_key])
+          .replaceFirst(rgx.variable_doc_title,
+            (dochead_meta_aa["title"]["full"] ~ ","))
+          .replaceFirst(rgx.variable_doc_author,
+            dochead_meta_aa["creator"]["author"]);
         collapsed_lev["h0"] = 0;
         an_object["lev_collapsed_number"] =
           to!string(collapsed_lev["h0"]);
@@ -2994,7 +2995,7 @@ template SiSUdocAbstraction() {
       }
     }
   }
-  auto _para_match_(L,O,K,I,B,T,C)(
+  void _para_match_(L,O,K,I,B,T,C)(
     return ref L  line,
     return ref O  an_object,
     return ref K  an_object_key,
@@ -3089,17 +3090,15 @@ template SiSUdocAbstraction() {
       n_foot_sp_asterisk = 0;
       n_foot_sp_plus = 0;
     }
-    string url_links(Ot)(Ot obj_txt_in, string suffix = ".html") {
+    string url_links(Ot)(Ot obj_txt_in) {
       debug(asserts){
         static assert(is(typeof(obj_txt_in) == string));
       }
       /+ url matched +/
-      if (match(obj_txt_in, rgx.inline_url)) {
+      if (match(obj_txt_in, rgx.inline_url_generic)) {
         /+ link: naked url: http://url +/
         if (match(obj_txt_in, rgx.inline_link_naked_url)) {
-          obj_txt_in =
-            replaceAll(
-              obj_txt_in,
+          obj_txt_in = (obj_txt_in).replaceAll(
               rgx.inline_link_naked_url,
               ("$1"
                 ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c
@@ -3113,40 +3112,34 @@ template SiSUdocAbstraction() {
              { link which includes url as footnote }http://url~{ { http://url }http://url }~
         +/
         if (match(obj_txt_in, rgx.inline_link_endnote_url_helper)) {
-          obj_txt_in =
-            replaceAll(
-              obj_txt_in,
-              rgx.inline_link_endnote_url_helper_punctuated,
-              (mkup.lnk_o ~ "$1" ~ mkup.lnk_c
-                ~ mkup.url_o ~ "$2" ~ mkup.url_c
-                ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c
-                ~ mkup.url_o ~ "$2" ~ mkup.url_c
-                ~  " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3")
-            );
-          obj_txt_in =
-            replaceAll(
-              obj_txt_in,
-              rgx.inline_link_endnote_url_helper,
-              (mkup.lnk_o ~ "$1" ~ mkup.lnk_c
-                ~ mkup.url_o ~ "$2" ~ mkup.url_c
-                ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c
-                ~ mkup.url_o ~ "$2" ~ mkup.url_c
-                ~  " }~") // ("{ $1 }$2~{ { $2 }$2 }~")
-            );
+          obj_txt_in = (obj_txt_in).replaceAll(
+            rgx.inline_link_endnote_url_helper_punctuated,
+            (mkup.lnk_o ~ "$1" ~ mkup.lnk_c
+              ~ mkup.url_o ~ "$2" ~ mkup.url_c
+              ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c
+              ~ mkup.url_o ~ "$2" ~ mkup.url_c
+              ~  " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3")
+          );
+          obj_txt_in = (obj_txt_in).replaceAll(
+            rgx.inline_link_endnote_url_helper,
+            (mkup.lnk_o ~ "$1" ~ mkup.lnk_c
+              ~ mkup.url_o ~ "$2" ~ mkup.url_c
+              ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c
+              ~ mkup.url_o ~ "$2" ~ mkup.url_c
+              ~  " }~") // ("{ $1 }$2~{ { $2 }$2 }~")
+          );
         }
         /+ link with regular markup:
            { linked text or image }http://url
         +/
         if (match(obj_txt_in, rgx.inline_link_markup_regular)) {
-          obj_txt_in =
-            replaceAll(
-              obj_txt_in,
-              rgx.inline_link_markup_regular,
-              ("$1"
-                ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c
-                ~  mkup.url_o ~ "$3" ~  mkup.url_c
-                ~ "$4")            // ("$1{ $2 }$3$4")
-            );
+          obj_txt_in = (obj_txt_in).replaceAll(
+            rgx.inline_link_markup_regular,
+            ("$1"
+              ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c
+              ~  mkup.url_o ~ "$3" ~  mkup.url_c
+              ~ "$4")            // ("$1{ $2 }$3$4")
+          );
         }
       }
       return obj_txt_in;
@@ -3158,12 +3151,10 @@ template SiSUdocAbstraction() {
       /+ endnotes (regular) +/
       bool flg_notes_reg  = false;
       bool flg_notes_star = false;
-      obj_txt_in =
-        replaceAll(
-          obj_txt_in,
-          rgx.inline_notes_curly,
-          (mkup.en_a_o ~ " $1" ~ mkup.en_a_c)
-        );
+      obj_txt_in = (obj_txt_in).replaceAll(
+        rgx.inline_notes_curly,
+        (mkup.en_a_o ~ " $1" ~ mkup.en_a_c)
+      );
       if (!(stage_reset_note_numbers) && reset_note_numbers) {
         stage_reset_note_numbers = true;
       }
@@ -3182,22 +3173,18 @@ template SiSUdocAbstraction() {
               ++n_foot_sp_asterisk;
               asterisks_ = "*";
               n_foot=n_foot_sp_asterisk;
-              obj_txt_out ~=
-                (replaceFirst(
-                  to!string(n.hit),
-                  rgx.inline_al_delimiter_open_symbol_star,
-                  (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ")
-                ) ~ "\n");
+              obj_txt_out ~= (to!string(n.hit)).replaceFirst(
+                rgx.inline_al_delimiter_open_symbol_star,
+                (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ")
+              ) ~ "\n";
             } else if (match(to!string(n.hit), rgx.inline_al_delimiter_open_regular)) {
               flg_notes_reg =  true;
               ++n_foot_reg;
               n_foot=n_foot_reg;
-              obj_txt_out ~=
-                (replaceFirst(
-                  to!string(n.hit),
-                  rgx.inline_al_delimiter_open_regular,
-                  (mkup.en_a_o ~ to!string(n_foot) ~ " ")
-                ) ~ "\n");
+              obj_txt_out ~= (to!string(n.hit)).replaceFirst(
+                rgx.inline_al_delimiter_open_regular,
+                (mkup.en_a_o ~ to!string(n_foot) ~ " ")
+              ) ~ "\n";
             } else {
               obj_txt_out ~= to!string(n.hit) ~ "\n";
             }
@@ -3276,9 +3263,9 @@ template SiSUdocAbstraction() {
       }
     }
     body {
-      obj_txt["munge"]=obj_txt_in;
-      obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.para_attribs, "");
-      obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.obj_cite_number_off_all, "");
+      obj_txt["munge"]=(obj_txt_in)
+        .replaceFirst(rgx.para_attribs, "")
+        .replaceFirst(rgx.obj_cite_number_off_all, "");
       auto t = object_notes_and_links_(obj_txt["munge"]);
       debug(munge) {
         writeln(__LINE__);
@@ -3295,10 +3282,10 @@ template SiSUdocAbstraction() {
       }
     }
     body {
-      obj_txt["munge"]=obj_txt_in;
-      obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.heading, "");
-      obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.obj_cite_number_off_all, "");
-      obj_txt["munge"]=strip(obj_txt["munge"]);
+      obj_txt["munge"]=(obj_txt_in)
+       .replaceFirst(rgx.heading, "")
+       .replaceFirst(rgx.obj_cite_number_off_all, "")
+       .strip;
       auto t = object_notes_and_links_(obj_txt["munge"], reset_note_numbers);
       debug(munge) {
         writeln(__LINE__);
@@ -3310,7 +3297,6 @@ template SiSUdocAbstraction() {
     }
     invariant() {
     }
-    /+ revisit +/
     string code(Ot)(Ot obj_txt_in)
     in {
       debug(asserts){
@@ -3490,12 +3476,9 @@ template SiSUdocAbstraction() {
        static assert(is(typeof(heading_toc_) == char[]));
      }
      auto m = matchFirst(cast(char[]) heading_toc_, rgx.heading);
-     heading_toc_ =
-       replaceAll(
-         m.post,
-         rgx.inline_notes_curly_gen,
-         ("")
-       );
+     heading_toc_ = (m.post).replaceAll(
+       rgx.inline_notes_curly_gen,
+       "");
      return heading_toc_;
     };
     auto table_of_contents_gather_headings(O,Ma,Ts,Ta,X,Toc)(
@@ -3769,10 +3752,11 @@ template SiSUdocAbstraction() {
             writeln(heading_number_auto_composite);
           }
           if (!empty(heading_number_auto_composite)) {
-            munge_=replaceFirst(munge_, rgx.heading,
-              "$1~$2 " ~ heading_number_auto_composite ~ ". ");
-            munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
-              "$1~" ~ heading_number_auto_composite ~ " ");
+            munge_=(munge_)
+              .replaceFirst(rgx.heading,
+                "$1~$2 " ~ heading_number_auto_composite ~ ". ")
+              .replaceFirst(rgx.heading_marker_missing_tag,
+                "$1~" ~ heading_number_auto_composite ~ " ");
           }
         }
       }
@@ -3788,16 +3772,19 @@ template SiSUdocAbstraction() {
       if (!(match(munge_, rgx.heading_anchor_tag))) { // if (anchor_tags_.length == 0) {
         if (match(munge_, rgx.heading_identify_anchor_tag)) {
           if (auto m = match(munge_, rgx.heading_extract_named_anchor_tag)) {
-            munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
+            munge_=(munge_).replaceFirst(
+              rgx.heading_marker_missing_tag,
               "$1~" ~ toLower(m.captures[1]) ~ "_"  ~ m.captures[2] ~ " ");
           } else if (auto m = match(munge_, rgx.heading_extract_unnamed_anchor_tag)) {
-            munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
+            munge_=(munge_).replaceFirst(
+              rgx.heading_marker_missing_tag,
               "$1~" ~ "s" ~ m.captures[1] ~ " ");
           }
         } else if (lev_ == "1") { // (if not successful) manufacture a unique anchor tag for lev=="1"
           static __gshared int heading_num_lev1 = 0;
           heading_num_lev1 ++;
-          munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag,
+          munge_=(munge_).replaceFirst(
+            rgx.heading_marker_missing_tag,
             "$1~" ~ "x" ~ to!string(heading_num_lev1) ~ " ");
         }
       }
@@ -4233,7 +4220,7 @@ template SiSUdocAbstraction() {
       foreach (mainkey; mainkeys) {
         write("_0_1 !{", mainkey, "}! ");
         foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) {
-          auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+          auto go = (ref_).replaceAll(rgx.book_index_go, "$1");
           write(" {", ref_, "}#", go, ", ");
         }
         writeln(" \\\\");
@@ -4243,7 +4230,7 @@ template SiSUdocAbstraction() {
         foreach (subkey; subkeys) {
           write("  ", subkey, ", ");
           foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) {
-            auto go = replaceAll(ref_, rgx.book_index_go, "$1");
+            auto go = (ref_).replaceAll(rgx.book_index_go, "$1");
             write(" {", ref_, "}#", go, ", ");
           }
           writeln(" \\\\");
@@ -4372,8 +4359,8 @@ template SiSUdocAbstraction() {
             bi_tmp_seg ~= " \\\\\n    ";
             ++skn;
           }
-          bi_tmp_scroll                       = replaceFirst(bi_tmp_scroll, rgx.trailing_linebreak, "");
-          bi_tmp_seg                          = replaceFirst(bi_tmp_seg, rgx.trailing_linebreak, "");
+          bi_tmp_scroll                       = (bi_tmp_scroll).replaceFirst(rgx.trailing_linebreak, "");
+          bi_tmp_seg                          = (bi_tmp_seg).replaceFirst(rgx.trailing_linebreak, "");
           comp_obj_para                       = comp_obj_para.init;
           comp_obj_para.use                   = "backmatter";
           comp_obj_para.is_of                 = "para";
diff --git a/src/sdp/ao_conf_make_meta_sdlang.d b/src/sdp/ao_conf_make_meta_sdlang.d
index af76593..04261d0 100644
--- a/src/sdp/ao_conf_make_meta_sdlang.d
+++ b/src/sdp/ao_conf_make_meta_sdlang.d
@@ -265,7 +265,7 @@ template SiSUheaderExtractSDLang() {
       string[] authors_arr;
       auto authors_raw_arr = split(dochead_meta["creator"]["author"], rgx.arr_delimiter);
       foreach (author_raw; authors_raw_arr) {
-        authors_arr ~= replace(author_raw, rgx.raw_author_munge, "$2 $1");
+        authors_arr ~= (author_raw).replace(rgx.raw_author_munge, "$2 $1");
       }
       dochead_meta["creator"]["author"] = join(authors_arr, ", ").chomp.chomp;
       auto t = tuple(dochead_make, dochead_meta);
diff --git a/src/sdp/ao_rgx.d b/src/sdp/ao_rgx.d
index 6d91096..7d47608 100644
--- a/src/sdp/ao_rgx.d
+++ b/src/sdp/ao_rgx.d
@@ -27,14 +27,6 @@ template SiSUrgxInit() {
     static levels_markup                                  = ctRegex!(`^[A-D1-4]$`);
     static levels_numbered                                = ctRegex!(`^[0-9]$`);
     static levels_numbered_headings                       = ctRegex!(`^[0-7]$`);
-    static src_pth                                        = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])$`);
-    static src_fn                                         =
-      ctRegex!(`^([a-zA-Z0-9._-]+/)*(?P<fn_src>(?P<fn_base>[a-zA-Z0-9._-]+)[.](?P<fn_src_suffix>ss[tm]))$`);
-    static src_fn_master                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssm)$`);
-    static src_fn_text                                    = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]sst)$`);
-    static src_fn_insert                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssi)$`);
-    static src_fn_find_inserts                            = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[im])$`);
-    static insert_src_fn_ssi_or_sst                       = ctRegex!(`^<<\s*(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`);
     /+ comments +/
     static comment                                        = ctRegex!(`^%+ `);
     static comments                                       = ctRegex!(`^%+ |^%+$`);
@@ -86,7 +78,7 @@ template SiSUrgxInit() {
     static para_bullet_indent                             = ctRegex!(`^_([1-9])[*] `);
     static para_indent                                    = ctRegex!(`^_([1-9]) `);
     static para_indent_hang                               = ctRegex!(`^_([0-9])_([0-9]) `);
-    static para_attribs                                   = ctRegex!(`^_(([0-9])(_([0-9]))?|_([1-9])?[*]) `);
+    static para_attribs                                   = ctRegex!(`^_(?:(?:[0-9])(?:_([0-9]))?|(?:[1-9])?[*]) `);
     /+ blocked markup +/
     static block_open                                     = ctRegex!("^((code([.][a-z][0-9a-z_]+)?|poem|group|block|quote|table)[{].*?$)|^`{3} (code([.][a-z][0-9a-z_]+)?|poem|group|block|quote|table)");
     static block_poem_open                                = ctRegex!("^((poem[{].*?$)|`{3} poem)");
@@ -142,8 +134,9 @@ template SiSUrgxInit() {
     static inline_curly_delimiter_close_regular           = ctRegex!(`\s*\}~`, "m");
     static inline_text_and_note_curly                     = ctRegex!(`(?P<text>.+?)(?:(?:[~])[{][*+ ]*)(?P<note>.+?)(?:[}][~])`, "mg");
     static note_ref                                       = ctRegex!(`^\S+?noteref_([0-9]+)`, "mg");     // {^{73.}^}#noteref_73
-    static inline_url                                      = ctRegex!(`((?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+)`, "mg");
-    static inline_link_naked_url                           = ctRegex!(`(?P<before>^|[ ])(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!]?(?:[ ]|$))`, "mg");
+    static inline_url_generic                              = ctRegex!(`(?:^|[}(\[ ])(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_]`, "mg");
+    static inline_url                                      = ctRegex!(`((?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_]\S*)`, "mg");
+    static inline_link_naked_url                           = ctRegex!(`(?P<before>^|[ ])(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!'"]?(?:[ ]|$))`, "mg");
     static inline_link_markup_regular                      = ctRegex!(`(?P<before>^|[ ])\{\s*(?P<content>.+?)\s*\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!]?(?:[ ]|$))`, "mg");
     static inline_link_endnote_url_helper_punctuated       = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!]?(?:[ ]|$))`, "mg");
     static inline_link_endnote_url_helper                  = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+)`, "mg");
@@ -185,6 +178,14 @@ template SiSUrgxInit() {
        ctRegex!("(am|bg|bn|br|ca|cs|cy|da|de|el|en|eo|es|et|eu|fi|fr|ga|gl|he|hi|hr|hy|ia|is|it|ja|ko|la|lo|lt|lv|ml|mr|nl|no|nn|oc|pl|pt|pt_BR|ro|ru|sa|se|sk|sl|sq|sr|sv|ta|te|th|tk|tr|uk|ur|vi|zh)");
     auto language_code_and_filename                                    =
        ctRegex!("(am|bg|bn|br|ca|cs|cy|da|de|el|en|eo|es|et|eu|fi|fr|ga|gl|he|hi|hr|hy|ia|is|it|ja|ko|la|lo|lt|lv|ml|mr|nl|no|nn|oc|pl|pt|pt_BR|ro|ru|sa|se|sk|sl|sq|sr|sv|ta|te|th|tk|tr|uk|ur|vi|zh)/[A-Za-z0-9._-].+?[.](?:sst|ssm)$");
+    static src_pth                                        = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])$`);
+    static src_fn                                         =
+      ctRegex!(`^([a-zA-Z0-9._-]+/)*(?P<fn_src>(?P<fn_base>[a-zA-Z0-9._-]+)[.](?P<fn_src_suffix>ss[tm]))$`);
+    static src_fn_master                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssm)$`);
+    static src_fn_text                                    = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]sst)$`);
+    static src_fn_insert                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssi)$`);
+    static src_fn_find_inserts                            = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[im])$`);
+    static insert_src_fn_ssi_or_sst                       = ctRegex!(`^<<\s*(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`);
     /+ inline markup footnotes endnotes +/
     static inline_notes_al                                = ctRegex!(`【(?:[*+]\s+|\s*)(.+?)】`, "mg");
     static inline_notes_al_gen                            = ctRegex!(`【.+?】`, "m");
@@ -199,27 +200,12 @@ template SiSUrgxInit() {
     static inline_al_delimiter_open_plus                  = ctRegex!(`【\+`, "m");
     static inline_text_and_note_al                        = ctRegex!(`(?P<text>.+?)【(?:[*+ ]*)(?P<note>.+?)】`, "mg");
     static inline_text_and_note_al_                       = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|$))`, "mg");
-  }
-}
-/++
-  regex: regular expressions used in sisu document parser
-+/
-template SiSUoutputRgxInit() {
-  private import output_defaults;
-  struct Rgx {
     /+ inline markup footnotes endnotes +/
-    static inline_notes_al                                = ctRegex!(`【(?:[*+]\s+|\s*)(.+?)】`, "mg");
-    static inline_notes_al_gen                            = ctRegex!(`【.+?】`, "m");
-    static inline_al_delimiter_open_regular               = ctRegex!(`【\s`, "m");
-    static inline_al_delimiter_open_symbol_star           = ctRegex!(`【[*]\s`, "m");
-    static inline_al_delimiter_open_symbol_plus           = ctRegex!(`【[+]\s`, "m");
-    static inline_al_delimiter_close_regular              = ctRegex!(`】`, "m");
-    static inline_al_delimiter_open_and_close_regular     = ctRegex!(`【|】`, "m");
-    static inline_notes_delimiter_al_regular              = ctRegex!(`【(.+?)】`, "mg");
-    static inline_notes_delimiter_al_regular_number_note  = ctRegex!(`【(\d+)\s+(.+?)】`, "mg");
-    static inline_al_delimiter_open_asterisk              = ctRegex!(`【\*`, "m");
-    static inline_al_delimiter_open_plus                  = ctRegex!(`【\+`, "m");
-    static inline_text_and_note_al                        = ctRegex!(`(?P<text>.+?)【(?:[*+ ]*)(?P<note>.+?)】`, "mg");
-    static inline_text_and_note_al_                       = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|$))`, "mg");
+    static inline_link                                    = ctRegex!(`┥(.+?)┝┤(.+?)├`, "mg");
+    static inline_a_url                                   = ctRegex!(`(┤)(\S+?)(├)`, "mg");
+    static fn_suffix                                      = ctRegex!(`\.fnSuffix`, "mg");
+    static inline_link_fn_suffix                          = ctRegex!(`¤(.+?)(\.fnSuffix)`, "mg");
+    static inline_seg_link                                = ctRegex!(`(¤)(?:.+?)\.fnSuffix`, "mg");
+    static mark_internal_site_lnk                         = ctRegex!(`¤`, "mg");
   }
 }
diff --git a/src/sdp/output_epub.d b/src/sdp/output_epub.d
index ca11828..c66bf8f 100644
--- a/src/sdp/output_epub.d
+++ b/src/sdp/output_epub.d
@@ -17,9 +17,10 @@ template outputEPub() {
     std.typecons,
     std.uni,
     std.utf,
-    defaults;
+    std.conv : to;
   import
-    ao_rgx,
+    defaults,
+    output_rgx,
     output_xhtmls;
   mixin InternalMarkup;
   mixin outputXHTMLs;
@@ -161,11 +162,12 @@ template outputEPub() {
     auto return ref const D    doc_abstraction,
     auto return ref I          doc_matters,
   ) {
-    mixin SiSUrgxInit;
+    mixin SiSUoutputRgxInit;
     auto xhtml_format = outputXHTMLs();
     auto rgx = Rgx();
     // string[] toc;
     string[][string] doc_epub;
+    string[][string] doc_epub_endnotes;
     string[] doc;
     string segment_filename;
     string[] top_level_headings = ["","","",""];
@@ -173,6 +175,7 @@ template outputEPub() {
     auto meta_inf_container_xml = epub_container_xml;
     auto oebps_toc_ncx = epub_oebps_toc(doc_abstraction, doc_matters);
     auto oebps_content_opf = epub_oebps_content(doc_abstraction, doc_matters);
+    string suffix = ".xhtml";
     foreach (part; doc_matters.keys_seq_seg) {
       foreach (obj; doc_abstraction[part]) {
         if (obj.is_a == "heading") {
@@ -199,7 +202,8 @@ template outputEPub() {
               top_level_headings[3] = "";
               goto default;
             default:
-              top_level_headings[obj.heading_lev_markup] = xhtml_format.heading(obj);
+              auto t = xhtml_format.heading_seg(obj, suffix);
+              top_level_headings[obj.heading_lev_markup] = t[0];
               break;
             }
             break;
@@ -209,10 +213,14 @@ template outputEPub() {
             foreach (top_level_heading; top_level_headings) {
               doc_epub[segment_filename] ~= top_level_heading;
             }
-            doc_epub[segment_filename] ~= xhtml_format.heading(obj);
+            auto t = xhtml_format.heading_seg(obj, suffix);
+            doc_epub[segment_filename] ~= t[0];
+            doc_epub_endnotes[segment_filename] ~= t[1];
             break;
           case 5: .. case 7:
-            doc_epub[segment_filename] ~= xhtml_format.heading(obj);
+            auto t = xhtml_format.heading_seg(obj, suffix);
+            doc_epub[segment_filename] ~= t[0];
+            doc_epub_endnotes[segment_filename] ~= t[1];
             break;
           case 8: .. case 9: // unused numbers, if remain check
             if ((doc_matters.opt_action_bool["debug"])) {
@@ -254,7 +262,9 @@ template outputEPub() {
             case "para":
               switch (obj.is_a) {
               case "para":
-                doc_epub[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_epub[segment_filename] ~= t[0];
+                doc_epub_endnotes[segment_filename] ~= t[1];
                 break;
               default:
                 if ((doc_matters.opt_action_bool["debug"])) {
@@ -280,7 +290,9 @@ template outputEPub() {
                 doc_epub[segment_filename] ~= xhtml_format.nugget(obj);
                 break;
               case "table":
-                doc_epub[segment_filename] ~= xhtml_format.para(obj); //
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_epub[segment_filename] ~= t[0];
+                doc_epub_endnotes[segment_filename] ~= t[1];
                 break;
               case "code":
                 doc_epub[segment_filename] ~= xhtml_format.code(obj);
@@ -304,19 +316,28 @@ template outputEPub() {
             case "para":
               switch (obj.is_a) {
               case "endnote":
-                doc_epub[segment_filename] ~= xhtml_format.endnote(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_epub[segment_filename] ~= t[0];
                 break;
               case "glossary":
-                doc_epub[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_epub[segment_filename] ~= t[0];
+                doc_epub_endnotes[segment_filename] ~= t[1];
                 break;
               case "bibliography":
-                doc_epub[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_epub[segment_filename] ~= t[0];
+                doc_epub_endnotes[segment_filename] ~= t[1];
                 break;
               case "bookindex":
-                doc_epub[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_epub[segment_filename] ~= t[0];
+                doc_epub_endnotes[segment_filename] ~= t[1];
                 break;
               case "blurb":
-                doc_epub[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_epub[segment_filename] ~= t[0];
+                doc_epub_endnotes[segment_filename] ~= t[1];
                 break;
               default:
                 if ((doc_matters.opt_action_bool["debug"])) {
@@ -346,19 +367,21 @@ template outputEPub() {
     epub_write_output_files(
       doc_matters,
       doc_epub,
+      doc_epub_endnotes,
       mimetypes,
       meta_inf_container_xml,
       oebps_toc_ncx,
       oebps_content_opf,
     );
   }
-  void epub_write_output_files(C,EpD,Mt,Mic,Ot,Oc)(
-    C   doc_matters,
-    EpD doc_epub,
-    Mt  mimetypes,
-    Mic meta_inf_container_xml,
-    Ot  oebps_toc_ncx,
-    Oc  oebps_content_opf,
+  void epub_write_output_files(M,D,E,Mt,Mic,Ot,Oc)(
+    M    doc_matters,
+    D    doc_epub,
+    E    doc_epub_endnotes,
+    Mt   mimetypes,
+    Mic  meta_inf_container_xml,
+    Ot   oebps_toc_ncx,
+    Oc   oebps_content_opf,
   ) {
     debug(asserts){
       static assert(is(typeof(doc_epub)               == string[][string]));
@@ -387,6 +410,9 @@ template outputEPub() {
         foreach (docseg; doc_epub[seg_filename]) {
           f.writeln(docseg);
         }
+        foreach (docseg; doc_epub_endnotes[seg_filename]) {
+          f.writeln(docseg);
+        }
         f.writeln(xhtml_format.tail); // needed for each lev4
       }
       /+ mimetypes +/
diff --git a/src/sdp/output_html.d b/src/sdp/output_html.d
index 9b8fc86..d356ee5 100644
--- a/src/sdp/output_html.d
+++ b/src/sdp/output_html.d
@@ -17,9 +17,10 @@ template outputHTML() {
     std.typecons,
     std.uni,
     std.utf,
-    defaults;
+    std.conv : to;
   import
-    ao_rgx,
+    defaults,
+    output_rgx,
     output_xhtmls;
   mixin outputXHTMLs;
   
@@ -27,11 +28,12 @@ template outputHTML() {
     auto return ref const D    doc_abstraction,
     auto return ref I          doc_matters,
   ) {
-    mixin SiSUrgxInit;
+    mixin SiSUoutputRgxInit;
     auto xhtml_format = outputXHTMLs();
     auto rgx = Rgx();
     string[] doc_html;
     string[] doc;
+    string suffix = ".html";
     foreach (part; doc_matters.keys_seq_scroll) {
       foreach (obj; doc_abstraction[part]) {
         switch (obj.use) {
@@ -40,10 +42,10 @@ template outputHTML() {
           case "para":
             switch (obj.is_a) {
             case "heading":
-              doc_html ~= xhtml_format.heading(obj);
+              doc_html ~= xhtml_format.heading_scroll(obj, suffix);
               break;
             case "toc":
-              doc_html ~= xhtml_format.toc(obj);
+              doc_html ~= xhtml_format.para_scroll(obj, suffix);
               break;
             default:
               if ((doc_matters.opt_action_bool["debug"])) {
@@ -64,10 +66,10 @@ template outputHTML() {
           case "para":
             switch (obj.is_a) {
             case "heading":
-              doc_html ~= xhtml_format.heading(obj);
+              doc_html ~= xhtml_format.heading_scroll(obj, suffix);
               break;
             case "para":
-              doc_html ~= xhtml_format.para(obj);
+              doc_html ~= xhtml_format.para_scroll(obj, suffix);
               break;
             default:
               if ((doc_matters.opt_action_bool["debug"])) {
@@ -93,7 +95,7 @@ template outputHTML() {
               doc_html ~= xhtml_format.nugget(obj);
               break;
             case "table":
-              doc_html ~= xhtml_format.para(obj); //
+              doc_html ~= xhtml_format.para_scroll(obj, suffix);
               break;
             case "code":
               doc_html ~= xhtml_format.code(obj);
@@ -117,22 +119,22 @@ template outputHTML() {
           case "para":
             switch (obj.is_a) {
             case "heading":
-              doc_html ~= xhtml_format.heading(obj);
+              doc_html ~= xhtml_format.heading_scroll(obj, suffix);
               break;
             case "endnote":
-              doc_html ~= xhtml_format.endnote(obj);
+              doc_html ~= xhtml_format.para_scroll(obj, suffix);
               break;
             case "glossary":
-              doc_html ~= xhtml_format.para(obj);
+              doc_html ~= xhtml_format.para_scroll(obj, suffix);
               break;
             case "bibliography":
-              doc_html ~= xhtml_format.para(obj);
+              doc_html ~= xhtml_format.para_scroll(obj, suffix);
               break;
             case "bookindex":
-              doc_html ~= xhtml_format.para(obj);
+              doc_html ~= xhtml_format.para_scroll(obj, suffix);
               break;
             case "blurb":
-              doc_html ~= xhtml_format.para(obj);
+              doc_html ~= xhtml_format.para_scroll(obj, suffix);
               break;
             default:
               if ((doc_matters.opt_action_bool["debug"])) {
@@ -153,6 +155,8 @@ template outputHTML() {
         default:
           if ((doc_matters.opt_action_bool["debug"])) {
             writeln(__FILE__, ":", __LINE__, ": ", obj.use);
+            writeln(__FILE__, ":", __LINE__, ": ", obj.is_a);
+            writeln(__FILE__, ":", __LINE__, ": ", obj.text);
           }
           break;
         }
@@ -188,13 +192,15 @@ template outputHTML() {
     auto return ref const D    doc_abstraction,
     auto return ref I          doc_matters,
   ) {
-    mixin SiSUrgxInit;
+    mixin SiSUoutputRgxInit;
     auto rgx = Rgx();
     auto xhtml_format = outputXHTMLs();
     string[][string] doc_html;
+    string[][string] doc_html_endnotes;
     string[] doc;
     string segment_filename;
     string[] top_level_headings = ["","","",""];
+    string suffix = ".html";
     foreach (part; doc_matters.keys_seq_seg) {
       foreach (obj; doc_abstraction[part]) {
         if (obj.is_a == "heading") {                            // all headings: frontmatter, body & backmatter
@@ -221,7 +227,8 @@ template outputHTML() {
               top_level_headings[3] = "";
               goto default;
             default:
-              top_level_headings[obj.heading_lev_markup] = xhtml_format.heading(obj);
+              auto t = xhtml_format.heading_seg(obj, suffix);
+              top_level_headings[obj.heading_lev_markup] = t[0];
               break;
             }
             break;
@@ -231,10 +238,14 @@ template outputHTML() {
             foreach (top_level_heading; top_level_headings) {
               doc_html[segment_filename] ~= top_level_heading;
             }
-            doc_html[segment_filename] ~= xhtml_format.heading(obj);
+            auto t = xhtml_format.heading_seg(obj, suffix);
+            doc_html[segment_filename] ~= to!string(t[0]);
+            doc_html_endnotes[segment_filename] ~= t[1];
             break;
           case 5: .. case 7:
-            doc_html[segment_filename] ~= xhtml_format.heading(obj);
+            auto t = xhtml_format.heading_seg(obj, suffix);
+            doc_html[segment_filename] ~= to!string(t[0]);
+            doc_html_endnotes[segment_filename] ~= t[1];
             break;
           case 8: .. case 9: // unused numbers, if remain check
             if ((doc_matters.opt_action_bool["debug"])) {
@@ -255,7 +266,8 @@ template outputHTML() {
             case "para":
               switch (obj.is_a) {
               case "toc":
-                doc_html[segment_filename] ~= xhtml_format.toc(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_html[segment_filename] ~= to!string(t[0]);
                 break;
               default:
                 if ((doc_matters.opt_action_bool["debug"])) {
@@ -276,7 +288,9 @@ template outputHTML() {
             case "para":
               switch (obj.is_a) {
               case "para":
-                doc_html[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_html[segment_filename] ~= to!string(t[0]);
+                doc_html_endnotes[segment_filename] ~= t[1];
                 break;
               default:
                 if ((doc_matters.opt_action_bool["debug"])) {
@@ -302,7 +316,9 @@ template outputHTML() {
                 doc_html[segment_filename] ~= xhtml_format.nugget(obj);
                 break;
               case "table":
-                doc_html[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_html[segment_filename] ~= t[0];
+                doc_html_endnotes[segment_filename] ~= t[1];
                 break;
               case "code":
                 doc_html[segment_filename] ~= xhtml_format.code(obj);
@@ -326,19 +342,28 @@ template outputHTML() {
             case "para":
               switch (obj.is_a) {
               case "endnote":
-                doc_html[segment_filename] ~= xhtml_format.endnote(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_html[segment_filename] ~= t[0];
                 break;
               case "glossary":
-                doc_html[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_html[segment_filename] ~= t[0];
+                doc_html_endnotes[segment_filename] ~= t[1];
                 break;
               case "bibliography":
-                doc_html[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_html[segment_filename] ~= t[0];
+                doc_html_endnotes[segment_filename] ~= t[1];
                 break;
               case "bookindex":
-                doc_html[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_html[segment_filename] ~= t[0];
+                doc_html_endnotes[segment_filename] ~= t[1];
                 break;
               case "blurb":
-                doc_html[segment_filename] ~= xhtml_format.para(obj);
+                auto t = xhtml_format.para_seg(obj, suffix);
+                doc_html[segment_filename] ~= t[0];
+                doc_html_endnotes[segment_filename] ~= t[1];
                 break;
               default:
                 if ((doc_matters.opt_action_bool["debug"])) {
@@ -365,16 +390,17 @@ template outputHTML() {
         }
       }
     }
-    seg_write_output(doc_matters, doc_html);
+    seg_write_output(doc_matters, doc_html, doc_html_endnotes);
   }
-  void seg_write_output(M,C)(
+  void seg_write_output(M,D,E)(
     M doc_matters,
-    C doc_html,
+    D doc_html,
+    E doc_html_endnotes,
   ) {
     debug(asserts){
       static assert(is(typeof(doc_html)      == string[][string]));
     }
-    mixin SiSUrgxInit;
+    mixin SiSUoutputRgxInit;
     auto rgx = Rgx();
     mixin SiSUpaths;
     auto pth_html = HtmlPaths();
@@ -389,6 +415,9 @@ template outputHTML() {
         foreach (docseg; doc_html[seg_filename]) {
           f.writeln(docseg);
         }
+        foreach (docseg; doc_html_endnotes[seg_filename]) {
+          f.writeln(docseg);
+        }
         f.writeln(xhtml_format.tail); // needed for each lev4
       }
     }
@@ -517,403 +546,403 @@ template outputHTML() {
     p.i8 {padding-left: 8em;}
     p.i9 {padding-left: 9em;}
     /* hanging indent */
-    p.h0i0 {
+    p[indent=\"h0i0\"] {
       padding-left: 0em;
       text-indent:  0em;
     }
-    p.h0i1 {
+    p[indent=\"h0i1\"] {
       padding-left: 1em;
       text-indent: -1em;
     }
-    p.h0i2 {
+    p[indent=\"h0i2\"] {
       padding-left: 2em;
       text-indent: -2em;
     }
-    p.h0i3 {
+    p[indent=\"h0i3\"] {
       padding-left: 3em;
       text-indent: -3em;
     }
-    p.h0i4 {
+    p[indent=\"h0i4\"] {
       padding-left: 4em;
       text-indent: -4em;
     }
-    p.h0i5 {
+    p[indent=\"h0i5\"] {
       padding-left: 5em;
       text-indent: -5em;
     }
-    p.h0i6 {
+    p[indent=\"h0i6\"] {
       padding-left: 6em;
       text-indent: -6em;
     }
-    p.h0i7 {
+    p[indent=\"h0i7\"] {
       padding-left: 7em;
       text-indent: -7em;
     }
-    p.h0i8 {
+    p[indent=\"h0i8\"] {
       padding-left: 8em;
       text-indent: -8em;
     }
-    p.h0i9 {
+    p[indent=\"h0i9\"] {
       padding-left: 9em;
       text-indent: -9em;
     }
-    p.h1i0 {
+    p[indent=\"h1i0\"] {
       padding-left: 0em;
       text-indent:  1em;
     }
-    p.h1i1 {
+    p[indent=\"h1i1\"] {
       padding-left: 1em;
       text-indent:  0em;
     }
-    p.h1i2 {
+    p[indent=\"h1i2\"] {
       padding-left: 2em;
       text-indent: -1em;
     }
-    p.h1i3 {
+    p[indent=\"h1i3\"] {
       padding-left: 3em;
       text-indent: -2em;
     }
-    p.h1i4 {
+    p[indent=\"h1i4\"] {
       padding-left: 4em;
       text-indent: -3em;
     }
-    p.h1i5 {
+    p[indent=\"h1i5\"] {
       padding-left: 5em;
       text-indent: -4em;
     }
-    p.h1i6 {
+    p[indent=\"h1i6\"] {
       padding-left: 6em;
       text-indent: -5em;
     }
-    p.h1i7 {
+    p[indent=\"h1i7\"] {
       padding-left: 7em;
       text-indent: -6em;
     }
-    p.h1i8 {
+    p[indent=\"h1i8\"] {
       padding-left: 8em;
       text-indent: -7em;
     }
-    p.h1i9 {
+    p[indent=\"h1i9\"] {
       padding-left: 9em;
       text-indent: -8em;
     }
-    p.h2i0 {
+    p[indent=\"h2i0\"] {
       padding-left: 0em;
       text-indent:  2em;
     }
-    p.h2i1 {
+    p[indent=\"h2i1\"] {
       padding-left: 1em;
       text-indent:  1em;
     }
-    p.h2i2 {
+    p[indent=\"h2i2\"] {
       padding-left: 2em;
       text-indent:  0em;
     }
-    p.h2i3 {
+    p[indent=\"h2i3\"] {
       padding-left: 3em;
       text-indent: -1em;
     }
-    p.h2i4 {
+    p[indent=\"h2i4\"] {
       padding-left: 4em;
       text-indent: -2em;
     }
-    p.h2i5 {
+    p[indent=\"h2i5\"] {
       padding-left: 5em;
       text-indent: -3em;
     }
-    p.h2i6 {
+    p[indent=\"h2i6\"] {
       padding-left: 6em;
       text-indent: -4em;
     }
-    p.h2i7 {
+    p[indent=\"h2i7\"] {
       padding-left: 7em;
       text-indent: -5em;
     }
-    p.h2i8 {
+    p[indent=\"h2i8\"] {
       padding-left: 8em;
       text-indent: -6em;
     }
-    p.h2i9 {
+    p[indent=\"h2i9\"] {
       padding-left: 9em;
       text-indent: -7em;
     }
-    p.h3i0 {
+    p[indent=\"h3i0\"] {
       padding-left: 0em;
       text-indent:  3em;
     }
-    p.h3i1 {
+    p[indent=\"h3i1\"] {
       padding-left: 1em;
       text-indent:  2em;
     }
-    p.h3i2 {
+    p[indent=\"h3i2\"] {
       padding-left: 2em;
       text-indent:  1em;
     }
-    p.h3i3 {
+    p[indent=\"h3i3\"] {
       padding-left: 3em;
       text-indent:  0em;
     }
-    p.h3i4 {
+    p[indent=\"h3i4\"] {
       padding-left: 4em;
       text-indent: -1em;
     }
-    p.h3i5 {
+    p[indent=\"h3i5\"] {
       padding-left: 5em;
       text-indent: -2em;
     }
-    p.h3i6 {
+    p[indent=\"h3i6\"] {
       padding-left: 6em;
       text-indent: -3em;
     }
-    p.h3i7 {
+    p[indent=\"h3i7\"] {
       padding-left: 7em;
       text-indent: -4em;
     }
-    p.h3i8 {
+    p[indent=\"h3i8\"] {
       padding-left: 8em;
       text-indent: -5em;
     }
-    p.h3i9 {
+    p[indent=\"h3i9\"] {
       padding-left: 9em;
       text-indent: -6em;
     }
-    p.h4i0 {
+    p[indent=\"h4i0\"] {
       padding-left: 0em;
       text-indent:  4em;
     }
-    p.h4i1 {
+    p[indent=\"h4i1\"] {
       padding-left: 1em;
       text-indent:  3em;
     }
-    p.h4i2 {
+    p[indent=\"h4i2\"] {
       padding-left: 2em;
       text-indent:  2em;
     }
-    p.h4i3 {
+    p[indent=\"h4i3\"] {
       padding-left: 3em;
       text-indent:  1em;
     }
-    p.h4i4 {
+    p[indent=\"h4i4\"] {
       padding-left: 4em;
       text-indent:  0em;
     }
-    p.h4i5 {
+    p[indent=\"h4i5\"] {
       padding-left: 5em;
       text-indent: -1em;
     }
-    p.h4i6 {
+    p[indent=\"h4i6\"] {
       padding-left: 6em;
       text-indent: -2em;
     }
-    p.h4i7 {
+    p[indent=\"h4i7\"] {
       padding-left: 7em;
       text-indent: -3em;
     }
-    p.h4i8 {
+    p[indent=\"h4i8\"] {
       padding-left: 8em;
       text-indent: -4em;
     }
-    p.h4i9 {
+    p[indent=\"h4i9\"] {
       padding-left: 9em;
       text-indent: -5em;
     }
-    p.h5i0 {
+    p[indent=\"h5i0\"] {
       padding-left: 0em;
       text-indent:  5em;
     }
-    p.h5i1 {
+    p[indent=\"h5i1\"] {
       padding-left: 1em;
       text-indent:  4em;
     }
-    p.h5i2 {
+    p[indent=\"h5i2\"] {
       padding-left: 2em;
       text-indent:  3em;
     }
-    p.h5i3 {
+    p[indent=\"h5i3\"] {
       padding-left: 3em;
       text-indent:  2em;
     }
-    p.h5i4 {
+    p[indent=\"h5i4\"] {
       padding-left: 4em;
       text-indent:  1em;
     }
-    p.h5i5 {
+    p[indent=\"h5i5\"] {
       padding-left: 5em;
       text-indent:  0em;
     }
-    p.h5i6 {
+    p[indent=\"h5i6\"] {
       padding-left: 6em;
       text-indent: -1em;
     }
-    p.h5i7 {
+    p[indent=\"h5i7\"] {
       padding-left: 7em;
       text-indent: -2em;
     }
-    p.h5i8 {
+    p[indent=\"h5i8\"] {
       padding-left: 8em;
       text-indent: -3em;
     }
-    p.h5i9 {
+    p[indent=\"h5i9\"] {
       padding-left: 9em;
       text-indent: -4em;
     }
-    p.h6i0 {
+    p[indent=\"h6i0\"] {
       padding-left: 0em;
       text-indent:  6em;
     }
-    p.h6i1 {
+    p[indent=\"h6i1\"] {
       padding-left: 1em;
       text-indent:  5em;
     }
-    p.h6i2 {
+    p[indent=\"h6i2\"] {
       padding-left: 2em;
       text-indent:  4em;
     }
-    p.h6i3 {
+    p[indent=\"h6i3\"] {
       padding-left: 3em;
       text-indent:  3em;
     }
-    p.h6i4 {
+    p[indent=\"h6i4\"] {
       padding-left: 4em;
       text-indent:  2em;
     }
-    p.h6i5 {
+    p[indent=\"h6i5\"] {
       padding-left: 5em;
       text-indent:  1em;
     }
-    p.h6i6 {
+    p[indent=\"h6i6\"] {
       padding-left: 6em;
       text-indent:  0em;
     }
-    p.h6i7 {
+    p[indent=\"h6i7\"] {
       padding-left: 7em;
       text-indent: -1em;
     }
-    p.h6i8 {
+    p[indent=\"h6i8\"] {
       padding-left: 8em;
       text-indent: -2em;
     }
-    p.h6i9 {
+    p[indent=\"h6i9\"] {
       padding-left: 9em;
       text-indent: -3em;
     }
-    p.h7i0 {
+    p[indent=\"h7i0\"] {
       padding-left: 0em;
       text-indent:  7em;
     }
-    p.h7i1 {
+    p[indent=\"h7i1\"] {
       padding-left: 1em;
       text-indent:  6em;
     }
-    p.h7i2 {
+    p[indent=\"h7i2\"] {
       padding-left: 2em;
       text-indent:  5em;
     }
-    p.h7i3 {
+    p[indent=\"h7i3\"] {
       padding-left: 3em;
       text-indent:  4em;
     }
-    p.h7i4 {
+    p[indent=\"h7i4\"] {
       padding-left: 4em;
       text-indent:  3em;
     }
-    p.h7i5 {
+    p[indent=\"h7i5\"] {
       padding-left: 5em;
       text-indent:  2em;
     }
-    p.h7i6 {
+    p[indent=\"h7i6\"] {
       padding-left: 6em;
       text-indent:  1em;
     }
-    p.h7i7 {
+    p[indent=\"h7i7\"] {
       padding-left: 7em;
       text-indent:  0em;
     }
-    p.h7i8 {
+    p[indent=\"h7i8\"] {
       padding-left: 8em;
       text-indent: -1em;
     }
-    p.h7i9 {
+    p[indent=\"h7i9\"] {
       padding-left: 9em;
       text-indent: -2em;
     }
-    p.h8i0 {
+    p[indent=\"h8i0\"] {
       padding-left: 0em;
       text-indent:  8em;
     }
-    p.h8i1 {
+    p[indent=\"h8i1\"] {
       padding-left: 1em;
       text-indent:  7em;
     }
-    p.h8i2 {
+    p[indent=\"h8i2\"] {
       padding-left: 2em;
       text-indent:  6em;
     }
-    p.h8i3 {
+    p[indent=\"h8i3\"] {
       padding-left: 3em;
       text-indent:  5em;
     }
-    p.h8i4 {
+    p[indent=\"h8i4\"] {
       padding-left: 4em;
       text-indent:  4em;
     }
-    p.h8i5 {
+    p[indent=\"h8i5\"] {
       padding-left: 5em;
       text-indent:  3em;
     }
-    p.h8i6 {
+    p[indent=\"h8i6\"] {
       padding-left: 6em;
       text-indent:  2em;
     }
-    p.h8i7 {
+    p[indent=\"h8i7\"] {
       padding-left: 7em;
       text-indent:  1em;
     }
-    p.h8i8 {
+    p[indent=\"h8i8\"] {
       padding-left: 8em;
       text-indent:  0em;
     }
-    p.h8i9 {
+    p[indent=\"h8i9\"] {
       padding-left: 9em;
       text-indent: -1em;
     }
-    p.h9i0 {
+    p[indent=\"h9i0\"] {
       padding-left: 0em;
       text-indent:  9em;
     }
-    p.h9i1 {
+    p[indent=\"h9i1\"] {
       padding-left: 1em;
       text-indent:  8em;
     }
-    p.h9i2 {
+    p[indent=\"h9i2\"] {
       padding-left: 2em;
       text-indent:  7em;
     }
-    p.h9i3 {
+    p[indent=\"h9i3\"] {
       padding-left: 3em;
       text-indent:  6em;
     }
-    p.h9i4 {
+    p[indent=\"h9i4\"] {
       padding-left: 4em;
       text-indent:  5em;
     }
-    p.h9i5 {
+    p[indent=\"h9i5\"] {
       padding-left: 5em;
       text-indent:  4em;
     }
-    p.h9i6 {
+    p[indent=\"h9i6\"] {
       padding-left: 6em;
       text-indent:  3em;
     }
-    p.h9i7 {
+    p[indent=\"h9i7\"] {
       padding-left: 7em;
       text-indent:  2em;
     }
-    p.h9i8 {
+    p[indent=\"h9i8\"] {
       padding-left: 8em;
       text-indent:  1em;
     }
-    p.h9i9 {
+    p[indent=\"h9i9\"] {
       padding-left: 9em;
       text-indent:  0em;
     }
diff --git a/src/sdp/output_hub.d b/src/sdp/output_hub.d
index a1182a6..67275e0 100644
--- a/src/sdp/output_hub.d
+++ b/src/sdp/output_hub.d
@@ -27,10 +27,10 @@ template outputHub() {
     output_xhtmls,
     source_sisupod;
   import
-    ao_rgx,
+    output_rgx,
     output_xhtmls;
   void outputHub(D,I)(D doc_abstraction, I doc_matters) {
-    mixin SiSUrgxInit;
+    mixin SiSUoutputRgxInit;
     auto rgx = Rgx();
     if ((doc_matters.opt_action_bool["verbose"])) {
       writeln(doc_matters.keys_seq_seg);
diff --git a/src/sdp/output_rgx.d b/src/sdp/output_rgx.d
new file mode 100644
index 0000000..5a9a47e
--- /dev/null
+++ b/src/sdp/output_rgx.d
@@ -0,0 +1,37 @@
+/++
+  regex: regular expressions used in sisu document parser
++/
+template SiSUoutputRgxInit() {
+  private import defaults;
+  struct Rgx {
+    static src_pth                                        = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])$`);
+    static src_fn                                         =
+      ctRegex!(`^([a-zA-Z0-9._-]+/)*(?P<fn_src>(?P<fn_base>[a-zA-Z0-9._-]+)[.](?P<fn_src_suffix>ss[tm]))$`);
+    static src_fn_master                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssm)$`);
+    static src_fn_text                                    = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]sst)$`);
+    static src_fn_insert                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssi)$`);
+    static src_fn_find_inserts                            = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[im])$`);
+    static insert_src_fn_ssi_or_sst                       = ctRegex!(`^<<\s*(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`);
+    /+ inline markup footnotes endnotes +/
+    static inline_notes_al                                = ctRegex!(`【(?:[*+]\s+|\s*)(.+?)】`, "mg");
+    static inline_notes_al_gen                            = ctRegex!(`【.+?】`, "m");
+    static inline_al_delimiter_open_regular               = ctRegex!(`【\s`, "m");
+    static inline_al_delimiter_open_symbol_star           = ctRegex!(`【[*]\s`, "m");
+    static inline_al_delimiter_open_symbol_plus           = ctRegex!(`【[+]\s`, "m");
+    static inline_al_delimiter_close_regular              = ctRegex!(`】`, "m");
+    static inline_al_delimiter_open_and_close_regular     = ctRegex!(`【|】`, "m");
+    static inline_notes_delimiter_al_regular              = ctRegex!(`【(.+?)】`, "mg");
+    static inline_notes_delimiter_al_regular_number_note  = ctRegex!(`【(\d+)\s+(.+?)】`, "mg");
+    static inline_al_delimiter_open_asterisk              = ctRegex!(`【\*`, "m");
+    static inline_al_delimiter_open_plus                  = ctRegex!(`【\+`, "m");
+    static inline_text_and_note_al                        = ctRegex!(`(?P<text>.+?)【(?:[*+ ]*)(?P<note>.+?)】`, "mg");
+    static inline_text_and_note_al_                       = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|$))`, "mg");
+    /+ inline markup footnotes endnotes +/
+    static inline_link                                    = ctRegex!(`┥(.+?)┝┤(.+?)├`, "mg");
+    static inline_a_url                                   = ctRegex!(`(┤)(\S+?)(├)`, "mg");
+    static fn_suffix                                      = ctRegex!(`\.fnSuffix`, "mg");
+    static inline_link_fn_suffix                          = ctRegex!(`¤(.+?)(\.fnSuffix)`, "mg");
+    static inline_seg_link                                = ctRegex!(`(¤)(?:.+?)\.fnSuffix`, "mg");
+    static mark_internal_site_lnk                         = ctRegex!(`¤`, "mg");
+  }
+}
diff --git a/src/sdp/output_xhtmls.d b/src/sdp/output_xhtmls.d
index 6a4c3a3..de5236d 100644
--- a/src/sdp/output_xhtmls.d
+++ b/src/sdp/output_xhtmls.d
@@ -1,5 +1,30 @@
 template outputXHTMLs() {
+  private import
+    std.algorithm,
+    std.array,
+    std.container,
+    std.exception,
+    std.file,
+    std.getopt,
+    std.json,
+    std.process,
+    std.stdio,
+    std.path,
+    std.range,
+    std.regex,
+    std.string,
+    std.traits,
+    std.typecons,
+    std.uni,
+    std.utf,
+    std.conv : to;
+  import
+    defaults,
+    output_rgx,
+    output_xhtmls;
+  mixin SiSUoutputRgxInit;
   struct outputXHTMLs {
+    auto rgx = Rgx();
     string _xhtml_anchor_tags(const(string[]) anchor_tags) {
       string tags="";
       if (anchor_tags.length > 0) {
@@ -98,6 +123,137 @@ template outputXHTMLs() {
     </html>¶");
       return o;
     }
+    auto inline_links(O)(
+      auto return ref const O obj,
+      string                  _txt,
+      string                  _suffix    = ".html",
+      string                  seg_scroll = "seg",
+    ) {
+      if (obj.inline_links) {
+        if ((seg_scroll == "scroll")
+        && match(_txt, rgx.mark_internal_site_lnk)) {
+          _txt = (_txt).replaceAll(
+            rgx.inline_seg_link,
+            "$1");
+        }
+        _txt = (_txt).replaceAll(
+          rgx.inline_link_fn_suffix,
+          ("$1" ~ _suffix));
+        _txt = (_txt).replaceAll(
+          rgx.inline_link,
+          ("<a href=\"$2\">$1</a>"));
+        _txt = (_txt).replaceAll(
+          rgx.mark_internal_site_lnk,
+          ""
+        );
+      }
+      debug(markup_links) {
+        if ( match(_txt, rgx.inline_link)) {
+          writeln(__LINE__,
+            " (missed) markup link identified (",
+            obj.inline_links,
+            "): ", obj.is_a, ": ",
+            obj.text
+          );
+        }
+      }
+      debug(markup) {
+        if ( match(_txt, rgx.inline_link)) {
+          writeln(__LINE__,
+            " (missed) markup link identified (",
+            obj.inline_links,
+            "): ", obj.is_a, ": ",
+            obj.text
+          );
+        }
+      }
+      return _txt;
+    }
+    auto inline_notes_scroll(O)(
+      auto return ref const O         obj,
+      string                  _txt,
+    ) {
+      if (obj.inline_notes_reg) {
+        _txt = (_txt).replaceAll(
+          rgx.inline_notes_delimiter_al_regular_number_note,
+          ("<a href=\"#note_$1\"><note id=\"noteref_$1\">&nbsp;<sup>$1</sup>&nbsp;</note></a>")
+        );
+      }
+      debug(markup_endnotes) {
+        if (match(_txt, rgx.inline_notes_delimiter_al_regular_number_note)) {
+          writeln(__LINE__, " (missed) markup endnote: ", obj.is_a, ": ", obj.text);
+        }
+      }
+      debug(markup) {
+        if (match(_txt, rgx.inline_notes_delimiter_al_regular_number_note)) {
+          writeln(__LINE__, " (missed) markup endnote: ", obj.is_a, ": ", obj.text);
+        }
+      }
+      // if (obj.inline_notes_star) {
+      //   _txt = replaceAll(
+      //     _txt,
+      //     rgx.inline_notes_delimiter_al_regular_number_note,
+      //     ("<a href=\"#note_$1\"><note id=\"noteref_$1\">&nbsp;<sup>$1</sup>&nbsp;</note></a>")
+      //   );
+      // }
+      return _txt;
+    }
+    auto inline_notes_seg(O)(
+      auto return ref const O     obj,
+      string                      _txt,
+    ) {
+      string[] _endnotes;
+      if (obj.inline_notes_reg) {
+        /+ need markup for text, and separated footnote +/
+        foreach(m; matchAll(_txt, rgx.inline_notes_delimiter_al_regular_number_note)) {
+          _endnotes ~= format(
+            "%s%s%s%s\n  %s%s%s%s%s\n  %s\n%s",
+            "<p class=\"endnote\">",
+            "<a href=\"#noteref_",
+            m.captures[1],
+            "\">",
+            "<note id=\"note_",
+            m.captures[1],
+            "\">&nbsp;<sup>",
+            m.captures[1],
+            ".</sup></note></a>",
+            m.captures[2],
+            "</p>"
+          );
+        }
+        _txt = (_txt).replaceAll(
+          rgx.inline_notes_delimiter_al_regular_number_note,
+          ("<a href=\"#note_$1\"><note id=\"noteref_$1\">&nbsp;<sup>$1</sup>&nbsp;</note></a>")
+        );
+      } else if (match(_txt, rgx.inline_notes_delimiter_al_regular_number_note)) {
+        debug(markup) {
+          writeln(__LINE__, " endnote: ", obj.is_a, ": ", obj.text);
+        }
+      }
+      auto t = tuple(
+        _txt,
+        _endnotes,
+      );
+      return t;
+    }
+    auto inline_markup_scroll(O)(
+      auto return ref const O  obj,
+      string                   _suffix = ".html",
+    ) {
+      string _txt = obj.text;
+      _txt = inline_links(obj, _txt, _suffix, "scroll");
+      _txt = inline_notes_scroll(obj, _txt);
+      return _txt;
+    }
+    auto inline_markup_seg(O)(
+      auto return ref const O  obj,
+      string                   _suffix = ".html",
+    ) {
+      string _txt = obj.text;
+      _txt = inline_links(obj, _txt, _suffix, "seg");
+      auto t = inline_notes_seg(obj, _txt);
+      return t;
+    }
     auto toc(O)(
       auto return ref const O    obj,
     ) {
@@ -116,6 +272,7 @@ template outputXHTMLs() {
     }
     auto heading(O)(
       auto return ref const O    obj,
+      string                     _txt,
     ) {
       auto tags = _xhtml_anchor_tags(obj.anchor_tags);
       string o;
@@ -129,7 +286,7 @@ template outputXHTMLs() {
           obj.heading_lev_markup,
           obj.is_a,
           tags,
-          obj.text,
+          _txt,
           obj.heading_lev_markup,
         );
       } else {
@@ -147,14 +304,38 @@ template outputXHTMLs() {
         obj.obj_cite_number,
         obj.obj_cite_number,
         tags,
-        obj.text,
+        _txt,
         obj.heading_lev_markup,
         );
       }
       return o;
     }
+    auto heading_scroll(O)(
+      auto return ref const O    obj,
+      string                     _suffix = ".html",
+    ) {
+      auto tags = _xhtml_anchor_tags(obj.anchor_tags);
+      string _txt = inline_markup_scroll(obj, _suffix); // issue
+      string o = heading(obj, _txt);
+      return o;
+    }
+    auto heading_seg(O)(
+      auto return ref const O    obj,
+      string                     _suffix = ".html",
+    ) {
+      auto t = inline_markup_seg(obj, _suffix);
+      string _txt = t[0];
+      string[] _endnotes = t[1];
+      string o = heading(obj, _txt);
+      auto u = tuple(
+        o,
+        _endnotes,
+      );
+      return u;
+    }
     auto para(O)(
       auto return ref const O    obj,
+      string                     _txt,
     ) {
       auto tags = _xhtml_anchor_tags(obj.anchor_tags);
       string o;
@@ -168,7 +349,7 @@ template outputXHTMLs() {
           obj.indent_hang,
           obj.indent_base,
           tags,
-          obj.text
+          _txt
         );
       } else {
         o = format(q"¶  <div class="substance">
@@ -184,11 +365,34 @@ template outputXHTMLs() {
           obj.indent_base,
           obj.obj_cite_number,
           tags,
-          obj.text
+          _txt
         );
       }
       return o;
     }
+    auto para_scroll(O)(
+      auto return ref const O    obj,
+      string                     _suffix = ".html",
+    ) {
+      auto tags = _xhtml_anchor_tags(obj.anchor_tags);
+      string _txt = inline_markup_scroll(obj, _suffix); // issue
+      string o = para(obj, _txt);
+      return o;
+    }
+    auto para_seg(O)(
+      auto return ref const O    obj,
+      string                     _suffix = ".html",
+    ) {
+      auto t = inline_markup_seg(obj, _suffix);
+      string _txt = to!string(t[0]);
+      string[] _endnotes = t[1];
+      string o = para(obj, _txt);
+      auto u = tuple(
+        o,
+        _endnotes,
+      );
+      return u;
+    }
     auto nugget(O)(
       auto return ref const O    obj,
     ) {
diff --git a/src/sdp/source_sisupod.d b/src/sdp/source_sisupod.d
index aa91b6d..ce2bfaf 100644
--- a/src/sdp/source_sisupod.d
+++ b/src/sdp/source_sisupod.d
@@ -17,15 +17,16 @@ template SiSUpod() {
     std.typecons,
     std.uni,
     std.utf,
-    defaults;
+    std.conv : to;
   import
-    ao_rgx,
+    defaults,
+    output_rgx,
     output_xhtmls;
   void SiSUpod(T)(T doc_matters) {
     debug(asserts){
       // static assert(is(typeof(doc_matters) == tuple));
     }
-    mixin SiSUrgxInit;
+    mixin SiSUoutputRgxInit;
     mixin SiSUpaths;
     auto pth_sisupod = SiSUpodPaths();
     mixin SiSUlanguageCodes;
@@ -103,6 +104,7 @@ template SiSUpod() {
           );
         }
       }
+      
     }
     catch (ErrnoException ex) {
       // Handle error
diff --git a/views/version.txt b/views/version.txt
index 7b826fb..93bb85a 100644
--- a/views/version.txt
+++ b/views/version.txt
@@ -4,4 +4,4 @@ struct Version {
   int minor;
   int patch;
 }
-enum ver = Version(0, 13, 4);
+enum ver = Version(0, 13, 5);
-- 
cgit v1.2.3