-*- 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 - 2023 Ralph Amissah
#+LANGUAGE:    en
#+STARTUP:     content hideblocks hidestars noindent entitiespretty
#+PROPERTY:    header-args  :noweb yes
#+PROPERTY:    header-args+ :exports code
#+PROPERTY:    header-args+ :results no
#+PROPERTY:    header-args+ :cache no
#+PROPERTY:    header-args+ :padline no
#+PROPERTY:    header-args+ :mkdirp yes
#+OPTIONS:     H:3 num:nil toc:t \n:t ::t |:t ^:nil -:t f:t *:t

#+NAME: meta_check_input_markup
#+BEGIN_SRC d
string check_input_markup()(
  string _txt,
) {
  _txt = _txt
   .replaceAll(regex(r"\\"), mkup.br_line_inline)
   .strip;
  return _txt;
}
#+END_SRC

- [[./doc-reform.org][doc-reform.org]]  [[./][org/]]

* generic
** conf yaml REFERENCE

NOTES on configuration hierarchy:
- compile time program defaults views/configuration.txt in config_d_cfte.org
  - config_d_cfte.org (writes views/configuration.txt)
    - compile time program defaults, set in views/configuration.txt
    - found in: _cfg.*
- run time default configuration administrators config ".dr/config_site_local"
  - in_source_files.org readConfigSite (reads administrators site defaults from
    yaml config file)
  - meta_conf_make_meta.org struct ConfCompositeSiteLocal
    - administrator site defaults read from yaml configuration file
      ".dr/config_site_local"
    - found in: "doc_matters.conf_make_meta.conf." (incorporates _cfg.* as
      initial default values that are overridden if set)
    - ("conf_make_meta.make" (& "conf_make_meta.meta") also available taken from
      document headers)
- command line execution configuration instruction
  - spine.org (org heading: initialize settings) (command line overrides)
    - command line settings/overrides
    - found in: doc_matters.opt.action.*

** table

|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| cfg ctfe                 | config local              | cli                        | cli-run                    | composite                   | default                                 |     |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| _cfg.                    | ["webserv"]               | --                         | opt_action.                | _struct_composite.conf.     | default                                 | ✓ ✗ |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| processing_path_doc_root | ["data_root_path"]        | output                     | output_dir_set             | output_path                 | "/srv/www/spine"                        | ✓   |
|                          |                           |                            |                            |                             | "/var/www"                              |     |
|                          |                           |                            |                            |                             | "/var/www/html"                         |     |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| http_request_type        | ["http"]                  | www-http                   | webserver_http             | w_srv_http                  | "http" or "https"                       | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| www_host                 | ["domain"]                | www-host                   | webserver_host_name        | CHECK                       | "localhost"                             | ✓   |
|                          |                           |                            |                            |                             | "sisudoc"                               |     |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| www_host_doc_root        | [""]                      | www-host-doc-root          | webserver_host_doc_root    | w_srv_data_root_path        |                                         | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| www_url_doc_root?        |                           | www-url-doc-root           |                            |                             | "http://localhost"                      |     |
| CHECK                    |                           |                            |                            |                             | "https://sisudoc.org"                   |     |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| cgi_http                 | [""]                      | cgi-http                   |                            |                             |                                         | ✗   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| cgi_host                 | [""]                      | cgi-host                   |                            |                             |                                         | ✗   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| cgi_bin_root             | ["cgi_bin_path"]          | cgi-bin-root               | cgi_bin_root               | cgi_bin_root                | "/var/www/cgi/cgi-bin"                  | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| cgi_filename             | ["cgi_search_script"]     | cgi-sqlite-search-filename | cgi_sqlite_search_filename | w_srv_cgi_search_script     | "spine_search"                          | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| cgi_url_root             | ["cgi_bin_url"]           | cgi-url-root               | cgi_url_root               |                             | REMOVE UNUSED                           | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| cgi_url_action           | ["cgi_action"]            | cgi-url-action             | cgi_url_action             | w_srv_cgi_action            | "http://localhost/cgi-bin/spine-search" | ✓   |
|                          |                           |                            |                            |                             | "https://sisudoc.org/spine-search"      |     |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| cgi_search_form_title    | ["cgi_search_form_title"] | cgi-search-title           | cgi_search_title           | w_srv_cgi_search_form_title | "≅ SiSU Spine search"                   | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
|                          |                           | config                     |                            |                             |                                         |     |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| default_language         | [""]                      | lang                       | languages_set              |                             | "all" or "en"                           | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| default_papersize        | [""]                      | set-papersize              | latex_papersize            | set_papersize               | "a4"?                                   | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| default_text_wrap        | [""]                      | set-textwrap               | text_wrap                  | set_text_wrap               | 80                                      | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| default_hash_digest      | [""]                      | set-digest                 | hash_digest_type           |                             | sha258                                  | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| db_sqlite_path           | [""]                      | sqlite-db-path             | sqliteDB_path              | w_srv_db_sqlite_path        | "/var/www/sqlite"                       | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
| db_sqlite_filename       | [""]                      | sqlite-db-filename         | sqliteDB_filename          | w_srv_db_sqlite_filename    | "spine_search.db"                       | ✓   |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|
|                          |                           |                            |                            |                             |                                         |     |
|--------------------------+---------------------------+----------------------------+----------------------------+-----------------------------+-----------------------------------------+-----|

