-*- mode: org -*-
#+TITLE:       spine (doc_reform) config & header (make & meta) extract
#+DESCRIPTION: documents - structuring, publishing in multiple formats & search
#+FILETAGS:    :spine:config:
#+AUTHOR:      Ralph Amissah
#+EMAIL:       [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
#+COPYRIGHT:   Copyright (C) 2015 - 2020 Ralph Amissah
#+LANGUAGE:    en
#+STARTUP:     content hideblocks hidestars noindent entitiespretty
#+OPTIONS:     H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t
#+PROPERTY:    header-args  :exports code
#+PROPERTY:    header-args+ :noweb yes
#+PROPERTY:    header-args+ :eval no
#+PROPERTY:    header-args+ :results no
#+PROPERTY:    header-args+ :cache no
#+PROPERTY:    header-args+ :padline no

[[./spine.org][spine]]  [[./][org/]]
* 0. generic
** conf yaml ref

#+BEGIN_SRC yaml
flag:
  act0:                       "--html"
  act1:                       "--html --epub"
output:
  path:                       "/var/www/html"
default:
  language:                   "en"
  papersize:                  "a4"
  text_wrap:                  "80"
  digest:                     "sha256"
webserv:
  http:                       "http"
  domain:                     "localhost"
  data_http:                  "http"
  data_domain:                "localhost"
  data_root_url:              "http://localhost"
  data_root_path:             "/var/www/html"
  data_root_part:             ""
  images_root_part:           "image"
  cgi_title:                  "≅ SiSU Spine search"
  cgi_http:                   "http"
  cgi_domain:                 "localhost"
  cgi_bin_url:                "http://localhost/cgi-bin"
  cgi_bin_part:               "cgi-bin"
  cgi_bin_path:               "/usr/lib/cgi-bin"
  cgi_search_title:           "≅ SiSU spine search form"
  cgi_search_script:          "spine-search"
  cgi_search_script_raw_fn_d: "spine_search.d"
  cgi_port:                   ""
  cgi_user:                   ""
  cgi_action:                 "http://localhost/cgi-bin/spine-search"
  db_sqlite:                  "spine.search.db"
  db_pg_table:                ""
  db_pg_user:                 ""
#+END_SRC

** imports

#+NAME: meta_defaults_imports
#+BEGIN_SRC d
import
  std.algorithm,
  std.array,
  std.container,
  std.exception,
  std.file,
  std.getopt,
  std.json,
  std.path,
  std.process,
  std.range,
  std.regex,
  std.stdio,
  std.string,
  std.typecons,
  std.uni,
  std.utf,
  std.conv : to;
import doc_reform.meta.conf_make_meta_structs;
#+END_SRC

** struct ConfComposite

#+BEGIN_SRC d :tangle "../src/doc_reform/meta/conf_make_meta_structs.d"
module doc_reform.meta.conf_make_meta_structs;
<<meta_defaults_template_structs_0>>
<<meta_defaults_template_structs_1>>
<<meta_defaults_template_structs_2>>
<<meta_defaults_template_structs_3>>
<<meta_defaults_template_structs_4>>
<<meta_defaults_template_structs_5>>
<<meta_defaults_template_structs_6>>
#+END_SRC

** initialize, imports etc.

#+NAME: meta_defaults_template_structs_0
#+BEGIN_SRC d
import
  std.exception,
  std.json,
  std.path,
  std.regex,
  std.stdio,
  std.string,
  std.typecons,
  std.utf,
  std.conv : to;
import
  doc_reform.meta.defaults,
  doc_reform.meta.rgx;
mixin spineRgxIn;
static auto rgx = RgxI();
mixin InternalMarkup;
static auto mkup = InlineMarkup();
#+END_SRC

** struct Generic ConfComposite

#+NAME: meta_defaults_template_structs_1
#+BEGIN_SRC d
@safe string url_markup(string line) {
  string line_ = line
    .replaceAll(
      rgx.smid_inline_link_markup_regular,
      ("$1"
        ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c
        ~ mkup.url_o ~ "$3" ~ mkup.url_c
      ) // ("$1{ $2 }$3$4")
    )
    .replaceAll(
        rgx.smid_inline_link_naked_url,
        ("$1"
          ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c
          ~ mkup.url_o ~ "$2" ~ mkup.url_c
        ) // ("$1{ $2 }$2$3")
    )
    .replaceAll(
       rgx.arr_delimiter,
       mkup.br_line
    );
  return line_;
}
struct ConfCompositeMakeStr {
  string     bold;
  string     breaks;
  string     cover_image;
  string     css;
  string     emphasis;
  string[]   footer;
  string[]   headings;
  string[]   home_button_image;
  string     home_button_text = "┥Spine, Doc Reform┝┤http://www.doc-reform.org├"
    ~ " ┥www.doc-reform.org┝┤http://www.doc-reform.org├"
    ~ " ┥sources / git┝┤https://git.doc-reform.org/software/spine├";
  string     italics;
  string     auto_num_top_at_level;
  int        auto_num_top_lv           = 9;
  int        auto_num_depth            = 2;
  string[][] substitute;
  string     texpdf_font;
}
struct confCompositeMakeBuild {
  string[] bold(string _mk) {
    string[] _out;
    if (_mk) {
      _out = [ (cast(string) (`(` ~ _mk.dup ~ `)`)), "*{$1}*", "<b>$1</b>"];
    }
    return _out;
  }
  string breaks(string _mk) {
    return _mk;
  }
  string cover_image(string _mk) {
    return _mk;
  }
  string css(string _mk) {
    return _mk;
  }
  string[] emphasis(string _mk) {
    string[] _out;
    if (_mk) {
      _out = [ (cast(string) (`(` ~ _mk.dup ~ `)`)), "!{$1}!", "<em>$1</em>" ];
    }
    return _out;
  }
  string[] footer(string[] _mk) {
    string line_;
    string[] _mk2;
    foreach (line; _mk) {
      _mk2 ~= url_markup(line);
    }
    return _mk2;
  }
  string[] headings(string[] _mk) {
    return _mk;
  }
  string[] home_button_image(string[] _mk) {
    return _mk;
  }
  string home_button_text(string _mk) {
    return url_markup(_mk);
  }
  string[] italics(string _mk) {
    string[] _out;
    if (_mk) {
      _out = [ (cast(string) (`(` ~ _mk.dup ~ `)`)), "/{$1}/", "<i>$1</i>" ];
    }
    return _out;
  }
  string auto_num_top_at_level(string _mk) {
    return _mk;
  }
  int auto_num_top_lv(int _mk) {
    return _mk;
  }
  int auto_num_depth(int _mk) {
    return _mk;
  }
  string[][] substitute(string[][] _mk) {
    return _mk;
  }
  string texpdf_font(string _mk) {
    return _mk;
  }
}
#+END_SRC

** initialize make & meta
*** composite make

#+NAME: meta_defaults_template_structs_2
#+BEGIN_SRC d
struct ConfCompositeMakeInit {
  string[]   bold;
  string     breaks;
  string     cover_image;
  string     css;
  string[]   emphasis;
  string[]   footer;
  string[]   headings;
  string[]   home_button_image;
  string     home_button_text = "┥Spine, Doc Reform┝┤http://www.doc-reform.org├"
    ~ " ┥www.doc-reform.org┝┤http://www.doc-reform.org├"
    ~ " ┥sources / git┝┤https://git.doc-reform.org/software/spine├";
  string[] italics;
  string     auto_num_top_at_level;
  int        auto_num_top_lv               = 9;
  int        auto_num_depth                = 2;
  string[][] substitute;
  string     texpdf_font;
}
#+END_SRC

*** struct: conf site local

#+NAME: meta_defaults_template_structs_3
#+BEGIN_SRC d
struct ConfCompositeSiteLocal {
  string   w_srv_http;
  string   w_srv_domain;
  string   w_srv_data_http;            // if not set same as webserv_http
  string   w_srv_data_domain;          // if not set same as webserv_domain
  string   w_srv_data_root_part;
  string   w_srv_data_root_url;
  string   w_srv_data_root_url_html;
  string   w_srv_data_root_path;
  string   w_srv_images_root_part;
  // string   w_srv_url_doc_path;
  string   w_srv_cgi_title;
  string   w_srv_cgi_http;             // if not set same as webserv_http
  string   w_srv_cgi_domain;           // if not set same as webserv_domain
  string   w_srv_cgi_bin_part;
  string   w_srv_cgi_bin_path;
  string   w_srv_cgi_search_title;
  string   w_srv_cgi_search_script;
  string   w_srv_cgi_search_script_raw_fn_d;
  string   w_srv_cgi_port;
  string   w_srv_cgi_user;
  string   w_srv_cgi_action;
  string   w_srv_cgi_bin_url;
  string   w_srv_db_sqlite;
  // string   w_srv_db_pg;
  string   w_srv_db_pg_table;
  string   w_srv_db_pg_user;
  // string   webserv_cgi_file_links;
  string   output_path;
  string   processing_path;
  string   processing_dir;
  string   processing_concord_max;
  string   flag_act0;
  string   flag_act1;
  string   flag_act2;
  string   flag_act3;
  string   flag_act4;
  string   flag_act5;
  string   flag_act6;
  string   flag_act7;
  string   flag_act8;
  string   flag_act9;
  string[] set_papersize;
  string   set_text_wrap;
  string   set_emphasis;
  string   set_language;
  string   set_digest;
  string   permission_share_source;
  string   search_flag;
  string   search_action;
  string   search_db;
  string   search_title;
}
#+END_SRC

*** struct: composite meta

#+NAME: meta_defaults_template_structs_4
#+BEGIN_SRC d
struct MetaComposite {
  string   classify_dewey;
  string   classify_keywords;
  string   classify_loc;
  string   classify_subject;
  string   classify_topic_register;
  string[] classify_topic_register_arr;
  string[] creator_author_arr;
  string   creator_author;
  string   creator_author_surname_fn;
  string   creator_author_surname;
  string   creator_author_email;
  string   creator_illustrator;
  string   creator_translator;
  string   date_added_to_site;
  string   date_available;
  string   date_created;
  string   date_issued;
  string   date_modified;
  string   date_published;
  string   date_valid;
  string   identifier_isbn;
  string   identifier_oclc;
  string   identifier_pg;
  string   language_document;
  string   language_document_char;
  string   links;
  string   notes_abstract;
  string   notes_description;
  string   notes_summary;
  string   original_language;
  string   original_language_char;
  string   original_publisher;
  string   original_source;
  string   original_title;
  string   publisher;
  string   rights_copyright;
  string   rights_copyright_audio;
  string   rights_copyright_cover;
  string   rights_copyright_illustrations;
  string   rights_copyright_photographs;
  string   rights_copyright_text;
  string   rights_copyright_translation;
  string   rights_copyright_video;
  string   rights_license;
  string   title_edition;
  string   title_full;
  string   title_language;
  string   title_main;
  string   title_note;
  string   title_short;
  string   title_sub;
  string   title_subtitle;
}
#+END_SRC

