From a87a80c4528ce1bfd0090b425f4194eddf33699c Mon Sep 17 00:00:00 2001
From: Ralph Amissah <ralph@amissah.com>
Date: Thu, 23 Jun 2016 00:55:33 -0400
Subject: step5.1 headers sdlang (like native headers) converted to json for
 common internal format

---
 src/sdp.d                        |   15 +-
 src/sdp/ao_abstract_doc_source.d |   10 +-
 src/sdp/ao_defaults.d            |  265 +++++---
 src/sdp/ao_header_extract.d      | 1307 ++++++++++++++++++++++++++++++++++++++
 src/sdp/ao_read_source_files.d   |   57 +-
 src/sdp/ao_rgx.d                 |   46 +-
 6 files changed, 1524 insertions(+), 176 deletions(-)
 create mode 100644 src/sdp/ao_header_extract.d

(limited to 'src')

diff --git a/src/sdp.d b/src/sdp.d
index c29014c..e19a21e 100755
--- a/src/sdp.d
+++ b/src/sdp.d
@@ -8,6 +8,7 @@ import
   compile_time_info,          // sdp/compile_time_info.d
   ao_abstract_doc_source,     // sdp/ao_abstract_doc_source.d
   ao_defaults,                // sdp/ao_defaults.d
+  ao_header_extract,          // sdp/ao_header_extract.d
   ao_read_config_files,       // sdp/ao_read_config_files.d
   ao_read_source_files,       // sdp/ao_read_source_files.d
   ao_output_debugs,           // sdp/ao_output_debugs.d