** cli flag

#+BEGIN_SRC d
string[string] settings = [
  "output"                      : "",
  "www-http"                    : "",
  "www-host"                    : "",
  "www-host-doc-root"           : "",
  "www-url-doc-root"            : "",
  "cgi-http"                    : "",
  "cgi-host"                    : "",
  "cgi-bin-root"                : "",
  "cgi-sqlite-search-filename"  : "",
  "cgi-url-root"                : "",
  "cgi-url-action"              : "",
  "cgi-search-title"            : "",
  "config"                      : "",
  "lang"                        : "all",
  "set-papersize"               : "",
  "set-textwrap"                : "",
  "set-digest"                  : "",
  "sqlite-db-path"              : "",
  "sqlite-db-filename"          : "",
];
#+END_SRC

** conf build - views/configuration.txt REFERENCE

- see: config_d_cfte.org
  for configuration_example.txt

#+HEADER: :NO-tangle "../views/configuration.txt"
#+BEGIN_SRC d
/+ obt - org-mode generated file +/
struct Cfg {
  string http_request_type        = "http";
  string http_host                = "localhost";
  string www_url_doc_root         = "http://localhost";
  string www_url_doc_subroot      = "/spine";
  string processing_path_doc_root = "/srv/www/spine";
  string cgi_bin_root             = "/var/www/cgi/cgi-bin";
  string cgi_bin_subpath          = "/cgi-bin";
  string cgi_filename             = "spine_search";
  string cgi_url_root             = "http://localhost/cgi-bin";
  string cgi_port                 = "";
  string cgi_user                 = "";
  string cgi_url_action           = "http://localhost/cgi-bin/spine_search";
  string cgi_search_form_title    = "≅ SiSU Spine search ፨";
  string db_sqlite_path           = "/var/www/sqlite";
  string db_sqlite_filename       = "spine.search.db";
  string default_language         = "en";
  string default_papersize        = "a4";
  string default_text_wrap        = "80";
  string default_hash_digest      = "sha256";
}
enum _cfg = Cfg();
#+END_SRC

** conf yaml - .dr/config_site_local REFERENCE

#+HEADER: :tangle "../.dr/config_local_site_example"
#+BEGIN_SRC yaml
# config_local_site
# read from directories ... FIX provide list
flag:
  act0:                        "--html"
  act1:                        "--html --epub"
output:
  path:                        "/srv/www/spine"
default:
  language:                    "en"
  papersize:                   "a4"
  text_wrap:                   "80"
  digest:                      "sha256"
webserv:
  http:                        "http"                             # "https"
  domain:                      "localhost"                        # "mysite"
  data_http:                   "https"                            # "http"
  data_domain:                 "localhost"                        # "mysite"
  data_root_url:               "http://localhost"                 # "https://mysite.org"
  data_root_path:              "/srv/www/spine"                   # "/var/www/html"
  data_root_part:              ""                                 # "/spine"
  images_root_part:            "image"
  cgi_search_form_title:       "≅ SiSU Spine search ፨"
  cgi_http:                    "http"                             # "https"
  cgi_domain:                  "localhost"                        # "mysite.org"
  cgi_bin_url:                 "http://localhost/cgi-bin"         # "https://mysite.org/cgi-bin"
  cgi_bin_part:                "cgi-bin"
  cgi_bin_path:                "/var/www/cgi/cgi-bin"             # "/usr/lib/cgi-bin"
  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" # "https://mysite.org/spine_search"
  db_sqlite_filename:          "spine.search.db"
  db_sqlite_path:              "/var/www/sqlite"
  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