*** composite structs

#+NAME: meta_defaults_template_structs_5
#+BEGIN_SRC d
struct ConfComposite {
  MetaComposite               meta;
  ConfCompositeMakeInit       make;
  ConfCompositeMakeStr        make_str;
  ConfCompositeSiteLocal      conf;
}
#+END_SRC

*** JSONValue

#+NAME: meta_defaults_template_structs_6
#+BEGIN_SRC d
JSONValue config_jsonstr = `{
}`;
#+END_SRC

* 1. YAML to spineStruct                         :module:conf_make_meta:yaml:
** _module template_

#+BEGIN_SRC d :tangle "../src/doc_reform/meta/conf_make_meta_yaml.d"
/++
  yaml headers<BR>
  extract yaml header return struct
+/
module doc_reform.meta.conf_make_meta_yaml;
template contentYAMLtoSpineStruct() {
  import
    std.algorithm,
    std.array,
    std.exception,
    std.path,
    std.regex,
    std.stdio,
    std.string,
    std.typecons,
    std.utf,
    std.conv : to;
  import
    doc_reform.meta.conf_make_meta_structs,
    doc_reform.meta.defaults,
    doc_reform.meta.rgx;
  ConfComposite _struct_composite;
  @system auto contentYAMLtoSpineStruct(C,Y,M,O)(
    C _struct_composite,
    Y _yaml,
    M _manifested,
    O _opt_action,
    string _identifier
  ) {
    mixin spineRgxIn;
    static auto rgx = RgxI();
    confCompositeMakeBuild _mk;
    <<yaml_objects_make>>
    <<yaml_objects_conf>>
    <<yaml_objects_meta>>
    return _struct_composite;
  }
}
#+END_SRC

**  make