@@ -98,6 +99,8 @@ mixin RgxInit;
 void main(string[] args) {
   
   mixin SiSUheaderSkel;
+  mixin SiSUheaderExtractNative;
+  mixin SiSUheaderExtractSDLang;
   mixin SiSUbiblio;
   mixin SiSUrgxInitFlags;
   mixin SiSUconfiguration;
@@ -107,6 +110,7 @@ void main(string[] args) {
   mixin SiSUoutputHub;
   mixin ScreenTxtColors;
   auto raw = MarkupRaw();
+  auto head_native = HeaderDocMetadataAndMakeNativeToJson();
   auto headsdl = HeaderExtractSDL();
   auto abs = Abstraction();
   auto dbg = SDPoutputDebugs();
@@ -266,9 +270,14 @@ void main(string[] args) {
         writeln(header_and_content_tuple.length);
         writeln(sourcefile_content[0]);
       }
-      /+ ↓ headers metadata & make sdlang +/
-      auto header_sdlang = headsdl.headerSDLang(header);
-      /+ ↓ porcess document, return abstraction as tuple +/
+      // Tuple!(JSONValue[string], JSONValue[string]) header_make_and_meta_tuple;
+      auto header_make_and_meta_tuple = (match(header, rgx.native_header_meta_title))
+      ? (head_native.headerContentJSON(header))
+      : (headsdl.headerSDLangToJSON(header));
+      static assert(!isTypeTuple!(header_make_and_meta_tuple));
+      JSONValue[string] dochead_make_json = header_make_and_meta_tuple[0];
+      JSONValue[string] dochead_meta_json = header_make_and_meta_tuple[1];
+      /+ ↓ process document, return abstraction as tuple +/
       auto t = abs.abstract_doc_source(sourcefile_content);
       static assert(!isTypeTuple!(t));
       auto doc_ao_contents = t[0]; // contents ~ endnotes ~ bookindex;
diff --git a/src/sdp/ao_abstract_doc_source.d b/src/sdp/ao_abstract_doc_source.d
index c814c15..aca4944 100644
--- a/src/sdp/ao_abstract_doc_source.d
+++ b/src/sdp/ao_abstract_doc_source.d
@@ -338,11 +338,11 @@ template SiSUdocAbstraction() {
                 && ((type["para"] == State.off)
                 && (type["heading"] == State.off))) {
                   /+ heading or para but neither flag nor line exists +/
-                  // if ((to!string(dochead_make["make"]["headings"]).length > 2)
+                  // if ((to!string(dochead_make_json["make"]["headings"]).length > 2)
                   // && (type["make_headings"] == State.off)) {
                   //   /+ heading found +/
                   //   auto dochead_make_headings =
-                  //     to!string(dochead_make["make"]["headings"]);
+                  //     to!string(dochead_make_json["make"]["headings"]);
                   //   heading_found(line, dochead_make_headings, heading_match_str, heading_match_rgx, type);
                   // }
                   if ((type["make_headings"] == State.on)
@@ -1691,10 +1691,8 @@ template SiSUdocAbstraction() {
         assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels
         switch (an_object["lev"]) {
         case "A":
-          // an_object["obj"]=replaceFirst(an_object["obj"], rgx.head_value_title, to!string(dochead_metadata["title"]["main"]));
-          // an_object["obj"]=replaceFirst(an_object["obj"], rgx.head_value_author, to!string(dochead_metadata["creator"]["author"]));
-          // // an_object["obj"]=replaceFirst(an_object["obj"], rgx.head_value_title, to!string(parseJSON(dochead_metadata["title"]["main"])));
-          // // an_object["obj"]=replaceFirst(an_object["obj"], rgx.head_value_author, to!string(parseJSON(dochead_metadata["creator"]["author"])));
+          // an_object["obj"]=replaceFirst(an_object["obj"], rgx.variable_doc_title, to!string(dochead_meta_json["title"]["main"]));
+          // an_object["obj"]=replaceFirst(an_object["obj"], rgx.variable_doc_author, to!string(dochead_meta_json["creator"]["author"]));
           collapsed_lev["h0"] = 1;
           an_object["lev_collapsed_number"] =
             to!string(collapsed_lev["h0"]);
diff --git a/src/sdp/ao_defaults.d b/src/sdp/ao_defaults.d
index 087067c..b6eeae1 100644
--- a/src/sdp/ao_defaults.d
+++ b/src/sdp/ao_defaults.d
@@ -5,148 +5,125 @@
 template SiSUheaderSkel() {
   auto header_make_jsonstr = `{
     "make": {
+      "bold"               : "",
+      "breaks"             : "",
       "cover_image"        : "",
-      "home_button_image"  : "",
-      "home_button_text"   : "",
+      "css"                : "",
+      "emphasis"           : "",
       "footer"             : "",
       "headings"           : "",
+      "home_button_image"  : "",
+      "home_button_text"   : "",
+      "italics"            : "",
       "num_top"            : "",
-      "breaks"             : "",
       "substitute"         : "",
-      "bold"               : "",
-      "italics"            : "",
-      "emphasis"           : "",
-      "texpdf_font"        : "",
-      "css"                : ""
+      "texpdf_font"        : ""
     }
   }`;
   auto header_meta_jsonstr = `{
+    "classify": {
+      "dewey"              : "",
+      "keywords"           : "",
+      "loc"                : "",
+      "subject"            : "",
+      "topic_register"     : ""
+    },
     "creator": {
       "author"             : "",
-      "translator"         : "",
-      "illustrator"        : ""
-    },
-    "title": {
-      "main"               : "",
-      "sub"                : "",
-      "full"               : "",
-      "language"           : "",
-      "edition"            : "",
-      "note"               : ""
-    },
-    "rights": {
-      "copyright"          : "",
-      "illustrations"      : "",
-      "license"            : "",
-      "cover"              : ""
+      "author_email"       : "",
+      "illustrator"        : "",
+      "translator"         : ""
     },
     "date": {
-      "published"          : "",
+      "added_to_site"      : "",
+      "available"          : "",
       "created"            : "",
       "issued"             : "",
-      "available"          : "",
-      "valid"              : "",
       "modified"           : "",
-      "added_to_site"      : ""
-    },
-    "original": {
-      "title"              : "",
-      "language"           : "",
-      "source"             : ""
-    },
-    "classify": {
-      "topic_register"     : "",
-      "subject"            : "",
-      "keywords"           : "",
-      "loc"                : "",
-      "dewey"              : ""
+      "published"          : "",
+      "valid"              : ""
     },
     "identifier": {
+      "isbn"               : "",
       "oclc"               : "",
-      "pg"                 : "",
-      "isbn"               : ""
+      "pg"                 : ""
+    },
+    "links": {
+      "link"               : ""
     },
     "notes": {
       "abstract"           : "",
       "description"        : ""
     },
+    "original": {
+      "language"           : "",
+      "source"             : "",
+      "title"              : ""
+    },
     "publisher": {
       "name"               : ""
     },
-    "links": {
+    "rights": {
+      "copyright"          : "",
+      "cover"              : "",
+      "illustrations"      : "",
+      "license"            : ""
+    },
+    "title": {
+      "edition"            : "",
+      "full"               : "",
+      "language"           : "",
+      "main"               : "",
+      "note"               : "",
+      "sub"                : ""
     }
   }`; // links
+  auto pointer_head_sub_classify =
+    [
+      "dewey",
+      "keywords",         //
+      "loc",
+      "subject",
+      "topic_register"
+    ];
   auto pointer_head_main =
     [
+      "classify",
       "creator",
-      "title",
-      "rights",
       "date",
-      "original",
-      "classify",
       "identifier",
+      "links",
+      "make",             /+ make +/
+      "original",
       "notes",
-      "make",
-      "links"
+      "rights",
+      "title"
     ];
   auto pointer_head_sub_creator =
     [
       "author",
-      "translator",
+      "author_email",
+      "cover",
       "illustrator",
-      "cover"
-    ];
-  auto pointer_head_sub_title =
-    [
-      "main",
-      "sub",
-      "full",
-      "language",
-      "edition",
-      "note"
-    ];
-  auto pointer_head_sub_rights =
-    [
-      "copyright",
-      "illustrations",
-      "license"
+      "translator"
     ];
   auto pointer_head_sub_date =
     [
-      "published",
+      "added_to_site",
+      "available",
       "created",
       "issued",
-      "valid",
       "modified",
-      "added_to_site"
-    ];
-  auto pointer_head_sub_original =
-    [
-      "title",
-      "language",
-      "source"
-    ];
-  auto pointer_head_sub_classify =
-    [
-      "topic_register",
-      "subject",
-      "keywords",
-      "loc",
-      "dewey"
+      "published",
+      "valid"
     ];
   auto pointer_head_sub_identifier =
     [
+      "isbn",
       "oclc",
-      "pg",
-      "isbn"
-    ];
-  auto pointer_head_sub_notes =
-    [
-      "abstract",
-      "description"
+      "pg"
     ];
-  auto pointer_head_sub_publisher =
-    [ "name" ];
+  /+ make +/
   auto pointer_head_sub_make =
     [
       "cover_image",
@@ -162,9 +139,112 @@ template SiSUheaderSkel() {
       "texpdf_font",
       "css"
     ];
+  auto pointer_head_sub_notes =
+    [
+      "abstract",
+      "description"
+    ];
+  auto pointer_head_sub_original =
+    [
+      "language",
+      "source",
+      "title"
+    ];
+  auto pointer_head_sub_publisher =
+    [ "name" ];
+  auto pointer_head_sub_rights =
+    [
+      "copyright",
+      "cover",
+      "illustrations",
+      "license"
+    ];
+  auto pointer_head_sub_title =
+    [
+      "edition",
+      "full",
+      "language",
+      "main",
+      "note",
+      "sub"
+    ];
   auto config_jsonstr = `{
   }`;
 }
+/+
+/+
+  unify internal representation of header info for native & sdlang document headers
+  represent either using struct, hashes or possibly json
+  sdp internal representation should be identical for native & sdlang variants
++/
+header.
+  ├── make                         // make instructions
+  │   ├── bold
+  │   ├── breaks
+  │   ├── cover_image
+  │   ├── css
+  │   ├── emphasis
+  │   ├── footer
+  │   ├── headings
+  │   ├── home_button_image
+  │   ├── home_button_text
+  │   ├── italics
+  │   ├── num_top
+  │   ├── substitute
+  │   └── texpdf_font
+  └── meta                         // metadata
+     ├── author                    // move author to creator:author
+     ├── classify
+     │   ├── dewey
+     │   ├── keyword
+     │   ├── loc
+     │   ├── subject
+     │   └── topic_register
+     ├── creator
+     │   ├── author
+     │   │     ├── [ [first_name: x0, last_name: y0], [first_name: x1, last_name: y1] ]
+     │   │     └── [ full_name0, full_name1 ]
+     │   ├── author_email
+     │   ├── illustrator
+     │   └── translator
+     ├── date
+     │   ├── added_to_site
+     │   ├── available
+     │   ├── created
+     │   ├── issued
+     │   ├── modified
+     │   ├── published
+     │   └── valid
+     ├── identifier
+     │   ├── isbn
+     │   ├── oclc
+     │   └── pg
+     ├── links
+     ├── notes
+     │   ├── abstract
+     │   └── description
+     ├── original
+     │   ├── language
+     │   ├── source
+     │   └── title
+     ├── publisher
+     │   └── name
+     ├── rights
+     │   ├── copyright
+     │   ├── cover
+     │   ├── illustrations
+     │   └── license
+     └── title                    // move title: to title:main
+         ├── edition
+         ├── [ full (main + sub) ]
+         ├── language
+         ├── main
+         ├── note
+         ├── sub
+         └── subtitle              // move title:subtitle to title:sub
+
+61 leaves
++/
 /+ regex flags +/
 template SiSUrgxInitFlags() {
   int[string] flags_type_init() {
@@ -203,6 +283,7 @@ template SiSUrgxInitFlags() {
   }
 }
 template SiSUbiblio() {
+  // required: deemed_author (author || editor); year; fulltitle;
   auto biblio_entry_tags_jsonstr =  `{
     "is"                   : "",
     "sortby_deemed_author_year_title"  : "",
diff --git a/src/sdp/ao_header_extract.d b/src/sdp/ao_header_extract.d
new file mode 100644
index 0000000..c02bc7c
--- /dev/null
+++ b/src/sdp/ao_header_extract.d
@@ -0,0 +1,1307 @@
+/+
+  extract sdl header return sdl
++/
+template SiSUheaderExtractSDLang() {
+  private import
+    std.regex;
+  private import
+    ao_rgx;
+  struct HeaderExtractSDL {
+    mixin RgxInit;
+    auto rgx = Rgx();
+    final private auto headerMakeSDLang(in string src_header) {
+      scope(failure) {
+        stderr.writefln(
+          "%s\n%s\n%s:%s failed here:\n  src_header: %s",
+          __MODULE__, __FUNCTION__,
+          __FILE__, __LINE__,
+          src_header,
+        );
+      }
+      Tag sdl_root_header;
+      try {
+        sdl_root_header = parseSource(src_header);
+      }
+      catch(SDLangParseException e) {
+        stderr.writeln("SDLang problem with this document header:");
+        stderr.writeln(src_header);
+        // Error messages of the form:
+        // myFile.sdl(5:28): Error: Invalid integer suffix.
+        stderr.writeln(e.msg);
+      }
+      debug(sdlang) {
+        writeln("header SDL:");
+        writeln(sdl_root_header.toSDLDocument());
+      }
+      return sdl_root_header;
+    }
+    private auto headerSDLangToJSON(in char[] src_header) {
+      char[][] source_header_arr =
+        split(cast(char[]) src_header, rgx.line_delimiter);
+      char[] header_clean;
+      // TODO
+      foreach(header_line; source_header_arr) {
+        if (!match(header_line, rgx.comments)) {
+          header_clean ~= header_line ~ "\n";
+          // writeln(header_line);
+        }
+      }
+      /+ get sdlang tags +/
+      auto header_sdlang=headerMakeSDLang(to!string(header_clean));
+      debug(sdlang) {
+        writeln("--------------");
+        stdout.rawWrite( header_sdlang.toSDLDocument() );
+        writeln("--------------");
+        Value test = header_sdlang.tags["title"][0].values[0];
+        assert(test == typeid(string));
+        writeln(header_sdlang.maybe.tags["title"]);
+        writeln(header_sdlang.maybe.tags["title"][0].maybe.attributes["subtitle"]);
+      }
+      /+ TODO separate modules? sdlang then json
+      return header_sdlang;
+      // then do json module?
+      +/
+      /+ TODO json next +/
+      /+ TODO
+        auto dochead_make = parseJSON(header_make_jsonstr).object;
+        auto dochead_meta = parseJSON(header_meta_jsonstr).object;
+        auto hm = to!string(t.captures[1]);
+        auto hs = to!string(s.captures[1]);
+        if (dochead_make[hm][hs].type() == JSON_TYPE.STRING) {
+          dochead_make[hm][hs].str = to!string(s.captures[2]);
+        }
+        if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+          dochead_meta[hm][hs].str = to!string(s.captures[2]);
+        }
+      +/
+      /+ dochead +/
+      string hm;
+      string hs;
+      /+ make +/
+      auto dochead_make = parseJSON(header_make_jsonstr).object;
+      if (!(header_sdlang.maybe.tags["make"].empty)) {
+        hm = "make";
+        hs = "bold";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "breaks";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "cover_image";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "css";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "emphasis";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "footer";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "headings";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "home_button_image";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "home_button_text";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "italics";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "num_top";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "substitute";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "texpdf_font";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_make[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+      }
+      /+ meta +/
+      auto dochead_meta = parseJSON(header_meta_jsonstr).object;
+      hm = "title";
+      if (!(header_sdlang.maybe.tags[hm].empty)) {
+        /+ TODO Title REQUIRED +/
+        hs = "main";
+        if (!(header_sdlang.tags[hm].empty)
+        && (header_sdlang.tags[hm][0].values[0].length > 1)) {
+          writeln(header_sdlang.tags[hm][0].values[0]);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].values[0]);
+            // to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        } else if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        } else {
+          writeln("Required header metadata Title, missing");
+        }
+        hs = "sub";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        } else if (!(header_sdlang.tags[hm][0].maybe.attributes["subtitle"].empty)
+        && (header_sdlang.tags[hm][0].attributes["subtitle"][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes["subtitle"][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes["subtitle"][0].value);
+        }
+        // full title composite (main + sub)
+        // hs = "full";
+        // dochead_meta[hm][hs] = dochead_meta[hm]["main"] ~ dochead_meta[hm]["sub"];
+        hs = "language";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes["lang"].empty)
+        && (header_sdlang.tags[hm][0].attributes["lang"][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes["lang"][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes["lang"][0].value);
+        } else if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "edition";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "note";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+      }
+      hm = "creator";
+      if (!(header_sdlang.maybe.tags[hm].empty)) {
+        /+ Creator / Author REQUIRED +/
+        /+ TODO
+        - decide on representation for & deal with multiple authors;
+        - author(s) full name;
+        - author(s) surname & other parts
+        +/
+        hs = "author";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "author_email";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "illustrator";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "translator";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+      }
+      hm = "classify";
+      if (!(header_sdlang.maybe.tags[hm].empty)) {
+        hs = "dewey";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "keywords";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "loc";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "subject";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "topic_register";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+      }
+      hm = "date";
+      if (!(header_sdlang.maybe.tags[hm].empty)) {
+        hs = "added_to_site";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "available";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "created";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "issued";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "modified";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "published";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "valid";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+      }
+      hm = "identifier";
+      if (!(header_sdlang.maybe.tags[hm].empty)) {
+        hs = "isbn";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "oclc";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "pg";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+      }
+      hm = "links";
+      if (!(header_sdlang.maybe.tags[hm].empty)) {
+        /+ TODO
+          stuff to fix
+        +/
+        // hs = "link";
+        // if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        // && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+        //   writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        //   dochead_meta[hm][hs].str =
+        //     to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        // }
+      }
+      hm = "notes";
+      if (!(header_sdlang.maybe.tags[hm].empty)) {
+        hs = "abstract";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "description";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+      }
+      hm = "original";
+      if (!(header_sdlang.maybe.tags[hm].empty)) {
+        hs = "language";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "source";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "title";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+      }
+      hm = "publisher";
+      if (!(header_sdlang.maybe.tags[hm].empty)) {
+        hs = "name";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+      }
+      hm = "rights";
+      if (!(header_sdlang.maybe.tags[hm].empty)) {
+        hs = "copyright";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "cover";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "illustrations";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+        hs = "license";
+        if (!(header_sdlang.tags[hm][0].maybe.attributes[hs].empty)
+        && (header_sdlang.tags[hm][0].attributes[hs][0].value.length > 1)) {
+          writeln(header_sdlang.tags[hm][0].attributes[hs][0].value);
+          dochead_meta[hm][hs].str =
+            to!string(header_sdlang.tags[hm][0].attributes[hs][0].value);
+        }
+      }
+      // writeln(dochead_make);
+      // writeln(dochead_meta);
+      auto t = tuple(dochead_make, dochead_meta);
+      static assert(!isTypeTuple!(t));
+      return t;
+    }
+    private auto headerSDLangToHash(in char[] src_header) {
+      char[][] source_header_arr =
+        split(cast(char[]) src_header, rgx.line_delimiter);
+      char[] header_clean;
+      string[string] header_make;
+      string[string][string] header_metadata;
+      foreach(header_line; source_header_arr) {
+        if (!match(header_line, rgx.comments)) {
+          header_clean ~= header_line ~ "\n";
+          // writeln(header_line);
+        }
+      }
+      /+ get sdlang tags +/
+      auto header_sdlang=headerMakeSDLang(to!string(header_clean));
+      Value test = header_sdlang.tags["title"][0].values[0];
+      // assert(test == typeid(string));
+      // writeln(header_sdlang.maybe.tags["title"]);
+      // writeln(header_sdlang.maybe.tags["title"][0].attributes["subtitle"]);
+      if (!(header_sdlang.maybe.tags["make"].empty)) {
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["bold"].empty)
+        && (header_sdlang.tags["make"][0].attributes["bold"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["bold"][0].value);
+          header_make["bold"] =
+            to!string(header_sdlang.tags["make"][0].attributes["bold"][0].value);
+        } else {
+          header_make["bold"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["breaks"].empty)
+        && (header_sdlang.tags["make"][0].attributes["breaks"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["breaks"][0].value);
+          header_make["breaks"] =
+            to!string(header_sdlang.tags["make"][0].attributes["breaks"][0].value);
+        } else {
+          header_make["breaks"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["cover_image"].empty)
+        && (header_sdlang.tags["make"][0].attributes["cover_image"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["cover_image"][0].value);
+          header_make["cover_image"] =
+            to!string(header_sdlang.tags["make"][0].attributes["cover_image"][0].value);
+        } else {
+          header_make["cover_image"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["css"].empty)
+        && (header_sdlang.tags["make"][0].attributes["css"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["css"][0].value);
+          header_make["css"] =
+            to!string(header_sdlang.tags["make"][0].attributes["css"][0].value);
+        } else {
+          header_make["css"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["emphasis"].empty)
+        && (header_sdlang.tags["make"][0].attributes["emphasis"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["emphasis"][0].value);
+          header_make["emphasis"] =
+            to!string(header_sdlang.tags["make"][0].attributes["emphasis"][0].value);
+        } else {
+          header_make["emphasis"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["footer"].empty)
+        && (header_sdlang.tags["make"][0].attributes["footer"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["footer"][0].value);
+          header_make["footer"] =
+            to!string(header_sdlang.tags["make"][0].attributes["footer"][0].value);
+        } else {
+          header_make["footer"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["headings"].empty)
+        && (header_sdlang.tags["make"][0].attributes["headings"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["headings"][0].value);
+          header_make["headings"] =
+            to!string(header_sdlang.tags["make"][0].attributes["headings"][0].value);
+        } else {
+          header_make["headings"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["home_button_image"].empty)
+        && (header_sdlang.tags["make"][0].attributes["home_button_image"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["home_button_image"][0].value);
+          header_make["home_button_image"] =
+            to!string(header_sdlang.tags["make"][0].attributes["home_button_image"][0].value);
+        } else {
+          header_make["home_button_image"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["home_button_text"].empty)
+        && (header_sdlang.tags["make"][0].attributes["home_button_text"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["home_button_text"][0].value);
+          header_make["home_button_text"] =
+            to!string(header_sdlang.tags["make"][0].attributes["home_button_text"][0].value);
+        } else {
+          header_make["home_button_text"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["italics"].empty)
+        && (header_sdlang.tags["make"][0].attributes["italics"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["italics"][0].value);
+          header_make["italics"] =
+            to!string(header_sdlang.tags["make"][0].attributes["italics"][0].value);
+        } else {
+          header_make["italics"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["num_top"].empty)
+        && (header_sdlang.tags["make"][0].attributes["num_top"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["num_top"][0].value);
+          header_make["num_top"] =
+            to!string(header_sdlang.tags["make"][0].attributes["num_top"][0].value);
+        } else {
+          header_make["num_top"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["substitute"].empty)
+        && (header_sdlang.tags["make"][0].attributes["substitute"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["substitute"][0].value);
+          header_make["substitute"] =
+            to!string(header_sdlang.tags["make"][0].attributes["substitute"][0].value);
+        } else {
+          header_make["substitute"] = "";
+        }
+        if (!(header_sdlang.tags["make"][0].maybe.attributes["texpdf_font"].empty)
+        && (header_sdlang.tags["make"][0].attributes["texpdf_font"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["make"][0].attributes["texpdf_font"][0].value);
+          header_make["texpdf_font"] =
+            to!string(header_sdlang.tags["make"][0].attributes["texpdf_font"][0].value);
+        } else {
+          header_make["texpdf_font"] = "";
+        }
+      }
+      if (!(header_sdlang.maybe.tags["title"].empty)) {
+        /+ Title REQUIRED +/
+        if (!(header_sdlang.tags["title"].empty)
+        && (header_sdlang.tags["title"][0].values[0].length > 1)) {
+          writeln(header_sdlang.tags["title"][0].values[0]);
+          header_metadata["title"]["main"] =
+            to!string(header_sdlang.tags["title"][0].values[0]);
+        } else if (!(header_sdlang.tags["title"][0].maybe.attributes["main"].empty)
+        && (header_sdlang.tags["title"][0].attributes["main"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["title"][0].attributes["main"][0].value);
+          header_metadata["title"]["main"] =
+            to!string(header_sdlang.tags["title"][0].attributes["main"][0].value);
+        } else {
+          writeln("Required header metadata Title, missing");
+          header_metadata["title"]["main"] = "";
+        }
+        if (!(header_sdlang.tags["title"][0].maybe.attributes["sub"].empty)
+        && (header_sdlang.tags["title"][0].attributes["sub"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["title"][0].attributes["sub"][0].value);
+          header_metadata["title"]["sub"] =
+            to!string(header_sdlang.tags["title"][0].attributes["sub"][0].value);
+        } else if (!(header_sdlang.tags["title"][0].maybe.attributes["subtitle"].empty)
+        && (header_sdlang.tags["title"][0].attributes["subtitle"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["title"][0].attributes["subtitle"][0].value);
+          header_metadata["title"]["sub"] =
+            to!string(header_sdlang.tags["title"][0].attributes["subtitle"][0].value);
+        } else {
+          header_metadata["title"]["sub"] = "";
+        }
+        // full title composite (main + sub)
+        header_metadata["title"]["full"] = header_metadata["title"]["main"] ~ header_metadata["title"]["sub"];
+        if (!(header_sdlang.tags["title"][0].maybe.attributes["lang"].empty)
+        && (header_sdlang.tags["title"][0].attributes["lang"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["title"][0].attributes["lang"][0].value);
+          header_metadata["title"]["language"] =
+            to!string(header_sdlang.tags["title"][0].attributes["lang"][0].value);
+        } else if (!(header_sdlang.tags["title"][0].maybe.attributes["language"].empty)
+        && (header_sdlang.tags["title"][0].attributes["language"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["title"][0].attributes["language"][0].value);
+          header_metadata["title"]["language"] =
+            to!string(header_sdlang.tags["title"][0].attributes["language"][0].value);
+        } else {
+          header_metadata["title"]["language"] = "";
+        }
+        if (!(header_sdlang.tags["title"][0].maybe.attributes["edition"].empty)
+        && (header_sdlang.tags["title"][0].attributes["edition"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["title"][0].attributes["edition"][0].value);
+          header_metadata["title"]["edition"] =
+            to!string(header_sdlang.tags["title"][0].attributes["edition"][0].value);
+        } else {
+          header_metadata["title"]["edition"] = "";
+        }
+        if (!(header_sdlang.tags["title"][0].maybe.attributes["note"].empty)
+        && (header_sdlang.tags["title"][0].attributes["note"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["title"][0].attributes["note"][0].value);
+          header_metadata["title"]["note"] =
+            to!string(header_sdlang.tags["title"][0].attributes["note"][0].value);
+        } else {
+          header_metadata["title"]["note"] = "";
+        }
+      }
+      if (!(header_sdlang.maybe.tags["creator"].empty)) {
+        /+ Creator / Author REQUIRED +/
+        /+ TODO
+        - decide on representation for & deal with multiple authors;
+        - author(s) full name;
+        - author(s) surname & other parts
+        +/
+        if (!(header_sdlang.tags["creator"][0].maybe.attributes["author"].empty)
+        && (header_sdlang.tags["creator"][0].attributes["author"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["creator"][0].attributes["author"][0].value);
+          header_metadata["creator"]["author"] =
+            to!string(header_sdlang.tags["creator"][0].attributes["author"][0].value);
+        } else {
+          header_metadata["creator"]["author"] = "";
+        }
+        if (!(header_sdlang.tags["creator"][0].maybe.attributes["author_email"].empty)
+        && (header_sdlang.tags["creator"][0].attributes["author_email"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["creator"][0].attributes["author_email"][0].value);
+          header_metadata["creator"]["author_email"] =
+            to!string(header_sdlang.tags["creator"][0].attributes["author_email"][0].value);
+        } else {
+          header_metadata["creator"]["author_email"] = "";
+        }
+        if (!(header_sdlang.tags["creator"][0].maybe.attributes["illustrator"].empty)
+        && (header_sdlang.tags["creator"][0].attributes["illustrator"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["creator"][0].attributes["illustrator"][0].value);
+          header_metadata["creator"][""] =
+            to!string(header_sdlang.tags["creator"][0].attributes["illustrator"][0].value);
+        } else {
+          header_metadata["creator"]["illustrator"] = "";
+        }
+        if (!(header_sdlang.tags["creator"][0].maybe.attributes["translator"].empty)
+        && (header_sdlang.tags["creator"][0].attributes["translator"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["creator"][0].attributes["translator"][0].value);
+          header_metadata["creator"]["translator"] =
+            to!string(header_sdlang.tags["creator"][0].attributes["translator"][0].value);
+        } else {
+          header_metadata["creator"][""] = "";
+        }
+      }
+      if (!(header_sdlang.maybe.tags["classify"].empty)) {
+        if (!(header_sdlang.tags["classify"][0].maybe.attributes["dewey"].empty)
+        && (header_sdlang.tags["classify"][0].attributes["dewey"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["classify"][0].attributes["dewey"][0].value);
+          header_metadata["classify"]["dewey"] =
+            to!string(header_sdlang.tags["classify"][0].attributes["dewey"][0].value);
+        } else {
+          header_metadata["classify"]["dewey"] = "";
+        }
+        if (!(header_sdlang.tags["classify"][0].maybe.attributes["keyword"].empty)
+        && (header_sdlang.tags["classify"][0].attributes["keyword"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["classify"][0].attributes["keyword"][0].value);
+          header_metadata["classify"]["keyword"] =
+            to!string(header_sdlang.tags["classify"][0].attributes["keyword"][0].value);
+        } else {
+          header_metadata["classify"]["keyword"] = "";
+        }
+        if (!(header_sdlang.tags["classify"][0].maybe.attributes["loc"].empty)
+        && (header_sdlang.tags["classify"][0].attributes["loc"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["classify"][0].attributes["loc"][0].value);
+          header_metadata["classify"]["loc"] =
+            to!string(header_sdlang.tags["classify"][0].attributes["loc"][0].value);
+        } else {
+          header_metadata["classify"]["loc"] = "";
+        }
+        if (!(header_sdlang.tags["classify"][0].maybe.attributes["subject"].empty)
+        && (header_sdlang.tags["classify"][0].attributes["subject"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["classify"][0].attributes["subject"][0].value);
+          header_metadata["classify"]["subject"] =
+            to!string(header_sdlang.tags["classify"][0].attributes["subject"][0].value);
+        } else {
+          header_metadata["classify"]["subject"] = "";
+        }
+        if (!(header_sdlang.tags["classify"][0].maybe.attributes["topic_register"].empty)
+        && (header_sdlang.tags["classify"][0].attributes["topic_register"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["classify"][0].attributes["topic_register"][0].value);
+          header_metadata["classify"]["topic_register"] =
+            to!string(header_sdlang.tags["classify"][0].attributes["topic_register"][0].value);
+        } else {
+          header_metadata["classify"]["topic_register"] = "";
+        }
+      }
+      if (!(header_sdlang.maybe.tags["date"].empty)) {
+        if (!(header_sdlang.tags["date"][0].maybe.attributes["added_to_site"].empty)
+        && (header_sdlang.tags["date"][0].attributes["added_to_site"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["date"][0].attributes["added_to_site"][0].value);
+          header_metadata["date"]["added_to_site"] =
+            to!string(header_sdlang.tags["date"][0].attributes["added_to_site"][0].value);
+        } else {
+          header_metadata["date"]["added_to_site"] = "";
+        }
+        if (!(header_sdlang.tags["date"][0].maybe.attributes["available"].empty)
+        && (header_sdlang.tags["date"][0].attributes["available"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["date"][0].attributes["available"][0].value);
+          header_metadata["date"]["available"] =
+            to!string(header_sdlang.tags["date"][0].attributes["available"][0].value);
+        } else {
+          header_metadata["date"]["available"] = "";
+        }
+        if (!(header_sdlang.tags["date"][0].maybe.attributes["created"].empty)
+        && (header_sdlang.tags["date"][0].attributes["created"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["date"][0].attributes["created"][0].value);
+          header_metadata["date"]["created"] =
+            to!string(header_sdlang.tags["date"][0].attributes["created"][0].value);
+        } else {
+          header_metadata["date"]["created"] = "";
+        }
+        if (!(header_sdlang.tags["date"][0].maybe.attributes["issued"].empty)
+        && (header_sdlang.tags["date"][0].attributes["issued"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["date"][0].attributes["issued"][0].value);
+          header_metadata["date"]["issued"] =
+            to!string(header_sdlang.tags["date"][0].attributes["issued"][0].value);
+        } else {
+          header_metadata["date"]["issued"] = "";
+        }
+        if (!(header_sdlang.tags["date"][0].maybe.attributes["modified"].empty)
+        && (header_sdlang.tags["date"][0].attributes["modified"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["date"][0].attributes["modified"][0].value);
+          header_metadata["date"]["modified"] =
+            to!string(header_sdlang.tags["date"][0].attributes["modified"][0].value);
+        } else {
+          header_metadata["date"]["modified"] = "";
+        }
+        if (!(header_sdlang.tags["date"][0].maybe.attributes["published"].empty)
+        && (header_sdlang.tags["date"][0].attributes["published"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["date"][0].attributes["published"][0].value);
+          header_metadata["date"]["published"] =
+            to!string(header_sdlang.tags["date"][0].attributes["published"][0].value);
+        } else {
+          header_metadata["date"]["published"] = "";
+        }
+        if (!(header_sdlang.tags["date"][0].maybe.attributes["valid"].empty)
+        && (header_sdlang.tags["date"][0].attributes["valid"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["date"][0].attributes["valid"][0].value);
+          header_metadata["date"]["valid"] =
+            to!string(header_sdlang.tags["date"][0].attributes["valid"][0].value);
+        } else {
+          header_metadata["date"]["valid"] = "";
+        }
+      }
+      if (!(header_sdlang.maybe.tags["identifier"].empty)) {
+        if (!(header_sdlang.tags["identifier"][0].maybe.attributes["isbn"].empty)
+        && (header_sdlang.tags["identifier"][0].attributes["isbn"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["identifier"][0].attributes["isbn"][0].value);
+          header_metadata["identifier"]["isbn"] =
+            to!string(header_sdlang.tags["identifier"][0].attributes["isbn"][0].value);
+        } else {
+          header_metadata["identifier"]["isbn"] = "";
+        }
+        if (!(header_sdlang.tags["identifier"][0].maybe.attributes["oclc"].empty)
+        && (header_sdlang.tags["identifier"][0].attributes["oclc"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["identifier"][0].attributes["oclc"][0].value);
+          header_metadata["identifier"]["oclc"] =
+            to!string(header_sdlang.tags["identifier"][0].attributes["oclc"][0].value);
+        } else {
+          header_metadata["identifier"]["oclc"] = "";
+        }
+        if (!(header_sdlang.tags["identifier"][0].maybe.attributes["pg"].empty)
+        && (header_sdlang.tags["identifier"][0].attributes["pg"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["identifier"][0].attributes["pg"][0].value);
+          header_metadata["identifier"]["pg"] =
+            to!string(header_sdlang.tags["identifier"][0].attributes["pg"][0].value);
+        } else {
+          header_metadata["identifier"]["pg"] = "";
+        }
+      }
+      if (!(header_sdlang.maybe.tags["links"].empty)) {
+        /+ TODO
+          stuff to fix
+        +/
+        if (!(header_sdlang.tags["links"][0].maybe.attributes["link"].empty)
+        && (header_sdlang.tags["links"][0].attributes["link"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["links"][0].attributes["link"][0].value);
+          // header_metadata["links"]["list"] =
+          //   to!string(header_sdlang.tags["links"][0].attributes["link"][0].value);
+          header_metadata["links"]["list"] = "";
+        } else {
+          header_metadata["links"]["list"] = "";
+        }
+      }
+      if (!(header_sdlang.maybe.tags["notes"].empty)) {
+        if (!(header_sdlang.tags["notes"][0].maybe.attributes["abstract"].empty)
+        && (header_sdlang.tags["notes"][0].attributes["abstract"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["notes"][0].attributes["abstract"][0].value);
+          header_metadata["notes"]["abstract"] =
+            to!string(header_sdlang.tags["notes"][0].attributes["abstract"][0].value);
+        } else {
+          header_metadata["notes"]["abstract"] = "";
+        }
+        if (!(header_sdlang.tags["notes"][0].maybe.attributes["description"].empty)
+        && (header_sdlang.tags["notes"][0].attributes["description"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["notes"][0].attributes["description"][0].value);
+          header_metadata["notes"]["description"] =
+            to!string(header_sdlang.tags["notes"][0].attributes["description"][0].value);
+        } else {
+          header_metadata["notes"]["description"] = "";
+        }
+      }
+      if (!(header_sdlang.maybe.tags["original"].empty)) {
+        if (!(header_sdlang.tags["original"][0].maybe.attributes["language"].empty)
+        && (header_sdlang.tags["original"][0].attributes["language"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["original"][0].attributes["language"][0].value);
+          header_metadata["original"]["language"] =
+            to!string(header_sdlang.tags["original"][0].attributes["language"][0].value);
+        } else {
+          header_metadata["original"]["language"] = "";
+        }
+        if (!(header_sdlang.tags["original"][0].maybe.attributes["source"].empty)
+        && (header_sdlang.tags["original"][0].attributes["source"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["original"][0].attributes["source"][0].value);
+          header_metadata["original"]["source"] =
+            to!string(header_sdlang.tags["original"][0].attributes["source"][0].value);
+        } else {
+          header_metadata["original"]["source"] = "";
+        }
+        if (!(header_sdlang.tags["original"][0].maybe.attributes["title"].empty)
+        && (header_sdlang.tags["original"][0].attributes["title"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["original"][0].attributes["title"][0].value);
+          header_metadata["original"]["title"] =
+            to!string(header_sdlang.tags["original"][0].attributes["title"][0].value);
+        } else {
+          header_metadata["original"]["title"] = "";
+        }
+      }
+      if (!(header_sdlang.maybe.tags["publisher"].empty)) {
+        if (!(header_sdlang.tags["publisher"][0].maybe.attributes["name"].empty)
+        && (header_sdlang.tags["publisher"][0].attributes["name"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["publisher"][0].attributes["name"][0].value);
+          header_metadata["publisher"]["name"] =
+            to!string(header_sdlang.tags["publisher"][0].attributes["name"][0].value);
+        } else {
+          header_metadata["publisher"]["name"] = "";
+        }
+      }
+      if (!(header_sdlang.maybe.tags["rights"].empty)) {
+        if (!(header_sdlang.tags["rights"][0].maybe.attributes["copyright"].empty)
+        && (header_sdlang.tags["rights"][0].attributes["copyright"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["rights"][0].attributes["copyright"][0].value);
+          header_metadata["rights"]["copyright"] =
+            to!string(header_sdlang.tags["rights"][0].attributes["copyright"][0].value);
+        } else {
+          header_metadata["rights"]["copyright"] = "";
+        }
+        if (!(header_sdlang.tags["rights"][0].maybe.attributes["cover"].empty)
+        && (header_sdlang.tags["rights"][0].attributes["cover"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["rights"][0].attributes["cover"][0].value);
+          header_metadata["rights"]["cover"] =
+            to!string(header_sdlang.tags["rights"][0].attributes["cover"][0].value);
+        } else {
+          header_metadata["rights"]["cover"] = "";
+        }
+        if (!(header_sdlang.tags["rights"][0].maybe.attributes["illustrations"].empty)
+        && (header_sdlang.tags["rights"][0].attributes["illustrations"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["rights"][0].attributes["illustrations"][0].value);
+          header_metadata["rights"]["illustrations"] =
+            to!string(header_sdlang.tags["rights"][0].attributes["illustrations"][0].value);
+        } else {
+          header_metadata["rights"]["illustrations"] = "";
+        }
+        if (!(header_sdlang.tags["rights"][0].maybe.attributes["license"].empty)
+        && (header_sdlang.tags["rights"][0].attributes["license"][0].value.length > 1)) {
+          writeln(header_sdlang.tags["rights"][0].attributes["license"][0].value);
+          header_metadata["rights"]["license"] =
+            to!string(header_sdlang.tags["rights"][0].attributes["license"][0].value);
+        } else {
+          header_metadata["rights"]["license"] = "";
+        }
+      }
+      writeln("--------------");
+      stdout.rawWrite( header_sdlang.toSDLDocument() );
+      writeln("--------------");
+      /+
+      namespace:name values attributes {
+        children
+      }
+      +/
+      return header_sdlang;
+    }
+    private auto headerSDLang(in char[] src_header) {
+      char[][] source_header_arr =
+        split(cast(char[]) src_header, rgx.line_delimiter);
+      char[] header_clean;
+      foreach(header_line; source_header_arr) {
+        if (!match(header_line, rgx.comments)) {
+          header_clean ~= header_line ~ "\n";
+          // writeln(header_line);
+        }
+      }
+      // writeln(header_clean); // consider
+      auto header_sdlang=headerMakeSDLang(to!string(header_clean));
+      return header_sdlang;
+    }
+    
+  }
+  struct HeaderUseSDL {
+    mixin RgxInit;
+    auto rgx = Rgx();
+    // Tag = sdl_header;
+    auto headerUseSDLang(T)(auto T sdl_root_header) {
+    // T sdl_root_header;
+    // auto headerUseSDLang(Tag sdl_root_header) {
+    // private auto headerUseSDLang(Tag sdl_root_header) {
+    // private auto headerUseSDLang(in Tag sdl_root_header) {
+      // auto sdl_root_header = T;
+
+  // Value is a std.variant.Algebraic
+  Value test = sdl_root_header.tags["title"][0].values[0];
+  // assert(test == typeid(string));
+  writeln(test);
+
+      return sdl_root_header;
+    }
+  }
+}
+/+
+  extract native/orig header return json
++/
+template SiSUheaderExtractNative() {
+  private import
+    std.exception,
+    std.regex,
+    std.utf,
+    std.conv : to;
+  private import
+    ao_rgx;
+  struct HeaderDocMetadataAndMakeNativeToJson {
+    mixin SiSUrgxInitFlags;
+    mixin RgxInit;
+    auto rgx = Rgx();
+    enum State { off, on }
+    string hm, hs;
+    auto header_metadata_and_make_jsonstr(
+      string header,
+      JSONValue[string] dochead_meta,
+      JSONValue[string] dochead_make
+    )
+    in { }
+    body {
+      scope(exit) {
+        destroy(header);
+        destroy(dochead_meta);
+        destroy(dochead_make);
+      }
+      if (auto t = match(header, rgx.native_header_main)) {
+        char[][] header_obj_spl = split(
+          cast(char[]) header,
+          rgx.line_delimiter_ws_strip
+        );
+        auto hm = to!string(t.captures[1]);
+        if (match(hm, rgx.main_headers)) {
+          foreach (line; header_obj_spl) {
+            if (auto m = match(line, rgx.native_header_main)) {
+              if (!empty(m.captures[2])) {
+                if (hm == "creator") {
+                  dochead_meta[hm]["author"].str =
+                    to!string(m.captures[2]);
+                } else if (hm == "title") {
+                  dochead_meta[hm]["main"].str =
+                    to!string(m.captures[2]);
+                } else if (hm == "publisher") {
+                  dochead_meta[hm]["name"].str =
+                    to!string(m.captures[2]);
+                }
+              }
+            } else if (auto s = match(line, rgx.native_header_sub)) {
+              if (!empty(s.captures[2])) {
+                auto hs = to!string(s.captures[1]);
+                if ((hm == "make" )
+                && (dochead_make[hm].type() == JSON_TYPE.OBJECT)) {
+                  switch (hm) {
+                  case "make":
+                    if (match(hs, rgx.native_subhead_make)) {
+                      if (dochead_make[hm][hs].type() == JSON_TYPE.STRING) {
+                        dochead_make[hm][hs].str = to!string(s.captures[2]);
+                      }
+                    } else {
+                      writeln("not a valid header type:", hm, ":", hs);
+                      destroy(hm);
+                      destroy(hs);
+                    }
+                    break;
+                  default:
+                    break;
+                  }
+                } else if (dochead_meta[hm].type() == JSON_TYPE.OBJECT) {
+                  switch (hm) {
+                  case "creator":
+                    if (match(hs, rgx.native_subhead_creator)) {
+                      if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+                        dochead_meta[hm][hs].str =
+                          to!string(s.captures[2]);
+                      }
+                    } else {
+                      writeln("not a valid header type:", hm, ":", hs);
+                      destroy(hm);
+                      destroy(hs);
+                    }
+                    break;
+                  case "title":
+                    if (match(hs, rgx.native_subhead_title)) {
+                      if ((hs == "subtitle")
+                      && (dochead_meta[hm]["sub"].type() == JSON_TYPE.STRING)) {
+                        dochead_meta[hm]["sub"].str =
+                          to!string(s.captures[2]);
+                      } else if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+                        dochead_meta[hm][hs].str =
+                          to!string(s.captures[2]);
+                      }
+                    } else {
+                      writeln("not a valid header type:", hm, ":", hs);
+                      destroy(hm);
+                      destroy(hs);
+                    }
+                    break;
+                  case "rights":
+                    if (match(hs, rgx.native_subhead_rights)) {
+                      if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+                        dochead_meta[hm][hs].str =
+                          to!string(s.captures[2]);
+                      }
+                    } else {
+                      writeln("not a valid header type:", hm, ":", hs);
+                      destroy(hm);
+                      destroy(hs);
+                    }
+                    break;
+                  case "date":
+                    if (match(hs, rgx.native_subhead_date)) {
+                      if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+                        dochead_meta[hm][hs].str =
+                          to!string(s.captures[2]);
+                      }
+                    } else {
+                      writeln("not a valid header type:", hm, ":", hs);
+                      destroy(hm);
+                      destroy(hs);
+                    }
+                    break;
+                  case "original":
+                    if (match(hs, rgx.native_subhead_original)) {
+                      if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+                        dochead_meta[hm][hs].str =
+                          to!string(s.captures[2]);
+                      }
+                    } else {
+                      writeln("not a valid header type:", hm, ":", hs);
+                      destroy(hm);
+                      destroy(hs);
+                    }
+                    break;
+                  case "classify":
+                    if (match(hs, rgx.native_subhead_classify)) {
+                      if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+                        dochead_meta[hm][hs].str =
+                          to!string(s.captures[2]);
+                      }
+                    } else {
+                      writeln("not a valid header type:", hm, ":", hs);
+                      destroy(hm);
+                      destroy(hs);
+                    }
+                    break;
+                  case "identifier":
+                    if (match(hs, rgx.native_subhead_identifier)) {
+                      if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+                        dochead_meta[hm][hs].str =
+                          to!string(s.captures[2]);
+                      }
+                    } else {
+                      writeln("not a valid header type:", hm, ":", hs);
+                      destroy(hm);
+                      destroy(hs);
+                    }
+                    break;
+                  case "notes":
+                    if (match(hs, rgx.native_subhead_notes)) {
+                      if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+                        dochead_meta[hm][hs].str =
+                          to!string(s.captures[2]);
+                      }
+                    } else {
+                      writeln("not a valid header type:", hm, ":", hs);
+                      destroy(hm);
+                      destroy(hs);
+                    }
+                    break;
+                  case "publisher":
+                    if (match(hs, rgx.native_subhead_publisher)) {
+                      if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+                        dochead_meta[hm][hs].str =
+                          to!string(s.captures[2]);
+                      }
+                    } else {
+                      writeln("not a valid header type:", hm, ":", hs);
+                      destroy(hm);
+                      destroy(hs);
+                    }
+                    break;
+                  case "links":
+                    destroy(hm);
+                    destroy(hs);
+                    // if (match(hs, rgx.native_subhead_links)) {
+                    //   if (dochead_meta[hm][hs].type() == JSON_TYPE.STRING) {
+                    //     dochead_meta[hm][hs].str = to!string(s.captures[2]);
+                    //   }
+                    // } else {
+                    //   writeln("not a valid header type:", hm, ":", hs);
+                    //   destroy(hm);
+                    //   destroy(hs);
+                    // }
+                    break;
+                  default:
+                    break;
+                  }
+                }
+              }
+            }
+          }
+        } else {
+          writeln("not a valid header type:", hm);
+        }
+      }
+      auto t = tuple(dochead_meta, dochead_make);
+      static assert(!isTypeTuple!(t));
+      return t;
+    }
+    private auto native_header_extract(
+      char[] line,
+      ref int[string] line_occur,
+      ref string[string] an_object,
+      ref int[string] type
+    ) {
+      if (matchFirst(line, rgx.native_header_make)) {   /+ matched header_make +/
+        debug(header1) { /+ writeln(line); +/ }
+        type["header"]      = State.on;
+        type["header_make"] = State.on;
+        type["header_meta"] = State.off;
+        ++line_occur["header_make"];
+        an_object["obj"] ~= line ~= "\n";
+      } else if (matchFirst(line, rgx.native_header)) { /+ matched header_metadata +/
+        /+ (generic header match and not previously caught by header_make) +/
+        debug(header1) { /+ writeln(line); +/ }
+        type["header"]      = State.on;
+        type["header_make"] = State.off;
+        type["header_meta"] = State.on;
+        ++line_occur["header_meta"];
+        an_object["obj"] ~= line ~= "\n";
+      } else if (type["header_make"] == State.on
+      && (line_occur["header_make"] > State.off)) {     /+ header_make flag set +/
+        if (matchFirst(line, rgx.native_header_sub)) {  /+ sub-header +/
+          debug(header1) { /+ writeln(line); +/ }
+          ++line_occur["header_make"];
+          an_object["obj"] ~= line ~= "\n";
+        }
+      } else if (type["header_meta"] == State.on
+      && (line_occur["header_meta"] > State.off)) {     /+ header_metadata flag set +/
+        if (matchFirst(line, rgx.native_header_sub)) {  /+ sub-header +/
+          debug(header1) { /+ writeln(line); +/ }
+          ++line_occur["header_meta"];
+          an_object["obj"] ~= line ~= "\n";
+        }
+      }
+      return an_object;
+    }
+    auto header_reset_states_common(
+      ref int[string] line_occur,
+      ref string[string] an_object,
+      ref int[string] type
+    ) {
+      // line_occur["header"] = State.off;
+      line_occur["header_make"] = State.off;
+      line_occur["header_meta"] = State.off;
+      type["header"] = State.off;
+      // type["header_make"] = State.off;
+      // type["header_meta"] = State.off;
+      an_object.remove("obj");
+      an_object.remove("is");
+      an_object.remove("attrib");
+    }
+    private auto headerContentJSON(in char[] src_header) {
+      auto type = flags_type_init;
+      type = [
+       "header"          : State.off,
+       "header_make"     : State.off,
+       "header_meta"     : State.off,
+      ];
+      string[string] an_object;
+      int[string] line_occur;
+      auto dochead_make = parseJSON(header_make_jsonstr).object;
+      auto dochead_meta = parseJSON(header_meta_jsonstr).object;
+      auto set_header = HeaderDocMetadataAndMakeNativeToJson();
+      char[][] source_header_arr =
+        split(cast(char[]) src_header, rgx.line_delimiter);
+      foreach(header_line; source_header_arr) {
+        if (auto m = matchFirst(header_line, rgx.comment)) {
+          /+ matched comment +/
+          debug(comment) {
+            // tell_l("blue", header_line);
+          }
+          header_reset_states_common(line_occur, an_object, type);
+          // type["header_make"] = State.off;
+          // type["header_meta"] = State.off;
+        } else if ((matchFirst(header_line, rgx.native_header))
+        || (type["header_make"] == State.on
+        && (line_occur["header_make"] > State.off))
+        || (type["header_meta"] == State.on
+        && (line_occur["header_meta"] > State.off))) {
+          if (header_line.length == 0) {
+            /+ header_make instructions (current line empty) +/
+            auto dochead_metadata_and_make =
+              set_header.header_metadata_and_make_jsonstr(strip(an_object["obj"]), dochead_meta, dochead_make);
+            static assert(!isTypeTuple!(dochead_metadata_and_make));
+            dochead_meta = dochead_metadata_and_make[0];
+            dochead_make = dochead_metadata_and_make[1];
+            header_reset_states_common(line_occur, an_object, type);
+            type["header_make"] = State.off;
+            type["header_meta"] = State.off;
+            writeln(dochead_metadata_and_make);
+          } else {
+            an_object = native_header_extract(header_line, line_occur, an_object, type);
+          }
+        } else {
+          // writeln(__LINE__);
+        }
+      }
+      auto t = tuple(
+        dochead_make,
+        dochead_meta,
+      );
+      return t;
+    }
+  }
+}
diff --git a/src/sdp/ao_read_source_files.d b/src/sdp/ao_read_source_files.d
index ef9b8b4..4d766b2 100644
--- a/src/sdp/ao_read_source_files.d
+++ b/src/sdp/ao_read_source_files.d
@@ -36,59 +36,6 @@ template SiSUmarkupRaw() {
     }
   }
   private
-  struct HeaderExtractSDL {
-    final private auto headerMakeSDLang(in string src_header) {
-      scope(failure) {
-        stderr.writefln(
-          "%s\n%s\n%s:%s failed here:\n  src_header: %s",
-          __MODULE__, __FUNCTION__,
-          __FILE__, __LINE__,
-          src_header,
-        );
-      }
-      Tag sdl_root_header;
-      try {
-        sdl_root_header = parseSource(src_header);
-      }
-      catch(SDLangParseException e) {
-        stderr.writeln("SDLang problem with this document header:");
-        stderr.writeln(src_header);
-        // Error messages of the form:
-        // myFile.sdl(5:28): Error: Invalid integer suffix.
-        stderr.writeln(e.msg);
-      }
-      debug(sdlang) {
-        // // Value is a std.variant.Algebraic
-        // Value output_dir_structure_by = sdl_root_header.tags["output_dir_structure_by"][0].values[0];
-        // assert(output_dir_structure_by.type == typeid(string));
-        // writeln(output_dir_structure_by);
-    
-        // Tag person = sdl_root_header.namespaces["myNamespace"].tags["person"][0];
-        // writeln("Name: ", person.attributes["name"][0].value);
-        //
-        // int age = person.tags["age"][0].values[0].get!int();
-        // writeln("Age: ", age);
-    
-        writeln("header SDL:");
-        writeln(sdl_root_header.toSDLDocument());
-      }
-      return sdl_root_header;
-    }
-    private auto headerSDLang(in char[] src_header) {
-      char[][] source_header_arr =
-        split(cast(char[]) src_header, rgx.line_delimiter);
-      char[] header_clean;
-      foreach(header_line; source_header_arr) {
-        if (!match(header_line, rgx.comments)) {
-          header_clean ~= header_line ~ "\n";
-          // writeln(header_line);
-        }
-      }
-      // writeln(header_clean); // consider
-      auto header_sdlang=headerMakeSDLang(to!string(header_clean));
-      return header_sdlang;
-    }
-  }
   struct MarkupRawUnit {
     private import std.file;
     // enum State { off, on }
@@ -205,14 +152,14 @@ template SiSUmarkupRaw() {
           contents_insert ~= line;
         } else if (
           (type1["header_make"] == 1)
-          && matchFirst(line, rgx.header_sub)
+          && matchFirst(line, rgx.native_header_sub)
         ) {
             type1["header_make"] = 1;
             type1["header_meta"] = 0;
             // cont_dynamic_array ~= "% " ~ line;
         } else if (
           (type1["header_meta"] == 1)
-          && matchFirst(line, rgx.header_sub)
+          && matchFirst(line, rgx.native_header_sub)
         ) {
             type1["header_meta"] = 1;
             type1["header_make"] = 0;
diff --git a/src/sdp/ao_rgx.d b/src/sdp/ao_rgx.d
index 1245a71..4e282ee 100644
--- a/src/sdp/ao_rgx.d
+++ b/src/sdp/ao_rgx.d
@@ -32,18 +32,36 @@ template RgxInit() {
     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])$`);
     // static insert_ssi_or_sst_fn      = ctRegex!(`^<<\s*[a-zA-Z0-9._-]+[.]ss[ti]`);
+    // static ssm_fn                    = ctRegex!(`^[a-zA-Z0-9._-]+[.]ssm$`);
+    /+ insert markup file +/
+    // static insert_src_fn_ssi_or_sst  = ctRegex!(`^<<\s*([a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`);
     /+ comments +/
     static comment                   = ctRegex!(`^%+ `);
     static comments                  = ctRegex!(`^%+ |^%+$`);
     /+ header +/
-    static header                    = ctRegex!(`^@([a-z_]+):(?:\s|$)`);
-    static header_make               = ctRegex!(`^@(make):(?:\s|$)`);
-    static header_meta               = ctRegex!(`^@([a-z_]+):(?:\s|$)`);
-    static header_sub                = ctRegex!(`^[ ]+:([a-z_]+):\s`);
-    static head_main                 = ctRegex!(`^@(?P<header>[a-z_]+):\s*(?P<content>.*)`, "m");
-    static head_sub                  = ctRegex!(`^[ ]*:(?P<subheader>[a-z_]+):\s+(?P<content>.+)`, "m");
-    static head_value_title          = ctRegex!(`@title`);
-    static head_value_author         = ctRegex!(`@author`);
+    static main_headers                     =
+      ctRegex!(`^(?:creator|title|rights|date|original|classify|identifier|notes|publisher|make|links)$`, "m");
+    static native_header                    = ctRegex!(`^@([a-z_]+):(?:\s|$)`);
+    static native_header_make               = ctRegex!(`^@(make):(?:\s|$)`);
+    static native_header_meta               =
+      ctRegex!(`^@(?:creator|title|rights|date|original|classify|identifier|notes|publisher|links):(?:\s|$)`);
+    static native_header_main               = ctRegex!(`^@(?P<header>[a-z_]+):\s*(?P<content>.*)`, "m");
+    static native_header_sub                = ctRegex!(`^[ ]*:(?P<subheader>[a-z_]+):\s+(?P<content>.+)`, "m");
+    // static native_header_sub                = ctRegex!(`^[ ]+:([a-z_]+):\s`);
+    static native_header_meta_title         = ctRegex!(`^@title:\s`, "m");
+    static variable_doc_title               = ctRegex!(`@title`);
+    static variable_doc_author              = ctRegex!(`@author`);
+    /+ head +/
+    static native_subhead_creator           = ctRegex!(`^(?:author|translator|illustrator)$`, "m");
+    static native_subhead_title             = ctRegex!(`^(?:main|sub(?:title)?|full|language|edition|note)$`, "m");
+    static native_subhead_rights            = ctRegex!(`^(?:copyright|illustrations|license|cover)$`, "m");
+    static native_subhead_date              = ctRegex!(`^(?:published|created|issued|available|valid|modified|added_to_site)$`, "m");
+    static native_subhead_original          = ctRegex!(`^(?:title|language|source)$`, "m");
+    static native_subhead_classify          = ctRegex!(`^(?:topic_register|subject|keywords|loc|dewey)$`, "m");
+    static native_subhead_identifier        = ctRegex!(`^(?:oclc|pg|isbn)$`, "m");
+    static native_subhead_notes             = ctRegex!(`^(?:abstract|description)$`, "m");
+    static native_subhead_publisher         = ctRegex!(`^(?:name)$`, "m");
+    static native_subhead_make              = ctRegex!(`^(?:cover_image|home_button_image|home_button_text|footer|headings|num_top|breaks|substitute|bold|italics|emphasis|texpdf_font|css)$`, "m");
     /+ heading & paragraph operators +/
     static heading_a          = ctRegex!(`^:?[A][~] `, "m");
     static heading            = ctRegex!(`^:?([A-D1-4])[~]([a-z0-9_.-]*[?]?) `);
@@ -160,18 +178,6 @@ template RgxInit() {
     static parent                    = ctRegex!(`([0-7]):([0-9]+)`);
     /+ json +/
     static tailing_comma             = ctRegex!(`,$`, "m");
-    /+ head +/
-    static main_headers              = ctRegex!(`^(?:creator|title|rights|date|original|classify|identifier|notes|publisher|make|links)$`, "m");
-    static subhead_creator           = ctRegex!(`^(?:author|translator|illustrator)$`, "m");
-    static subhead_title             = ctRegex!(`^(?:main|sub(?:title)?|full|language|edition|note)$`, "m");
-    static subhead_rights            = ctRegex!(`^(?:copyright|illustrations|license|cover)$`, "m");
-    static subhead_date              = ctRegex!(`^(?:published|created|issued|available|valid|modified|added_to_site)$`, "m");
-    static subhead_original          = ctRegex!(`^(?:title|language|source)$`, "m");
-    static subhead_classify          = ctRegex!(`^(?:topic_register|subject|keywords|loc|dewey)$`, "m");
-    static subhead_identifier        = ctRegex!(`^(?:oclc|pg|isbn)$`, "m");
-    static subhead_notes             = ctRegex!(`^(?:abstract|description)$`, "m");
-    static subhead_publisher         = ctRegex!(`^(?:name)$`, "m");
-    static subhead_make              = ctRegex!(`^(?:cover_image|home_button_image|home_button_text|footer|headings|num_top|breaks|substitute|bold|italics|emphasis|texpdf_font|css)$`, "m");
     /+ biblio tags +/
     static biblio_tags               = ctRegex!(`^(is|au|author_raw|author|author_arr|editor_raw|ed|editor_arr|ti|title|subtitle|fulltitle|lng|language|trans|src|jo|journal|in|vol|volume|edn|edition|yr|year|pl|place|pb|pub|publisher|url|pg|pages|note|short_name|id):\s+(.+)`);
     static biblio_abbreviations      = ctRegex!(`^(au|ed|ti|lng|jo|vol|edn|yr|pl|pb|pub|pg|pgs|sn)$`);
-- 
cgit v1.2.3