#+HEADER: :tangle "../src/doc_reform/meta/conf_make_meta_structs.d"
#+HEADER: :noweb yes
#+BEGIN_SRC d
<<doc_header_including_copyright_and_license>>
module doc_reform.meta.conf_make_meta_structs;
<<meta_defaults_template_structs_init>>
<<meta_defaults_template_structs_setup>>
<<meta_defaults_template_structs_composite_make_init>>
<<meta_defaults_template_structs_conf_composite_site_local>>
<<meta_defaults_template_structs_meta_composite>>
<<meta_defaults_template_structs_conf_composite>>
<<meta_defaults_template_structs_json>>
#+END_SRC

** initialize, imports etc.

#+NAME: meta_defaults_template_structs_init
#+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_yaml,
  doc_reform.meta.rgx;
mixin spineRgxIn;
static auto rgx = RgxI();
mixin spineRgxYamlTags;
static auto rgx_y = RgxYaml();
mixin InternalMarkup;
static auto mkup = InlineMarkup();
#+END_SRC

** struct Generic ConfComposite

#+NAME: meta_defaults_template_structs_setup
#+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     doc_type = "book"; // book, article
  string     breaks;
  string     bold;
  string     cover_image;
  string     css;
  string     emphasis;
  string[]   footer;
  string[]   headings;
  string[]   home_button_image;
  string     home_button_text = "┥Spine, Doc Reform┝┤https://www.doc-reform.org├"
    ~ " ┥www.doc-reform.org┝┤https://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 doc_type(string _mk) {
    return _mk;
  }
  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_composite_make_init