#+NAME: yaml_objects_make
#+BEGIN_SRC d
/+ make ------------------------------------------------------------------- +/
if ("make" in _yaml
  && _yaml["make"].type.sequence
) {
  if (_yaml["make"].type.mapping
    && _yaml["make"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("bold" in _yaml["make"]
      && _yaml["make"]["bold"].type.string
      && _yaml["make"]["bold"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.bold = _yaml["make"]["bold"].get!string;
    }
    if ("breaks" in _yaml["make"]
      && _yaml["make"]["breaks"].type.string
      && _yaml["make"]["breaks"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.breaks = _yaml["make"]["breaks"].get!string;
    }
    if ("cover_image" in _yaml["make"]
      && _yaml["make"]["cover_image"].type.string
      && _yaml["make"]["cover_image"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.cover_image = _yaml["make"]["cover_image"].get!string;
    }
    if ("css" in _yaml["make"]
      && _yaml["make"]["css"].type.string
      && _yaml["make"]["css"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.css = _yaml["make"]["css"].get!string;
    }
    if ("emphasis" in _yaml["make"]
      && _yaml["make"]["emphasis"].type.string
      && _yaml["make"]["emphasis"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.emphasis = _yaml["make"]["emphasis"].get!string;
    }
    if ("footer" in _yaml["make"]
      && _yaml["make"]["footer"].type.string
      && _yaml["make"]["footer"].tag.match(rgx.yaml_tag_is_str)
    ) {
      char[][] __match_footer_array
        = (cast(char[]) _yaml["make"]["footer"].get!string)
          .split(rgx.make_heading_delimiter);
      _struct_composite.make_str.footer = __match_footer_array.to!(string[]);
    }
    if ("headings" in _yaml["make"]
      && _yaml["make"]["headings"].type.string
      && _yaml["make"]["headings"].tag.match(rgx.yaml_tag_is_str)
    ) {
      char[][] __match_headings_array
        = (cast(char[]) _yaml["make"]["headings"].get!string)
          .split(rgx.make_heading_delimiter);
      _struct_composite.make_str.headings = __match_headings_array.to!(string[]);
    } else if ("headings" in _yaml["make"]
      && _yaml["make"]["headings"].type.string
      && _yaml["make"]["headings"].tag.match(rgx.yaml_tag_is_seq)
    ) {
      foreach(string identify_heading_level; _yaml["make"]["headings"]) {
        _struct_composite.make_str.headings ~= identify_heading_level;
      }
    }
    if ("home_button_image" in _yaml["make"]
      && _yaml["make"]["home_button_image"].type.string
      && _yaml["make"]["home_button_image"].tag.match(rgx.yaml_tag_is_str)
    ) {
      char[][] __match_home_button_image_array
        = (cast(char[]) _yaml["make"]["home_button_image"].get!string)
          .split(rgx.make_heading_delimiter);
      _struct_composite.make_str.home_button_image = __match_home_button_image_array.to!(string[]);
    }
    if ("home_button_text" in _yaml["make"]
      && _yaml["make"]["home_button_text"].type.string
      && _yaml["make"]["home_button_text"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.home_button_text = _yaml["make"]["home_button_text"].get!string;
    } else if ("home_button_text" in _yaml["make"]
      && _yaml["make"]["home_button_text"].type.string
      && _yaml["make"]["home_button_text"].tag.match(rgx.yaml_tag_is_seq)
    ) {
      _struct_composite.make_str.home_button_text = "";
      foreach(string hbt; _yaml["make"]["home_button_text"]) {
        _struct_composite.make_str.home_button_text ~= hbt ~ "; ";
      }
    }
    if ("italics" in _yaml["make"]
      && _yaml["make"]["italics"].type.string
      && _yaml["make"]["italics"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.italics = _yaml["make"]["italics"].get!string;
    }
    if ("auto_num_top_at_level" in _yaml["make"]
      && _yaml["make"]["auto_num_top_at_level"].type.string
      && _yaml["make"]["auto_num_top_at_level"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.auto_num_top_at_level = _yaml["make"]["auto_num_top_at_level"].get!string;
      switch (_yaml["make"]["auto_num_top_at_level"].get!string) {
      case "A":
        break;
      case "B": _struct_composite.make_str.auto_num_top_lv = 1;
        break;
      case "C": _struct_composite.make_str.auto_num_top_lv = 2;
        break;
      case "D": _struct_composite.make_str.auto_num_top_lv = 3;
        break;
      case "1": _struct_composite.make_str.auto_num_top_lv = 4;
        break;
      case "2": _struct_composite.make_str.auto_num_top_lv = 5;
        break;
      case "3": _struct_composite.make_str.auto_num_top_lv = 6;
        break;
      case "4": _struct_composite.make_str.auto_num_top_lv = 7;
        break;
      default:
        break;
      }
    }
    if ("auto_num_depth" in _yaml["make"]
      && _yaml["make"]["auto_num_depth"].type.string
      && _yaml["make"]["auto_num_depth"].tag.match(rgx.yaml_tag_is_int)
    ) { // not sure implemented for documents
      _struct_composite.make_str.auto_num_depth = _yaml["make"]["auto_num_depth"].get!int;
    } else if ("auto_num_depth" in _yaml["make"]
      && _yaml["make"]["auto_num_depth"].type.string
      && _yaml["make"]["auto_num_depth"].tag.match(rgx.yaml_tag_is_str)
    ) { // not sure implemented for documents
      _struct_composite.make_str.auto_num_depth = _yaml["make"]["auto_num_depth"].get!int;
    }
    if ("texpdf_font" in _yaml["make"]
      && _yaml["make"]["texpdf_font"].type.string
    ) {
      _struct_composite.make_str.texpdf_font = _yaml["make"]["texpdf_font"].get!string;
    }
  }
  _struct_composite.make.bold                     = _mk.bold(_struct_composite.make_str.bold);
  _struct_composite.make.breaks                   = _mk.breaks(_struct_composite.make_str.breaks);
  _struct_composite.make.cover_image              = _mk.cover_image(_struct_composite.make_str.cover_image);
  _struct_composite.make.css                      = _mk.css(_struct_composite.make_str.css);
  _struct_composite.make.emphasis                 = _mk.emphasis(_struct_composite.make_str.emphasis);
  _struct_composite.make.footer                   = _mk.footer(_struct_composite.make_str.footer);
  _struct_composite.make.headings                 = _mk.headings(_struct_composite.make_str.headings);
  _struct_composite.make.home_button_image        = _mk.home_button_image(_struct_composite.make_str.home_button_image);
  _struct_composite.make.home_button_text         = _mk.home_button_text(_struct_composite.make_str.home_button_text);
  _struct_composite.make.italics                  = _mk.italics(_struct_composite.make_str.italics);
  _struct_composite.make.auto_num_top_at_level    = _mk.auto_num_top_at_level(_struct_composite.make_str.auto_num_top_at_level);
  _struct_composite.make.auto_num_top_lv          = _mk.auto_num_top_lv(_struct_composite.make_str.auto_num_top_lv);
  _struct_composite.make.auto_num_depth           = _mk.auto_num_depth(_struct_composite.make_str.auto_num_depth);
  _struct_composite.make.substitute               = _mk.substitute(_struct_composite.make_str.substitute);
  _struct_composite.make.texpdf_font              = _mk.texpdf_font(_struct_composite.make_str.texpdf_font);
}

#+END_SRC

**  conf

#+NAME: yaml_objects_conf
#+BEGIN_SRC d
/+ conf ------------------------------------------------------------------- +/
if ("webserv" in _yaml
  && _yaml["webserv"].type.sequence
) {
  if (_yaml["webserv"].type.mapping
    && _yaml["webserv"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("http" in _yaml["webserv"]
      && _yaml["webserv"]["http"].type.string
      && _yaml["webserv"]["http"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_http = _yaml["webserv"]["http"].get!string;
    } // else { set default? }
    if ("data_http" in _yaml["webserv"]
      && _yaml["webserv"]["data_http"].type.string
      && _yaml["webserv"]["data_http"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_data_http = _yaml["webserv"]["data_http"].get!string;
    }
    if ("cgi_http" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_http"].type.string
      && _yaml["webserv"]["cgi_http"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_http = _yaml["webserv"]["cgi_http"].get!string;
    }
    if ("domain" in _yaml["webserv"]
      && _yaml["webserv"]["domain"].type.string
      && _yaml["webserv"]["domain"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_domain = _yaml["webserv"]["domain"].get!string;
    }
    // if ("data_root_url" in _yaml["webserv"]
    //   && _yaml["webserv"]["data_root_url"].type.string
    //   && _yaml["webserv"]["data_root_url"].tag.match(rgx.yaml_tag_is_str)
    // ) {
    //   _struct_composite.conf.w_srv_data_root_url = _yaml["webserv"]["data_root_url"].get!string;
    //   if (auto m = _struct_composite.conf.w_srv_data_root_url.match(rgx.webserv_url_doc_root)) {
    //     _struct_composite.conf.w_srv_url_domain = m.captures[2].to!string;
    //     _struct_composite.conf.w_srv_url_doc_path = m.captures[3].to!string;
    //   }
    // }
    if ("data_root_path" in _yaml["webserv"]
      && _yaml["webserv"]["data_root_path"].type.string
      && _yaml["webserv"]["data_root_path"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_data_root_path = _yaml["webserv"]["data_root_path"].get!string;
    }
    if ("data_root_part" in _yaml["webserv"]
      && _yaml["webserv"]["data_root_part"].type.string
      && _yaml["webserv"]["data_root_part"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_data_root_part = _yaml["webserv"]["data_root_part"].get!string;
    }
    if ("images_root_part" in _yaml["webserv"]
      && _yaml["webserv"]["images_root_part"].type.string
      && _yaml["webserv"]["images_root_part"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_images_root_part = _yaml["webserv"]["images_root_part"].get!string;
    }
    if ("data_root_url" in _yaml["webserv"]
      && _yaml["webserv"]["data_root_url"].type.string
      && _yaml["webserv"]["data_root_url"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_data_root_url      = _yaml["webserv"]["data_root_url"].get!string;
      _struct_composite.conf.w_srv_data_root_url_html =
        _yaml["webserv"]["data_root_url"].get!string ~ "/"
        ~ _manifested.src.language ~ "/"
        ~ "html";
    } else {
      _struct_composite.conf.w_srv_data_root_url =  _struct_composite.conf.w_srv_data_root_part;
      _struct_composite.conf.w_srv_data_root_url_html =
        _struct_composite.conf.w_srv_data_root_part ~ "/"
        ~ _manifested.src.language ~ "/"
        ~ "html";
    }
    if ("cgi_domain" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_domain"].type.string
      && _yaml["webserv"]["cgi_domain"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_domain = _yaml["webserv"]["cgi_domain"].get!string;
    } else { // composite construct
      _struct_composite.conf.w_srv_cgi_domain = _struct_composite.conf.w_srv_domain;
    }
    if ("cgi_title" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_title"].type.string
      && _yaml["webserv"]["cgi_title"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_title = _yaml["webserv"]["cgi_title"].get!string;
    }
    if ("cgi_bin_part" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_bin_part"].type.string
      && _yaml["webserv"]["cgi_bin_part"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_bin_part = _yaml["webserv"]["cgi_bin_part"].get!string;
    }
    if ("cgi_bin_path" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_bin_path"].type.string
      && _yaml["webserv"]["cgi_bin_path"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_bin_path = _yaml["webserv"]["cgi_bin_path"].get!string;
    }
    if (_opt_action.cgi_search_title.length > 0) {
      _struct_composite.conf.w_srv_cgi_search_title = _opt_action.cgi_search_title;
    } else if ("cgi_search_title" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_search_title"].type.string
      && _yaml["webserv"]["cgi_search_title"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_search_title = _yaml["webserv"]["cgi_search_title"].get!string;
    } else {
      _struct_composite.conf.w_srv_cgi_search_title = "≅ SiSU spine search form";
    }
    if (_opt_action.cgi_sqlite_search_filename.length > 0) {
      _struct_composite.conf.w_srv_cgi_search_script = _opt_action.cgi_sqlite_search_filename;
    } else if ("cgi_search_script" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_search_script"].type.string
      && _yaml["webserv"]["cgi_search_script"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_search_script = _yaml["webserv"]["cgi_search_script"].get!string;
    } else {
      _struct_composite.conf.w_srv_cgi_search_script = "spine-search";
    }
    if (_opt_action.cgi_sqlite_search_filename_d.length > 0) {
      _struct_composite.conf.w_srv_cgi_search_script_raw_fn_d = _opt_action.cgi_sqlite_search_filename_d;
    } else if ("cgi_search_script_raw_fn_d" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_search_script_raw_fn_d"].type.string
      && _yaml["webserv"]["cgi_search_script_raw_fn_d"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_search_script_raw_fn_d = _yaml["webserv"]["cgi_search_script_raw_fn_d"].get!string;
    } else if ("cgi_search_script" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_search_script"].type.string
      && _yaml["webserv"]["cgi_search_script"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_search_script_raw_fn_d = (_yaml["webserv"]["cgi_search_script"].get!string).translate(['-' : "_"]) ~ ".d";
    } else {
      _struct_composite.conf.w_srv_cgi_search_script_raw_fn_d = "spine_search.d";
    }
    if ("cgi_port" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_port"].type.string
      && _yaml["webserv"]["cgi_port"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_port = _yaml["webserv"]["cgi_port"].get!string;
    }
    if ("cgi_user" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_user"].type.string
      && _yaml["webserv"]["cgi_user"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_user = _yaml["webserv"]["cgi_user"].get!string;
    }
    if ("cgi_bin_url" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_bin_url"].type.string
      && _yaml["webserv"]["cgi_bin_url"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_bin_url = _yaml["webserv"]["cgi_bin_url"].get!string;
    } else {
      _struct_composite.conf.w_srv_cgi_bin_url =
        (_struct_composite.conf.w_srv_cgi_http.empty)
          ? _struct_composite.conf.w_srv_http
          :_struct_composite.conf.w_srv_cgi_http
        ~ "://"
        ~ (_struct_composite.conf.w_srv_cgi_domain.empty)
          ? _struct_composite.conf.w_srv_cgi_domain
          : _struct_composite.conf.w_srv_domain
        ~ "/"
        ~ _struct_composite.conf.w_srv_cgi_bin_part;
    }
    if (_opt_action.cgi_sqlite_search_filename.length > 0) {
      _struct_composite.conf.w_srv_cgi_action = _struct_composite.conf.w_srv_cgi_bin_url ~ "/" ~ _opt_action.cgi_sqlite_search_filename;
    } else if ("cgi_action" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_action"].type.string
      && _yaml["webserv"]["cgi_action"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_action = _yaml["webserv"]["cgi_action"].get!string;
    } else { // action is composite, build
    }
    // if ("cgi_file_links" in _yaml["webserv"]
    //   && _yaml["webserv"]["cgi_file_links"].type.string
    //   && _yaml["webserv"]["cgi_file_links"].tag.match(rgx.yaml_tag_is_str)
    // ) {
    //   _struct_composite.conf.w_srv_cgi_file_links = _yaml["webserv"]["cgi_file_links"].get!string;
    // }
    if (_opt_action.sqlite_filename.length > 0) {
      _struct_composite.conf.w_srv_db_sqlite = _opt_action.sqlite_filename;
    } else if ("db_sqlite" in _yaml["webserv"]
      && _yaml["webserv"]["db_sqlite"].type.string
      && _yaml["webserv"]["db_sqlite"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_db_sqlite = _yaml["webserv"]["db_sqlite"].get!string;
    } else { // set default ?
    }
  }
}
if (!(_struct_composite.conf.output_path)) {
  _struct_composite.conf.output_path = ((_manifested.output.path).asNormalizedPath).array;
}
if (_opt_action.output_dir_set.length > 0) {
  _struct_composite.conf.output_path = (_opt_action.output_dir_set.asNormalizedPath).array;
} else if ("output" in _yaml
  && _yaml["output"].type.sequence
) {
  if (_yaml["output"].type.mapping
    && _yaml["output"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("path" in _yaml["output"]
      && _yaml["output"]["path"].type.string
      && _yaml["output"]["path"].tag.match(rgx.yaml_tag_is_str)
    ) {
      if (_manifested.output.path == _manifested.env.pwd
        && _yaml["output"]["path"].get!string.length > 0
      ) {
        _struct_composite.conf.output_path = (((_yaml["output"]["path"].get!string).expandTilde).asNormalizedPath).array;
      }
    }
  }
}
if ("processing" in _yaml
  && _yaml["processing"].type.sequence
) {
  if (_yaml["processing"].type.mapping
    && _yaml["processing"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("concord_max" in _yaml["processing"]
      && _yaml["processing"]["concord_max"].type.string
      && _yaml["processing"]["concord_max"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.processing_concord_max = _yaml["processing"]["concord_max"].get!string;
    }
  }
}
if ("flag" in _yaml
  && _yaml["flag"].type.sequence
) {
  if (_yaml["flag"].type.mapping
    && _yaml["flag"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("act0" in _yaml["flag"]
      && _yaml["flag"]["act0"].type.string
      && _yaml["flag"]["act0"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.flag_act0 = _yaml["flag"]["act0"].get!string;
    }
    if ("act1" in _yaml["flag"]
      && _yaml["flag"]["act1"].type.string
      && _yaml["flag"]["act1"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.flag_act1 = _yaml["flag"]["act1"].get!string;
    }
    if ("act2" in _yaml["flag"]
      && _yaml["flag"]["act2"].type.string
      && _yaml["flag"]["act2"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.flag_act2 = _yaml["flag"]["act2"].get!string;
    }
    if ("act3" in _yaml["flag"]
      && _yaml["flag"]["act3"].type.string
      && _yaml["flag"]["act3"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.flag_act3 = _yaml["flag"]["act3"].get!string;
    }
    if ("act4" in _yaml["flag"]
      && _yaml["flag"]["act4"].type.string
      && _yaml["flag"]["act4"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.flag_act4 = _yaml["flag"]["act4"].get!string;
    }
    if ("act5" in _yaml["flag"]
      && _yaml["flag"]["act5"].type.string
      && _yaml["flag"]["act5"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.flag_act5 = _yaml["flag"]["act5"].get!string;
    }
    if ("act6" in _yaml["flag"]
      && _yaml["flag"]["act6"].type.string
      && _yaml["flag"]["act6"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.flag_act6 = _yaml["flag"]["act6"].get!string;
    }
    if ("act7" in _yaml["flag"]
      && _yaml["flag"]["act7"].type.string
      && _yaml["flag"]["act7"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.flag_act7 = _yaml["flag"]["act7"].get!string;
    }
    if ("act8" in _yaml["flag"]
      && _yaml["flag"]["act8"].type.string
      && _yaml["flag"]["act8"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.flag_act8 = _yaml["flag"]["act8"].get!string;
    }
    if ("act9" in _yaml["flag"]
      && _yaml["flag"]["act9"].type.string
      && _yaml["flag"]["act9"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.flag_act9 = _yaml["flag"]["act9"].get!string;
    }
  }
}
string[] selected_papersize(string _sizes_str) {
  string[] _sizes = _sizes_str.split(regex(r"\s*,\s*"));
  string[] _selected_sizes;
  foreach (_size; _sizes) {
    switch (_size) {
      case "a4":
        _selected_sizes ~= "a4.portrait";
        _selected_sizes ~= "a4.landscape";
        break;
      case "a4.portrait":
        _selected_sizes ~= _size;
        break;
      case "a4.landscape":
        _selected_sizes ~= _size;
        break;
      case "a5":
        _selected_sizes ~= "a5.portrait";
        _selected_sizes ~= "a5.landscape";
        break;
      case "a5.portrait":
        _selected_sizes ~= _size;
        break;
      case "a5.landscape":
        _selected_sizes ~= _size;
        break;
      case "b4":
        _selected_sizes ~= "b4.portrait";
        _selected_sizes ~= "b4.landscape";
        break;
      case "b4.portrait":
        _selected_sizes ~= _size;
        break;
      case "b4.landscape":
        _selected_sizes ~= _size;
        break;
      case "letter":
        _selected_sizes ~= "letter.portrait";
        _selected_sizes ~= "letter.landscape";
        break;
      case "letter.portrait":
        _selected_sizes ~= _size;
        break;
      case "letter.landscape":
        _selected_sizes ~= _size;
        break;
      case "legal":
        _selected_sizes ~= "legal.portrait";
        _selected_sizes ~= "legal.landscape";
        break;
      case "legal.portrait":
        _selected_sizes ~= _size;
        break;
      case "legal.landscape":
        _selected_sizes ~= _size;
        break;
      default: break;
    }
  }
  return _selected_sizes;
}
if (_opt_action.latex_papersize.length > 0) {
  _struct_composite.conf.set_papersize = selected_papersize(_opt_action.latex_papersize);
} else if (
  "default" in _yaml
  && _yaml["default"].type.sequence
  && _yaml["default"].type.mapping
  && _yaml["default"].tag.match(rgx.yaml_tag_is_map)
) {
  if ("papersize" in _yaml["default"]
    && _yaml["default"]["papersize"].type.string
    && _yaml["default"]["papersize"].tag.match(rgx.yaml_tag_is_str)
  ) {
    _struct_composite.conf.set_papersize = selected_papersize(_yaml["default"]["papersize"].get!string);
  }
}
if (_struct_composite.conf.set_papersize.length == 0) {
  _struct_composite.conf.set_papersize = ["a4.portrait", "a4.landscape"];
}
if (
  "default" in _yaml
  && _yaml["default"].type.sequence
  && _yaml["default"].type.mapping
  && _yaml["default"].tag.match(rgx.yaml_tag_is_map)
) {
  if ("text_wrap" in _yaml["default"]
    && _yaml["default"]["text_wrap"].type.string
    && _yaml["default"]["text_wrap"].tag.match(rgx.yaml_tag_is_str)
  ) {
    _struct_composite.conf.set_text_wrap = _yaml["default"]["text_wrap"].get!string;
  }
  if ("emphasis" in _yaml["default"]
    && _yaml["default"]["emphasis"].type.string
    && _yaml["default"]["emphasis"].tag.match(rgx.yaml_tag_is_str)
  ) {
    _struct_composite.conf.set_emphasis = _yaml["default"]["emphasis"].get!string;
  }
  if ("language" in _yaml["default"]
    && _yaml["default"]["language"].type.string
    && _yaml["default"]["language"].tag.match(rgx.yaml_tag_is_str)
  ) {
    _struct_composite.conf.set_language = _yaml["default"]["language"].get!string;
  }
  if ("digest" in _yaml["default"]
    && _yaml["default"]["digest"].type.string
    && _yaml["default"]["digest"].tag.match(rgx.yaml_tag_is_str)
  ) {
    _struct_composite.conf.set_digest = _yaml["default"]["digest"].get!string;
  }
}
if ("search" in _yaml
  && _yaml["search"].type.sequence
) {
  if (_yaml["search"].type.mapping
    && _yaml["search"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("flag" in _yaml["search"]
      && _yaml["search"]["flag"].type.string
      && _yaml["search"]["flag"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.search_flag = _yaml["search"]["flag"].get!string;
    }
    if ("action" in _yaml["search"]
      && _yaml["search"]["action"].type.string
      && _yaml["search"]["action"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.search_action = _yaml["search"]["action"].get!string;
    }
    if ("db" in _yaml["search"]
      && _yaml["search"]["db"].type.string
      && _yaml["search"]["db"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.search_db = _yaml["search"]["db"].get!string;
    }
    if ("title" in _yaml["search"]
      && _yaml["search"]["title"].type.string
      && _yaml["search"]["title"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.conf.search_title = _yaml["search"]["title"].get!string;
    }
  }
}
#+END_SRC

**  meta

#+NAME: yaml_objects_meta
#+BEGIN_SRC d
/+ meta ------------------------------------------------------------------- +/
if (_struct_composite.meta.creator_author.empty) {
  if ("creator" in _yaml
    && _yaml["creator"].type.sequence
  ) {
    if (_yaml["creator"].type.mapping
      && _yaml["creator"].tag.match(rgx.yaml_tag_is_map)
    ) {
      if ("author" in _yaml["creator"]
        && _yaml["creator"]["author"].type.string
        && _yaml["creator"]["author"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.creator_author = _yaml["creator"]["author"].get!string;
      }
      if ("email" in _yaml["creator"]
        && _yaml["creator"]["email"].type.string
        && _yaml["creator"]["email"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.creator_author_email = _yaml["creator"]["email"].get!string;
      }
      if ("illustrator" in _yaml["creator"]
        && _yaml["creator"]["illustrator"].type.string
        && _yaml["creator"]["illustrator"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.creator_illustrator = _yaml["creator"]["illustrator"].get!string;
      }
      if ("translator" in _yaml["creator"]
        && _yaml["creator"]["translator"].type.string
        && _yaml["creator"]["translator"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.creator_translator = _yaml["creator"]["translator"].get!string;
      }
    } else if (_yaml["creator"].type.string
      && _yaml["creator"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.creator_author = _yaml["creator"].get!string;
    }
  }
  string[] author_arr;
  string[][string] authors_hash_arr = [ "first" : [], "last" : [], "full" : [], "last_first" : [], "as_input" : [] ];
  string[] authors_raw_arr
    = _struct_composite.meta.creator_author.split(rgx.arr_delimiter);
  auto _lastname = appender!(char[])();
  foreach (author_raw; authors_raw_arr) {
    if (auto m = author_raw.match(rgx.raw_author_munge)) {
      author_arr                   ~= author_raw.replace(rgx.raw_author_munge, "$2 $1");
      authors_hash_arr["first"]    ~= author_raw.replace(rgx.raw_author_munge, "$2");
      authors_hash_arr["last"]     ~= author_raw.replace(rgx.raw_author_munge, "$1");
      authors_hash_arr["full"]     ~= author_raw.replace(rgx.raw_author_munge, "$2 $1");
      (m.captures[1]).map!toUpper.copy(_lastname);
      authors_hash_arr["last_first"] ~= _lastname.data.to!string ~ ", " ~ m.captures[2];
      _lastname = appender!(char[])();
    } else {
      author_arr                     ~= author_raw;
      authors_hash_arr["last"]       ~= author_raw;
      authors_hash_arr["full"]       ~= author_raw;
      authors_hash_arr["last_first"] ~= author_raw;
    }
    authors_hash_arr["as_input"] ~= author_raw;
  }
  _struct_composite.meta.creator_author_arr = author_arr;
  _struct_composite.meta.creator_author     = author_arr.join(", ").chomp.chomp;
  _struct_composite.meta.creator_author_surname = (authors_hash_arr["last"].length > 0) ? authors_hash_arr["last"][0] : "";
  string _author_name_last_first = authors_hash_arr["last_first"].join("; ").chomp.chomp;
  _struct_composite.meta.creator_author_surname_fn = (_author_name_last_first.length > 0)
  ? _author_name_last_first
  : authors_hash_arr["as_input"].join("; ").chomp.chomp;
}
if (_struct_composite.meta.title_main.empty) {
  if ("title" in _yaml
    && _yaml["title"].type.sequence
  ) {
    if (_yaml["title"].type.mapping
      && _yaml["title"].tag.match(rgx.yaml_tag_is_map)
    ) {
      if ("main" in _yaml["title"]
        && _yaml["title"]["main"].type.string
        && _yaml["title"]["main"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.title_main = _yaml["title"]["main"].get!string;
      } else if ("title" in _yaml["title"]
        && _yaml["title"]["title"].type.string
        && _yaml["title"]["title"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.title_main = _yaml["title"]["title"].get!string;
      }
      if ("edition" in _yaml["title"]
        && _yaml["title"]["edition"].type.string
        && _yaml["title"]["edition"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.title_edition = _yaml["title"]["edition"].get!string;
      }
      if ("full" in _yaml["title"]
        && _yaml["title"]["full"].type.string
        && _yaml["title"]["full"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.title_full = _yaml["title"]["full"].get!string;
      }
      if ("language" in _yaml["title"]
        && _yaml["title"]["language"].type.string
        && _yaml["title"]["language"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.title_language = _yaml["title"]["language"].get!string;
      }
      if ("note" in _yaml["title"]
        && _yaml["title"]["note"].type.string
        && _yaml["title"]["note"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.title_note = _yaml["title"]["note"].get!string;
      }
      if ("subtitle" in _yaml["title"]
        && _yaml["title"]["subtitle"].type.string
        && _yaml["title"]["subtitle"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.title_subtitle = _yaml["title"]["subtitle"].get!string;
      } else if ("sub" in _yaml["title"]
        && _yaml["title"]["sub"].type.string
        && _yaml["title"]["sub"].tag.match(rgx.yaml_tag_is_str)
      ) {
        _struct_composite.meta.title_subtitle = _yaml["title"]["sub"].get!string;
      }
    } else if (
      _yaml["title"].type.string
      && _yaml["title"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.title_main = _yaml["title"].get!string;
    }
  }
  _struct_composite.meta.title_sub = _struct_composite.meta.title_subtitle;
  if ((!(_struct_composite.meta.title_subtitle.empty))
  && (_struct_composite.meta.title_sub.empty)) {
    _struct_composite.meta.title_sub = _struct_composite.meta.title_subtitle;
  }
  _struct_composite.meta.title_full = (_struct_composite.meta.title_subtitle.empty)
  ? _struct_composite.meta.title_main
  : format(
      "%s - %s",
      _struct_composite.meta.title_main,
      _struct_composite.meta.title_subtitle,
    );
}
if ("classify" in _yaml
  && _yaml["classify"].type.sequence
) {
  if (_yaml["classify"].type.mapping
    && _yaml["classify"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("dewey" in _yaml["classify"]
      && _yaml["classify"]["dewey"].type.string
      && _yaml["classify"]["dewey"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.classify_dewey = _yaml["classify"]["dewey"].get!string;
    }
    if ("loc" in _yaml["classify"]
      && _yaml["classify"]["loc"].type.string
      && _yaml["classify"]["loc"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.classify_loc = _yaml["classify"]["loc"].get!string;
    }
    if ("keywords" in _yaml["classify"]
      && _yaml["classify"]["keywords"].type.string
      && _yaml["classify"]["keywords"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.classify_keywords = _yaml["classify"]["keywords"].get!string;
    }
    if ("topic_register" in _yaml["classify"]
      && _yaml["classify"]["topic_register"].type.string
      && _yaml["classify"]["topic_register"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.classify_topic_register = _yaml["classify"]["topic_register"].get!string;
      string[] main_topics_ = _struct_composite.meta.classify_topic_register.strip.split(rgx.topic_register_main_terms_split);
      string[] topics;
      string   topics_tmp;
      string[] multiple_sub_terms;
      foreach (mt; main_topics_) {
        topics_tmp = mt.replaceAll(rgx.topic_register_main_term_plus_rest_split,    mkup.sep);
        if (auto m = topics_tmp.match(rgx.topic_register_multiple_sub_terms_split)) {
          multiple_sub_terms = m.captures[1].split(rgx.topic_register_sub_terms_split);
          foreach (subterm; multiple_sub_terms) {
            topics ~= m.captures.pre ~ mkup.sep ~ subterm;
          }
        } else {
          topics ~= topics_tmp;
        }
      }
      // writeln("--> ", topics);
      _struct_composite.meta.classify_topic_register_arr = topics;
    }
  }
}
if ("date" in _yaml
  && _yaml["date"].type.sequence
) {
  if (_yaml["date"].type.mapping
    && _yaml["date"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("added_to_site" in _yaml["date"]
      && _yaml["date"]["added_to_site"].type.string
      && _yaml["date"]["added_to_site"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.date_added_to_site = _yaml["date"]["added_to_site"].get!string;
    }
    if ("available" in _yaml["date"]
      && _yaml["date"]["available"].type.string
      && _yaml["date"]["available"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.date_available = _yaml["date"]["available"].get!string;
    }
    if ("created" in _yaml["date"]
      && _yaml["date"]["created"].type.string
      && _yaml["date"]["created"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.date_created = _yaml["date"]["created"].get!string;
    }
    if ("issued" in _yaml["date"]
      && _yaml["date"]["issued"].type.string
      && _yaml["date"]["issued"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.date_issued = _yaml["date"]["issued"].get!string;
    }
    if ("modified" in _yaml["date"]
      && _yaml["date"]["modified"].type.string
      && _yaml["date"]["modified"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.date_modified = _yaml["date"]["modified"].get!string;
    }
    if ("published" in _yaml["date"]
      && _yaml["date"]["published"].type.string
      && _yaml["date"]["published"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.date_published = _yaml["date"]["published"].get!string;
    }
    if ("valid" in _yaml["date"]
      && _yaml["date"]["valid"].type.string
      && _yaml["date"]["valid"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.date_valid = _yaml["date"]["valid"].get!string;
    }
  }
}
_struct_composite.meta.language_document_char = _manifested.src.language; // move
if ("links" in _yaml) {
  // if ("" in _yaml["links"]) {
  //   _struct_composite.meta.links_ = _yaml["links"][""].str;
  // }
}
if ("notes" in _yaml
  && _yaml["notes"].type.sequence
) {
  if (_yaml["notes"].type.mapping
    && _yaml["notes"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("abstract" in _yaml["notes"]
      && _yaml["notes"]["abstract"].type.string
      && _yaml["notes"]["abstract"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.notes_abstract = _yaml["notes"]["abstract"].get!string;
    }
    if ("description" in _yaml["notes"]
      && _yaml["notes"]["description"].type.string
      && _yaml["notes"]["description"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.notes_description = _yaml["notes"]["description"].get!string;
    }
    if ("summary" in _yaml["notes"]
      && _yaml["notes"]["summary"].type.string
      && _yaml["notes"]["summary"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.notes_summary = _yaml["notes"]["summary"].get!string;
    }
  }
}
if ("original" in _yaml
  && _yaml["original"].type.sequence
) {
  if (_yaml["original"].type.mapping
    && _yaml["original"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("language" in _yaml["original"]
      && _yaml["original"]["language"].type.string
      && _yaml["original"]["language"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.original_language = _yaml["original"]["language"].get!string;
    }
    if ("language_char" in _yaml["original"]
      && _yaml["original"]["language_char"].type.string
      && _yaml["original"]["language_char"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.original_language_char = _yaml["original"]["language_char"].get!string;
    }
    if ("source" in _yaml["original"]
      && _yaml["original"]["source"].type.string
      && _yaml["original"]["source"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.original_source = _yaml["original"]["source"].get!string;
    }
    if ("title" in _yaml["original"]
      && _yaml["original"]["title"].type.string
      && _yaml["original"]["title"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.original_title = _yaml["original"]["title"].get!string;
    }
  }
}
if ("publisher" in _yaml) {
  // if ("" in _yaml["publisher"]) {
  //   _struct_composite.meta.publisher = _yaml["publisher"][""].str;
  // }
}
if ("rights" in _yaml
  && _yaml["rights"].type.sequence
) {
  if (_yaml["rights"].type.mapping
    && _yaml["rights"].tag.match(rgx.yaml_tag_is_map)
  ) {
    if ("copyright" in _yaml["rights"]
      && _yaml["rights"]["copyright"].type.string
      && _yaml["rights"]["copyright"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_copyright = _yaml["rights"]["copyright"].get!string;
    }
    if ("copyright_text" in _yaml["rights"]
      && _yaml["rights"]["copyright_text"].type.string
      && _yaml["rights"]["copyright_text"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_copyright_text = _yaml["rights"]["copyright_text"].get!string;
    }
    if ("copyright_audio" in _yaml["rights"]
      && _yaml["rights"]["copyright_audio"].type.string
      && _yaml["rights"]["copyright_audio"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_copyright_audio = _yaml["rights"]["copyright_audio"].get!string;
    }
    if ("copyright_cover" in _yaml["rights"]
      && _yaml["rights"]["copyright_cover"].type.string
      && _yaml["rights"]["copyright_cover"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_copyright_cover = _yaml["rights"]["copyright_cover"].get!string;
    }
    if ("copyright_illustrations" in _yaml["rights"]
      && _yaml["rights"]["copyright_illustrations"].type.string
      && _yaml["rights"]["copyright_illustrations"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_copyright_illustrations = _yaml["rights"]["copyright_illustrations"].get!string;
    }
    if ("copyright_photographs" in _yaml["rights"]
      && _yaml["rights"]["copyright_photographs"].type.string
      && _yaml["rights"]["copyright_photographs"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_copyright_photographs = _yaml["rights"]["copyright_photographs"].get!string;
    }
    if ("copyright_translation" in _yaml["rights"]
      && _yaml["rights"]["copyright_translation"].type.string
      && _yaml["rights"]["copyright_translation"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_copyright_translation = _yaml["rights"]["copyright_translation"].get!string;
    }
    if ("copyright_video" in _yaml["rights"]
      && _yaml["rights"]["copyright_video"].type.string
      && _yaml["rights"]["copyright_video"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_copyright_video = _yaml["rights"]["copyright_video"].get!string;
    }
    if ("license" in _yaml["rights"]
      && _yaml["rights"]["license"].type.string
      && _yaml["rights"]["license"].tag.match(rgx.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_license = _yaml["rights"]["license"].get!string;
    }
  }
}
#+END_SRC

* 1. JSON to spineStruct                         :module:conf_make_meta:json:
** _module template_

#+BEGIN_SRC d :tangle "../src/doc_reform/meta/conf_make_meta_json.d"
/++
  json headers<BR>
  extract json header return json
+/
module doc_reform.meta.conf_make_meta_json;
static template contentJSONtoSpineStruct() {
  import
    std.algorithm,
    std.array,
    std.exception,
    std.regex,
    std.stdio,
    std.string,
    std.typecons,
    std.utf,
    std.conv : to;
  import
    doc_reform.meta.conf_make_meta_structs,
    doc_reform.meta.conf_make_meta_json,
    doc_reform.meta.defaults,
    doc_reform.meta.rgx;
  ConfComposite _struct_composite;
  @safe auto contentJSONtoSpineStruct(C,J,M)(C _struct_composite, J _json, M _manifested, string _identifier) {
    mixin spineRgxIn;
    static auto rgx = RgxI();
    debug (json) {
      writeln(">> --------------------------- >>");
      foreach (tag0; _json.object.byKeyValue) {
        if (tag0.value.stringof == "string") {
          writeln(tag0.key, ": ", tag0.value);
        } else {
          // writeln(tag0.key, ":");
          foreach (tag1; tag0.value.object.byKeyValue) {
            writeln(tag0.key, ":", tag1.key, ": ", tag1.value);
          }
        }
      }
      writeln("<< --------------------------- <<");
    }
    confCompositeMakeBuild _mk;
    <<json_objects_0>>
    <<json_objects_1>>
    <<json_objects_2>>
    return _struct_composite;
  }
}
#+END_SRC

**  make

#+NAME: json_objects_0
#+BEGIN_SRC d
/+ make ------------------------------------------------------------------- +/
if ("make" in _json.object) {
  if ("bold" in _json.object["make"]
    && (_json.object["make"]["bold"].type().to!string == "string")
  ) {
    _struct_composite.make_str.bold = _json.object["make"]["bold"].str;
  }
  if ("breaks" in _json.object["make"]
    && (_json.object["make"]["breaks"].type().to!string == "string")
  ) {
    _struct_composite.make_str.breaks = _json.object["make"]["breaks"].str;
  }
  if ("cover_image" in _json.object["make"]
    && (_json.object["make"]["cover_image"].type().to!string == "string")
  ) {
    _struct_composite.make_str.cover_image = _json.object["make"]["cover_image"].str;
  }
  if ("css" in _json.object["make"]
    && (_json.object["make"]["css"].type().to!string == "string")
  ) {
    _struct_composite.make_str.css = _json.object["make"]["css"].str;
  }
  if ("emphasis" in _json.object["make"]
    && (_json.object["make"]["emphasis"].type().to!string == "string")
  ) {
    _struct_composite.make_str.emphasis = _json.object["make"]["emphasis"].str;
  }
  if ("footer" in _json.object["make"]) {
    if (_json.object["make"]["footer"].type().to!string == "string") {
      char[][] __match_footer_array
        = (cast(char[]) _json.object["make"]["footer"].str)
          .split(rgx.make_heading_delimiter);
      _struct_composite.make_str.footer = __match_footer_array.to!(string[]);
    } else if (_json.object["make"]["footer"].type().to!string == "array") {
      string[] _match_footer_array;
      foreach (_match_heading; _json.object["make"]["footer"].arrayNoRef) {
        _match_footer_array ~= _match_heading.str;
      }
      _struct_composite.make_str.footer = _match_footer_array;
    }
  }
  if ("headings" in _json.object["make"]) {
    if (_json.object["make"]["headings"].type().to!string == "string") {
     char[][] __match_headings_array
        = (cast(char[]) _json.object["make"]["headings"].str)
          .split(rgx.make_heading_delimiter);
      _struct_composite.make_str.headings = __match_headings_array.to!(string[]);
    } else if (_json.object["make"]["headings"].type().to!string == "array") {
      string[] _match_headings_array;
      foreach (_match_heading; _json.object["make"]["headings"].arrayNoRef) {
        _match_headings_array ~= _match_heading.str;
      }
      _struct_composite.make_str.headings = _match_headings_array;
    }
  }
  if ("home_button_image" in _json.object["make"]) {
    if (_json.object["make"]["home_button_image"].type().to!string == "string") {
     char[][] __match_home_button_image_array
        = (cast(char[]) _json.object["make"]["home_button_image"].str)
          .split(rgx.make_heading_delimiter);
      _struct_composite.make_str.home_button_image = __match_home_button_image_array.to!(string[]);
    } else if (_json.object["make"]["home_button_image"].type().to!string == "array") {
      string[] _match_home_button_image_array;
      foreach (_match_heading; _json.object["make"]["home_button_image"].arrayNoRef) {
        _match_home_button_image_array ~= _match_heading.str;
      }
      _struct_composite.make_str.home_button_image = _match_home_button_image_array;
    }
  }
  if ("home_button_text" in _json.object["make"]) {
    if (_json.object["make"]["home_button_text"].type().to!string == "string") {
      _struct_composite.make_str.home_button_text = _json.object["make"]["home_button_text"].str;
    } else if (_json.object["make"]["home_button_text"].type().to!string == "array") {
      string[] _match_home_button_text_array;
      foreach (_match_heading; _json.object["make"]["home_button_text"].arrayNoRef) {
        _match_home_button_text_array ~= _match_heading.str;
      }
      string _match_home_button_text_str = (_match_home_button_text_array).join("; ");
      _struct_composite.make_str.home_button_text = _match_home_button_text_str;
    }
  }
  if ("italics" in _json.object["make"]
    && (_json.object["make"]["italics"].type().to!string == "string")
  ) {
    _struct_composite.make_str.italics = _json.object["make"]["italics"].str;
  }
  if ("auto_num_top_at_level" in _json.object["make"] // str == A - D, 1 - 4
    && (_json.object["make"]["auto_num_top_at_level"].type().to!string == "string")
  ) {
    _struct_composite.make_str.auto_num_top_at_level = _json.object["make"]["auto_num_top_at_level"].str;
    switch (_json.object["make"]["auto_num_top_at_level"].str) {
    case "A":
      break;
    case "B": _struct_composite.make_str.auto_num_top_lv = 1;
      break;
    case "C": _struct_composite.make_str.auto_num_top_lv = 2;
      break;
    case "D": _struct_composite.make_str.auto_num_top_lv = 3;
      break;
    case "1": _struct_composite.make_str.auto_num_top_lv = 4;
      break;
    case "2": _struct_composite.make_str.auto_num_top_lv = 5;
      break;
    case "3": _struct_composite.make_str.auto_num_top_lv = 6;
      break;
    case "4": _struct_composite.make_str.auto_num_top_lv = 7;
      break;
    default:
      break;
    }
  }
  if ("auto_num_depth" in _json.object["make"]) {
    if (_json.object["make"]["auto_num_depth"].type().to!string == "int") { // TODO watch this match
      _struct_composite.make_str.auto_num_depth = _json.object["make"]["auto_num_depth"].integer.to!int;
    } else if (_json.object["make"]["auto_num_depth"].type().to!string == "string") {
      _struct_composite.make_str.auto_num_depth = _json.object["make"]["auto_num_depth"].str.to!int;
    }
  }
  if ("substitute" in _json.object["make"]) {
    string[][] _sub;
    if (_json.object["make"]["substitute"].type().to!string == "array") {
      if (_json.object["make"]["substitute"][0].type().to!string == "array") {
        foreach (substitute_pair; _json.object["make"]["substitute"].arrayNoRef) {
          if ((substitute_pair.type().to!string) == "array") {
            if (!empty(substitute_pair[0].str) && !empty(substitute_pair[1].str)) {
              _sub ~= [ substitute_pair[0].str,  substitute_pair[1].str];
            }
          }
        }
      } else if (_json.object["make"]["substitute"][0].type().to!string == "string") {
         if (!empty(_json.object["make"]["substitute"][0].str) && !empty(_json.object["make"]["substitute"][1].str)) {
           _sub = [[_json.object["make"]["substitute"][0].str, _json.object["make"]["substitute"][1].str]];
         }
      }
    }
    // writeln(_sub);
    _struct_composite.make_str.substitute  = _sub;
  }
  if ("texpdf_font" in _json.object["make"]
    && (_json.object["make"]["texpdf_font"].type().to!string == "string")
  ) {
    _struct_composite.make_str.texpdf_font  = _json.object["make"]["texpdf_font"].str;
  }
  _struct_composite.make.bold                     = _mk.bold(_struct_composite.make_str.bold);
  _struct_composite.make.breaks                   = _mk.breaks(_struct_composite.make_str.breaks);
  _struct_composite.make.cover_image              = _mk.cover_image(_struct_composite.make_str.cover_image);
  _struct_composite.make.css                      = _mk.css(_struct_composite.make_str.css);
  _struct_composite.make.emphasis                 = _mk.emphasis(_struct_composite.make_str.emphasis);
  _struct_composite.make.footer                   = _mk.footer(_struct_composite.make_str.footer);
  _struct_composite.make.headings                 = _mk.headings(_struct_composite.make_str.headings);
  _struct_composite.make.home_button_image        = _mk.home_button_image(_struct_composite.make_str.home_button_image);
  _struct_composite.make.home_button_text         = _mk.home_button_text(_struct_composite.make_str.home_button_text);
  _struct_composite.make.italics                  = _mk.italics(_struct_composite.make_str.italics);
  _struct_composite.make.auto_num_top_at_level    = _mk.auto_num_top_at_level(_struct_composite.make_str.auto_num_top_at_level);
  _struct_composite.make.auto_num_top_lv          = _mk.auto_num_top_lv(_struct_composite.make_str.auto_num_top_lv);
  _struct_composite.make.auto_num_depth           = _mk.auto_num_depth(_struct_composite.make_str.auto_num_depth);
  _struct_composite.make.substitute               = _mk.substitute(_struct_composite.make_str.substitute);
  _struct_composite.make.texpdf_font              = _mk.texpdf_font(_struct_composite.make_str.texpdf_font);
}
#+END_SRC

**  conf

#+NAME: json_objects_1
#+BEGIN_SRC d
/+ conf ------------------------------------------------------------------- +/
if ("webserv" in _json.object) {
  if ("data_root_url" in _json.object["webserv"]
    && (_json.object["webserv"]["data_root_url"].type().to!string == "string")
  ) {
    _struct_composite.conf.w_srv_data_root_url = _json.object["webserv"]["data_root_url"].str;
    if (auto m = _struct_composite.conf.w_srv_data_root_url.match(rgx.webserv_data_root_url)) {
      _struct_composite.conf.w_srv_url_domain = m.captures[2].to!string;
      _struct_composite.conf.w_srv_url_doc_path = m.captures[3].to!string;
    }
  }
  if ("images" in _json.object["webserv"]
    && (_json.object["webserv"]["images"].type().to!string == "string")
  ) {
    _struct_composite.conf.w_srv_images = _json.object["webserv"]["images"].str;
  }
  if ("cgi" in _json.object["webserv"]
    && (_json.object["webserv"]["cgi"].type().to!string == "string")
  ) {
    _struct_composite.conf.w_srv_cgi = _json.object["webserv"]["cgi"].str;
  }
  if ("cgi_host" in _json.object["webserv"]
    && (_json.object["webserv"]["cgi_host"].type().to!string == "string")
  ) {
    _struct_composite.conf.w_srv_cgi_host = _json.object["webserv"]["cgi_host"].str;
  }
  if ("cgi_host_path" in _json.object["webserv"]
    && (_json.object["webserv"]["cgi_host_path"].type().to!string == "string")
  ) {
    _struct_composite.conf.w_srv_cgi_host_path = _json.object["webserv"]["cgi_host_path"].str;
  }
  if ("cgi_port" in _json.object["webserv"]
    && (_json.object["webserv"]["cgi_port"].type().to!string == "string")
  ) {
    _struct_composite.conf.w_srv_cgi_port = _json.object["webserv"]["cgi_port"].str;
  }
  if ("cgi_user" in _json.object["webserv"]
    && (_json.object["webserv"]["cgi_user"].type().to!string == "string")
  ) {
    _struct_composite.conf.w_srv_cgi_user = _json.object["webserv"]["cgi_user"].str;
  }
  if ("cgi_file_links" in _json.object["webserv"]
    && (_json.object["webserv"]["cgi_file_links"].type().to!string == "string")
  ) {
    _struct_composite.conf.w_srv_cgi_file_links = _json.object["webserv"]["cgi_file_links"].str;
  }
}
if ("processing" in _json.object) {
  if ("path" in _json.object["processing"]
    && (_json.object["processing"]["path"].type().to!string == "string")
  ) {
    _struct_composite.conf.processing_path = _json.object["processing"]["path"].str;
  }
  if ("dir" in _json.object["processing"]
    && (_json.object["processing"]["dir"].type().to!string == "string")
  ) {
    _struct_composite.conf.processing_dir = _json.object["processing"]["dir"].str;
  }
  if ("concord_max" in _json.object["processing"]
    && (_json.object["processing"]["concord_max"].type().to!string == "string")
  ) {
    _struct_composite.conf.processing_concord_max = _json.object["processing"]["concord_max"].str;
  }
}
if ("flag" in _json.object) {
  if ("act0" in _json.object["flag"]
    && (_json.object["flag"]["act0"].type().to!string == "string")
  ) {
    _struct_composite.conf.flag_act0 = _json.object["flag"]["act0"].str;
  }
  if ("act1" in _json.object["flag"]
    && (_json.object["flag"]["act1"].type().to!string == "string")
  ) {
    _struct_composite.conf.flag_act1 = _json.object["flag"]["act1"].str;
  }
  if ("act2" in _json.object["flag"]
    && (_json.object["flag"]["act2"].type().to!string == "string")
  ) {
    _struct_composite.conf.flag_act2 = _json.object["flag"]["act2"].str;
  }
  if ("act3" in _json.object["flag"]
    && (_json.object["flag"]["act3"].type().to!string == "string")
  ) {
    _struct_composite.conf.flag_act3 = _json.object["flag"]["act3"].str;
  }
  if ("act4" in _json.object["flag"]
    && (_json.object["flag"]["act4"].type().to!string == "string")
  ) {
    _struct_composite.conf.flag_act4 = _json.object["flag"]["act4"].str;
  }
  if ("act5" in _json.object["flag"]
    && (_json.object["flag"]["act5"].type().to!string == "string")
  ) {
    _struct_composite.conf.flag_act5 = _json.object["flag"]["act5"].str;
  }
  if ("act6" in _json.object["flag"]
    && (_json.object["flag"]["act6"].type().to!string == "string")
  ) {
    _struct_composite.conf.flag_act6 = _json.object["flag"]["act6"].str;
  }
  if ("act7" in _json.object["flag"]
    && (_json.object["flag"]["act7"].type().to!string == "string")
  ) {
    _struct_composite.conf.flag_act7 = _json.object["flag"]["act7"].str;
  }
  if ("act8" in _json.object["flag"]
    && (_json.object["flag"]["act8"].type().to!string == "string")
  ) {
    _struct_composite.conf.flag_act8 = _json.object["flag"]["act8"].str;
  }
  if ("act9" in _json.object["flag"]
    && (_json.object["flag"]["act9"].type().to!string == "string")
  ) {
    _struct_composite.conf.flag_act9 = _json.object["flag"]["act9"].str;
  }
}
if ("default" in _json.object) {
  if ("papersize" in _json.object["default"]
    && (_json.object["default"]["papersize"].type().to!string == "string")
  ) {
    _struct_composite.conf.set_papersize = _json.object["default"]["papersize"].str;
  }
  if ("text_wrap" in _json.object["default"]
    && (_json.object["default"]["text_wrap"].type().to!string == "string")
  ) {
    _struct_composite.conf.set_text_wrap = _json.object["default"]["text_wrap"].str;
  }
  if ("emphasis" in _json.object["default"]
    && (_json.object["default"]["emphasis"].type().to!string == "string")
  ) {
    _struct_composite.conf.set_emphasis = _json.object["default"]["emphasis"].str;
  }
  if ("language" in _json.object["default"]
    && (_json.object["default"]["language"].type().to!string == "string")
  ) {
    _struct_composite.conf.set_language = _json.object["default"]["language"].str;
  }
  if ("digest" in _json.object["default"]
    && (_json.object["default"]["digest"].type().to!string == "string")
  ) {
    _struct_composite.conf.set_digest = _json.object["default"]["digest"].str;
  }
}
if ("search" in _json.object) {
  if ("flag" in _json.object["search"]
    && (_json.object["search"]["flag"].type().to!string == "string")
  ) {
    _struct_composite.conf.search_flag = _json.object["search"]["flag"].str;
  }
  if ("action" in _json.object["search"]
    && (_json.object["search"]["action"].type().to!string == "string")
  ) {
    _struct_composite.conf.search_action = _json.object["search"]["action"].str;
  }
  if ("db" in _json.object["search"]
    && (_json.object["search"]["db"].type().to!string == "string")
  ) {
    _struct_composite.conf.search_db = _json.object["search"]["db"].str;
  }
  if ("title" in _json.object["search"]
    && (_json.object["search"]["title"].type().to!string == "string")
  ) {
    _struct_composite.conf.search_title = _json.object["search"]["title"].str;
  }
}
#+END_SRC

**  meta

#+NAME: json_objects_2
#+BEGIN_SRC d
/+ meta ------------------------------------------------------------------- +/
if (_struct_composite.meta.creator_author.empty) {
  if ("creator" in _json.object) {
    if ("author" in _json.object["creator"]
      && (_json.object["creator"]["author"].type().to!string == "string")
    ) {
      _struct_composite.meta.creator_author = _json.object["creator"]["author"].str;
    }
    if ("email" in _json.object["creator"]
      && (_json.object["creator"]["email"].type().to!string == "string")
    ) {
      _struct_composite.meta.creator_author_email = _json.object["creator"]["email"].str;
    }
    if ("illustrator" in _json.object["creator"]
      && (_json.object["creator"]["illustrator"].type().to!string == "string")
    ) {
      _struct_composite.meta.creator_illustrator = _json.object["creator"]["illustrator"].str;
    }
    if ("translator" in _json.object["creator"]
      && (_json.object["creator"]["translator"].type().to!string == "string")
    ) {
      _struct_composite.meta.creator_translator = _json.object["creator"]["translator"].str;
    }
  }
  string[] author_arr;
  string[][string] authors_hash_arr = [ "first" : [], "last" : [], "full" : [], "last_first" : [], "as_input" : [] ];
  string[] authors_raw_arr
    = _struct_composite.meta.creator_author.split(rgx.arr_delimiter);
  auto _lastname = appender!(char[])();
  foreach (author_raw; authors_raw_arr) {
    if (auto m = author_raw.match(rgx.raw_author_munge)) {
      author_arr                   ~= author_raw.replace(rgx.raw_author_munge, "$2 $1");
      authors_hash_arr["first"]    ~= author_raw.replace(rgx.raw_author_munge, "$2");
      authors_hash_arr["last"]     ~= author_raw.replace(rgx.raw_author_munge, "$1");
      authors_hash_arr["full"]     ~= author_raw.replace(rgx.raw_author_munge, "$2 $1");
      (m.captures[1]).map!toUpper.copy(_lastname);
      authors_hash_arr["last_first"] ~= _lastname.data.to!string ~ ", " ~ m.captures[2];
      _lastname = appender!(char[])();
    } {
      author_arr                     ~= author_raw;
      authors_hash_arr["last"]       ~= author_raw;
      authors_hash_arr["full"]       ~= author_raw;
      authors_hash_arr["last_first"] ~= author_raw;
    }
    authors_hash_arr["as_input"] ~= author_raw;
  }
  _struct_composite.meta.creator_author_arr = author_arr;
  _struct_composite.meta.creator_author     = author_arr.join(", ").chomp.chomp;
  _struct_composite.meta.creator_author_surname = (authors_hash_arr["last"].length > 0) ? authors_hash_arr["last"][0] : "";
  string _author_name_last_first = authors_hash_arr["last_first"].join("; ").chomp.chomp;
  _struct_composite.meta.creator_author_surname_fn = (_author_name_last_first.length > 0)
  ? _author_name_last_first
  : authors_hash_arr["as_input"].join("; ").chomp.chomp;
}
if (_struct_composite.meta.title_main.empty) {
  if ("title" in _json.object) {
    if ((_json.object["title"].type().to!string) == "string") {
      _struct_composite.meta.title_main = _json.object["title"].str;
    } else {
      if ("edition" in _json.object["title"]
        && (_json.object["title"]["edition"].type().to!string == "string")
      ) {
        _struct_composite.meta.title_edition = _json.object["title"]["edition"].str;
      }
      if ("full" in _json.object["title"]
        && (_json.object["title"]["full"].type().to!string == "string")
      ) {}
      if ("language" in _json.object["title"]
        && (_json.object["title"]["language"].type().to!string == "string")
      ) {
        _struct_composite.meta.title_language = _json.object["title"]["language"].str;
      }
      if ("main" in _json.object["title"]
        && (_json.object["title"]["main"].type().to!string == "string")
      ) {
        _struct_composite.meta.title_main = _json.object["title"]["main"].str;
      } else if ("title" in _json.object["title"]
        && (_json.object["title"]["title"].type().to!string == "string")
      ) {
        _struct_composite.meta.title_main = _json.object["title"]["title"].str;
      }
      if ("note" in _json.object["title"]
        && (_json.object["title"]["note"].type().to!string == "string")
      ) {
        _struct_composite.meta.title_note = _json.object["title"]["note"].str;
      }
      if ("sub" in _json.object["title"]
        && (_json.object["title"]["sub"].type().to!string == "string")
      ) {
        _struct_composite.meta.title_sub = _json.object["title"]["sub"].str;
      }
      if ("subtitle" in _json.object["title"]
        && (_json.object["title"]["subtitle"].type().to!string == "string")
      ) {
        _struct_composite.meta.title_subtitle = _json.object["title"]["subtitle"].str;
      }
    }
  }
  if ((!(_struct_composite.meta.title_subtitle.empty))
  && (_struct_composite.meta.title_sub.empty)) {
    _struct_composite.meta.title_sub = _struct_composite.meta.title_subtitle;
  }
  _struct_composite.meta.title_full = (_struct_composite.meta.title_sub.empty)
  ? _struct_composite.meta.title_main
  : format(
      "%s - %s",
      _struct_composite.meta.title_main,
      _struct_composite.meta.title_sub,
    );
}
if ("classify" in _json.object) {
  if ("dewey" in _json.object["classify"]
    && (_json.object["classify"]["dewey"].type().to!string == "string")
  ) {
    _struct_composite.meta.classify_dewey = _json.object["classify"]["dewey"].str;
  }
  if ("keywords" in _json.object["classify"]
    && (_json.object["classify"]["keywords"].type().to!string == "string")
  ) {
    _struct_composite.meta.classify_keywords = _json.object["classify"]["keywords"].str;
  }
  if ("loc" in _json.object["classify"]
    && (_json.object["classify"]["loc"].type().to!string == "string")
  ) {
    _struct_composite.meta.classify_loc = _json.object["classify"]["loc"].str;
  }
  if ("subject" in _json.object["classify"]
    && (_json.object["classify"]["subject"].type().to!string == "string")
  ) {
    _struct_composite.meta.classify_subject = _json.object["classify"]["subject"].str;
  }
  if ("topic_register" in _json.object["classify"]
    && (_json.object["classify"]["topic_register"].type().to!string == "string")
  ) {
    _struct_composite.meta.classify_topic_register = _json.object["classify"]["topic_register"].str.strip;
    string[] main_topics_ = _struct_composite.meta.classify_topic_register.strip.split(rgx.topic_register_main_terms_split);
    string[] topics;
    string   topics_tmp;
    string[] multiple_sub_terms;
    foreach (mt; main_topics_) {
      topics_tmp = mt.replaceAll(rgx.topic_register_main_term_plus_rest_split,    mkup.sep);
      if (auto m = topics_tmp.match(rgx.topic_register_multiple_sub_terms_split)) {
        multiple_sub_terms = m.captures[1].split(rgx.topic_register_sub_terms_split);
        foreach (subterm; multiple_sub_terms) {
          topics ~= m.captures.pre ~ mkup.sep ~ subterm;
        }
      } else {
        topics ~= topics_tmp;
      }
    }
    _struct_composite.meta.classify_topic_register_arr = topics;
  }
}
if ("date" in _json.object) {
  if ("added_to_site" in _json.object["date"]
    && (_json.object["date"]["added_to_site"].type().to!string == "string")
  ) {
    _struct_composite.meta.date_added_to_site = _json.object["date"]["added_to_site"].str;
  }
  if ("available" in _json.object["date"]
    && (_json.object["date"]["available"].type().to!string == "string")
  ) {
    _struct_composite.meta.date_available = _json.object["date"]["available"].str;
  }
  if ("created" in _json.object["date"]
    && (_json.object["date"]["created"].type().to!string == "string")
  ) {
    _struct_composite.meta.date_created = _json.object["date"]["created"].str;
  }
  if ("issued" in _json.object["date"]
    && (_json.object["date"]["issued"].type().to!string == "string")
  ) {
    _struct_composite.meta.date_issued = _json.object["date"]["issued"].str;
  }
  if ("modified" in _json.object["date"]
    && (_json.object["date"]["modified"].type().to!string == "string")
  ) {
    _struct_composite.meta.date_modified = _json.object["date"]["modified"].str;
  }
  if ("published" in _json.object["date"]
    && (_json.object["date"]["published"].type().to!string == "string")
  ) {
    _struct_composite.meta.date_published = _json.object["date"]["published"].str;
  }
  if ("valid" in _json.object["date"]
    && (_json.object["date"]["valid"].type().to!string == "string")
  ) {
    _struct_composite.meta.date_valid = _json.object["date"]["valid"].str;
  }
  _struct_composite.meta.language_document_char = _manifested.src.language;
}
if ("links" in _json.object) {}
if ("notes" in _json.object) {
  if ("abstract" in _json.object["notes"]
    && (_json.object["notes"]["abstract"].type().to!string == "string")
  ) {
    _struct_composite.meta.notes_abstract = _json.object["notes"]["abstract"].str;
  }
  if ("description" in _json.object["notes"]
    && (_json.object["notes"]["description"].type().to!string == "string")
  ) {
    _struct_composite.meta.notes_description = _json.object["notes"]["description"].str;
  }
}
if ("original" in _json.object) {
  if ("language" in _json.object["original"]
    && (_json.object["original"]["language"].type().to!string == "string")
  ) {
    _struct_composite.meta.original_language = _json.object["original"]["language"].str;
  }
  if ("language_char" in _json.object["original"]
    && (_json.object["original"]["language_char"].type().to!string == "string")
  ) {
    _struct_composite.meta.original_language_char = _json.object["original"]["language_char"].str;
  }
  if ("source" in _json.object["original"]
    && (_json.object["original"]["source"].type().to!string == "string")
  ) {
    _struct_composite.meta.original_source = _json.object["original"]["source"].str;
  }
  if ("title" in _json.object["original"]
    && (_json.object["original"]["title"].type().to!string == "string")
  ) {
    _struct_composite.meta.original_title = _json.object["original"]["title"].str;
  }
}
if ("publisher" in _json.object) {}
if ("rights" in _json.object) {
  if ("copyright" in _json.object["rights"]
    && (_json.object["rights"]["copyright"].type().to!string == "string")
  ) {
    _struct_composite.meta.rights_copyright = _json.object["rights"]["copyright"].str;
  }
  if ("copyright_text" in _json.object["rights"]
    && (_json.object["rights"]["copyright_text"].type().to!string == "string")
  ) {
    _struct_composite.meta.rights_copyright_text = _json.object["rights"]["copyright_text"].str;
  }
  if ("copyright_audio" in _json.object["rights"]
    && (_json.object["rights"]["copyright_audio"].type().to!string == "string")
  ) {
    _struct_composite.meta.rights_copyright_audio = _json.object["rights"]["copyright_audio"].str;
  }
  if ("copyright_cover" in _json.object["rights"]
    && (_json.object["rights"]["copyright_cover"].type().to!string == "string")
  ) {
    _struct_composite.meta.rights_copyright_cover = _json.object["rights"]["copyright_cover"].str;
  }
  if ("copyright_illustrations" in _json.object["rights"]
    && (_json.object["rights"]["copyright_illustrations"].type().to!string == "string")
  ) {
    _struct_composite.meta.rights_copyright_illustrations = _json.object["rights"]["copyright_illustrations"].str;
  }
  if ("copyright_photographs" in _json.object["rights"]
    && (_json.object["rights"]["copyright_photographs"].type().to!string == "string")
  ) {
    _struct_composite.meta.rights_copyright_photographs = _json.object["rights"]["copyright_photographs"].str;
  }
  if ("copyright_translation" in _json.object["rights"]
    && (_json.object["rights"]["copyright_translation"].type().to!string == "string")
  ) {
    _struct_composite.meta.rights_copyright_translation = _json.object["rights"]["copyright_translation"].str;
  }
  if ("copyright_video" in _json.object["rights"]
    && (_json.object["rights"]["copyright_video"].type().to!string == "string")
  ) {
    _struct_composite.meta.rights_copyright_video = _json.object["rights"]["copyright_video"].str;
  }
  if ("license" in _json.object["rights"]
    && (_json.object["rights"]["license"].type().to!string == "string")
  ) {
    _struct_composite.meta.rights_license = _json.object["rights"]["license"].str;
  }
}
#+END_SRC

** 1. parse Yaml config return spineStruct

#+BEGIN_SRC d :tangle "../src/doc_reform/meta/conf_make_meta_yaml.d"
template configParseYAMLreturnSpineStruct() {
  import dyaml;
  import
    doc_reform.meta.conf_make_meta_structs,
    doc_reform.meta.conf_make_meta_json;
  mixin contentYAMLtoSpineStruct;
  @system auto configParseYAMLreturnSpineStruct(T,CCm,M,O)(
    T       _document_struct,
    CCm     _make_and_meta_struct,
    M       _manifested,
    O       _opt_action
  ){
    Node _yaml;
    if (_document_struct.content.length > 0) {
      try {
        _yaml = Loader.fromString(_document_struct.content).load();
      } catch (Throwable) {
        import std.stdio;
        writeln("ERROR failed to parse content as yaml: ", _document_struct.filename);
        // writeln(_document_struct.content);
      }
      try {
      _make_and_meta_struct
        = contentYAMLtoSpineStruct!()(_make_and_meta_struct, _yaml, _manifested, _opt_action, _document_struct.filename);
      } catch (Throwable) {
        import std.stdio;
        writeln("ERROR failed to convert yaml to struct: ", _document_struct.filename);
      }
    }
    return _make_and_meta_struct;
  }
}
#+END_SRC

** 2. parse YAML header to +(JSON then)+ Struct

#+BEGIN_SRC d :tangle "../src/doc_reform/meta/conf_make_meta_yaml.d"
template docHeaderMakeAndMetaTupYamlExtractAndConvertToStruct() {
  import
    std.exception,
    std.regex,
    std.stdio,
    std.traits,
    std.typecons,
    std.utf,
    std.conv : to;
  import
    dyaml;
  import
    doc_reform.meta.conf_make_meta_structs,
    doc_reform.meta.conf_make_meta_json,
    doc_reform.meta.rgx;
  mixin spineRgxIn;
  mixin contentJSONtoSpineStruct;
  static auto rgx = RgxI();
  @system auto docHeaderMakeAndMetaTupYamlExtractAndConvertToStruct(CCm,Src,M,O)(
    Src     header_src,
    CCm     _make_and_meta_struct,
    M       _manifested,
    O       _opt_action,
  ) {
    Node _yaml;
    try {
      _yaml = Loader.fromString(header_src).load();
      if (("title" in _yaml) && ("creator" in _yaml)) {} else { // need test for _yaml content (does not work)
        writeln("ERROR failed to read document header, yaml header does not contain essential information related to title and author");
      }
      return contentYAMLtoSpineStruct!()(_make_and_meta_struct, _yaml, _manifested, _opt_action, "header");
    } catch (Throwable) {
      writeln("ERROR failed to read document header, header not parsed as yaml: ", _manifested.src.filename);
      return _make_and_meta_struct;
    }
  }
}
#+END_SRC

* __END__
** notes headers

#+BEGIN_SRC d
/+
  /+
    unify internal representation of header info for yaml document headers
    represent either using struct, hashes or possibly json
  +/
header.
  ├── make                         // make instructions
  │   ├── bold
  │   ├── breaks
  │   ├── cover_image
  │   ├── css
  │   ├── emphasis
  │   ├── footer
  │   ├── headings
  │   ├── home_button_image
  │   ├── home_button_text
  │   ├── italics
  │   ├── auto_num_top_at_level
  │   ├── 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
+/
#+END_SRC

** dlang rgx example

#+BEGIN_SRC d
import std.conv, std.regex, std.range, std.file, std.stdio;
import std.string : format;
void main(string[] argv) {
  immutable ratio = 1.5824;  // UK pounds to US dollar as of this writing
  auto toDollars(Captures!string price) {
    real value = to!real(price["integer"]);
    if (!price["fraction"].empty)
      value += 0.01*to!real(price["fraction"]);
    return format("$%.2f",value * ratio);
  }
  string text = std.file.readText(argv[1]);
  auto converted = replaceAll!toDollars(text,
    regex(r"£\s*(?P<integer>[0-9]+)(\.(?P<fraction>[0-9]{2}))?","g"));
  write(converted);
}
#+END_SRC