#+BEGIN_SRC d
struct ConfCompositeMakeInit {
  string     doc_type;
  string     breaks;
  string     cover_image;
  string     css;
  string[]   bold;
  string[]   emphasis;
  string[]   footer;
  string[]   headings;
  string[]   home_button_image;
  string     home_button_text = "┥Spine, Doc Reform┝┤https://www.doc-reform.org├"
    ~ " ┥www.doc-reform.org┝┤https://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

SEE NOTES on configuration hierarchy in spine.org

#+NAME: meta_defaults_template_structs_conf_composite_site_local
#+BEGIN_SRC d
struct ConfCompositeSiteLocal {
  string   w_srv_http;
  string   w_srv_host;
  string   w_srv_data_http;            // if not set same as webserv_http
  string   w_srv_data_host;            // if not set same as webserv_host
  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_search_form_title;
  string   w_srv_cgi_http;             // if not set same as webserv_http
  string   w_srv_cgi_host;             // if not set same as webserv_host
  string   w_srv_cgi_bin_subpath;
  string   w_srv_cgi_bin_path;
  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_filename;
  string   w_srv_db_sqlite_path;
  // 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_meta_composite
#+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[] classify_topic_register_expanded_arr; // experimental use in sqlite topics table
  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_conf_composite
#+BEGIN_SRC d
struct ConfComposite {
  MetaComposite               meta;
  ConfCompositeMakeInit       make;
  ConfCompositeMakeStr        make_str;
  ConfCompositeSiteLocal      conf;
}
#+END_SRC

*** JSONValue

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

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

#+HEADER: :tangle "../src/doc_reform/meta/conf_make_meta_yaml.d"
#+HEADER: :noweb yes
#+BEGIN_SRC d
<<doc_header_including_copyright_and_license>>
/++
  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_yaml,
    doc_reform.meta.rgx;
  ConfComposite _struct_composite;
  @system auto contentYAMLtoSpineStruct(C,Y,M,O,Cfg)(
    C      _struct_composite,
    Y      _yaml,
    M      _manifested,
    O      _opt_action,
    Cfg    _cfg,
    string _identifier
  ) {
    mixin spineRgxIn;
    static auto rgx = RgxI();
    mixin spineRgxYamlTags;
    static auto rgx_y = RgxYaml();
    <<meta_check_input_markup>>
    confCompositeMakeBuild _mk;
    if (_identifier != "header") { // called only once per run anyway
      <<yaml_objects_conf>>
    } else {
      <<yaml_objects_make>>
      <<yaml_objects_meta>>
    }
    return _struct_composite;
  }
}
<<parse_yaml_return_spineStruct>>
<<doc_header_convert_to_struct>>
#+END_SRC

**  conf

#+NAME: yaml_objects_conf
#+BEGIN_SRC d
/+ conf ------------------------------------------------------------------- +/
/+
 _cfg. build defaults (else program runtime defaults)
 local_site_configuration defaults
 command line overrides
+/
{
  if (_opt_action.webserver_http.length > 0) {
    _struct_composite.conf.w_srv_http
      = _opt_action.webserver_http;
  } else {
    _struct_composite.conf.w_srv_http
      = (_cfg.http_request_type.empty)
        ? "http"
        : _cfg.http_request_type;
    if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
      && (_yaml["webserv"].type.mapping
        && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
    ) {
      if ("http" in _yaml["webserv"]
        && _yaml["webserv"]["http"].type.string
        && _yaml["webserv"]["http"].tag.match(rgx_y.yaml_tag_is_str)
      ) {
        _struct_composite.conf.w_srv_http
          = _yaml["webserv"]["http"].get!string;
      }
    }
  }
  if (_opt_action.cgi_search_title.length > 0) {
    _struct_composite.conf.w_srv_cgi_search_form_title
      = _opt_action.cgi_search_title;
  } else {
    _struct_composite.conf.w_srv_cgi_search_form_title
      = (_cfg.cgi_search_form_title.empty)
        ? "≅ SiSU spine search form"
        : _cfg.cgi_search_form_title;
    if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
      && (_yaml["webserv"].type.mapping
        && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
    ) {
      if ("cgi_search_form_title" in _yaml["webserv"]
        && _yaml["webserv"]["cgi_search_form_title"].type.string
        && _yaml["webserv"]["cgi_search_form_title"].tag.match(rgx_y.yaml_tag_is_str)
      ) {
        _struct_composite.conf.w_srv_cgi_search_form_title
          = _yaml["webserv"]["cgi_search_form_title"].get!string;
      }
    }
  }
  if (_opt_action.cgi_sqlite_search_filename.length > 0) {
    _struct_composite.conf.w_srv_cgi_search_script
      = _opt_action.cgi_sqlite_search_filename;
  } else {
    _struct_composite.conf.w_srv_cgi_search_script
      = (_cfg.cgi_filename.empty)
        ? "spine_search"
        : _cfg.cgi_filename;
    if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
      && (_yaml["webserv"].type.mapping
        && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
    ) {
      if ("cgi_search_script" in _yaml["webserv"]
        && _yaml["webserv"]["cgi_search_script"].type.string
        && _yaml["webserv"]["cgi_search_script"].tag.match(rgx_y.yaml_tag_is_str)
      ) {
        _struct_composite.conf.w_srv_cgi_search_script
          = _yaml["webserv"]["cgi_search_script"].get!string;
      }
    }
  }
  if (_opt_action.sqliteDB_filename.length > 0) {
    _struct_composite.conf.w_srv_db_sqlite_filename
      = _opt_action.sqliteDB_filename;
  } else {
    _struct_composite.conf.w_srv_db_sqlite_filename
      = (_cfg.db_sqlite_filename.empty)
        ?  "spine.search.db"
        : _cfg.db_sqlite_filename;
    if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
      && (_yaml["webserv"].type.mapping
        && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
    ) {
      if ("db_sqlite_filename" in _yaml["webserv"]
        && _yaml["webserv"]["db_sqlite_filename"].type.string
        && _yaml["webserv"]["db_sqlite_filename"].tag.match(rgx_y.yaml_tag_is_str)
      ) {
        _struct_composite.conf.w_srv_db_sqlite_filename
          = _yaml["webserv"]["db_sqlite_filename"].get!string;
      }
    }
  }
  if (_opt_action.sqliteDB_path.length > 0) {
    _struct_composite.conf.w_srv_db_sqlite_path
      = _opt_action.sqliteDB_path;
  } else {
    _struct_composite.conf.w_srv_db_sqlite_path
      = (_cfg.db_sqlite_path.empty)
        ?  "/var/www/sqlite"
        : _cfg.db_sqlite_path;
    if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
      && (_yaml["webserv"].type.mapping
        && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
    ) {
      if ("db_sqlite_path" in _yaml["webserv"]
        && _yaml["webserv"]["db_sqlite_path"].type.string
        && _yaml["webserv"]["db_sqlite_path"].tag.match(rgx_y.yaml_tag_is_str)
      ) {
        _struct_composite.conf.w_srv_db_sqlite_path
          = _yaml["webserv"]["db_sqlite_path"].get!string;
      }
    }
  }
  if (_opt_action.cgi_url_action.length > 0) {
    _struct_composite.conf.w_srv_cgi_action
      = _opt_action.cgi_url_action;
  } else {
    _struct_composite.conf.w_srv_cgi_action
      = (_cfg.www_url_doc_root.empty)
        ?  "http://locahost" // "https://sisudoc.org"
        : _cfg.www_url_doc_root;
    if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
      && (_yaml["webserv"].type.mapping
        && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
    ) {
      if ("cgi_action" in _yaml["webserv"]
        && _yaml["webserv"]["cgi_action"].type.string
        && _yaml["webserv"]["cgi_action"].tag.match(rgx_y.yaml_tag_is_str)
      ) {
        _struct_composite.conf.w_srv_cgi_action
          = _yaml["webserv"]["cgi_action"].get!string;
      } else 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;
      }
    }
  }
  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 {
      _struct_composite.conf.output_path
        = (_cfg.processing_path_doc_root.empty)
          ?  "/srv/www/spine"
          : _cfg.processing_path_doc_root;
      if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
        && (_yaml["webserv"].type.mapping
          && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
      ) {
        if (_yaml["output"].type.mapping
          && _yaml["output"].tag.match(rgx_y.yaml_tag_is_map)
        ) {
          if ("path" in _yaml["output"]
            && _yaml["output"]["path"].type.string
            && _yaml["output"]["path"].tag.match(rgx_y.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 (_opt_action.webserver_host_doc_root.length > 0) { // same as output_path immediately above, resolve FIX REMOVE
      _struct_composite.conf.w_srv_data_root_path
        = _opt_action.webserver_host_doc_root;
    } else {
      _struct_composite.conf.w_srv_data_root_path
        = (_cfg.processing_path_doc_root.empty)
          ? "/var/www/spine"
          : _cfg.processing_path_doc_root;
      if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
        && (_yaml["webserv"].type.mapping
          && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
      ) {
        if ("data_root_path" in _yaml["webserv"]
          && _yaml["webserv"]["data_root_path"].type.string
          && _yaml["webserv"]["data_root_path"].tag.match(rgx_y.yaml_tag_is_str)
        ) {
          _struct_composite.conf.w_srv_data_root_path
            = _yaml["webserv"]["data_root_path"].get!string;
        }
      }
    }
  }
  if (_opt_action.cgi_bin_root.length > 0) {
    _struct_composite.conf.w_srv_cgi_bin_path
      = _opt_action.cgi_bin_root;
  } else {
    _struct_composite.conf.w_srv_cgi_bin_path
      = (_cfg.cgi_bin_root.empty)
        ? "/var/www/cgi/cgi-bin"
        : _cfg.cgi_bin_root;
    if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
      && (_yaml["webserv"].type.mapping
        && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
    ) {
      if ("cgi_bin_path" in _yaml["webserv"]
        && _yaml["webserv"]["cgi_bin_path"].type.string
        && _yaml["webserv"]["cgi_bin_path"].tag.match(rgx_y.yaml_tag_is_str)
      ) {
        _struct_composite.conf.w_srv_cgi_bin_path
          = _yaml["webserv"]["cgi_bin_path"].get!string;
      }
    }
  }
  { _struct_composite.conf.w_srv_data_root_part
      = "";
    if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
      && (_yaml["webserv"].type.mapping
        && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
    ) {
      if ("data_root_part" in _yaml["webserv"]
        && _yaml["webserv"]["data_root_part"].type.string
        && _yaml["webserv"]["data_root_part"].tag.match(rgx_y.yaml_tag_is_str)
      ) {
        _struct_composite.conf.w_srv_data_root_part = _yaml["webserv"]["data_root_part"].get!string;
      }
    }
  }
  { _struct_composite.conf.w_srv_images_root_part
      = "image";
    if (("webserv" in _yaml && _yaml["webserv"].type.sequence)
      && (_yaml["webserv"].type.mapping
        && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
    ) {
      if ("images_root_part" in _yaml["webserv"]
        && _yaml["webserv"]["images_root_part"].type.string
        && _yaml["webserv"]["images_root_part"].tag.match(rgx_y.yaml_tag_is_str)
      ) {
        _struct_composite.conf.w_srv_images_root_part = _yaml["webserv"]["images_root_part"].get!string;
      }
    }
  }
}
if (("webserv" in _yaml
  && _yaml["webserv"].type.sequence)
  && (_yaml["webserv"].type.mapping
    && _yaml["webserv"].tag.match(rgx_y.yaml_tag_is_map))
) { // cannot be used as is with opt_action FIX look at remaining, decide what to do later
    if ("data_http" in _yaml["webserv"]
      && _yaml["webserv"]["data_http"].type.string
      && _yaml["webserv"]["data_http"].tag.match(rgx_y.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_data_http = _yaml["webserv"]["data_http"].get!string;
    }
    // if (_opt_action.*.length > 0) {
    if ("cgi_http" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_http"].type.string
      && _yaml["webserv"]["cgi_http"].tag.match(rgx_y.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_http = _yaml["webserv"]["cgi_http"].get!string;
    }
    // if (_opt_action.*.length > 0) {
    if ("host" in _yaml["webserv"]
      && _yaml["webserv"]["host"].type.string
      && _yaml["webserv"]["host"].tag.match(rgx_y.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_host = _yaml["webserv"]["host"].get!string;
    }
    if ("data_root_url" in _yaml["webserv"]
      && _yaml["webserv"]["data_root_url"].type.string
      && _yaml["webserv"]["data_root_url"].tag.match(rgx_y.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
        ~ _struct_composite.conf.w_srv_data_root_part ~ "/"
        ~ _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_host" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_host"].type.string
      && _yaml["webserv"]["cgi_host"].tag.match(rgx_y.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_host = _yaml["webserv"]["cgi_host"].get!string;
    } else { // composite construct
      _struct_composite.conf.w_srv_cgi_host = _struct_composite.conf.w_srv_host;
    }
    if ("cgi_bin_subpath" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_bin_subpath"].type.string
      && _yaml["webserv"]["cgi_bin_subpath"].tag.match(rgx_y.yaml_tag_is_str)
    ) {
      _struct_composite.conf.w_srv_cgi_bin_subpath = _yaml["webserv"]["cgi_bin_subpath"].get!string;
    }
    if ("cgi_port" in _yaml["webserv"]
      && _yaml["webserv"]["cgi_port"].type.string
      && _yaml["webserv"]["cgi_port"].tag.match(rgx_y.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_y.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_y.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_host.empty)
          ? _struct_composite.conf.w_srv_cgi_host
          : _struct_composite.conf.w_srv_host
        ~ _struct_composite.conf.w_srv_cgi_bin_subpath;
    }
    // if ("cgi_file_links" in _yaml["webserv"]
    //   && _yaml["webserv"]["cgi_file_links"].type.string
    //   && _yaml["webserv"]["cgi_file_links"].tag.match(rgx_y.yaml_tag_is_str)
    // ) {
    //   _struct_composite.conf.w_srv_cgi_file_links = _yaml["webserv"]["cgi_file_links"].get!string;
    // }
}
// make (in: conf, make, meta)?
if ("processing" in _yaml
  && _yaml["processing"].type.sequence
) {
  if (_yaml["processing"].type.mapping
    && _yaml["processing"].tag.match(rgx_y.yaml_tag_is_map)
  ) {
    if ("concord_max" in _yaml["processing"]
      && _yaml["processing"]["concord_max"].type.string
      && _yaml["processing"]["concord_max"].tag.match(rgx_y.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_y.yaml_tag_is_map)
  ) {
    if ("act0" in _yaml["flag"]
      && _yaml["flag"]["act0"].type.string
      && _yaml["flag"]["act0"].tag.match(rgx_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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 "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 "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 "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;
}
string _set_papersize;
if (_opt_action.latex_papersize.length > 0) {
  _set_papersize
    = _opt_action.latex_papersize;
} else {
  _set_papersize
    = (_cfg.default_papersize.empty)
      ? "a4,letter.portrait"
      : _cfg.default_papersize;
  if ("papersize" in _yaml["default"]
    && _yaml["default"]["papersize"].type.string
    && _yaml["default"]["papersize"].tag.match(rgx_y.yaml_tag_is_str)
  ) {
    _set_papersize
      = _yaml["default"]["papersize"].get!string;
  }
}
_struct_composite.conf.set_papersize = selected_papersize(_set_papersize);
if (
  "default" in _yaml
  && _yaml["default"].type.sequence
  && _yaml["default"].type.mapping
  && _yaml["default"].tag.match(rgx_y.yaml_tag_is_map)
) {
  if ("text_wrap" in _yaml["default"]
    && _yaml["default"]["text_wrap"].type.string
    && _yaml["default"]["text_wrap"].tag.match(rgx_y.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_y.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_y.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_y.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_y.yaml_tag_is_map)
  ) {
    if ("flag" in _yaml["search"]
      && _yaml["search"]["flag"].type.string
      && _yaml["search"]["flag"].tag.match(rgx_y.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_y.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_y.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_y.yaml_tag_is_str)
    ) {
      _struct_composite.conf.search_title = _yaml["search"]["title"].get!string;
    }
  }
}
#+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_y.yaml_tag_is_map)
  ) {
    if ("doc_type" in _yaml["make"]
      && _yaml["make"]["doc_type"].type.string
      && _yaml["make"]["doc_type"].tag.match(rgx_y.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.doc_type = _yaml["make"]["doc_type"].get!string;
    }
    if ("breaks" in _yaml["make"]
      && _yaml["make"]["breaks"].type.string
      && _yaml["make"]["breaks"].tag.match(rgx_y.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.breaks = _yaml["make"]["breaks"].get!string;
    }
    if ("bold" in _yaml["make"]
      && _yaml["make"]["bold"].type.string
      && _yaml["make"]["bold"].tag.match(rgx_y.yaml_tag_is_str)
    ) {
      _struct_composite.make_str.bold = _yaml["make"]["bold"].get!string;
    }
    if ("cover_image" in _yaml["make"]
      && _yaml["make"]["cover_image"].type.string
      && _yaml["make"]["cover_image"].tag.match(rgx_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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.doc_type                 = _mk.doc_type(_struct_composite.make_str.doc_type);
  _struct_composite.make.breaks                   = _mk.breaks(_struct_composite.make_str.breaks);
  _struct_composite.make.bold                     = _mk.bold(_struct_composite.make_str.bold);
  _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

**  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_y.yaml_tag_is_map)
    ) {
      if ("author" in _yaml["creator"]
        && _yaml["creator"]["author"].type.string
        && _yaml["creator"]["author"].tag.match(rgx_y.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_y.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_y.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_y.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_y.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_y.yaml_tag_is_map)
    ) {
      if ("main" in _yaml["title"]
        && _yaml["title"]["main"].type.string
        && _yaml["title"]["main"].tag.match(rgx_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.yaml_tag_is_map)
  ) {
    if ("dewey" in _yaml["classify"]
      && _yaml["classify"]["dewey"].type.string
      && _yaml["classify"]["dewey"].tag.match(rgx_y.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_y.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_y.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_y.yaml_tag_is_str)
    ) {
      _struct_composite.meta.classify_topic_register = _yaml["classify"]["topic_register"].get!string;
      if (_struct_composite.meta.classify_topic_register.length > 0) {
        auto wrds = ctRegex!(`([\wa-zA-Z(). -]+)`); // ctRegex!(`([(]?\w+[a-zA-Z(). -]*)+`);
        auto mkp_delim = ctRegex!(`:([^:]+?)(;|$)`);
        string _topic_register = _struct_composite.meta.classify_topic_register;
        _topic_register = _topic_register
          .replaceAll(wrds, "\"$1\"")
          .replaceAll(mkp_delim, ":$1$2");
      }
      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;
      string[] topics_expanded;
      if (_struct_composite.meta.classify_topic_register_arr.length > 0) {
        foreach (i, topic; _struct_composite.meta.classify_topic_register_arr) {
          string[] subject_tree = topic.split(mkup.sep);
          if (topic.length > 0) {
            topics_expanded ~= subject_tree.join(", ");
          }
        }
      }
      _struct_composite.meta.classify_topic_register_expanded_arr = topics_expanded;
      // writeln("\n------\n", _struct_composite.meta.title_full);
      // writeln(_struct_composite.meta.classify_topic_register);
      // writeln(_struct_composite.meta.classify_topic_register_expanded_arr.sort.join("\n"));
      // writeln(_struct_composite.meta.classify_topic_register_arr);
    }
  }
}
if ("date" in _yaml
  && _yaml["date"].type.sequence
) {
  if (_yaml["date"].type.mapping
    && _yaml["date"].tag.match(rgx_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.yaml_tag_is_map)
  ) {
    if ("abstract" in _yaml["notes"]
      && _yaml["notes"]["abstract"].type.string
      && _yaml["notes"]["abstract"].tag.match(rgx_y.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_y.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_y.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_y.yaml_tag_is_map)
  ) {
    if ("language" in _yaml["original"]
      && _yaml["original"]["language"].type.string
      && _yaml["original"]["language"].tag.match(rgx_y.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_y.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_y.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_y.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_y.yaml_tag_is_map)
  ) {
    if ("copyright" in _yaml["rights"]
      && _yaml["rights"]["copyright"].type.string
      && _yaml["rights"]["copyright"].tag.match(rgx_y.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_copyright = check_input_markup(_yaml["rights"]["copyright"].get!string);
    }
    if ("copyright_text" in _yaml["rights"]
      && _yaml["rights"]["copyright_text"].type.string
      && _yaml["rights"]["copyright_text"].tag.match(rgx_y.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_y.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_y.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_y.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_y.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_y.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_y.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_y.yaml_tag_is_str)
    ) {
      _struct_composite.meta.rights_license = check_input_markup(_yaml["rights"]["license"].get!string);
    }
  }
}
#+END_SRC

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

#+HEADER: :tangle "../src/doc_reform/meta/conf_make_meta_json.d"
#+HEADER: :noweb yes
#+BEGIN_SRC d
<<doc_header_including_copyright_and_license>>
/++
  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_yaml,
    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();
    mixin spineRgxYamlTags;
    static auto rgx_y = RgxYaml();
    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 ("doc_type" in _json.object["make"]
    && (_json.object["make"]["doc_type"].type().to!string == "string")
  ) {
    _struct_composite.make_str.doc_type = _json.object["make"]["doc_type"].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 ("bold" in _json.object["make"]
    && (_json.object["make"]["bold"].type().to!string == "string")
  ) {
    _struct_composite.make_str.bold = _json.object["make"]["bold"].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_host = 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

#+NAME: parse_yaml_return_spineStruct
#+BEGIN_SRC 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,Cfg)(
    T       _document_struct,
    CCm     _make_and_meta_struct,
    M       _manifested,
    O       _opt_action,
    Cfg     _cfg
  ){
    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, _cfg, _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

#+NAME: doc_header_convert_to_struct
#+BEGIN_SRC 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_yaml,
    doc_reform.meta.rgx;
  mixin spineRgxIn;
  mixin contentJSONtoSpineStruct;
  static auto rgx = RgxI();
  mixin spineRgxYamlTags;
  static auto rgx_y = RgxYaml();
  @system auto docHeaderMakeAndMetaTupYamlExtractAndConvertToStruct(CCm,Src,M,O,Cfg)(
    Src     header_src,
    CCm     _make_and_meta_struct,
    M       _manifested,
    O       _opt_action,
    Cfg     _cfg,
  ) {
    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, _cfg, "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

* document header including copyright & license

#+NAME: doc_header_including_copyright_and_license
#+BEGIN_SRC txt
/+
- Name: Spine, Doc Reform [a part of]
  - Description: documents, structuring, processing, publishing, search
    - static content generator

  - Author: Ralph Amissah
    [ralph.amissah@gmail.com]

  - Copyright: (C) 2015 - 2023 Ralph Amissah, All Rights Reserved.

  - License: AGPL 3 or later:

    Spine (SiSU), a framework for document structuring, publishing and
    search

    Copyright (C) Ralph Amissah

    This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU AFERO General Public License as published by the
    Free Software Foundation, either version 3 of the License, or (at your
    option) any later version.

    This program is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
    more details.

    You should have received a copy of the GNU General Public License along with
    this program. If not, see [https://www.gnu.org/licenses/].

    If you have Internet connection, the latest version of the AGPL should be
    available at these locations:
    [https://www.fsf.org/licensing/licenses/agpl.html]
    [https://www.gnu.org/licenses/agpl.html]

  - Spine (by Doc Reform, related to SiSU) uses standard:
    - docReform markup syntax
      - standard SiSU markup syntax with modified headers and minor modifications
    - docReform object numbering
      - standard SiSU object citation numbering & system

  - Homepages:
    [https://www.doc_reform.org]
    [https://www.sisudoc.org]

  - Git
    [https://git.sisudoc.org/projects/?p=software/spine.git;a=summary]

+/
#+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