diff options
Diffstat (limited to 'src/doc_reform')
29 files changed, 18201 insertions, 0 deletions
diff --git a/src/doc_reform/conf/compile_time_info.d b/src/doc_reform/conf/compile_time_info.d new file mode 100644 index 0000000..0e09edd --- /dev/null +++ b/src/doc_reform/conf/compile_time_info.d @@ -0,0 +1,38 @@ +/++ +  compile_time_info ++/ +module doc_reform.conf.compile_time_info; +template CompileTimeInfo() { +  version(Windows) { +    pragma(msg, "[ Windows compilation ]"); +    enum os = "Windows"; +  } else version(OSX) { +    pragma(msg, "[ Mac OS X POSIX System compilation ]"); +    enum os = "OSX"; +  } else version(linux) { +    pragma(msg, "[ Linux POSIX System compilation ]"); +    enum os = "Linux"; +  } else version(FreeBSD) { +    pragma(msg, "[ FreeBSD POSIX System compilation ]"); +    enum os = "FreeBSD"; +  } else version(OpenBSD) { +    pragma(msg, "[ OpenBSD POSIX System compilation ]"); +    enum os = "OpenBSD"; +  } else version(NetBSD) { +    pragma(msg, "[ NetBSD POSIX System compilation ]"); +    enum os = "NetBSD"; +  } else version(DragonFlyBSD) { +    pragma(msg, "[ DragonFlyBSD POSIX System compilation ]"); +    enum os = "DragonFlyBSD"; +  } else version(POSIX) { +    pragma(msg, "[ POSIX System compilation ]"); +    enum os = "POSIX"; +  } else { +    static assert(0, "OS not listed"); +  } +  version(D_LP64) { +    enum bits = "64 bit"; +  } else { +    enum bits = "32 bit"; +  } +} diff --git a/src/doc_reform/doc_reform.d b/src/doc_reform/doc_reform.d new file mode 100755 index 0000000..f7c9751 --- /dev/null +++ b/src/doc_reform/doc_reform.d @@ -0,0 +1,512 @@ +#!/usr/bin/env rdmd +module doc_reform.sisu_document_parser; +import +  doc_reform.conf.compile_time_info, +  doc_reform.meta.metadoc; +import +  std.getopt, +  std.file, +  std.path, +  std.process; +import +  doc_reform.meta, +  doc_reform.meta.metadoc_summary, +  doc_reform.meta.metadoc_from_src, +  doc_reform.meta.conf_make_meta_structs, +  doc_reform.meta.conf_make_meta_toml, +  doc_reform.meta.conf_make_meta_json, +  doc_reform.meta.defaults, +  doc_reform.meta.doc_debugs, +  doc_reform.meta.rgx, +  doc_reform.source.paths_source, +  doc_reform.source.read_config_files, +  doc_reform.source.read_source_files, +  doc_reform.output.hub; +import std.algorithm; +import std.parallelism; +mixin(import("version.txt")); +mixin CompileTimeInfo; +/++ +name        "doc_reform" +description "A SiSU inspired document parser writen in D." +homepage    "http://sisudoc.org" ++/ +void main(string[] args) { +  mixin SiSUrgxInit; +  mixin contentJSONtoSiSUstruct; +  mixin SiSUbiblio; +  mixin SiSUrgxInitFlags; +  mixin outputHub; +  string flag_action; +  string arg_unrecognized; +  enum dAM { abstraction, matters } +  static auto rgx = Rgx(); +  scope(success) { +    debug(checkdoc) { +      writefln( +        "~ run complete, ok ~ (doc_reform-%s.%s.%s, %s D:%s, %s %s)", +        ver.major, ver.minor, ver.patch, +        __VENDOR__, __VERSION__, +        bits, os, +      ); +    } +  } +  scope(failure) { +    debug(checkdoc) { +      stderr.writefln( +        "run failure", +      ); +    } +  } +  bool[string] opts = [ +    "abstraction"        : false, +    "assertions"         : false, +    "concordance"        : false, +    "debug"              : false, +    "digest"             : false, +    "epub"               : false, +    "html"               : false, +    "html-seg"           : false, +    "html-scroll"        : false, +    "manifest"           : false, +    "ocn"                : true, +    "pp2"                : false, +    "quiet"              : false, +    "sisupod"            : false, +    "source"             : false, +    "sqlite-discrete"    : false, +    "sqlite-db-create"   : false, +    "sqlite-db-drop"     : false, +    "sqlite-db-recreate" : false, +    "sqlite-delete"      : false, +    "sqlite-insert"      : false, +    "sqlite-update"      : false, +    "text"               : false, +    "verbose"            : false, +    "very-verbose"        : false, +    "xhtml"              : false, +    "section_toc"        : true, +    "section_body"       : true, +    "section_endnotes"   : true, +    "section_glossary"   : true, +    "section_biblio"     : true, +    "section_bookindex"  : true, +    "section_blurb"      : true, +    "backmatter"         : true, +    "skip-output"        : false, +  ]; +  string[string] settings = [ +    "output-dir"         : "", +    "site-config-dir"    : "", +    "lang"               : "all", +    "sqlite-filename"    : "documents", +  ]; +  auto helpInfo = getopt(args, +    std.getopt.config.passThrough, +    "abstraction",        "--abstraction document abstraction ",                                      &opts["abstraction"], +    "assert",             "--assert set optional assertions on",                                      &opts["assertions"], +    "concordance",        "--concordance file for document",                                          &opts["concordance"], +    "debug",              "--debug",                                                                  &opts["debug"], +    "digest",             "--digest hash digest for each object",                                     &opts["digest"], +    "epub",               "--epub process epub output",                                               &opts["epub"], +    "html",               "--html process html output",                                               &opts["html"], +    "html-seg",           "--html-seg process html output",                                           &opts["html-seg"], +    "html-scroll",        "--html-seg process html output",                                           &opts["html-scroll"], +    "manifest",           "--manifest process manifest output",                                       &opts["manifest"], +    "ocn",                "--ocn object cite numbers (default)",                                      &opts["ocn"], +    "pp2",                "--pp2 nested parallelisation",                                             &opts["pp2"], +    "quiet",              "--quiet output to terminal",                                               &opts["quiet"], +    "sisupod",            "--sisupod sisupod source content bundled",                                 &opts["sisupod"], +    "source",             "--source markup source text content",                                      &opts["source"], +    "sqlite-discrete",    "--sqlite process discrete sqlite output",                                  &opts["sqlite-discrete"], +    "sqlite-db-create",   "--sqlite-db-create create db, create tables",                              &opts["sqlite-db-create"], +    "sqlite-db-drop",     "--sqlite-db-drop drop tables & db",                                        &opts["sqlite-db-drop"], +    "sqlite-db-recreate", "--sqlite-db-recreate create db, create tables",                            &opts["sqlite-db-recreate"], +   // "sqlite-db-populate", "--sqlite-db-populate create db & tables, insert specified",  &opts["sqlite-db-populate"], +    "sqlite-delete",      "--sqlite process sqlite output",                                           &opts["sqlite-delete"], +    "sqlite-insert",      "--sqlite process sqlite output",                                           &opts["sqlite-insert"], +    "sqlite-update",      "--sqlite process sqlite output",                                           &opts["sqlite-update"], +    "text",               "--text process text output",                                               &opts["text"], +    "txt",                "--txt process text output",                                                &opts["text"], +    "verbose|v",          "--verbose output to terminal",                                             &opts["verbose"], +    "very-verbose",       "--very-verbose output to terminal",                                        &opts["very-verbose"], +    "xhtml",              "--xhtml process xhtml output",                                             &opts["xhtml"], +    "section-toc",        "--section-toc process table of contents (default)",                        &opts["section_toc"], +    "section-body",       "--section-body process document body (default)",                           &opts["section_body"], +    "section-endnotes",   "--section-endnotes process document endnotes (default)",                   &opts["section_endnotes"], +    "section-glossary",   "--section-glossary process document glossary (default)",                   &opts["section_glossary"], +    "section-biblio",     "--section-biblio process document biblio (default)",                       &opts["section_biblio"], +    "section-bookindex",  "--section-bookindex process document bookindex (default)",                 &opts["section_bookindex"], +    "section-blurb",      "--section-blurb process document blurb (default)",                         &opts["section_blurb"], +    "backmatter",         "--section-backmatter process document backmatter (default)",               &opts["backmatter"], +    "skip-output",        "--skip-output",                                                            &opts["skip-output"], +    "output-dir",         "--output-dir=[dir path]",                                                  &settings["output-dir"], +    "site-config-dir",    "--site-config-dir=[dir path]",                                             &settings["site-config-dir"], +    "sqlite-filename",    "--sqlite-filename=[filename].sqlite",                                      &settings["sqlite-filename"], +    "lang",               "--lang=[lang code e.g. =en or =en,es]",                                    &settings["lang"], +  ); +  if (helpInfo.helpWanted) { +    defaultGetoptPrinter("Some information about the program.", helpInfo.options); +  } +  enum outTask { sisupod, source, sqlite, sqlite_multi, epub, html_scroll, html_seg, html_stuff } +  struct OptActions { +    auto assertions() { +      return opts["assertions"]; +    } +    auto concordance() { +      return opts["concordance"]; +    } +    auto debug_do() { +      return opts["debug"]; +    } +    auto digest() { +      return opts["digest"]; +    } +    auto epub() { +      return opts["epub"]; +    } +    auto html() { +      bool _is = ( +        opts["html"] +        || opts["html-seg"] +        || opts["html-scroll"] +      ) +      ? true +      : false; +      return _is; +    } +    auto html_seg() { +      bool _is = ( +        opts["html"] +        || opts["html-seg"] +      ) +      ? true +      : false; +      return _is; +    } +    auto html_scroll() { +      bool _is = ( +        opts["html"] +        || opts["html-scroll"] +      ) +      ? true +      : false; +      return _is; +    } +    auto html_stuff() { +      bool _is = ( +        opts["html"] +        || opts["html-scroll"] +        || opts["html-seg"] +      ) +      ? true +      : false; +      return _is; +    } +    auto manifest() { +      return opts["manifest"]; +    } +    auto ocn() { +      return opts["ocn"]; +    } +    auto quiet() { +      return opts["quiet"]; +    } +    auto sisupod() { +      return opts["sisupod"]; +    } +    auto source() { +      return opts["source"]; +    } +    auto sqlite_discrete() { +      return opts["sqlite-discrete"]; +    } +    auto sqlite_db_drop() { +      bool _is = ( +        opts["sqlite-db-recreate"] +        || opts["sqlite-db-drop"] +      ) +      ? true +      : false; +      return _is; +    } +    auto sqlite_db_create() { +      bool _is = ( +        opts["sqlite-db-recreate"] +        || opts["sqlite-db-create"] +      ) +      ? true +      : false; +      return _is; +    } +    auto sqlite_insert() { +      return opts["sqlite-insert"]; +    } +    auto sqlite_delete() { +      return opts["sqlite-delete"]; +    } +    auto sqlite_update() { +      return opts["sqlite-update"]; +    } +    auto text() { +      return opts["text"]; +    } +    auto verbose() { +      bool _is = ( +        opts["verbose"] +        || opts["very-verbose"] +      ) +      ? true +      : false; +      return _is; +    } +    auto very_verbose() { +      return opts["very-verbose"]; +    } +    auto xhtml() { +      return opts["xhtml"]; +    } +    auto section_toc() { +      return opts["section_toc"]; +    } +    auto section_body() { +      return opts["section_body"]; +    } +    auto section_endnotes() { +      return opts["section_endnotes"]; +    } +    auto section_glossary() { +      return opts["section_glossary"]; +    } +    auto section_biblio() { +      return opts["section_biblio"]; +    } +    auto section_bookindex() { +      return opts["section_bookindex"]; +    } +    auto section_blurb() { +      return opts["section_blurb"]; +    } +    auto backmatter() { +      return opts["backmatter"]; +    } +    auto skip_output() { +      return opts["skip-output"]; +    } +    auto languages_set() { +      return settings["lang"].split(","); +    } +    auto output_dir_set() { +      return settings["output-dir"]; +    } +    auto sqlite_filename() { +      return settings["sqlite-filename"]; +    } +    auto pp2() { +      return opts["pp2"]; +    } +    auto output_task_scheduler() { +      int[] schedule; +      if (sisupod) { +        schedule ~= outTask.sisupod; +      } +      if (source) { +        schedule ~= outTask.source; +      } +      if (sqlite_discrete) { +        schedule ~= outTask.sqlite; +      } +      if (epub) { +        schedule ~= outTask.epub; +      } +      if (html_scroll) { +        schedule ~= outTask.html_scroll; +      } +      if (html_seg) { +        schedule ~= outTask.html_seg; +      } +      if (html_stuff) { +        schedule ~= outTask.html_stuff; +      } +      return schedule.sort().uniq; +    } +    auto abstraction() { +      bool _is = ( +        opts["abstraction"] +        || concordance +        || epub +        || html +        || manifest +        || sisupod +        || source +        || sqlite_discrete +        || sqlite_delete +        || sqlite_insert +        || sqlite_update +      ) +      ? true +      : false; +      return _is; +    } +  } +  auto _opt_action = OptActions(); +  auto _env = [ +    "pwd" : environment["PWD"], +    "home" : environment["HOME"], +  ]; +  auto _manifest_start = PodManifest!()(""); +  auto _manifest_matter = PathMatters!()(_opt_action, _env, ""); +  auto _manifests = [ _manifest_matter ]; +  foreach(arg; args[1..$]) { +    _manifest_start = PodManifest!()(arg); +    if (arg.match(rgx.flag_action)) { +      flag_action ~= " " ~ arg;   // flags not taken by getopt +    } else if ( +      !(arg.match(rgx.src_pth_sst_or_ssm)) +      && _manifest_start.pod_manifest_file_with_path +      && _opt_action.abstraction +    ) { +      string contents_location_raw_; +      string contents_location_; +      string sisudoc_txt_ = _manifest_start.pod_manifest_file_with_path; +      enforce( +        exists(sisudoc_txt_)!=0, +        "file not found: «" ~ +        sisudoc_txt_ ~ "»" +      ); +      if (exists(sisudoc_txt_)) { +        try { +          if (exists(sisudoc_txt_)) { +            contents_location_raw_ = sisudoc_txt_.readText; +          } +        } catch (ErrnoException ex) { +        } catch (FileException ex) { +          // Handle errors +        } +        if (contents_location_raw_.match(rgx.pod_content_location)) { // (file name followed by language codes \n)+ +          foreach (m; contents_location_raw_.matchAll(rgx.pod_content_location)) { +            foreach (n; m.captures[2].matchAll(rgx.language_codes)) { +              contents_location_ ~= "media/text/" ~ n.captures[1].to!string ~ "/" ~ m.captures[1].to!string ~ "\n"; +            } +          } +        } else { +          contents_location_ = contents_location_raw_; +        } +      } else { +        writeln("manifest not found: ", sisudoc_txt_); +      } +      auto contents_locations_arr +        = (cast(char[]) contents_location_).split; +      auto tmp_dir_ = (sisudoc_txt_).dirName.array; +      foreach (contents_location; contents_locations_arr) { +        assert(contents_location.match(rgx.src_pth_sst_or_ssm), +          "not a recognised file: «" ~ +          contents_location ~ "»" +        ); +        auto contents_location_pth_ = (contents_location).to!string; +        auto lang_rgx_ = regex(r"/(" ~ _opt_action.languages_set.join("|") ~ ")/"); +        if (_opt_action.languages_set[0] == "all" +          || (contents_location_pth_).match(lang_rgx_) +        ) { +          auto _fns = (((tmp_dir_).chainPath(contents_location_pth_)).array).to!string; +          _manifest_matter = PathMatters!()(_opt_action, _env, arg, _fns, contents_locations_arr); +          _manifests ~= _manifest_matter; +        } +      } +    } else if (arg.match(rgx.src_pth_sst_or_ssm)) { +      if (exists(arg)==0) { +        writeln("ERROR >> Processing Skipped! File not found: ", arg); +      } else { +        _manifest_matter = PathMatters!()(_opt_action, _env, arg, arg); +        _manifests ~= _manifest_matter; +      } +    } else if (arg.match(rgx.src_pth_zip)) { +      // fns_src ~= arg;          // gather input markup source file names for processing +    } else {                      // anything remaining, unused +      arg_unrecognized ~= " " ~ arg; +    } +  } +  if (!(_opt_action.skip_output)) { +    debug(steps) { +      writeln("step0 commence → (without processing files)"); +    } +    outputHubOp!()(_env, _opt_action); +    debug(steps) { +      writeln("- step0 complete"); +    } +  } +  if (_manifests.length > 1) {                            // _manifests[0] initialized dummy element +    foreach(manifest; parallel(_manifests[1..$])) { +      if (!empty(manifest.src.filename)) { +        scope(success) { +          if (!(_opt_action.quiet)) { +            writefln( +              "%s\n%s", +              "~ document complete, ok ~", +              "------------------------------------------------------------------", +            ); +          } +        } +        scope(failure) { +          debug(checkdoc) { +            stderr.writefln( +              "~ document run failure ~ (%s  v%s)\n\t%s\n%s", +              __VENDOR__, __VERSION__, +              manifest.src.filename, +              "------------------------------------------------------------------", +            ); +          } +        } +        enforce( +          manifest.src.filename.match(rgx.src_pth_types), +          "not a sisu markup filename: «" ~ +          manifest.src.filename ~ "»" +        ); +        debug(steps) { +          writeln("--->\nstepX commence → (document abstraction)"); +        } +        auto t = SiSUabstraction!()(_env, _opt_action, manifest); +        static assert(!isTypeTuple!(t)); +        static assert(t.length==2); +        auto doc_abstraction = t[dAM.abstraction]; +        auto doc_matters = t[dAM.matters]; +        debug(steps) { +          writeln("- stepX complete"); +        } +        /+ ↓ debugs +/ +        if (doc_matters.opt.action.verbose) { +          SiSUabstractionSummary!()(doc_abstraction, doc_matters); +        } +        /+ ↓ debugs +/ +        if ((doc_matters.opt.action.debug_do) +        || (doc_matters.opt.action.verbose) +        ) { +          SiSUdebugs!()(doc_abstraction, doc_matters); +        } +        /+ ↓ output hub +/ +        if (!(doc_matters.opt.action.skip_output)) { +          debug(steps) { +            writeln("step5 commence → (process outputs)"); +          } +          outputHub!()(doc_abstraction, doc_matters); +          debug(steps) { +            writeln("- step5 complete"); +          } +        } +        scope(exit) { +          if (!(_opt_action.quiet)) { +            writefln( +              "processed file: %s", +              manifest.src.filename +            ); +          } +          destroy(manifest); +        } +      } else { +        /+ no recognized filename provided +/ +        writeln("no recognized filename"); +        break; // terminate, stop +      } +    } +  } +} diff --git a/src/doc_reform/meta/conf_make_meta_json.d b/src/doc_reform/meta/conf_make_meta_json.d new file mode 100644 index 0000000..d6adfa7 --- /dev/null +++ b/src/doc_reform/meta/conf_make_meta_json.d @@ -0,0 +1,607 @@ +/++ +  json headers<BR> +  extract json header return json ++/ +module doc_reform.meta.conf_make_meta_json; +static template contentJSONtoSiSUstruct() { +  import +    std.exception, +    std.regex, +    std.stdio, +    std.string, +    std.traits, +    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.rgx; +  ConfCompositePlus _struct_composite; +  auto contentJSONtoSiSUstruct(C, J)(C _struct_composite, J _json, string _identifier) { +    mixin SiSUrgxInit; +    static auto _rgx = Rgx(); +    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; +    /+ make ------------------------------------------------------------------- +/ +    if ("make" in _json.object) { +      if ("bold" in _json.object["make"] +        && (_json.object["make"]["bold"].type().to!string == "STRING") +      ) { +        _struct_composite.make_str.bold = _json.object["make"]["bold"].str; +      } +      if ("breaks" in _json.object["make"] +        && (_json.object["make"]["breaks"].type().to!string == "STRING") +      ) { +        _struct_composite.make_str.breaks = _json.object["make"]["breaks"].str; +      } +      if ("cover_image" in _json.object["make"] +        && (_json.object["make"]["cover_image"].type().to!string == "STRING") +      ) { +        _struct_composite.make_str.cover_image = _json.object["make"]["cover_image"].str; +      } +      if ("css" in _json.object["make"] +        && (_json.object["make"]["css"].type().to!string == "STRING") +      ) { +        _struct_composite.make_str.css = _json.object["make"]["css"].str; +      } +      if ("emphasis" in _json.object["make"] +        && (_json.object["make"]["emphasis"].type().to!string == "STRING") +      ) { +        _struct_composite.make_str.emphasis = _json.object["make"]["emphasis"].str; +      } +      if ("footer" in _json.object["make"] +        && (_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 ("footer" in _json.object["make"] +        && _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"] +        && (_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 ("headings" in _json.object["make"] +        && _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"] +        && (_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 ("home_button_image" in _json.object["make"] +        && _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"] +        && (_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 ("home_button_text" in _json.object["make"] +        && _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"] +        && (_json.object["make"]["auto_num_depth"].type().to!string == "INTEGER") +      ) { +        _struct_composite.make_str.auto_num_depth = _json.object["make"]["auto_num_depth"].integer.to!int; +      } else if ("auto_num_depth" in _json.object["make"] +        && (_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") +          && (_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"].type().to!string == "ARRAY") +          && (_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); +    } +    /+ conf ------------------------------------------------------------------- +/ +    if ("webserv" in _json.object) { +      if ("url_root" in _json.object["webserv"] +        && (_json.object["webserv"]["url_root"].type().to!string == "STRING") +      ) { +        _struct_composite.conf.webserv_url_root = _json.object["webserv"]["url_root"].str; +      } +      if ("path" in _json.object["webserv"] +        && (_json.object["webserv"]["path"].type().to!string == "STRING") +      ) { +        _struct_composite.conf.webserv_path = _json.object["webserv"]["path"].str; +      } +      if ("images" in _json.object["webserv"] +        && (_json.object["webserv"]["images"].type().to!string == "STRING") +      ) { +        _struct_composite.conf.webserv_images = _json.object["webserv"]["images"].str; +      } +      if ("cgi" in _json.object["webserv"] +        && (_json.object["webserv"]["cgi"].type().to!string == "STRING") +      ) { +        _struct_composite.conf.webserv_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.webserv_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.webserv_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.webserv_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.webserv_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.webserv_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.default_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.default_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.default_emphasis = _json.object["default"]["emphasis"].str; +      } +      if ("language" in _json.object["default"] +        && (_json.object["default"]["language"].type().to!string == "STRING") +      ) { +        _struct_composite.conf.default_language = _json.object["default"]["language"].str; +      } +      if ("digest" in _json.object["default"] +        && (_json.object["default"]["digest"].type().to!string == "STRING") +      ) { +        _struct_composite.conf.default_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; +      } +    } +    /+ meta ------------------------------------------------------------------- +/ +    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; +      } +    } +    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; +      } +    } +    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; +      } +    } +    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[] authors_arr; +      auto authors_raw_arr = _struct_composite.meta.creator_author.split(_rgx.arr_delimiter); +      foreach (author_raw; authors_raw_arr) { +        authors_arr ~= author_raw.replace(_rgx.raw_author_munge, "$2 $1"); +      } +      _struct_composite.meta.creator_author = join(authors_arr, ", ").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; +          } +          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, +        ); +    } +    return _struct_composite; +  } +} diff --git a/src/doc_reform/meta/conf_make_meta_structs.d b/src/doc_reform/meta/conf_make_meta_structs.d new file mode 100644 index 0000000..cf279a5 --- /dev/null +++ b/src/doc_reform/meta/conf_make_meta_structs.d @@ -0,0 +1,328 @@ +module doc_reform.meta.conf_make_meta_structs; +import +  std.exception, +  std.json, +  std.regex, +  std.stdio, +  std.string, +  std.traits, +  std.typecons, +  std.utf, +  std.conv : to; +import +  doc_reform.meta.defaults, +  doc_reform.meta.rgx; +mixin SiSUrgxInit; +static auto _rgx = Rgx(); +mixin InternalMarkup; +auto _mkup = InlineMarkup(); +auto url_markup(string line) { +  auto line_ = (line) +    .replaceAll( +      _rgx.smid_inline_link_markup_regular, +      ("$1" +        ~ _mkup.lnk_o ~ "$2" ~ _mkup.lnk_c +        ~ _mkup.url_o ~ "$3" ~ _mkup.url_c +        ~ "$4")            // ("$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 +          ~ "$3")            // ("$1{ $2 }$2$3") +    ) +    .replaceAll( +       _rgx.arr_delimiter, +       _mkup.br_line +    ); +  return line_; +} +struct ConfCompositeMakeStr { +  string bold; +  string breaks; +  string cover_image; +  string css; +  string emphasis; +  string[] footer; +  string[] headings; +  string[] home_button_image; +  string home_button_text = "{Doc Reform}http://www.doc-reform.org;" +    ~ " {www.doc-reform.org}http://www.doc-reform.org;" +    ~ " {sources / git}https://git.doc-reform.org/software/doc-reform"; +  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 { +  auto bold(string _mk) { +    string[] _out; +    if (_mk) { +      _out = [ (cast(string) (`(` ~ _mk.dup ~ `)`)), "*{$1}*", "<b>$1</b>"]; +    } +    return _out; +  } +  auto breaks(string _mk) { +    return _mk; +  } +  auto cover_image(string _mk) { +    return _mk; +  } +  auto css(string _mk) { +    return _mk; +  } +  auto emphasis(string _mk) { +    string[] _out; +    if (_mk) { +      _out = [ (cast(string) (`(` ~ _mk.dup ~ `)`)), "!{$1}!", "<em>$1</em>" ]; +    } +    return _out; +  } +  auto footer(string[] _mk) { +    string line_; +    string[] _mk2; +    foreach (line; _mk) { +      _mk2 ~= url_markup(line); +    } +    return _mk2; +  } +  auto headings(string[] _mk) { +    return _mk; +  } +  auto home_button_image(string[] _mk) { +    return _mk; +  } +  auto home_button_text(string _mk) { +    return url_markup(_mk); +  } +  auto italics(string _mk) { +    string[] _out; +    if (_mk) { +      _out = [ (cast(string) (`(` ~ _mk.dup ~ `)`)), "/{$1}/", "<i>$1</i>" ]; +    } +    return _out; +  } +  auto auto_num_top_at_level(string _mk) { +    return _mk; +  } +  auto auto_num_top_lv(int _mk) { +    return _mk; +  } +  auto auto_num_depth(int _mk) { +    return _mk; +  } +  auto substitute(string[][] _mk) { +    return _mk; +  } +  auto texpdf_font(string _mk) { +    return _mk; +  } +} +struct ConfCompositeMakeInit { +  string[] bold; +  string breaks; +  string cover_image; +  string css; +  string[] emphasis; +  string[] footer; +  string[] headings; +  string[] home_button_image; +  string home_button_text = "{Doc Reform}http://www.doc-reform.org;" +    ~ " {www.doc-reform.org}http://www.doc-reform.org;" +    ~ " {sources / git}https://git.doc-reform.org/software/doc-reform"; +  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 ConfCompositeSiteLocal { +  string webserv_url_root; +  string webserv_path; +  string webserv_images; +  string webserv_cgi; +  string webserv_cgi_host; +  string webserv_cgi_host_path; +  string webserv_cgi_port; +  string webserv_cgi_user; +  string webserv_cgi_file_links; +  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 default_papersize; +  string default_text_wrap; +  string default_emphasis; +  string default_language; +  string default_digest; +  string permission_share_source; +  string search_flag; +  string search_action; +  string search_db; +  string search_title; +} +struct MetaComposite { +  string classify_dewey; +  string classify_keywords; +  string classify_loc; +  string classify_subject; +  string classify_topic_register; +  string creator_author; +  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 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; +} +struct ConfComposite { +  MetaComposite               meta; +  ConfCompositeMakeInit       make; +  ConfCompositeSiteLocal      conf; +} +struct ConfCompositePlus { +  MetaComposite               meta; +  ConfCompositeMakeInit       make; +  ConfCompositeMakeStr        make_str; +  ConfCompositeSiteLocal      conf; +} +static auto ptr_head_main +  = [ +    "classify", +    "creator", +    "date", +    "identifier", +    "links", +    "make", +    "original", +    "notes", +    "rights", +    "title" +  ]; +static auto ptr_head_sub_classify +  = [ +    "dewey", +    "keywords", +    "loc", +    "subject", +    "topic_register" +  ]; +static auto ptr_head_sub_creator +  = [ +    "author", +    "author_email", +    "cover", +    "illustrator", +    "translator" +  ]; +static auto ptr_head_sub_date +  = [ +    "added_to_site", +    "available", +    "created", +    "issued", +    "modified", +    "published", +    "valid" +  ]; +static auto ptr_head_sub_identifier +  = [ +    "isbn", +    "oclc", +    "pg" +  ]; +/+ make +/ +static auto ptr_head_sub_make +  = [ +    "cover_image", +    "home_button_image", +    "home_button_text", +    "footer", "headings", +    "auto_num_top_at_level", "auto_num_top_lv", "auto_num_depth", +    "breaks", +    "substitute", +    "bold", +    "italics", +    "emphasis", +    "texpdf_font", +    "css" +  ]; +static auto ptr_head_sub_notes +  = [ +    "abstract", +    "description" +  ]; +static auto ptr_head_sub_original +  = [ +    "language", +    "source", +    "title" +  ]; +static auto ptr_head_sub_publisher +  = [ "name" ]; +static auto ptr_head_sub_rights +  = [ +    "copyright", +    "cover", +    "illustrations", +    "license" +  ]; +static auto ptr_head_sub_title +  = [ +    "edition", +    "full", +    "language", +    "main", +    "note", +    "sub" +  ]; +auto config_jsonstr = `{ +}`; diff --git a/src/doc_reform/meta/conf_make_meta_toml.d b/src/doc_reform/meta/conf_make_meta_toml.d new file mode 100644 index 0000000..d308ae4 --- /dev/null +++ b/src/doc_reform/meta/conf_make_meta_toml.d @@ -0,0 +1,77 @@ +/++ +  extract native/orig header return associative array<BR> + +  the header is passed as text (lopped off top of a sisu markup file until the +  required first heading ^A~), determine whether is a native header or sdlang one +  with a regex check if whether it contains the "native header" required tag/field +  @title: then process accordingly as a "native header" or "sdlang header" +  converting the metadata and make instructions to a common json format used by +  program internally. Moved to associative array. ++/ +module doc_reform.meta.conf_make_meta_toml; +static template configParseTOMLreturnJSON() { +  import +    toml, +    toml.json; +  auto configParseTOMLreturnJSON(T)( +    T _text +  ){ +    TOMLDocument _doc; +    _doc = parseTOML(cast(string)(_text.content)); +    auto _doc_json = toJSON(_doc); +    return _doc_json; +  } +} +static template configParseTOMLreturnSiSUstruct() { +  import +    toml, +    toml.json; +  import +    doc_reform.meta.conf_make_meta_structs, +    doc_reform.meta.conf_make_meta_json; +  mixin contentJSONtoSiSUstruct; +  auto configParseTOMLreturnSiSUstruct(CCm, T)( +    CCm     _make_and_meta_struct, +    T       _document_struct +  ){ +    TOMLDocument _doc = parseTOML(cast(string)(_document_struct.content)); +    auto _doc_json = toJSON(_doc); +    _make_and_meta_struct = contentJSONtoSiSUstruct!()(_make_and_meta_struct, _doc_json, _document_struct.filename); // struct from json +    return _make_and_meta_struct; +  } +} +static template docHeaderMakeAndMetaTupTomlExtractAndConvertToStruct() { +  import +    std.exception, +    std.regex, +    std.stdio, +    std.traits, +    std.typecons, +    std.utf, +    std.conv : to; +  import +    toml, +    toml.json; +  import +    doc_reform.meta.conf_make_meta_structs, +    doc_reform.meta.conf_make_meta_json, +    doc_reform.meta.rgx; +  mixin SiSUrgxInit; +  mixin contentJSONtoSiSUstruct; +  static auto rgx = Rgx(); +  auto docHeaderMakeAndMetaTupTomlExtractAndConvertToStruct(CCm, Src)( +    CCm     _make_and_meta_struct, +    Src     header_src, +  ) { +    TOMLDocument _doc; +    if (header_src.match(rgx.toml_header_meta_title)) { +      debug (json) { +        writeln(">>> document header is toml, convert to JSON"); +      } +      _doc = parseTOML(cast(string)(header_src)); +    } +    auto _doc_json = toJSON(_doc); +    auto _header_and_make_and_meta_struct = contentJSONtoSiSUstruct!()(_make_and_meta_struct, _doc_json, "header"); +    return _header_and_make_and_meta_struct; +  } +} diff --git a/src/doc_reform/meta/defaults.d b/src/doc_reform/meta/defaults.d new file mode 100644 index 0000000..2f8c068 --- /dev/null +++ b/src/doc_reform/meta/defaults.d @@ -0,0 +1,241 @@ +/++ +  default settings ++/ +module doc_reform.meta.defaults; +template SiSUrgxInitFlags() { +  /+ regex flags +/ +  static int[string] flags_type_init() { +    int[string] flags_type_init = [ +      "make_headings"                       : 0, +      "header_make"                         : 0, +      "header_meta"                         : 0, +      "heading"                             : 0, +      "biblio_section"                      : 0, +      "glossary_section"                    : 0, +      "blurb_section"                       : 0, +      "para"                                : 0, +      "blocks"                              : 0, // 0..2 generic +      "code"                                : 0, // 0..2 +      "poem"                                : 0, // 0..2 +      "table"                               : 0, // 0..2 +      "group"                               : 0, // 0..2 +      "block"                               : 0, // 0..2 +      "quote"                               : 0, // 0..2 +      "verse_new"                           : 0, +      "curly_code"                          : 0, +      "curly_poem"                          : 0, +      "curly_group"                         : 0, +      "curly_block"                         : 0, +      "curly_quote"                         : 0, +      "curly_table"                         : 0, +      "curly_table_special_markup"          : 0, +      "tic_code"                            : 0, +      "tic_poem"                            : 0, +      "tic_group"                           : 0, +      "tic_block"                           : 0, +      "tic_quote"                           : 0, +      "tic_table"                           : 0, +      "ocn_status"                          : 0, // 0 object_number; 1 no object_number; 2 no object_number & dummy headings +      "ocn_status_off_for_multiple_objects" : 0, // 0 object_number; 1 no object_number; 2 no object_number & dummy headings +      "book_index"                          : 0, +    ]; +    return flags_type_init; +  } +} +template SiSUnode() { +  static string[string] node_metadata_heading_str() { +    auto _node = [ +        "is"                            : "", +        "ocn"                           : "", +        "marked_up_lev"                 : "", +        "segment_anchor_tag"            : "", +        "attrib"                        : "", +    ]; +    return _node; +  } +  static int[string] node_metadata_heading_int() { +    auto _node = [ +        "ocn"                           : 0, // decide whether to use or keep? +        "ptr_doc_object"                : 0, +        "ptr_html_segnames"             : 0, +        "ptr_heading"                   : 0, +        "heading_lev_markup"            : 9, +        "heading_lev_collapsed"         : 9, +        "parent_ocn"                    : 0, +        "parent_lev_markup"             : 9, +    ]; +    return _node; +  } +  static string[string] node_metadata_para_str() { +    auto _node = [ +        "is"                            : "", +        "ocn"                           : "", +        "attrib"                        : "", +    ]; +    return _node; +  } +  static int[string] node_metadata_para_int() { +    auto _node = [ +        "ocn"                           : 0, +        "indent_base"                   : 0, +        "indent_hang"                   : 0, +        "bullet"                        : 0, // bool (0|1) +    ]; +    return _node; +  } +} +template SiSUbiblio() { +  // required: deemed_author (author || editor); year; fulltitle; +  struct BibJsnStr { +    static auto biblio_entry_tags_jsonstr() { +      string x =  `{ +        "is"                               : "", +        "sortby_deemed_author_year_title"  : "", +        "deemed_author"                    : "", +        "author_raw"                       : "", +        "author"                           : "", +        "author_arr"                       : [ "" ], +        "editor_raw"                       : "", +        "editor"                           : "", +        "editor_arr"                       : [ "" ], +        "title"                            : "", +        "subtitle"                         : "", +        "fulltitle"                        : "", +        "language"                         : "", +        "trans"                            : "", +        "src"                              : "", +        "journal"                          : "", +        "in"                               : "", +        "volume"                           : "", +        "edition"                          : "", +        "year"                             : "", +        "place"                            : "", +        "publisher"                        : "", +        "url"                              : "", +        "pages"                            : "", +        "note"                             : "", +        "short_name"                       : "", +        "id"                               : "" +      }`; // is: book, article, magazine, newspaper, blog, other +      return x; +    } +  } +} +template InternalMarkup() { +  import std.array; +  static struct InlineMarkup { +    auto en_a_o = "【";      auto en_a_c = "】"; +    auto en_b_o = "〖";      auto en_b_c = "〗"; +    auto lnk_o = "┥";        auto lnk_c = "┝"; +    auto url_o = "┤";        auto url_c = "├"; +    auto mark_internal_site_lnk = "¤"; +    auto nbsp = "░"; +    auto br_line = "┘"; +    auto br_nl = "┙"; +    auto br_paragraph = "┚"; +    auto br_obj = "break_obj"; +    auto br_page_line = "┼"; +    auto br_page = "┿"; +    auto br_page_new = "╂"; +    auto tc_s = "┊"; +    auto tc_o = "┏"; +    auto tc_c = "┚"; +    auto tc_p = "┆"; +    auto mono = "■"; +    auto img = "☼"; +    static string indent_by_spaces_provided(int indent, string _indent_spaces ="░░") { +      _indent_spaces = replicate(_indent_spaces, indent); +      return _indent_spaces; +    } +    static string repeat_character_by_number_provided(C,N)(C _character ="-", N number=10) { +      _character = replicate(_character, number); +      return _character; +    } +  } +} +template SiSUlanguageCodes() { +  /+ language codes +/ +  struct Lang { +    static string[string][string] codes() { +      auto _lang_codes = [ +        "am":    [ "c": "am",    "n": "Amharic",           "t": "Amharic",                   "xlp": "amharic"      ], +        "bg":    [ "c": "bg",    "n": "Bulgarian",         "t": "Български (Bəlgarski)",     "xlp": "bulgarian"    ], +        "bn":    [ "c": "bn",    "n": "Bengali",           "t": "Bengali",                   "xlp": "bengali"      ], +        "br":    [ "c": "br",    "n": "Breton",            "t": "Breton",                    "xlp": "breton"       ], +        "ca":    [ "c": "ca",    "n": "Catalan",           "t": "catalan",                   "xlp": "catalan"      ], +        "cs":    [ "c": "cs",    "n": "Czech",             "t": "česky",                     "xlp": "czech"        ], +        "cy":    [ "c": "cy",    "n": "Welsh",             "t": "Welsh",                     "xlp": "welsh"        ], +        "da":    [ "c": "da",    "n": "Danish",            "t": "dansk",                     "xlp": "danish"       ], +        "de":    [ "c": "de",    "n": "German",            "t": "Deutsch",                   "xlp": "german"       ], +        "el":    [ "c": "el",    "n": "Greek",             "t": "Ελληνικά (Ellinika)",       "xlp": "greek"        ], +        "en":    [ "c": "en",    "n": "English",           "t": "English",                   "xlp": "english"      ], +        "eo":    [ "c": "eo",    "n": "Esperanto",         "t": "Esperanto",                 "xlp": "esperanto"    ], +        "es":    [ "c": "es",    "n": "Spanish",           "t": "español",                   "xlp": "spanish"      ], +        "et":    [ "c": "et",    "n": "Estonian",          "t": "Estonian",                  "xlp": "estonian"     ], +        "eu":    [ "c": "eu",    "n": "Basque",            "t": "basque",                    "xlp": "basque"       ], +        "fi":    [ "c": "fi",    "n": "Finnish",           "t": "suomi",                     "xlp": "finnish"      ], +        "fr":    [ "c": "fr",    "n": "French",            "t": "français",                  "xlp": "french"       ], +        "ga":    [ "c": "ga",    "n": "Irish",             "t": "Irish",                     "xlp": "irish"        ], +        "gl":    [ "c": "gl",    "n": "Galician",          "t": "Galician",                  "xlp": "galician"     ], +        "he":    [ "c": "he",    "n": "Hebrew",            "t": "Hebrew",                    "xlp": "hebrew"       ], +        "hi":    [ "c": "hi",    "n": "Hindi",             "t": "Hindi",                     "xlp": "hindi"        ], +        "hr":    [ "c": "hr",    "n": "Croatian",          "t": "Croatian",                  "xlp": "croatian"     ], +        "hy":    [ "c": "hy",    "n": "Armenian",          "t": "Armenian",                  "xlp": "armenian"     ], +        "ia":    [ "c": "ia",    "n": "Interlingua",       "t": "Interlingua",               "xlp": "interlingua"  ], +        "is":    [ "c": "is",    "n": "Icelandic",         "t": "Icelandic",                 "xlp": "icelandic"    ], +        "it":    [ "c": "it",    "n": "Italian",           "t": "Italiano",                  "xlp": "italian"      ], +        "ja":    [ "c": "ja",    "n": "Japanese",          "t": "日本語 (Nihongo)",         "xlp": "japanese"      ], +        "ko":    [ "c": "ko",    "n": "Korean",            "t": "Korean",                    "xlp": "korean"       ], +        "la":    [ "c": "la",    "n": "Latin",             "t": "Latin",                     "xlp": "latin"        ], +        "lo":    [ "c": "lo",    "n": "Lao",               "t": "Lao",                       "xlp": "lao"          ], +        "lt":    [ "c": "lt",    "n": "Lithuanian",        "t": "Lithuanian",                "xlp": "lithuanian"   ], +        "lv":    [ "c": "lv",    "n": "Latvian",           "t": "Latvian",                   "xlp": "latvian"      ], +        "ml":    [ "c": "ml",    "n": "Malayalam",         "t": "Malayalam",                 "xlp": "malayalam"    ], +        "mr":    [ "c": "mr",    "n": "Marathi",           "t": "Marathi",                   "xlp": "marathi"      ], +        "nl":    [ "c": "nl",    "n": "Dutch",             "t": "Nederlands",                "xlp": "dutch"        ], +        "no":    [ "c": "no",    "n": "Norwegian",         "t": "norsk",                     "xlp": "norsk"        ], +        "nn":    [ "c": "nn",    "n": "Norwegian Nynorsk", "t": "nynorsk",                   "xlp": "nynorsk"      ], +        "oc":    [ "c": "oc",    "n": "Occitan",           "t": "Occitan",                   "xlp": "occitan"      ], +        "pl":    [ "c": "pl",    "n": "Polish",            "t": "polski",                    "xlp": "polish"       ], +        "pt":    [ "c": "pt",    "n": "Portuguese",        "t": "Português",                 "xlp": "portuges"     ], +        "pt_BR": [ "c": "pt_BR", "n": "Portuguese Brazil", "t": "Brazilian Português",       "xlp": "brazilian"    ], +        "ro":    [ "c": "ro",    "n": "Romanian",          "t": "română",                    "xlp": "romanian"     ], +        "ru":    [ "c": "ru",    "n": "Russian",           "t": "Русский (Russkij)",         "xlp": "russian"      ], +        "sa":    [ "c": "sa",    "n": "Sanskrit",          "t": "Sanskrit",                  "xlp": "sanskrit"     ], +        "se":    [ "c": "se",    "n": "Sami",              "t": "Samin",                     "xlp": "samin"        ], +        "sk":    [ "c": "sk",    "n": "Slovak",            "t": "slovensky",                 "xlp": "slovak"       ], +        "sl":    [ "c": "sl",    "n": "Slovenian",         "t": "Slovenian",                 "xlp": "slovenian"    ], +        "sq":    [ "c": "sq",    "n": "Albanian",          "t": "Albanian",                  "xlp": "albanian"     ], +        "sr":    [ "c": "sr",    "n": "Serbian",           "t": "Serbian",                   "xlp": "serbian"      ], +        "sv":    [ "c": "sv",    "n": "Swedish",           "t": "svenska",                   "xlp": "swedish"      ], +        "ta":    [ "c": "ta",    "n": "Tamil",             "t": "Tamil",                     "xlp": "tamil"        ], +        "te":    [ "c": "te",    "n": "Telugu",            "t": "Telugu",                    "xlp": "telugu"       ], +        "th":    [ "c": "th",    "n": "Thai",              "t": "Thai",                      "xlp": "thai"         ], +        "tk":    [ "c": "tk",    "n": "Turkmen",           "t": "Turkmen",                   "xlp": "turkmen"      ], +        "tr":    [ "c": "tr",    "n": "Turkish",           "t": "Türkçe",                    "xlp": "turkish"      ], +        "uk":    [ "c": "uk",    "n": "Ukranian",          "t": "українська (ukrajins\"ka)", "xlp": "ukrainian"    ], +        "ur":    [ "c": "ur",    "n": "Urdu",              "t": "Urdu",                      "xlp": "urdu"         ], +        "us":    [ "c": "en",    "n": "English (American)","t": "English",                   "xlp": "english"      ], +        "vi":    [ "c": "vi",    "n": "Vietnamese",        "t": "Vietnamese",                "xlp": "vietnamese"   ], +        "zh":    [ "c": "zh",    "n": "Chinese",           "t": "中文",                     "xlp": "chinese"       ], +        "en":    [ "c": "en",    "n": "English",           "t": "English",                   "xlp": "english"      ], +        "xx":    [ "c": "xx",    "n": "Default",           "t": "English",                   "xlp": "english"      ], +      ]; +      return _lang_codes; +    } +    static string[] code_arr_ptr() { +      auto _lang_codes = ["am", "bg", "bn", "br", "ca", "cs", "cy", "da", "de", "el", "en", "eo", "es", "et", "eu", "fi", "fr", "ga", "gl", "he", "hi", "hr", "hy", "ia", "is", "it", "ja", "ko", "la", "lo", "lt", "lv", "ml", "mr", "nl", "no", "nn", "oc", "pl", "pt", "pt_BR", "ro", "ru", "sa", "se", "sk", "sl", "sq", "sr", "sv", "ta", "te", "th", "tk", "tr", "uk", "ur", "us", "vi", "zh", "en", "xx",]; +      return _lang_codes; +    } +    static string[] code_arr() { +      auto _lang_codes = ["am", "bg", "bn", "br", "ca", "cs", "cy", "da", "de", "el", "en", "eo", "es", "et", "eu", "fi", "fr", "ga", "gl", "he", "hi", "hr", "hy", "ia", "is", "it", "ja", "ko", "la", "lo", "lt", "lv", "ml", "mr", "nl", "no", "nn", "oc", "pl", "pt", "pt_BR", "ro", "ru", "sa", "se", "sk", "sl", "sq", "sr", "sv", "ta", "te", "th", "tk", "tr", "uk", "ur", "vi", "zh"]; +      return _lang_codes; +    } +    static auto codes_() { +      return "(" ~ join(code_arr,"|") ~ ")"; +    } +    static auto codes_regex() { +      return regex(codes_); +    } +  } +} diff --git a/src/doc_reform/meta/doc_debugs.d b/src/doc_reform/meta/doc_debugs.d new file mode 100644 index 0000000..04dedb2 --- /dev/null +++ b/src/doc_reform/meta/doc_debugs.d @@ -0,0 +1,652 @@ +/++ +  output debugs ++/ +module doc_reform.meta.doc_debugs; +template SiSUdebugs() { +  import +    doc_reform.meta.defaults, +    doc_reform.meta.rgx; +  import +    std.algorithm, +    std.array, +    std.container, +    std.exception, +    std.json, +    std.stdio, +    std.file, +    std.path, +    std.range, +    std.regex, +    std.string, +    std.traits, +    std.typecons, +    std.utf, +    std.conv : to; +  auto SiSUdebugs(S,T)( +    const S  contents, +          T  doc_matters, +  ) { +    mixin SiSUrgxInit; +    mixin InternalMarkup; +    static auto rgx = Rgx(); +    auto markup = InlineMarkup(); +    string key; +    debug(parent) { +      writefln( +        "%s:%s", +        __FILE__, +        __LINE__, +      ); +      foreach (key; doc_matters.xml.keys_seq.seg) { +        foreach (obj; contents[key]) { +          if (obj.metainfo.is_of_part != "empty") { +            if (obj.metainfo.is_a == "heading") { +              writefln( +                "%s node: %s heading: %s %s", +                obj.object_number, +                obj.node, +                obj.heading_lev_markup, +                obj.text, +              ); +            } +          } +        } +      } +    } +    debug(dumpdoc) { +      writefln( +        "> %s:%s", +        __FILE__, +        __LINE__, +      ); +    } +    debug(section_head) { +      key="head"; +      if (contents[key].length > 1) { +        foreach (obj; contents[key]) { +          writefln( +            "[%s][%s]\n%s", +            obj.object_number, +            obj.metainfo.is_a, +            obj.text +          ); +        } +      } +    } +    debug(section_toc) { +      key="toc_seg"; +      out_toc(contents, key); +    } +    debug(section_toc_seg) { +      key="toc_seg"; +      out_toc(contents, key); +    } +    debug(section_toc_scroll) { +      key="toc_scroll"; +      out_toc(contents, key); +    } +    debug(segnames) { +      writeln(__LINE__); +      out_segnames(contents, doc_matters); +    } +    debug(section_body) { +      key="body"; +      if (contents[key].length > 1) { +        foreach (obj; contents[key]) { +          writefln( +            "[%s][%s]\n%s", +            obj.object_number, +            obj.metainfo.is_a, +            obj.text +          ); +        } +      } +    } +    debug(toc_nav_dom) { +      enum DomTags { none, open, close, close_and_open, open_still, } +      foreach (sect; doc_matters.xml.keys_seq.seg) { +        foreach (obj; contents[sect]) { +          if (obj.metainfo.is_a == "heading") { +            foreach_reverse (k; 0 .. 7) { +              switch (obj.dom_structure_markedup_tags_status[k]) { +              case DomTags.close : +                writeln(markup.indent_by_spaces_provided(k), "</", k, ">"); +                break; +              case DomTags.close_and_open : +                writeln(markup.indent_by_spaces_provided(k), "</", k, ">"); +                writeln(markup.indent_by_spaces_provided(k), +                  "<", k, ">", obj.text, +                  " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn); +                break; +              case DomTags.open : +                writeln(markup.indent_by_spaces_provided(k), +                  "<", k, ">", obj.text, +                  " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn); +                break; +              default : +                break; +              } +            } +          } +        } +      } +      writeln("--------------------"); +      foreach (sect; doc_matters.xml.keys_seq.seg) { +        foreach (obj; contents[sect]) { +          if (obj.metainfo.is_a == "heading") { +            foreach_reverse (k; 0 .. 7) { +              switch (obj.dom_structure_collapsed_tags_status[k]) { +              case DomTags.close : +                writeln(markup.indent_by_spaces_provided(k), "</", k, ">"); +                break; +              case DomTags.close_and_open : +                writeln(markup.indent_by_spaces_provided(k), "</", k, ">"); +                writeln(markup.indent_by_spaces_provided(k), +                  "<", k, ">", obj.text, +                  " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn); +                break; +              case DomTags.open : +                writeln(markup.indent_by_spaces_provided(k), +                  "<", k, ">", obj.text, +                  " file: ", obj.segment_anchor_tag, ".xhtml#", obj.ocn); +                break; +              default : +                break; +              } +            } +          } +        } +      } +    } +    debug(decendants) { +      foreach (sect; doc_matters.xml.keys_seq.scroll) { +        foreach (obj; contents[sect]) { +          if (obj.metainfo.is_a == "heading") { +            writeln(obj.metainfo.ocn, " .. ", obj.metainfo.last_decendant_ocn); +          } +        } +      } +    } +    debug(section_endnotes) { +      key="endnotes"; +      out_endnotes(contents, key); +    } +    debug(section_endnotes_seg) { +      key="endnotes"; +      out_endnotes(contents, key); +    } +    debug(section_glossary) { +      key="glossary"; +      if (contents[key].length > 1) { +        foreach (obj; contents[key]) { +          writefln( +            "[%s][%s]\n%s", +            obj.object_number, +            obj.metainfo.is_a, +            obj.text +          ); +        } +      } +    } +    debug(section_bibliography) { +      key="bibliography"; +      if (contents[key].length > 1) { +        foreach (obj; contents[key]) { +          writefln( +            "[%s][%s]\n%s", +            obj.object_number, +            obj.metainfo.is_a, +            obj.text +          ); +        } +      } +    } +    debug(section_bookindex) { +      key="bookindex_seg"; +      out_bookindex(contents, key); +    } +    debug(section_bookindex_seg) { +      key="bookindex_seg"; +      out_bookindex(contents, key); +    } +    debug(section_bookindex_scroll) { +      key="bookindex_scroll"; +      out_bookindex(contents, key); +    } +    debug(blurb_section) { +      key="blurb"; +      if (contents[key].length > 1) { +        foreach (obj; contents[key]) { +          writefln( +            "[%s][%s]\n%s", +            obj.object_number, +            obj.metainfo.is_a, +            obj.text +          ); +        } +      } +    } +    debug(objects) { +      writefln( +        "> %s:%s", +        __FILE__, +        __LINE__, +      ); +      foreach (obj; contents[key]) { +        if (obj.metainfo.is_of_part != "empty") { +          writefln( +            "* [%s][%s] %s", +            obj.object_number, +            obj.metainfo.is_a, +            obj.text +          ); +        } +      } +    } +    debug(headermakejson) { +      writefln( +        "%s\n%s\n%s", +        "document header, metadata & make instructions:", +        doc_matters.conf_make_meta.meta, +        ptr_head_main, +      ); +      foreach (main_header; ptr_head_main) { +        switch (main_header) { +        case "make": +          foreach (sub_header; ptr_head_sub_make) { +            if (doc_matters.conf_make_meta.meta.title_full.to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.conf_make_meta.meta.title_full +              ); +            } +          } +          break; +        default: +          break; +        } +      } +    } +    debug(headermetadatajson) { +      writefln( +        "%s\n%s\n%s", +        "document header, metadata & make instructions:", +        doc_matters.conf_make_meta.meta, +        ptr_head_main, +      ); +      foreach (main_header; ptr_head_main) { +        switch (main_header) { +        case "creator": +          foreach (sub_header; ptr_head_sub_creator) { +            if (doc_matters.conf_make_meta.meta.title_full.to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.conf_make_meta.meta.title_full, +              ); +            } +          } +          break; +        case "title": +          foreach (sub_header; ptr_head_sub_title) { +            if (doc_matters.conf_make_meta.meta.title_full.to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.conf_make_meta.meta.title_full +              ); +            } +          } +          break; +        case "rights": +          foreach (sub_header; ptr_head_sub_rights) { +            if (doc_matters.conf_make_meta.meta.title_full.to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.conf_make_meta.meta.title_full +              ); +            } +          } +          break; +        case "date": +          foreach (sub_header; ptr_head_sub_date) { +            if (doc_matters.conf_make_meta.meta.title_full.to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.conf_make_meta.meta.title_full +              ); +            } +          } +          break; +        case "original": +          foreach (sub_header; ptr_head_sub_original) { +            if (doc_matters.conf_make_meta.meta.title_full.to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.conf_make_meta.meta.title_full +              ); +            } +          } +          break; +        case "classify": +          foreach (sub_header; ptr_head_sub_classify) { +            if (doc_matters.conf_make_meta.meta.title_full.to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.conf_make_meta.meta.title_full +              ); +            } +          } +          break; +        case "identifier": +          foreach (sub_header; ptr_head_sub_identifier) { +            if (doc_matters.conf_make_meta.meta.title_full.to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.conf_make_meta.meta.title_full +              ); +            } +          } +          break; +        case "notes": +          foreach (sub_header; ptr_head_sub_notes) { +            if (doc_matters.conf_make_meta.meta.title_full.to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.conf_make_meta.meta.title_full +              ); +            } +          } +          break; +        case "publisher": +          foreach (sub_header; ptr_head_sub_publisher) { +            if (doc_matters.conf_make_meta.meta.title_full.to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.conf_make_meta.meta.title_full +              ); +            } +          } +          break; +        default: +          break; +        } +      } +    } +    debug(anchor) { +      writefln( +        "> %s:%s", +        __FILE__, +        __LINE__, +      ); +      foreach (k; doc_matters.xml.keys_seq.seg) { +        foreach (obj; contents[k]) { +          if (obj.metainfo.is_a == "heading") { +            writefln( +              "%s~ [%s] %s %s", +              obj.marked_up_level, +              obj.object_number, +              obj.anchor_tags, +              obj.text +            ); +          } +        } +      } +    } +    debug(heading) {                         // heading +      foreach (k; doc_matters.xml.keys_seq.seg) { +        foreach (o; contents[k]) { +          if (o.metainfo.is_a == "heading") { +            writefln( +              "%s* %s\n                (markup level: %s; collapsed level: %s)", +              replicate("  ", o.heading_lev_markup), +              strip(o.text), +              o.heading_lev_markup, +              o.heading_lev_collapsed, +            ); +          } +        } +      } +    } +    debug(headings) { +      writefln( +        "> %s:%s", +        __FILE__, +        __LINE__, +      ); +      foreach (k; doc_matters.xml.keys_seq.seg) { +        foreach (obj; contents[k]) { +          if (obj.metainfo.is_a == "heading") { +            writefln( +              "%s~ [%s] %s", +              obj.marked_up_level, +              obj.object_number, +              obj.text +            ); +          } +        } +      } +    } +    debug(summary) { +      string[string] check = [ +        "last_object_number" : "NA [debug \"checkdoc\" not run]", +      ]; +    } +    debug(checkdoc) { +      if ((doc_matters.opt.action.debug_do)) { +        debug(checkdoc) { +          if (auto mfn=match(doc_matters.src.filename, rgx.src_fn)) { +            if (doc_matters.opt.action.assertions) { +              switch (mfn.captures[2]) { +              // live manual: +              case "live-manual.ssm": +                assert(check["last_object_number"] == +                  "1019","last object_number should be: 1019 (check test, document is frequently updated)"); // ok +                break; +              // sisu_markup: +              case "sisu_markup.sst": +                assert(check["last_object_number"] == +                  "297","last object_number expected to be: 297 rather than " ~ check["last_object_number"]); // ok +                // assert(check["last_object_number"] == "297","last object_number expected to be: 297 rather than " ~ check["last_object_number"]); +                // notes for first divergance study sisu headings 247 250 +                // sisu has issue with code that contains heading 1~ which results in no object_number! ?? +                // sisu currently has incorrect last body object_number of 294! +                // bug in sisu? attend +                break; +              // sisu-markup-samples: +              case "accelerando.charles_stross.sst": +                assert(check["last_object_number"] == +                  "2861","last object_number expected to be: 2861 rather than " ~ check["last_object_number"]); // ok +                break; +              case "alices_adventures_in_wonderland.lewis_carroll.sst": +                assert(check["last_object_number"] == +                  "805","last object_number expected to be: 805 rather than " ~ check["last_object_number"]); // 808 +                break; +              case "autonomy_markup0.sst": +                assert(check["last_object_number"] == +                  "77","last object_number expected to be: 77 rather than " ~ check["last_object_number"]); // ok endnotes +                // assert(check["last_object_number"] == "78","last object_number expected to be: 78 rather than " ~ check["last_object_number"]); +                break; +              case "content.cory_doctorow.sst": +                assert(check["last_object_number"] == +                  "953","last object_number expected to be: 953 rather than " ~ check["last_object_number"]); // 1007 way off, check object_number off switches +                // assert(check["last_object_number"] == "953","last object_number expected to be: 953 rather than " ~ check["last_object_number"]); +                break; +              case "democratizing_innovation.eric_von_hippel.sst": +                // fixed ERROR! range violation, broken check! endnotes, bookindex, biblio +                // error in bookindex ... (ch1; ch6; ch8 ) +                assert(check["last_object_number"] == +                  "905","last object_number expected to be: 905 rather than " ~ check["last_object_number"]); // 911 +                break; +              case "down_and_out_in_the_magic_kingdom.cory_doctorow.sst": +                assert(check["last_object_number"] == +                  "1417","last object_number expected to be: 1417 rather than " ~ check["last_object_number"]); // 1455 check object_number off switches +                break; +              case "for_the_win.cory_doctorow.sst": +                assert(check["last_object_number"] == +                  "3510","last object_number expected to be: 3510 rather than " ~ check["last_object_number"]); // 3569 check object_number off switches +                break; +              case "free_as_in_freedom_2.richard_stallman_and_the_free_software_revolution.sam_williams.richard_stallman.sst": +                assert(check["last_object_number"] == +                  "1082","last object_number expected to be: 1082 rather than " ~ check["last_object_number"]); // check 1079 too few +                break; +              case "free_culture.lawrence_lessig.sst": +                assert(check["last_object_number"] == +                  "1330","last object_number expected to be: 1330 rather than " ~ check["last_object_number"]); // 1312 +                // fixed ERROR! range violation, broken check! +                // error in bookindex ... sections piracy (ch1) & property (ch10 market concentration) fixed +                break; +              case "free_for_all.peter_wayner.sst": // endnotes, bookindex, biblio +                assert(check["last_object_number"] == +                  "1559","last object_number expected to be: 1559 rather than " ~ check["last_object_number"]); // 1560, check object_number off switches, has endnotes so 2 too many +                // assert(check["last_object_number"] == "1559","last object_number expected to be: 1559 rather than " ~ check["last_object_number"]); +                break; +              case "gpl2.fsf.sst": +                assert(check["last_object_number"] == +                  "65","last object_number expected to be: 65 rather than " ~ check["last_object_number"]); // ok endnotes? check +                // assert(check["last_object_number"] == "66","last object_number expected to be: 66 rather than " ~ check["last_object_number"]); +                break; +              case "gpl3.fsf.sst": +                assert(check["last_object_number"] == +                  "123","last object_number expected to be: 123 rather than " ~ check["last_object_number"]); // ok +                break; +              case "gullivers_travels.jonathan_swift.sst": +                assert(check["last_object_number"] == +                  "668","last object_number expected to be: 668 rather than " ~ check["last_object_number"]); // 674 +                break; +              case "little_brother.cory_doctorow.sst": +                assert(check["last_object_number"] == +                  "3130","last object_number expected to be: 3130 rather than " ~ check["last_object_number"]); // 3204, check object_number off switches +                break; +              case "the_cathedral_and_the_bazaar.eric_s_raymond.sst": +                assert(check["last_object_number"] == +                  "258","last object_number expected to be: 258 rather than " ~ check["last_object_number"]); // ok +                break; +              case "the_public_domain.james_boyle.sst": +                assert(check["last_object_number"] == +                  "970","last object_number expected to be: 970 rather than " ~ check["last_object_number"]); // 978 +                break; +              case "the_wealth_of_networks.yochai_benkler.sst": // endnotes, bookindex +                assert(check["last_object_number"] == +                  "829","last object_number expected to be: 829 rather than " ~ check["last_object_number"]); // ok +                // assert(check["last_object_number"] == "832","last object_number expected to be: 832 rather than " ~ check["last_object_number"]); +                // has endnotes and bookindex, issue with sisu.rb +                break; +              case "through_the_looking_glass.lewis_carroll.sst": +                assert(check["last_object_number"] == +                  "949","last object_number expected to be: 949 rather than " ~ check["last_object_number"]); // 955 +                break; +              case "two_bits.christopher_kelty.sst": // endnotes, bookindex, biblio +                assert(check["last_object_number"] == +                  "1190","last object_number expected to be: 1190 rather than " ~ check["last_object_number"]); // 1191 +                // assert(check["last_object_number"] == "1193","last object_number expected to be: 1193 rather than " ~ check["last_object_number"]); // 1191 ok? +                // has endnotes and bookindex, issue with sisu.rb +                break; +                // fixed ERROR! range violation! +                // error in bookindex ... (ch3 the movement) +              case "un_contracts_international_sale_of_goods_convention_1980.sst": +                assert(check["last_object_number"] == +                  "377","last object_number expected to be: 377 rather than " ~ check["last_object_number"]); // ok +                break; +              case "viral_spiral.david_bollier.sst": // endnotes, bookindex +                assert(check["last_object_number"] == +                  "1078","last object_number expected to be: 1078 rather than " ~ check["last_object_number"]); // 1100 +                // fixed ERROR! range violation! +                // error in bookindex ... (ch7 ... building the cc machine, an extra semi colon) +                break; +              default: +                writeln(doc_matters.src.filename); +                break; +              } +            } +          } +        } +        debug(checkdoc) { +          void out_segnames(S,T)( +            const S  contents, +                  T  doc_matters, +          ) { +            foreach (key; doc_matters.xml.keys_seq.seg) { +              if (contents[key].length > 1) { +                foreach (obj; contents[key]) { +                  if (obj.heading_lev_markup == 4) { +                    writeln(obj.ptr_html_segnames, ". (", doc_matters.xml.segnames[obj.ptr_html_segnames], ") -> ",  obj.text); +                  } +                } +              } +            } +          } +        } +        debug(checkdoc) { +          void out_toc(S)( +            const S  contents, +            string                   key, +          ) { +            if (contents[key].length > 1) { +              string indent_spaces; +              foreach (obj; contents[key]) { +                indent_spaces=markup.indent_by_spaces_provided(obj.indent_hang); +                writefln( +                  "%s%s", +                  indent_spaces, +                  obj.text +                ); +              } +            } +          } +        } +        debug(checkdoc) { +          void out_endnotes(S)( +            const S  contents, +            string                   key, +          ) { +            if (contents[key].length > 1) { +              foreach (obj; contents[key]) { +                writefln( +                  "[%s]\n%s", +                  obj.metainfo.is_a, +                  obj.text +                ); +              } +            } +          } +        } +        debug(checkdoc) { +          void out_bookindex(S)( +            const S  contents, +            string                   key, +          ) { +            if (contents[key].length > 1) { +              foreach (obj; contents[key]) { +                writefln( +                  "[%s][%s]\n%s", +                  obj.object_number, +                  obj.metainfo.is_a, +                  obj.text +                ); +              } +            } +          } +        } +      } +    } +  } +} diff --git a/src/doc_reform/meta/metadoc.d b/src/doc_reform/meta/metadoc.d new file mode 100644 index 0000000..7c0e90d --- /dev/null +++ b/src/doc_reform/meta/metadoc.d @@ -0,0 +1,177 @@ +module doc_reform.meta.metadoc; +template SiSUabstraction() { +  import +    std.getopt, +    std.file, +    std.path, +    std.process; +  import +    doc_reform.meta, +    doc_reform.meta.metadoc_summary, +    doc_reform.meta.metadoc_from_src, +    doc_reform.meta.conf_make_meta_structs, +    doc_reform.meta.conf_make_meta_toml, +    doc_reform.meta.conf_make_meta_json, +    doc_reform.meta.defaults, +    doc_reform.meta.doc_debugs, +    doc_reform.meta.rgx, +    doc_reform.source.paths_source, +    doc_reform.source.read_config_files, +    doc_reform.source.read_source_files, +    doc_reform.output.hub; +  mixin SiSUrgxInit; +  mixin contentJSONtoSiSUstruct; +  mixin SiSUbiblio; +  mixin SiSUrgxInitFlags; +  mixin outputHub; +  enum headBody { header, body_content, insert_file_list, image_list } +  enum makeMeta { make, meta } +  enum docAbst  { doc_abstraction, section_keys, segnames, segnames_0_4, images } +  static auto rgx = Rgx(); +  auto SiSUabstraction(E,O,M)( +    E _env, +    O _opt_action, +    M _manifest +  ){ +    auto _config_document_struct = readConfigDoc!()(_manifest, _env);    // document config file +    auto _config_local_site_struct = readConfigSite!()(_manifest, _env); // local site config +    ConfCompositePlus _make_and_meta_struct; +    _make_and_meta_struct = configParseTOMLreturnSiSUstruct!()(_make_and_meta_struct, _config_document_struct); +    _make_and_meta_struct = configParseTOMLreturnSiSUstruct!()(_make_and_meta_struct, _config_local_site_struct); +    /+ ↓ read file (filename with path) +/ +    /+ ↓ file tuple of header and content +/ +    debug(steps) { +      writeln("step1 commence → (get document header & body & insert file list & if needed image list)" +      ); +    } +    auto _header_body_insertfilelist_imagelist +      = SiSUrawMarkupContent!()(_opt_action, _manifest.src.path_and_fn); +    static assert(!isTypeTuple!(_header_body_insertfilelist_imagelist)); +    static assert(_header_body_insertfilelist_imagelist.length==4); +    debug(steps) { +      writeln("- step1 complete"); +    } +    debug(header_and_body) { +      writeln(header); +      writeln(_header_body_insertfilelist_imagelist.length); +      writeln(_header_body_insertfilelist_imagelist.length[headBody.body_content][0]); +    } +    /+ ↓ split header into make and meta +/ +    debug(steps) { +      writeln("step2 commence → (read document header - toml, return struct)"); +    } +    _make_and_meta_struct = +    docHeaderMakeAndMetaTupTomlExtractAndConvertToStruct!()( +      _make_and_meta_struct, +      _header_body_insertfilelist_imagelist[headBody.header] +    ); +    debug(steps) { +      writeln("- step2 complete"); +    } +    /+ ↓ document abstraction: process document, return abstraction as tuple +/ +    debug(steps) { +      writeln("step3 commence → (document abstraction (da); da keys; segnames; doc_matters)"); +    } +    auto da = SiSUdocAbstraction!()( +      _header_body_insertfilelist_imagelist[headBody.body_content], +      _make_and_meta_struct, +      _opt_action, +      _manifest, +      true, +    ); +    static assert(!isTypeTuple!(da)); +    static assert(da.length==5); +    auto doc_abstraction = da[docAbst.doc_abstraction]; /+ head ~ toc ~ body ~ endnotes_seg ~ glossary ~ bibliography ~ bookindex ~ blurb; +/ +    auto _document_section_keys_sequenced = da[docAbst.section_keys]; +    string[] _doc_html_segnames = da[docAbst.segnames]; +    string[] _doc_epub_segnames_0_4 = da[docAbst.segnames_0_4]; +    auto _images = da[docAbst.images]; +    debug(steps) { +      writeln("- step3 complete"); +    } +    debug(steps) { +      writeln("step4 commence → (doc_matters)"); +    } +    struct DocumentMatters { +      auto conf_make_meta() { // TODO meld with all make instructions +        return _make_and_meta_struct; +      } +      auto env() { +        struct Env_ { +          auto pwd() { +            return _manifest.env.pwd; +          } +          auto home() { +            return _manifest.env.home; +          } +        } +        return Env_(); +      } +      auto opt() { +        struct Opt_ { +          auto action() { +            /+ getopt options, commandline instructions, raw +             - processing instructions --epub --html etc. +             - command line config instructions --output-path +            +/ +            return _opt_action; +          } +        } +        return Opt_(); +      } +      auto src() { +        return _manifest.src; +      } +      auto src_path_info() { +        return SiSUpathsSRC!()(_manifest.env.pwd, _manifest.src.file_with_absolute_path); // would like (to have and use) relative path +      } +      auto srcs() { +        struct SRC_ { +          auto file_insert_list() { +            return _header_body_insertfilelist_imagelist[headBody.insert_file_list]; +          } +          auto image_list() { +            return _images; +          } +        } +        return SRC_(); +      } +      auto pod() { +        return _manifest.pod; +      } +      auto sqlite() { +        struct SQLite_ { +          string filename() { +            return _opt_action.sqlite_filename; +          } +        } +        return SQLite_(); +      } +      auto xml() { +        struct XML_ { +          auto keys_seq() { +            /+ contains .seg & .scroll sequences +/ +            return _document_section_keys_sequenced; +          } +          string[] segnames() { +            return _doc_html_segnames; +          } +          string[] segnames_lv_0_to_4() { +            return _doc_epub_segnames_0_4; +          } +        } +        return XML_(); +      } +      auto output_path() { +        return _manifest.output.path; +      } +    } +    auto doc_matters = DocumentMatters(); +    debug(steps) { +      writeln("- step4 complete"); +    } +    auto t = tuple(doc_abstraction, doc_matters); +    static assert(t.length==2); +    return t; +  } +} diff --git a/src/doc_reform/meta/metadoc_from_src.d b/src/doc_reform/meta/metadoc_from_src.d new file mode 100644 index 0000000..c4a12bb --- /dev/null +++ b/src/doc_reform/meta/metadoc_from_src.d @@ -0,0 +1,6322 @@ +/++ +  document abstraction: +  abstraction of sisu markup for downstream processing +  metadoc_from_src.d ++/ +module doc_reform.meta.metadoc_from_src; +template SiSUdocAbstraction() { +  /+ ↓ abstraction imports +/ +  import doc_reform.meta; +  import +    std.algorithm, +    std.container, +    std.file, +    std.json, +    std.path; +  import +    doc_reform.meta.defaults, +    doc_reform.meta.object_setter, +    doc_reform.meta.rgx; +  /+ ↓ abstraction mixins +/ +  mixin ObjectSetter; +  mixin InternalMarkup; +  mixin SiSUrgxInit; +  /+ ↓ abstraction struct init +/ +  /+ initialize +/ +  ObjGenericComposite[][string] the_table_of_contents_section; +  ObjGenericComposite[] the_document_head_section, the_document_body_section, the_bibliography_section, the_glossary_section, the_blurb_section; +  ObjGenericComposite[] the_dom_tail_section; +  string[string] an_object, processing; +  string an_object_key; +  string[] anchor_tags; +  string anchor_tag_; +  string segment_anchor_tag_that_object_belongs_to; +  string segment_anchor_tag_that_object_belongs_to_uri; +  /+ enum +/ +  enum State { off, on } +  enum TriState { off, on, closing } +  enum DocStructMarkupHeading { +    h_sect_A, +    h_sect_B, +    h_sect_C, +    h_sect_D, +    h_text_1, +    h_text_2, +    h_text_3, +    h_text_4, +    h_text_5, // extra level, drop +    content_non_header +  } // header section A-D; header text 1-4 +  enum OCNstatus { on, off, bkidx, closing, reset, } +  enum OCNtype { ocn, non, bkidx, } +  /+ biblio variables +/ +  string biblio_tag_name, biblio_tag_entry, st; +  string[] biblio_arr_json; +  string biblio_entry_str_json; +  JSONValue[] bib_arr_json; +  int bib_entry; +  /+ counters +/ +  int cntr, previous_count, previous_length; +  bool reset_note_numbers=true; +  int[string] line_occur; +  int html_segnames_ptr=0; +  int html_segnames_ptr_cntr=0; +  int verse_line, heading_ptr; +  /+ paragraph attributes +/ +  int[string] indent; +  bool bullet = true; +  string content_non_header = "8"; +  static auto obj_im = ObjInlineMarkup(); +  static auto obj_att = ObjAttributes(); +  /+ ocn +/ +  struct OCNset { +    int digit; +    int on; +    int off; +    int bkidx; +    int type; +  } +  OCNset obj_cite_digits; +  int obj_cite_digit_, obj_cite_digit_off, obj_cite_digit_bkidx, obj_cite_digit_type; +  auto object_citation_number = OCNemitter(); +  int[] dom_structure_markedup_tags_status         = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +  int[] dom_structure_markedup_tags_status_buffer  = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +  int[] dom_structure_collapsed_tags_status        = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +  int[] dom_structure_collapsed_tags_status_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +  enum DomTags { none, open, close, close_and_open, open_still, } +  pure auto obj_heading_ancestors(O)( +    O          obj, +    string[]   lv_ancestors_txt, +  ) { +    switch (obj.metainfo.heading_lev_markup) { +    case 0: +      lv_ancestors_txt[0] = obj.text.to!string; +      foreach(k; 1..8) { +        lv_ancestors_txt[k] = ""; +      } +      goto default; +    case 1: +      lv_ancestors_txt[1] = obj.text.to!string; +      foreach(k; 2..8) { +        lv_ancestors_txt[k] = ""; +      } +      goto default; +    case 2: +      lv_ancestors_txt[2] = obj.text.to!string; +      foreach(k; 3..8) { +        lv_ancestors_txt[k] = ""; +      } +      goto default; +    case 3: +      lv_ancestors_txt[3] = obj.text.to!string; +      foreach(k; 4..8) { +        lv_ancestors_txt[k] = ""; +      } +      goto default; +    case 4: +      lv_ancestors_txt[4] = obj.text.to!string; +      foreach(k; 5..8) { +        lv_ancestors_txt[k] = ""; +      } +      goto default; +    case 5: +      lv_ancestors_txt[5] = obj.text.to!string; +      foreach(k; 6..8) { +        lv_ancestors_txt[k] = ""; +      } +      goto default; +    case 6: +      lv_ancestors_txt[6] = obj.text.to!string; +      lv_ancestors_txt[7] = ""; +      goto default; +    case 7: +      lv_ancestors_txt[7] = obj.text.to!string; +      goto default; +    default: +      obj.tags.heading_ancestors_text = lv_ancestors_txt.dup; +    } +    return obj; +  } +  pure auto obj_dom_structure_set_markup_tags(O)( +    O           obj, +    int[]       dom, +    int         lev +  ) { +    foreach (i; 0 .. 8) { +      if (i < lev) { +        if (dom[i] == DomTags.open +           || dom[i] == DomTags.close_and_open +        ) { +          dom[i] = DomTags.open_still; +        } else if (dom[i] == DomTags.close) { +          dom[i] = DomTags.none; +        } +      } else if (i == lev) { +        if (lev  == 0 +          && dom[i] == DomTags.open_still +        ) { +          dom[i] = DomTags.close; +        } else if (dom[i] == DomTags.open +          || dom[i] == DomTags.open_still +          || dom[i] == DomTags.close_and_open +        ) { +          dom[i] = DomTags.close_and_open; +        } else { +          dom[i] = DomTags.open; +        } +      } else if (i > lev) { +        if (dom[i] == DomTags.close) { +          dom[i] = DomTags.none; +        } else if (dom[i] == DomTags.open +          || dom[i] == DomTags.open_still +          || dom[i] == DomTags.close_and_open +        ) { +          dom[i] = DomTags.close; +        } +      } +    } +    debug(dom_magic_numbers) { +      writeln("marked up: ", lev, ": ", dom); +    } +    obj.metainfo.dom_structure_markedup_tags_status = dom.dup; +    return obj; +  } +  pure auto obj_dom_set_collapsed_tags(O)( +    O           obj, +    int[]       dom, +    int         lev +  ) { +    foreach (i; 0 .. 8) { +      if (i < lev) { +        if (dom[i] == DomTags.open +           || dom[i] == DomTags.close_and_open +        ) { +          dom[i] = DomTags.open_still; +        } else if (dom[i] == DomTags.close) { +          dom[i] = DomTags.none; +        } +      } else if (i == lev) { +        if (lev  == 0 +          && dom[i] == DomTags.open_still +        ) { +          dom[i] = DomTags.close; +        } else if (dom[i] == DomTags.open +          || dom[i] == DomTags.open_still +          || dom[i] == DomTags.close_and_open +        ) { +          dom[i] = DomTags.close_and_open; +        } else { +          dom[i] = DomTags.open; +        } +      } else if (i > lev) { +        if (dom[i] == DomTags.close) { +          dom[i] = DomTags.none; +        } else if (dom[i] == DomTags.open +          || dom[i] == DomTags.open_still +          || dom[i] == DomTags.close_and_open +        ) { +          dom[i] = DomTags.close; +        } +      } +    } +    debug(dom_magic_numbers) { +      writeln("collapsed: ", lev, ": ", dom); +    } +    obj.metainfo.dom_structure_collapsed_tags_status = dom.dup; +    return obj; +  } +  static auto ocn_emit(int ocn_status_flag) { +    return object_citation_number.ocn_emitter(ocn_status_flag); +  } +  /+ book index variables +/ +  string book_idx_tmp; +  string[][string][string] bookindex_unordered_hashes; +  /+ node +/ +  ObjGenericComposite comp_obj_heading, comp_obj_location, comp_obj_block, comp_obj_code, comp_obj_poem_ocn, comp_obj_comment; +  auto node_construct = NodeStructureMetadata(); +  enum sObj { content, anchor_tags, notes_reg, notes_star, links, image_no_dimensions } +  /+ ↓ abstract marked up document +/ +  auto SiSUdocAbstraction(Src,CMM,Opt,Mfst)( +    Src                  markup_sourcefile_content, +    CMM                  conf_make_meta, +    Opt                  opt_action, +    Mfst                 manifest_matter, +    bool                 _new_doc +  ) { +    static auto rgx = Rgx(); +    debug(asserts) { +      static assert(is(typeof(markup_sourcefile_content) == char[][])); +    } +    /+ ↓ abstraction init +/ +    scope(success) { +    } +    scope(failure) { +    } +    scope(exit) { +      destroy(the_document_head_section); +      destroy(the_table_of_contents_section); +      destroy(the_document_body_section); +      destroy(the_bibliography_section); +      destroy(an_object); +      destroy(processing); +      destroy(biblio_arr_json); +      previous_length=0; +      reset_note_numbers=true; +    } +    mixin SiSUrgxInitFlags; +    mixin SiSUnode; +    auto node_para_int_    = node_metadata_para_int; +    auto node_para_str_    = node_metadata_para_str; +    ObjGenericComposite comp_obj_heading_, comp_obj_para, comp_obj_toc; +    line_occur = [ +      "heading"  : 0, +      "para"     : 0, +      "glossary" : 0, +      "blurb"    : 0, +    ]; +    auto obj_type_status = flags_type_init; +    string[string] object_number_poem = [ +      "start" : "", +      "end"   : "" +    ]; +    string[] lv_ancestors_txt = [ "", "", "", "", "", "", "", "", ]; +    int[string] lv = [ +      "lv" : State.off, +      "h0" : State.off, +      "h1" : State.off, +      "h2" : State.off, +      "h3" : State.off, +      "h4" : State.off, +      "h5" : State.off, +      "h6" : State.off, +      "h7" : State.off, +      "lev_int_collapsed" : 0, +    ]; +    int[string] collapsed_lev = [ +      "h0" : State.off, +      "h1" : State.off, +      "h2" : State.off, +      "h3" : State.off, +      "h4" : State.off, +      "h5" : State.off, +      "h6" : State.off, +      "h7" : State.off +    ]; +    string[string] heading_match_str = [ +      "h_A": "^(none)", +      "h_B": "^(none)", +      "h_C": "^(none)", +      "h_D": "^(none)", +      "h_1": "^(none)", +      "h_2": "^(none)", +      "h_3": "^(none)", +      "h_4": "^(none)" +    ]; +    auto heading_match_rgx = [ +      "h_A": regex(r"^(none)"), +      "h_B": regex(r"^(none)"), +      "h_C": regex(r"^(none)"), +      "h_D": regex(r"^(none)"), +      "h_1": regex(r"^(none)"), +      "h_2": regex(r"^(none)"), +      "h_3": regex(r"^(none)"), +      "h_4": regex(r"^(none)") +    ]; +    string _anchor_tag; +    string toc_txt_; +    an_object["glossary_nugget"]                                   = ""; +    an_object["blurb_nugget"]                                      = ""; +    comp_obj_heading_                                              = comp_obj_heading_.init; +    comp_obj_heading_.metainfo.is_of_part                          = "frontmatter"; +    comp_obj_heading_.metainfo.is_of_section                       = "toc"; +    comp_obj_heading_.metainfo.is_of_type                          = "para"; +    comp_obj_heading_.metainfo.is_a                                = "heading"; +    comp_obj_heading_.text                                         = "Table of Contents"; +    comp_obj_heading_.metainfo.ocn                                 = 0; +    comp_obj_heading_.metainfo.object_number_off                   = ""; +    comp_obj_heading_.metainfo.object_number_type                  = 0; +    comp_obj_heading_.tags.segment_anchor_tag                      = "toc"; +    comp_obj_heading_.metainfo.heading_lev_markup                  = 4; +    comp_obj_heading_.metainfo.heading_lev_collapsed               = 1; +    comp_obj_heading_.metainfo.parent_ocn                          = 1; +    comp_obj_heading_.metainfo.parent_lev_markup                   = 0; +    comp_obj_heading_.ptr.html_segnames                            = html_segnames_ptr; +    comp_obj_heading_.tags.anchor_tags                             = ["toc"]; +    comp_obj_heading_.metainfo.dom_structure_markedup_tags_status  = [ 1, 1, 0, 0, 1, 0, 0, 0]; +    comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 1, 0, 0, 0, 0, 0]; +    auto toc_head                                                  = comp_obj_heading_; +    html_segnames_ptr_cntr++; +    the_table_of_contents_section = [ +      "seg": [toc_head], +      "scroll": [toc_head], +    ]; +    static auto mkup = InlineMarkup(); +    static auto munge = ObjInlineMarkupMunge(); +    auto note_section = NotesSection(); +    auto bookindex_extract_hash = BookIndexNuggetHash(); +    string[][string] lev4_subtoc; +    string[] html_segnames=["toc"]; +    int cnt1 = 1; int cnt2 = 1; int cnt3 = 1; +    /+ abstraction init ↑ +/ +    enum Substitute { match, markup, } +    debug (substitutions) { +      writeln(__LINE__, ":", __FILE__, ": DEBUG substitutions:"); +      if (!(conf_make_meta.make.headings.empty)) { +        writeln(conf_make_meta.make.headings); +      } +      if (conf_make_meta.make.substitute) { +        foreach(substitution_pair; conf_make_meta.make.substitute) { +           writeln("regex to match:       ", substitution_pair[Substitute.match]); +           writeln("substitution to make: ", substitution_pair[Substitute.markup]); +        } +      } +      if (conf_make_meta.make.bold) { +        writeln("regex to match:       ", conf_make_meta.make.bold[Substitute.match]); +        writeln("substitution to make: ", conf_make_meta.make.bold[Substitute.markup]); +      } +      if (conf_make_meta.make.emphasis) { +        writeln("regex to match:       ", conf_make_meta.make.emphasis[Substitute.match]); +        writeln("substitution to make: ", conf_make_meta.make.emphasis[Substitute.markup]); +      } +      if (conf_make_meta.make.italics) { +        writeln("regex to match:       ", conf_make_meta.make.italics[Substitute.match]); +        writeln("substitution to make: ", conf_make_meta.make.italics[Substitute.markup]); +      } +    } +    /+ ↓ ↻ loop markup document/text line by line +/ +    srcDocLoop: +    foreach (line; markup_sourcefile_content) { +      // "line" variable can be empty but should never be null +      /+ ↓ markup document/text line by line +/ +      /+ scope +/ +      scope(exit) { +      } +      scope(failure) { +        stderr.writefln( +          "%s\n%s\n%s:%s failed here:\n  line: %s", +          __MODULE__, __FUNCTION__, +          __FILE__, __LINE__, +          line, +        ); +      } +      line = (line).replaceAll(rgx.true_dollar, "$$$$"); +        /+ dollar represented as $$ needed to stop submatching on $ +           (substitutions using ${identifiers} must take into account (i.e. happen earlier)) +         +/ +      debug(source) { +        writeln(line); +      } +      debug(srclines) { +        if (!line.empty) { +          writefln( +            "* %s", +            line +          ); +        } +      } +      if (!line.empty) { +        obj_type_status = _check_ocn_status_(line, obj_type_status); +      } +      if (obj_type_status["code"] == TriState.on) { +        /+ block object: code +/ +        _code_block_(line, an_object, obj_type_status); +        continue; +      } else if (!matchFirst(line, rgx.skip_from_regular_parse)) { +        /+ object other than "code block" object +           (includes regular text paragraph, headings & blocks other than code) +/ +        /+ heading, glossary, blurb, poem, group, block, quote, table +/ +        if (line.matchFirst(rgx.heading_biblio) +        || (obj_type_status["biblio_section"] == State.on +        && (!(line.matchFirst(rgx.heading_blurb_glossary))) +        && (!(line.matchFirst(rgx.heading))) +        && (!(line.matchFirst(rgx.comment))))) { +          /+ within section (block object): biblio +/ +          obj_type_status["glossary_section"] = State.off; +          obj_type_status["biblio_section"]   = State.on; +          obj_type_status["blurb_section"]    = State.off; +          if (opt_action.backmatter && opt_action.section_biblio) { +            _biblio_block_(line, obj_type_status, bib_entry, biblio_entry_str_json, biblio_arr_json); +            debug(bibliobuild) { +              writeln("-  ", biblio_entry_str_json); +              writeln("-> ", biblio_arr_json.length); +            } +          } +          continue; +        } else if (line.matchFirst(rgx.heading_glossary) +        || (obj_type_status["glossary_section"] == State.on +        && (!(line.matchFirst(rgx.heading_biblio_blurb))) +        && (!(line.matchFirst(rgx.heading))) +        && (!(line.matchFirst(rgx.comment))))) { +          /+ within section (block object): glossary +/ +          debug(glossary) { +            writeln(__LINE__); +            writeln(line); +          } +          obj_type_status["glossary_section"] = State.on; +          obj_type_status["biblio_section"]   = State.off; +          obj_type_status["blurb_section"]    = State.off; +          if (opt_action.backmatter && opt_action.section_glossary) { +            indent=[ +              "hang_position" : 0, +              "base_position" : 0, +            ]; +            bullet = false; +            obj_type_status["para"] = State.on; +            line_occur["para"] = State.off; +            an_object_key="glossary_nugget"; // +            if (line.matchFirst(rgx.heading_glossary)) { +              comp_obj_heading_                                = comp_obj_heading_.init; +              comp_obj_heading_.metainfo.is_of_part            = "backmatter"; +              comp_obj_heading_.metainfo.is_of_section         = "glossary"; +              comp_obj_heading_.metainfo.is_of_type            = "para"; +              comp_obj_heading_.metainfo.is_a                  = "heading"; +              comp_obj_heading_.text                           = "Glossary"; +              comp_obj_heading_.metainfo.ocn                   = 0; +              comp_obj_heading_.metainfo.object_number_off     = ""; +              comp_obj_heading_.metainfo.object_number_type    = 0; +              comp_obj_heading_.tags.segment_anchor_tag        = "_part_glossary"; +              comp_obj_heading_.metainfo.heading_lev_markup    = 1; +              comp_obj_heading_.metainfo.heading_lev_collapsed = 1; +              comp_obj_heading_.metainfo.parent_ocn            = 1; +              comp_obj_heading_.metainfo.parent_lev_markup     = 0; +              comp_obj_heading_.metainfo.dom_structure_markedup_tags_status  = [ 1, 1, 0, 0, 0, 0, 0, 0]; +              comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; +              the_glossary_section                             ~= comp_obj_heading_; +              comp_obj_heading_                                = comp_obj_heading_.init; +              comp_obj_heading_.metainfo.is_of_part            = "backmatter"; +              comp_obj_heading_.metainfo.is_of_section         = "glossary"; +              comp_obj_heading_.metainfo.is_of_type            = "para"; +              comp_obj_heading_.metainfo.is_a                  = "heading"; +              comp_obj_heading_.text                           = "Glossary"; +              comp_obj_heading_.metainfo.ocn                   = 0; +              comp_obj_heading_.metainfo.object_number_off     = ""; +              comp_obj_heading_.metainfo.object_number_type    = 0; +              comp_obj_heading_.tags.segment_anchor_tag        = "glossary"; +              comp_obj_heading_.metainfo.heading_lev_markup    = 4; +              comp_obj_heading_.metainfo.heading_lev_collapsed = 2; +              comp_obj_heading_.metainfo.parent_ocn            = 1; +              comp_obj_heading_.metainfo.parent_lev_markup     = 0; +              comp_obj_heading_.metainfo.dom_structure_markedup_tags_status  = [ 1, 1, 0, 0, 1, 0, 0, 0]; +              comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 1, 0, 0, 0, 0, 0]; +              comp_obj_heading_.tags.anchor_tags               = ["glossary"]; +              the_glossary_section                             ~= comp_obj_heading_; +            } else { +              _para_match_(line, an_object, an_object_key, indent, bullet, obj_type_status, line_occur); +              comp_obj_para                               = comp_obj_para.init; +              comp_obj_para.metainfo.is_of_part           = "backmatter"; +              comp_obj_para.metainfo.is_of_section        = "glossary"; +              comp_obj_para.metainfo.is_of_type           = "para"; +              comp_obj_para.metainfo.is_a                 = "glossary"; +              comp_obj_para.text                          = line.to!string.strip; +              comp_obj_para.metainfo.ocn                  = 0; +              comp_obj_para.metainfo.object_number_off    = ""; +              comp_obj_para.metainfo.object_number_type   = 0; +              comp_obj_para.attrib.indent_hang            = indent["hang_position"]; +              comp_obj_para.attrib.indent_base            = indent["base_position"]; +              comp_obj_para.attrib.bullet                 = bullet; +              the_glossary_section                        ~= comp_obj_para; +            } +            obj_type_status["ocn_status"] = OCNstatus.on; +          } +          continue; +        } else if (line.matchFirst(rgx.heading_blurb) +        || (obj_type_status["blurb_section"] == State.on +        && (!(line.matchFirst(rgx.heading_biblio_glossary))) +        && (!(line.matchFirst(rgx.heading))) +        && (!(line.matchFirst(rgx.comment))))) { +          /+ within section (block object): blurb +/ +          debug(blurb) { +            writeln(__LINE__); +            writeln(line); +          } +          obj_type_status["glossary_section"] = State.off; +          obj_type_status["biblio_section"]   = State.off; +          obj_type_status["blurb_section"]    = State.on; +          if (opt_action.backmatter && opt_action.section_blurb) { +            indent=[ +              "hang_position" : 0, +              "base_position" : 0, +            ]; +            bullet = false; +            if (auto m = line.matchFirst(rgx.para_indent)) { +              debug(paraindent) { +                writeln(line); +              } +              indent["hang_position"] = (m.captures[1]).to!int; +              indent["base_position"] = 0; +            } else if (line.matchFirst(rgx.para_bullet)) { +              debug(parabullet) { +                writeln(line); +              } +              bullet = true; +            } else if (auto m = line.matchFirst(rgx.para_indent_hang)) { +              debug(paraindenthang) { +                writeln(line); +              } +              indent=[ +                "hang_position" : (m.captures[1]).to!int, +                "base_position" : (m.captures[2]).to!int, +              ]; +            } else if (auto m = line.matchFirst(rgx.para_bullet_indent)) { +              debug(parabulletindent) { +                writeln(line); +              } +              indent=[ +                "hang_position" : (m.captures[1]).to!int, +                "base_position" : 0, +              ]; +              bullet = true; +            } +            obj_type_status["para"] = State.on; +            line_occur["para"] = State.off; +            an_object_key="blurb_nugget"; +            if (line.matchFirst(rgx.heading_blurb)) { +              comp_obj_heading_                                              = comp_obj_heading_.init; +              comp_obj_heading_.metainfo.is_of_part                          = "backmatter"; +              comp_obj_heading_.metainfo.is_of_section                       = "blurb"; +              comp_obj_heading_.metainfo.is_of_type                          = "para"; +              comp_obj_heading_.metainfo.is_a                                = "heading"; +              comp_obj_heading_.text                                         = "Blurb"; +              comp_obj_heading_.metainfo.ocn                                 = 0; +              comp_obj_heading_.metainfo.object_number_off                   = ""; +              comp_obj_heading_.metainfo.object_number_type                  = 0; +              comp_obj_heading_.tags.segment_anchor_tag                      = "_part_blurb"; +              comp_obj_heading_.metainfo.heading_lev_markup                  = 1; +              comp_obj_heading_.metainfo.heading_lev_collapsed               = 1; +              comp_obj_heading_.metainfo.parent_ocn                          = 1; +              comp_obj_heading_.metainfo.parent_lev_markup                   = 0; +              comp_obj_heading_.metainfo.dom_structure_markedup_tags_status  = [ 1, 1, 0, 0, 0, 0, 0, 0]; +              comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; +              the_blurb_section                                              ~= comp_obj_heading_; +              comp_obj_heading_                                              = comp_obj_heading_.init; +              comp_obj_heading_.metainfo.is_of_part                          = "backmatter"; +              comp_obj_heading_.metainfo.is_of_section                       = "blurb"; +              comp_obj_heading_.metainfo.is_of_type                          = "para"; +              comp_obj_heading_.metainfo.is_a                                = "heading"; +              comp_obj_heading_.text                                         = "Blurb"; +              comp_obj_heading_.metainfo.ocn                                 = 0; +              comp_obj_heading_.metainfo.object_number_off                   = ""; +              comp_obj_heading_.metainfo.object_number_type                  = 0; +              comp_obj_heading_.tags.segment_anchor_tag                      = "blurb"; +              comp_obj_heading_.metainfo.heading_lev_markup                  = 4; +              comp_obj_heading_.metainfo.heading_lev_collapsed               = 2; +              comp_obj_heading_.metainfo.parent_ocn                          = 1; +              comp_obj_heading_.metainfo.parent_lev_markup                   = 0; +              comp_obj_heading_.tags.anchor_tags                             = ["blurb"]; +              comp_obj_heading_.metainfo.dom_structure_markedup_tags_status  = [ 1, 1, 0, 0, 1, 0, 0, 0]; +              comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 1, 0, 0, 0, 0, 0]; +              the_blurb_section                                              ~= comp_obj_heading_; +            } else if (line.matchFirst(rgx.heading) +            && (opt_action.backmatter && opt_action.section_blurb)) { +              comp_obj_heading_                                = comp_obj_heading_.init; +              comp_obj_heading_.metainfo.is_of_part            = "backmatter"; +              comp_obj_heading_.metainfo.is_of_section         = "blurb"; +              comp_obj_heading_.metainfo.is_of_type            = "para"; +              comp_obj_heading_.metainfo.is_a                  = "heading"; +              comp_obj_heading_.text                           = line.to!string; +              comp_obj_heading_.metainfo.ocn                   = 0; +              comp_obj_heading_.metainfo.object_number_off     = ""; +              comp_obj_heading_.metainfo.object_number_type    = 0; +              comp_obj_heading_.tags.segment_anchor_tag        = "blurb"; +              comp_obj_heading_.metainfo.heading_lev_markup    = an_object["lev_markup_number"].to!int;    // make int, remove need to conv +              comp_obj_heading_.metainfo.heading_lev_collapsed = an_object["lev_collapsed_number"].to!int; // make int, remove need to conv +              comp_obj_heading_.metainfo.parent_ocn            = 1; +              comp_obj_heading_.metainfo.parent_lev_markup     = 0; +              the_blurb_section                                ~= comp_obj_heading_; +            } else { +              _para_match_(line, an_object, an_object_key, indent, bullet, obj_type_status, line_occur); +              comp_obj_para                               = comp_obj_para.init; +              comp_obj_para.metainfo.is_of_part           = "backmatter"; +              comp_obj_para.metainfo.is_of_section        = "blurb"; +              comp_obj_para.metainfo.is_of_type           = "para"; +              comp_obj_para.metainfo.is_a                 = "blurb"; +              comp_obj_para.text                          = munge.url_links(line.to!string.strip).replaceFirst(rgx.para_attribs, ""); +              comp_obj_para.metainfo.ocn                  = 0; +              comp_obj_para.metainfo.object_number_off    = ""; +              comp_obj_para.metainfo.object_number_type   = 0; +              comp_obj_para.attrib.indent_hang            = indent["hang_position"]; +              comp_obj_para.attrib.indent_base            = indent["base_position"]; +              comp_obj_para.has.inline_links              = true; +              comp_obj_para.attrib.bullet                 = bullet; +              the_blurb_section                           ~= comp_obj_para; +            } +            obj_type_status["ocn_status"] = OCNstatus.on; +          } +          continue; +        } else if (obj_type_status["quote"] == TriState.on) { +          /+ within block object: quote +/ +          line = _doc_header_and_make_substitutions_(line, conf_make_meta); +          line = _doc_header_and_make_substitutions_fontface_(line, conf_make_meta); +          _quote_block_(line, an_object, obj_type_status); +          continue; +        /+ within block object: group +/ +        } else if (obj_type_status["group"] == TriState.on) { +          /+ within block object: group +/ +          line = _doc_header_and_make_substitutions_(line, conf_make_meta); +          line = _doc_header_and_make_substitutions_fontface_(line, conf_make_meta); +          line = (line) +            .replaceAll(rgx.para_delimiter, mkup.br_paragraph ~ "$1"); +          _group_block_(line, an_object, obj_type_status); +          continue; +        } else if (obj_type_status["block"] == TriState.on) { +          /+ within block object: block +/ +          line = _doc_header_and_make_substitutions_(line, conf_make_meta); +          line = _doc_header_and_make_substitutions_fontface_(line, conf_make_meta); +          if (auto m = line.match(rgx.spaces_line_start)) { +            line = (line) +              .replaceAll(rgx.spaces_line_start, (m.captures[1]).translate([ ' ' : mkup.nbsp ])); +          } +          if (auto m = line.match(rgx.spaces_multiple)) { +            line = (line) +              .replaceAll(rgx.spaces_multiple, (m.captures[1]).translate([ ' ' : mkup.nbsp ])); +          } +          _block_block_(line, an_object, obj_type_status); +          continue; +        } else if (obj_type_status["poem"] == TriState.on) { +          /+ within block object: poem +/ +          _poem_block_(line, an_object, obj_type_status, cntr, object_number_poem, conf_make_meta); +          continue; +        } else if (obj_type_status["table"] == TriState.on) { +          /+ within block object: table +/ +          _table_block_(line, an_object, obj_type_status, conf_make_meta); +          continue; +        } else { +          /+ not within a block group +/ +          assert( +            (obj_type_status["blocks"] == TriState.off) +            || (obj_type_status["blocks"] == TriState.closing), +            "block status: none or closed" +          ); +          assertions_flag_types_block_status_none_or_closed(obj_type_status); +          if (line.matchFirst(rgx.block_open)) { +            if (line.matchFirst(rgx.block_poem_open)) { +              /+ poem to verse exceptions! +/ +              object_reset(an_object); +              processing.remove("verse"); +              object_number_poem["start"] = obj_cite_digits.on.to!string; +            } +            _start_block_(line, obj_type_status, object_number_poem); +            continue; +          } else if (!line.empty) { +            /+ line not empty +/ +            /+ non blocks (headings, paragraphs) & closed blocks +/ +            assert( +              !line.empty, +              "line tested, line not empty surely:\n  \"" ~ line ~ "\"" +            ); +            assert( +              (obj_type_status["blocks"] == TriState.off) +              || (obj_type_status["blocks"] == TriState.closing), +              "code block status: none or closed" +            ); +            if (obj_type_status["blocks"] == TriState.closing) { +              debug(check) {                           // block +                writeln(__LINE__); +                writeln(line); +              } +              assert( +                line.matchFirst(rgx.book_index) +                || line.matchFirst(rgx.book_index_open) +                || obj_type_status["book_index"] == State.on, +                "\nblocks closed, unless followed by book index, non-matching line:\n  \"" +                ~ line ~ "\"" +              ); +            } +            if (line.matchFirst(rgx.book_index) +            || line.matchFirst(rgx.book_index_open) +            || obj_type_status["book_index"] == State.on )  { +              /+ book_index +/ +              _book_index_(line, book_idx_tmp, an_object, obj_type_status, opt_action); +            } else { +              /+ not book_index +/ +              an_object_key="body_nugget"; +              if (auto m = matchFirst(line, rgx.comment)) { +                /+ matched comment +/ +                debug(comment) { +                  writeln(line); +                } +                an_object[an_object_key]                ~= line ~= "\n"; +                comp_obj_comment                        = comp_obj_comment.init; +                comp_obj_comment.metainfo.is_of_part    = "comment"; // breaks flow +                comp_obj_comment.metainfo.is_of_section = "comment"; // breaks flow +                comp_obj_comment.metainfo.is_of_type    = "comment"; +                comp_obj_comment.metainfo.is_a          = "comment"; +                comp_obj_comment.text                   = an_object[an_object_key].strip; +                the_document_body_section               ~= comp_obj_comment; +                _common_reset_(line_occur, an_object, obj_type_status); +                processing.remove("verse"); +                ++cntr; +              } else if (((line_occur["para"] == State.off) +              && (line_occur["heading"] == State.off)) +              && ((obj_type_status["para"] == State.off) +              && (obj_type_status["heading"] == State.off))) { +                /+ heading or para but neither flag nor line exists +/ +                if ((conf_make_meta.make.headings.length > 2) +                && (obj_type_status["make_headings"] == State.off)) { +                  /+ heading found +/ +                  _heading_found_(line, conf_make_meta.make.headings, heading_match_str, heading_match_rgx, obj_type_status); +                } +                if ((obj_type_status["make_headings"] == State.on) +                && ((line_occur["para"] == State.off) +                && (line_occur["heading"] == State.off)) +                && ((obj_type_status["para"] == State.off) +                && (obj_type_status["heading"] == State.off))) { +                  /+ heading make set +/ +                  line = _heading_make_set_(line, line_occur, heading_match_rgx, obj_type_status); +                } +                /+ TODO node info: all headings identified at this point, +                   - extract node info here?? +                   - how long can it wait? +                   - should be incorporated in composite objects +                   - should happen before endnote links set (they need to be moved down?) +                +/ +                if (line.matchFirst(rgx.heading)) { +                  /+ heading match +/ +                  line = _doc_header_and_make_substitutions_(line, conf_make_meta); +                  _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, obj_type_status, conf_make_meta); +                } else if (line_occur["para"] == State.off) { +                  /+ para match +/ +                  an_object_key="body_nugget"; +                  line = _doc_header_and_make_substitutions_(line, conf_make_meta); +                  line = _doc_header_and_make_substitutions_fontface_(line, conf_make_meta); +                  _para_match_(line, an_object, an_object_key, indent, bullet, obj_type_status, line_occur); +                } +              } else if (line_occur["heading"] > State.off) { +                /+ heading +/ +                debug(heading) { +                  writeln(line); +                } +                an_object[an_object_key] ~= line ~= "\n"; +                ++line_occur["heading"]; +              } else if (line_occur["para"] > State.off) { +                /+ paragraph +/ +                debug(para) { +                  writeln(an_object_key, "-> ", line); +                } +                line = _doc_header_and_make_substitutions_(line, conf_make_meta); +                line = _doc_header_and_make_substitutions_fontface_(line, conf_make_meta); +                an_object[an_object_key] ~= " " ~ line; +                ++line_occur["para"]; +              } +            } +          } else if (obj_type_status["blocks"] == TriState.closing) { +            /+ line empty, with blocks flag +/ +            _block_flag_line_empty_( +              bookindex_extract_hash, +              line, +              an_object, +              the_document_body_section, +              bookindex_unordered_hashes, +              obj_cite_digits, +              comp_obj_heading, +              cntr, +              obj_type_status, +              object_number_poem, +              conf_make_meta, +            ); +          } else { +            /+ line.empty, post contents, empty variables: +/ +            assert( +              line.empty, +              "\nline should be empty:\n  \"" +              ~ line ~ "\"" +            ); +            assert( +              (obj_type_status["blocks"] == State.off), +              "code block status: none" +            ); +            if ((obj_type_status["heading"] == State.on) +            && (line_occur["heading"] > State.off)) { +              /+ heading object (current line empty) +/ +              obj_cite_digits = (an_object["lev_markup_number"].to!int == 0) +              ? ocn_emit(OCNstatus.reset) +              : ocn_emit(OCNstatus.on); +              an_object["is"] = "heading"; +              an_object_key="body_nugget"; +              auto substantive_object_and_anchor_tags_tuple +                = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, _new_doc); +              an_object["substantive"] = substantive_object_and_anchor_tags_tuple[sObj.content]; +              anchor_tags = substantive_object_and_anchor_tags_tuple[sObj.anchor_tags]; +              if (_new_doc) { +                cnt1 = 1; +                cnt2 = 1; +                cnt3 = 1; +                _new_doc = false; +              } +              if ( +                an_object["lev_markup_number"].to!int == 4 +                && anchor_tags.length > 0 +              ) { +                segment_anchor_tag_that_object_belongs_to = anchor_tags[0]; +                segment_anchor_tag_that_object_belongs_to_uri = anchor_tags[0] ~ ".fnSuffix"; +                anchor_tag_ = anchor_tags[0]; +              } else if (an_object["lev_markup_number"].to!int > 4) { +                segment_anchor_tag_that_object_belongs_to = anchor_tag_; +                segment_anchor_tag_that_object_belongs_to_uri = anchor_tag_ ~ ".fnSuffix#" ~ obj_cite_digits.on.to!string; +              } else if (an_object["lev_markup_number"].to!int < 4) { +                string segn; +                switch (an_object["lev_markup_number"].to!int) { +                case 0: +                  segn = "_the_title"; +                  goto default; +                case 1: +                  segn = "_part_" ~ cnt1.to!string; +                  ++cnt1; +                  goto default; +                case 2: +                  segn = "_part_" ~  cnt1.to!string ~ "_" ~ cnt2.to!string; +                  ++cnt2; +                  goto default; +                case 3: +                  segn =  "_part_" ~  cnt1.to!string ~ "_" ~ cnt2.to!string ~ "_" ~ cnt3.to!string; +                  ++cnt3; +                  goto default; +                default: +                  segment_anchor_tag_that_object_belongs_to = segn; +                  segment_anchor_tag_that_object_belongs_to_uri = segn ~ ".fnSuffix"; +                  break; +                } +              } +              an_object["bookindex_nugget"] +                = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; +              bookindex_unordered_hashes +                = bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_digits, segment_anchor_tag_that_object_belongs_to); +              /+ (incrementally build toc) table of contents here! +/ +              _anchor_tag=to!string(obj_cite_digits.on); +              the_table_of_contents_section = obj_im.table_of_contents_gather_headings( +                an_object, +                conf_make_meta, +                segment_anchor_tag_that_object_belongs_to, +                _anchor_tag, +                lev4_subtoc, +                the_table_of_contents_section, +              ); +              if (an_object["lev_markup_number"] == "4") { +                html_segnames ~= segment_anchor_tag_that_object_belongs_to; +                html_segnames_ptr = html_segnames_ptr_cntr; +                html_segnames_ptr_cntr++; +              } +              auto comp_obj_heading +                = node_construct.node_emitter_heading( +                  an_object["substantive"],                     // string +                  an_object["lev_markup_number"],               // string +                  an_object["lev_collapsed_number"],            // string +                  segment_anchor_tag_that_object_belongs_to,    // string +                  obj_cite_digits,                              // OCNset +                  cntr,                                         // int +                  heading_ptr,                                  // int +                  lv_ancestors_txt,                             // string[] +                  an_object["is"],                              // string +                  html_segnames_ptr,                            // int +                  substantive_object_and_anchor_tags_tuple[sObj.notes_reg], +                  substantive_object_and_anchor_tags_tuple[sObj.notes_star], +                  substantive_object_and_anchor_tags_tuple[sObj.links], +                ); +              ++heading_ptr; +              debug(segments) { +                writeln(an_object["lev_markup_number"]); +                writeln(segment_anchor_tag_that_object_belongs_to); +              } +              the_document_body_section ~= comp_obj_heading; +              debug(objectrelated1) { // check +                writeln(line); +              } +              _common_reset_(line_occur, an_object, obj_type_status); +              an_object.remove("lev"); +              an_object.remove("lev_markup_number"); +              processing.remove("verse"); +              ++cntr; +            } else if ((obj_type_status["para"] == State.on) +            && (line_occur["para"] > State.off)) { +              /+ paragraph object (current line empty) +/ +              obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]); +              an_object["bookindex_nugget"] +                = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; +              bookindex_unordered_hashes +                = bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_digits, segment_anchor_tag_that_object_belongs_to); +              an_object["is"] = "para"; +              auto comp_obj_heading +                = node_construct.node_location_emitter( +                  content_non_header, +                  segment_anchor_tag_that_object_belongs_to, +                  obj_cite_digits, +                  cntr, +                  heading_ptr-1, +                  an_object["is"], +                ); +              auto substantive_obj_misc_tuple +                = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, false); +              an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; +              anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; +              comp_obj_para                                             = comp_obj_para.init; +              comp_obj_para.metainfo.is_of_part                         = "body"; +              comp_obj_para.metainfo.is_of_section                      = "body"; +              comp_obj_para.metainfo.is_of_type                         = "para"; +              comp_obj_para.metainfo.is_a                               = "para"; +              comp_obj_para.text                                        = an_object["substantive"].to!string.strip; +              comp_obj_para.metainfo.ocn                                = obj_cite_digits.digit; +              comp_obj_para.metainfo.object_number_off                  = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +              comp_obj_para.metainfo.o_n_book_index                     = obj_cite_digits.bkidx; +              comp_obj_para.metainfo.object_number_type                 = obj_cite_digits.type; +              comp_obj_para.attrib.indent_hang                          = indent["hang_position"]; +              comp_obj_para.attrib.indent_base                          = indent["base_position"]; +              comp_obj_para.attrib.bullet                               = bullet; +              comp_obj_para.tags.anchor_tags                            = anchor_tags; +              comp_obj_para.has.inline_notes_reg                        = substantive_obj_misc_tuple[sObj.notes_reg]; +              comp_obj_para.has.inline_notes_star                       = substantive_obj_misc_tuple[sObj.notes_star]; +              comp_obj_para.has.inline_links                            = substantive_obj_misc_tuple[sObj.links]; +              comp_obj_para.has.contains_image_without_dimensions       = substantive_obj_misc_tuple[sObj.image_no_dimensions]; +              the_document_body_section                                 ~= comp_obj_para; +              _common_reset_(line_occur, an_object, obj_type_status); +              indent=[ +                "hang_position" : 0, +                "base_position" : 0, +              ]; +              bullet = false; +              processing.remove("verse"); +              ++cntr; +            } else { +              // could be useful to test line variable should be empty and never null +            } +          } // close else for line empty +        } // close else for not the above +      } // close after non code, other blocks or regular text +      /+ unless (the_document_body_section.length == 0) ? +/ +      if (the_document_body_section.length > 0) { +        if (((the_document_body_section[$-1].metainfo.is_a == "para") +          || (the_document_body_section[$-1].metainfo.is_a == "heading") +          || (the_document_body_section[$-1].metainfo.is_a == "quote") +          || (the_document_body_section[$-1].metainfo.is_a == "group") +          || (the_document_body_section[$-1].metainfo.is_a == "block") +          || (the_document_body_section[$-1].metainfo.is_a == "verse")) +        && (the_document_body_section.length > previous_length)) { +          if ((the_document_body_section[$-1].metainfo.is_a == "heading") +          && (the_document_body_section[$-1].metainfo.heading_lev_markup < 5)) { +            obj_type_status["biblio_section"]   = State.off; +            obj_type_status["glossary_section"] = State.off; +            obj_type_status["blurb_section"]    = State.off; +          } +          if (the_document_body_section[$-1].metainfo.is_a == "verse") { +            /+ scan for endnotes for whole poem (each verse in poem) +/ +            foreach (i; previous_length .. the_document_body_section.length) { +              if (the_document_body_section[i].metainfo.is_a == "verse") { +                if ((the_document_body_section[i].text).match( +                  rgx.inline_notes_delimiter_al_regular_number_note +                )) { +                  note_section.gather_notes_for_endnote_section( +                    the_document_body_section, +                    segment_anchor_tag_that_object_belongs_to, +                    (i).to!int, +                  ); +                } +              } +            } +          } else { +            /+ scan object for endnotes +/ +            previous_length = the_document_body_section.length.to!int; +            if ((the_document_body_section[$-1].text).match( +              rgx.inline_notes_delimiter_al_regular_number_note +            )) { +              previous_count=(the_document_body_section.length -1).to!int; +              note_section.gather_notes_for_endnote_section( +                the_document_body_section, +                segment_anchor_tag_that_object_belongs_to, +                (the_document_body_section.length-1).to!int, +              ); +            } +          } +          previous_length = the_document_body_section.length.to!int; +        } +      } +    } /+ ← srcDocLoop closed: loop markup document/text line by line +/ +    /+ ↓ post loop markup document/text +/ +    auto en_tuple +      = note_section.endnote_objects(obj_cite_digits, opt_action); +    static assert(!isTypeTuple!(en_tuple)); +    auto the_endnotes_section = en_tuple[0]; +    obj_cite_digits = en_tuple[1]; +    debug(endnotes) { +      writefln( +        "%s %s", +        __LINE__, +        the_endnotes_section.length +      ); +      foreach (o; the_endnotes_section) { +        writeln(o); +      } +    } +    if (an_object["glossary_nugget"].length == 0) { +      comp_obj_heading_                                = comp_obj_heading_.init; +      comp_obj_heading_.metainfo.is_of_part            = "empty"; +      comp_obj_heading_.metainfo.is_of_section         = "empty"; +      comp_obj_heading_.metainfo.is_of_type            = "para"; +      comp_obj_heading_.metainfo.is_a                  = "heading"; +      comp_obj_heading_.text                           = "(skip) there is no Glossary section"; +      comp_obj_heading_.metainfo.ocn                   = 0; +      comp_obj_heading_.metainfo.object_number_off     = ""; +      comp_obj_heading_.metainfo.object_number_type    = 0; +      comp_obj_heading_.metainfo.heading_lev_markup    = 1; +      comp_obj_heading_.metainfo.heading_lev_collapsed = 1; +      comp_obj_heading_.metainfo.parent_ocn            = 1; +      comp_obj_heading_.metainfo.parent_lev_markup     = 0; +      the_glossary_section                             ~= comp_obj_heading_; +    } +    debug(glossary) { +      foreach (gloss; the_glossary_section) { +        writeln(gloss.text); +      } +    } +    auto biblio_unsorted_incomplete = biblio_arr_json.dup; +    auto biblio = Bibliography(); +    auto biblio_ordered +      = biblio._bibliography_(biblio_unsorted_incomplete, bib_arr_json); +    if (biblio_ordered.length > 0) { +      comp_obj_heading_                                = comp_obj_heading_.init; +      comp_obj_heading_.metainfo.is_of_part            = "backmatter"; +      comp_obj_heading_.metainfo.is_of_section         = "bibliography"; +      comp_obj_heading_.metainfo.is_of_type            = "para"; +      comp_obj_heading_.metainfo.is_a                  = "heading"; +      comp_obj_heading_.text                           = "Bibliography"; +      comp_obj_heading_.metainfo.ocn                   = 0; +      comp_obj_heading_.metainfo.object_number_off     = ""; +      comp_obj_heading_.metainfo.object_number_type    = 0; +      comp_obj_heading_.tags.segment_anchor_tag        = "_part_bibliography"; +      comp_obj_heading_.metainfo.heading_lev_markup    = 1; +      comp_obj_heading_.metainfo.heading_lev_collapsed = 1; +      comp_obj_heading_.metainfo.parent_ocn            = 1; +      comp_obj_heading_.metainfo.parent_lev_markup     = 0; +      the_bibliography_section                         ~= comp_obj_heading_; +      comp_obj_heading_                                = comp_obj_heading_.init; +      comp_obj_heading_.metainfo.is_of_part            = "backmatter"; +      comp_obj_heading_.metainfo.is_of_section         = "bibliography"; +      comp_obj_heading_.metainfo.is_of_type            = "para"; +      comp_obj_heading_.metainfo.is_a                  = "heading"; +      comp_obj_heading_.text                           = "Bibliography"; +      comp_obj_heading_.metainfo.ocn                   = 0; +      comp_obj_heading_.metainfo.object_number_off     = ""; +      comp_obj_heading_.metainfo.object_number_type    = 0; +      comp_obj_heading_.tags.segment_anchor_tag        = "bibliography"; +      comp_obj_heading_.metainfo.heading_lev_markup    = 4; +      comp_obj_heading_.metainfo.heading_lev_collapsed = 2; +      comp_obj_heading_.metainfo.parent_ocn            = 1; +      comp_obj_heading_.metainfo.parent_lev_markup     = 0; +      comp_obj_heading_.tags.anchor_tags               = ["bibliography"]; +      the_bibliography_section                         ~= comp_obj_heading_; +    } else { +      comp_obj_heading_                                = comp_obj_heading_.init; +      comp_obj_heading_.metainfo.is_of_part            = "empty"; +      comp_obj_heading_.metainfo.is_of_section         = "empty"; +      comp_obj_heading_.metainfo.is_of_type            = "para"; +      comp_obj_heading_.metainfo.is_a                  = "heading"; +      comp_obj_heading_.text                           = "(skip) there is no Bibliography"; +      comp_obj_heading_.metainfo.ocn                   = 0; +      comp_obj_heading_.metainfo.object_number_off     = ""; +      comp_obj_heading_.metainfo.object_number_type    = 0; +      comp_obj_heading_.metainfo.heading_lev_markup    = 1; +      comp_obj_heading_.metainfo.heading_lev_collapsed = 1; +      comp_obj_heading_.metainfo.parent_ocn            = 1; +      comp_obj_heading_.metainfo.parent_lev_markup     = 0; +      the_bibliography_section                         ~= comp_obj_heading_; +    } +    string out_; +    foreach (entry; biblio_ordered) { +      out_ = format( +        "%s \"%s\"%s%s%s%s%s%s%s%s%s.", +        ((entry["author"].str.empty) ? entry["editor"].str : entry["author"].str), +        entry["fulltitle"].str, +        ((entry["journal"].str.empty) ? "" : ", /{" ~ entry["journal"].str ~ "}/"), +        ((entry["volume"].str.empty) ? "" : ", " ~ entry["volume"].str), +        ((entry["in"].str.empty) ? "" : ", " ~ entry["in"].str), +        ((!(entry["author"].str.empty) && (!(entry["editor"].str.empty))) ? entry["editor"].str : ""), +        ", " ~ entry["year"].str, +        ((entry["pages"].str.empty) ? "" : ", " ~ entry["pages"].str), +        ((entry["publisher"].str.empty) ? "" : ", " ~ entry["publisher"].str), +        ((entry["place"].str.empty) ? "" : ", " ~ entry["place"].str), +        ((entry["url"].str.empty) ? "" : ", [" ~ entry["url"].str ~ "]"), +      ); +      comp_obj_para                               = comp_obj_para.init; +      comp_obj_para.metainfo.is_of_part           = "backmatter"; +      comp_obj_para.metainfo.is_of_section        = "bibliography"; +      comp_obj_para.metainfo.is_of_type           = "para"; +      comp_obj_para.metainfo.is_a                 = "bibliography"; +      comp_obj_para.text                          = out_.to!string.strip; +      comp_obj_para.metainfo.ocn                  = 0; +      comp_obj_para.metainfo.object_number_off    = ""; +      comp_obj_para.metainfo.object_number_type   = 0; +      comp_obj_para.attrib.indent_hang            = 0; +      comp_obj_para.attrib.indent_base            = 1; +      comp_obj_para.attrib.bullet                 = bullet; +      comp_obj_para.tags.anchor_tags              = anchor_tags; +      the_bibliography_section                    ~= comp_obj_para; +    } +    debug(bibliosection) { +      foreach (o; the_bibliography_section) { +        writeln(o.text); +      } +    } +    auto bi = BookIndexReportSection(); +    auto bi_tuple +      = bi.bookindex_build_abstraction_section( +        bookindex_unordered_hashes, +        obj_cite_digits, +        opt_action, +      ); +    destroy(bookindex_unordered_hashes); +    static assert(!isTypeTuple!(bi_tuple)); +    auto the_bookindex_section = bi_tuple[0]; +    obj_cite_digits = bi_tuple[1]; +    debug(bookindex) { +      foreach (bi_entry; the_bookindex_section["seg"]) { +        writeln(bi_entry); +      } +    } +    if (an_object["blurb_nugget"].length == 0) { +      comp_obj_heading_                                = comp_obj_heading_.init; +      comp_obj_heading_.metainfo.is_of_part            = "empty"; +      comp_obj_heading_.metainfo.is_of_section         = "empty"; +      comp_obj_heading_.metainfo.is_of_type            = "para"; +      comp_obj_heading_.metainfo.is_a                  = "heading"; +      comp_obj_heading_.text                           = "(skip) there is no Blurb section"; +      comp_obj_heading_.metainfo.ocn                   = 0; +      comp_obj_para.metainfo.object_number_off         = ""; +      comp_obj_para.metainfo.object_number_type        = 0; +      comp_obj_heading_.tags.segment_anchor_tag        = ""; +      comp_obj_heading_.metainfo.heading_lev_markup    = 1; +      comp_obj_heading_.metainfo.heading_lev_collapsed = 1; +      comp_obj_heading_.metainfo.parent_ocn            = 1; +      comp_obj_heading_.metainfo.parent_lev_markup     = 0; +      the_blurb_section                                ~= comp_obj_heading_; +    } +    debug(blurb) { +      foreach (blurb; the_blurb_section) { +        writeln(blurb.text); +      } +    } +    indent=[ +      "hang_position" : 1, +      "base_position" : 1, +    ]; +    comp_obj_toc                               = comp_obj_toc.init; +    comp_obj_toc.metainfo.is_of_part           = "frontmatter"; +    comp_obj_toc.metainfo.is_of_section        = "toc"; +    comp_obj_toc.metainfo.is_of_type           = "para"; +    comp_obj_toc.metainfo.is_a                 = "toc"; +    comp_obj_toc.metainfo.ocn                  = 0; +    comp_obj_toc.metainfo.object_number_off    = ""; +    comp_obj_toc.metainfo.object_number_type   = 0; +    comp_obj_toc.attrib.indent_hang            = indent["hang_position"]; +    comp_obj_toc.attrib.indent_base            = indent["base_position"]; +    comp_obj_toc.attrib.bullet                 = false; +    if (the_endnotes_section.length > 1) { +      toc_txt_ = format( +        "{ %s }%s%s%s", +        "Endnotes", +        mkup.mark_internal_site_lnk, +        "endnotes",               // segment_anchor_tag_that_object_belongs_to +        ".fnSuffix", +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.has.inline_links           = true; +      the_table_of_contents_section["seg"]    ~= comp_obj_toc; +    } +    if (the_glossary_section.length > 1) { +      toc_txt_ = format( +        "{ %s }%s%s%s", +        "Glossary", +        mkup.mark_internal_site_lnk, +        "glossary",               // segment_anchor_tag_that_object_belongs_to +        ".fnSuffix", +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.has.inline_links           = true; +      the_table_of_contents_section["seg"]    ~= comp_obj_toc; +      toc_txt_ = format( +        "{ %s }#%s", +        "Glossary", +        "glossary", +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.has.inline_links           = true; +      the_table_of_contents_section["scroll"] ~= comp_obj_toc; +    } +    if (the_bibliography_section.length > 1){ +      toc_txt_ = format( +        "{ %s }%s%s%s", +        "Bibliography", +        mkup.mark_internal_site_lnk, +        "bibliography",           // segment_anchor_tag_that_object_belongs_to +        ".fnSuffix", +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.has.inline_links           = true; +      the_table_of_contents_section["seg"]    ~= comp_obj_toc; +     +      toc_txt_ = format( +        "{ %s }#%s", +        "Bibliography", +        "bibliography", +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.has.inline_links           = true; +      the_table_of_contents_section["scroll"] ~= comp_obj_toc; +    } +    if (the_bookindex_section["seg"].length > 1) { +      toc_txt_ = format( +        "{ %s }%s%s%s", +        "Book Index", +        mkup.mark_internal_site_lnk, +        "bookindex",              // segment_anchor_tag_that_object_belongs_to +        ".fnSuffix", +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.has.inline_links           = true; +      the_table_of_contents_section["seg"]    ~= comp_obj_toc; +    } +    if (the_bookindex_section["scroll"].length > 1) { +      toc_txt_ = format( +        "{ %s }#%s", +        "Book Index", +        "bookindex", +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.has.inline_links           = true; +      the_table_of_contents_section["scroll"] ~= comp_obj_toc; +    } +    if (the_blurb_section.length > 1) { +      toc_txt_ = format( +        "{ %s }%s%s%s", +        "Blurb", +        mkup.mark_internal_site_lnk, +        "blurb",                  // segment_anchor_tag_that_object_belongs_to +        ".fnSuffix", +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.has.inline_links           = true; +      the_table_of_contents_section["seg"]    ~= comp_obj_toc; +      toc_txt_ = format( +        "{ %s }#%s", +        "Blurb", +        "blurb", +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.has.inline_links           = true; +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      the_table_of_contents_section["scroll"] ~= comp_obj_toc; +    } +    debug(toc) { +      writefln( +        "%s %s", +        __LINE__, +        the_table_of_contents_section["seg"].length +      ); +      foreach (toc_linked_heading; the_table_of_contents_section["seg"]) { +        writeln(mkup.indent_by_spaces_provided(toc_linked_heading.attrib.indent_hang), toc_linked_heading.text); +      } +    } +    debug(tocscroll) { +      writefln( +        "%s %s", +        __LINE__, +        the_table_of_contents_section["seg"].length +      ); +      foreach (toc_linked_heading; the_table_of_contents_section["scroll"]) { +        writeln(mkup.indent_by_spaces_provided(toc_linked_heading.attrib.indent_hang), toc_linked_heading.text); +      } +    } +    the_document_head_section ~= the_document_body_section[0]; +    the_document_body_section=the_document_body_section[1..$]; +    int[] _get_ancestors_markup(O)(O obj, ref int[] _ancestors_markup) { +      if (obj.metainfo.is_a == "heading") { +        debug(dom) { +          writeln(obj.text); +        } +        if (obj.metainfo.heading_lev_markup == 1) { +          _ancestors_markup = [ +            _ancestors_markup[0], +            0,0,0,0,0,0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_markup == 2) { +          _ancestors_markup = [ +            _ancestors_markup[0], +            _ancestors_markup[1], +            0,0,0,0,0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_markup == 3) { +          _ancestors_markup = [ +            _ancestors_markup[0], +            _ancestors_markup[1], +            _ancestors_markup[2], +            0,0,0,0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_markup == 4) { +          _ancestors_markup = [ +            _ancestors_markup[0], +            _ancestors_markup[1], +            _ancestors_markup[2], +            _ancestors_markup[3], +            0,0,0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_markup == 5) { +          _ancestors_markup = [ +            _ancestors_markup[0], +            _ancestors_markup[1], +            _ancestors_markup[2], +            _ancestors_markup[3], +            _ancestors_markup[4], +            0,0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_markup == 6) { +          _ancestors_markup = [ +            _ancestors_markup[0], +            _ancestors_markup[1], +            _ancestors_markup[2], +            _ancestors_markup[3], +            _ancestors_markup[4], +            _ancestors_markup[5], +            0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_markup == 7) { +          _ancestors_markup = [ +            _ancestors_markup[0], +            _ancestors_markup[1], +            _ancestors_markup[2], +            _ancestors_markup[3], +            _ancestors_markup[4], +            _ancestors_markup[5], +            _ancestors_markup[6], +            0 +          ]; +        } +        if (obj.metainfo.heading_lev_markup == 8) { +          _ancestors_markup = [ +            _ancestors_markup[0], +            _ancestors_markup[1], +            _ancestors_markup[2], +            _ancestors_markup[3], +            _ancestors_markup[4], +            _ancestors_markup[5], +            _ancestors_markup[6], +            _ancestors_markup[7] +          ]; +        } +        _ancestors_markup[obj.metainfo.heading_lev_markup] = obj.metainfo.ocn; +      } +      debug(ancestor_markup) { +        writeln("marked up: ", _ancestors_markup); +      } +      return _ancestors_markup; +    } +    int[] _get_ancestors_collapsed(O)(O obj, ref int[] _ancestors_collapsed) { +      if (obj.metainfo.is_a == "heading") { +        if (obj.metainfo.heading_lev_collapsed == 1) { +          _ancestors_collapsed = [ +            _ancestors_collapsed[0], +            0,0,0,0,0,0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_collapsed == 2) { +          _ancestors_collapsed = [ +            _ancestors_collapsed[0], +            _ancestors_collapsed[1], +            0,0,0,0,0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_collapsed == 3) { +          _ancestors_collapsed = [ +            _ancestors_collapsed[0], +            _ancestors_collapsed[1], +            _ancestors_collapsed[2], +            0,0,0,0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_collapsed == 4) { +          _ancestors_collapsed = [ +            _ancestors_collapsed[0], +            _ancestors_collapsed[1], +            _ancestors_collapsed[2], +            _ancestors_collapsed[3], +            0,0,0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_collapsed == 5) { +          _ancestors_collapsed = [ +            _ancestors_collapsed[0], +            _ancestors_collapsed[1], +            _ancestors_collapsed[2], +            _ancestors_collapsed[3], +            _ancestors_collapsed[4], +            0,0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_collapsed == 6) { +          _ancestors_collapsed = [ +            _ancestors_collapsed[0], +            _ancestors_collapsed[1], +            _ancestors_collapsed[2], +            _ancestors_collapsed[3], +            _ancestors_collapsed[4], +            _ancestors_collapsed[5], +            0,0 +          ]; +        } +        if (obj.metainfo.heading_lev_collapsed == 7) { +          _ancestors_collapsed = [ +            _ancestors_collapsed[0], +            _ancestors_collapsed[1], +            _ancestors_collapsed[2], +            _ancestors_collapsed[3], +            _ancestors_collapsed[4], +            _ancestors_collapsed[5], +            _ancestors_collapsed[6], +            0 +          ]; +        } +        if (obj.metainfo.heading_lev_collapsed == 8) { +          _ancestors_collapsed = [ +            _ancestors_collapsed[0], +            _ancestors_collapsed[1], +            _ancestors_collapsed[2], +            _ancestors_collapsed[3], +            _ancestors_collapsed[4], +            _ancestors_collapsed[5], +            _ancestors_collapsed[6], +            _ancestors_collapsed[7] +          ]; +        } +        _ancestors_collapsed[obj.metainfo.heading_lev_collapsed] = obj.metainfo.ocn; +      } +      debug(ancestor_collapsed) { +        writeln("collapsed: ", _ancestors_collapsed); +      } +      return _ancestors_collapsed; +    } +    /+ multiple 1~ levels, loop through document body +/ +    if (the_document_body_section.length > 1) { +      int[] _ancestors_markup = [0,0,0,0,0,0,0,0]; +      int[][] _ancestors_markup_; +      _ancestors_markup = [1,0,0,0,0,0,0,0]; +      _ancestors_markup_ ~= _ancestors_markup; +      int[] _ancestors_collapsed = [0,0,0,0,0,0,0,0]; +      int[][] _ancestors_collapsed_; +      _ancestors_collapsed = [1,0,0,0,0,0,0,0]; +      _ancestors_collapsed_ ~= _ancestors_collapsed; +      foreach (ref obj; the_document_body_section) { +        if (obj.metainfo.is_a == "heading") { +          obj.metainfo.markedup_ancestors = _get_ancestors_markup(obj, _ancestors_markup); +          obj.metainfo.collapsed_ancestors = _get_ancestors_collapsed(obj, _ancestors_collapsed); +          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; +        } +      } +      debug(ancestors) { +        writeln("ancestors markup o_n:    ", obj.metainfo.markedup_ancestors); +        writeln("ancestors collapsed o_n: ", obj.metainfo.markedup_ancestors); +      } +    } +    if (the_endnotes_section.length > 1) { +      html_segnames ~= "endnotes"; +      html_segnames_ptr = html_segnames_ptr_cntr; +      foreach (ref obj; the_endnotes_section) { +        if (obj.metainfo.is_a == "heading") { +          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; +        } +        if (obj.metainfo.heading_lev_markup == 4) { +          obj.ptr.html_segnames = html_segnames_ptr; +          break; +        } +      } +      html_segnames_ptr_cntr++; +    } +    if (the_glossary_section.length > 1) { +      html_segnames ~= "glossary"; +      html_segnames_ptr = html_segnames_ptr_cntr; +      foreach (ref obj; the_glossary_section) { +        if (obj.metainfo.is_a == "heading") { +          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; +        } +        if (obj.metainfo.heading_lev_markup == 4) { +          obj.ptr.html_segnames = html_segnames_ptr; +          break; +        } +      } +      html_segnames_ptr_cntr++; +    } +    if (the_bibliography_section.length > 1) { +      html_segnames ~= "bibliography"; +      html_segnames_ptr = html_segnames_ptr_cntr; +      foreach (ref obj; the_bibliography_section) { +        if (obj.metainfo.is_a == "heading") { +          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; +        } +        if (obj.metainfo.heading_lev_markup == 4) { +          obj.ptr.html_segnames = html_segnames_ptr; +          break; +        } +      } +      html_segnames_ptr_cntr++; +    } +    if (the_bookindex_section["scroll"].length > 1) { +      html_segnames ~= "bookindex"; +      html_segnames_ptr = html_segnames_ptr_cntr; +      foreach (ref obj; the_bookindex_section["scroll"]) { +        if (obj.metainfo.is_a == "heading") { +          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; +        } +        if (obj.metainfo.heading_lev_markup == 4) { +          obj.ptr.html_segnames = html_segnames_ptr; +          break; +        } +      } +      foreach (ref obj; the_bookindex_section["seg"]) { +        if (obj.metainfo.heading_lev_markup == 4) { +          obj.ptr.html_segnames = html_segnames_ptr; +          break; +        } +      } +      html_segnames_ptr_cntr++; +    } +    if (the_blurb_section.length > 1) { +      html_segnames ~= "blurb"; +      html_segnames_ptr = html_segnames_ptr_cntr; +      foreach (ref obj; the_blurb_section) { +        if (obj.metainfo.is_a == "heading") { +          obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; +        } +        if (obj.metainfo.heading_lev_markup == 4) { +          obj.ptr.html_segnames = html_segnames_ptr; +          break; +        } +      } +      html_segnames_ptr_cntr++; +    } +    auto get_decendants(S)(S document_sections) { +      int[string] _heading_ocn_decendants; +      string[] _ocn_open_key = ["","","","","","","",""]; +      auto _doc_sect_length = document_sections.length - 1; +      int _last_ocn; +      foreach (_lg, ref obj; document_sections) { +        if (obj.metainfo.is_a == "heading") { +          foreach (_dts_lv, dom_tag_status; obj.metainfo.dom_structure_markedup_tags_status) { +            switch (dom_tag_status) { +            case DomTags.none: break; +            case DomTags.open: +                _ocn_open_key[_dts_lv] = (obj.metainfo.ocn).to!string; +                _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn; +              break; +            case DomTags.close: +              if (_ocn_open_key[_dts_lv].empty) { +                _ocn_open_key[_dts_lv] = "0"; +              } +              _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn - 1; +              _ocn_open_key[_dts_lv] = (0).to!string; +              break; +            case DomTags.close_and_open: +              if (_ocn_open_key[_dts_lv].empty) { +                _ocn_open_key[_dts_lv] = "0"; +              } +              _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn - 1; +              _ocn_open_key[_dts_lv] = (obj.metainfo.ocn).to!string; +              _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn; +              break; +            case DomTags.open_still: break; +            default: break; +            } +          } +        } +        if (obj.metainfo.ocn > 0) { +          _last_ocn = obj.metainfo.ocn; +        } +        if (_lg == _doc_sect_length) { +          _heading_ocn_decendants["1"] = _last_ocn; // close existing o_n key +        } +      } +      Tuple!(int, int)[] pairs; +      foreach (pair; _heading_ocn_decendants.byPair) { +        pairs ~= tuple(pair[0].to!int, pair[1]); +      } +      return pairs.sort; +    } +    string[] _images; +    auto extract_images(S)(S content_block) { +      string[] images_; +      if (auto m = content_block.matchAll(rgx.image)) { +        images_ ~= m.captures[1]; +      } +      return images_; +    } +    string[] segnames_0_4; +    auto _image_dimensions(M,O)(M manifest_matter, O obj) { +      if (obj.has.contains_image_without_dimensions) { +        import std.math; +        import imageformats; +        int w, h, chans; +        real _w, _h; +        int max_width = 640; +        foreach (m; obj.text.matchAll(rgx.inline_image_without_dimensions)) { +          debug(images) { +            writeln(manifest_matter.src.image_dir_path ~ "/" ~ m.captures["img"]); +          } +          read_image_info(manifest_matter.src.image_dir_path ~ "/" ~ m.captures["img"], w, h, chans); +          // calculate, decide max width and proportionally reduce to keep w & h within it +          debug(images) { +            writeln("width: ", w, ", height: ", h); +          } +          if (w > max_width) { +            _w = max_width; +            _h = round((max_width / w.to!real) * h.to!real); +          } else { +            _w = w; +            _h = h; +          } +          obj.text = obj.text.replaceFirst( +            rgx.inline_image_without_dimensions, +            ("$1☼$3,w" ~ _w.to!string ~ "h" ~ _h.to!string ~ " $6") +          ); +        } +        debug(images) { +          writeln("image without dimensions: ", obj.text); +        } +      } +      return obj; +    } +    foreach (ref obj; the_document_head_section) { +      if (obj.metainfo.is_a == "heading") { +        debug(dom) { +          writeln(obj.text); +        } +        if (obj.metainfo.heading_lev_markup <= 4) { +          segnames_0_4 ~= obj.tags.segment_anchor_tag; +        } +        if (obj.metainfo.heading_lev_markup == 0) { +          /+ TODO second hit (of two) with same assertion failure, check, fix and reinstate +          assert( obj.metainfo.ocn == 1, +            "Title OCN should be 1 not: " ~ obj.metainfo.ocn.to!string); // bug introduced 0.18.1 +          +/ +          obj.metainfo.ocn = 1; +          obj.metainfo.object_number_type = OCNtype.ocn; +        } +        /+ dom structure (marked up & collapsed) +/ +        if ((opt_action.html) +        || (opt_action.html_scroll) +        || (opt_action.html_seg) +        || (opt_action.epub) +        || (opt_action.sqlite_discrete) +        || (opt_action.sqlite_update)) { +          obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); +          obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); +        } +        obj = obj_heading_ancestors(obj, lv_ancestors_txt); +      } +    } +    if (the_table_of_contents_section["scroll"].length > 1) { +      /+ scroll +/ +      dom_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup; +      dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup; +      foreach (ref obj; the_table_of_contents_section["scroll"]) { +        if (obj.metainfo.is_a == "heading") { +          if (obj.metainfo.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.tags.segment_anchor_tag; +            if (obj.metainfo.heading_lev_markup == 4) { +              obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; +              assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], +                obj.tags.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr.html_segnames]); +            } +          } +          /+ dom structure (marked up & collapsed) +/ +          if ((opt_action.html) +          || (opt_action.html_scroll) +          || (opt_action.html_seg) +          || (opt_action.epub) +          || (opt_action.sqlite_discrete) +          || (opt_action.sqlite_update)) { +            obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } +      } +      /+ seg +/ +      dom_structure_markedup_tags_status = dom_structure_markedup_tags_status_buffer.dup; +      dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status_buffer.dup; +      foreach (ref obj; the_table_of_contents_section["seg"]) { +        if (obj.metainfo.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          if (obj.metainfo.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.tags.segment_anchor_tag; +            if (obj.metainfo.heading_lev_markup == 4) { +              obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; +              assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], +                obj.tags.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr.html_segnames]); +            } +          } +          if ((opt_action.html) +          || (opt_action.html_scroll) +          || (opt_action.html_seg) +          || (opt_action.epub)) { +            obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } +      } +    } +    /+ multiple 1~ levels, loop through document body +/ +    if (the_document_body_section.length > 1) { +      foreach (ref obj; the_document_body_section) { +        if (obj.metainfo.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          if (obj.metainfo.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.tags.segment_anchor_tag; +            if (obj.metainfo.heading_lev_markup == 4) { +              obj.tags.lev4_subtoc = lev4_subtoc[obj.tags.segment_anchor_tag]; +              obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; +              if (html_segnames.length > obj.ptr.html_segnames + 1) { +                obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; +              } +              assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], +                obj.tags.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr.html_segnames]); +            } +          } +          /+ dom structure (marked up & collapsed) +/ +          if ((opt_action.html) +          || (opt_action.html_scroll) +          || (opt_action.html_seg) +          || (opt_action.epub) +          || (opt_action.sqlite_discrete) +          || (opt_action.sqlite_update)) { +            obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } else if (obj.metainfo.is_a == "para") { +           _images ~= extract_images(obj.text); +           obj = _image_dimensions(manifest_matter, obj); +        } +      } +    } +    auto images=uniq(_images.sort()); +    /+ optional only one 1~ level +/ +    if (the_endnotes_section.length > 1) { +      dom_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup; +      dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup; +      dom_structure_markedup_tags_status = dom_structure_markedup_tags_status_buffer.dup; +      dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status_buffer.dup; +      foreach (ref obj; the_endnotes_section) { +        if (obj.metainfo.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          obj_cite_digits = ocn_emit(OCNstatus.on); +          obj.metainfo.ocn = obj_cite_digits.digit; +          if (obj.metainfo.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.tags.segment_anchor_tag; +            if (obj.metainfo.heading_lev_markup == 4) { +              obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; +              if (html_segnames.length > obj.ptr.html_segnames + 1) { +                obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; +              } +              assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], +                obj.tags.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr.html_segnames]); +            } +          } +          /+ dom structure (marked up & collapsed) +/ +          if ((opt_action.html) +          || (opt_action.html_scroll) +          || (opt_action.html_seg) +          || (opt_action.epub) +          || (opt_action.sqlite_discrete) +          || (opt_action.sqlite_update)) { +            obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } +      } +    } +    /+ optional only one 1~ level +/ +    if (the_glossary_section.length > 1) { +      foreach (ref obj; the_glossary_section) { +        if (obj.metainfo.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          obj_cite_digits = ocn_emit(OCNstatus.on); +          obj.metainfo.ocn = obj_cite_digits.digit; +          if (obj.metainfo.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.tags.segment_anchor_tag; +            if (obj.metainfo.heading_lev_markup == 4) { +              obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; +              if (html_segnames.length > obj.ptr.html_segnames + 1) { +                obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; +              } +              assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], +                obj.tags.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr.html_segnames]); +            } +          } +          /+ dom structure (marked up & collapsed) +/ +          if ((opt_action.html) +          || (opt_action.html_scroll) +          || (opt_action.html_seg) +          || (opt_action.epub) +          || (opt_action.sqlite_discrete) +          || (opt_action.sqlite_update)) { +            obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } else if (obj.metainfo.is_a == "glossary") { +          obj_cite_digits = ocn_emit(OCNstatus.on); +          obj.metainfo.ocn = obj_cite_digits.digit; +        } +      } +    } +    /+ optional only one 1~ level +/ +    if (the_bibliography_section.length > 1) { +      foreach (ref obj; the_bibliography_section) { +        if (obj.metainfo.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          obj_cite_digits = ocn_emit(OCNstatus.on); +          obj.metainfo.ocn = obj_cite_digits.digit; +          if (obj.metainfo.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.tags.segment_anchor_tag; +            if (obj.metainfo.heading_lev_markup == 4) { +              obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; +              if (html_segnames.length > obj.ptr.html_segnames + 1) { +                obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; +              } +              assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], +                obj.tags.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr.html_segnames]); +            } +          } +          /+ dom structure (marked up & collapsed) +/ +          if ((opt_action.html) +          || (opt_action.html_scroll) +          || (opt_action.html_seg) +          || (opt_action.epub) +          || (opt_action.sqlite_discrete) +          || (opt_action.sqlite_update)) { +            obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } else if (obj.metainfo.is_a == "bibliography") { +          obj_cite_digits = ocn_emit(OCNstatus.on); +          obj.metainfo.ocn = obj_cite_digits.on; +        } +      } +    } +    /+ optional only one 1~ level +/ +    int ocn_ = obj_cite_digits.on; +    int ocn_bkidx_ = 0; +    int ocn_bidx_; +    if (the_bookindex_section["scroll"].length > 1) { +      /+ scroll +/ +      dom_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup; +      dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup; +      foreach (ref obj; the_bookindex_section["scroll"]) { +        if (obj.metainfo.is_a == "heading") { +          debug(dom) { +          } +          obj_cite_digits = ocn_emit(OCNstatus.on); +          obj.metainfo.ocn = obj_cite_digits.on; +          if (obj.metainfo.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.tags.segment_anchor_tag; +            if (obj.metainfo.heading_lev_markup == 4) { +              obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; +              if (html_segnames.length > obj.ptr.html_segnames + 1) { +                obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; +              } +              assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], +                obj.tags.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr.html_segnames]); +            } +          } +          /+ dom structure (marked up & collapsed) +/ +          if ((opt_action.html) +          || (opt_action.html_scroll) +          || (opt_action.html_seg) +          || (opt_action.epub) +          || (opt_action.sqlite_discrete) +          || (opt_action.sqlite_update)) { +            obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } else if (obj.metainfo.is_a == "bookindex") { +          obj_cite_digits                       = ocn_emit(OCNstatus.bkidx); +          obj.metainfo.ocn                      = obj_cite_digits.digit; +          obj.metainfo.o_n_book_index           = obj_cite_digits.bkidx; +          obj.metainfo.object_number_type       = OCNtype.bkidx; +        } +      } +      /+ seg +/ +      dom_structure_markedup_tags_status = dom_structure_markedup_tags_status_buffer.dup; +      dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status_buffer.dup; +      foreach (ref obj; the_bookindex_section["seg"]) { +        if (obj.metainfo.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          obj.metainfo.ocn = ++ocn_; +          if (obj.metainfo.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.tags.segment_anchor_tag; +            if (obj.metainfo.heading_lev_markup == 4) { +              obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; +              if (html_segnames.length > obj.ptr.html_segnames + 1) { +                obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; +              } +              assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], +                obj.tags.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr.html_segnames]); +            } +          } +          /+ dom structure (marked up & collapsed) +/ +          if ((opt_action.html) +          || (opt_action.html_scroll) +          || (opt_action.html_seg) +          || (opt_action.epub) +          || (opt_action.sqlite_discrete) +          || (opt_action.sqlite_update)) { +            obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } else if (obj.metainfo.is_a == "bookindex") { +          ocn_bidx_                             = ++ocn_bkidx_; +          obj.metainfo.o_n_book_index           = ocn_bidx_; // FIX need to distinguish from regular ocn +          obj.metainfo.object_number_type       = OCNtype.bkidx; +        } +      } +      /+ TODO assert failure, reinstate +      assert(obj_cite_digit_bkidx == ocn_bidx_ +        obj_cite_digit_bkidx ~ " == ocn_" ~ ocn_ ~ "?"); +      +/ +    } +    /+ optional only one 1~ level +/ +    if (the_blurb_section.length > 1) { +      foreach (ref obj; the_blurb_section) { +        if (obj.metainfo.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          obj_cite_digits = ocn_emit(OCNstatus.on); +          obj.metainfo.ocn = obj_cite_digits.on; +          if (obj.metainfo.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.tags.segment_anchor_tag; +            if (obj.metainfo.heading_lev_markup == 4) { +              obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; +              if (html_segnames.length > obj.ptr.html_segnames + 1) { +                obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; +              } +              assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], +                obj.tags.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr.html_segnames]); +            } +          } +          /+ dom structure (marked up & collapsed) +/ +          if ((opt_action.html) +          || (opt_action.html_scroll) +          || (opt_action.html_seg) +          || (opt_action.epub) +          || (opt_action.sqlite_discrete) +          || (opt_action.sqlite_update)) { +            obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } else if (obj.metainfo.is_a == "blurb") { +          obj_cite_digits = ocn_emit(OCNstatus.off); +          obj.metainfo.object_number_off  = obj_cite_digits.off.to!string; +          obj.metainfo.object_number_type = OCNtype.non; +        } +      } +    } +    if (the_document_body_section.length > 1) { +      auto pairs = get_decendants( +        the_document_head_section ~ +        the_document_body_section ~ +        the_endnotes_section ~ +        the_glossary_section ~ +        the_bibliography_section ~ +        the_bookindex_section["scroll"] ~ +        the_blurb_section +      ); +      debug(decendants_tuple) { +        pairs = pairs.sort(); +        foreach (pair; pairs) {  // (pair; pairs.sort()) +          writeln(pair[0], "..", pair[1]); +        } +      } +      foreach (ref obj; the_document_head_section) { +        if (obj.metainfo.is_a == "heading") { +          foreach (pair; pairs) { +            if (obj.metainfo.ocn == pair[0]) { +              obj.metainfo.last_decendant_ocn = pair[1]; +            } +          } +        } +      } +      if (the_document_body_section.length > 1) { +        foreach (ref obj; the_document_body_section) { +          if (obj.metainfo.is_a == "heading") { +            foreach (pair; pairs) { +              if (obj.metainfo.ocn == pair[0]) { +                obj.metainfo.last_decendant_ocn = pair[1]; +              } +            } +          } +        } +      } +      if (the_endnotes_section.length > 1) { +        foreach (ref obj; the_endnotes_section) { +          if (obj.metainfo.is_a == "heading") { +            foreach (pair; pairs) { +              if (obj.metainfo.ocn == pair[0]) { +                obj.metainfo.last_decendant_ocn = pair[1]; +              } +            } +          } +        } +      } +      if (the_glossary_section.length > 1) { +        foreach (ref obj; the_glossary_section) { +          if (obj.metainfo.is_a == "heading") { +            foreach (pair; pairs) { +              if (obj.metainfo.ocn == pair[0]) { +                obj.metainfo.last_decendant_ocn = pair[1]; +              } +            } +          } +        } +      } +      if (the_bibliography_section.length > 1) { +        foreach (ref obj; the_bibliography_section) { +          if (obj.metainfo.is_a == "heading") { +            foreach (pair; pairs) { +              if (obj.metainfo.ocn == pair[0]) { +                obj.metainfo.last_decendant_ocn = pair[1]; +              } +            } +          } +        } +      } +      if (the_bookindex_section["scroll"].length > 1) { +        foreach (ref obj; the_bookindex_section["scroll"]) { +          if (obj.metainfo.is_a == "heading") { +            foreach (pair; pairs) { +              if (obj.metainfo.ocn == pair[0]) { +                obj.metainfo.last_decendant_ocn = pair[1]; +              } +            } +          } +        } +      } +      if (the_blurb_section.length > 1) { +        foreach (ref obj; the_blurb_section) { +          if (obj.metainfo.is_a == "heading") { +            foreach (pair; pairs) { +              if (obj.metainfo.ocn == pair[0]) { +                obj.metainfo.last_decendant_ocn = pair[1]; +              } +            } +          } +        } +      } +    } +      /+ TODO +        - note create/insert heading object sole purpose eof close all open tags +          sort out: +          - obj.metainfo.dom_structure_markedup_tags_status = dom_structure_markedup_tags_status; +          - obj.metainfo.dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status; +      +/ +    comp_obj_heading_                                = comp_obj_heading_.init; +    comp_obj_heading_.metainfo.is_of_part            = "empty"; +    comp_obj_heading_.metainfo.is_of_section         = "empty"; +    comp_obj_heading_.metainfo.is_of_type            = "para"; +    comp_obj_heading_.metainfo.is_a                  = "heading"; +    comp_obj_heading_.metainfo.ocn                   = 0; +    comp_obj_para.metainfo.object_number_off         = ""; +    comp_obj_para.metainfo.object_number_type        = 0; +    comp_obj_heading_.tags.segment_anchor_tag        = ""; +    comp_obj_heading_.metainfo.heading_lev_markup    = 9; +    comp_obj_heading_.metainfo.heading_lev_collapsed = 9; +    comp_obj_heading_.metainfo.parent_ocn            = 0; +    comp_obj_heading_.metainfo.parent_lev_markup     = 0; +    comp_obj_heading_.metainfo.dom_structure_markedup_tags_status          = dom_structure_markedup_tags_status.dup; +    comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status         = dom_structure_collapsed_tags_status.dup; +    comp_obj_heading_ = obj_dom_structure_set_markup_tags(comp_obj_heading_, dom_structure_markedup_tags_status, 0); +    comp_obj_heading_ = obj_dom_set_collapsed_tags(comp_obj_heading_, dom_structure_collapsed_tags_status, 0); +    comp_obj_heading_ = obj_heading_ancestors(comp_obj_heading_, lv_ancestors_txt); +    // the_dom_tail_section                      ~= comp_obj_heading_; // remove tail for now, decide on later +    auto document_the = [ +      "head":             the_document_head_section, +      "toc_seg":          the_table_of_contents_section["seg"], +      "toc_scroll":       the_table_of_contents_section["scroll"], +      /+ substantive/body: +/ +      "body":             the_document_body_section, +      /+ backmatter: +/ +      "endnotes":         the_endnotes_section, +      "glossary":         the_glossary_section, +      "bibliography":     the_bibliography_section, +      "bookindex_scroll": the_bookindex_section["scroll"], +      "bookindex_seg":    the_bookindex_section["seg"], +      "blurb":            the_blurb_section, +      /+ dom tail only +/ +      "tail":             the_dom_tail_section, +    ]; +    string[][string] document_section_keys_sequenced = [ +      "seg":    ["head", "toc_seg", "body",], +      "scroll": ["head", "toc_scroll", "body",], +      "sql":    ["head", "body",] +    ]; +    if (document_the["endnotes"].length > 1) { +      document_section_keys_sequenced["seg"]    ~= "endnotes"; +      document_section_keys_sequenced["scroll"] ~= "endnotes"; +    } +    if (document_the["glossary"].length > 1) { +      document_section_keys_sequenced["seg"]    ~= "glossary"; +      document_section_keys_sequenced["scroll"] ~= "glossary"; +      document_section_keys_sequenced["sql"]    ~= "glossary"; +    } +    if (document_the["bibliography"].length > 1) { +      document_section_keys_sequenced["seg"]    ~= "bibliography"; +      document_section_keys_sequenced["scroll"] ~= "bibliography"; +      document_section_keys_sequenced["sql"]    ~= "bibliography"; +    } +    if (document_the["bookindex_seg"].length > 1) { +      document_section_keys_sequenced["seg"]    ~= "bookindex_seg"; +      document_section_keys_sequenced["sql"]    ~= "bookindex_seg"; +    } +    if (document_the["bookindex_scroll"].length > 1) { +      document_section_keys_sequenced["scroll"] ~= "bookindex_scroll"; +    } +    if (document_the["blurb"].length > 1) { +      document_section_keys_sequenced["seg"]    ~= "blurb"; +      document_section_keys_sequenced["scroll"] ~= "blurb"; +      document_section_keys_sequenced["sql"]    ~= "blurb"; +    } +    if ((opt_action.html) +    || (opt_action.html_scroll) +    || (opt_action.html_seg) +    || (opt_action.epub)) { +      document_section_keys_sequenced["seg"]    ~= "tail"; +      document_section_keys_sequenced["scroll"] ~= "tail"; +    } +    auto sequenced_document_keys = docSectKeysSeq!()(document_section_keys_sequenced); +    auto segnames = html_segnames.dup; +    destroy(the_document_head_section); +    destroy(the_table_of_contents_section); +    destroy(the_document_body_section); +    destroy(the_endnotes_section); +    destroy(the_glossary_section); +    destroy(the_bibliography_section); +    destroy(the_bookindex_section); +    destroy(the_blurb_section); +    destroy(html_segnames); +    destroy(bookindex_unordered_hashes); +    destroy(an_object); +    obj_cite_digits                              = ocn_emit(OCNstatus.reset); +    biblio_arr_json                              = []; +    obj_cite_digit_                              = 0; +    html_segnames_ptr                            = 0; +    html_segnames_ptr_cntr                       = 0; +    content_non_header                           = "8"; +    dom_structure_markedup_tags_status           = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +    dom_structure_markedup_tags_status_buffer    = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +    dom_structure_collapsed_tags_status          = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +    dom_structure_collapsed_tags_status_buffer   = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +    debug(abstraction) { +      foreach (part; sequenced_document_keys.scroll) { +        foreach (ref obj; document_the[part]) { +          debug(node_misc) { +            if (obj.metainfo.is_a == "heading") { +              writeln("heading ancestors text?: ", obj.tags.heading_ancestors_text); +            } +          } +          debug(node_headings) { +            if (obj.metainfo.is_a == "heading") { +              writeln("---"); +              writeln(obj.text); +              writeln("  node:                    ", obj.metainfo.node); +              writeln("  ocn:                     ", obj.metainfo.ocn); +              writeln("  markedup heading lev:    ", obj.metainfo.heading_lev_markup); +              writeln("  collapsed heading lev    ", obj.metainfo.heading_lev_collapsed); +              writeln("  parent ocn:              ", obj.metainfo.parent_ocn); +              writeln("  parent lev:              ", obj.metainfo.parent_lev_markup); +              writeln("  markedup ancestors o_n:  ", obj.metainfo.markedup_ancestors); +              writeln("  dom markedup:            ", obj.metainfo.dom_structure_markedup_tags_status); +              writeln("  collapsed ancestors o_n: ", obj.metainfo.collapsed_ancestors); +              writeln("  dom collapsed:           ", obj.metainfo.dom_structure_collapsed_tags_status); +            } +          } +          debug(node_all) { +            writeln("---"); +            if (obj.metainfo.is_a == "heading") { +              writeln(obj.text); +            } +            writeln("node:                    ", obj.metainfo.node); +            writeln("ocn:                     ", obj.metainfo.ocn); +            writeln("markedup heading lev:    ", obj.metainfo.heading_lev_markup); +            writeln("collapsed heading lev    ", obj.metainfo.heading_lev_collapsed); +            writeln("markedup ancestors o_n:  ", obj.metainfo.markedup_ancestors); +            writeln("collapsed ancestors o_n: ", obj.metainfo.collapsed_ancestors); +            writeln("dom markedup:            ", obj.metainfo.dom_structure_markedup_tags_status); +            writeln("dom collapsed:           ", obj.metainfo.dom_structure_collapsed_tags_status); +            writeln("parent ocn:              ", obj.metainfo.parent_ocn); +            writeln("parent lev:              ", obj.metainfo.parent_lev_markup); +            writeln("Node:                    ", obj.metainfo.ocn); +          } +        } +      } +    } +    auto t = tuple( +      document_the, +      sequenced_document_keys, +      segnames, +      segnames_0_4, +      images, +    ); +    return t; +    /+ post loop markup document/text ↑ +/ +  } /+ ← closed: abstract doc source +/ +  /+ ↓ abstraction functions +/ +  static auto object_reset(O)(O an_object) { +    debug(asserts) { +      static assert(is(typeof(an_object) == string[string])); +    } +    an_object.remove("body_nugget"); +    an_object.remove("substantive"); +    an_object.remove("is"); +    an_object.remove("attrib"); +    an_object.remove("bookindex_nugget"); +    return an_object; +  } +  auto _common_reset_(L,O,T)( +    return ref L line_occur, +    return ref O an_object, +    return ref T obj_type_status +  ) { +    debug(asserts) { +      static assert(is(typeof(line_occur)      == int[string])); +      static assert(is(typeof(an_object)       == string[string])); +      static assert(is(typeof(obj_type_status) == int[string])); +    } +    line_occur["heading"]      = State.off; +    line_occur["para"]         = State.off; +    obj_type_status["heading"] = State.off; +    obj_type_status["para"]    = State.off; +    an_object = object_reset(an_object); +  } +  static auto _check_ocn_status_(L,T)( +    L            line, +    T            obj_type_status +  ) { +    debug(asserts) { +      static assert(is(typeof(line) == char[])); +      static assert(is(typeof(obj_type_status) == int[string])); +    } +    static auto rgx = Rgx(); +    if ((!line.empty) && (obj_type_status["ocn_status_off_for_multiple_objects"] == TriState.off)) { +      /+ not multi-line object, check whether object_number is on or turned off +/ +      if (line.matchFirst(rgx.object_number_block_marks)) { +        /+ switch off object_number +/ +        if (line.matchFirst(rgx.object_number_off_block)) { +          obj_type_status["ocn_status_off_for_multiple_objects"] = TriState.on; +          debug(ocnoff) { +            writeln(line); +          } +        } +        if (line.matchFirst(rgx.object_number_off_block_dh)) { +          obj_type_status["ocn_status_off_for_multiple_objects"] = TriState.closing; +          debug(ocnoff) { +            writeln(line); +          } +        } +      } else { +        if (obj_type_status["ocn_status_off_for_multiple_objects"] == TriState.off) { +          if (line.matchFirst(rgx.object_number_off)) { +            obj_type_status["ocn_status"] = OCNstatus.off; +          } else if (line.matchFirst(rgx.object_number_off_dh)) { +            obj_type_status["ocn_status"] = OCNstatus.closing; +          } else { +            obj_type_status["ocn_status"] = OCNstatus.on; +          } +        } else { +          obj_type_status["ocn_status"] +            = obj_type_status["ocn_status_off_for_multiple_objects"]; +        } +      } +    } else if ((!line.empty) && (obj_type_status["ocn_status_off_for_multiple_objects"] > TriState.off)) { +      if (line.matchFirst(rgx.object_number_off_block_close)) { +        obj_type_status["ocn_status_off_for_multiple_objects"] = TriState.off; +        obj_type_status["ocn_status"]                          = OCNstatus.on; +        debug(ocnoff) { +          writeln(line); +        } +      } +    } +    return obj_type_status; +  } +  auto _doc_header_and_make_substitutions_(L,CMM)( +    L    line, +    CMM  conf_make_meta, +  ) { +    debug(asserts) { +      static assert(is(typeof(line)            == char[])); +    } +    enum Substitute { match, markup, } +    if (conf_make_meta.make.substitute) { +      foreach(substitution_pair; conf_make_meta.make.substitute) { +        line = line.replaceAll( +          regex("\b" ~ substitution_pair[Substitute.match]), +          substitution_pair[Substitute.markup] +        ); +      } +    } +    return line; +  } +  auto _doc_header_and_make_substitutions_fontface_(L,CMM)( +    L    line, +    CMM  conf_make_meta, +  ) { +    debug(asserts) { +      static assert(is(typeof(line)            == char[])); +    } +    enum Substitute { match, markup, } +    if ( conf_make_meta.make.bold) { +      line = line.replaceAll( +        regex("\b" ~ conf_make_meta.make.bold[Substitute.match]), +        conf_make_meta.make.bold[Substitute.markup] +      ); +    } +    if (conf_make_meta.make.emphasis) { +      line = line.replaceAll( +        regex("\b" ~ conf_make_meta.make.emphasis[Substitute.match]), +        conf_make_meta.make.emphasis[Substitute.markup] +      ); +    } +    if (conf_make_meta.make.italics) { +      line = line.replaceAll( +        regex("\b" ~ conf_make_meta.make.italics[Substitute.match]), +        conf_make_meta.make.italics[Substitute.markup] +      ); +    } +    return line; +  } +  void _start_block_(L,T,N)( +               L line, +    return ref T obj_type_status, +    return ref N object_number_poem +  ) { +    debug(asserts) { +      static assert(is(typeof(line)                 == char[])); +      static assert(is(typeof(obj_type_status)      == int[string])); +      static assert(is(typeof(object_number_poem)   == string[string])); +    } +    static auto rgx = Rgx(); +    string code_block_syntax = ""; +    bool code_block_numbered = false; +    if (auto m = line.matchFirst(rgx.block_curly_code_open)) { +      /+ curly code open +/ +      code_block_syntax = (m.captures[1]) ? m.captures[1].to!string : ""; +      code_block_numbered = (m.captures[2] == "#") ? true : false; +      debug(code) {                              // code (curly) open +        writefln( +          "* [code curly] %s", +          line +        ); +      } +      obj_type_status["blocks"]     = TriState.on; +      obj_type_status["code"]       = TriState.on; +      obj_type_status["curly_code"] = TriState.on; +    } else if (line.matchFirst(rgx.block_curly_poem_open)) { +      /+ curly poem open +/ +      debug(poem) {                              // poem (curly) open +        writefln( +          "* [poem curly] %s", +          line +        ); +      } +      object_number_poem["start"] = obj_cite_digits.on.to!string; +      obj_type_status["blocks"]     = TriState.on; +      obj_type_status["verse_new"]  = State.on; +      obj_type_status["poem"]       = TriState.on; +      obj_type_status["curly_poem"] = TriState.on; +    } else if (line.matchFirst(rgx.block_curly_group_open)) { +      /+ curly group open +/ +      debug(group) {                             // group (curly) open +        writefln( +          "* [group curly] %s", +          line +        ); +      } +      obj_type_status["blocks"]      = TriState.on; +      obj_type_status["group"]       = TriState.on; +      obj_type_status["curly_group"] = TriState.on; +    } else if (line.matchFirst(rgx.block_curly_block_open)) { +      /+ curly block open +/ +      debug(block) {                             // block (curly) open +        writefln( +          "* [block curly] %s", +          line +        ); +      } +      obj_type_status["blocks"]      = TriState.on; +      obj_type_status["block"]       = TriState.on; +      obj_type_status["curly_block"] = TriState.on; +    } else if (line.matchFirst(rgx.block_curly_quote_open)) { +      /+ curly quote open +/ +      debug(quote) {                             // quote (curly) open +        writefln( +          "* [quote curly] %s", +          line +        ); +      } +      obj_type_status["blocks"]      = TriState.on; +      obj_type_status["quote"]       = TriState.on; +      obj_type_status["curly_quote"] = TriState.on; +    } else if (auto m = line.matchFirst(rgx.block_curly_table_open)) { +      /+ curly table open +/ +      debug(table) {                             // table (curly) open +        writefln( +          "* [table curly] %s", +          line +        ); +      } +      an_object["table_head"]        = m.captures[1].to!string; +      an_object["block_type"]        = "curly"; +      obj_type_status["blocks"]      = TriState.on; +      obj_type_status["table"]       = TriState.on; +      obj_type_status["curly_table"] = TriState.on; +    } else if (auto m = line.matchFirst(rgx.block_curly_table_special_markup)) { +      /+ table: special table block markup syntax! +/ +      an_object["table_head"]                       = m.captures[1].to!string; +      an_object["block_type"]                       = "special"; +      obj_type_status["blocks"]                     = TriState.on; +      obj_type_status["table"]                      = TriState.on; +      obj_type_status["curly_table_special_markup"] = TriState.on; +    } else if (auto m = line.matchFirst(rgx.block_tic_code_open)) { +      /+ tic code open +/ +      code_block_syntax = (m.captures[1]) ? m.captures[1].to!string : ""; +      code_block_numbered = (m.captures[2] == "#") ? true : false; +      debug(code) {                              // code (tic) open +        writefln( +          "* [code tic] %s", +          line +        ); +      } +      obj_type_status["blocks"]   = TriState.on; +      obj_type_status["code"]     = TriState.on; +      obj_type_status["tic_code"] = TriState.on; +    } else if (line.matchFirst(rgx.block_tic_poem_open)) { +      /+ tic poem open +/ +      debug(poem) {                              // poem (tic) open +        writefln( +          "* [poem tic] %s", +          line +        ); +      } +      object_number_poem["start"] = obj_cite_digits.on.to!string; +      obj_type_status["blocks"]    = TriState.on; +      obj_type_status["verse_new"] = State.on; +      obj_type_status["poem"]      = TriState.on; +      obj_type_status["tic_poem"]  = TriState.on; +    } else if (line.matchFirst(rgx.block_tic_group_open)) { +      /+ tic group open +/ +      debug(group) {                             // group (tic) open +        writefln( +          "* [group tic] %s", +          line +        ); +      } +      obj_type_status["blocks"]    = TriState.on; +      obj_type_status["group"]     = TriState.on; +      obj_type_status["tic_group"] = TriState.on; +    } else if (line.matchFirst(rgx.block_tic_block_open)) { +      /+ tic block open +/ +      debug(block) {                             // block (tic) open +        writefln( +          "* [block tic] %s", +          line +        ); +      } +      obj_type_status["blocks"]    = TriState.on; +      obj_type_status["block"]     = TriState.on; +      obj_type_status["tic_block"] = TriState.on; +    } else if (line.matchFirst(rgx.block_tic_quote_open)) { +      /+ tic quote open +/ +      debug(quote) {                             // quote (tic) open +        writefln( +          "* [quote tic] %s", +          line +        ); +      } +      obj_type_status["blocks"]    = TriState.on; +      obj_type_status["quote"]     = TriState.on; +      obj_type_status["tic_quote"] = TriState.on; +    } else if (auto m = line.matchFirst(rgx.block_tic_table_open)) { +      /+ tic table open +/ +      debug(table) {                             // table (tic) open +        writefln( +          "* [table tic] %s", +          line +        ); +      } +      an_object["table_head"]      = m.captures[1].to!string; +      an_object["block_type"]      = "tic"; +      obj_type_status["blocks"]    = TriState.on; +      obj_type_status["table"]     = TriState.on; +      obj_type_status["tic_table"] = TriState.on; +    } +  } +  void _quote_block_(L,O,T)( +               L line, +    return ref O an_object, +    return ref T obj_type_status +  ) { +    debug(asserts) { +      static assert(is(typeof(line)            == char[])); +      static assert(is(typeof(an_object)       == string[string])); +      static assert(is(typeof(obj_type_status) == int[string])); +    } +    static auto rgx = Rgx(); +    if (obj_type_status["curly_quote"] == TriState.on) { +      if (line.matchFirst(rgx.block_curly_quote_close)) { +        debug(quote) {                              // quote (curly) close +          writeln(line); +        } +        an_object[an_object_key] = an_object[an_object_key].stripRight; +        obj_type_status["blocks"]      = TriState.closing; +        obj_type_status["quote"]       = TriState.closing; +        obj_type_status["curly_quote"] = TriState.off; +      } else { +        debug(quote) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string) +      } +    } else if (obj_type_status["tic_quote"] == TriState.on) { +      if (line.matchFirst(rgx.block_tic_close)) { +        debug(quote) {                              // quote (tic) close +          writeln(line); +        } +        an_object[an_object_key] = an_object[an_object_key].stripRight; +        obj_type_status["blocks"]    = TriState.closing; +        obj_type_status["quote"]     = TriState.closing; +        obj_type_status["tic_quote"] = TriState.off; +      } else { +        debug(quote) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string) +      } +    } +  } +  void _group_block_(L,O,T)( +               L line, +    return ref O an_object, +    return ref T obj_type_status +  ) { +    debug(asserts) { +      static assert(is(typeof(line)            == char[])); +      static assert(is(typeof(an_object)       == string[string])); +      static assert(is(typeof(obj_type_status) == int[string])); +    } +    static auto rgx = Rgx(); +    if (obj_type_status["curly_group"] == State.on) { +      if (line.matchFirst(rgx.block_curly_group_close)) { +        debug(group) { +          writeln(line); +        } +        an_object[an_object_key] = an_object[an_object_key].stripRight; +        obj_type_status["blocks"]      = TriState.closing; +        obj_type_status["group"]       = TriState.closing; +        obj_type_status["curly_group"] = TriState.off; +      } else { +        debug(group) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";   // build group array (or string) +      } +    } else if (obj_type_status["tic_group"] == TriState.on) { +      if (line.matchFirst(rgx.block_tic_close)) { +        debug(group) { +          writeln(line); +        } +        an_object[an_object_key] = an_object[an_object_key].stripRight; +        obj_type_status["blocks"]    = TriState.closing; +        obj_type_status["group"]     = TriState.closing; +        obj_type_status["tic_group"] = TriState.off; +      } else { +        debug(group) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";   // build group array (or string) +      } +    } +  } +  void _block_block_(L,O,T)( +               L line, +    return ref O an_object, +    return ref T obj_type_status +  ) { +    debug(asserts) { +      static assert(is(typeof(line)            == char[])); +      static assert(is(typeof(an_object)       == string[string])); +      static assert(is(typeof(obj_type_status) == int[string])); +    } +    static auto rgx = Rgx(); +    if (obj_type_status["curly_block"] == TriState.on) { +      if (line.matchFirst(rgx.block_curly_block_close)) { +        debug(block) {                             // block (curly) close +          writeln(line); +        } +        an_object[an_object_key] = an_object[an_object_key].stripRight; +        obj_type_status["blocks"]      = TriState.closing; +        obj_type_status["block"]       = TriState.closing; +        obj_type_status["curly_block"] = TriState.off; +      } else { +        debug(block) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";   // build block array (or string) +      } +    } else if (obj_type_status["tic_block"] == TriState.on) { +      if (line.matchFirst(rgx.block_tic_close)) { +        debug(block) { +          writeln(line); +        } +        an_object[an_object_key] = an_object[an_object_key].stripRight; +        obj_type_status["blocks"]    = TriState.closing; +        obj_type_status["block"]     = TriState.closing; +        obj_type_status["tic_block"] = TriState.off; +      } else { +        debug(block) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";   // build block array (or string) +      } +    } +  } +  void _poem_block_(L,O,T,C,N,CMM)( +               L   line, +    return ref O   an_object, +    return ref T   obj_type_status, +    return ref C   cntr, +               N   object_number_poem, +               CMM conf_make_meta, +  ) { +    debug(asserts) { +      static assert(is(typeof(line)                 == char[])); +      static assert(is(typeof(an_object)            == string[string])); +      static assert(is(typeof(obj_type_status)      == int[string])); +      static assert(is(typeof(cntr)                 == int)); +      static assert(is(typeof(object_number_poem)   == string[string])); +    } +    static auto rgx = Rgx(); +    if (obj_type_status["curly_poem"] == TriState.on) { +      if (line.matchFirst(rgx.block_curly_poem_close)) { +        if (an_object_key in an_object +        || processing.length > 0) { +          an_object[an_object_key]                    = ""; +          debug(poem) { +            writefln( +              "* [poem curly] %s", +              line +            ); +          } +          if (processing.length > 0) { +            an_object[an_object_key] = processing["verse"]; +          } +          debug(poem) { +            writeln(__LINE__); +            writefln( +              "* %s %s", +              obj_cite_digits.on, +              line +            ); +          } +          if (an_object.length > 0) { +            debug(poem) {                             // poem (curly) close +              writeln( +                obj_cite_digits.on, +                an_object[an_object_key] +              ); +            } +            an_object["is"]                           = "verse"; +            auto substantive_obj_misc_tuple +              = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, false); +            an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; +            anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; +            comp_obj_block                               = comp_obj_block.init; +            comp_obj_block.metainfo.is_of_part           = "body"; +            comp_obj_block.metainfo.is_of_section        = "body"; +            comp_obj_block.metainfo.is_of_type           = "block"; +            comp_obj_block.metainfo.is_a                 = "verse"; +            comp_obj_block.metainfo.ocn                  = obj_cite_digits.on; +            comp_obj_block.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +            comp_obj_block.metainfo.o_n_book_index       = obj_cite_digits.bkidx; +            comp_obj_block.metainfo.object_number_type   = obj_cite_digits.type; +            comp_obj_block.text                          = an_object["substantive"]; +            comp_obj_block.has.inline_notes_reg          = substantive_obj_misc_tuple[sObj.notes_reg]; +            comp_obj_block.has.inline_notes_star         = substantive_obj_misc_tuple[sObj.notes_star]; +            comp_obj_block.has.inline_links              = substantive_obj_misc_tuple[sObj.links]; +            the_document_body_section                    ~= comp_obj_block; +          } +          object_reset(an_object); +          processing.remove("verse"); +          ++cntr; +        } +        object_number_poem["end"]   = obj_cite_digits.on.to!string; +        obj_type_status["blocks"]     = TriState.closing; +        obj_type_status["poem"]       = TriState.closing; +        obj_type_status["curly_poem"] = TriState.off; +      } else { +        processing["verse"] ~= line ~= "\n"; +        if (obj_type_status["verse_new"] == State.on) { +          obj_cite_digits = ocn_emit(OCNstatus.on); +          obj_type_status["verse_new"] = State.off; +        } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) { +          processing["verse"] = processing["verse"].stripRight; +          verse_line = TriState.off; +          obj_type_status["verse_new"] = State.on; +        } +        if (obj_type_status["verse_new"] == State.on) { +          verse_line=1; +          an_object[an_object_key] = processing["verse"]; +          debug(poem) {                          // poem verse +            writefln( +              "* %s curly\n%s", +              obj_cite_digits.on, +              an_object[an_object_key] +            ); +          } +          processing.remove("verse"); +          an_object["is"]                           = "verse"; +          auto comp_obj_location = node_construct.node_location_emitter( +            content_non_header, +            segment_anchor_tag_that_object_belongs_to, +            obj_cite_digits, +            cntr, +            heading_ptr-1, +            an_object["is"] +          ); +          auto substantive_obj_misc_tuple +            = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, false); +          an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; +          anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; +          comp_obj_block                               = comp_obj_block.init; +          comp_obj_block.metainfo.is_of_part           = "body"; +          comp_obj_block.metainfo.is_of_section        = "body"; +          comp_obj_block.metainfo.is_of_type           = "block"; +          comp_obj_block.metainfo.is_a                 = "verse"; +          comp_obj_block.metainfo.ocn                  = obj_cite_digits.on; +          comp_obj_block.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +          comp_obj_block.metainfo.o_n_book_index       = obj_cite_digits.bkidx; +          comp_obj_block.metainfo.object_number_type   = obj_cite_digits.type; +          comp_obj_block.text                          = an_object["substantive"]; +          comp_obj_block.has.inline_notes_reg          = substantive_obj_misc_tuple[sObj.notes_reg]; +          comp_obj_block.has.inline_notes_star         = substantive_obj_misc_tuple[sObj.notes_star]; +          comp_obj_block.has.inline_links              = substantive_obj_misc_tuple[sObj.links]; +          the_document_body_section                    ~= comp_obj_block; +          object_reset(an_object); +          processing.remove("verse"); +          ++cntr; +        } +      } +    } else if (obj_type_status["tic_poem"] == TriState.on) { +      if (auto m = line.matchFirst(rgx.block_tic_close)) { // tic_poem_close +        an_object[an_object_key]="verse"; +        debug(poem) { +          writefln( +            "* [poem tic] %s", +            line +          ); +        } +        if (processing.length > 0) { +          an_object[an_object_key] = processing["verse"]; +        } +        if (an_object.length > 0) { +          debug(poem) {                                     // poem (tic) close +            writeln(__LINE__); +            writeln(obj_cite_digits.on, line); +          } +          processing.remove("verse"); +          an_object["is"]                           = "verse"; +          auto substantive_obj_misc_tuple +            = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, false); +          an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; +          anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; +          comp_obj_block                               = comp_obj_block.init; +          comp_obj_block.metainfo.is_of_part           = "body"; +          comp_obj_block.metainfo.is_of_section        = "body"; +          comp_obj_block.metainfo.is_of_type           = "block"; +          comp_obj_block.metainfo.is_a                 = "verse"; +          comp_obj_block.metainfo.ocn                  = obj_cite_digits.on; +          comp_obj_block.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +          comp_obj_block.metainfo.o_n_book_index       = obj_cite_digits.bkidx; +          comp_obj_block.metainfo.object_number_type   = obj_cite_digits.type; +          comp_obj_block.text                          = an_object["substantive"]; +          comp_obj_block.has.inline_notes_reg          = substantive_obj_misc_tuple[sObj.notes_reg]; +          comp_obj_block.has.inline_notes_star         = substantive_obj_misc_tuple[sObj.notes_star]; +          comp_obj_block.has.inline_links              = substantive_obj_misc_tuple[sObj.links]; +          the_document_body_section                    ~= comp_obj_block; +          object_number_poem["end"]                    = obj_cite_digits.on.to!string; +          object_reset(an_object); +          processing.remove("verse"); +          ++cntr; +        } +        obj_type_status["blocks"]   = TriState.closing; +        obj_type_status["poem"]     = TriState.closing; +        obj_type_status["tic_poem"] = TriState.off; +      } else { +        processing["verse"] ~= line ~= "\n"; +        if (obj_type_status["verse_new"] == State.on) { +          obj_cite_digits = ocn_emit(OCNstatus.on); +          obj_type_status["verse_new"] = State.off; +        } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) { +          processing["verse"] = processing["verse"].stripRight; +          obj_type_status["verse_new"] = State.on; +          verse_line = TriState.off; +        } +        if (obj_type_status["verse_new"] == State.on) { +          verse_line=1; +          an_object[an_object_key] = processing["verse"]; +          debug(poem) {                            // poem (tic) close +            writefln( +              "* %s tic\n%s", +              obj_cite_digits.on, +              an_object[an_object_key] +            ); +          } +          processing.remove("verse"); +          an_object["is"]                           = "verse"; +          auto comp_obj_location +            = node_construct.node_location_emitter( +              content_non_header, +              segment_anchor_tag_that_object_belongs_to, +              obj_cite_digits, +              cntr, +              heading_ptr-1, +              an_object["is"] +            ); +          auto substantive_obj_misc_tuple +            = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, false); +          an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; +          anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; +          comp_obj_block                               = comp_obj_block.init; +          comp_obj_block.metainfo.is_of_part           = "body"; +          comp_obj_block.metainfo.is_of_section        = "body"; +          comp_obj_block.metainfo.is_of_type           = "block"; +          comp_obj_block.metainfo.is_a                 = "verse"; +          comp_obj_block.metainfo.ocn                  = obj_cite_digits.on; +          comp_obj_block.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +          comp_obj_block.metainfo.o_n_book_index       = obj_cite_digits.bkidx; +          comp_obj_block.metainfo.object_number_type   = obj_cite_digits.type; +          comp_obj_block.text                          = an_object["substantive"]; +          comp_obj_block.has.inline_notes_reg          = substantive_obj_misc_tuple[sObj.notes_reg]; +          comp_obj_block.has.inline_notes_star         = substantive_obj_misc_tuple[sObj.notes_star]; +          comp_obj_block.has.inline_links              = substantive_obj_misc_tuple[sObj.links]; +          the_document_body_section                    ~= comp_obj_block; +          object_reset(an_object); +          processing.remove("verse"); +          ++cntr; +        } +      } +    } +  } +  void _code_block_(L,O,T)( +               L line, +    return ref O an_object, +    return ref T obj_type_status +  ) { +    debug(asserts) { +      static assert(is(typeof(line)            == char[])); +      static assert(is(typeof(an_object)       == string[string])); +      static assert(is(typeof(obj_type_status) == int[string])); +    } +    static auto rgx = Rgx(); +    if (obj_type_status["curly_code"] == TriState.on) { +      if (line.matchFirst(rgx.block_curly_code_close)) { +        debug(code) {                                    // code (curly) close +          writeln(line); +        } +        an_object[an_object_key] = an_object[an_object_key] +          .replaceFirst(rgx.newline_eol_delimiter_only, "") +          .stripRight; +        obj_type_status["blocks"]     = TriState.closing; +        obj_type_status["code"]       = TriState.closing; +        obj_type_status["curly_code"] = TriState.off; +      } else { +        debug(code) {                                    // code (curly) line +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";        // code (curly) line +      } +    } else if (obj_type_status["tic_code"] == TriState.on) { +      if (line.matchFirst(rgx.block_tic_close)) { +        debug(code) {                                    // code (tic) close +          writeln(line); +        } +        an_object[an_object_key] = an_object[an_object_key] +          .replaceFirst(rgx.newline_eol_delimiter_only, "") +          .stripRight; +        obj_type_status["blocks"]   = TriState.closing; +        obj_type_status["code"]     = TriState.closing; +        obj_type_status["tic_code"] = TriState.off; +      } else { +        debug(code) {                                    // code (tic) line +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";        // code (tic) line +      } +    } +  } +  void _table_block_(L,O,T,CMM)( +               L line, +    return ref O an_object, +    return ref T   obj_type_status, +    return ref CMM conf_make_meta, +  ) { +    debug(asserts) { +      static assert(is(typeof(line)            == char[])); +      static assert(is(typeof(an_object)       == string[string])); +      static assert(is(typeof(obj_type_status) == int[string])); +    } +    static auto rgx = Rgx(); +    if (obj_type_status["curly_table"] == TriState.on) { +      if (line.matchFirst(rgx.block_curly_table_close)) { +        debug(table) {                           // table (curly) close +          writeln(line); +        } +        obj_type_status["blocks"]      = TriState.closing; +        obj_type_status["table"]       = TriState.closing; +        obj_type_status["curly_table"] = TriState.off; +      } else { +        debug(table) {                           // table +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";           // build table array (or string) +      } +    } else if (obj_type_status["curly_table_special_markup"] == TriState.on) { +      if (line.empty) { +        obj_type_status["blocks"]                     = TriState.off; +        obj_type_status["table"]                      = TriState.off; +        obj_type_status["curly_table_special_markup"] = TriState.off; +        _table_closed_make_special_notation_table_( +          line, +          an_object, +          the_document_body_section, +          obj_cite_digits, +          comp_obj_heading, +          cntr, +          obj_type_status, +          conf_make_meta, +        ); +      } else { +        debug(table) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n"; +      } +    } else if (obj_type_status["tic_table"] == TriState.on) { +      if (line.matchFirst(rgx.block_tic_close)) { +        debug(table) {                           // table (tic) close +          writeln(line); +        } +        obj_type_status["blocks"]    = TriState.closing; +        obj_type_status["table"]     = TriState.closing; +        obj_type_status["tic_table"] = TriState.off; +      } else { +        debug(table) {                           // table +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";           // build table array (or string) +      } +    } +  } +  final string biblio_tag_map(A)(A abr) { +    debug(asserts) { +      static assert(is(typeof(abr) == string)); +    } +    auto btm = [ +      "au"                               : "author_raw", +      "ed"                               : "editor_raw", +      "ti"                               : "fulltitle", +      "lng"                              : "language", +      "jo"                               : "journal", +      "vol"                              : "volume", +      "edn"                              : "edition", +      "yr"                               : "year", +      "pl"                               : "place", +      "pb"                               : "publisher", +      "pub"                              : "publisher", +      "pg"                               : "pages", +      "pgs"                              : "pages", +      "sn"                               : "short_name" +    ]; +    return btm[abr]; +  } +  void _biblio_block_( +    char[]                 line, +    return ref int[string] obj_type_status, +    return ref int         bib_entry, +    return ref string      biblio_entry_str_json, +    return ref string[]    biblio_arr_json +  ) { +    mixin SiSUbiblio; +    auto jsn = BibJsnStr(); +    static auto rgx = Rgx(); +    if (line.matchFirst(rgx.heading_biblio)) { +      obj_type_status["biblio_section"]   = TriState.on; +      obj_type_status["blurb_section"]    = State.off; +      obj_type_status["glossary_section"] = State.off; +    } +    if (line.empty) { +      debug { +        debug(biblioblock) { +          writeln("---"); +        } +        debug(biblioblockinclude) { +          writeln(biblio_entry_str_json.length); +        } +      } +      if ((bib_entry == State.off) +      && (biblio_entry_str_json.empty)) { +        bib_entry = State.on; +        biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr; +      } else if (!(biblio_entry_str_json.empty)) { +        bib_entry = State.off; +        if (!(biblio_entry_str_json == jsn.biblio_entry_tags_jsonstr)) { +          auto biblio_entry = parseJSON(biblio_entry_str_json); +          if (biblio_entry["fulltitle"].str.empty) { +            writeln("check problem entry (Title missing): ", biblio_entry_str_json); +          } else if ((biblio_entry["author_raw"].str.empty) && (biblio_entry["editor_raw"].str.empty)) { +            writeln("check problem entry (No author and no editor): ", biblio_entry_str_json); +          } else { +            biblio_arr_json ~= biblio_entry_str_json; +          } +          biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr; +        } +      } else { // CHECK ERROR +        writeln("?? 2. ERROR ", biblio_entry_str_json, "??"); +        biblio_entry_str_json = ""; +      } +    } else if (line.matchFirst(rgx.biblio_tags)) { +      debug(biblioblock) { +        writeln(line); +      } +      auto bt = line.match(rgx.biblio_tags); +      bib_entry = State.off; +      st = bt.captures[1].to!string; +      auto header_tag_value=(bt.captures[2]).to!string; +      JSONValue j = parseJSON(biblio_entry_str_json); +      biblio_tag_name = (st.match(rgx.biblio_abbreviations)) +        ? (biblio_tag_map(st)) +        : st; +      j.object[biblio_tag_name] = header_tag_value; +      debug(bibliounsortedcheckduplicates) { +        writeln(biblio_tag_name, ": ", header_tag_value); +        writeln("--"); +      } +      switch (biblio_tag_name) { +      case "author_raw": // author_arr author (fn sn) +        j["author_arr"] +         = header_tag_value.split(rgx.arr_delimiter); +        string tmp; +        biblioAuthorLoop: +        foreach (au; j["author_arr"].array) { +          if (auto x = au.str.match(rgx.name_delimiter)) { +            tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", "; +          } else { +            tmp ~= au.str; +          } +        } +        tmp = (tmp).replace(rgx.trailing_comma, ""); +        j["author"].str = tmp; +        goto default; +      case "editor_raw": // editor_arr editor (fn sn) +        j["editor_arr"] +          = header_tag_value.split(rgx.arr_delimiter); +        string tmp; +        biblioEditorLoop: +        foreach (ed; j["editor_arr"].array) { +          if (auto x = ed.str.match(rgx.name_delimiter)) { +            tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", "; +          } else { +            tmp ~= ed.str; +          } +        } +        tmp = (tmp).replace(rgx.trailing_comma, ""); +        j["editor"].str = tmp; +        goto default; +      case "fulltitle": // title & subtitle +        goto default; +      default: +        break; +      } +      auto s = j.toString(); +      debug(biblio1) { +        writefln( +          "* %s: %s\n%s", +          biblio_tag_name, +          biblio_tag_entry, +          j[biblio_tag_name] +        ); +      } +      if (line.match(rgx.comment)) { +        writeln("ERROR", line, "COMMENT"); +        writeln("ERROR", s, "%%"); +      } +      if (!(match(line, rgx.comment))) { +        debug(biblioblockinclude) { +          writeln(line); +        } +        biblio_entry_str_json = s; +      } else { +        biblio_entry_str_json = ""; +      } +      header_tag_value=""; +    } +  } +  void _table_closed_make_special_notation_table_(N,CMM)( +    char[]                           line, +    return ref string[string]        an_object, +    return ref ObjGenericComposite[] the_document_body_section, +    return ref N                     obj_cite_digits, +    return ref ObjGenericComposite   _comp_obj_heading, +    return ref int                   cntr, +    return ref int[string]           obj_type_status, +    CMM                              conf_make_meta +  ) { +      comp_obj_block = comp_obj_block.init; +      obj_cite_digits = ocn_emit(OCNstatus.on); +      auto comp_obj_location +        = node_construct.node_location_emitter( +          content_non_header, +          segment_anchor_tag_that_object_belongs_to, +          obj_cite_digits, +          cntr, +          heading_ptr-1, +          "table" +        ); +      an_object["is"] = "table"; +      auto substantive_obj_misc_tuple +        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, "body_nugget", conf_make_meta, false); +      an_object["substantive"]                     = substantive_obj_misc_tuple[sObj.content]; +      comp_obj_block.metainfo.ocn                  = obj_cite_digits.on; +      comp_obj_block.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +      comp_obj_block.metainfo.o_n_book_index       = obj_cite_digits.bkidx; +      comp_obj_block.metainfo.object_number_type   = obj_cite_digits.type; +      comp_obj_block                               = table_instructions(comp_obj_block, an_object["table_head"]); +      comp_obj_block                               = table_substantive_munge_special(comp_obj_block, an_object["substantive"]); +      the_document_body_section                    ~= comp_obj_block; +      object_reset(an_object); +      processing.remove("verse"); +      ++cntr; +  } +  void _block_flag_line_empty_(B,N,CMM)( +    B                                   bookindex_extract_hash, +    char[]                              line, +    return ref string[string]           an_object, +    return ref ObjGenericComposite[]    the_document_body_section, +    return ref string[][string][string] bookindex_unordered_hashes, +    return ref N                        obj_cite_digits, +    return ref ObjGenericComposite      _comp_obj_heading, +    return ref int                      cntr, +    return ref int[string]              obj_type_status, +    string[string]                      object_number_poem, +    CMM                                 conf_make_meta, +  ) { +    assert( +      line.empty, +      "\nline should be empty:\n  \"" +      ~ line ~ "\"" +    ); +    assert( +      (obj_type_status["blocks"] == TriState.closing), +      "code block status: closed" +    ); +    assertions_flag_types_block_status_none_or_closed(obj_type_status); +    if (obj_type_status["quote"] == TriState.closing) { +      obj_cite_digits = ocn_emit(OCNstatus.on); +      an_object["bookindex_nugget"] +        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; +      bookindex_unordered_hashes +        = bookindex_extract_hash.bookindex_nugget_hash( +          an_object["bookindex_nugget"], +          obj_cite_digits, +          segment_anchor_tag_that_object_belongs_to +        ); +      an_object["is"] = "quote"; +      auto comp_obj_location +        = node_construct.node_location_emitter( +          content_non_header, +          segment_anchor_tag_that_object_belongs_to, +          obj_cite_digits, +          cntr, +          heading_ptr-1, +          an_object["is"] +        ); +      auto substantive_obj_misc_tuple +        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, false); +      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; +      anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; +      comp_obj_block                               = comp_obj_block.init; +      comp_obj_block.metainfo.is_of_part           = "body"; +      comp_obj_block.metainfo.is_of_section        = "body"; +      comp_obj_block.metainfo.is_of_type           = "block"; +      comp_obj_block.metainfo.is_a                 = "quote"; +      comp_obj_block.metainfo.ocn                  = obj_cite_digits.on; +      comp_obj_block.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +      comp_obj_block.metainfo.o_n_book_index       = obj_cite_digits.bkidx; +      comp_obj_block.metainfo.object_number_type   = obj_cite_digit_type; +      comp_obj_block.text                          = an_object["substantive"]; +      comp_obj_block.has.inline_notes_reg          = substantive_obj_misc_tuple[sObj.notes_reg]; +      comp_obj_block.has.inline_notes_star         = substantive_obj_misc_tuple[sObj.notes_star]; +      comp_obj_block.has.inline_links              = substantive_obj_misc_tuple[sObj.links]; +      the_document_body_section                    ~= comp_obj_block; +      obj_type_status["blocks"]                    = TriState.off; +      obj_type_status["quote"]                     = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +      ++cntr; +    } else if (obj_type_status["group"] == TriState.closing) { +      obj_cite_digits = ocn_emit(OCNstatus.on); +      an_object["bookindex_nugget"] +        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; +      bookindex_unordered_hashes +        = bookindex_extract_hash.bookindex_nugget_hash( +          an_object["bookindex_nugget"], +          obj_cite_digits, +          segment_anchor_tag_that_object_belongs_to +        ); +      an_object["is"] = "group"; +      auto comp_obj_location +        = node_construct.node_location_emitter( +          content_non_header, +          segment_anchor_tag_that_object_belongs_to, +          obj_cite_digits, +          cntr, +          heading_ptr-1, +          an_object["is"] +        ); +      auto substantive_obj_misc_tuple +        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, false); +      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; +      anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; +      comp_obj_block                               = comp_obj_block.init; +      comp_obj_block.metainfo.is_of_part           = "body"; +      comp_obj_block.metainfo.is_of_section        = "body"; +      comp_obj_block.metainfo.is_of_type           = "block"; +      comp_obj_block.metainfo.is_a                 = "group"; +      comp_obj_block.metainfo.ocn                  = obj_cite_digits.on; +      comp_obj_block.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +      comp_obj_block.metainfo.o_n_book_index       = obj_cite_digits.bkidx; +      comp_obj_block.metainfo.object_number_type   = obj_cite_digits.type; +      comp_obj_block.text                          = an_object["substantive"]; +      comp_obj_block.has.inline_notes_reg          = substantive_obj_misc_tuple[sObj.notes_reg]; +      comp_obj_block.has.inline_notes_star         = substantive_obj_misc_tuple[sObj.notes_star]; +      comp_obj_block.has.inline_links              = substantive_obj_misc_tuple[sObj.links]; +      the_document_body_section                    ~= comp_obj_block; +      obj_type_status["blocks"]                    = TriState.off; +      obj_type_status["group"]                     = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +      ++cntr; +    } else if (obj_type_status["block"] == TriState.closing) { +      obj_cite_digits = ocn_emit(OCNstatus.on); +      an_object["bookindex_nugget"] +        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; +      bookindex_unordered_hashes +        = bookindex_extract_hash.bookindex_nugget_hash( +          an_object["bookindex_nugget"], +          obj_cite_digits, +          segment_anchor_tag_that_object_belongs_to +        ); +      an_object["is"] = "block"; +      auto comp_obj_location +        = node_construct.node_location_emitter( +          content_non_header, +          segment_anchor_tag_that_object_belongs_to, +          obj_cite_digits, +          cntr, +          heading_ptr-1, +          an_object["is"] +        ); +      auto substantive_obj_misc_tuple +        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, false); +      an_object["substantive"]                     = substantive_obj_misc_tuple[sObj.content]; +      comp_obj_block                               = comp_obj_block.init; +      comp_obj_block.metainfo.is_of_part           = "body"; +      comp_obj_block.metainfo.is_of_section        = "body"; +      comp_obj_block.metainfo.is_of_type           = "block"; +      comp_obj_block.metainfo.is_a                 = "block"; +      comp_obj_block.metainfo.ocn                  = obj_cite_digits.on; +      comp_obj_block.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +      comp_obj_block.metainfo.o_n_book_index       = obj_cite_digits.bkidx; +      comp_obj_block.metainfo.object_number_type   = obj_cite_digit_type; +      comp_obj_block.text                          = an_object["substantive"]; +      comp_obj_block.has.inline_notes_reg          = substantive_obj_misc_tuple[sObj.notes_reg]; +      comp_obj_block.has.inline_notes_star         = substantive_obj_misc_tuple[sObj.notes_star]; +      comp_obj_block.has.inline_links              = substantive_obj_misc_tuple[sObj.links]; +      the_document_body_section                    ~= comp_obj_block; +      obj_type_status["blocks"]                    = TriState.off; +      obj_type_status["block"]                     = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +      ++cntr; +    } else if (obj_type_status["poem"] == TriState.closing) { +      an_object["bookindex_nugget"] +        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; +      bookindex_unordered_hashes +        = bookindex_extract_hash.bookindex_nugget_hash( +          an_object["bookindex_nugget"], +          obj_cite_digits, +          segment_anchor_tag_that_object_belongs_to +        ); +      an_object["is"]                           = "verse"; +      auto comp_obj_location +        = node_construct.node_location_emitter( +          content_non_header, +          segment_anchor_tag_that_object_belongs_to, +          obj_cite_digits, +          cntr, +          heading_ptr-1, +          an_object["is"] +        ); +      comp_obj_poem_ocn                               = comp_obj_poem_ocn.init; +      comp_obj_poem_ocn.metainfo.is_of_part           = "body"; +      comp_obj_poem_ocn.metainfo.is_of_section        = "body"; +      comp_obj_poem_ocn.metainfo.is_of_type           = "block"; +      comp_obj_poem_ocn.metainfo.is_a                 = "poem"; +      comp_obj_poem_ocn.metainfo.ocn                  = obj_cite_digits.on; +      comp_obj_poem_ocn.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; // +      comp_obj_poem_ocn.metainfo.o_n_book_index       = obj_cite_digits.bkidx; // +      comp_obj_poem_ocn.metainfo.object_number_type   = obj_cite_digits.type; +      comp_obj_poem_ocn.text                          = ""; +      the_document_body_section                       ~= comp_obj_poem_ocn; +      obj_type_status["blocks"]                       = TriState.off; +      obj_type_status["poem"]                         = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +    } else if (obj_type_status["code"] == TriState.closing) { +      obj_cite_digits = ocn_emit(OCNstatus.on); +      an_object["bookindex_nugget"] +        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; +      bookindex_unordered_hashes +        = bookindex_extract_hash.bookindex_nugget_hash( +          an_object["bookindex_nugget"], +          obj_cite_digits, +          segment_anchor_tag_that_object_belongs_to +        ); +      an_object["is"] = "code"; +      auto comp_obj_location +        = node_construct.node_location_emitter( +          content_non_header, +          segment_anchor_tag_that_object_belongs_to, +          obj_cite_digits, +          cntr, +          heading_ptr-1, +          an_object["is"] +        ); +      auto substantive_obj_misc_tuple +        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, false); +      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; +      anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; +      comp_obj_code                                = comp_obj_code.init; +      comp_obj_code.metainfo.is_of_part            = "body"; +      comp_obj_code.metainfo.is_of_section         = "body"; +      comp_obj_code.metainfo.is_of_type            = "block"; +      comp_obj_code.metainfo.is_a                  = "code"; +      comp_obj_code.metainfo.ocn                   = obj_cite_digits.on; +      comp_obj_block.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +      comp_obj_block.metainfo.o_n_book_index       = obj_cite_digits.bkidx; +      comp_obj_block.metainfo.object_number_type   = obj_cite_digits.type; +      comp_obj_code.text                           = an_object["substantive"]; +      comp_obj_code.has.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg]; +      comp_obj_code.has.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star]; +      comp_obj_code.has.inline_links               = substantive_obj_misc_tuple[sObj.links]; +      the_document_body_section                    ~= comp_obj_code; +      obj_type_status["blocks"]                    = TriState.off; +      obj_type_status["code"]                      = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +      ++cntr; +    } else if (obj_type_status["table"] == TriState.closing) { +      comp_obj_block = comp_obj_block.init; +      obj_cite_digits = ocn_emit(OCNstatus.on); +      an_object["bookindex_nugget"] +        = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; +      bookindex_unordered_hashes +        = bookindex_extract_hash.bookindex_nugget_hash( +          an_object["bookindex_nugget"], +          obj_cite_digits, +          segment_anchor_tag_that_object_belongs_to +        ); +      an_object["is"] = "table"; +      auto comp_obj_location +        = node_construct.node_location_emitter( +          content_non_header, +          segment_anchor_tag_that_object_belongs_to, +          obj_cite_digits, +          cntr, +          heading_ptr-1, +          an_object["is"] +        ); +      auto substantive_obj_misc_tuple +        = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, false); +      an_object["substantive"]                     = substantive_obj_misc_tuple[sObj.content]; +      comp_obj_block                               = comp_obj_block.init; +      comp_obj_block.metainfo.ocn                  = obj_cite_digits.on; +      comp_obj_block.metainfo.object_number_off    = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +      comp_obj_block.metainfo.o_n_book_index       = obj_cite_digits.bkidx; +      comp_obj_block.metainfo.object_number_type   = obj_cite_digits.type; +      comp_obj_block                               = table_instructions(comp_obj_block, an_object["table_head"]); +      comp_obj_block                               = table_substantive_munge(comp_obj_block, an_object["substantive"]); +      the_document_body_section                    ~= comp_obj_block; +      obj_type_status["blocks"]                    = TriState.off; +      obj_type_status["table"]                     = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +      ++cntr; +    } +  } +  auto _book_index_(L,I,O,T,B)( +    L      line, +    return ref I  book_idx_tmp, +    return ref O  an_object, +    return ref T  obj_type_status, +    B             opt_action, +  ) { +    debug(asserts) { +      static assert(is(typeof(line)            == char[])); +      static assert(is(typeof(book_idx_tmp)    == string)); +      static assert(is(typeof(an_object)       == string[string])); +      static assert(is(typeof(obj_type_status) == int[string])); +    } +    static auto rgx = Rgx(); +    if (auto m = line.match(rgx.book_index)) { +      /+ match book_index +/ +      debug(bookindexmatch) { +        writefln( +          "* [bookindex] %s\n", +          m.captures[1].to!string, +        ); +      } +      an_object["bookindex_nugget"] = m.captures[1].to!string; +    } else if (auto m = line.match(rgx.book_index_open))  { +      /+ match open book_index +/ +      obj_type_status["book_index"] = State.on; +      if (opt_action.backmatter && opt_action.section_bookindex) { +        book_idx_tmp = m.captures[1].to!string; +        debug(bookindexmatch) { +          writefln( +            "* [bookindex] %s\n", +            book_idx_tmp, +          ); +        } +      } +    } else if (obj_type_status["book_index"] == State.on )  { +      /+ book_index flag set +/ +      if (auto m = line.match(rgx.book_index_close))  { +        obj_type_status["book_index"] = State.off; +        if (opt_action.backmatter +        && opt_action.section_bookindex) { +          an_object["bookindex_nugget"] = book_idx_tmp ~ m.captures[1].to!string; +          debug(bookindexmatch) { +            writefln( +              "* [bookindex] %s\n", +              book_idx_tmp, +            ); +          } +        } +        book_idx_tmp = ""; +      } else { +        if (opt_action.backmatter +        && opt_action.section_bookindex) { +          book_idx_tmp ~= line; +        } +      } +    } +  } +  auto _heading_found_(L,X,H,R,T)( +    L     line, +    X     _make_unmarked_headings, +    return ref H heading_match_str, +    return ref R heading_match_rgx, +    return ref T obj_type_status +  ) { +    debug(asserts) { +      static assert(is(typeof(line)                      == char[])); +      static assert(is(typeof(_make_unmarked_headings)   == string[])); +      static assert(is(typeof(heading_match_str)         == string[string])); +      static assert(is(typeof(heading_match_rgx)         == Regex!(char)[string])); +      static assert(is(typeof(obj_type_status)           == int[string])); +    } +    static auto rgx = Rgx(); +    if ((_make_unmarked_headings.length > 2) +    && (obj_type_status["make_headings"] == State.off)) { +      /+ headings found +/ +      debug(headingsfound) { +        writeln(_make_unmarked_headings); +      } +      debug(headingsfound) { +        writeln(_make_unmarked_headings.length); +        writeln(_make_unmarked_headings); +      } +      switch (_make_unmarked_headings.length) { +      case 7 : +        if (!empty(_make_unmarked_headings[6])) { +          heading_match_str["h_4"] +            = "^(" ~ _make_unmarked_headings[6].to!string ~ ")"; +          heading_match_rgx["h_4"] +            = regex(heading_match_str["h_4"]); +        } +        goto case; +      case 6 : +        if (!empty(_make_unmarked_headings[5])) { +          heading_match_str["h_3"] +            = "^(" ~ _make_unmarked_headings[5].to!string ~ ")"; +          heading_match_rgx["h_3"] +            = regex(heading_match_str["h_3"]); +        } +        goto case; +      case 5 : +        if (!empty(_make_unmarked_headings[4])) { +          heading_match_str["h_2"] +            = "^(" ~ _make_unmarked_headings[4].to!string ~ ")"; +          heading_match_rgx["h_2"] +            = regex(heading_match_str["h_2"]); +        } +        goto case; +      case 4 : +        if (!empty(_make_unmarked_headings[3])) { +          heading_match_str["h_1"] +            = "^(" ~ _make_unmarked_headings[3].to!string ~ ")"; +          heading_match_rgx["h_1"] +            = regex(heading_match_str["h_1"]); +        } +        goto case; +      case 3 : +        if (!empty(_make_unmarked_headings[2])) { +          heading_match_str["h_D"] +            = "^(" ~ _make_unmarked_headings[2].to!string ~ ")"; +          heading_match_rgx["h_D"] +            = regex(heading_match_str["h_D"]); +        } +        goto case; +      case 2 : +        if (!empty(_make_unmarked_headings[1])) { +          heading_match_str["h_C"] +            = "^(" ~ _make_unmarked_headings[1].to!string ~ ")"; +          heading_match_rgx["h_C"] +            = regex(heading_match_str["h_C"]); +        } +        goto case; +      case 1 : +        if (!empty(_make_unmarked_headings[0])) { +          heading_match_str["h_B"] +            = "^(" ~ _make_unmarked_headings[0].to!string ~ ")"; +          heading_match_rgx["h_B"] +            = regex(heading_match_str["h_B"]); +        } +        break; +      default: +        break; +      } +      obj_type_status["make_headings"] = State.on; +    } +  } +  auto _heading_make_set_(L,C,R,T)( +               L line, +               C line_occur, +    return ref R heading_match_rgx, +    return ref T obj_type_status +  ) { +    debug(asserts) { +      static assert(is(typeof(line)              == char[])); +      static assert(is(typeof(line_occur)        == int[string])); +      static assert(is(typeof(heading_match_rgx) == Regex!(char)[string])); +      static assert(is(typeof(obj_type_status)   == int[string])); +    } +    if ((obj_type_status["make_headings"] == State.on) +    && ((line_occur["para"] == State.off) +    && (line_occur["heading"] == State.off)) +    && ((obj_type_status["para"] == State.off) +    && (obj_type_status["heading"] == State.off))) { +      /+ heading make set +/ +      if (line.matchFirst(heading_match_rgx["h_B"])) { +        line = "B~ " ~ line; +        debug(headingsfound) { +          writeln(line); +        } +      } +      if (line.matchFirst(heading_match_rgx["h_C"])) { +        line = "C~ " ~ line; +        debug(headingsfound) { +          writeln(line); +        } +      } +      if (line.matchFirst(heading_match_rgx["h_D"])) { +        line = "D~ " ~ line; +        debug(headingsfound) { +          writeln(line); +        } +      } +      if (line.matchFirst(heading_match_rgx["h_1"])) { +        line = "1~ " ~ line; +        debug(headingsfound) { +          writeln(line); +        } +      } +      if (line.matchFirst(heading_match_rgx["h_2"])) { +        line = "2~ " ~ line; +        debug(headingsfound) { +          writeln(line); +        } +      } +      if (line.matchFirst(heading_match_rgx["h_3"])) { +        line = "3~ " ~ line; +        debug(headingsfound) { +          writeln(line); +        } +      } +      if (line.matchFirst(heading_match_rgx["h_4"])) { +        line = "4~ " ~ line; +        debug(headingsfound) { +          writeln(line); +        } +      } +    } +    return line; +  } +  auto _heading_matched_(L,C,O,K,Lv,Lc,T,CMM)( +               L   line, +    return ref C   line_occur, +    return ref O   an_object, +    return ref K   an_object_key, +    return ref Lv  lv, +    return ref Lc  collapsed_lev, +    return ref T   obj_type_status, +    return ref CMM conf_make_meta, +  ) { +    debug(asserts) { +      static assert(is(typeof(line)            == char[])); +      static assert(is(typeof(line_occur)      == int[string])); +      static assert(is(typeof(an_object)       == string[string])); +      static assert(is(typeof(an_object_key)   == string)); +      static assert(is(typeof(lv)              == int[string])); +      static assert(is(typeof(collapsed_lev)   == int[string])); +      static assert(is(typeof(obj_type_status) == int[string])); +    } +    static auto rgx = Rgx(); +    if (auto m = line.match(rgx.heading)) { +      /+ heading match +/ +      ++line_occur["heading"]; +      obj_type_status["heading"]            = State.on; +      obj_type_status["para"]               = State.off; +      if (line.match(rgx.heading_seg_and_above)) { +        obj_type_status["biblio_section"]   = State.off; +        obj_type_status["glossary_section"] = State.off; +        obj_type_status["blurb_section"]    = State.off; +      } +      an_object[an_object_key] ~= line ~= "\n"; +      an_object["lev"] ~= m.captures[1]; +      assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels +      switch (an_object["lev"]) { +      case "A":                                // Title set +        an_object[an_object_key]=(an_object[an_object_key]) +          .replaceFirst(rgx.variable_doc_title, +            (conf_make_meta.meta.title_full ~ ",")) +          .replaceFirst(rgx.variable_doc_author, +            conf_make_meta.meta.creator_author); +        collapsed_lev["h0"] = 0; +        an_object["lev_collapsed_number"] +          = collapsed_lev["h0"].to!string; +        lv["lv"] = DocStructMarkupHeading.h_sect_A; +        ++lv["h0"]; +        lv["h1"] = State.off; +        lv["h2"] = State.off; +        lv["h3"] = State.off; +        lv["h4"] = State.off; +        lv["h5"] = State.off; +        lv["h6"] = State.off; +        lv["h7"] = State.off; +        goto default; +      case "B": +        collapsed_lev["h1"] = collapsed_lev["h0"] + 1; +        an_object["lev_collapsed_number"] +          = collapsed_lev["h1"].to!string; +        lv["lv"] = DocStructMarkupHeading.h_sect_B; +        ++lv["h1"]; +        lv["h2"] = State.off; +        lv["h3"] = State.off; +        lv["h4"] = State.off; +        lv["h5"] = State.off; +        lv["h6"] = State.off; +        lv["h7"] = State.off; +        goto default; +      case "C": +        collapsed_lev["h2"] = collapsed_lev["h1"] + 1; +        an_object["lev_collapsed_number"] +          = collapsed_lev["h2"].to!string; +        lv["lv"] = DocStructMarkupHeading.h_sect_C; +        ++lv["h2"]; +        lv["h3"] = State.off; +        lv["h4"] = State.off; +        lv["h5"] = State.off; +        lv["h6"] = State.off; +        lv["h7"] = State.off; +        goto default; +      case "D": +        collapsed_lev["h3"] = collapsed_lev["h2"] + 1; +        an_object["lev_collapsed_number"] +          = collapsed_lev["h3"].to!string; +        lv["lv"] = DocStructMarkupHeading.h_sect_D; +        ++lv["h3"]; +        lv["h4"] = State.off; +        lv["h5"] = State.off; +        lv["h6"] = State.off; +        lv["h7"] = State.off; +        goto default; +      case "1": +        if (lv["h3"] > State.off) { +          collapsed_lev["h4"] = collapsed_lev["h3"] + 1; +        } else if (lv["h2"] > State.off) { +          collapsed_lev["h4"] = collapsed_lev["h2"] + 1; +        } else if (lv["h1"] > State.off) { +          collapsed_lev["h4"] = collapsed_lev["h1"] + 1; +        } else if (lv["h0"] > State.off) { +          collapsed_lev["h4"] = collapsed_lev["h0"] + 1; +        } +        an_object["lev_collapsed_number"] +          = collapsed_lev["h4"].to!string; +        lv["lv"] = DocStructMarkupHeading.h_text_1; +        ++lv["h4"]; +        lv["h5"] = State.off; +        lv["h6"] = State.off; +        lv["h7"] = State.off; +        goto default; +      case "2": +        if (lv["h5"] > State.off) { +          an_object["lev_collapsed_number"] +            = collapsed_lev["h5"].to!string; +        } else if (lv["h4"] > State.off) { +          collapsed_lev["h5"] = collapsed_lev["h4"] + 1; +          an_object["lev_collapsed_number"] +            = collapsed_lev["h5"].to!string; +        } +        lv["lv"] = DocStructMarkupHeading.h_text_2; +        ++lv["h5"]; +        lv["h6"] = State.off; +        lv["h7"] = State.off; +        goto default; +      case "3": +        if (lv["h6"] > State.off) { +          an_object["lev_collapsed_number"] +            = collapsed_lev["h6"].to!string; +        } else if (lv["h5"] > State.off) { +          collapsed_lev["h6"] = collapsed_lev["h5"] + 1; +          an_object["lev_collapsed_number"] +            = collapsed_lev["h6"].to!string; +        } +        lv["lv"] = DocStructMarkupHeading.h_text_3; +        ++lv["h6"]; +        lv["h7"] = State.off; +        goto default; +      case "4": +        if (lv["h7"] > State.off) { +          an_object["lev_collapsed_number"] +            = collapsed_lev["h7"].to!string; +        } else if (lv["h6"] > State.off) { +          collapsed_lev["h7"] = collapsed_lev["h6"] + 1; +          an_object["lev_collapsed_number"] +            = collapsed_lev["h7"].to!string; +        } +        lv["lv"] = DocStructMarkupHeading.h_text_4; +        ++lv["h7"]; +        goto default; +      default: +        an_object["lev_markup_number"] = lv["lv"].to!string; +      } +      debug(heading) { +        writeln(line.strip); +      } +    } +  } +  void _para_match_(L,O,K,I,B,T,C)( +               L  line, +    return ref O  an_object, +    return ref K  an_object_key, +    return ref I  indent, +    return ref B  bullet, +    return ref T  obj_type_status, +    return ref C  line_occur, +  ) { +    debug(asserts) { +      static assert(is(typeof(line)            == char[])); +      static assert(is(typeof(an_object)       == string[string])); +      static assert(is(typeof(an_object_key)   == string)); +      static assert(is(typeof(indent)          == int[string])); +      static assert(is(typeof(bullet)          == bool)); +      static assert(is(typeof(obj_type_status) == int[string])); +      static assert(is(typeof(line_occur)      == int[string])); +    } +    static auto rgx = Rgx(); +    if (line_occur["para"] == State.off) { +      line = font_faces_line(line); +      /+ para matches +/ +      obj_type_status["para"] = State.on; +      an_object[an_object_key] ~= line; +      indent=[ +        "hang_position" : 0, +        "base_position" : 0, +      ]; +      bullet = false; +      if (auto m = line.matchFirst(rgx.para_indent)) { +        debug(paraindent) { +          writeln(line); +        } +        indent["hang_position"] = (m.captures[1]).to!int; +        indent["base_position"] = 0; +      } else if (line.matchFirst(rgx.para_bullet)) { +        debug(parabullet) { +          writeln(line); +        } +        bullet = true; +      } else if (auto m = line.matchFirst(rgx.para_indent_hang)) { +        debug(paraindenthang) { +          writeln(line); +        } +        indent=[ +          "hang_position" : (m.captures[1]).to!int, +          "base_position" : (m.captures[2]).to!int, +        ]; +      } else if (auto m = line.matchFirst(rgx.para_bullet_indent)) { +        debug(parabulletindent) { +          writeln(line); +        } +        indent=[ +          "hang_position" : (m.captures[1]).to!int, +          "base_position" : 0, +        ]; +        bullet = true; +      } +      ++line_occur["para"]; +    } +  } +  auto font_faces_line(T)( +    T  textline, +  ) { +    static auto rgx = Rgx(); +    if (textline.match(rgx.inline_faces_line)) { +      textline = (textline) +        .replaceFirst(rgx.inline_emphasis_line,   ("*{$1}*$2")) +        .replaceFirst(rgx.inline_bold_line,       ("!{$1}!$2")) +        .replaceFirst(rgx.inline_underscore_line, ("_{$1}_$2")) +        .replaceFirst(rgx.inline_italics_line,    ("/{$1}/$2")); +    } +    return textline; +  } +  auto table_instructions(O,H)( +    return ref O  table_object, +    return ref H  table_head, +  ) { +    static auto rgx = Rgx(); +    table_object.metainfo.is_of_part      = "body"; +    table_object.metainfo.is_of_section   = "body"; +    table_object.metainfo.is_of_type      = "block"; +    table_object.metainfo.is_a            = "table"; +    table_object.has.inline_notes_reg     = false; +    table_object.has.inline_notes_star    = false; +    table_object.has.inline_links         = false; +    if (auto m = table_head.matchFirst(rgx.table_head_instructions)) { +      table_object.table.heading = ((m["c_heading"].length > 0) && (m["c_heading"] == "h")) ? true : false; +      table_object.table.number_of_columns = ((m["c_num"].length > 0) && (m["c_num"].to!int > 0)) ? m["c_num"].to!int : 0; // double check, may be obsolete +      foreach (cw; m["c_widths"].matchAll(rgx.table_col_widths)) { +        auto x = cw.hit.matchFirst(rgx.table_col_widths_and_alignment); +        table_object.table.column_widths ~= x["width"].to!int; +        table_object.table.column_aligns ~= (x["align"].empty) ? "" : x["align"]; +      } +    } +    return table_object; +  } +  auto table_array_munge(O,T)( +    return ref O  table_object, +    return ref T  table_array, +  ) { +    static auto rgx = Rgx(); +    static auto mng = InlineMarkup(); +    string _table_substantive; +    ulong col_num; +    ulong col_num_; +    ulong col_num_chk = 0; +    foreach(idx_r, row; table_array) { +      debug(table_dev) { +        writeln("row ", idx_r); +      } +      col_num_ = 0; +      if (col_num == 0 +      || col_num < row.length) { +        col_num = row.length; +      } +      if (col_num_chk == 0) { +        col_num_chk = col_num; +      } else if (col_num == 1) { +        debug(table_dev) { +          writeln("table note: "); +        } +      } else if (col_num_chk != col_num) { +        debug(table_dev) { +          writeln("warning irregular number of columns: ", col_num_chk, " != ", col_num); +        } +      } else { +      } +      foreach(idx_c, col; row) { +        debug(table_dev) { +          write(idx_c, ", "); +        } +        col_num_ = idx_c; +        _table_substantive ~= col ~ mng.tc_s; +        if (idx_r == 0 && comp_obj_block.table.heading) { +        } else if (col.match(rgx.numeric_col) && idx_r == 1) { // conditions reversed to avoid: gdc compiled program run segfault +          if ((comp_obj_block.table.column_aligns.length > idx_c) +          && (comp_obj_block.table.column_aligns[idx_c].matchFirst(rgx.table_col_align_match))) { +            comp_obj_block.table.column_aligns[idx_c] +              = comp_obj_block.table.column_aligns[idx_c]; +          } else if (comp_obj_block.table.column_aligns.length > idx_c) { +            comp_obj_block.table.column_aligns[idx_c] = "r"; +          } else { +            comp_obj_block.table.column_aligns ~= "r"; +          } +        } else if (idx_r == 1) { +          if ((comp_obj_block.table.column_aligns.length > idx_c) +          && (comp_obj_block.table.column_aligns[idx_c].matchFirst(rgx.table_col_align_match))) { +            comp_obj_block.table.column_aligns[idx_c] +              = comp_obj_block.table.column_aligns[idx_c]; +          } else if (comp_obj_block.table.column_aligns.length > idx_c) { +            comp_obj_block.table.column_aligns[idx_c] = "l"; +          } else { +            comp_obj_block.table.column_aligns ~= "l"; +          } +        } +      } +      debug(table_dev) { +        writeln(""); +      } +      if (col_num_chk > 0 && (col_num != col_num_chk)) { +      } else if (col_num == col_num_chk){ +      } else { +        col_num_chk = col_num; +      } +      _table_substantive = _table_substantive.replaceFirst(rgx.table_col_separator_nl, "\n"); +    } +    if (comp_obj_block.table.number_of_columns != col_num) { +      if (comp_obj_block.table.number_of_columns == 0) { +        comp_obj_block.table.number_of_columns = (col_num).to!int; +      } else { +        debug(table_dev) { +          writeln(comp_obj_block.table.number_of_columns, " != ", col_num); +        } +      } +    } +    if (table_object.table.number_of_columns == 0 +    && table_object.table.column_widths.length > 0) { +        writeln(__LINE__, " ERROR"); +    } +    if (table_object.table.number_of_columns > 0 +    && table_object.table.column_widths.length == 0) { +      double col_w = (100.00 / table_object.table.number_of_columns); +      foreach (i; 0..table_object.table.number_of_columns) { +        table_object.table.column_widths ~= col_w; +      } +    } else if (table_object.table.number_of_columns +    != table_object.table.column_widths.length) { +      debug(table_dev) { +        writeln(m.hit); // further logic required +      } +      if (table_object.table.number_of_columns > table_object.table.column_widths.length) { +        double col_w = (100.00 - (table_object.table.column_widths).sum) +          / (table_object.table.number_of_columns - table_object.table.column_widths.length); +        foreach (i; 0..table_object.table.column_widths.length) { +          table_object.table.column_widths ~= col_w; +        } +        foreach (i; 0..(table_object.table.number_of_columns - table_object.table.column_widths.length)) { +          table_object.table.column_widths ~= col_w; +        } +      } else if (table_object.table.number_of_columns < table_object.table.column_widths.length) { +        writeln(__LINE__, " warning, ERROR"); +      } +    } +    if (table_object.table.column_widths.sum > 101 +    || table_object.table.column_widths.sum < 95 ) { +      writeln("sum: ", table_object.table.column_widths.sum, +        ", array: ", table_object.table.column_widths, +        ", cols: ", table_object.table.number_of_columns); +      writeln(_table_substantive); +    } +    debug(table_res) { +      writeln("aligns: ", comp_obj_block.table.column_aligns, "\n", +        "no. of columns: ", comp_obj_block.table.number_of_columns, "\n", +        "col widths: ", comp_obj_block.table.column_widths, +          " sum: ", comp_obj_block.table.column_widths.sum, "\n", +        _table_substantive); +    } +    comp_obj_block.text = _table_substantive; +    return table_object; +  } +  auto table_array_munge_open_close(O,T)( +    return ref O  table_object, +    return ref T  table_array, +  ) { +    static auto rgx = Rgx(); +    static auto mng = InlineMarkup(); +    string _table_substantive; +    foreach(row; table_array) { +      foreach(col; row) { +        _table_substantive ~= mng.tc_o ~ col ~ mng.tc_c; +      } +      _table_substantive ~= "\n"; +    } +    debug(table_dev) { +      writeln(_table_substantive); +    } +    comp_obj_block.text = _table_substantive; +    return table_object; +  } +  auto table_substantive_munge(O,T)( +    return ref O  table_object, +    return ref T  table_substantive, +  ) { +    static auto rgx = Rgx(); +    static auto munge = ObjInlineMarkupMunge(); +    string[] _table_rows = (table_substantive).split(rgx.table_row_delimiter); +    string[] _table_cols; +    string[][] _table; +    foreach(col; _table_rows) { +      _table_cols = col.split(rgx.table_col_delimiter); +      _table ~= _table_cols; +    } +    table_object = table_array_munge(table_object, _table); +    return table_object; +  } +  auto table_substantive_munge_special(O,T)( +    return ref O  table_object, +    return ref T  table_substantive, +  ) { +    static auto rgx = Rgx(); +    static auto munge = ObjInlineMarkupMunge(); +    string[] _table_rows = (table_substantive).split(rgx.table_row_delimiter_special); +    string[] _table_cols; +    string[][] _table; +    foreach(col; _table_rows) { +      _table_cols = col.split(rgx.table_col_delimiter_special); +      _table ~= _table_cols; +    } +    table_object = table_array_munge(table_object, _table); +    return table_object; +  } +  /+ abstraction functions ↑ +/ +  /+ ↓ abstraction function emitters +/ +  pure struct OCNemitter { +    int ocn_, ocn_on, ocn_on_, ocn_off, ocn_off_, ocn_bkidx, ocn_bkidx_; +    auto ocn_emitter(int ocn_status_flag) { +      OCNset ocn; +      assert(ocn_status_flag <= OCNstatus.reset); +      ocn_on = ocn_off = ocn_bkidx = 0; +      switch(ocn_status_flag) { +      case OCNstatus.reset: +        ocn_ = ocn_on_ = ocn_off_ = 1; +        ocn_bkidx_ = 0; +        break; +      case OCNstatus.on: +        ocn_ = ocn_on = ++ocn_on_; +        break; +      case OCNstatus.off: +        ocn_ = ocn_off = ++ocn_off_; +        break; +      case OCNstatus.bkidx: +        ocn_ = ocn_bkidx = ++ocn_bkidx_; +        break; +      case OCNstatus.closing: +        break; +      default: +        ocn_ = 0; +      } +      assert(ocn_ >= 0); +      ocn.digit = ocn_; +      ocn.on    = ocn_on; +      ocn.off   = ocn_off; +      ocn.bkidx = ocn_bkidx; +      ocn.type  = ocn_status_flag; +      return ocn; +    } +    invariant() { +    } +  } +  /+ +/ +  static struct ObjInlineMarkupMunge { +    string[string] obj_txt; +    int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus; +    string asterisks_, plus_; +    string obj_txt_out, tail, note; +    static auto rgx = Rgx(); +    static auto mkup = InlineMarkup(); +    int stage_reset_note_numbers = true; +    private auto initialize_note_numbers() { +      n_foot = 0; +      n_foot_reg = 0; +      n_foot_sp_asterisk = 0; +      n_foot_sp_plus = 0; +    } +    static auto url_links(Ot)(Ot obj_txt_in) { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +      static auto mng = InlineMarkup(); +      obj_txt_in = obj_txt_in.replaceAll(rgx.inline_mono, (mng.mono ~ "{$1}" ~ mng.mono)); +      /+ url matched +/ +      obj_txt_in = obj_txt_in.replaceAll(rgx.inline_notes_al_special, ""); // TODO reinstate when special footnotes are implemented +      if (obj_txt_in.match(rgx.smid_inline_url_generic)) { +        /+ link: naked url: http://url +/ +        if (obj_txt_in.match(rgx.smid_inline_link_naked_url)) { +          obj_txt_in = (obj_txt_in).replaceAll( +              rgx.smid_inline_link_naked_url, +              ("$1" +                ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c +                ~  mkup.url_o ~ "$2" ~  mkup.url_c +                ~ "$3")            // ("$1{ $2 }$2$3") +            ); +        } +        /+ link with helper for endnote including the url: +             {~^ link which includes url as footnote }http://url +           maps to: +             { link which includes url as footnote }http://url~{ { http://url }http://url }~ +        +/ +        if (obj_txt_in.match(rgx.smid_inline_link_endnote_url_helper)) { +          obj_txt_in = (obj_txt_in) +            .replaceAll( +              rgx.smid_inline_link_endnote_url_helper_punctuated, +              (mkup.lnk_o ~ "$1" ~ mkup.lnk_c +                ~ mkup.url_o ~ "$2" ~ mkup.url_c +                ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c +                ~ mkup.url_o ~ "$2" ~ mkup.url_c +                ~  " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3") +            ) +            .replaceAll( +              rgx.smid_inline_link_endnote_url_helper, +              (mkup.lnk_o ~ "$1" ~ mkup.lnk_c +                ~ mkup.url_o ~ "$2" ~ mkup.url_c +                ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c +                ~ mkup.url_o ~ "$2" ~ mkup.url_c +                ~  " }~") // ("{ $1 }$2~{ { $2 }$2 }~") +            ); +        } +        /+ link with regular markup: +           { linked text or image }http://url +        +/ +        if (obj_txt_in.match(rgx.smid_inline_link_markup_regular)) { +          obj_txt_in = (obj_txt_in).replaceAll( +            rgx.smid_inline_link_markup_regular, +            ("$1" +              ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c +              ~  mkup.url_o ~ "$3" ~  mkup.url_c +              ~ "$4")            // ("$1{ $2 }$3$4") +          ); +        } +      } +      obj_txt_in = obj_txt_in.replaceAll(rgx.inline_mono_box, ("#{$1}#")); +      return obj_txt_in; +    } +    static auto images(Ot)(Ot obj_txt_in) { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +      static auto mng = InlineMarkup(); +      obj_txt_in = obj_txt_in.replaceAll(rgx.inline_mono, (mng.mono ~ "{$1}" ~ mng.mono)); // figure +      /+ url matched +/ +      obj_txt_in = obj_txt_in.replaceAll(rgx.inline_notes_al_special, ""); // TODO reinstate when special footnotes are implemented +      if (obj_txt_in.match(rgx.smid_image_generic)) { /+ images with and without links +/ +        debug(images) { +          writeln("Image: ", obj_txt_in); +        } +        if (obj_txt_in.match(rgx.smid_image_with_dimensions)) { +          obj_txt_in = (obj_txt_in).replaceAll( +              rgx.smid_image_with_dimensions, +              ("$1" +                ~ mkup.img ~ "$2,w$3h$4 " +                ~ "$5")            // ("$1{ $2 }$2$3") +            ); +          debug(images) { +            writeln("IMAGE with size: ", obj_txt_in); // decide on representation +          } +        } else if (obj_txt_in.match(rgx.smid_image)) { +          obj_txt_in = (obj_txt_in).replaceAll( +              rgx.smid_image, +              ("$1" +                ~ mkup.img ~ "$2,w0h0 " +                ~ "$3")            // ("$1{ $2 }$2$3") +            ); +          debug(images) { +            writeln("IMAGE: ", obj_txt_in); // decide on representation +          } +        } +      } +      obj_txt_in = obj_txt_in.replaceAll(rgx.inline_mono_box, ("#{$1}#")); // figure +      return obj_txt_in; +    } +    auto footnotes_endnotes_markup_and_number_or_stars(Ot)(Ot obj_txt_in, bool reset_note_numbers) { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +      /+ endnotes (regular) +/ +      bool flg_notes_reg  = false; +      bool flg_notes_star = false; +      bool flg_notes_plus = false; +      obj_txt_in = (obj_txt_in).replaceAll( +        rgx.inline_notes_curly, +        (mkup.en_a_o ~ " $1" ~ mkup.en_a_c) +      ); +      if (!(stage_reset_note_numbers) && reset_note_numbers) { +        stage_reset_note_numbers = true; +      } +      if (obj_txt_in.match(rgx.inline_notes_al_gen)) { +        if (auto m = obj_txt_in.matchAll(rgx.inline_text_and_note_al_)) { +          if (stage_reset_note_numbers) { +            n_foot = 0; +            n_foot_reg = 0; +            n_foot_sp_asterisk = 0; +            n_foot_sp_plus = 0; +          } +          stage_reset_note_numbers = false; +          foreach(n; m) { +            if (n.hit.to!string.match(rgx.inline_al_delimiter_open_symbol_star)) { +              flg_notes_star =  true; +              ++n_foot_sp_asterisk; +              asterisks_ = "*"; +              n_foot=n_foot_sp_asterisk; +              obj_txt_out ~= n.hit.to!string.replaceFirst( +                rgx.inline_al_delimiter_open_symbol_star, +                (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ") +              ) ~ "\n"; +            } else if (n.hit.to!string.match(rgx.inline_al_delimiter_open_symbol_plus)) { +              flg_notes_plus =  true; +              ++n_foot_sp_plus; +              plus_ = "*"; +              n_foot=n_foot_sp_plus; +              obj_txt_out ~= n.hit.to!string.replaceFirst( +                rgx.inline_al_delimiter_open_symbol_plus, +                (mkup.en_a_o ~ replicate(plus_, n_foot_sp_plus) ~ " ") +              ) ~ "\n"; +            } else if (n.hit.to!string.match(rgx.inline_al_delimiter_open_regular)) { +              flg_notes_reg =  true; +              ++n_foot_reg; +              n_foot=n_foot_reg; +              obj_txt_out ~= n.hit.to!string.replaceFirst( +                rgx.inline_al_delimiter_open_regular, +                (mkup.en_a_o ~ to!string(n_foot) ~ " ") +              ) ~ "\n"; +            } else { +              obj_txt_out ~= n.hit.to!string ~ "\n"; +            } +          } +        } +      } else { +        obj_txt_out = obj_txt_in; +      } +      auto t = tuple( +        obj_txt_out, +        flg_notes_reg, +        flg_notes_star, +        flg_notes_plus, +      ); +      return t; +    } +    private auto object_notes_and_links_(Ot)(Ot obj_txt_in, bool reset_note_numbers=false) +    in { +      debug(asserts) { +        assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      obj_txt_out = ""; +      bool urls = false; +      bool images_without_dimensions = false; +      tail = ""; +      /+ special endnotes +/ +      obj_txt_in = obj_txt_in.replaceAll( +        rgx.inline_notes_curly_sp_asterisk, +        (mkup.en_a_o ~ "*" ~ " $1" ~ mkup.en_a_c) +      ); +      obj_txt_in +        = obj_txt_in.replaceAll( +          rgx.inline_notes_curly_sp_plus, +          (mkup.en_a_o ~ "+" ~ " $1" ~ mkup.en_a_c) +        ); +      /+ image matched +/ +      if (obj_txt_in.match(rgx.smid_image_generic)) { +        obj_txt_in = images(obj_txt_in); +        if (obj_txt_in.match(rgx.smid_mod_image_without_dimensions)) { +          images_without_dimensions = true; +        } +      } +      /+ url matched +/ +      if (obj_txt_in.match(rgx.smid_inline_url)) { +        urls = true; +        obj_txt_in = url_links(obj_txt_in); +      } +      auto ftn = footnotes_endnotes_markup_and_number_or_stars(obj_txt_in, reset_note_numbers); +      obj_txt_out = ftn[0]; +      debug(footnotes) { +        writeln(obj_txt_out, tail); +      } +      obj_txt_out = obj_txt_out ~ tail; +      debug(footnotesdone) { +        foreach(m; matchAll(obj_txt_out, +        (mkup.en_a_o ~ `\s*(.+?)` ~ mkup.en_a_c))) { +          writeln(m.captures[1]); +          writeln(m.hit); +        } +      } +      auto t = tuple( +        obj_txt_out, +        ftn[1], +        ftn[2], +        ftn[3], +        urls, +        images_without_dimensions, +      ); +      return t; +    } +    auto init() +    in { } +    body { +      auto t = object_notes_and_links_(""); +      return t; +    } +    invariant() { +    } +    auto munge_heading(Ot)(Ot obj_txt_in, bool reset_note_numbers=false) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      obj_txt["munge"]=(obj_txt_in) +       .replaceFirst(rgx.heading, "") +       .replaceFirst(rgx.object_number_off_all, "") +       .strip; +      auto t = object_notes_and_links_(obj_txt["munge"], reset_note_numbers); +      debug(munge) { +        writeln(__LINE__); +        writeln(obj_txt_in); +        writeln(__LINE__); +        writeln(obj_txt["munge"].to!string); +      } +      return t; +    } +    invariant() { +    } +    auto munge_para(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      obj_txt["munge"]=(obj_txt_in) +        .replaceFirst(rgx.para_attribs, "") +        .replaceFirst(rgx.object_number_off_all, ""); +      auto t = object_notes_and_links_(obj_txt["munge"]); +      debug(munge) { +        writeln(__LINE__); +        writeln(obj_txt_in); +        writeln(__LINE__); +        writeln(obj_txt["munge"].to!string); +      } +      return t; +    } +    string munge_quote(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      obj_txt["munge"]=obj_txt_in; +      return obj_txt["munge"]; +    } +    invariant() { +    } +    auto munge_group(string obj_txt_in) +    in { } +    body { +      obj_txt["munge"]=obj_txt_in; +      auto t = object_notes_and_links_(obj_txt["munge"]); +      return t; +    } +    invariant() { +    } +    auto munge_block(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      obj_txt["munge"]=obj_txt_in; +      auto t = object_notes_and_links_(obj_txt["munge"]); +      return t; +    } +    invariant() { +    } +    auto munge_verse(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      obj_txt["munge"]=obj_txt_in; +      auto t = object_notes_and_links_(obj_txt["munge"]); +      return t; +    } +    invariant() { +    } +    string munge_code(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      obj_txt_in = (obj_txt_in).replaceAll(rgx.space, mkup.nbsp); +      obj_txt["munge"] = obj_txt_in; +      return obj_txt["munge"]; +    } +    invariant() { +    } +    string munge_table(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      obj_txt["munge"]=obj_txt_in; +      return obj_txt["munge"]; +    } +    invariant() { +    } +    string munge_comment(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      obj_txt["munge"]=obj_txt_in; +      return obj_txt["munge"]; +    } +    invariant() { +    } +  } +  static struct ObjInlineMarkup { +    static auto rgx = Rgx(); +    static auto munge = ObjInlineMarkupMunge(); +    string[string] obj_txt; +    static string[] anchor_tags_ = []; +    static string anchor_tag = ""; +    auto obj_inline_markup_and_anchor_tags_and_misc(O,K,CMM)( +      O   obj_, +      K   obj_key_, +      CMM conf_make_meta, +      bool _new_doc +    ) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_)            == string[string])); +        static assert(is(typeof(obj_key_)        == string)); +      } +    } +    body { +      obj_txt["munge"] = obj_[obj_key_].dup; +      obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`))) +      ? obj_txt["munge"] +      : obj_txt["munge"].strip; +      if (_new_doc) { +        anchor_tags_ = []; +      } +      auto x = munge.init; +      bool[string] obj_notes_and_links; +      obj_notes_and_links["notes_reg"]           = false; +      obj_notes_and_links["notes_star"]          = false; +      obj_notes_and_links["links"]               = false; +      obj_notes_and_links["image_no_dimensions"] = false; +      switch (obj_["is"]) { +      case "heading": +        if (_new_doc) { +          anchor_tag = ""; +        } +        obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, conf_make_meta, _new_doc); +        obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"], _new_doc); +        if (auto m = obj_txt["munge"].match(rgx.heading_anchor_tag)) { +          anchor_tag = m.captures[1]; +          anchor_tags_ ~= anchor_tag; +        } else if (obj_["lev"] == "1") { +          writeln("heading anchor tag missing: ", obj_txt["munge"]); +        } +        x = munge.munge_heading(obj_txt["munge"], reset_note_numbers); +        reset_note_numbers=false; +        goto default; +      case "para": +        x = munge.munge_para(obj_txt["munge"]); +        goto default; +      case "group": +        x = munge.munge_group(obj_txt["munge"]); +        goto default; +      case "block": +        x = munge.munge_block(obj_txt["munge"]); +        goto default; +      case "verse": +        x = munge.munge_verse(obj_txt["munge"]); +        goto default; +      case "code": +        obj_txt["munge"] = munge.munge_code(obj_txt["munge"]); +        break; +      case "table": +        obj_txt["munge"] = munge.munge_table(obj_txt["munge"]); +        break; +      case "quote": +        obj_txt["munge"] = munge.munge_quote(obj_txt["munge"]); +        break; +      case "comment": +        obj_txt["munge"] = munge.munge_comment(obj_txt["munge"]); +        break; +      case "doc_end_reset": +        munge.initialize_note_numbers(); +        break; +      default: +        /+ para, heading, group, block, verse +/ +        obj_txt["munge"]                  = x[0]; +        obj_notes_and_links["notes_reg"]  = x[1]; +        obj_notes_and_links["notes_star"] = x[2]; +        obj_notes_and_links["notes_plus"] = x[3]; +        obj_notes_and_links["links"]      = x[4]; +        obj_notes_and_links["image_no_dimensions"] = x[5]; +        break; +      } +      auto t = tuple( +        obj_txt["munge"], +        anchor_tags_, +        obj_notes_and_links["notes_reg"], +        obj_notes_and_links["notes_star"], +        obj_notes_and_links["links"], +        obj_notes_and_links["image_no_dimensions"], +      ); +      anchor_tags_=[]; +      return t; +    } +    invariant() { +    } +    auto _clean_heading_toc_(Toc)( +      Toc heading_toc_, +    ) { +     debug(asserts) { +       static assert(is(typeof(heading_toc_) == char[])); +     } +     auto m = (cast(char[]) heading_toc_).matchFirst(rgx.heading); +     heading_toc_ = (m.post).replaceAll( +       rgx.inline_notes_curly_gen, +       ""); +     return heading_toc_; +    }; +    auto table_of_contents_gather_headings(O,CMM,Ts,Ta,X,Toc)( +      O            obj_, +      CMM          conf_make_meta, +      Ts           segment_anchor_tag_that_object_belongs_to, +      Ta           _anchor_tag, +      return ref X lev4_subtoc, +      Toc          the_table_of_contents_section, +    ) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_)                                      == string[string])); +        static assert(is(typeof(segment_anchor_tag_that_object_belongs_to) == string)); +        static assert(is(typeof(_anchor_tag)                               == string)); +        static assert(is(typeof(lev4_subtoc)                               == string[][string])); +        static assert(is(typeof(the_table_of_contents_section)             == ObjGenericComposite[][string])); +      } +    } +    body { +      ObjGenericComposite comp_obj_toc; +      mixin InternalMarkup; +      static auto mkup = InlineMarkup(); +      char[] heading_toc_ = (obj_["substantive"].dup.strip.to!(char[])).replaceAll(rgx.inline_notes_al, ""); +      heading_toc_ = _clean_heading_toc_(heading_toc_); +      auto attrib=""; +      string toc_txt_, subtoc_txt_; +      int[string] indent; +      if (obj_["lev_markup_number"].to!int > 0) { +        indent=[ +          "hang_position" : obj_["lev_markup_number"].to!int, +          "base_position" : obj_["lev_markup_number"].to!int, +        ]; +        toc_txt_ = format( +          "{ %s }#%s", +          heading_toc_, +          _anchor_tag, +        ); +        toc_txt_= munge.url_links(toc_txt_); +        comp_obj_toc                             = comp_obj_toc.init; +        comp_obj_toc.metainfo.is_of_part         = "frontmatter"; +        comp_obj_toc.metainfo.is_of_section      = "toc"; +        comp_obj_toc.metainfo.is_of_type         = "para"; +        comp_obj_toc.metainfo.is_a               = "toc"; +        comp_obj_toc.metainfo.ocn                = 0; +        comp_obj_toc.metainfo.object_number_off  = ""; +        comp_obj_toc.metainfo.object_number_type = 0; +        comp_obj_toc.attrib.indent_hang          = indent["hang_position"]; +        comp_obj_toc.attrib.indent_base          = indent["base_position"]; +        comp_obj_toc.attrib.bullet               = false; +        comp_obj_toc.text                        = toc_txt_.to!string.strip; +        comp_obj_toc.has.inline_links            = true; +        the_table_of_contents_section["scroll"]  ~= comp_obj_toc; +      } else { +        indent=[ +          "hang_position" : 0, +          "base_position" : 0, +        ]; +        comp_obj_toc                             = comp_obj_toc.init; +        comp_obj_toc.metainfo.is_of_part         = "frontmatter"; +        comp_obj_toc.metainfo.is_of_section      = "toc"; +        comp_obj_toc.metainfo.is_of_type         = "para"; +        comp_obj_toc.metainfo.is_a               = "toc"; +        comp_obj_toc.metainfo.ocn                = 0; +        comp_obj_toc.metainfo.object_number_off  = ""; +        comp_obj_toc.metainfo.object_number_type = 0; +        comp_obj_toc.attrib.indent_hang          = indent["hang_position"]; +        comp_obj_toc.attrib.indent_base          = indent["base_position"]; +        comp_obj_toc.attrib.bullet               = false; +        comp_obj_toc.text                        = "Table of Contents"; +        comp_obj_toc.has.inline_links            = true; +        the_table_of_contents_section["scroll"]  ~= comp_obj_toc; +      } +      comp_obj_toc                               = comp_obj_toc.init; +      comp_obj_toc.metainfo.is_of_part           = "frontmatter"; +      comp_obj_toc.metainfo.is_of_section        = "toc"; +      comp_obj_toc.metainfo.is_of_type           = "para"; +      comp_obj_toc.metainfo.is_a                 = "toc"; +      comp_obj_toc.metainfo.ocn                  = 0; +      comp_obj_toc.metainfo.object_number_off    = ""; +      comp_obj_toc.metainfo.object_number_type   = 0; +      comp_obj_toc.attrib.bullet                 = false; +      comp_obj_toc.has.inline_links              = true; +      switch (obj_["lev_markup_number"].to!int) { +      case 0: +        indent=[ +          "hang_position" : 0, +          "base_position" : 0, +        ]; +        toc_txt_ = "{ Table of Contents }" ~ mkup.mark_internal_site_lnk ~ "toc.fnSuffix"; +        toc_txt_= munge.url_links(toc_txt_); +        comp_obj_toc.attrib.indent_hang          = indent["hang_position"]; +        comp_obj_toc.attrib.indent_base          = indent["base_position"]; +        comp_obj_toc.text                        = toc_txt_.to!string.strip; +        comp_obj_toc.has.inline_links            = true; +        the_table_of_contents_section["seg"]     ~= comp_obj_toc; +        break; +      case 1: .. case 3: +        indent=[ +          "hang_position" : obj_["lev_markup_number"].to!int, +          "base_position" : obj_["lev_markup_number"].to!int, +        ]; +        toc_txt_ = format( +          "%s", +          heading_toc_, +        ); +        toc_txt_= munge.url_links(toc_txt_); +        comp_obj_toc.attrib.indent_hang          = indent["hang_position"]; +        comp_obj_toc.attrib.indent_base          = indent["base_position"]; +        comp_obj_toc.text                        = toc_txt_.to!string.strip; +        comp_obj_toc.has.inline_links            = true; +        the_table_of_contents_section["seg"]     ~= comp_obj_toc; +        break; +      case 4: +        toc_txt_ = format( +          "{ %s }%s%s%s", +          heading_toc_, +          mkup.mark_internal_site_lnk, +          segment_anchor_tag_that_object_belongs_to, +          ".fnSuffix", +        ); +        lev4_subtoc[segment_anchor_tag_that_object_belongs_to] = []; +        toc_txt_= munge.url_links(toc_txt_); +        indent=[ +          "hang_position" : obj_["lev_markup_number"].to!int, +          "base_position" : obj_["lev_markup_number"].to!int, +        ]; +        comp_obj_toc.attrib.indent_hang          = indent["hang_position"]; +        comp_obj_toc.attrib.indent_base          = indent["base_position"]; +        comp_obj_toc.text                        = toc_txt_.to!string.strip; +        comp_obj_toc.has.inline_links            = true; +        the_table_of_contents_section["seg"]     ~= comp_obj_toc; +        break; +      case 5: .. case 7: +        toc_txt_ = format( +          "{ %s }%s%s%s#%s", +          heading_toc_, +          mkup.mark_internal_site_lnk, +          segment_anchor_tag_that_object_belongs_to, +          ".fnSuffix", +          _anchor_tag, +        ); +        subtoc_txt_ = format( +          "{ %s }#%s", +          heading_toc_, +          _anchor_tag, +        ); +        lev4_subtoc[segment_anchor_tag_that_object_belongs_to] +        ~= munge.url_links(obj_["lev_markup_number"] +             ~ "~ " ~ subtoc_txt_.to!string.strip +           ); +        toc_txt_= munge.url_links(toc_txt_); +        indent=[ +          "hang_position" : obj_["lev_markup_number"].to!int, +          "base_position" : obj_["lev_markup_number"].to!int, +        ]; +        comp_obj_toc.attrib.indent_hang          = indent["hang_position"]; +        comp_obj_toc.attrib.indent_base          = indent["base_position"]; +        comp_obj_toc.text                        = toc_txt_.to!string.strip; +        comp_obj_toc.has.inline_links            = true; +        the_table_of_contents_section["seg"]     ~= comp_obj_toc; +        break; +      default: +        break; +      } +      return the_table_of_contents_section; +    } +    invariant() { +    } +  private: +    static int[] heading_num = [ 0, 0, 0, 0 ]; +    static string heading_number_auto_composite = ""; +    static string _configured_auto_heading_numbering_and_segment_anchor_tags(M,O,CMM)( +      M   munge_, +      O   obj_, +      CMM conf_make_meta, +      bool _new_doc +    ) { +      debug(asserts) { +        static assert(is(typeof(munge_)          == string)); +        static assert(is(typeof(obj_)            == string[string])); +      } +      if (_new_doc) { +        heading_num = [ 0, 0, 0, 0 ]; +        heading_number_auto_composite = ""; +      } +      if (conf_make_meta.make.auto_num_top_lv) { +        if (obj_["lev_markup_number"].to!int == 0) { +          heading_num[0] = 0; +          heading_num[1] = 0; +          heading_num[2] = 0; +          heading_num[3] = 0; +          heading_number_auto_composite = ""; +        } +        /+ auto_num_depth minimum 0 +           (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement +/ +        if ( +          conf_make_meta.make.auto_num_top_lv +          > obj_["lev_markup_number"].to!uint +        ) { +          heading_num[1] = 0; +          heading_num[2] = 0; +          heading_num[3] = 0; +        } else if ( +          conf_make_meta.make.auto_num_top_lv +            == obj_["lev_markup_number"].to!uint +        ) { +          heading_num[0] ++; +          heading_num[1] = 0; +          heading_num[2] = 0; +          heading_num[3] = 0; +        } else if ( +          conf_make_meta.make.auto_num_top_lv +            == (obj_["lev_markup_number"].to!uint - 1) +        ) { +          heading_num[1] ++; +          heading_num[2] = 0; +          heading_num[3] = 0; +        } else if ( +          conf_make_meta.make.auto_num_top_lv +            == (obj_["lev_markup_number"].to!uint - 2) +        ) { +          heading_num[2] ++; +          heading_num[3] = 0; +        } else if ( +          conf_make_meta.make.auto_num_top_lv +            == (obj_["lev_markup_number"].to!uint - 3) +        ) { +          heading_num[3] ++; +        } +        if (heading_num[3] > 0) { +          heading_number_auto_composite +            = (conf_make_meta.make.auto_num_depth.to!uint == 3) +            ? ( heading_num[0].to!string ~ "." +                ~ heading_num[1].to!string ~ "." +                ~ heading_num[2].to!string ~ "." +                ~ heading_num[3].to!string +              ) +            : ""; +        } else if (heading_num[2] > 0) { +          heading_number_auto_composite +            = ((conf_make_meta.make.auto_num_depth.to!uint >= 2) +            && (conf_make_meta.make.auto_num_depth.to!uint <= 3)) +            ?  ( heading_num[0].to!string ~ "." +                 ~ heading_num[1].to!string ~ "." +                 ~ heading_num[2].to!string +               ) +            : ""; +        } else if (heading_num[1] > 0) { +          heading_number_auto_composite +            = ((conf_make_meta.make.auto_num_depth.to!uint >= 1) +            && (conf_make_meta.make.auto_num_depth.to!uint <= 3)) +            ? ( heading_num[0].to!string ~ "." +                 ~ heading_num[1].to!string +               ) +            : ""; +        } else if (heading_num[0] > 0) { +          heading_number_auto_composite +            = ((conf_make_meta.make.auto_num_depth.to!uint >= 0) +            && (conf_make_meta.make.auto_num_depth.to!uint <= 3)) +            ?  (heading_num[0].to!string) +            : ""; +        } else { +          heading_number_auto_composite = ""; +        } +        debug(heading_number_auto) { +          writeln(heading_number_auto_composite); +        } +        if ((!empty(heading_number_auto_composite)) +        && (obj_["lev_markup_number"].to!uint >= conf_make_meta.make.auto_num_top_lv)) { +          munge_=(munge_) +          .replaceFirst(rgx.heading, +            "$1~$2 " ~ heading_number_auto_composite ~ ". ") +          .replaceFirst(rgx.heading_marker_missing_tag, +            "$1~" ~ heading_number_auto_composite ~ " "); +        } +      } +      return munge_; +    } +    static int heading_num_lev1 = 0; +    static string _make_segment_anchor_tags_if_none_provided(M,Lv)( +      M munge_, +      Lv lev_, +      bool _new_doc +    ) { +      debug(asserts) { +        static assert(is(typeof(munge_) == string)); +        static assert(is(typeof(lev_)   == string)); +      } +      if (!(munge_.match(rgx.heading_anchor_tag))) { +        if (munge_.match(rgx.heading_identify_anchor_tag)) { +          if (auto m = munge_.match(rgx.heading_extract_named_anchor_tag)) { +            munge_=(munge_).replaceFirst( +              rgx.heading_marker_missing_tag, +              "$1~" ~ m.captures[1].toLower ~ "_"  ~ m.captures[2] ~ " "); +            if (auto n = munge_.match(rgx.heading_anchor_tag_plus_colon)) { +              auto tag_remunge_ = n.captures[2].replaceAll(rgx.heading_marker_tag_has_colon, ".."); +              munge_=(munge_).replaceFirst(rgx.heading_anchor_tag_plus_colon, n.captures[1] ~ tag_remunge_ ~ " "); +            } +          } else if (auto m = munge_.match(rgx.heading_extract_unnamed_anchor_tag)) { +            munge_=(munge_).replaceFirst( +              rgx.heading_marker_missing_tag, +              "$1~" ~ "s" ~ m.captures[1] ~ " "); +          } +        } else if (lev_ == "1") { // (if not successful) manufacture a unique anchor tag for lev=="1" +          if (_new_doc) { +            heading_num_lev1 = 0; +          } +          heading_num_lev1 ++; +          munge_=(munge_).replaceFirst( +            rgx.heading_marker_missing_tag, +            "$1~" ~ "x" ~ heading_num_lev1.to!string ~ " "); +        } +      } +      return munge_; +    } +    unittest { +      string txt_lev="1"; +      string txt_in, txt_out; +   +      txt_in = "1~copyright Copyright"; +      txt_out ="1~copyright Copyright"; +      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); +   +      txt_in = "1~ 6. Writing Copyright Licenses"; +      txt_out ="1~s6 6. Writing Copyright Licenses"; +      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); +   +      txt_in= "1~ 1. Reinforcing trends"; +      txt_out= "1~s1 1. Reinforcing trends"; +      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); +   +      txt_in= "1~ 11 SCIENCE AS A COMMONS"; +      txt_out= "1~s11 11 SCIENCE AS A COMMONS"; +      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); +   +      txt_in= "1~ Chapter 1"; +      txt_out="1~chapter_1 Chapter 1"; +      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); +   +      txt_in= "1~ Chapter 1."; +      txt_out="1~chapter_1 Chapter 1."; +      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); +   +      txt_in= "1~ Chapter 1: Done"; +      txt_out="1~chapter_1 Chapter 1: Done"; +      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); +   +      txt_in=  "1~ Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment"; +      txt_out= "1~chapter_11 Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment"; +      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); +   +      txt_in= "1~ CHAPTER I."; +      txt_out="1~x1 CHAPTER I."; +      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); +   +      txt_in= "1~ CHAPTER II."; +      txt_out="1~x2 CHAPTER II."; +      assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); +    } +  } +  /+ +/ +  struct ObjAttributes { +    string[string] _obj_attrib; +    string obj_attributes(Oi,OR,OH)( +      Oi obj_is_, +      OR obj_raw, +      OH _comp_obj_heading, +    ) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_is_)           == string)); +        static assert(is(typeof(obj_raw)           == string)); +        static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite)); +      } +    } +    body { +      scope(exit) { +        destroy(obj_is_); +        destroy(obj_raw); +        destroy(_comp_obj_heading); +      } +      _obj_attrib["json"] ="{"; +      switch (obj_is_) { +      case "heading": +        _obj_attrib["json"] ~= _heading(obj_raw); +        break; +      case "para": +        _obj_attrib["json"] ~= _para_and_blocks(obj_raw) +        ~ _para(obj_raw); +        break; +      case "code": +        _obj_attrib["json"] ~= _code(obj_raw); +        break; +      case "group": +        _obj_attrib["json"] ~= _para_and_blocks(obj_raw) +        ~ _group(obj_raw); +        break; +      case "block": +        _obj_attrib["json"] ~= _para_and_blocks(obj_raw) +        ~ _block(obj_raw); +        break; +      case "verse": +        _obj_attrib["json"] ~= _verse(obj_raw); +        break; +      case "quote": +        _obj_attrib["json"] ~= _quote(obj_raw); +        break; +      case "table": +        _obj_attrib["json"] ~= _table(obj_raw); +        break; +      case "comment": +        _obj_attrib["json"] ~= _comment(obj_raw); +        break; +      default: +        _obj_attrib["json"] ~= _para(obj_raw); +        break; +      } +      _obj_attrib["json"] ~=" }"; +      _obj_attrib["json"]=_set_additional_values_parse_as_json(_obj_attrib["json"], obj_is_, _comp_obj_heading); +      debug(structattrib) { +        if (oa_j["is"].str() == "heading") { +          writeln(_obj_attrib["json"]); +          writeln( +            "is: ", oa_j["is"].str(), +            "; object_number: ", oa_j["object_number"].integer() +          ); +        } +      } +      return _obj_attrib["json"]; +    } +    invariant() { +    } +    private: +    string _obj_attributes; +    string _para_and_blocks(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      if (obj_txt_in.matchFirst(rgx.para_bullet)) { +        _obj_attributes =" \"bullet\": \"true\"," +        ~ " \"indent_hang\": 0," +        ~ " \"indent_base\": 0,"; +      } else if (auto m = obj_txt_in.matchFirst(rgx.para_bullet_indent)) { +        _obj_attributes =" \"bullet\": \"true\"," +        ~ " \"indent_hang\": " ~ m.captures[1].to!string ~ "," +        ~ " \"indent_base\": " ~ m.captures[1].to!string ~ ","; +      } else if (auto m = obj_txt_in.matchFirst(rgx.para_indent_hang)) { +        _obj_attributes =" \"bullet\": \"false\"," +        ~ " \"indent_hang\": " ~ m.captures[1].to!string ~ "," +        ~ " \"indent_base\": " ~ m.captures[2].to!string ~ ","; +      } else if (auto m = obj_txt_in.matchFirst(rgx.para_indent)) { +        _obj_attributes =" \"bullet\": \"false\"," +        ~ " \"indent_hang\": " ~ m.captures[1].to!string ~ "," +        ~ " \"indent_base\": " ~ m.captures[1].to!string ~ ","; +      } else { +        _obj_attributes =" \"bullet\": \"false\"," +        ~ " \"indent_hang\": 0," +        ~ " \"indent_base\": 0,"; +      } +      return _obj_attributes; +    } +    string _heading(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      _obj_attributes = " \"use\": \"content\"," +      ~ " \"of\": \"para\"," +      ~ " \"is\": \"heading\""; +      return _obj_attributes; +    } +    invariant() { +    } +    string _para(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      _obj_attributes = " \"use\": \"content\"," +      ~ " \"of\": \"para\"," +      ~ " \"is\": \"para\""; +      return _obj_attributes; +    } +    invariant() { +    } +    string _quote(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      _obj_attributes = " \"use\": \"content\"," +      ~ " \"of\": \"block\"," +      ~ " \"is\": \"quote\""; +      return _obj_attributes; +    } +    invariant() { +    } +    string _group(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      _obj_attributes = " \"use\": \"content\"," +      ~ " \"of\": \"block\"," +      ~ " \"is\": \"group\""; +      return _obj_attributes; +    } +    invariant() { +    } +    string _block(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      _obj_attributes = " \"use\": \"content\"," +      ~ " \"of\": \"block\"," +      ~ " \"is\": \"block\""; +      return _obj_attributes; +    } +    invariant() { +    } +    string _verse(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      _obj_attributes = " \"use\": \"content\"," +      ~ " \"of\": \"block\"," +      ~ " \"is\": \"verse\""; +      return _obj_attributes; +    } +    invariant() { +    } +    string _code(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      _obj_attributes = " \"use\": \"content\"," +      ~ " \"of\": \"block\"," +      ~ " \"is\": \"code\""; +      return _obj_attributes; +    } +    invariant() { +    } +    string _table(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      _obj_attributes = " \"use\": \"content\"," +      ~ " \"of\": \"block\"," +      ~ " \"is\": \"table\""; +      return _obj_attributes; +    } +    invariant() { +    } +    string _comment(Ot)(Ot obj_txt_in) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +    } +    body { +      _obj_attributes = " \"use\": \"comment\"," +      ~ " \"of\": \"comment\"," +      ~ " \"is\": \"comment\""; +      return _obj_attributes; +    } +    invariant() { +    } +    string _set_additional_values_parse_as_json(OA,Oi,OH)( +      OA _obj_attrib, +      Oi obj_is_, +      OH _comp_obj_heading, +    ) { +      debug(asserts) { +        static assert(is(typeof(_obj_attrib)       == string)); +        static assert(is(typeof(obj_is_)           == string)); +        static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite)); +      } +      JSONValue oa_j = parseJSON(_obj_attrib); +      assert( +        (oa_j.type == JSON_TYPE.OBJECT) +      ); +      if (obj_is_ == "heading") { +        oa_j.object["object_number"]          = _comp_obj_heading.metainfo.ocn; +        oa_j.object["lev_markup_number"]      = _comp_obj_heading.metainfo.heading_lev_markup; +        oa_j.object["lev_collapsed_number"]   = _comp_obj_heading.metainfo.heading_lev_collapsed; +        oa_j.object["heading_ptr"] +          = _comp_obj_heading.ptr.heading; +        oa_j.object["doc_object_ptr"] +          = _comp_obj_heading.ptr.doc_object; +      } +      oa_j.object["parent_object_number"]     = _comp_obj_heading.metainfo.parent_ocn; +      oa_j.object["parent_lev_markup_number"] = _comp_obj_heading.metainfo.parent_lev_markup; +      _obj_attrib = oa_j.toString(); +      return _obj_attrib; +    } +  } +  /+ +/ +  struct BookIndexNuggetHash { +    string main_term, sub_term, sub_term_bits; +    int object_number_offset, object_number_endpoint; +    string[] object_numbers; +    string[][string][string] bi; +    string[][string][string] hash_nugget; +    string[] bi_main_terms_split_arr; +    string[][string][string] bookindex_nugget_hash(BI,N,S)( +      BI bookindex_section, +      N  obj_cite_digits, +      S  segment_anchor_tag, +    ) +    in { +      debug(asserts) { +        static assert(is(typeof(bookindex_section)  == string)); +        static assert(is(typeof(obj_cite_digits.on) == int)); +      } +      debug(bookindexraw) { +        if (!bookindex_section.empty) { +          writeln( +            "* [bookindex] ", +            "[", obj_cite_digits.on.to!string, ": ", segment_anchor_tag, "] ", bookindex_section +          ); +        } +      } +    } +    body { +      static auto rgx = Rgx(); +      if (!bookindex_section.empty) { +        auto bi_main_terms_split_arr +          = bookindex_section.split(rgx.bi_main_terms_split); +        foreach (bi_main_terms_content; bi_main_terms_split_arr) { +          auto bi_main_term_and_rest +            = bi_main_terms_content.split(rgx.bi_main_term_plus_rest_split); +          if (auto m = bi_main_term_and_rest[0].match( +            rgx.bi_term_and_object_numbers_match) +          ) { +            main_term = m.captures[1].strip; +            object_number_offset = m.captures[2].to!int; +            object_number_endpoint=(obj_cite_digits.on + object_number_offset); +            object_numbers ~= (obj_cite_digits.on.to!string ~ "-" ~ to!string(object_number_endpoint) +            ~ ":" ~ segment_anchor_tag); +          } else { +            main_term = bi_main_term_and_rest[0].strip; +            object_numbers ~= obj_cite_digits.on.to!string +            ~ ":" ~ segment_anchor_tag; +          } +          bi[main_term]["_a"] ~= object_numbers; +          object_numbers=null; +          if (bi_main_term_and_rest.length > 1) { +            auto bi_sub_terms_split_arr +              = bi_main_term_and_rest[1].split( +                rgx.bi_sub_terms_plus_object_number_offset_split +              ); +            foreach (sub_terms_bits; bi_sub_terms_split_arr) { +              if (auto m = sub_terms_bits.match(rgx.bi_term_and_object_numbers_match)) { +                sub_term = m.captures[1].strip; +                object_number_offset = m.captures[2].to!int; +                object_number_endpoint=(obj_cite_digits.on + object_number_offset); +                object_numbers ~= (obj_cite_digits.on.to!string ~ " - " ~ to!string(object_number_endpoint) +                ~ ":" ~ segment_anchor_tag); +              } else { +                sub_term = sub_terms_bits.strip; +                object_numbers ~= to!string(obj_cite_digits.on) +                ~ ":" ~ segment_anchor_tag; +              } +              if (!empty(sub_term)) { +                bi[main_term][sub_term] ~= object_numbers; +              } +              object_numbers=null; +            } +          } +        } +      } +      hash_nugget = bi; +      return hash_nugget; +    } +    invariant() { +    } +  } +  struct BookIndexReportIndent { +    int mkn, skn; +    auto bookindex_report_indented(BI)( +      BI bookindex_unordered_hashes +    ) { +      debug(asserts) { +        static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string])); +      } +      auto mainkeys +        = bookindex_unordered_hashes.byKey.array.sort().release; +      foreach (mainkey; mainkeys) { +        debug(bookindex1) { +          writeln(mainkey); +        } +        auto subkeys +          = bookindex_unordered_hashes[mainkey].byKey.array.sort().release; +        foreach (subkey; subkeys) { +          debug(bookindex1) { +            writeln("  ", subkey); +            writeln("    ", to!string( +              bookindex_unordered_hashes[mainkey][subkey] +            )); +          } +          ++skn; +        } +        ++mkn; +      } +    } +  } +  struct BookIndexReportSection { +    int  mkn, skn; +    static auto rgx = Rgx(); +    static auto munge = ObjInlineMarkupMunge(); +    auto bookindex_write_section(BI)( +      BI bookindex_unordered_hashes +    ) { +      debug(asserts) { +        static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string])); +      } +      auto mainkeys=bookindex_unordered_hashes.byKey.array.sort().release; +      foreach (mainkey; mainkeys) { +        write("_0_1 !{", mainkey, "}! "); +        foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { +          auto go = (ref_).replaceAll(rgx.book_index_go, "$1"); +          write(" {", ref_, "}#", go, ", "); +        } +        writeln(" \\\\"); +        bookindex_unordered_hashes[mainkey].remove("_a"); +        auto subkeys +          = bookindex_unordered_hashes[mainkey].byKey.array.sort().release; +        foreach (subkey; subkeys) { +          write("  ", subkey, ", "); +          foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { +            auto go = (ref_).replaceAll(rgx.book_index_go, "$1"); +            write(" {", ref_, "}#", go, ", "); +          } +          writeln(" \\\\"); +          ++skn; +        } +        ++mkn; +      } +    } +    auto bookindex_build_abstraction_section(BI,N,B)( +      BI bookindex_unordered_hashes, +      N  obj_cite_digits, +      B  opt_action, +    ) { +      debug(asserts) { +        static assert(is(typeof(bookindex_unordered_hashes)                == string[][string][string])); +        static assert(is(typeof(obj_cite_digits.on)                        == int)); +      } +      mixin SiSUnode; +      mixin InternalMarkup; +      static auto mkup = InlineMarkup(); +      string type_is; +      string lev; +      int heading_lev_markup, heading_lev_collapsed; +      string attrib; +      int[string] indent; +      auto mainkeys +        = bookindex_unordered_hashes.byKey.array.sort().release; +      ObjGenericComposite[][string] bookindex_section; +      ObjGenericComposite comp_obj_heading_, comp_obj_para; +      auto node_para_int_ = node_metadata_para_int; +      auto node_para_str_ = node_metadata_para_str; +      if ((mainkeys.length > 0) +      && (opt_action.backmatter +      && opt_action.section_bookindex)) { +        string bi_tmp_seg, bi_tmp_scroll; +        string[] bi_tmp_tags; +        comp_obj_heading_                                = comp_obj_heading_.init; +        comp_obj_heading_.metainfo.is_of_part            = "backmatter"; +        comp_obj_heading_.metainfo.is_of_section         = "bookindex"; +        comp_obj_heading_.metainfo.is_of_type            = "para"; +        comp_obj_heading_.metainfo.is_a                  = "heading"; +        comp_obj_heading_.text                           = "Book Index"; +        comp_obj_heading_.metainfo.ocn                   = 0; +        comp_obj_heading_.metainfo.object_number_off     = ""; +        comp_obj_heading_.metainfo.object_number_type    = 0; +        comp_obj_heading_.tags.segment_anchor_tag        = "_part_book_index"; +        comp_obj_heading_.metainfo.heading_lev_markup    = 1; +        comp_obj_heading_.metainfo.heading_lev_collapsed = 1; +        comp_obj_heading_.metainfo.parent_ocn            = 1; +        comp_obj_heading_.metainfo.parent_lev_markup     = 0; +        comp_obj_heading.has.inline_links                = true; +        bookindex_section["scroll"]                      ~= comp_obj_heading_; +        bookindex_section["seg"]                         ~= comp_obj_heading_; +        ++mkn; +        comp_obj_heading_                                = comp_obj_heading_.init; +        comp_obj_heading_.metainfo.is_of_part            = "backmatter"; +        comp_obj_heading_.metainfo.is_of_section         = "bookindex"; +        comp_obj_heading_.metainfo.is_of_type            = "para"; +        comp_obj_heading_.metainfo.is_a                  = "heading"; +        comp_obj_heading_.text                           = "Index"; +        comp_obj_heading_.metainfo.ocn                   = 0; +        comp_obj_heading_.metainfo.object_number_off     = ""; +        comp_obj_heading_.metainfo.object_number_type    = 0; +        comp_obj_heading_.tags.segment_anchor_tag        = "bookindex"; +        comp_obj_heading_.metainfo.heading_lev_markup    = 4; +        comp_obj_heading_.metainfo.heading_lev_collapsed = 2; +        comp_obj_heading_.metainfo.parent_ocn            = 1; +        comp_obj_heading_.metainfo.parent_lev_markup     = 0; +        comp_obj_heading.has.inline_links                = false; +        comp_obj_heading_.tags.anchor_tags               = ["bookindex"]; +        bookindex_section["scroll"]                      ~= comp_obj_heading_; +        bookindex_section["seg"]                         ~= comp_obj_heading_; +        ++mkn; +        import std.array : appender; +        auto buffer = appender!(char[])(); +        string[dchar] transTable = [' ' : "_"]; +        foreach (mainkey; mainkeys) { +          bi_tmp_tags = [""]; +          bi_tmp_scroll = "!{" ~ mainkey ~ "}! "; +          buffer.clear(); +          bi_tmp_tags ~= translate(mainkey, transTable); +          bi_tmp_seg = "!{" ~ mainkey ~ "}! "; +          auto bkidx_lnk_seg(string locs) { +            string markup = ""; +            if (auto m = locs.matchFirst(rgx.book_index_go_seg)) { +              markup +                = munge.url_links("{ " ~ m["link"] ~ " }" +                ~ mkup.mark_internal_site_lnk ~ m["seg"] ~ ".fnSuffix" +                ~ "#" ~ m["ocn"] ~ ", "); +            } else { +              writeln(__LINE__, ": ", locs); +            } +            return markup; +          } +          auto bkidx_lnk_scroll(string locs) { +            string markup = ""; +            if (auto m = locs.matchFirst(rgx.book_index_go)) { +              markup +                = munge.url_links("{ " ~ m["link"] ~ " }" +                ~ mkup.mark_internal_site_lnk +                ~ "#" ~ m["ocn"] ~ ", "); +            } else { +              writeln(__LINE__, ": ", locs); +            } +            return markup; +          } +          foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { +            bi_tmp_scroll ~= bkidx_lnk_scroll(ref_); +            bi_tmp_seg ~= bkidx_lnk_seg(ref_); +          } +          bi_tmp_scroll ~= " \\\\\n    "; +          bi_tmp_seg ~= " \\\\\n    "; +          bookindex_unordered_hashes[mainkey].remove("_a"); +          auto subkeys +            = bookindex_unordered_hashes[mainkey].byKey.array.sort().release; +          foreach (subkey; subkeys) { +            bi_tmp_scroll ~= subkey ~ ", "; +            buffer.clear(); +            bi_tmp_tags ~= translate(subkey, transTable); +            bi_tmp_seg ~= subkey ~ ", "; +            foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { +              bi_tmp_scroll ~= bkidx_lnk_scroll(ref_); +              bi_tmp_seg ~= bkidx_lnk_seg(ref_); +            } +            bi_tmp_scroll ~= " \\\\\n    "; +            bi_tmp_seg ~= " \\\\\n    "; +            ++skn; +          } +          bi_tmp_scroll                                  = (bi_tmp_scroll).replaceFirst(rgx.trailing_linebreak, ""); +          bi_tmp_seg                                     = (bi_tmp_seg).replaceFirst(rgx.trailing_linebreak, ""); +          comp_obj_para                                  = comp_obj_para.init; +          comp_obj_para.metainfo.is_of_part              = "backmatter"; +          comp_obj_para.metainfo.is_of_section           = "bookindex"; +          comp_obj_para.metainfo.is_of_type              = "para"; +          comp_obj_para.metainfo.is_a                    = "bookindex"; +          comp_obj_para.text                             = bi_tmp_scroll.to!string.strip; +          comp_obj_para.metainfo.ocn                     = 0; +          comp_obj_para.metainfo.object_number_off       = ""; +          comp_obj_para.metainfo.object_number_type      = 0; +          comp_obj_para.tags.anchor_tags                 = bi_tmp_tags; +          comp_obj_para.attrib.indent_hang               = 0; +          comp_obj_para.attrib.indent_base               = 1; +          comp_obj_para.attrib.bullet                    = false; +          comp_obj_para.has.inline_links                 = true; +          bookindex_section["scroll"]                    ~= comp_obj_para; +          comp_obj_para.text                             = bi_tmp_seg.to!string.strip; +          bookindex_section["seg"]                       ~= comp_obj_para; +          ++mkn; +        } +      } else {                              // no book index, (figure out what to do here) +        comp_obj_heading_                                = comp_obj_heading_.init; +        comp_obj_heading_.text                           = "(skip) there is no Book Index"; +        comp_obj_heading_.metainfo.ocn                   = 0; +        comp_obj_heading_.metainfo.object_number_off     = ""; +        comp_obj_heading_.metainfo.object_number_type    = 0; +        comp_obj_heading_.metainfo.heading_lev_markup    = 1; +        comp_obj_heading_.metainfo.heading_lev_collapsed = 1; +        comp_obj_heading_.metainfo.parent_ocn            = 1; +        comp_obj_heading_.metainfo.parent_lev_markup     = 0; +        bookindex_section["scroll"]                      ~= comp_obj_heading_; +        bookindex_section["seg"]                         ~= comp_obj_heading_; +      } +      auto t = tuple(bookindex_section, obj_cite_digits); +      return t; +    } +  } +  /+ +/ +  struct NotesSection { +    string[string] object_notes; +    int previous_count; +    int mkn; +    static auto rgx = Rgx(); +    private auto gather_notes_for_endnote_section( +      ObjGenericComposite[] contents_am, +      string                segment_anchor_tag_that_object_belongs_to, +      int                   cntr, +    ) +    in { +      assert((contents_am[cntr].metainfo.is_a == "para") +      || (contents_am[cntr].metainfo.is_a     == "heading") +      || (contents_am[cntr].metainfo.is_a     == "quote") +      || (contents_am[cntr].metainfo.is_a     == "group") +      || (contents_am[cntr].metainfo.is_a     == "block") +      || (contents_am[cntr].metainfo.is_a     == "verse")); +      assert(cntr >= previous_count); +      assert( +        (contents_am[cntr].text).match( +        rgx.inline_notes_delimiter_al_regular_number_note) +      ); +    } +    body { +      mixin InternalMarkup; +      previous_count=cntr; +      static auto mkup = InlineMarkup(); +      static auto munge = ObjInlineMarkupMunge(); +      foreach( +        m; +        (contents_am[cntr].text).matchAll( +          rgx.inline_notes_delimiter_al_regular_number_note +        ) +      ) { +        debug(endnotes_build) { +          writeln( +            "{^{", m.captures[1], ".}^}" +            ~ mkup.mark_internal_site_lnk, +            segment_anchor_tag_that_object_belongs_to, +              ".fnSuffix#noteref_\n  ", m.captures[1], " ", +            m.captures[2]); // sometimes need segment name (segmented html & epub) +        } +        // you need anchor for segments at this point -> +        object_notes["anchor"] ~= "note_" ~ m.captures[1] ~ "』"; +        object_notes["notes"] ~= (segment_anchor_tag_that_object_belongs_to.empty) +        ? (munge.url_links( +            "{^{" ~ m.captures[1] ~ ".}^}#noteref_" +            ~ m.captures[1]) ~ " " +            ~ m.captures[2] ~ "』" +          ) +        : (munge.url_links( +            "{^{" ~ m.captures[1] ~ ".}^}" +             ~ mkup.mark_internal_site_lnk +             ~ segment_anchor_tag_that_object_belongs_to +             ~ ".fnSuffix#noteref_" +             ~ m.captures[1]) ~ " " +             ~ m.captures[2] ~ "』" +          ); +      } +      return object_notes; +    } +    private auto gathered_notes() +    in { +    } +    body { +      string[][string] endnotes_; +      if (object_notes.length > 1) { +        endnotes_["notes"] = (object_notes["notes"].split(rgx.break_string))[0..$-1]; +        endnotes_["anchor"] = (object_notes["anchor"].split(rgx.break_string))[0..$-1]; +      } else { +        endnotes_["notes"] = []; +        endnotes_["anchor"] = []; +      } +      return endnotes_; +    } +    private auto endnote_objects(N,O)( +      N              obj_cite_digits, +      O              opt_action, +    ) +    in { +    } +    body { +      mixin SiSUnode; +      ObjGenericComposite[] the_endnotes_section; +      auto endnotes_ = gathered_notes(); +      string type_is; +      string lev, lev_markup_number, lev_collapsed_number; +      string attrib; +      int[string] indent; +      ObjGenericComposite comp_obj_heading_; +      if ((endnotes_["notes"].length > 0) +      && (opt_action.backmatter && opt_action.section_endnotes)) { +        comp_obj_heading_                                = comp_obj_heading_.init; +        comp_obj_heading_.metainfo.is_of_part            = "backmatter"; +        comp_obj_heading_.metainfo.is_of_section         = "endnotes"; +        comp_obj_heading_.metainfo.is_of_type            = "para"; +        comp_obj_heading_.metainfo.is_a                  = "heading"; +        comp_obj_heading_.text                           = "Endnotes"; +        comp_obj_heading_.metainfo.ocn                   = 0; +        comp_obj_heading_.metainfo.object_number_off     = ""; +        comp_obj_heading_.metainfo.object_number_type    = 0; +        comp_obj_heading_.tags.segment_anchor_tag        = "_part_endnotes"; +        comp_obj_heading_.metainfo.heading_lev_markup    = 1; +        comp_obj_heading_.metainfo.heading_lev_collapsed = 1; +        comp_obj_heading_.metainfo.parent_ocn            = 1; +        comp_obj_heading_.metainfo.parent_lev_markup     = 0; +        the_endnotes_section                             ~= comp_obj_heading_; +        ++mkn; +        comp_obj_heading_                                = comp_obj_heading_.init; +        comp_obj_heading_.metainfo.is_of_part            = "backmatter"; +        comp_obj_heading_.metainfo.is_of_section         = "endnotes"; +        comp_obj_heading_.metainfo.is_of_type            = "para"; +        comp_obj_heading_.metainfo.is_a                  = "heading"; +        comp_obj_heading_.text                           = "Endnotes"; +        comp_obj_heading_.metainfo.ocn                   = 0; +        comp_obj_heading_.metainfo.object_number_off     = ""; +        comp_obj_heading_.metainfo.object_number_type    = 0; +        comp_obj_heading_.tags.segment_anchor_tag        = "endnotes"; +        comp_obj_heading_.metainfo.heading_lev_markup    = 4; +        comp_obj_heading_.metainfo.heading_lev_collapsed = 2; +        comp_obj_heading_.metainfo.parent_ocn            = 1; +        comp_obj_heading_.metainfo.parent_lev_markup     = 0; +        comp_obj_heading_.tags.anchor_tags               = ["endnotes"]; +        the_endnotes_section                             ~= comp_obj_heading_; +        ++mkn; +      } else { +        comp_obj_heading_                                = comp_obj_heading_.init; +        comp_obj_heading_.metainfo.is_of_part            = "empty"; +        comp_obj_heading_.metainfo.is_of_section         = "empty"; +        comp_obj_heading_.metainfo.is_of_type            = "para"; +        comp_obj_heading_.metainfo.is_a                  = "heading"; +        comp_obj_heading_.text                           = "(skip) there are no Endnotes"; +        comp_obj_heading_.metainfo.ocn                   = 0; +        comp_obj_heading_.metainfo.object_number_off     = ""; +        comp_obj_heading_.metainfo.object_number_type    = 0; +        comp_obj_heading_.metainfo.heading_lev_markup    = 1; +        comp_obj_heading_.metainfo.heading_lev_collapsed = 1; +        comp_obj_heading_.metainfo.parent_ocn            = 1; +        comp_obj_heading_.metainfo.parent_lev_markup     = 0; +        the_endnotes_section                             ~= comp_obj_heading_; +      } +      if (opt_action.backmatter && opt_action.section_endnotes) { +        ObjGenericComposite comp_obj_endnote_; +        comp_obj_endnote_                                = comp_obj_endnote_.init; +        comp_obj_endnote_.metainfo.is_of_part            = "backmatter"; +        comp_obj_endnote_.metainfo.is_of_section         = "endnote"; +        comp_obj_endnote_.metainfo.is_of_type            = "para"; +        comp_obj_endnote_.metainfo.is_a                  = "endnote"; +        comp_obj_endnote_.metainfo.ocn                   = 0; +        comp_obj_heading_.metainfo.object_number_off     = ""; +        comp_obj_heading_.metainfo.object_number_type    = 0; +        comp_obj_endnote_.attrib.indent_hang             = 0; +        comp_obj_endnote_.attrib.indent_base             = 0; +        comp_obj_endnote_.attrib.bullet                  = false; +        foreach (i, endnote; endnotes_["notes"]) { +          auto     m                                     = endnote.matchFirst(rgx.note_ref); +          string   notenumber                            = m.captures[1].to!string; +          string   anchor_tag                            = "note_" ~ notenumber; +          comp_obj_endnote_.tags.anchor_tags             = [ endnotes_["anchor"][i] ]; +          comp_obj_endnote_.has.inline_links             = true; +          comp_obj_endnote_.text                         = endnote.strip; +          the_endnotes_section                           ~= comp_obj_endnote_; +        } +      } +      auto t = tuple(the_endnotes_section, obj_cite_digits); +      return t; +    } +  } +  /+ +/ +  struct Bibliography { +    public JSONValue[] _bibliography_(Bi,BJ)( +      return ref Bi biblio_unsorted_incomplete, +      return ref BJ bib_arr_json +    ) +    in { +      debug(asserts) { +        static assert(is(typeof(biblio_unsorted_incomplete) == string[])); +        static assert(is(typeof(bib_arr_json)               == JSONValue[])); +      } +   } +    body { +      JSONValue[] biblio_unsorted +        = _biblio_unsorted_complete_(biblio_unsorted_incomplete, bib_arr_json); +      biblio_arr_json = []; +      biblio_unsorted_incomplete = []; +      JSONValue[] biblio_sorted__ = biblio_sort(biblio_unsorted); +      biblio_debug(biblio_sorted__); +      debug(biblio0) { +        writeln("---"); +        writeln("unsorted incomplete: ", biblio_unsorted_incomplete.length); +        writeln("json:                ", bib_arr_json.length); +        writeln("unsorted:            ", biblio_unsorted.length); +        writeln("sorted:              ", biblio_sorted__.length); +        int cntr; +        int[7] x; +        while (cntr < x.length) { +          writeln(cntr, ": ", biblio_sorted__[cntr]["fulltitle"]); +          cntr++; +        } +      } +      return biblio_sorted__; +    } +    final private JSONValue[] _biblio_unsorted_complete_(Bi,BJ)( +      Bi            biblio_unordered, +      return ref BJ bib_arr_json +    ) { +      debug(asserts) { +        static assert(is(typeof(biblio_unordered) == string[])); +        static assert(is(typeof(bib_arr_json)     == JSONValue[])); +      } +      foreach (bibent; biblio_unordered) { +        /+ update bib to include deemed_author, needed for: +          sort_bibliography_array_by_deemed_author_year_title +          either: sort on multiple fields, or; create such sort field +        +/ +        JSONValue j = parseJSON(bibent); +        if (!empty(j["fulltitle"].str)) { +          if (!empty(j["author_raw"].str)) { +            j["deemed_author"]=j["author_arr"][0]; +          } else if (!empty(j["editor_raw"].str)) { +            j["deemed_author"]=j["editor_arr"][0]; +          } +          j["sortby_deemed_author_year_title"] = ( +            j["deemed_author"].str ~ +             "; " ~ +             j["year"].str ~ +             "; "  ~ +             j["fulltitle"].str +          ); +        } +        bib_arr_json ~= j; +      } +      JSONValue[] biblio_unsorted_array_of_json_objects +        = bib_arr_json.dup; +      destroy(bib_arr_json); +      return biblio_unsorted_array_of_json_objects; +    } +    final private JSONValue[] biblio_sort(BJ)(BJ biblio_unordered) { +      debug(asserts) { +        static assert(is(typeof(biblio_unordered) == JSONValue[])); +      } +      JSONValue[] biblio_sorted_; +      biblio_sorted_ +        = sort!((a, b){ +          return ((a["sortby_deemed_author_year_title"].str) < (b["sortby_deemed_author_year_title"].str)); +        })(biblio_unordered).array; +      debug(bibliosorted) { +        foreach (j; biblio_sorted_) { +          if (!empty(j["fulltitle"].str)) { +            writeln(j["sortby_deemed_author_year_title"]); +          } +        } +      } +      return biblio_sorted_; +    } +    void biblio_debug(BJ)(BJ biblio_sorted) { +      debug(asserts) { +        static assert(is(typeof(biblio_sorted) == JSONValue[])); +      } +      debug(biblio0) { +        foreach (j; biblio_sorted) { +          if (!empty(j["fulltitle"].str)) { +            writeln(j["sortby_deemed_author_year_title"]); +          } +        } +      } +    } +  } +  /+ +/ +  struct NodeStructureMetadata { +    int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7; +    int obj_cite_digit; +    int[string] p_; // p_ parent_ +    static auto rgx = Rgx(); +    ObjGenericComposite node_location_emitter(Lv,Ta,N,C,P,I)( +      Lv lev_markup_number, +      Ta segment_anchor_tag, +      N  obj_cite_digits, +      C  cntr_, +      P  ptr_, +      I  is_ +    ) +    in { +      debug(asserts) { +        static assert(is(typeof(lev_markup_number)  == string)); +        static assert(is(typeof(segment_anchor_tag) == string)); +        static assert(is(typeof(obj_cite_digits.on) == int)); +        static assert(is(typeof(cntr_)              == int)); +        static assert(is(typeof(ptr_)               == int)); +        static assert(is(typeof(is_)                == string)); +      } +      assert(is_ != "heading"); +      assert(obj_cite_digits.on.to!int >= 0); +    } +    body { +      assert(is_ != "heading");               // should not be necessary +      assert(obj_cite_digits.on.to!int >= 0); // should not be necessary +      if (lv7 > State.off) { +        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_4; +        p_["object_number"] = lv7; +      } else if (lv6 > State.off) { +        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3; +        p_["object_number"] = lv6; +      } else if (lv5 > State.off) { +        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2; +        p_["object_number"] = lv5; +      } else { +        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1; +        p_["object_number"] = lv4; +      } +      ObjGenericComposite comp_obj_location; +      comp_obj_location                             = comp_obj_location.init; +      comp_obj_location.metainfo.is_a               = is_; +      comp_obj_location.metainfo.ocn                = obj_cite_digits.on; +      comp_obj_location.tags.segment_anchor_tag     = segment_anchor_tag.to!string; +      comp_obj_location.metainfo.parent_ocn         = p_["object_number"]; +      comp_obj_location.metainfo.parent_lev_markup  = p_["lev_markup_number"]; +      debug(_node) { +        if (lev_markup_number.match(rgx.levels_numbered_headings)) { +          writeln("x ", _node.to!string); +        } else { +          writeln("- ", _node.to!string); +        } +      } +      assert(comp_obj_location.metainfo.parent_lev_markup >= 4); +      assert(comp_obj_location.metainfo.parent_lev_markup <= 7); +      assert(comp_obj_location.metainfo.parent_ocn >= 0); +      return comp_obj_location; +    } +    invariant() { +    } +    ObjGenericComposite node_emitter_heading(T,Lm,Lc,Ta,N,C,P,LA,I,PSn,fNr,fNs,fL)( +      T   _text, +      Lm  lev_markup_number, +      Lc  lev_collapsed_number, +      Ta  segment_anchor_tag, +      N   obj_cite_digits, +      C   cntr_, +      P   ptr_, +      LA  lv_ancestors_txt, +      I   is_, +      PSn html_segnames_ptr, +      fNr flag_notes_reg, +      fNs flag_notes_star, +      fL  flag_links, +    ) +    in { +      debug(asserts) { +        static assert(is(typeof(_text)                == string)); +        static assert(is(typeof(lev)                  == string)); +        static assert(is(typeof(lev_markup_number)    == string)); +        static assert(is(typeof(lev_collapsed_number) == string)); +        static assert(is(typeof(segment_anchor_tag)   == string)); +        static assert(is(typeof(obj_cite_digits.on)   == int)); +        static assert(is(typeof(cntr_)                == int)); +        static assert(is(typeof(ptr_)                 == int)); +        static assert(is(typeof(lv_ancestors_txt)     == string[])); +        static assert(is(typeof(is_)                  == string)); +        static assert(is(typeof(html_segnames_ptr)    == int)); +      } +      assert(is_ == "heading"); +      assert((obj_cite_digits.on).to!int >= 0); +      assert( +        lev_markup_number.match(rgx.levels_numbered), +        ("not a valid heading level: " ~ lev_markup_number ~ " at " ~ obj_cite_digits.on.to!string) +      ); +      if (lev_markup_number.match(rgx.levels_numbered)) { +        if (lev_markup_number.to!int == 0) { +          /+ TODO first hit (of two) with this assertion failure, check, fix & reinstate +          assert(obj_cite_digits.on.to!int == 1, +            "ERROR header lev markup number is: " ~ +            lev_markup_number.to!string ~ +            " obj_cite_digits.on.to!int should == 1 but is: " ~ +             obj_cite_digits.on.to!string ~ +            "\n" ~ _text); +          +/ +        } +      } +    } +    body { +      switch (lev_markup_number.to!int) { +      case 0: +        lv = DocStructMarkupHeading.h_sect_A; +        lv0 = obj_cite_digit; +        lv1=0; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; +        p_["lev_markup_number"] = 0; +        p_["object_number"] = 0; +        break; +      case 1: +        lv = DocStructMarkupHeading.h_sect_B; +        lv1 = obj_cite_digit; +        lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; +        p_["lev_markup_number"] +          = DocStructMarkupHeading.h_sect_A; +        p_["object_number"] = lv0; +        break; +      case 2: +        lv = DocStructMarkupHeading.h_sect_C; +        lv2 = obj_cite_digit; +        lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; +        p_["lev_markup_number"] +          = DocStructMarkupHeading.h_sect_B; +        p_["object_number"] = lv1; +        break; +      case 3: +        lv = DocStructMarkupHeading.h_sect_D; +        lv3=obj_cite_digit; +        lv4=0; lv5=0; lv6=0; lv7=0; +        p_["lev_markup_number"] +          = DocStructMarkupHeading.h_sect_C; +        p_["object_number"] = lv2; +        break; +      case 4: +        lv = DocStructMarkupHeading.h_text_1; +        lv4 = obj_cite_digit; +        lv5=0; lv6=0; lv7=0; +        if (lv3 > State.off) { +          p_["lev_markup_number"] +            = DocStructMarkupHeading.h_sect_D; +          p_["object_number"] = lv3; +        } else if (lv2 > State.off) { +          p_["lev_markup_number"] +            = DocStructMarkupHeading.h_sect_C; +          p_["object_number"] = lv2; +        } else if (lv1 > State.off) { +          p_["lev_markup_number"] +            = DocStructMarkupHeading.h_sect_B; +          p_["object_number"] = lv1; +        } else { +          p_["lev_markup_number"] +            = DocStructMarkupHeading.h_sect_A; +          p_["object_number"] = lv0; +        } +        break; +      case 5: +        lv = DocStructMarkupHeading.h_text_2; +        lv5 = obj_cite_digit; +        lv6=0; lv7=0; +        p_["lev_markup_number"] +          = DocStructMarkupHeading.h_text_1; +        p_["object_number"] = lv4; +        break; +      case 6: +        lv = DocStructMarkupHeading.h_text_3; +        lv6 = obj_cite_digit; +        lv7=0; +        p_["lev_markup_number"] +          = DocStructMarkupHeading.h_text_2; +        p_["object_number"] = lv5; +        break; +      case 7: +        lv = DocStructMarkupHeading.h_text_4; +        lv7 = obj_cite_digit; +        p_["lev_markup_number"] +          = DocStructMarkupHeading.h_text_3; +        p_["object_number"] = lv6; +        break; +      default: +        break; +      } +      ObjGenericComposite _comp_obj_heading_; +      _comp_obj_heading_                                  = _comp_obj_heading_.init; +      _comp_obj_heading_.metainfo.is_of_part              = "body"; +      _comp_obj_heading_.metainfo.is_of_section           = "body"; +      _comp_obj_heading_.metainfo.is_of_type              = "para"; +      _comp_obj_heading_.metainfo.is_a                    = "heading"; +      _comp_obj_heading_.text                             = _text.to!string.strip; +      _comp_obj_heading_.metainfo.ocn                     = obj_cite_digits.on; +      _comp_obj_heading_.metainfo.object_number_off       = (obj_cite_digits.off==0)   ? "" : obj_cite_digits.off.to!string; +      _comp_obj_heading_.metainfo.object_number_type      = obj_cite_digits.type; +      _comp_obj_heading_.tags.segment_anchor_tag          = segment_anchor_tag.to!string; +      _comp_obj_heading_.metainfo.heading_lev_markup      = (!(lev_markup_number.empty) ? lev_markup_number.to!int : 0); +      _comp_obj_heading_.metainfo.heading_lev_collapsed   = (!(lev_collapsed_number.empty) ? lev_collapsed_number.to!int : 0); +      _comp_obj_heading_.metainfo.parent_ocn              = p_["object_number"]; +      _comp_obj_heading_.metainfo.parent_lev_markup       = p_["lev_markup_number"]; +      _comp_obj_heading_.tags.heading_ancestors_text      = lv_ancestors_txt; +      _comp_obj_heading_.ptr.doc_object                   = cntr_; +      _comp_obj_heading_.ptr.html_segnames                = ((lev_markup_number == "4") ? html_segnames_ptr : 0); +      _comp_obj_heading_.ptr.heading                      = ptr_; +      _comp_obj_heading_.has.inline_notes_reg             = flag_notes_reg; +      _comp_obj_heading_.has.inline_notes_star            = flag_notes_star; +      _comp_obj_heading_.has.inline_links                 = flag_links; +      debug(_node) { +        if (lev_markup_number.match(rgx.levels_numbered_headings)) { +          writeln("* ", _node.to!string); +        } +      } +      debug(nodeheading) { +        if (lev_markup_number.match(rgx.levels_numbered_headings)) { +          writeln("* ", _node.to!string); +        } +      } +      assert(_comp_obj_heading_.metainfo.parent_lev_markup <= 7); +      assert(_comp_obj_heading_.metainfo.parent_ocn >= 0); +      if (lev_markup_number.match(rgx.levels_numbered_headings)) { +        assert(_comp_obj_heading_.metainfo.heading_lev_markup <= 7); +        assert(_comp_obj_heading_.metainfo.ocn >= 0); +        if (_comp_obj_heading_.metainfo.parent_lev_markup > 0) { +          assert(_comp_obj_heading_.metainfo.parent_lev_markup < _comp_obj_heading_.metainfo.heading_lev_markup); +          if (_comp_obj_heading_.metainfo.ocn != 0) { +            assert(_comp_obj_heading_.metainfo.parent_ocn < _comp_obj_heading_.metainfo.ocn); +          } +        } +        if (_comp_obj_heading_.metainfo.heading_lev_markup == 0) { +          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_A); +        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_B) { +          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_A); +        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_C) { +          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_B); +        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_D) { +          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_C); +        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_1) { +          assert(_comp_obj_heading_.metainfo.parent_lev_markup <= DocStructMarkupHeading.h_sect_D); +        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_2) { +          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_1); +        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_3) { +          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_2); +        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_4) { +          assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_3); +        } else if  (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_5) { +        } +      } +      return _comp_obj_heading_; +    } +    invariant() { +    } +  } +  /+ abstraction functions emitters ↑ +/ +  /+ ↓ abstraction functions assertions +/ +  pure void assertions_doc_structure(O,Lv)( +    O  an_object, +    Lv lv +  ) { +    debug(asserts) { +      static assert(is(typeof(an_object) == string[string])); +      static assert(is(typeof(lv)        == int[string])); +    } +    if (lv["h3"] > State.off) { +      assert(lv["h0"] > State.off); +      assert(lv["h1"] > State.off); +      assert(lv["h2"] > State.off); +    } else if (lv["h2"] > State.off) { +      assert(lv["h0"] > State.off); +      assert(lv["h1"] > State.off); +      assert(lv["h3"] == State.off); +    } else if (lv["h1"] > State.off) { +      assert(lv["h0"] > State.off); +      assert(lv["h2"] == State.off); +      assert(lv["h3"] == State.off); +    } else if (lv["h0"] > State.off) { +      assert(lv["h1"] == State.off); +      assert(lv["h2"] == State.off); +      assert(lv["h3"] == State.off); +    } else { +      assert(lv["h0"] == State.off); +      assert(lv["h1"] == State.off); +      assert(lv["h2"] == State.off); +      assert(lv["h3"] == State.off); +    } +    if (lv["h7"] > State.off) { +      assert(lv["h4"] > State.off); +      assert(lv["h5"] > State.off); +      assert(lv["h6"] > State.off); +    } else if (lv["h6"] > State.off) { +      assert(lv["h4"] > State.off); +      assert(lv["h5"] > State.off); +      assert(lv["h7"] == State.off); +    } else if (lv["h5"] > State.off) { +      assert(lv["h4"] > State.off); +      assert(lv["h6"] == State.off); +      assert(lv["h7"] == State.off); +    } else if (lv["h4"] > State.off) { +      assert(lv["h5"] == State.off); +      assert(lv["h6"] == State.off); +      assert(lv["h7"] == State.off); +    } else { +      assert(lv["h4"] == State.off); +      assert(lv["h5"] == State.off); +      assert(lv["h6"] == State.off); +      assert(lv["h7"] == State.off); +    } +    if (lv["h0"] == State.off) { +      assert(lv["h1"] == State.off); +      assert(lv["h2"] == State.off); +      assert(lv["h3"] == State.off); +      assert(lv["h4"] == State.off); +      assert(lv["h5"] == State.off); +      assert(lv["h6"] == State.off); +      assert(lv["h7"] == State.off); +    } +    if (lv["h1"] == State.off) { +      assert(lv["h2"] == State.off); +      assert(lv["h3"] == State.off); +    } +    if (lv["h2"] == State.off) { +      assert(lv["h3"] == State.off); +    } +    if (lv["h3"] == State.off) { +    } +    if (lv["h4"] == State.off) { +      assert(lv["h5"] == State.off); +      assert(lv["h6"] == State.off); +      assert(lv["h7"] == State.off); +    } +    if (lv["h5"] == State.off) { +      assert(lv["h6"] == State.off); +      assert(lv["h7"] == State.off); +    } +    if (lv["h6"] == State.off) { +      assert(lv["h7"] == State.off); +    } +    if (lv["h7"] == State.off) { +    } +    switch ((an_object["lev"]).to!string) { +    case "A": +      if (lv["h0"] == State.off) { +        assert(lv["h1"] == State.off); +        assert(lv["h2"] == State.off); +        assert(lv["h3"] == State.off); +        assert(lv["h4"] == State.off); +        assert(lv["h5"] == State.off); +        assert(lv["h6"] == State.off); +        assert(lv["h7"] == State.off); +      } else {                       // (lv["h0"] > State.off) +        assert(lv["h0"] == State.off,"error should not enter level A a second time"); +      } +      break; +    case "B": +      if (lv["h1"] == State.off) { +        assert(lv["h0"] > State.off); +        assert(lv["h2"] == State.off); +        assert(lv["h3"] == State.off); +      } else {                       // (lv["h1"] > State.off) +        assert(lv["h0"] > State.off); +        assert(lv["h1"] > State.off); +      } +      break; +    case "C": +      if (lv["h2"] == State.off) { +        assert(lv["h0"] > State.off); +        assert(lv["h1"] > State.off); +        assert(lv["h3"] == State.off); +      } else {                       // (lv["h2"] > State.off) +        assert(lv["h0"] > State.off); +        assert(lv["h1"] > State.off); +        assert(lv["h2"] > State.off); +      } +      break; +    case "D": +      if (lv["h3"] == State.off) { +        assert(lv["h0"] > State.off); +        assert(lv["h1"] > State.off); +        assert(lv["h2"] > State.off); +      } else {                      // (lv["h3"] > State.off) +        assert(lv["h0"] > State.off); +        assert(lv["h1"] > State.off); +        assert(lv["h2"] > State.off); +        assert(lv["h3"] > State.off); +      } +      break; +    case "1": +      if (lv["h4"] == State.off) { +        assert(lv["h0"] > State.off); +      } else {                      // (lv["h4"] > State.off) +        assert(lv["h0"] > State.off); +        assert(lv["h4"] > State.off); +      } +      break; +    case "2": +      if (lv["h5"] == State.off) { +        assert(lv["h0"] > State.off); +        assert(lv["h4"] > State.off); +      } else {                      // (lv["h5"] > State.off) +        assert(lv["h0"] > State.off); +        assert(lv["h4"] > State.off); +        assert(lv["h5"] > State.off); +      } +      break; +    case "3": +      if (lv["h6"] == State.off) { +        assert(lv["h0"] > State.off); +        assert(lv["h4"] > State.off); +        assert(lv["h5"] > State.off); +      } else {                      // (lv["h6"] > State.off) +        assert(lv["h0"] > State.off); +        assert(lv["h4"] > State.off); +        assert(lv["h5"] > State.off); +        assert(lv["h6"] > State.off); +      } +      break; +    case "4": +      if (lv["h7"] == State.off) { +        assert(lv["h0"] > State.off); +        assert(lv["h4"] > State.off); +        assert(lv["h5"] > State.off); +        assert(lv["h6"] > State.off); +      } else {                      // (lv["h7"] > State.off) +        assert(lv["h0"] > State.off); +        assert(lv["h4"] > State.off); +        assert(lv["h5"] > State.off); +        assert(lv["h6"] > State.off); +        assert(lv["h7"] > State.off); +      } +      break; +    default: +      break; +    } +  } +  pure void assertions_flag_types_block_status_none_or_closed(T)(T obj_type_status) { +    debug(asserts) { +      static assert(is(typeof(obj_type_status) == int[string])); +    } +    assert( +      (obj_type_status["code"] == TriState.off) +      || (obj_type_status["code"] == TriState.closing), +      "code block status: off or closing"); +    assert( +      (obj_type_status["poem"] == TriState.off) +      || (obj_type_status["poem"] == TriState.closing), +      "poem status: off or closing"); +    assert( +      (obj_type_status["table"] == TriState.off) +      || (obj_type_status["table"] == TriState.closing), +      "table status: off or closing"); +    assert( +      (obj_type_status["group"] == TriState.off) +      || (obj_type_status["group"] == TriState.closing), +      "group block status: off or closing"); +    assert( +      (obj_type_status["block"] == TriState.off) +      || (obj_type_status["block"] == TriState.closing), +      "block status: off or closing"); +  } +  /+ abstraction functions assertions ↑ +/ +} /+ ← closed: template SiSUdocAbstraction +/ +template docSectKeysSeq() { +  auto docSectKeysSeq(string[][string] document_section_keys_sequenced) { +    struct doc_sect_keys_seq { +      auto seg() { +        return document_section_keys_sequenced["seg"]; +      } +      auto scroll() { +        return document_section_keys_sequenced["scroll"]; +      } +      auto sql() { +        return document_section_keys_sequenced["sql"]; +      } +    } +    return doc_sect_keys_seq(); +  } +} diff --git a/src/doc_reform/meta/metadoc_summary.d b/src/doc_reform/meta/metadoc_summary.d new file mode 100644 index 0000000..f2e0632 --- /dev/null +++ b/src/doc_reform/meta/metadoc_summary.d @@ -0,0 +1,101 @@ +module doc_reform.meta.metadoc_summary; +template SiSUabstractionSummary() { +  auto SiSUabstractionSummary(S,T)( +    auto ref const S  doc_abstraction, +    auto ref       T  doc_matters, +  ) { +    import +      doc_reform.meta.defaults, +      doc_reform.meta.rgx; +    import +      std.array, +      std.exception, +      std.regex, +      std.stdio, +      std.string, +      std.traits, +      std.typecons, +      std.uni, +      std.utf, +      std.conv : to; +    mixin InternalMarkup; +    auto markup = InlineMarkup(); +    if (doc_matters.opt.action.verbose) { +      string[string] check = [ +        "last_object_number" : "NA [debug \"checkdoc\" not run]", +        "last_object_number_body"  : "0", +        "last_object_number_book_index" : "0", +      ]; +      foreach (k; doc_matters.xml.keys_seq.seg) { +        foreach (obj; doc_abstraction[k]) { +          if (obj.metainfo.is_of_part != "empty") { +            if (!empty(obj.metainfo.object_number)) { +              if (k == "body") { +                check["last_object_number_body"] = obj.metainfo.object_number; +              } +              if (!(obj.metainfo.object_number.empty)) { +                check["last_object_number"] = obj.metainfo.object_number; +              } +            } +            if (k == "bookindex_seg") { +              if (obj.metainfo.object_number_type == 2) { +                check["last_object_number_book_index"] = obj.metainfo.object_number_book_index; +              } +            } +          } +        } +      } +      auto min_repeat_number = 66; +      auto char_repeat_number = (doc_matters.conf_make_meta.meta.title_full.length +        + doc_matters.conf_make_meta.meta.creator_author.length + 4); +      char_repeat_number = (char_repeat_number > min_repeat_number) +      ? char_repeat_number +      : min_repeat_number; +      writefln( +        "%s\n\"%s\", %s\n%s\n%s\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n%30-s%10-d\n(%s: %s)\n%s", +        markup.repeat_character_by_number_provided("-", char_repeat_number), +        doc_matters.conf_make_meta.meta.title_full, +        doc_matters.conf_make_meta.meta.creator_author, +        doc_matters.src.filename, +        markup.repeat_character_by_number_provided("-", char_repeat_number), +        "length toc arr:", +        to!int(doc_abstraction["toc_seg"].length), +        "length doc_abstraction arr:", +        to!int(doc_abstraction["body"].length), +        "last doc body ocn:", +        to!int(check["last_object_number_body"]), +        "last object_number:", +        to!int(check["last_object_number"]), +        "length endnotes:",                                // subtract headings +        (doc_abstraction["endnotes"].length > 2) +        ? (to!int(doc_abstraction["endnotes"].length - 2)) +        : 0, +        "length glossary:", +        (doc_abstraction["glossary"].length > 1) +        ? (to!int(doc_abstraction["glossary"].length)) +        : 0, +        "length biblio:", +        (doc_abstraction["bibliography"].length > 1) +        ? (to!int(doc_abstraction["bibliography"].length)) +        : 0, +        "length bookindex:", +        (doc_abstraction["bookindex_seg"].length > 1) +        ? (to!int(doc_abstraction["bookindex_seg"].length)) +        : 0, +        "  last book idx ocn:", +        to!int(check["last_object_number_book_index"]), +        "length blurb:", +        (doc_abstraction["blurb"].length > 1) +        ? (to!int(doc_abstraction["blurb"].length)) +        : 0, +        "number of segments:", +        (doc_matters.xml.segnames.length > 1) +        ? (to!int(doc_matters.xml.segnames.length)) +        : 0, +        __FILE__, +        __LINE__, +        markup.repeat_character_by_number_provided("-", min_repeat_number), +      ); +    } +  } +} diff --git a/src/doc_reform/meta/object_setter.d b/src/doc_reform/meta/object_setter.d new file mode 100644 index 0000000..f481ec1 --- /dev/null +++ b/src/doc_reform/meta/object_setter.d @@ -0,0 +1,126 @@ +/++ +  object setter: +  setting of sisu objects for downstream processing +  meta_object_setter.d ++/ +module doc_reform.meta.object_setter; +template ObjectSetter() { +  /+ structs +/ +  struct DocObj_MetaInfo_ { +    string                 is_of_part                         = ""; // frontmatter, body, backmatter +    string                 is_of_section                      = ""; // toc, body, glossary, biography, book index, blurb +    string                 is_of_type                         = ""; // para, block ? +    string                 is_a                               = ""; // heading, para, table, code block, group, ... +    alias                  of_part                            = is_of_part; +    alias                  of_section                         = is_of_section; +    alias                  is_of                              = is_of_type; +    /+ o_n +/ +    int                    o_n_substantive                    = 0; +    int                    o_n_non_substantive                = 0; +    int                    o_n_glossary                       = 0; +    int                    o_n_bibliography                   = 0; +    int                    o_n_book_index                     = 0; +    int                    o_n_blurb                          = 0; +    string object_number_substantive() const @property { +      return (o_n_substantive==0) ? "" : o_n_substantive.to!string; +    } +    string object_number_non_substantive() const @property { +      return (o_n_non_substantive==0) ? "" : o_n_non_substantive.to!string; +    } +    string object_number_glossary() const @property { +      return (o_n_glossary==0) ? "" : o_n_glossary.to!string; +    } +    string object_number_bibliography() const @property { +      return (o_n_bibliography==0) ? "" : o_n_bibliography.to!string; +    } +    string object_number_book_index() const @property { +      return (o_n_book_index==0) ? "" : o_n_book_index.to!string; +    } +    string object_number_blurb() const @property { +      return (o_n_blurb==0) ? "" : o_n_blurb.to!string; +    } +    string                 object_number_off                  = ""; +    bool                   visible_object_number              = false; +    // enum ONtype { none, substantive, non_substantive, glossary, bibliography, book_index, blurb, comment } +    int                    object_number_type                 = 0; // { ocn, non, bkidx } +    /+ node +/ +    string[string][string] node; +    int                    ocn                                = 0; +    string object_number() const @property { +      return (ocn==0) ? "" : ocn.to!string; +    } +    int                    o_n_type                           = 0; +    int                    heading_lev_markup                 = 9; +    int                    heading_lev_collapsed              = 9; +    string marked_up_level() const @property { +      string _out; +      switch (heading_lev_markup) { +      case 0: _out = "A"; break; +      case 1: _out = "B"; break; +      case 2: _out = "C"; break; +      case 3: _out = "D"; break; +      case 4: _out = "1"; break; +      case 5: _out = "2"; break; +      case 6: _out = "3"; break; +      case 7: _out = "4"; break; +      default: _out = ""; break; +      } +      return _out; +    } +    int[]                  markedup_ancestors                  = [ 0, 0, 0, 0, 0, 0, 0, 0,]; +    int[]                  collapsed_ancestors                 = [ 0, 0, 0, 0, 0, 0, 0, 0,]; +    int[]                  dom_structure_markedup_tags_status  = [ 0, 0, 0, 0, 0, 0, 0, 0,]; +    int[]                  dom_structure_collapsed_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0,]; +    int                    parent_lev_markup                   = 0; +    int                    parent_ocn                          = 0; +    int                    last_decendant_ocn                  = 0; +  } +  struct DocObj_TxtAttrib_ { +    int                    indent_base                         = 0; +    int                    indent_hang                         = 0; +    bool                   bullet                              = false; +    string                 language                            = ""; // not implemented, consider +  } +  struct DocObj_Has_ {                                         // has +    bool                   inline_links                        = false; +    bool                   inline_notes_reg                    = false; +    bool                   inline_notes_star                   = false; +    bool                   contains_image_without_dimensions   = false; +  } +  struct DocObj_Table_ { +    int                    number_of_columns                   = 0; +    double[]               column_widths                       = []; +    string[]               column_aligns                       = []; +    bool                   heading                             = false; +    bool                   walls                               = false; // not implemented +  } +  struct DocObj_CodeBlock_ { +    string                 syntax                              = ""; +  } +  struct DocObj_Pointer_ { +    int                    doc_object                          = 0; +    int                    html_segnames                       = 0; +    int                    heading                             = 0; +  } +  struct DocObj_Tags_ { +    string[]               heading_ancestors_text              = [ "", "", "", "", "", "", "", "", ]; // TODO redundant? see markedup and collapsed ancestors DONE +    string                 segment_anchor_tag                  = ""; +    string                 segname_prev                        = ""; +    string                 segname_next                        = ""; +    string[]               lev4_subtoc                         = []; +    string[]               anchor_tags                         = []; +  } +  struct ObjGenericComposite { +    string                 text                                = ""; +    DocObj_MetaInfo_       metainfo; +    DocObj_TxtAttrib_      attrib; +    DocObj_Tags_           tags; +    DocObj_Has_            has; +    DocObj_Table_          table; +    DocObj_CodeBlock_      code_block; +    DocObj_Pointer_        ptr; +  } +  struct TheObjects { +    ObjGenericComposite[] oca; +  } +} diff --git a/src/doc_reform/meta/package.d b/src/doc_reform/meta/package.d new file mode 100644 index 0000000..2981b6a --- /dev/null +++ b/src/doc_reform/meta/package.d @@ -0,0 +1,17 @@ +module doc_reform.meta; +public import +  doc_reform.meta.defaults, +  doc_reform.meta.rgx; +/+ std +/ +public import +  std.array, +  std.exception, +  std.range, +  std.regex, +  std.stdio, +  std.string, +  std.traits, +  std.typecons, +  // std.uni, +  std.utf, +  std.conv : to; diff --git a/src/doc_reform/meta/rgx.d b/src/doc_reform/meta/rgx.d new file mode 100644 index 0000000..63bb4ee --- /dev/null +++ b/src/doc_reform/meta/rgx.d @@ -0,0 +1,290 @@ +/++ +  regex: regular expressions used in sisu document parser ++/ +module doc_reform.meta.rgx; +static template SiSUrgxInit() { +  import doc_reform.meta.defaults; +  static struct Rgx { +    /+ misc +/ +    static true_dollar                                    = ctRegex!(`\$`, "gm"); +    static flag_action                                    = ctRegex!(`^(--[a-z][a-z0-9-]+)$`); +    static flag_action_str                                = ctRegex!(` (--[a-z][a-z0-9-]+)`); +    static within_quotes                                  = ctRegex!(`"(.+?)"`); +    static make_heading_delimiter                         = ctRegex!(`[;][ ]*`); +    static arr_delimiter                                  = ctRegex!(`[ ]*[;][ ]*`); +    static name_delimiter                                 = ctRegex!(`^([^,]+)[ ]*,[ ]+(.+?)$`); +    static book_index_go                                  = ctRegex!("(?P<link>(?P<ocn>[0-9]+)(?:-[0-9]+)?)"); +    static book_index_go_scroll                           = ctRegex!("(?P<link>(?P<ocn>[0-9]+)(?:-[0-9]+)?)"); +    static book_index_go_seg                              = ctRegex!("(?P<link>(?P<ocn>[0-9]+)(?:-[0-9]+)?):(?P<seg>[a-z0-9_-]+)"); +    static book_index_go_seg_                             = ctRegex!("(?P<link>(?P<ocn>[0-9]+)(?:-[0-9]+)?)(:(?P<seg>[a-z0-9_-]+))?"); +    static book_index_go_seg_anchorless                   = ctRegex!("(?P<link>(?P<ocn>[0-9]+)(?:-[0-9]+)?)"); +    static trailing_comma                                 = ctRegex!(",[ ]*$"); +    static trailing_linebreak                             = ctRegex!(",[ ]{1,2}\\\\\\\\\n[ ]{4}$","m"); +    static newline_eol_delimiter                          = ctRegex!("\n"); +    static newline_eol_strip_preceding                    = ctRegex!("[ ]*\n"); +    static newline_eol_delimiter_only                     = ctRegex!("^\n"); +    static line_delimiter_ws_strip                        = ctRegex!("[ ]*\n[ ]*"); +    static para_delimiter                                 = ctRegex!("\n[ ]*\n+"); +    static table_col_delimiter                            = ctRegex!("[ ]*\n+", "mg"); +    static table_row_delimiter                            = ctRegex!("\n[ ]*\n+", "mg"); +    static table_row_delimiter_special                    = ctRegex!("[ ]*\n", "mg"); +    static table_col_delimiter_special                    = ctRegex!("[ ]*[|][ ]*", "mg"); +    static levels_markup                                  = ctRegex!(`^[A-D1-4]$`); +    static levels_numbered                                = ctRegex!(`^[0-9]$`); +    static levels_numbered_headings                       = ctRegex!(`^[0-7]$`); +    static numeric                                        = ctRegex!(`[ 0-9,.-]+`); +    static numeric_col                                    = ctRegex!(`^[ 0-9,.$£₤Є€€¥-]+$`); +    /+ comments +/ +    static comment                                        = ctRegex!(`^%+ `); +    static comments                                       = ctRegex!(`^%+ |^%+$`); +    /+ header +/ +    static make_simple_substitutions_rb                   = ctRegex!(`(?P<substitution>/(?P<match>.+?)/,[ ]*['"](?P<replace>.+?)['"])`); +    static make_simple_substitutions_d                    = ctRegex!(`(?P<substitution>` ~ '`' ~ `(?P<match>.+?)` ~ '`' ~ `,[ ]*['"](?P<replace>.+?)['"])`); +    /+ header +/ +    static main_headers                                   = +      ctRegex!(`^(?:creator|title|rights|date|original|classify|identifier|notes|publisher|make|links)$`, "m"); +    static native_header                                  = ctRegex!(`^@([a-z_]+):(?:\s|$)`); +    static native_header_make                             = ctRegex!(`^@(make):(?:\s|$)`); +    static native_header_meta                             = +      ctRegex!(`^@(?:creator|title|rights|date|original|classify|identifier|notes|publisher|links):(?:\s|$)`); +    static native_header_main                             = ctRegex!(`^@(?P<header>[a-z_]+):\s*(?P<content>.*)`, "m"); +    static native_header_sub                              = ctRegex!(`^[ ]*:(?P<subheader>[a-z_]+):\s+(?P<content>.+)`, "m"); +    static native_header_meta_title                       = ctRegex!(`^@title:\s`, "m"); +    static variable_doc_title                             = ctRegex!(`@title`); +    static variable_doc_author                            = ctRegex!(`@author|@creator`); +    static raw_author_munge                               = ctRegex!(`(\S.+?),\s+(.+)`,"i"); +    static toml_header_meta_title                         = ctRegex!(`^\s*(title\s*=\s*"|\[title\])`, "m"); +    /+ head +/ +    static native_subhead_creator                         = ctRegex!(`^(?:author|translator|illustrator)$`, "m"); +    static native_subhead_title                           = ctRegex!(`^(?:main|sub(?:title)?|full|language|edition|note)$`, "m"); +    static native_subhead_rights                          = ctRegex!(`^(?:copyright|illustrations|license|cover)$`, "m"); +    static native_subhead_date                            = ctRegex!(`^(?:published|created|issued|available|valid|modified|added_to_site)$`, "m"); +    static native_subhead_original                        = ctRegex!(`^(?:title|language|source)$`, "m"); +    static native_subhead_classify                        = ctRegex!(`^(?:topic_register|subject|keywords|loc|dewey)$`, "m"); +    static native_subhead_identifier                      = ctRegex!(`^(?:oclc|pg|isbn)$`, "m"); +    static native_subhead_notes                           = ctRegex!(`^(?:abstract|description)$`, "m"); +    static native_subhead_publisher                       = ctRegex!(`^(?:name)$`, "m"); +    static native_subhead_make                            = ctRegex!(`^(?:cover_image|home_button_image|home_button_text|footer|headings|num_top|auto_num_depth|breaks|substitute|bold|italics|emphasis|texpdf_font|css)$`, "m"); +    /+ heading & paragraph operators +/ +    static heading_a                                      = ctRegex!(`^:?[A][~] `, "m"); +    static heading                                        = ctRegex!(`^:?([A-D1-4])[~]([a-z0-9_.-]*[?]?)\s+`,"i"); +    static heading_seg_and_above                          = ctRegex!(`^:?([A-D1])[~]([a-z0-9_.-]*[?]?)\s+`,"i"); +    static heading_marker                                 = ctRegex!(`^:?([A-D1-4])[~]`); +    static heading_anchor_tag                             = ctRegex!(`^:?[A-D1-4][~]([a-z0-9_.-]+) `,"i"); +    static heading_identify_anchor_tag                    = ctRegex!(`^:?[A-D1-4][~]\s+(?:(?:(?:chapter|article|section|clause)\s+[0-9.]+)|(?:[0-9]+))`,"i"); +    static heading_extract_named_anchor_tag               = ctRegex!(`^:?[A-D1-4][~]\s+(chapter|article|section|clause)\s+((?:[0-9]+[.:])*[0-9]+)(?:[.:;, ]|$)`,"i"); +    static heading_extract_unnamed_anchor_tag             = ctRegex!(`^:?[A-D1-4][~]\s+((?:[0-9]+.)*[0-9]+)(?:[.:;, ]|$)`); +    static heading_marker_missing_tag                     = ctRegex!(`^:?([A-D1-4])[~] `); +    static heading_anchor_tag_plus_colon                  = ctRegex!(`^:?([A-D1-4][~])([a-z0-9_.:-]+) `,"i"); +    static heading_marker_tag_has_colon                   = ctRegex!(`([:])`); +    static heading_title                                  = ctRegex!(`^:?[A-D1-4][~][a-z0-9_.-]*[?]?\s+(.+?)$`); +    static heading_all                                    = ctRegex!(`^:?([A-D1-4])[~]([a-z0-9_.-]*[?]?)\s+(.+?)$`); +    static heading_backmatter                             = ctRegex!(`^:?1[~][!](glossary|bibliography|biblio|blurb)\s+`,"i"); +    static heading_biblio                                 = ctRegex!(`^:?(1)[~][!](biblio(?:graphy)?|references?)`); +    static heading_glossary                               = ctRegex!(`^:?(1)[~][!](glossary)`); +    static heading_blurb                                  = ctRegex!(`^:?(1)[~][!](blurb)`); +    static heading_biblio_glossary                        = ctRegex!(`^:?(?:(1)[~][!](?:(?:biblio(?:graphy)?|references?)|glossary)|[A-D1][~])`); +    static heading_biblio_blurb                           = ctRegex!(`^:?(?:(1)[~][!](?:(?:biblio(?:graphy)?|references?)|blurb)|[A-D1][~])`); +    static heading_blurb_glossary                         = ctRegex!(`^:?(?:(1)[~][!](?:blurb|glossary)|[A-D1][~])`); +    static para_bullet                                    = ctRegex!(`^_[*] `); +    static para_bullet_indent                             = ctRegex!(`^_([1-9])[*] `); +    static para_indent                                    = ctRegex!(`^_([1-9]) `); +    static para_indent_hang                               = ctRegex!(`^_([0-9])_([0-9]) `); +    static para_attribs                                   = ctRegex!(`^_(?:(?:[0-9])(?:_([0-9]))?|(?:[1-9])?[*]) `); +    /+ blocked markup +/ +    static block_open                                     = ctRegex!("^((code([.][a-z][0-9a-z_]+)?|poem|group|block|quote|table)[{].*?$)|^`{3} (code([.][a-z][0-9a-z_]+)?|poem|group|block|quote|table)|^[{]table(~h)?(?P<columns>(?:[ ]+[0-9]+;)+)[}]"); +    static block_poem_open                                = ctRegex!("^((poem[{].*?$)|`{3} poem)"); +    /+ blocked markup tics +/ +    static block_tic_open                                 = ctRegex!("^`{3} (code([.][a-z][0-9a-z_]+)?|poem|group|block|quote|table)"); // what of numbered code? +    static block_tic_code_open                            = ctRegex!("^`{3} (?:code)(?:[.]([a-z][0-9a-z_]+))?(?:[ ]+([#]))?"); // extract additional info +    static block_tic_poem_open                            = ctRegex!("^`{3} (poem)"); +    static block_tic_group_open                           = ctRegex!("^`{3} (group)"); +    static block_tic_block_open                           = ctRegex!("^`{3} (block)"); +    static block_tic_quote_open                           = ctRegex!("^`{3} (quote)"); +    static block_tic_table_open                           = ctRegex!("^`{3} table(.*)"); +    static block_tic_close                                = ctRegex!("^(`{3})$","m"); +    /+ blocked markup curly +/ +    static block_curly_open                               = ctRegex!(`^((code([.][a-z][0-9a-z_]+)?|poem|group|block|quote|table)[{].*?$)`); +    static block_curly_code_open                          = ctRegex!(`^(?:code(?:[.]([a-z][0-9a-z_]+))?[{]([#]?)\s*$)`); // extract additional info +    static block_curly_code_close                         = ctRegex!(`^([}]code)`); +    static block_curly_poem_open                          = ctRegex!(`^(poem[{].*?$)`); +    static block_curly_poem_close                         = ctRegex!(`^([}]poem)`); +    static block_curly_group_open                         = ctRegex!(`^(group[{].*?$)`); +    static block_curly_group_close                        = ctRegex!(`^([}]group)`); +    static block_curly_block_open                         = ctRegex!(`^(block[{].*?$)`); +    static block_curly_block_close                        = ctRegex!(`^([}]block)`); +    static block_curly_quote_open                         = ctRegex!(`^(quote[{].*?$)`); +    static block_curly_quote_close                        = ctRegex!(`^([}]quote)`); +    static block_curly_table_open                         = ctRegex!(`^table[{](.*)`); +    static block_curly_table_close                        = ctRegex!(`^([}]table)`); +    static block_curly_table_special_markup               = ctRegex!(`^[{]table((~h)?(?P<columns>(?:[ ]+[0-9]+;)+))[}]`, "mg"); +    static table_head_instructions                        = ctRegex!(`(?P<c_heading>h)?(?:[ ]+c(?P<c_num>[0-9]);)?(?P<c_widths>(?:[ ]+[0-9]+[lr]?;)+)`); +    static table_col_widths_and_alignment                 = ctRegex!(`(?P<width>[0-9]+)(?P<align>[lr]?)`); +    static table_col_widths                               = ctRegex!(`(?P<widths>[0-9]+)`); +    static table_col_align                                = ctRegex!(`(?P<align>[lr]?)`); +    static table_col_align_match                          = ctRegex!(`(?P<align>[lr])`); +    static table_col_separator                            = ctRegex!(`┊`); +    static table_col_separator_nl                         = ctRegex!(`[┊]$`, "mg"); +    /+ inline markup footnotes endnotes +/ +    static inline_notes_curly_gen                         = ctRegex!(`~\{.+?\}~`, "m"); +    static inline_notes_curly                             = ctRegex!(`~\{\s*(.+?)\}~`, "mg"); +    static inline_curly_delimiter_open_and_close_regular  = ctRegex!(`~\{\s*|\s*\}~`, "m"); +    static inline_notes_delimiter_curly_regular           = ctRegex!(`~\{[ ]*(.+?)\}~`, "m"); +    static inline_notes_curly_sp                          = ctRegex!(`~\{[*+]+\s+(.+?)\}~`, "m"); +    static inline_notes_curly_sp_asterisk                 = ctRegex!(`~\{[*]+\s+(.+?)\}~`, "m"); +    static inline_notes_curly_sp_plus                     = ctRegex!(`~\{[+]+\s+(.+?)\}~`, "m"); +    static inline_note_curly_delimiters                   = ctRegex!(`(~\{[*+]?\s*)(.+?)(\}~)`, "mg"); +    static inline_notes_square                            = ctRegex!(`~\[\s*(.+?)\]~`, "mg"); +    static inline_text_and_note_square_sp                 = ctRegex!(`(.+?)~\[[*+]+\s+(.+?)\]~`, "mg"); +    static inline_text_and_note_square                    = ctRegex!(`(.+?)~\[\s*(.+?)\]~`, "mg"); +    static inline_note_square_delimiters                  = ctRegex!(`(~\[\s*)(.+?)(\]~)`, "mg"); +    static inline_curly_delimiter_open_regular            = ctRegex!(`~\{\s*`, "m"); +    static inline_curly_delimiter_open_symbol_star        = ctRegex!(`~\{[*]\s`, "m"); +    static inline_curly_delimiter_open_symbol_plus        = ctRegex!(`~\{[+]\s`, "m"); +    static inline_curly_delimiter_open_star_or_plus       = ctRegex!(`~\{[+*]`, "m"); +    static inline_curly_delimiter_close_regular           = ctRegex!(`\s*\}~`, "m"); +    static inline_text_and_note_curly                     = ctRegex!(`(?P<text>.+?)(?:(?:[~])[{][*+ ]*)(?P<note>.+?)(?:[}][~])`, "mg"); +    static note_ref                                       = ctRegex!(`^\S+?noteref_([0-9]+)`, "mg");     // {^{73.}^}#noteref_73 +    static smid_inline_url_generic                        = ctRegex!(`(?:^|[}(\[ ])(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_#]`, "mg"); +    static smid_inline_url                                = ctRegex!(`((?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_]\S*)`, "mg"); +    static smid_inline_link_naked_url                     = ctRegex!(`(?P<pre>^|[ ])(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤)\S+?)(?P<post>[.,;:?!'"]?(?:[ ]|$))`, "mg"); // issue with #link #32 +    static smid_inline_link_markup_regular                = ctRegex!(`(?P<pre>^|[ ]|[^\S]?)\{\s*(?P<content>.+?)\s*\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<post>[;:!,?.]?(?:[ )\]]|$))`, "mg"); // NEXT +    static smid_inline_link_endnote_url_helper_punctuated = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!]?(?:[ ]|$))`, "mg"); +    static smid_inline_link_endnote_url_helper            = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+)`, "mg"); +    static image                                           = ctRegex!(`([a-zA-Z0-9._-]+?\.(?:png|gif|jpg))`, "mg"); +    static smid_image_generic                              = ctRegex!(`(?:^|[ ]|[^\S]?)\{(?:~\^\s+|\s*)\S+\.(?:png|gif|jpg).+?\}(?:image|(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)[;:!,?.]?(?:[ )\]]|$)`, "mg"); +    static smid_image_with_dimensions                      = ctRegex!(`(?P<pre>(?:^|[ ]|[^\S]?)\{(?:~\^\s+|\s*))(?P<image>\S+\.(?:png|gif|jpg))\s+(?P<width>\d+)x(?P<height>\d+)\s*(?P<post>(?:.+?)\s*\}(?:image|(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?:[;:!,?.]?(?:[ )\]]|$)))`, "mg"); +    static smid_image                                      = ctRegex!(`(?P<pre>(?:^|[ ]|[^\S]?)\{(?:~\^\s+|\s*))(?P<image>\S+\.(?:png|gif|jpg))\s*(?P<post>(?:.+?)\s*\}(?:image|(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?:[;:!,?.]?(?:[ )\]]|$)))`, "mg"); +    static smid_mod_image_without_dimensions               = ctRegex!(`\{(?:~\^\s+|\s*)☼\S+\.(?:png|gif|jpg),w0h0\s+(?:.+?)\s*\}(?:image|(?:https?|git):\/\/\S+?)(?:[;:!,?.]?(?:[ )\]]|$))`, "mg"); +    /+ inline markup book index +/ +    static book_index                                     = ctRegex!(`^=\{\s*(.+?)\}$`, "m"); +    static book_index_open                                = ctRegex!(`^=\{\s*([^}]+?)$`); +    static book_index_close                               = ctRegex!(`^(.*?)\}$`, "m"); +    /+ no object_number object +/ +    static object_number_off                            = ctRegex!(`~#$`, "m"); +    static object_number_off_dh                         = ctRegex!(`-#$`, "m"); +    static object_number_off_all                        = ctRegex!(`[~-]#$`, "m"); +    /+ no object_number block +/ +    static object_number_off_block                      = ctRegex!(`^--~#$`); +    static object_number_off_block_dh                   = ctRegex!(`^---#$`); +    static object_number_off_block_close                = ctRegex!(`^--\+#$`); +    static object_number_block_marks                    = ctRegex!(`^--[+~-]#$`); +    /+ ignore outside code blocks +/ +    static skip_from_regular_parse    = ctRegex!(`^(--[+~-]#|-[\\]{2}-|=[.\\]{2}=)$`); +    /+ line & page breaks +/ +    static break_line_within_object                       = ctRegex!(`[\\]{2}( |$)`); +    static break_page                                     = ctRegex!(`^-[\\]{2}-$`); +    static break_page_new                                 = ctRegex!(`^=[\\]{2}=$`); +    static break_page_line_across                         = ctRegex!(`^=[.]{2}=$`); +    static break_string                                   = ctRegex!(`』`); +    static parent                                         = ctRegex!(`([0-7]):([0-9]+)`); +    static header_regex_content                           = ctRegex!(`([0-7]):([0-9]+)`); +    /+ json +/ +    static tailing_comma                                  = ctRegex!(`,$`, "m"); +    /+ biblio tags +/ +    static biblio_tags                                    = ctRegex!(`^(is|au|author_raw|author|author_arr|editor_raw|ed|editor_arr|ti|title|subtitle|fulltitle|lng|language|trans|src|jo|journal|in|vol|volume|edn|edition|yr|year|pl|place|pb|pub|publisher|url|pg|pages|note|short_name|id):\s+(.+)`); +    static biblio_abbreviations                           = ctRegex!(`^(au|ed|ti|lng|jo|vol|edn|yr|pl|pb|pub|pg|pgs|sn)$`); +    /+ bookindex split +/ +    static bi_main_terms_split                            = ctRegex!(`\s*;\s*`); +    static bi_main_term_plus_rest_split                   = ctRegex!(`\s*:\s*`); +    static bi_sub_terms_plus_object_number_offset_split = ctRegex!(`\s*\|\s*`); +    static bi_term_and_object_numbers_match             = ctRegex!(`^(.+?)\+(\d+)`); +    /+ language codes +/ +    auto language_codes                                    = +       ctRegex!("(am|bg|bn|br|ca|cs|cy|da|de|el|en|eo|es|et|eu|fi|fr|ga|gl|he|hi|hr|hy|ia|is|it|ja|ko|la|lo|lt|lv|ml|mr|nl|no|nn|oc|pl|pt|pt_BR|ro|ru|sa|se|sk|sl|sq|sr|sv|ta|te|th|tk|tr|uk|ur|vi|zh)"); +    auto language_code_and_filename                                    = +       ctRegex!("(?:^|[/])(am|bg|bn|br|ca|cs|cy|da|de|el|en|eo|es|et|eu|fi|fr|ga|gl|he|hi|hr|hy|ia|is|it|ja|ko|la|lo|lt|lv|ml|mr|nl|no|nn|oc|pl|pt|pt_BR|ro|ru|sa|se|sk|sl|sq|sr|sv|ta|te|th|tk|tr|uk|ur|vi|zh)/[A-Za-z0-9._-].+?[.](?:sst|ssm)$"); +    static newline                                        = ctRegex!("\n", "mg"); +    static strip_br                                       = ctRegex!("^<br>\n|<br>\n*$"); +    static space                                          = ctRegex!(`[ ]`, "mg"); +    static spaces_line_start                              = ctRegex!(`^(?P<opening_spaces>[ ]+)`, "mg"); +    static spaces_multiple                                = ctRegex!(`(?P<multiple_spaces>[ ]{2,})`, "mg"); +    static two_spaces                                     = ctRegex!(`[ ]{2}`, "mg"); +    static nbsp_char                                      = ctRegex!(`░`, "mg"); +    static nbsp_chars_line_start                          = ctRegex!(`^░+`, "mg"); +    static nbsp_and_space                                 = ctRegex!(` [ ]`, "mg"); +    static nbsp_char_and_space                            = ctRegex!(`░[ ]`, "mg"); +    static special_markup_chars                           = ctRegex!(`[【】〖〗┥┝┤├¤░┘┙┚┼┿╂┊┏┚┆■]`, "mg"); +    static src_pth_sst_or_ssm                             = ctRegex!(`^(?P<path>[/]?(?:[a-zA-Z0-9._-]+/)*)(?P<filename>[a-zA-Z0-9._-]+[.](?P<extension>ss[tm]))$`); +    static src_pth_pod_sst_or_ssm                         = ctRegex!(`^(?P<podpath>[/]?(?:[a-zA-Z0-9._-]+/)*)media/text/[a-z]{2}/(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])$`); +    static src_pth_contents                               = ctRegex!(`^(?P<path>[/]?(?:[a-zA-Z0-9._-]+/)*)(?P<filename>[a-zA-Z0-9._-]+)/sisupod[.]manifest$`); +    static src_pth_pod_root                               = ctRegex!(`^(?P<podroot>(?:[/]?(?:[a-zA-Z0-9._-]+/)*)(sisupod))$`); +    static src_pth_zip                                    = ctRegex!(`^(?P<path>[/]?(?:[a-zA-Z0-9._-]+/)*)(?P<filename>[a-zA-Z0-9._-]+[.]zip)$`); +    static src_pth_unzip_pod                              = ctRegex!(`^(?P<path>media/text/[a-z]{2}/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[im])$`); +    static src_pth_types                                  = +      ctRegex!(`^(?P<path>[/]?[a-zA-Z0-9._-]+/)*(?P<gotfile>(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])|(?P<filelist>[a-zA-Z0-9._-]+/sisupod[.]manifest)|(?P<filezip>[a-zA-Z0-9._-]+[.]zip))$`); +    static pod_content_location                           = +      ctRegex!(`^(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])(?P<languages>(?:\s+[a-z]{2}(?:,|$))+)`, "mg"); +    static src_fn                                         = +      ctRegex!(`^([/]?(?:[a-zA-Z0-9._-]+/)*)(?P<fn_src>(?P<fn_base>[a-zA-Z0-9._-]+)[.](?P<fn_src_suffix>ss[tm]))$`); +    static src_fn_master                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssm)$`); +    static src_fn_text                                    = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]sst)$`); +    static src_fn_insert                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssi)$`); +    static src_fn_find_inserts                            = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[im])$`); +    static insert_src_fn_ssi_or_sst                       = ctRegex!(`^<<\s*(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`); +    static src_base_parent_dir_name                       = ctRegex!(`[/](?P<dir>(?:[a-zA-Z0-9._-]+))(?:/media/text/[a-z]{2})$`); // formalizes dir structure +    static src_base_parent_path                           = ctRegex!(`(?P<dir>(?:[/a-zA-Z0-9._-]+))(?:/media/text/[a-z]{2})$`); // formalizes dir structure +    static src_formalised_file_path_parts                 = ctRegex!(`(?P<pth>(?:[/a-zA-Z0-9._-]+?)(?P<dir>[a-zA-Z0-9._-]+))(?:/media/text/[a-z]{2})$`); // formalizes dir structure +    /+ line breaks +/ +    static br_line                                        = ctRegex!(`┘`, "mg"); +    static br_nl                                          = ctRegex!(`┙`, "mg"); +    static br_paragraph                                   = ctRegex!(`┚`, "mg"); +    static br_page_line                                   = ctRegex!(`┼`, "mg"); +    static br_page                                        = ctRegex!(`┿`, "mg"); +    static br_page_new                                    = ctRegex!(`╂`, "mg"); +    /+ inline markup footnotes endnotes +/ +    static inline_notes_al                                = ctRegex!(`【(?:[*+]\s+|\s*)(.+?)】`, "mg"); +    static inline_notes_al_special                        = ctRegex!(`【(?:[*+]\s+)(.+?)】`, "mg"); // TODO remove match when special footnotes are implemented +    static inline_notes_al_gen                            = ctRegex!(`【.+?】`, "m"); +    static inline_notes_al_gen_text                       = ctRegex!(`【(?P<text>.+?)】`, "m"); +    static inline_notes_al_gen_ref                        = ctRegex!(`【(?P<ref>[*+]\s+)\s*(?P<text>.+?)】`, "mg"); +    static inline_al_delimiter_open_regular               = ctRegex!(`【\s`, "m"); +    static inline_al_delimiter_open_symbol_star           = ctRegex!(`【[*]\s`, "m"); +    static inline_al_delimiter_open_symbol_plus           = ctRegex!(`【[+]\s`, "m"); +    static inline_al_delimiter_close_regular              = ctRegex!(`】`, "m"); +    static inline_al_delimiter_open_and_close_regular     = ctRegex!(`【|】`, "m"); +    static inline_notes_delimiter_al_regular              = ctRegex!(`【(.+?)】`, "mg"); +    static inline_notes_delimiter_al_regular_number_note  = ctRegex!(`【(\d+)\s+(.+?)】`, "mg"); +    static inline_al_delimiter_open_asterisk              = ctRegex!(`【\*`, "m"); +    static inline_al_delimiter_open_plus                  = ctRegex!(`【\+`, "m"); +    static inline_text_and_note_al                        = ctRegex!(`(?P<text>.+?)【(?:[*+ ]*)(?P<note>.+?)】`, "mg"); +    static inline_text_and_note_al_                       = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|$))`, "mg"); +    /+ inline markup footnotes endnotes +/ +    static inline_image                                   = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>\S+?\.(?:jpg|gif|png)),w(?P<width>\d+)h(?P<height>\d+))\s*(?P<post>.*?┝┤.+?├)`, "mg"); +    static inline_image_without_dimensions                = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>\S+?\.(?:jpg|gif|png)),w(?P<width>0)h(?P<height>0))\s*(?P<post>.*?┝┤.+?├)`, "mg"); +    static inline_link                                    = ctRegex!(`┥(?P<text>.+?)┝┤(?P<link>.+?)├`, "mg"); +    static inline_link_clean                              = ctRegex!(`┤(?:.+?)├|[┥┝]`, "mg"); +    static inline_a_url                                   = ctRegex!(`(┤)(\S+?)(├)`, "mg"); +    static url                                            = ctRegex!(`https?://`, "mg"); +    static inline_link_subtoc                             = ctRegex!(`^(?P<level>[5-7])~ ┥(?P<text>.+?)┝┤(?P<link>.+?)├`, "mg"); +    static fn_suffix                                      = ctRegex!(`\.fnSuffix`, "mg"); +    static inline_link_fn_suffix                          = ctRegex!(`¤(.+?)(\.fnSuffix)`, "mg"); +    static inline_seg_link                                = ctRegex!(`(¤)(?:.+?)\.fnSuffix`, "mg"); +    static mark_internal_site_lnk                         = ctRegex!(`¤`, "mg"); +    static quotation_mark_sql_insert_delimiter            = ctRegex!("[']", "mg"); +    static quotation_mark_various                         = ctRegex!(q"¶['‘’“”"`´¨]¶", "mg"); +    /+ inline markup font face mod +/ +    static inline_faces                                   = ctRegex!(`(?P<markup>(?P<mod>[*!_^,+#-])\{(?P<text>.+?)\}[*!_^,+#-])`, "mg"); +    static inline_emphasis                                = ctRegex!(`\*\{(?P<text>.+?)\}\*`, "mg"); +    static inline_bold                                    = ctRegex!(`!\{(?P<text>.+?)\}!`, "mg"); +    static inline_underscore                              = ctRegex!(`_\{(?P<text>.+?)\}_`, "mg"); +    static inline_italics                                 = ctRegex!(`/\{(?P<text>.+?)\}/`, "mg"); +    static inline_superscript                             = ctRegex!(`\^\{(?P<text>.+?)\}\^`, "mg"); +    static inline_subscript                               = ctRegex!(`,\{(?P<text>.+?)\},`, "mg"); +    static inline_strike                                  = ctRegex!(`-\{(?P<text>.+?)\}-`, "mg"); +    static inline_insert                                  = ctRegex!(`\+\{(?P<text>.+?)\}\+`, "mg"); +    static inline_mono                                    = ctRegex!(`#\{(?P<text>.+?)\}#`, "mg"); +    static inline_mono_box                                = ctRegex!(`■\{(?P<text>.+?)\}■`, "mg"); +    static inline_cite                                    = ctRegex!(`"\{(?P<text>.+?)\}"`, "mg"); +    static inline_faces_line                              = ctRegex!(`^[*!/_]_ (?P<text>.+?)((?: [\\]{2}|[~]#){0,2}$)`); +    static inline_emphasis_line                           = ctRegex!(`^\*_ (?P<text>.+?)((?: [\\]{2}|[~]#){0,2}$)`); +    static inline_bold_line                               = ctRegex!(`^!_ (?P<text>.+?)((?: [\\]{2}|[~]#){0,2}$)`); +    static inline_italics_line                            = ctRegex!(`^/_ (?P<text>.+?)((?: [\\]{2}|[~]#){0,2}$)`); +    static inline_underscore_line                         = ctRegex!(`^__ (?P<text>.+?)((?: [\\]{2}|[~]#){0,2}$)`); +    static inline_fontface_clean                          = ctRegex!(`[*!_/^,+#■"-]\{|\}[*!_/^,+#■"-]`, "mg"); +    static no_header_rgx                                  = ctRegex!(`^=NULL$`); +    /+ table delimiters +/ +    static table_delimiter_col                           = ctRegex!("[ ]*[┊][ ]*", "mg"); +    static table_delimiter_row                           = ctRegex!("[ ]*\n", "mg"); +  } +} diff --git a/src/doc_reform/output/create_zip_file.d b/src/doc_reform/output/create_zip_file.d new file mode 100644 index 0000000..fa752ad --- /dev/null +++ b/src/doc_reform/output/create_zip_file.d @@ -0,0 +1,17 @@ +module doc_reform.output.create_zip_file; +template createZipFile() { +  import std.file; +  import std.outbuffer; +  import std.string; +  import std.zip; +  void createZipFile( +    string zip_file_name, +    void[] compressed_zip_data, +  ) { +    try { +      write(zip_file_name, compressed_zip_data); +    } catch (ZipException ex) { +      // Handle Errors +    } +  } +} diff --git a/src/doc_reform/output/defaults.d b/src/doc_reform/output/defaults.d new file mode 100644 index 0000000..97ba691 --- /dev/null +++ b/src/doc_reform/output/defaults.d @@ -0,0 +1,123 @@ +/++ +  default settings ++/ +module doc_reform.output.defaults; + +template InternalMarkup() { +  import std.array; +  static struct InlineMarkup { +    auto en_a_o = "【";      auto en_a_c = "】"; +    auto en_b_o = "〖";      auto en_b_c = "〗"; +    auto lnk_o = "┥";        auto lnk_c = "┝"; +    auto url_o = "┤";        auto url_c = "├"; +    auto mark_internal_site_lnk = "¤"; +    auto nbsp = "░"; +    auto br_line = "┘"; +    auto br_nl = "┙"; +    auto br_paragraph = "┚"; +    auto br_obj = "break_obj"; +    auto br_page_line = "┼"; +    auto br_page = "┿"; +    auto br_page_new = "╂"; +    auto tc_s = "┊"; +    auto tc_o = "┏"; +    auto tc_c = "┚"; +    auto tc_p = "┆"; +    auto mono = "■"; +    auto img = "☼"; +    static string indent_by_spaces_provided(int indent, string _indent_spaces ="░░") { +      _indent_spaces = replicate(_indent_spaces, indent); +      return _indent_spaces; +    } +    static string repeat_character_by_number_provided(C,N)(C _character ="-", N number=10) { +      _character = replicate(_character, number); +      return _character; +    } +  } +} +template SiSUlanguageCodes() { +  /+ language codes +/ +  struct Lang { +    static string[string][string] codes() { +      auto _lang_codes = [ +        "am":    [ "c": "am",    "n": "Amharic",           "t": "Amharic",                   "xlp": "amharic"      ], +        "bg":    [ "c": "bg",    "n": "Bulgarian",         "t": "Български (Bəlgarski)",     "xlp": "bulgarian"    ], +        "bn":    [ "c": "bn",    "n": "Bengali",           "t": "Bengali",                   "xlp": "bengali"      ], +        "br":    [ "c": "br",    "n": "Breton",            "t": "Breton",                    "xlp": "breton"       ], +        "ca":    [ "c": "ca",    "n": "Catalan",           "t": "catalan",                   "xlp": "catalan"      ], +        "cs":    [ "c": "cs",    "n": "Czech",             "t": "česky",                     "xlp": "czech"        ], +        "cy":    [ "c": "cy",    "n": "Welsh",             "t": "Welsh",                     "xlp": "welsh"        ], +        "da":    [ "c": "da",    "n": "Danish",            "t": "dansk",                     "xlp": "danish"       ], +        "de":    [ "c": "de",    "n": "German",            "t": "Deutsch",                   "xlp": "german"       ], +        "el":    [ "c": "el",    "n": "Greek",             "t": "Ελληνικά (Ellinika)",       "xlp": "greek"        ], +        "en":    [ "c": "en",    "n": "English",           "t": "English",                   "xlp": "english"      ], +        "eo":    [ "c": "eo",    "n": "Esperanto",         "t": "Esperanto",                 "xlp": "esperanto"    ], +        "es":    [ "c": "es",    "n": "Spanish",           "t": "español",                   "xlp": "spanish"      ], +        "et":    [ "c": "et",    "n": "Estonian",          "t": "Estonian",                  "xlp": "estonian"     ], +        "eu":    [ "c": "eu",    "n": "Basque",            "t": "basque",                    "xlp": "basque"       ], +        "fi":    [ "c": "fi",    "n": "Finnish",           "t": "suomi",                     "xlp": "finnish"      ], +        "fr":    [ "c": "fr",    "n": "French",            "t": "français",                  "xlp": "french"       ], +        "ga":    [ "c": "ga",    "n": "Irish",             "t": "Irish",                     "xlp": "irish"        ], +        "gl":    [ "c": "gl",    "n": "Galician",          "t": "Galician",                  "xlp": "galician"     ], +        "he":    [ "c": "he",    "n": "Hebrew",            "t": "Hebrew",                    "xlp": "hebrew"       ], +        "hi":    [ "c": "hi",    "n": "Hindi",             "t": "Hindi",                     "xlp": "hindi"        ], +        "hr":    [ "c": "hr",    "n": "Croatian",          "t": "Croatian",                  "xlp": "croatian"     ], +        "hy":    [ "c": "hy",    "n": "Armenian",          "t": "Armenian",                  "xlp": "armenian"     ], +        "ia":    [ "c": "ia",    "n": "Interlingua",       "t": "Interlingua",               "xlp": "interlingua"  ], +        "is":    [ "c": "is",    "n": "Icelandic",         "t": "Icelandic",                 "xlp": "icelandic"    ], +        "it":    [ "c": "it",    "n": "Italian",           "t": "Italiano",                  "xlp": "italian"      ], +        "ja":    [ "c": "ja",    "n": "Japanese",          "t": "日本語 (Nihongo)",         "xlp": "japanese"      ], +        "ko":    [ "c": "ko",    "n": "Korean",            "t": "Korean",                    "xlp": "korean"       ], +        "la":    [ "c": "la",    "n": "Latin",             "t": "Latin",                     "xlp": "latin"        ], +        "lo":    [ "c": "lo",    "n": "Lao",               "t": "Lao",                       "xlp": "lao"          ], +        "lt":    [ "c": "lt",    "n": "Lithuanian",        "t": "Lithuanian",                "xlp": "lithuanian"   ], +        "lv":    [ "c": "lv",    "n": "Latvian",           "t": "Latvian",                   "xlp": "latvian"      ], +        "ml":    [ "c": "ml",    "n": "Malayalam",         "t": "Malayalam",                 "xlp": "malayalam"    ], +        "mr":    [ "c": "mr",    "n": "Marathi",           "t": "Marathi",                   "xlp": "marathi"      ], +        "nl":    [ "c": "nl",    "n": "Dutch",             "t": "Nederlands",                "xlp": "dutch"        ], +        "no":    [ "c": "no",    "n": "Norwegian",         "t": "norsk",                     "xlp": "norsk"        ], +        "nn":    [ "c": "nn",    "n": "Norwegian Nynorsk", "t": "nynorsk",                   "xlp": "nynorsk"      ], +        "oc":    [ "c": "oc",    "n": "Occitan",           "t": "Occitan",                   "xlp": "occitan"      ], +        "pl":    [ "c": "pl",    "n": "Polish",            "t": "polski",                    "xlp": "polish"       ], +        "pt":    [ "c": "pt",    "n": "Portuguese",        "t": "Português",                 "xlp": "portuges"     ], +        "pt_BR": [ "c": "pt_BR", "n": "Portuguese Brazil", "t": "Brazilian Português",       "xlp": "brazilian"    ], +        "ro":    [ "c": "ro",    "n": "Romanian",          "t": "română",                    "xlp": "romanian"     ], +        "ru":    [ "c": "ru",    "n": "Russian",           "t": "Русский (Russkij)",         "xlp": "russian"      ], +        "sa":    [ "c": "sa",    "n": "Sanskrit",          "t": "Sanskrit",                  "xlp": "sanskrit"     ], +        "se":    [ "c": "se",    "n": "Sami",              "t": "Samin",                     "xlp": "samin"        ], +        "sk":    [ "c": "sk",    "n": "Slovak",            "t": "slovensky",                 "xlp": "slovak"       ], +        "sl":    [ "c": "sl",    "n": "Slovenian",         "t": "Slovenian",                 "xlp": "slovenian"    ], +        "sq":    [ "c": "sq",    "n": "Albanian",          "t": "Albanian",                  "xlp": "albanian"     ], +        "sr":    [ "c": "sr",    "n": "Serbian",           "t": "Serbian",                   "xlp": "serbian"      ], +        "sv":    [ "c": "sv",    "n": "Swedish",           "t": "svenska",                   "xlp": "swedish"      ], +        "ta":    [ "c": "ta",    "n": "Tamil",             "t": "Tamil",                     "xlp": "tamil"        ], +        "te":    [ "c": "te",    "n": "Telugu",            "t": "Telugu",                    "xlp": "telugu"       ], +        "th":    [ "c": "th",    "n": "Thai",              "t": "Thai",                      "xlp": "thai"         ], +        "tk":    [ "c": "tk",    "n": "Turkmen",           "t": "Turkmen",                   "xlp": "turkmen"      ], +        "tr":    [ "c": "tr",    "n": "Turkish",           "t": "Türkçe",                    "xlp": "turkish"      ], +        "uk":    [ "c": "uk",    "n": "Ukranian",          "t": "українська (ukrajins\"ka)", "xlp": "ukrainian"    ], +        "ur":    [ "c": "ur",    "n": "Urdu",              "t": "Urdu",                      "xlp": "urdu"         ], +        "us":    [ "c": "en",    "n": "English (American)","t": "English",                   "xlp": "english"      ], +        "vi":    [ "c": "vi",    "n": "Vietnamese",        "t": "Vietnamese",                "xlp": "vietnamese"   ], +        "zh":    [ "c": "zh",    "n": "Chinese",           "t": "中文",                     "xlp": "chinese"       ], +        "en":    [ "c": "en",    "n": "English",           "t": "English",                   "xlp": "english"      ], +        "xx":    [ "c": "xx",    "n": "Default",           "t": "English",                   "xlp": "english"      ], +      ]; +      return _lang_codes; +    } +    static string[] code_arr_ptr() { +      auto _lang_codes = ["am", "bg", "bn", "br", "ca", "cs", "cy", "da", "de", "el", "en", "eo", "es", "et", "eu", "fi", "fr", "ga", "gl", "he", "hi", "hr", "hy", "ia", "is", "it", "ja", "ko", "la", "lo", "lt", "lv", "ml", "mr", "nl", "no", "nn", "oc", "pl", "pt", "pt_BR", "ro", "ru", "sa", "se", "sk", "sl", "sq", "sr", "sv", "ta", "te", "th", "tk", "tr", "uk", "ur", "us", "vi", "zh", "en", "xx",]; +      return _lang_codes; +    } +    static string[] code_arr() { +      auto _lang_codes = ["am", "bg", "bn", "br", "ca", "cs", "cy", "da", "de", "el", "en", "eo", "es", "et", "eu", "fi", "fr", "ga", "gl", "he", "hi", "hr", "hy", "ia", "is", "it", "ja", "ko", "la", "lo", "lt", "lv", "ml", "mr", "nl", "no", "nn", "oc", "pl", "pt", "pt_BR", "ro", "ru", "sa", "se", "sk", "sl", "sq", "sr", "sv", "ta", "te", "th", "tk", "tr", "uk", "ur", "vi", "zh"]; +      return _lang_codes; +    } +    static auto codes_() { +      return "(" ~ join(code_arr,"|") ~ ")"; +    } +    static auto codes_regex() { +      return regex(codes_); +    } +  } +} diff --git a/src/doc_reform/output/epub3.d b/src/doc_reform/output/epub3.d new file mode 100644 index 0000000..45e632a --- /dev/null +++ b/src/doc_reform/output/epub3.d @@ -0,0 +1,782 @@ +module doc_reform.output.epub3; +template outputEPub3() { +  import doc_reform.output; +  import +    std.digest.sha, +    std.file, +    std.outbuffer, +    std.zip, +    std.conv : to; +  import +    doc_reform.output.create_zip_file, +    doc_reform.output.xmls, +    doc_reform.output.xmls_css; +  mixin InternalMarkup; +  mixin outputXHTMLs; +  string epub3_mimetypes() { +    string o; +    o = format(q"¶application/epub+zip¶") ~ "\n"; +    return o; +  } +  string epub3_container_xml() { +    string o; +    o = format(q"¶<?xml version='1.0' encoding='utf-8'?>¶") ~ "\n"; +    o ~= format(q"¶<container version="1.0" +  xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> +  <rootfiles> +    <rootfile full-path="OEBPS/content.opf" +      media-type="application/oebps-package+xml" /> +  </rootfiles>¶") ~ "\n</container>\n"; +    return o; +  } +  string epub3_oebps_content(D,M,P)(D doc_abstraction, M doc_matters, P parts) { +    auto xhtml_format = outputXHTMLs(); +    auto pth_epub3 = SiSUpathsEPUB!()(doc_matters.output_path, doc_matters.src.language); +    string uuid = "18275d951861c77f78acd05672c9906924c59f18a2e0ba06dad95959693e9bd8"; // TODO sort uuid in doc_matters! +    string content = format(q"¶  <?xml version='1.0' encoding='utf-8'?> +  <package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="EPB-UUID"> +    <metadata +      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +      xmlns:dcterms="http://purl.org/dc/terms/" +      xmlns:dc="http://purl.org/dc/elements/1.1/" +      unique-identifier="urn:uuid:%s" version="2.0"> +      <!-- <dc:title id="title">%s</dc:title> --> +      <dc:title id="title">%s</dc:title> +      <meta refines="#title" property="title-type">main</meta> +      <dc:title id="subtitle">%s</dc:title> +      <meta refines="#subtitle" property="title-type">subtitle</meta> +      <dc:creator file-as="%s" id="aut">%s</dc:creator> +      <dc:language>%s</dc:language> +      <dc:date id="published">%s</dc:date> +      <dc:rights>Copyright: %s</dc:rights> +      <dc:identifier scheme="URI">%s</dc:identifier> +      <dc:identifier id="bookid">urn:uuid:%s</dc:identifier> +      <!-- <dc:identifier id="EPB-UUID">urn:uuid:%s</dc:identifier> --> +    </metadata> +    <manifest> +      <!-- NCX epub2 navigation --> +        <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" /> +      <!-- CSS Style Sheets --> +        <link rel="stylesheet" href="%s" type="text/css" id="main-css" /> +      <!-- nav epub3 navigation --> +        <item id="nav" href="toc_nav.xhtml" media-type="application/xhtml+xml" properties="nav" /> +  ¶", +      uuid, +      xhtml_format.special_characters_text(doc_matters.conf_make_meta.meta.title_full), +      xhtml_format.special_characters_text(doc_matters.conf_make_meta.meta.title_main), +      (doc_matters.conf_make_meta.meta.title_sub.empty) +        ? "" : xhtml_format.special_characters_text(doc_matters.conf_make_meta.meta.title_sub), +      (doc_matters.conf_make_meta.meta.creator_author.empty) +        ? "" : xhtml_format.special_characters_text(doc_matters.conf_make_meta.meta.creator_author), +      (doc_matters.conf_make_meta.meta.creator_author.empty) +        ? "" : xhtml_format.special_characters_text(doc_matters.conf_make_meta.meta.creator_author), +      doc_matters.src.language,                                   // language, fix (needed in dochead metadata) +      (doc_matters.conf_make_meta.meta.date_published.empty) +        ? "" : xhtml_format.special_characters_text(doc_matters.conf_make_meta.meta.date_published), +      (doc_matters.conf_make_meta.meta.rights_copyright.empty) +        ? "" : xhtml_format.special_characters_text(doc_matters.conf_make_meta.meta.rights_copyright), +      uuid, +      uuid, +      uuid, +      (pth_epub3.fn_oebps_css(doc_matters.src.filename)).chompPrefix("OEBPS/"), +    ); +    content ~= "    " ~ "<!-- Content Documents -->" ~ "\n  "; +    content ~= parts["manifest_documents"]; +    // TODO sort jpg & png +    content ~= "    " ~ "<!-- Images -->" ~ "\n  "; +    foreach (image; doc_matters.srcs.image_list) { +      content ~= format(q"¶      <item id="%s" href="%s/%s" media-type="image/%s" /> +  ¶", +        image.baseName.stripExtension, +        (pth_epub3.doc_oebps_image(doc_matters.src.filename)).chompPrefix("OEBPS/"), +        image, +        image.extension.chompPrefix("."), +      ); +    } +    content ~= "  " ~ "</manifest>"         ~ "\n  "; +    content ~= "  " ~ "<spine toc=\"ncx\">" ~ "\n  "; +    content ~= parts["spine"]; +    content ~= "  " ~ "</spine>"            ~ "\n  "; +    content ~= "  " ~ "<guide>"             ~ "\n  "; +    content ~= parts["guide"]; +    content ~= "  " ~ "</guide>"            ~ "\n  "; +    content ~= ""   ~ "</package>"; +    debug(epubmanifest) { +      foreach (s; doc_matters.xml.keys_seq.seg) { +        foreach (obj; doc_abstraction[s]) { +          if (obj.metainfo.is_a == "heading") { +            if (obj.metainfo.heading_lev_markup == 4) { +              writefln( +                "%s~ [%s.xhtml] %s", +                obj.marked_up_level, +                obj.tags.segment_anchor_tag, +                obj.text +              ); +            } else if (obj.metainfo.heading_lev_markup > 4) { +              writefln( +                "%s~ [%s.xhtml#%s] %s", +                obj.marked_up_level, +                obj.tags.segment_anchor_tag, +                obj.metainfo.object_number, +                obj.text +              ); +            } +          } +        } +      } +    } +    return content; +  } +  string epub3_oebps_toc_nav_xhtml(D,I)(D doc_abstraction, I doc_matters) { +    enum DomTags { none, open, close, close_and_open, open_still, } +    auto markup = InlineMarkup(); +    auto rgx = Rgx(); +    string toc =format("<html xmlns=\"http://www.w3.org/1999/xhtml\" +      xmlns:epub=\"http://www.idpf.org/2007/ops\"> +  <head> +    <title>%s</title> +  </head> +  <body> +    <section epub:type=\"frontmatter toc\"> +      <header> +        <h1>Contents</h1> +      </header> +      <nav epub:type=\"toc\" id=\"toc\">\n", +      doc_matters.conf_make_meta.meta.title_full, +    ); +    foreach (sect; doc_matters.xml.keys_seq.seg) { +      foreach (obj; doc_abstraction[sect]) { +        if (obj.metainfo.is_a == "heading") { +          string _txt = obj.text.replaceAll(rgx.inline_notes_al_gen, "").strip; +          foreach_reverse (n; 0 .. 7) { +            string k = n.to!string; +            switch (obj.metainfo.dom_structure_collapsed_tags_status[n]) { +            case DomTags.close : +              toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "</li>" ~ "\n"; +              toc ~= markup.indent_by_spaces_provided(n, "  ") ~ "</ol>" ~ "\n"; +              break; +            case DomTags.close_and_open : +              toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "</li>" ~ "\n"; +              if  (obj.metainfo.heading_lev_markup < 4) { +                toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n" +                ~ markup.indent_by_spaces_provided((n + 2), "  ") +                ~ "<a href=\"" ~ obj.tags.segment_anchor_tag ~ ".xhtml" ~ "\">" +                ~ _txt +                ~ "</a>" ~ "\n"; +              } else { +                string hashtag =(obj.metainfo.heading_lev_markup == 4) +                ? "" +                : ("#" ~ obj.metainfo.ocn.to!string); +                toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n" +                ~ markup.indent_by_spaces_provided((n + 2), "  ") +                ~ "<a href=\"" ~ obj.tags.segment_anchor_tag ~ ".xhtml" ~ hashtag ~ "\">" +                ~ _txt +                ~ "</a>" ~ "\n"; +              } +              break; +            case DomTags.open : +              toc ~= markup.indent_by_spaces_provided(n, "  ") ~ "<ol>" ~ "\n"; +              if  (obj.metainfo.heading_lev_markup < 4) { +                toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n" +                ~ markup.indent_by_spaces_provided((n + 2), "  ") +                ~ "<a href=\"" ~ obj.tags.segment_anchor_tag ~ ".xhtml" ~ "\">" +                ~ _txt +                ~ "</a>" ~ "\n"; +              } else { +                string hashtag =(obj.metainfo.heading_lev_markup == 4) +                ? "" +                : ("#" ~ obj.metainfo.ocn.to!string); +                toc ~= markup.indent_by_spaces_provided((n + 1), "  ") ~ "<li>" ~ "\n" +                ~ markup.indent_by_spaces_provided((n + 2), "  ") +                ~ "<a href=\"" ~ obj.tags.segment_anchor_tag ~ ".xhtml" ~ hashtag ~ "\">" +                ~ _txt +                ~ "</a>" ~ "\n"; +              } +              break; +            default : +              break; +            } +          } +        } +      } +    } +    toc ~="</nav> +      </section> +    </body> +  </html>\n"; +    return toc; +  } +  string epub2_oebps_toc_ncx(D,I)(D doc_abstraction, I doc_matters) { +    int counter = 0; +    string uuid = "18275d951861c77f78acd05672c9906924c59f18a2e0ba06dad95959693e9bd8"; // TODO shared elsewhere +    auto markup = InlineMarkup(); +    auto rgx = Rgx(); +    enum DomTags { none, open, close, close_and_open, open_still, } +    string toc = format(q"¶<?xml version='1.0' encoding='utf-8'?> +  <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1"> +  <head> +    <!-- four required metadata items (for all NCX documents, +      (including the relaxed constraints of OPS 2.0) --> +    <title>%s%s</title> +    <link rel="stylesheet" href="css/epub.css" type="text/css" id="main-css" /> +    <meta name="dtb:uid" content="urn:uuid:%s" /> +    <!-- <meta name="epub-creator" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> --> +    <meta name="dtb:depth" content="%s" /> +    <meta name="dtb:totalPageCount" content="0" /> +    <meta name="dtb:maxPageNumber" content="0" /> +  </head> +  <docTitle> +    <text>%s</text> +  </docTitle> +  <docAuthor> +    <text>%s</text> +  </docAuthor> +  <navMap>¶", +      doc_matters.conf_make_meta.meta.title_full,                          // title +      (doc_matters.conf_make_meta.meta.creator_author.empty) ? "" +        : " by " ~ doc_matters.conf_make_meta.meta.creator_author,         // author +      uuid,                                                               // uuid +      "3",                                                                // content depth +      doc_matters.conf_make_meta.meta.title_full,                          // title +      (doc_matters.conf_make_meta.meta.creator_author.empty) ? "" +        : doc_matters.conf_make_meta.meta.creator_author,                  // author +    ); +    foreach (sect; doc_matters.xml.keys_seq.seg) { +      foreach (obj; doc_abstraction[sect]) { +        if (obj.metainfo.is_a == "heading") { +          string _txt = obj.text.replaceAll(rgx.inline_notes_al_gen, "").strip; +          string hashtag =(obj.metainfo.heading_lev_markup <= 4) ? "" : ("#" ~ obj.metainfo.ocn.to!string); +          foreach_reverse (k; 0 .. 7) { +            switch (obj.metainfo.dom_structure_markedup_tags_status[k]) { +            case DomTags.close : +              toc ~= "\n    </navPoint>"; +              break; +            case DomTags.close_and_open : +              ++counter; +              toc ~= "\n    </navPoint>"; +              toc ~= format(q"¶ +    <navPoint class="chapter" id="navpoint" playOrder="%s"> +      <navLabel> +        <text>%s</text> +      </navLabel> +      <content src="%s.xhtml%s" />¶", +                counter, +                _txt, +                obj.tags.segment_anchor_tag, +                hashtag, +              ); +              break; +            case DomTags.open : +              ++counter; +              toc ~= format(q"¶ +    <navPoint class="chapter" id="navpoint" playOrder="%s"> +      <navLabel> +        <text>%s</text> +      </navLabel> +      <content src="%s.xhtml%s" />¶", +                counter, +                _txt, +                obj.tags.segment_anchor_tag, +                hashtag, +              ); +              break; +            default : +              break; +            } +          } +        } +      } +    } +    toc ~= format(q"¶  </navMap> +  </ncx>¶"); +    return toc; +  } +   +  void outputEPub3(D,I)( +    const D    doc_abstraction, +          I    doc_matters, +  ) { +    mixin SiSUoutputRgxInit; +    auto xhtml_format = outputXHTMLs(); +    auto rgx = Rgx(); +    string[][string] doc_epub3; +    string[][string] doc_epub3_endnotes; +    string[] doc; +    string segment_filename; +    string[] top_level_headings = ["","","",""]; +    string[string] oepbs_content_parts; +    string suffix = ".xhtml"; +    string[] doc_parts_; +    foreach (part; doc_matters.xml.keys_seq.seg) { +      foreach (obj; doc_abstraction[part]) { +        string _txt = xhtml_format.special_characters(obj, obj.text); +        if (obj.metainfo.is_a == "heading") { +          assert(part == "head" || "toc_seg" || "body" || "endnotes" || "glossary" || "bibliography" || "bookindex_seg" || "blurb" || "tail"); +          switch (obj.metainfo.heading_lev_markup) { +          case 0: .. case 3: +            /+ fill buffer, and replace with new levels from 1 to 3 +/ +            switch (obj.metainfo.heading_lev_markup) { +            case 0: +              top_level_headings[0] = ""; +              top_level_headings[1] = ""; +              top_level_headings[2] = ""; +              top_level_headings[3] = ""; +              goto default; +            case 1: +              top_level_headings[1] = ""; +              top_level_headings[2] = ""; +              top_level_headings[3] = ""; +              goto default; +            case 2: +              top_level_headings[2] = ""; +              top_level_headings[3] = ""; +              goto default; +            case 3: +              top_level_headings[3] = ""; +              goto default; +            default: +              doc_parts_ ~= obj.tags.segment_anchor_tag; +              doc_epub3[obj.tags.segment_anchor_tag] ~= xhtml_format.epub3_seg_head(doc_matters); +              auto t = xhtml_format.heading_seg(obj, _txt, suffix, "epub"); +              doc_epub3[obj.tags.segment_anchor_tag] ~= t[0]; +              doc_epub3_endnotes[obj.tags.segment_anchor_tag] ~= t[1]; +              break; +            } +            break; +          case 4: +            segment_filename = obj.tags.segment_anchor_tag; +            doc_epub3[segment_filename] ~= xhtml_format.epub3_seg_head(doc_matters); +            auto t = xhtml_format.heading_seg(obj, _txt, suffix, "epub"); +            doc_epub3[segment_filename] ~= t[0]; +            doc_epub3_endnotes[segment_filename] ~= t[1]; +            break; +          case 5: .. case 7: +            auto t = xhtml_format.heading_seg(obj, _txt, suffix, "epub"); +            doc_epub3[segment_filename] ~= t[0]; +            doc_epub3_endnotes[segment_filename] ~= t[1]; +            break; +          case 8: .. case 9: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a, ": ", obj.metainfo.heading_lev_markup); +              writeln(__FILE__, ":", __LINE__, ": ", obj.text); +            } +            break; +          default: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a, ": ", obj.metainfo.heading_lev_markup); +            } +            break; +          } +        } else { +          assert(part == "head" || "toc_seg" || "body" || "endnotes" || "glossary" || "bibliography" || "bookindex_seg" || "blurb" || "tail"); +          switch (obj.metainfo.is_of_part) { +          case "frontmatter":             assert(part == "head" || "toc_seg"); +            switch (obj.metainfo.is_of_type) { +            case "para": +              switch (obj.metainfo.is_a) { +              case "toc": +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              default: +                if ((doc_matters.opt.action.debug_do)) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +                } +                break; +              } +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +              } +              break; +            } +            break; +          case "body":                    assert(part == "body"); +            switch (obj.metainfo.is_of_type) { +            case "para": +              switch (obj.metainfo.is_a) { +              case "para": +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              default: +                if ((doc_matters.opt.action.debug_do)) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +                } +                break; +              } +              break; +            case "block": +              switch (obj.metainfo.is_a) { +              case "quote": +                auto t = xhtml_format.quote_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0].to!string; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "group": +                auto t = xhtml_format.group_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0].to!string; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "block": +                auto t = xhtml_format.block_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0].to!string; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "poem": +                break; +              case "verse": +                auto t = xhtml_format.verse_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0].to!string; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "code": +                doc_epub3[segment_filename] ~= xhtml_format.code(obj, _txt); +                break; +              case "table": +                doc_epub3[segment_filename] ~= xhtml_format.table(obj, _txt); +                doc_epub3_endnotes[segment_filename] ~= ""; +                break; +              default: +                if ((doc_matters.opt.action.debug_do)) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +                } +                break; +              } +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +              } +              break; +            } +            break; +          case "backmatter": +            assert(part == "endnotes" || "glossary" || "bibliography" || "bookindex_seg" || "blurb" || "tail"); +            switch (obj.metainfo.is_of_type) { +            case "para": +              switch (obj.metainfo.is_a) { +              case "endnote":             assert(part == "endnotes"); +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0]; +                break; +              case "glossary":            assert(part == "glossary"); +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "bibliography":        assert(part == "bibliography"); +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "bookindex":           assert(part == "bookindex_seg"); +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              case "blurb":               assert(part == "blurb"); +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "epub"); +                doc_epub3[segment_filename] ~= t[0]; +                doc_epub3_endnotes[segment_filename] ~= t[1]; +                break; +              default: +                if ((doc_matters.opt.action.debug_do)) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +                } +                break; +              } +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +              } +              break; +            } +            break; +          case "comment": +            break; +          default: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_part); +            } +            break; +          } +        } +        if (obj.metainfo.is_a == "heading") { +          assert(obj.text.length > 0); +          if (obj.metainfo.heading_lev_markup <= 4) { +            oepbs_content_parts["manifest_documents"] ~= +              format(q"¶      <item id="%s.xhtml" href="%s.xhtml" media-type="application/xhtml+xml" /> +  ¶", +              obj.tags.segment_anchor_tag, +              obj.tags.segment_anchor_tag, +            ); +            oepbs_content_parts["spine"] ~= +              format(q"¶    <itemref idref="%s.xhtml" linear="yes" /> +  ¶", +              obj.tags.segment_anchor_tag, +            ); +            oepbs_content_parts["guide"] ~= +              format(q"¶      <reference type="%s" href="%s" /> +  ¶", +              obj.tags.segment_anchor_tag, +              obj.tags.segment_anchor_tag, +            ); +          } else if (obj.metainfo.heading_lev_markup > 4) { +            oepbs_content_parts["manifest_documents"] ~= +              format(q"¶      <item id="%s.xhtml#%s" href="%s.xhtml#%s" media-type="application/xhtml+xml" /> +  ¶", +              obj.tags.segment_anchor_tag, +              obj.metainfo.object_number, +              obj.tags.segment_anchor_tag, +              obj.metainfo.object_number, +            ); +            oepbs_content_parts["spine"] ~= +              format(q"¶    <itemref idref="%s.xhtml#%s" linear="yes" /> +  ¶", +              obj.tags.segment_anchor_tag, +              obj.metainfo.object_number, +            ); +            oepbs_content_parts["guide"] ~= +              format(q"¶      <reference type="%s#%s" href="%s#%s" /> +  ¶", +              obj.tags.segment_anchor_tag, +              obj.metainfo.object_number, +              obj.tags.segment_anchor_tag, +              obj.metainfo.object_number, +            ); +          } +        } +      } +    } +    /+ epub specific documents +/ +    auto mimetypes = epub3_mimetypes; +    auto meta_inf_container_xml = epub3_container_xml; +    auto oebps_toc_ncx = epub2_oebps_toc_ncx(doc_abstraction, doc_matters); +    auto oebps_toc_nav_xhtml = epub3_oebps_toc_nav_xhtml(doc_abstraction, doc_matters); +    auto oebps_content_opf = epub3_oebps_content(doc_abstraction, doc_matters, oepbs_content_parts); +    epub3_write_output_files( +      doc_matters, +      doc_epub3, +      doc_epub3_endnotes, +      mimetypes, +      meta_inf_container_xml, +      oebps_toc_nav_xhtml, +      oebps_toc_ncx, +      oebps_content_opf, +      doc_parts_, +    ); +  } +  void epub3_write_output_files(M,D,E,Mt,Mic,Otnx,Otn,Oc)( +    M    doc_matters, +    D    doc_epub3, +    E    doc_epub3_endnotes, +    Mt   mimetypes, +    Mic  meta_inf_container_xml, +    Otnx oebps_toc_nav_xhtml, +    Otn  oebps_toc_ncx, +    Oc   oebps_content_opf, +    string[] doc_parts_, +  ) { +    debug(asserts) { +      static assert(is(typeof(doc_epub3)              == string[][string])); +      static assert(is(typeof(mimetypes)              == string)); +      static assert(is(typeof(meta_inf_container_xml) == string)); +      static assert(is(typeof(oebps_toc_nav_xhtml)    == string)); +      static assert(is(typeof(oebps_toc_ncx)          == string)); +      static assert(is(typeof(oebps_content_opf)      == string)); +    } +    auto pth_epub3 = SiSUpathsEPUB!()(doc_matters.output_path, doc_matters.src.language); +    auto xhtml_format = outputXHTMLs(); +    /+ zip file +/ +    auto fn_epub = pth_epub3.epub_file(doc_matters.src.filename); +    auto zip = new ZipArchive(); // ZipArchive zip = new ZipArchive(); +    /+ zip archive member files +/ +    try { +      if (!exists(pth_epub3.base)) { +        pth_epub3.base.mkdirRecurse; +      } +      debug(epub_output) { +        if (!exists(pth_epub3.dbg_doc_meta_inf(doc_matters.src.filename))) { +          pth_epub3.dbg_doc_meta_inf(doc_matters.src.filename).mkdirRecurse; +        } +        if (!exists(pth_epub3.dbg_doc_oebps_css(doc_matters.src.filename))) { +          pth_epub3.dbg_doc_oebps_css(doc_matters.src.filename).mkdirRecurse; +        } +        if (!exists(pth_epub3.dbg_doc_oebps_image(doc_matters.src.filename))) { +          pth_epub3.dbg_doc_oebps_image(doc_matters.src.filename).mkdirRecurse; +        } +      } +      { /+ OEBPS/[segments].xhtml (the document contents) +/ +        foreach (seg_filename; doc_matters.xml.segnames_lv_0_to_4) { +          string fn = pth_epub3.fn_oebps_content_xhtml(doc_matters.src.filename, seg_filename); +          auto zip_arc_member_file = new ArchiveMember(); +          zip_arc_member_file.name = fn; +          auto zip_data = new OutBuffer(); +          debug(epub_output) { +            string fn_dbg = pth_epub3.dbg_fn_oebps_content_xhtml(doc_matters.src.filename, seg_filename); +            auto f = File(fn_dbg, "w"); +          } +          foreach (docseg; doc_epub3[seg_filename]) { +            debug(epub_output) { f.writeln(docseg); } +            zip_data.write(docseg.dup); +          } +          foreach (docseg; doc_epub3_endnotes[seg_filename]) { +            debug(epub_output) { f.writeln(docseg); } +            zip_data.write(docseg.dup); +          } +          debug(epub_output) { f.writeln(xhtml_format.tail); } +          zip_data.write(xhtml_format.tail.dup); +          zip_arc_member_file.expandedData = zip_data.toBytes(); +          zip.addMember(zip_arc_member_file); +          /+ create the zip file +/ +          createZipFile!()(fn_epub, zip.build()); +        } +      } +      string fn; +      debug(epub_output) { string fn_dbg; } +      File f; +      { /+ mimetypes (identify zip file type) +/ +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_mimetypes(doc_matters.src.filename); +          File(fn_dbg, "w").writeln(mimetypes); +        } +        fn = pth_epub3.fn_mimetypes(doc_matters.src.filename); +        auto zip_arc_member_file = new ArchiveMember(); +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(mimetypes.dup); +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        createZipFile!()(fn_epub, zip.build()); +      } +      { /+  META-INF/container.xml (identify doc root) +/ +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_dmi_container_xml(doc_matters.src.filename); +          File(fn_dbg, "w").writeln(meta_inf_container_xml); +        } +        fn = pth_epub3.fn_dmi_container_xml(doc_matters.src.filename); +        auto zip_arc_member_file = new ArchiveMember(); +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(meta_inf_container_xml.dup); +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        createZipFile!()(fn_epub, zip.build()); +      } +      { /+ OEBPS/toc_nav.xhtml (navigation toc epub3) +/ +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_oebps_toc_nav_xhtml(doc_matters.src.filename); +          File(fn_dbg, "w").writeln(oebps_toc_nav_xhtml); +        } +        fn = pth_epub3.fn_oebps_toc_nav_xhtml(doc_matters.src.filename); +        auto zip_arc_member_file = new ArchiveMember(); +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(oebps_toc_nav_xhtml.dup); +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        createZipFile!()(fn_epub, zip.build()); +      } +      { /+ OEBPS/toc.ncx (navigation toc epub2) +/ +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_oebps_toc_ncx(doc_matters.src.filename); +          File(fn_dbg, "w").writeln(oebps_toc_ncx); +        } +        fn = pth_epub3.fn_oebps_toc_ncx(doc_matters.src.filename); +        auto zip_arc_member_file = new ArchiveMember(); +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(oebps_toc_ncx.dup); +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        createZipFile!()(fn_epub, zip.build()); +      } +      { /+ OEBPS/content.opf (doc manifest) +/ +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_oebps_content_opf(doc_matters.src.filename); +          File(fn_dbg, "w").writeln(oebps_content_opf); +        } +        fn = pth_epub3.fn_oebps_content_opf(doc_matters.src.filename); +        auto zip_arc_member_file = new ArchiveMember(); +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(oebps_content_opf.dup); +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        createZipFile!()(fn_epub, zip.build()); +      } +      { /+ OEBPS/_sisu/image (images) +/ +        foreach (image; doc_matters.srcs.image_list) { +          debug(epub_output) { +            if (exists(doc_matters.src_path_info.image_root ~ "/" ~ image)) { +              (doc_matters.src_path_info.image_root ~ "/" ~ image) +              .copy((pth_epub3.dbg_doc_oebps_image(doc_matters.src.filename)) ~ "/" ~ image); +            } +          } +        } +        foreach (image; doc_matters.srcs.image_list) { +          debug(epub_output) { +            debug(epub_images) { +              writeln( +                doc_matters.src.image_dir_path, "/", image, " -> ", +                pth_epub3.dbg_doc_oebps_image(doc_matters.src.filename), "/", image +              ); +            } +          } +          auto fn_src = doc_matters.src.image_dir_path ~ "/" ~ image; +          auto fn_out =  pth_epub3.doc_oebps_image(doc_matters.src.filename.to!string) ~ "/" ~ image; +          if (exists(fn_src)) { +            { +              auto zip_arc_member_file = new ArchiveMember(); +              zip_arc_member_file.name = fn_out; +              auto zip_data = new OutBuffer(); +              zip_data.write(cast(char[]) ((fn_src).read)); +              zip_arc_member_file.expandedData = zip_data.toBytes(); +              zip.addMember(zip_arc_member_file); +              createZipFile!()(fn_epub, zip.build()); +            } +          } +        } +      } +      { /+ OEBPS/epub.css +/ +        auto css = SiSUcss(); +        debug(epub_output) { +          fn_dbg = pth_epub3.dbg_fn_oebps_css(doc_matters.src.filename); +          File(fn_dbg, "w").writeln(css.epub_css); +        } +        fn = pth_epub3.fn_oebps_css(doc_matters.src.filename); +        auto zip_arc_member_file = new ArchiveMember(); +        zip_arc_member_file.name = fn; +        auto zip_data = new OutBuffer(); +        zip_data.write(css.epub_css.dup); +        zip_arc_member_file.expandedData = zip_data.toBytes(); +        zip.addMember(zip_arc_member_file); +        createZipFile!()(fn_epub, zip.build()); +      } +    } catch (ErrnoException ex) { +      // Handle error +    } +    if (!(doc_matters.opt.action.quiet)) { +      writeln(" ", fn_epub); +    } +    debug(epub_archive) { +      if (exists(fn_epub)) { +        try { +          auto zipped = new ZipArchive((fn_epub).read); +          foreach (filename, member; zipped.directory) { +            auto data = zipped.expand(member); +            writeln(filename, " length ", data.length); +          } +        } catch (ZipException ex) { +          // Handle errors +        } +      } +    } +  } +   +} diff --git a/src/doc_reform/output/html.d b/src/doc_reform/output/html.d new file mode 100644 index 0000000..07fe081 --- /dev/null +++ b/src/doc_reform/output/html.d @@ -0,0 +1,481 @@ +module doc_reform.output.html; +template outputHTML() { +  import doc_reform.output; +  import +    std.digest.sha, +    std.file, +    std.outbuffer, +    std.zip, +    std.conv : to; +  import +    doc_reform.output.create_zip_file, +    doc_reform.output.xmls, +    doc_reform.output.xmls_css; +  mixin outputXHTMLs; +  void scroll(D,I)( +    const D    doc_abstraction, +          I    doc_matters, +  ) { +    mixin SiSUoutputRgxInit; +    auto xhtml_format = outputXHTMLs(); +    auto rgx = Rgx(); +    string[] doc_html; +    string[] doc; +    string suffix = ".html"; +    string previous_part = ""; +    string delimit = ""; +    foreach (part; doc_matters.xml.keys_seq.scroll) { +      foreach (obj; doc_abstraction[part]) { +        delimit = xhtml_format.div_delimit(part, previous_part); +        string _txt = xhtml_format.special_characters(obj, obj.text); +        switch (obj.metainfo.is_of_part) { +        case "frontmatter":              assert(part == "head" || "toc_scroll"); +          switch (obj.metainfo.is_of_type) { +          case "para": +            switch (obj.metainfo.is_a) { +            case "heading": +              doc_html ~= delimit ~ xhtml_format.heading_scroll(obj, _txt, suffix); +              break; +            case "toc": +              doc_html ~= xhtml_format.para_scroll(obj, _txt, suffix); +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +              } +              break; +            } +            break; +          default: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +            } +            break; +          } +          break; +        case "body":                     assert(part == "body" || "head"); +          switch (obj.metainfo.is_of_type) { +          case "para": +            switch (obj.metainfo.is_a) { +            case "heading": +              doc_html ~= delimit ~ xhtml_format.heading_scroll(obj, _txt, suffix); +              break; +            case "para": +              doc_html ~= xhtml_format.para_scroll(obj, _txt, suffix); +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +              } +              break; +            } +            break; +          case "block": +            switch (obj.metainfo.is_a) { +            case "quote": +              doc_html ~= xhtml_format.quote_scroll(obj, _txt); +              break; +            case "group": +              doc_html ~= xhtml_format.group_scroll(obj, _txt); +              break; +            case "block": +              doc_html ~= xhtml_format.block_scroll(obj, _txt); +              break; +            case "poem": +              break; +            case "verse": +              doc_html ~= xhtml_format.verse_scroll(obj, _txt, suffix); +              break; +            case "code": +              doc_html ~= xhtml_format.code(obj, _txt); +              break; +            case "table": +              doc_html ~= xhtml_format.table(obj, _txt); +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +              } +              break; +            } +            break; +          default: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +            } +            break; +          } +          break; +        case "backmatter": +          assert(part == "endnotes" || "glossary" || "bibliography" || "bookindex_scroll" || "blurb" || "tail"); +          switch (obj.metainfo.is_of_type) { +          case "para": +            switch (obj.metainfo.is_a) { +            case "heading": +              doc_html ~= delimit ~ xhtml_format.heading_scroll(obj, _txt, suffix); +              break; +            case "endnote":              assert(part == "endnotes"); +              doc_html ~= xhtml_format.para_scroll(obj, _txt, suffix); +              break; +            case "glossary":             assert(part == "glossary"); +              doc_html ~= xhtml_format.para_scroll(obj, _txt, suffix); +              break; +            case "bibliography":         assert(part == "bibliography"); +              doc_html ~= xhtml_format.para_scroll(obj, _txt, suffix); +              break; +            case "bookindex":            assert(part == "bookindex_scroll"); +              doc_html ~= xhtml_format.para_scroll(obj, _txt, suffix); +              break; +            case "blurb":                assert(part == "blurb"); +              doc_html ~= xhtml_format.para_scroll(obj, _txt, suffix); +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +              } +              break; +            } +            break; +          default: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +            } +            break; +          } +          break; +        case "comment": +          break; +        default: +          if ((doc_matters.opt.action.debug_do)) { +            writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_part); +            writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +            writeln(__FILE__, ":", __LINE__, ": ", obj.text); +          } +          break; +        } +      } +    } +    doc = xhtml_format.html_head(doc_matters, "scroll") ~ doc_html ~ xhtml_format.tail; +    scroll_write_output(doc_matters, doc); +  } +  void scroll_write_output(M,C)( +    M doc_matters, +    C doc, +  ) { +    debug(asserts) { +      static assert(is(typeof(doc)    == string[])); +    } +    auto pth_html = SiSUpathsHTML!()(doc_matters.output_path, doc_matters.src.language); +    try { +      if (!exists(pth_html.base)) { +        pth_html.base.mkdirRecurse; +      } +      auto f = File(pth_html.fn_scroll(doc_matters.src.filename), "w"); +      foreach (o; doc) { +        f.writeln(o); +      } +    } catch (ErrnoException ex) { +      // Handle error +    } +    if (!(doc_matters.opt.action.quiet)) { +      writeln(" ", pth_html.fn_scroll(doc_matters.src.filename)); +    } +  } +  void seg(D,M)( +    const D    doc_abstraction, +          M    doc_matters, +  ) { +    mixin SiSUoutputRgxInit; +    auto rgx = Rgx(); +    auto xhtml_format = outputXHTMLs(); +    string[][string] doc_html; +    string[][string] doc_html_endnotes; +    string[] doc; +    string segment_filename; +    string[] top_level_headings = ["","","",""]; +    string previous_seg_filename = ""; +    string suffix = ".html"; +    string previous_part = ""; +    string delimit = ""; +    foreach (part; doc_matters.xml.keys_seq.seg) { +      foreach (obj; doc_abstraction[part]) { +        delimit = xhtml_format.div_delimit(part, previous_part); +        string _txt = xhtml_format.special_characters(obj, obj.text); +        if (obj.metainfo.is_a == "heading") { +          assert(part == "head" || "toc_seg" || "body" || "endnotes" || "glossary" || "bibliography" || "bookindex_seg" || "blurb" || "tail"); +          switch (obj.metainfo.heading_lev_markup) { +          case 0: .. case 3: +            /+ fill buffer, and replace with new levels from 1 to 3 +/ +            switch (obj.metainfo.heading_lev_markup) { +            case 0: +              top_level_headings[0] = ""; +              top_level_headings[1] = ""; +              top_level_headings[2] = ""; +              top_level_headings[3] = ""; +              goto default; +            case 1: +              top_level_headings[1] = ""; +              top_level_headings[2] = ""; +              top_level_headings[3] = ""; +              goto default; +            case 2: +              top_level_headings[2] = ""; +              top_level_headings[3] = ""; +              goto default; +            case 3: +              top_level_headings[3] = ""; +              goto default; +            default: +              auto t = xhtml_format.heading_seg(obj, _txt, suffix, "seg"); +              top_level_headings[obj.metainfo.heading_lev_markup] = t[0]; +              break; +            } +            break; +          case 4: +            segment_filename = obj.tags.segment_anchor_tag; +            doc_html[segment_filename] ~= xhtml_format.html_head(doc_matters, "seg"); +            auto navigation_bar = xhtml_format.nav_pre_next_svg(obj); +            doc_html[segment_filename] ~= navigation_bar.toc_pre_next; +            previous_seg_filename = segment_filename; +            foreach (top_level_heading; top_level_headings) { +              doc_html[segment_filename] ~= top_level_heading; +            } +            auto t = xhtml_format.heading_seg(obj, _txt, suffix, "seg"); +            doc_html[segment_filename] ~= t[0].to!string; +            doc_html[segment_filename] ~= xhtml_format.lev4_heading_subtoc(obj); +            doc_html_endnotes[segment_filename] ~= t[1]; +            break; +          case 5: .. case 7: +            auto t = xhtml_format.heading_seg(obj, _txt, suffix, "seg"); +            doc_html[segment_filename] ~= t[0].to!string; +            doc_html_endnotes[segment_filename] ~= t[1]; +            break; +          case 8: .. case 9: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a, ": ", obj.metainfo.heading_lev_markup); +              writeln(__FILE__, ":", __LINE__, ": ", obj.text); +            } +            break; +          default: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a, ": ", obj.metainfo.heading_lev_markup); +            } +            break; +          } +        } else { +          assert(part == "head" || "toc_seg" || "body" || "endnotes" || "glossary" || "bibliography" || "bookindex_seg" || "blurb" || "tail"); +          switch (obj.metainfo.is_of_part) { +          case "frontmatter":             assert(part == "head" || "toc_seg"); +            switch (obj.metainfo.is_of_type) { +            case "para": +              switch (obj.metainfo.is_a) { +              case "toc": +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0].to!string; +                break; +              default: +                if ((doc_matters.opt.action.debug_do)) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +                } +                break; +              } +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +              } +              break; +            } +            break; +          case "body":                    assert(part == "body"); +            switch (obj.metainfo.is_of_type) { +            case "para": +              switch (obj.metainfo.is_a) { +              case "para": +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0].to!string; +                doc_html_endnotes[segment_filename] ~= t[1]; +                break; +              default: +                if ((doc_matters.opt.action.debug_do)) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +                } +                break; +              } +              break; +            case "block": +              switch (obj.metainfo.is_a) { +              case "quote": +                auto t = xhtml_format.quote_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0].to!string; +                doc_html_endnotes[segment_filename] ~= t[1]; +                break; +              case "group": +                auto t = xhtml_format.group_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0].to!string; +                doc_html_endnotes[segment_filename] ~= t[1]; +                break; +              case "block": +                auto t = xhtml_format.block_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0].to!string; +                doc_html_endnotes[segment_filename] ~= t[1]; +                break; +              case "poem": +                break; +              case "verse": +                auto t = xhtml_format.verse_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0].to!string; +                doc_html_endnotes[segment_filename] ~= t[1]; +                break; +              case "code": +                doc_html[segment_filename] ~= xhtml_format.code(obj, _txt); +                break; +              case "table": +                doc_html[segment_filename] ~= xhtml_format.table(obj, _txt); +                doc_html_endnotes[segment_filename] ~= ""; +                break; +              default: +                if ((doc_matters.opt.action.debug_do)) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +                } +                break; +              } +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +              } +              break; +            } +            break; +          case "backmatter": +            assert(part == "endnotes" || "glossary" || "bibliography" || "bookindex_seg" || "blurb" || "tail"); +            switch (obj.metainfo.is_of_type) { +            case "para": +              switch (obj.metainfo.is_a) { +              case "endnote":             assert(part == "endnotes"); +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0]; +                break; +              case "glossary":            assert(part == "glossary"); +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0]; +                doc_html_endnotes[segment_filename] ~= t[1]; +                break; +              case "bibliography":        assert(part == "bibliography"); +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0]; +                doc_html_endnotes[segment_filename] ~= t[1]; +                break; +              case "bookindex":           assert(part == "bookindex_seg"); +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0]; +                doc_html_endnotes[segment_filename] ~= t[1]; +                break; +              case "blurb":               assert(part == "blurb"); +                auto t = xhtml_format.para_seg(obj, _txt, suffix, "seg"); +                doc_html[segment_filename] ~= t[0]; +                doc_html_endnotes[segment_filename] ~= t[1]; +                break; +              default: +                if ((doc_matters.opt.action.debug_do)) { +                  writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +                } +                break; +              } +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +              } +              break; +            } +            break; +          case "comment": +            break; +          default: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_part); +            } +            break; +          } +        } +      } +    } +    seg_write_output(doc_matters, doc_html, doc_html_endnotes); +  } +  void seg_write_output(M,D,E)( +    M doc_matters, +    D doc_html, +    E doc_html_endnotes, +  ) { +    debug(asserts) { +      static assert(is(typeof(doc_html)      == string[][string])); +    } +    mixin SiSUoutputRgxInit; +    auto rgx = Rgx(); +    auto pth_html = SiSUpathsHTML!()(doc_matters.output_path, doc_matters.src.language); +    auto xhtml_format = outputXHTMLs(); +    auto m = doc_matters.src.filename.matchFirst(rgx.src_fn); +    try { +      if (!exists(pth_html.seg(doc_matters.src.filename))) { +        pth_html.seg(doc_matters.src.filename).mkdirRecurse; +      } +      foreach (seg_filename; doc_matters.xml.segnames) { +        auto f = File(pth_html.fn_seg(doc_matters.src.filename, seg_filename), "w"); +        foreach (docseg; doc_html[seg_filename]) { +          f.writeln(docseg); +        } +        foreach (docseg; doc_html_endnotes[seg_filename]) { +          f.writeln(docseg); +        } +        f.writeln(xhtml_format.tail); +      } +    } catch (ErrnoException ex) { +      // handle error +    } +    if (!(doc_matters.opt.action.quiet)) { +      writeln(" ", pth_html.fn_seg(doc_matters.src.filename, "toc")); +    } +  } +  void css(M)( +    auto ref              M    doc_matters, +  ) { +    auto css = SiSUcss(); +    auto pth_html = SiSUpathsHTML!()(doc_matters.output_path, doc_matters.src.language); +    try { +      if (!exists(pth_html.css)) { +        (pth_html.css).mkdirRecurse; +      } +      auto f = File(pth_html.fn_seg_css, "w"); +      f.writeln(css.html_seg_css); +      f = File(pth_html.fn_scroll_css, "w"); +      f.writeln(css.html_scroll_css); +    } catch (ErrnoException ex) { +      // Handle error +    } +  } +  void images_cp(M)( +    auto ref              M    doc_matters, +  ) { +    { /+ (copy html images) +/ +   +      auto pth_html = SiSUpathsHTML!()(doc_matters.output_path, doc_matters.src.language); +      if (!exists(pth_html.image)) { +        pth_html.image.mkdirRecurse; +      } +      foreach (image; doc_matters.srcs.image_list) { +        auto fn_src_in = doc_matters.src.image_dir_path ~ "/" ~ image; +        auto fn_src_out = pth_html.image ~ "/" ~ image; +        debug(images_html) { +          writeln(fn_src_in, " -> ", fn_src_out); +        } +        if (exists(fn_src_in)) { +          fn_src_in.copy(fn_src_out); +        } else { +          writeln("WARNING image not found: ", fn_src_in); +        } +      } +    } +  } +} diff --git a/src/doc_reform/output/hub.d b/src/doc_reform/output/hub.d new file mode 100644 index 0000000..b40c929 --- /dev/null +++ b/src/doc_reform/output/hub.d @@ -0,0 +1,106 @@ +/++ +  output hub<BR> +  check & generate output types requested ++/ +module doc_reform.output.hub; +template outputHub() { +  import doc_reform.output, +    doc_reform.output.epub3, +    doc_reform.output.html, +    doc_reform.output.sqlite, +    doc_reform.output.xmls, +    doc_reform.output.source_sisupod, +    doc_reform.output.create_zip_file, +    doc_reform.output.paths_output; +  import std.parallelism; +  void outputHub(D,I)(D doc_abstraction, I doc_matters) { +    mixin SiSUoutputRgxInit; +    mixin Msg; +    auto msg = Msg!()(doc_matters); +    static auto rgx = Rgx(); +    enum outTask { sisupod, source, sqlite, sqlite_multi, epub, html_scroll, html_seg, html_stuff } +    void Scheduled(D,I)(int sched, D doc_abstraction, I doc_matters) { +      auto msg = Msg!()(doc_matters); +      if (sched == outTask.sisupod) { +        msg.v("sisu source processing... "); +        SiSUpod!()(doc_matters); +        msg.vv("sisu source done"); +      } +      if (sched == outTask.sqlite) { +        msg.v("sqlite processing... "); +        SQLiteHubDiscreteBuildTablesAndPopulate!()(doc_abstraction, doc_matters); +        msg.vv("sqlite done"); +      } +      if (sched == outTask.epub) { +        msg.v("epub3 processing... "); +        outputEPub3!()(doc_abstraction, doc_matters); +        msg.vv("epub3 done"); +      } +      if (sched == outTask.html_scroll) { +        msg.v("html scroll processing... "); +        outputHTML!().scroll(doc_abstraction, doc_matters); +        msg.vv("html scroll done"); +      } +      if (sched == outTask.html_seg) { +        msg.v("html seg processing... "); +        outputHTML!().seg(doc_abstraction, doc_matters); +        msg.vv("html seg done"); +      } +      if (sched == outTask.html_stuff) { +        outputHTML!().css(doc_matters); +        outputHTML!().images_cp(doc_matters); +        msg.vv("html css & images done"); +      } +    } +    if (!(doc_matters.opt.action.pp2)) { +      foreach(schedule; doc_matters.opt.action.output_task_scheduler) { +        Scheduled!()(schedule, doc_abstraction, doc_matters); +      } +    } else { +      foreach(schedule; parallel(doc_matters.opt.action.output_task_scheduler)) { +        Scheduled!()(schedule, doc_abstraction, doc_matters); +      } +    } +    if (doc_matters.opt.action.sqlite_update) { +      msg.v("sqlite update processing..."); +      SQLiteHubBuildTablesAndPopulate!()(doc_abstraction, doc_matters); +      msg.vv("sqlite update done"); +    } else if (doc_matters.opt.action.sqlite_delete) { +      msg.v("sqlite delete processing..."); +      SQLiteHubBuildTablesAndPopulate!()(doc_abstraction, doc_matters); +      msg.vv("sqlite delete done"); +    } +  } +} +template outputHubOp() { +  import doc_reform.output, +    doc_reform.output.epub3, +    doc_reform.output.html, +    doc_reform.output.sqlite, +    doc_reform.output.xmls, +    doc_reform.output.source_sisupod, +    doc_reform.output.create_zip_file, +    doc_reform.output.paths_output; +  void outputHubOp(E,O)(E env, O opt_action) { +    mixin SiSUoutputRgxInit; +    static auto rgx = Rgx(); +    if ((opt_action.sqlite_db_drop)) { +      if ((opt_action.verbose)) { +        writeln("sqlite drop db..."); +      } +      SQLiteDbDrop!()(opt_action); +      if ((opt_action.very_verbose)) { +        writeln("sqlite drop db done"); +      } +    } +    if ((opt_action.sqlite_db_create)) { +      if ((opt_action.verbose)) { +        writeln("sqlite create table..."); +      } +      SQLiteTablesCreate!()(env, opt_action); +      if ((opt_action.very_verbose)) { +        writeln("sqlite create table done"); +      } +    } +  } +} diff --git a/src/doc_reform/output/package.d b/src/doc_reform/output/package.d new file mode 100644 index 0000000..5e14e8a --- /dev/null +++ b/src/doc_reform/output/package.d @@ -0,0 +1,22 @@ +module doc_reform.output; +public import +  std.algorithm, +  std.array, +  std.container, +  std.exception, +  std.path, +  std.process, +  std.range, +  std.regex, +  std.stdio, +  std.string, +  std.traits, +  std.typecons, +  // std.uni, +  std.utf; +public import +  doc_reform.share.defaults, +  doc_reform.source.paths_source, +  doc_reform.output.defaults, +  doc_reform.output.paths_output, +  doc_reform.output.rgx; diff --git a/src/doc_reform/output/paths_output.d b/src/doc_reform/output/paths_output.d new file mode 100644 index 0000000..abd21b6 --- /dev/null +++ b/src/doc_reform/output/paths_output.d @@ -0,0 +1,272 @@ +/++ +  default settings ++/ +module doc_reform.output.paths_output; +import std.array, +  std.path, +  std.regex, +  std.stdio; +import doc_reform.meta.rgx; +template SiSUoutPaths() { +  auto SiSUoutPaths(Po,Lng)( +    Po  output_pth_root, +    Lng lng, +  ) { +    struct _PathsStruct { +      string output_root() { +        return (output_pth_root.length > 0) +        ? output_pth_root +        : "sisugen"; +      } +      string output_base() { +        return asNormalizedPath(output_root.chainPath(lng)).array; +      } +    } +    return _PathsStruct(); +  } +} +template SiSUoutPathSQLite() { +  auto SiSUoutPathSQLite(Po)( +    Po  output_pth_root, +  ) { +    struct _PathsStruct { +      string output_root() { +        return (output_pth_root.length > 0) +        ? output_pth_root +        : "sisugen"; +      } +      string output_base() { +        return asNormalizedPath(output_root).array; +      } +    } +    return _PathsStruct(); +  } +} +template SiSUoutPathsFnPd() { +  /+ TODO stuff to work out here +/ +  auto SiSUoutPathsFnPd(Fn,Pn)( +    Fn  fn_src_pth, +    Pn  pod_name +  ) { +    struct _PathsStruct { +      string base_filename() { +        return fn_src_pth.baseName.stripExtension; +      } +      string base_pod_and_filename() { // TODO +        /+ +          - if pod, +            - pod_name +            - file_name +            - if pod_name == file_name +              - file_name +            - else if pod_name != file_name +              - pod_name.file_name +        +/ +        string _fn_src = fn_src_pth.baseName.stripExtension; +        string _output_base_name; +        if (!(pod_name.empty)) { +          if (pod_name == _fn_src) { +            _output_base_name = _fn_src; +          } else { +            _output_base_name = pod_name ~ "." ~ _fn_src; +          } +        } else { +          _output_base_name = _fn_src; +        } +        return _output_base_name; +      } +    } +    return _PathsStruct(); +  } +} +template SiSUpathsHTML() { +  mixin SiSUrgxInit; +  static auto rgx = Rgx(); +  auto SiSUpathsHTML(Po,Lng)( +    Po  output_pth_root, +    Lng lng, +  ) { +    auto out_pth = SiSUoutPaths!()(output_pth_root, lng); +    string base_dir = "html"; +    string suffix = ".html"; +    struct _PathsStruct { +      string base_filename(string fn_src) { +        return fn_src.baseName.stripExtension; +      } +      string base() { +        return asNormalizedPath((out_pth.output_base).chainPath(base_dir)).array; +      } +      string image() { +        return asNormalizedPath((out_pth.output_root).chainPath("image")).array; +      } +      string css() { +        return asNormalizedPath((out_pth.output_root).chainPath("css")).array; +      } +      string fn_seg_css() { +        return asNormalizedPath(css.chainPath("html_seg.css")).array; +      } +      string fn_scroll_css() { +        return asNormalizedPath(css.chainPath("html_scroll.css")).array; +      } +      string seg(string fn_src) { +        return asNormalizedPath(base.chainPath(base_filename(fn_src))).array; +      } +      string fn_scroll(string fn_src) { +        return asNormalizedPath(base.chainPath(base_filename(fn_src) ~ suffix)).array; +      } +      string fn_seg(string fn_src, string seg_filename) { +        return asNormalizedPath(seg(fn_src).chainPath(seg_filename ~ suffix)).array; +      } +    } +    return _PathsStruct(); +  } +} +template SiSUpathsEPUB() { +  mixin SiSUrgxInit; +  static auto rgx = Rgx(); +  auto SiSUpathsEPUB(Po,Lng)( +    Po  output_pth_root, +    Lng lng, +  ) { +    auto out_pth = SiSUoutPaths!()( output_pth_root, lng); +    string base_dir = "epub"; +    struct _PathsStruct { +      string base() { +        return asNormalizedPath((out_pth.output_base).chainPath(base_dir)).array; +      } +      string base_filename(string fn_src) { +        return fn_src.baseName.stripExtension; +      } +      string epub_file(string fn_src) { +        return asNormalizedPath(base.chainPath(base_filename(fn_src) ~ ".epub")).array; +      } +      string dirtop() { +        return "".chainPath("").array; +      } +      string doc_meta_inf(string fn_src) { +        return asNormalizedPath(dirtop.chainPath("META-INF")).array; +      } +      string doc_oebps(string fn_src) { +        return asNormalizedPath(dirtop.chainPath("OEBPS")).array; +      } +      string doc_oebps_css(string fn_src) { +        return asNormalizedPath(doc_oebps(fn_src).chainPath("css")).array; +      } +      string doc_oebps_image(string fn_src) { +        return asNormalizedPath(doc_oebps(fn_src).chainPath("image")).array; +      } +      string fn_mimetypes(string fn_src) { +        return asNormalizedPath(dirtop.chainPath("mimetypes")).array; +      } +      string fn_dmi_container_xml(string fn_src) { +        return asNormalizedPath(doc_meta_inf(fn_src).chainPath("container.xml")).array; +      } +      string fn_oebps_toc_nav_xhtml(string fn_src) { +        return asNormalizedPath(doc_oebps(fn_src).chainPath("toc_nav.xhtml")).array; +      } +      string fn_oebps_toc_ncx(string fn_src) { +        return asNormalizedPath(doc_oebps(fn_src).chainPath("toc.ncx")).array; +      } +      string fn_oebps_content_opf(string fn_src) { +        return asNormalizedPath(doc_oebps(fn_src).chainPath("content.opf")).array; +      } +      string fn_oebps_content_xhtml(string fn_src, string seg_filename) { +        return asNormalizedPath(doc_oebps(fn_src).chainPath(seg_filename ~ ".xhtml")).array; +      } +      string fn_oebps_css(string fn_src) { +        return asNormalizedPath(doc_oebps_css(fn_src).chainPath("epub.css")).array; +      } +      debug(epub_output) { +        string dbg_docdir(string fn_src) { +          return base.chainPath(base_filename(fn_src)).array; +        } +        string dbg_docdir_oebps(string fn_src) { +          return dbg_docdir(fn_src).chainPath("OEBPS").array; +        } +        string dbg_doc_meta_inf(string fn_src) { +          return dbg_docdir(fn_src).chainPath("META-INF").array; +        } +        string dbg_doc_oebps(string fn_src) { +          return dbg_docdir(fn_src).chainPath("OEBPS").array; +        } +        string dbg_doc_oebps_css(string fn_src) { +          return dbg_doc_oebps(fn_src).chainPath("css").array; +        } +        string dbg_doc_oebps_image(string fn_src) { +          return dbg_doc_oebps(fn_src).chainPath("image").array; +        } +        string dbg_fn_mimetypes(string fn_src) { +          return dbg_docdir(fn_src).chainPath("mimetypes").array; +        } +        string dbg_fn_dmi_container_xml(string fn_src) { +          return dbg_doc_meta_inf(fn_src).chainPath("container.xml").array; +        } +        string dbg_fn_oebps_toc_nav_xhtml(string fn_src) { +          return dbg_docdir_oebps(fn_src).chainPath("toc_nav.xhtml").array; +        } +        string dbg_fn_oebps_toc_ncx(string fn_src) { +          return dbg_docdir_oebps(fn_src).chainPath("toc.ncx").array; +        } +        string dbg_fn_oebps_content_opf(string fn_src) { +          return dbg_docdir_oebps(fn_src).chainPath("content.opf").array; +        } +        string dbg_fn_oebps_content_xhtml(string fn_src, string seg_filename) { +          return dbg_docdir_oebps(fn_src).chainPath(seg_filename ~ ".xhtml").array; +        } +        string dbg_fn_oebps_css(string fn_src) { +          return dbg_doc_oebps_css(fn_src).chainPath("epub.css").array; +        } +      } +    } +    return _PathsStruct(); +  } +} +template SiSUpathsSQLiteDiscrete() { +  mixin SiSUrgxInit; +  static auto rgx = Rgx(); +  auto SiSUpathsSQLiteDiscrete(Po,Lng)( +    Po  output_pth_root, +    Lng lng, +  ) { +    struct _PathsStruct { +      string base_filename(string fn_src) { +        return fn_src.baseName.stripExtension; +      } +      string base() { +        auto out_pth = SiSUoutPaths!()(output_pth_root, lng); +        string base_dir = "sqlite"; +        return asNormalizedPath((out_pth.output_base).chainPath(base_dir)).array; +      } +      string seg(string fn_src) { +        return asNormalizedPath(base.chainPath(base_filename(fn_src))).array; +      } +      string sqlite_file(string fn_src) { +        return asNormalizedPath(base.chainPath(base_filename(fn_src) ~ ".sql.db")).array; +      } +    } +    return _PathsStruct(); +  } +} +template SiSUpathsSQLite() { +  mixin SiSUrgxInit; +  static auto rgx = Rgx(); +  auto SiSUpathsSQLite(DbN, Po)( +    DbN db_name, +    Po  output_pth_root, +  ) { +    struct _PathsStruct { +      string base_filename(string fn_src) { +        return fn_src.baseName.stripExtension; +      } +      string base() { +        auto out_pth = SiSUoutPathSQLite!()(output_pth_root); // decide whether to have separate files for each language +        string base_dir = "sqlite"; +        return asNormalizedPath((out_pth.output_root).chainPath(base_dir)).array; +      } +      string sqlite_file() { +        return asNormalizedPath(base.chainPath(base_filename(db_name) ~ ".sql.db")).array; +      } +    } +    return _PathsStruct(); +  } +} diff --git a/src/doc_reform/output/rgx.d b/src/doc_reform/output/rgx.d new file mode 100644 index 0000000..0d23f11 --- /dev/null +++ b/src/doc_reform/output/rgx.d @@ -0,0 +1,106 @@ +/++ +  regex: regular expressions used in sisu document parser ++/ +module doc_reform.output.rgx; +static template SiSUoutputRgxInit() { +  import doc_reform.output.defaults; +  static struct Rgx { +    static newline                                        = ctRegex!("\n", "mg"); +    static strip_br                                       = ctRegex!("^<br>\n|<br>\n*$"); +    static space                                          = ctRegex!(`[ ]`, "mg"); +    static spaces_line_start                              = ctRegex!(`^(?P<opening_spaces>[ ]+)`, "mg"); +    static spaces_multiple                                = ctRegex!(`(?P<multiple_spaces>[ ]{2,})`, "mg"); +    static two_spaces                                     = ctRegex!(`[ ]{2}`, "mg"); +    static nbsp_char                                      = ctRegex!(`░`, "mg"); +    static nbsp_chars_line_start                          = ctRegex!(`^░+`, "mg"); +    static nbsp_and_space                                 = ctRegex!(` [ ]`, "mg"); +    static nbsp_char_and_space                            = ctRegex!(`░[ ]`, "mg"); +    static special_markup_chars                           = ctRegex!(`[【】〖〗┥┝┤├¤░┘┙┚┼┿╂┊┏┚┆■]`, "mg"); +    static src_pth_sst_or_ssm                             = ctRegex!(`^(?P<path>[/]?(?:[a-zA-Z0-9._-]+/)*)(?P<filename>[a-zA-Z0-9._-]+[.](?P<extension>ss[tm]))$`); +    static src_pth_pod_sst_or_ssm                         = ctRegex!(`^(?P<podpath>[/]?(?:[a-zA-Z0-9._-]+/)*)media/text/[a-z]{2}/(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])$`); +    static src_pth_contents                               = ctRegex!(`^(?P<path>[/]?(?:[a-zA-Z0-9._-]+/)*)(?P<filename>[a-zA-Z0-9._-]+)/sisupod[.]manifest$`); +    static src_pth_pod_root                               = ctRegex!(`^(?P<podroot>(?:[/]?(?:[a-zA-Z0-9._-]+/)*)(sisupod))$`); +    static src_pth_zip                                    = ctRegex!(`^(?P<path>[/]?(?:[a-zA-Z0-9._-]+/)*)(?P<filename>[a-zA-Z0-9._-]+[.]zip)$`); +    static src_pth_unzip_pod                              = ctRegex!(`^(?P<path>media/text/[a-z]{2}/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[im])$`); +    static src_pth_types                                  = +      ctRegex!(`^(?P<path>[/]?[a-zA-Z0-9._-]+/)*(?P<gotfile>(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])|(?P<filelist>[a-zA-Z0-9._-]+/sisupod[.]manifest)|(?P<filezip>[a-zA-Z0-9._-]+[.]zip))$`); +    static pod_content_location                           = +      ctRegex!(`^(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])(?P<languages>(?:\s+[a-z]{2}(?:,|$))+)`, "mg"); +    static src_fn                                         = +      ctRegex!(`^([/]?(?:[a-zA-Z0-9._-]+/)*)(?P<fn_src>(?P<fn_base>[a-zA-Z0-9._-]+)[.](?P<fn_src_suffix>ss[tm]))$`); +    static src_fn_master                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssm)$`); +    static src_fn_text                                    = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]sst)$`); +    static src_fn_insert                                  = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ssi)$`); +    static src_fn_find_inserts                            = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[im])$`); +    static insert_src_fn_ssi_or_sst                       = ctRegex!(`^<<\s*(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`); +    static src_base_parent_dir_name                       = ctRegex!(`[/](?P<dir>(?:[a-zA-Z0-9._-]+))(?:/media/text/[a-z]{2})$`); // formalizes dir structure +    static src_base_parent_path                           = ctRegex!(`(?P<dir>(?:[/a-zA-Z0-9._-]+))(?:/media/text/[a-z]{2})$`); // formalizes dir structure +    static src_formalised_file_path_parts                 = ctRegex!(`(?P<pth>(?:[/a-zA-Z0-9._-]+?)(?P<dir>[a-zA-Z0-9._-]+))(?:/media/text/[a-z]{2})$`); // formalizes dir structure +    /+ line breaks +/ +    static br_line                                        = ctRegex!(`┘`, "mg"); +    static br_nl                                          = ctRegex!(`┙`, "mg"); +    static br_paragraph                                   = ctRegex!(`┚`, "mg"); +    static br_page_line                                   = ctRegex!(`┼`, "mg"); +    static br_page                                        = ctRegex!(`┿`, "mg"); +    static br_page_new                                    = ctRegex!(`╂`, "mg"); +    /+ inline markup footnotes endnotes +/ +    static inline_notes_al                                = ctRegex!(`【(?:[*+]\s+|\s*)(.+?)】`, "mg"); +    static inline_notes_al_special                        = ctRegex!(`【(?:[*+]\s+)(.+?)】`, "mg"); // TODO remove match when special footnotes are implemented +    static inline_notes_al_gen                            = ctRegex!(`【.+?】`, "m"); +    static inline_notes_al_gen_text                       = ctRegex!(`【(?P<text>.+?)】`, "m"); +    static inline_notes_al_gen_ref                        = ctRegex!(`【(?P<ref>[*+]\s+)\s*(?P<text>.+?)】`, "mg"); +    static inline_al_delimiter_open_regular               = ctRegex!(`【\s`, "m"); +    static inline_al_delimiter_open_symbol_star           = ctRegex!(`【[*]\s`, "m"); +    static inline_al_delimiter_open_symbol_plus           = ctRegex!(`【[+]\s`, "m"); +    static inline_al_delimiter_close_regular              = ctRegex!(`】`, "m"); +    static inline_al_delimiter_open_and_close_regular     = ctRegex!(`【|】`, "m"); +    static inline_notes_delimiter_al_regular              = ctRegex!(`【(.+?)】`, "mg"); +    static inline_notes_delimiter_al_regular_number_note  = ctRegex!(`【(\d+)\s+(.+?)】`, "mg"); +    static inline_al_delimiter_open_asterisk              = ctRegex!(`【\*`, "m"); +    static inline_al_delimiter_open_plus                  = ctRegex!(`【\+`, "m"); +    static inline_text_and_note_al                        = ctRegex!(`(?P<text>.+?)【(?:[*+ ]*)(?P<note>.+?)】`, "mg"); +    static inline_text_and_note_al_                       = ctRegex!(`(.+?(?:【[*+]*\s+.+?】|$))`, "mg"); +    /+ inline markup footnotes endnotes +/ +    static inline_image                                   = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>\S+?\.(?:jpg|gif|png)),w(?P<width>\d+)h(?P<height>\d+))\s*(?P<post>.*?┝┤.+?├)`, "mg"); +    static inline_image_without_dimensions                = ctRegex!(`(?P<pre>┥)☼(?P<imginf>(?P<img>\S+?\.(?:jpg|gif|png)),w(?P<width>0)h(?P<height>0))\s*(?P<post>.*?┝┤.+?├)`, "mg"); +    static inline_link                                    = ctRegex!(`┥(?P<text>.+?)┝┤(?P<link>.+?)├`, "mg"); +    static inline_link_clean                              = ctRegex!(`┤(?:.+?)├|[┥┝]`, "mg"); +    static inline_a_url                                   = ctRegex!(`(┤)(\S+?)(├)`, "mg"); +    static url                                            = ctRegex!(`https?://`, "mg"); +    static inline_link_subtoc                             = ctRegex!(`^(?P<level>[5-7])~ ┥(?P<text>.+?)┝┤(?P<link>.+?)├`, "mg"); +    static fn_suffix                                      = ctRegex!(`\.fnSuffix`, "mg"); +    static inline_link_fn_suffix                          = ctRegex!(`¤(.+?)(\.fnSuffix)`, "mg"); +    static inline_seg_link                                = ctRegex!(`(¤)(?:.+?)\.fnSuffix`, "mg"); +    static mark_internal_site_lnk                         = ctRegex!(`¤`, "mg"); +    static quotation_mark_sql_insert_delimiter            = ctRegex!("[']", "mg"); +    static quotation_mark_various                         = ctRegex!(q"¶['‘’“”"`´¨]¶", "mg"); +    /+ inline markup font face mod +/ +    static inline_faces                                   = ctRegex!(`(?P<markup>(?P<mod>[*!_^,+#-])\{(?P<text>.+?)\}[*!_^,+#-])`, "mg"); +    static inline_emphasis                                = ctRegex!(`\*\{(?P<text>.+?)\}\*`, "mg"); +    static inline_bold                                    = ctRegex!(`!\{(?P<text>.+?)\}!`, "mg"); +    static inline_underscore                              = ctRegex!(`_\{(?P<text>.+?)\}_`, "mg"); +    static inline_italics                                 = ctRegex!(`/\{(?P<text>.+?)\}/`, "mg"); +    static inline_superscript                             = ctRegex!(`\^\{(?P<text>.+?)\}\^`, "mg"); +    static inline_subscript                               = ctRegex!(`,\{(?P<text>.+?)\},`, "mg"); +    static inline_strike                                  = ctRegex!(`-\{(?P<text>.+?)\}-`, "mg"); +    static inline_insert                                  = ctRegex!(`\+\{(?P<text>.+?)\}\+`, "mg"); +    static inline_mono                                    = ctRegex!(`#\{(?P<text>.+?)\}#`, "mg"); +    static inline_mono_box                                = ctRegex!(`■\{(?P<text>.+?)\}■`, "mg"); +    static inline_cite                                    = ctRegex!(`"\{(?P<text>.+?)\}"`, "mg"); +    static inline_faces_line                              = ctRegex!(`^[*!/_]_ (?P<text>.+?)((?: [\\]{2}|[~]#){0,2}$)`); +    static inline_emphasis_line                           = ctRegex!(`^\*_ (?P<text>.+?)((?: [\\]{2}|[~]#){0,2}$)`); +    static inline_bold_line                               = ctRegex!(`^!_ (?P<text>.+?)((?: [\\]{2}|[~]#){0,2}$)`); +    static inline_italics_line                            = ctRegex!(`^/_ (?P<text>.+?)((?: [\\]{2}|[~]#){0,2}$)`); +    static inline_underscore_line                         = ctRegex!(`^__ (?P<text>.+?)((?: [\\]{2}|[~]#){0,2}$)`); +    static inline_fontface_clean                          = ctRegex!(`[*!_/^,+#■"-]\{|\}[*!_/^,+#■"-]`, "mg"); +    static no_header_rgx                                  = ctRegex!(`^=NULL$`); +    /+ table delimiters +/ +    static table_delimiter_col                           = ctRegex!("[ ]*[┊][ ]*", "mg"); +    static table_delimiter_row                           = ctRegex!("[ ]*\n", "mg"); +    static xhtml_ampersand                            = ctRegex!(`[&]`);      // & +    static xhtml_quotation                            = ctRegex!(`["]`);      // " +    static xhtml_less_than                            = ctRegex!(`[<]`);      // < +    static xhtml_greater_than                         = ctRegex!(`[>]`);      // > +    static xhtml_line_break                           = ctRegex!(` [\\]{2}`); // <br /> +  } +} diff --git a/src/doc_reform/output/source_sisupod.d b/src/doc_reform/output/source_sisupod.d new file mode 100644 index 0000000..fa041fd --- /dev/null +++ b/src/doc_reform/output/source_sisupod.d @@ -0,0 +1,278 @@ +module doc_reform.output.source_sisupod; +template SiSUpod() { +  import doc_reform.output; +  import +    std.digest.sha, +    std.file, +    std.outbuffer, +    std.zip, +    std.conv : to; +  import +    doc_reform.output.create_zip_file, +    doc_reform.output.xmls; +  void SiSUpod(T)(T doc_matters) { +    debug(asserts) { +      // static assert(is(typeof(doc_matters) == tuple)); +    } +    mixin SiSUoutputRgxInit; +    string pwd = doc_matters.env.pwd; +    auto src_path_info = doc_matters.src_path_info; +    auto pth_sisudoc_src = doc_matters.src_path_info; +    auto pths_sisupod = SiSUpathsSisupods!()(doc_matters); +    mixin SiSUlanguageCodes; +    auto lang = Lang(); +    static auto rgx = Rgx(); +    assert (doc_matters.src.filename.match(rgx.src_fn)); +    try { +      /+ create directory structure +/ +      if (!exists(pths_sisupod.sisupod_dir_())) { +        // used both by sisupod zipped (& sisupod filesystem (unzipped) which makes its own recursive dirs) +        pths_sisupod.sisupod_dir_().mkdirRecurse; +      } +      if (doc_matters.opt.action.source) { +        if (!exists(pths_sisupod.text_root(doc_matters.src.filename).filesystem_open_zpod)) { +          pths_sisupod.text_root(doc_matters.src.filename).filesystem_open_zpod.mkdirRecurse; +        } +        if (!exists(pths_sisupod.conf_root(doc_matters.src.filename).filesystem_open_zpod)) { +          pths_sisupod.conf_root(doc_matters.src.filename).filesystem_open_zpod.mkdirRecurse; +        } +        if (!exists(pths_sisupod.media_root(doc_matters.src.filename).filesystem_open_zpod)) { +          pths_sisupod.media_root(doc_matters.src.filename).filesystem_open_zpod.mkdirRecurse; +        } +        if (!exists(pths_sisupod.css(doc_matters.src.filename).filesystem_open_zpod)) { +          pths_sisupod.css(doc_matters.src.filename).filesystem_open_zpod.mkdirRecurse; +        } +        if (!exists(pths_sisupod.image_root(doc_matters.src.filename).filesystem_open_zpod)) { +          pths_sisupod.image_root(doc_matters.src.filename).filesystem_open_zpod.mkdirRecurse; +        } +        if (!exists(pths_sisupod.doc_lng(doc_matters.src.filename, doc_matters.src.language).filesystem_open_zpod)) { +          pths_sisupod.doc_lng(doc_matters.src.filename, doc_matters.src.language).filesystem_open_zpod.mkdirRecurse; +        } +      } +      debug(sisupod) { +        writeln(__LINE__, ": ", +          doc_matters.src.filename, " -> ", +          pths_sisupod.fn_doc(doc_matters.src.filename, doc_matters.src.language).filesystem_open_zpod +        ); +      } +      auto zip = new ZipArchive(); +      auto fn_sisupod = pths_sisupod.sisupod_filename(doc_matters.src.filename).zpod; +      { /+ bundle images +/ +        foreach (image; doc_matters.srcs.image_list) { +          debug(sisupodimages) { +            writeln( +              pth_sisudoc_src.image_root.to!string, "/", image, " -> ", +              pths_sisupod.image_root(doc_matters.src.filename).zpod, "/", image +            ); +          } +          auto fn_src_in = doc_matters.src.image_dir_path ~ "/" ~ image; +          auto fn_src_out_sisupod_zip_base +            = pths_sisupod.image_root(doc_matters.src.filename).zpod.to!string +            ~ "/" ~ image; +          auto fn_src_out_filesystem +            = pths_sisupod.image_root(doc_matters.src.filename).filesystem_open_zpod.to!string +            ~ "/" ~ image; +          if (exists(fn_src_in)) { +            debug(io) { +              writeln("(io debug) src out found: ", fn_src_in); +            } +            if (doc_matters.opt.action.source) { +              fn_src_in.copy(fn_src_out_filesystem); +            } +            if (doc_matters.opt.action.sisupod) { +              auto zip_arc_member_file = new ArchiveMember(); +              zip_arc_member_file.name = fn_src_out_sisupod_zip_base; +              auto zip_data = new OutBuffer(); +              zip_data.write(cast(char[]) ((fn_src_in).read)); +              zip_arc_member_file.expandedData = zip_data.toBytes(); +              zip.addMember(zip_arc_member_file); +            } +          } else { +            if (doc_matters.opt.action.verbose) { +              writeln("WARNING (io) src out NOT found (image): ", fn_src_in); +            } +          } +        } +      } { /+ bundle sisu_document_make +/ +        auto fn_src_in = ((doc_matters.src.is_pod) +          ? doc_matters.src.conf_dir_path +          : pth_sisudoc_src.conf_root).to!string +          ~ "/" ~ "sisu_document_make"; +        auto fn_src_out_sisupod_zip_base +          = pths_sisupod.conf_root(doc_matters.src.filename).zpod.to!string ~ "/" ~ "sisu_document_make"; +        auto fn_src_out_filesystem +          = pths_sisupod.conf_root(doc_matters.src.filename).filesystem_open_zpod.to!string +          ~ "/" ~ "sisu_document_make"; +        if (exists(fn_src_in)) { +          debug(io) { +            writeln("(io debug) src out found: ", fn_src_in); +          } +          if (doc_matters.opt.action.source) { +            fn_src_in.copy(fn_src_out_filesystem); +          } +          if (doc_matters.opt.action.sisupod) { +            auto zip_arc_member_file = new ArchiveMember(); +            zip_arc_member_file.name = fn_src_out_sisupod_zip_base; +            auto zip_data = new OutBuffer(); +            zip_data.write((fn_src_in).readText); +            zip_arc_member_file.expandedData = zip_data.toBytes(); +            zip.addMember(zip_arc_member_file); +          } +        } else { +          if (doc_matters.opt.action.verbose +          || doc_matters.opt.action.debug_do) { +            writeln("WARNING (io) src out NOT found (document make): ", fn_src_in); +          } +        } +      } { /+ bundle primary file +/ +        auto fn_src_in = doc_matters.src.file_with_absolute_path.to!string; +        auto fn_src_out_sisupod_zip_base +          = pths_sisupod.fn_doc(doc_matters.src.filename, doc_matters.src.language).zpod.to!string; +        auto fn_src_out_filesystem +          = pths_sisupod.fn_doc(doc_matters.src.filename, doc_matters.src.language).filesystem_open_zpod.to!string; // without root path: +        auto fn_src_out_inside_pod +          = pths_sisupod.fn_doc(doc_matters.src.filename, doc_matters.src.language).zpod.to!string; // without root path: +        string[] filelist_src_out_sisupod_arr; +        string[] filelist_src_zpod_arr; +        if (exists(fn_src_in)) { +          debug(io) { +            writeln("(io debug) src in found: ", fn_src_in); +          } +          filelist_src_out_sisupod_arr ~= fn_src_out_sisupod_zip_base; +          filelist_src_zpod_arr ~= fn_src_out_inside_pod; +          if (doc_matters.opt.action.source) { +            auto filelist +              = File(pths_sisupod.fn_pod_filelist(doc_matters.src.filename).filesystem_open_zpod, "w"); +            foreach (source_pth_and_fn; filelist_src_zpod_arr) { +              filelist.writeln(source_pth_and_fn); +            } +            fn_src_in.copy(fn_src_out_filesystem); +          } +          if (doc_matters.opt.action.sisupod) { +            auto zip_arc_member_file = new ArchiveMember(); +            zip_arc_member_file.name = fn_src_out_sisupod_zip_base; +            auto zip_data = new OutBuffer(); +            zip_data.write((fn_src_in).readText); +            zip_arc_member_file.expandedData = zip_data.toBytes(); +            zip.addMember(zip_arc_member_file); +          } +        } else { +          if (doc_matters.opt.action.verbose +          || doc_matters.opt.action.debug_do) { +            writeln("WARNING (io) src in NOT found (markup source): ", fn_src_in); +          } +        } +      } { /+ bundle insert files +/ +        if (doc_matters.srcs.file_insert_list.length > 0) { +          foreach (insert_file; doc_matters.srcs.file_insert_list) { +            debug(sisupod) { +              writeln( +                insert_file, " -> ", +                pths_sisupod.fn_doc_insert( +                  doc_matters.src.filename, +                  insert_file, +                  doc_matters.src.language, +                ).zpod +              ); +            } +            auto fn_src_in = insert_file; +            auto fn_src_out_sisupod_zip_base +              = pths_sisupod.fn_doc_insert( +                doc_matters.src.filename, +                insert_file, +                doc_matters.src.language, +              ).zpod.to!string; +            auto fn_src_out_filesystem +              = pths_sisupod.fn_doc_insert( +                doc_matters.src.filename, +                insert_file, +                doc_matters.src.language, +              ).filesystem_open_zpod.to!string; +            if (exists(fn_src_in)) { +              debug(io) { +                writeln("(io debug) src out found: ", fn_src_in); +              } +              if (doc_matters.opt.action.source) { +                fn_src_in.copy(fn_src_out_filesystem); +              } +              if (doc_matters.opt.action.sisupod) { +                auto zip_arc_member_file = new ArchiveMember(); +                zip_arc_member_file.name = fn_src_out_sisupod_zip_base; +                auto zip_data = new OutBuffer(); +                zip_data.write((fn_src_in).readText); +                zip_arc_member_file.expandedData = zip_data.toBytes(); +                zip.addMember(zip_arc_member_file); +                createZipFile!()(fn_sisupod, zip.build()); +              } +            } else { +              if (doc_matters.opt.action.verbose +              || doc_matters.opt.action.debug_do) { +                writeln("WARNING (io) src out NOT found (insert file): ", fn_src_in); +              } +            } +          } +        } +      } { +        auto fn_src_in = doc_matters.src.filename; +        if (doc_matters.opt.action.sisupod) { +          if (exists(doc_matters.src.file_with_absolute_path)) { +            createZipFile!()(fn_sisupod, zip.build()); +          } else { +            writeln("WARNING check missing source file(s): ", doc_matters.opt.action.sisupod); +          } +          if (!(exists(fn_sisupod))) { +            writeln("WARNING failed to create sisupod zip archive: ", fn_sisupod); +          } +        } +      } +      if (exists(fn_sisupod)) { +        try { +          if (doc_matters.opt.action.verbose) { +            auto data = (cast(byte[]) (fn_sisupod).read); +            writeln(doc_matters.src.filename, " >> "); +            writefln("%-(%02x%) %s", data.sha256Of, fn_sisupod); +          } +          debug(sisupod) { +            try { +              auto zipped = new ZipArchive((fn_sisupod).read); +              foreach (filename, member; zipped.directory) { +                auto data = zipped.expand(member); +                writeln("> ", filename, " length ", data.length); +              } +            } +            catch (ZipException ex) { +              // Handle errors +            } +            if (doc_matters.src.filename == "sisudoc/media/text/en/the_wealth_of_networks.yochai_benkler.sst") { +              assert( +                ((data).sha256Of).toHexString +                == "626F83A31ED82F42CF528E922C1643498A137ABA3F2E5AFF8A379EA79EA22A1E", +                "\nsisupod: sha256 value for " +                ~ doc_matters.src.filename +                ~ " has changed, is now: " +                ~ ((data).sha256Of).toHexString +              ); +            } +            if (doc_matters.src.filename == "sisudoc/media/text/en/sisu_markup_stress_test.sst") { +              assert( +                ((data).sha256Of).toHexString +                == "AAE0C87AB3F6D5F7385AEEA6EE661F56D40475CFE87AD930C78C9FE07FFB0D91", +                "\nsisupod: sha256 value for " +                ~ doc_matters.src.filename +                ~ " has changed, is now: " +                ~ ((data).sha256Of).toHexString +              ); +            } +          } +        } +        catch (ErrnoException ex) { +          // Handle errors +        } +      } +       +    } +    catch (ErrnoException ex) { +      // Handle error +    } +  } +} diff --git a/src/doc_reform/output/sqlite.d b/src/doc_reform/output/sqlite.d new file mode 100644 index 0000000..a765fd7 --- /dev/null +++ b/src/doc_reform/output/sqlite.d @@ -0,0 +1,1242 @@ +module doc_reform.output.sqlite; +import doc_reform.output; +import +  std.file, +  std.conv : to; +import d2sqlite3; +import std.typecons : Nullable; +mixin SiSUoutputRgxInit; +static auto rgx = Rgx(); +long _metadata_tid_lastrowid; +template SQLiteHubBuildTablesAndPopulate() { +  void SQLiteHubBuildTablesAndPopulate(D,I)( +    D    doc_abstraction, +    I    doc_matters, +  ) { +    auto pth_sqlite = SiSUpathsSQLite!()(doc_matters.sqlite.filename, doc_matters.output_path); +    pth_sqlite.base.mkdirRecurse; +    auto db = Database(pth_sqlite.sqlite_file); +    template SQLiteDbStatementComposite() { +      void SQLiteDbStatementComposite(Db,D,I)( +        Db   db, +        D    doc_abstraction, +        I    doc_matters, +      ) { +        { +          string _db_statement; +          { +            if ((doc_matters.opt.action.sqlite_db_create)) { +              auto pth_sqlite = SiSUpathsSQLite!()(doc_matters.sqlite.filename, doc_matters.output_path); +              pth_sqlite.base.mkdirRecurse; +              _db_statement ~= SQLiteTablesReCreate!()(); +              SQLiteDbRun!()(db, _db_statement, doc_matters.opt.action, "TABLE RE-CREATE"); +            } +            if (doc_matters.opt.action.sqlite_delete) { +              _db_statement ~= SQLiteDeleteDocument!()(doc_matters); +              SQLiteDbRun!()(db, _db_statement, doc_matters.opt.action, "DELETE Document"); +            } +            if (doc_matters.opt.action.sqlite_update) { +              _db_statement ~= SQLiteDeleteDocument!()(doc_matters); +              SQLiteDbRun!()(db, _db_statement, doc_matters.opt.action, "DELETE Document"); +              _db_statement ~= SQLiteInsertMetadata!()(doc_matters); +              SQLiteDbRun!()(db, _db_statement, doc_matters.opt.action, "INSERT MetaData"); +              /+ get tid (lastrowid or max) for use in doc_objects table +/ +              _db_statement ~= SQLiteInsertDocObjectsLoop!()(doc_abstraction, doc_matters); +              SQLiteDbRun!()(db, _db_statement, doc_matters.opt.action, "INSERT DocObjects"); +            } +          } +          db.close; +        } +        if (!(doc_matters.opt.action.quiet)) { +          writeln(" ", pth_sqlite.sqlite_file); +        } +      } +    } +    SQLiteDbStatementComposite!()(db, doc_abstraction, doc_matters); +  } +} +template SQLiteHubDiscreteBuildTablesAndPopulate() { +  void SQLiteHubDiscreteBuildTablesAndPopulate(D,I)( +    D    doc_abstraction, +    I    doc_matters, +  ) { +    auto pth_sqlite = SiSUpathsSQLiteDiscrete!()(doc_matters.output_path, doc_matters.src.language); +    pth_sqlite.base.mkdirRecurse; +    auto db = Database(pth_sqlite.sqlite_file(doc_matters.src.filename)); +    template SQLiteDiscreteDbStatementComposite() { +      void SQLiteDiscreteDbStatementComposite(Db,D,I)( +        Db   db, +        D    doc_abstraction, +        I    doc_matters, +      ) { +        { +          string _db_statement; +          { +            _db_statement ~= SQLiteTablesReCreate!()(); +            _db_statement ~= SQLiteInsertMetadata!()(doc_matters); +            _db_statement ~= SQLiteInsertDocObjectsLoop!()(doc_abstraction, doc_matters); +            SQLiteDbRun!()(db, _db_statement, doc_matters.opt.action, "table CREATE Tables, INSERT DocObjects"); +          } +          db.close; +        } +        if (!(doc_matters.opt.action.quiet)) { +          writeln(" ", pth_sqlite.sqlite_file(doc_matters.src.filename)); +        } +      } +    } +    SQLiteDiscreteDbStatementComposite!()(db, doc_abstraction, doc_matters); +  } +} +template SQLiteDbRun() { +  void SQLiteDbRun(Db,St,O)( +    Db       db, +    St       db_statement, +    O        opt_action, +    string   note, +  ) { +    debug(sql_statement) { +      writeln(db_statement); +    } +    try { +      db.run( +        "\nBEGIN;\n" ~ +        db_statement ~ +        "\nCOMMIT;\n" +      ); +      if (!(opt_action.sqlite_discrete) +        && !(opt_action.sqlite_db_create) +      ) { +      } +    } catch (ErrnoException ex) { +      writeln("ERROR SQLite : ", ex); +    } catch (Exception ex) { +      writeln("ERROR SQLite : ", ex); +    } +    if (opt_action.debug_do) { +      writeln(note); +      if (opt_action.verbose) { +        writeln(db_statement); +      } +    } +  } +} +template SQLinsertDelimiter() { +  auto SQLinsertDelimiter(string _txt) { +    _txt = _txt +      .replaceAll(rgx.quotation_mark_sql_insert_delimiter, "$0$0"); +    return _txt; +  } +} +template SQLiteFormatAndLoadObject() { +  auto SQLiteFormatAndLoadObject(I)( +    I    doc_matters, +  ) { +    mixin SiSUoutputRgxInit; +    struct sqlite_format_and_load_objects { +      auto generic_munge_sanitize_text_for_search( +        string _txt, +      ) { +        string _notes; +        string _urls; +        if (_txt.matchFirst(rgx.inline_notes_al_gen)) { +          foreach (m; _txt.matchAll(rgx.inline_notes_al_gen_text)) { +            _notes ~= "\n" ~ m["text"]; +          } +          _txt = _txt.replaceAll(rgx.inline_notes_al_gen, ""); +        } +        if (_txt.matchFirst(rgx.inline_link)) { +          foreach (m; _txt.matchAll(rgx.inline_link)) { +            if (m["link"].match(rgx.url)) { +              _urls ~= "\n" ~ m["link"]; +            } +          } +          _txt = _txt.replaceAll(rgx.inline_link_clean, ""); +        } +        if (_notes.length > 0) { +          _txt ~= _notes; +        } +        if (_urls.length > 0) { +          _txt ~= _urls; +        } +        if (doc_matters.opt.action.debug_do) { +          writeln(_txt, "\n"); +        } +        debug(sql_text_clean) { +          writeln(_txt); +        } +        return _txt; +      } +      auto munge_html(O)( +        auto ref const O    obj, +      ) { +        string _html_special_characters(string _txt){ +          _txt = _txt +            .replaceAll(rgx.xhtml_ampersand,    "&") +            .replaceAll(rgx.xhtml_quotation,    """) +            .replaceAll(rgx.xhtml_less_than,    "<") +            .replaceAll(rgx.xhtml_greater_than, ">") +            .replaceAll(rgx.nbsp_char,          " ") +            .replaceAll(rgx.xhtml_line_break,   "<br />"); +          return _txt; +        } +        string _html_font_face(string _txt){ +          _txt = _txt +            .replaceAll(rgx.inline_emphasis,    "<em>$1</em>") +            .replaceAll(rgx.inline_bold,        "<b>$1</b>") +            .replaceAll(rgx.inline_underscore,  "<u>$1</u>") +            .replaceAll(rgx.inline_italics,     "<i>$1</i>") +            .replaceAll(rgx.inline_superscript, "<sup>$1</sup>") +            .replaceAll(rgx.inline_subscript,   "<sub>$1</sub>") +            .replaceAll(rgx.inline_strike,      "<del>$1</del>") +            .replaceAll(rgx.inline_insert,      "<ins>$1</ins>") +            .replaceAll(rgx.inline_mono,        "<tt>$1</tt>") +            .replaceAll(rgx.inline_cite,        "<cite>$1</cite>"); +          return _txt; +        } +        string _notes; +        string _urls; +        string _txt = _html_font_face(_html_special_characters(obj.text)); +        if (_txt.matchFirst(rgx.inline_notes_al_gen)) { +          foreach (m; _txt.matchAll(rgx.inline_notes_al_gen_text)) { +            _notes ~= "\n" ~ m["text"]; +          } +          _txt = _txt.replaceAll(rgx.inline_notes_al_gen_ref, "<sup>$1</sup> "); +        } +        if (_txt.matchFirst(rgx.inline_link)) { +          foreach (m; _txt.matchAll(rgx.inline_link)) { +          } +          _txt = _txt.replaceAll(rgx.inline_link_clean, ""); +        } +        if (_notes.length > 0) { +          _txt ~= _notes; +        } +        if (doc_matters.opt.action.debug_do) { +          writeln(_txt, "\n"); +        } +        return _txt; +      } +      string html_special_characters(string _txt){ +        _txt = _txt +          .replaceAll(rgx.xhtml_ampersand,    "&") +          .replaceAll(rgx.xhtml_quotation,    """) +          .replaceAll(rgx.xhtml_less_than,    "<") +          .replaceAll(rgx.xhtml_greater_than, ">") +          .replaceAll(rgx.nbsp_char,          " ") +          .replaceAll(rgx.xhtml_line_break,   "<br />"); +        return _txt; +      } +      string html_special_characters_code(string _txt){ +        _txt = _txt +          .replaceAll(rgx.xhtml_ampersand,    "&") +          .replaceAll(rgx.xhtml_quotation,    """) +          .replaceAll(rgx.xhtml_less_than,    "<") +          .replaceAll(rgx.xhtml_greater_than, ">") +          .replaceAll(rgx.nbsp_char,          " "); +        return _txt; +      } +      string html_font_face(string _txt){ +        _txt = _txt +          .replaceAll(rgx.inline_emphasis,    "<em>$1</em>") +          .replaceAll(rgx.inline_bold,        "<b>$1</b>") +          .replaceAll(rgx.inline_underscore,  "<u>$1</u>") +          .replaceAll(rgx.inline_italics,     "<i>$1</i>") +          .replaceAll(rgx.inline_superscript, "<sup>$1</sup>") +          .replaceAll(rgx.inline_subscript,   "<sub>$1</sub>") +          .replaceAll(rgx.inline_strike,      "<del>$1</del>") +          .replaceAll(rgx.inline_insert,      "<ins>$1</ins>") +          .replaceAll(rgx.inline_mono,        "<tt>$1</tt>") +          .replaceAll(rgx.inline_cite,        "<cite>$1</cite>"); +        return _txt; +      } +      auto html_heading(O)( +        auto ref const O    obj, +      ) { +        string _txt = munge_html(obj); +        string o = format(q"¶<p class="%s"><b> +            %s +          </b></p>¶", +            obj.metainfo.is_a, +            _txt, +          ); +        return o; +      } +      auto html_para(O)( +        auto ref const O    obj, +      ) { +        string _txt = munge_html(obj); +        _txt = (obj.attrib.bullet) ? ("●  " ~ _txt) : _txt; +        string o = format(q"¶<p class="%s" indent="h%si%s"> +          %s +        </p>¶", +            obj.metainfo.is_a, +            obj.attrib.indent_hang, +            obj.attrib.indent_base, +            _txt +          ); +        return o; +      } +      auto html_quote(O)( +        auto ref const O    obj, +      ) { +        string _txt = munge_html(obj); +        string o = format(q"¶<p class="%s"> +          %s +        </p>¶", +            obj.metainfo.is_a, +            _txt +          ); +        return o; +      } +      auto html_group(O)( +        auto ref const O    obj, +      ) { +        string _txt = munge_html(obj); +        string o = format(q"¶<p class="%s"> +          %s +        </p>¶", +            obj.metainfo.is_a, +            _txt +          ); +        return o; +      } +      auto html_block(O)( +        auto ref const O    obj, +      ) { +        string _txt = munge_html(obj); +        string o = format(q"¶ +        <p class="%s">%s</p>¶", +            obj.metainfo.is_a, +            _txt.stripRight +          ); +        return o; +      } +      auto html_verse(O)( +        auto ref const O    obj, +      ) { +        string _txt = munge_html(obj); +        string o = format(q"¶<p class="%s">%s</p>¶", +            obj.metainfo.is_a, +            _txt +          ); +        return o; +      } +      auto html_code(O)( +        auto ref const O    obj, +      ) { +        string _txt = html_special_characters_code(obj.text); +        string o = format(q"¶<p class="%s">%s</p>¶", +            obj.metainfo.is_a, +            _txt +          ); +        return o; +      } +      auto html_table(O)( +        auto ref const O     obj, +      ) { +        auto _tablarize(O)( +          auto ref const O    obj, +          string                     _txt, +        ) { +          string[] _table_rows = _txt.split(rgx.table_delimiter_row); +          string[] _table_cols; +          string _table; +          string _tablenote; +          foreach(row_idx, row; _table_rows) { +            _table_cols = row.split(rgx.table_delimiter_col); +              _table ~= "<tr>"; +              foreach(col_idx, cell; _table_cols) { +                if ((_table_cols.length == 1) +                && (_table_rows.length <= row_idx+2)) { // check row_idx+2 (rather than == ++row_idx) +                  _tablenote ~= cell; +                } else { +                  string _col_is = (row_idx == 0 && obj.table.heading) ? "th" : "td"; +                  string _align = ("style=\"text-align:" +                  ~ ((obj.table.column_aligns[col_idx] == "l") +                  ? "left\"" : "right\"")); +                  _table ~= "<" +                    ~ _col_is +                    ~ " width=\"" +                    ~ obj.table.column_widths[col_idx].to!string +                    ~ "%\" " +                    ~ _align +                    ~ ">"; +                  _table ~= cell; +                  _table ~= "</" +                    ~ _col_is +                    ~ ">"; +                } +              } +              _table ~= "</tr>"; +            } +          auto t = tuple( +            _table, +            _tablenote, +          ); +          return t; +        } +        string _txt = munge_html(obj); +        auto t = _tablarize(obj, _txt); +        _txt = t[0]; +        string _note = t[1]; +        string o = format(q"¶<p class="%s"> +          <table summary="normal text css" width="95%%" border="0" bgcolor="white" cellpadding="2" align="center"> +            %s +          </table> +          %s +        </p>¶", +          obj.metainfo.is_a, +          _txt, +          _note +        ); +        return o; +      } +      auto sqlite_load_string(O,Dm)( +        auto ref const O     obj, +        auto ref       Dm    doc_matters, +      ) { +        string o; +        return o; +      } +      auto postgresql_load_string(O,Dm)( +        auto ref const O     obj, +        auto ref       Dm    doc_matters, +      ) { +        string o; +        return o; +      } +      string sqlite_statement(O)( +        auto ref const O    obj, +        string                     _txt, +        string                     _html, +      ) { +        void _sql_exe(O)( +          string                   _sql, +        ) { +          writeln(_html); +          writeln(_sql); +        } +        string _sql; +        return _sql; +      } +      auto heading(O)( +        auto ref const O      obj, +      ) { +        string[string] obj_txt = [ +          "text": generic_munge_sanitize_text_for_search(obj.text), +          "html": html_heading(obj) +        ]; +        if (doc_matters.opt.action.debug_do) { +          debug(sql_txt) { +            writeln(obj_txt["text"]); +          } +          debug(sql_html) { +            writeln(obj_txt["html"]); +          } +        } else { +          // load sql +        } +        return obj_txt; +      } +      auto para(O)( +        auto ref const O     obj, +      ) { +        string[string] obj_txt = [ +          "text": generic_munge_sanitize_text_for_search(obj.text), +          "html": html_para(obj) +        ]; +        if (doc_matters.opt.action.debug_do) { +          debug(sql_txt) { +            writeln(obj_txt["text"]); +          } +          debug(sql_html) { +            writeln(obj_txt["html"]); +          } +        } else { +          // load sql +        } +        return obj_txt; +      } +      auto quote(O)( +        auto ref const O     obj, +      ) { +        string[string] obj_txt = [ +          "text": generic_munge_sanitize_text_for_search(obj.text), +          "html": html_quote(obj) +        ]; +        if (doc_matters.opt.action.debug_do) { +          debug(sql_txt) { +            writeln(obj_txt["text"]); +          } +          debug(sql_html) { +            writeln(obj_txt["html"]); +          } +        } else { +          // load sql +        } +        return obj_txt; +      } +      auto group(O)( +        auto ref const O     obj, +      ) { +        string[string] obj_txt = [ +          "text": generic_munge_sanitize_text_for_search(obj.text), +          "html": html_group(obj) +        ]; +        if (doc_matters.opt.action.debug_do) { +          debug(sql_txt) { +            writeln(obj_txt["text"]); +          } +          debug(sql_html) { +            writeln(obj_txt["html"]); +          } +        } else { +          // load sql +        } +        return obj_txt; +      } +      auto block(O)( +        auto ref const O     obj, +      ) { +        string[string] obj_txt = [ +          "text": generic_munge_sanitize_text_for_search(obj.text), +          "html": html_block(obj) +        ]; +        if (doc_matters.opt.action.debug_do) { +          debug(sql_txt) { +            writeln(obj_txt["text"]); +          } +          debug(sql_html) { +            writeln(obj_txt["html"]); +          } +        } else { +          // load sql +        } +        return obj_txt; +      } +      auto verse(O)( +        auto ref const O     obj, +      ) { +        string[string] obj_txt = [ +          "text": generic_munge_sanitize_text_for_search(obj.text), +          "html": html_verse(obj) +        ]; +        if (doc_matters.opt.action.debug_do) { +          debug(sql_txt) { +            writeln(obj_txt["text"]); +          } +          debug(sql_html) { +            writeln(obj_txt["html"]); +          } +        } else { +          // load sql +        } +        return obj_txt; +      } +      auto code(O)( +        auto ref const O     obj, +      ) { +        string[string] obj_txt = [ +          "text": generic_munge_sanitize_text_for_search(obj.text), +          "html": html_code(obj) +        ]; +        if (doc_matters.opt.action.debug_do) { +          debug(sql_txt) { +            writeln(obj_txt["text"]); +          } +          debug(sql_html) { +            writeln(obj_txt["html"]); +          } +        } else { +          // load sql +        } +        return obj_txt; +      } +      auto table(O)( +        auto ref const O     obj, +      ) { +        string[string] obj_txt = [ +          "text": generic_munge_sanitize_text_for_search(obj.text), +          "html": html_table(obj) +        ]; +        if (doc_matters.opt.action.debug_do) { +          debug(sql_txt) { +            writeln(obj_txt["text"]); +          } +          debug(sql_html) { +            writeln(obj_txt["html"]); +          } +        } else { +          // load sql +        } +        return obj_txt; +      } +    } +    return sqlite_format_and_load_objects(); +  } +} +template SQLiteTablesReCreate() { +  string SQLiteTablesReCreate()() { +    string _sql_instruct; +    _sql_instruct = format(q"¶ +      DROP INDEX IF EXISTS idx_ocn; +      DROP INDEX IF EXISTS idx_uid; +      DROP INDEX IF EXISTS idx_digest_clean; +      DROP INDEX IF EXISTS idx_digest_all; +      DROP INDEX IF EXISTS idx_clean; +      DROP INDEX IF EXISTS idx_title; +      DROP INDEX IF EXISTS idx_creator_author; +      DROP INDEX IF EXISTS src_filename; +      DROP INDEX IF EXISTS idx_language_document_char; +      DROP INDEX IF EXISTS idx_classify_topic_register; +      DROP TABLE IF EXISTS metadata_and_text; +      DROP TABLE IF EXISTS doc_objects; +      DROP TABLE IF EXISTS urls; +      CREATE TABLE metadata_and_text ( +        uid                              VARCHAR(256)      UNIQUE, /* filename, language char, pod/txt (decide on delimiter [,;:/]) */ +        src_composite_id_per_txt         VARCHAR(256)  NOT NULL,   /* UNIQUE, /* z pod name if any + src filename + language code */ +        src_composite_id_per_pod         VARCHAR(256)  NOT NULL,   /* z pod name if any + src filename */ +        title                            VARCHAR(800)  NOT NULL, +        title_main                       VARCHAR(400)  NOT NULL, +        title_sub                        VARCHAR(400)      NULL, +        title_short                      VARCHAR(400)      NULL, +        title_edition                    VARCHAR(10)       NULL, +        title_note                       VARCHAR(2500)     NULL, +        title_language                   VARCHAR(100)      NULL, +        title_language_char              VARCHAR(6)        NULL, +        creator_author                   VARCHAR(600)  NOT NULL, +        creator_author_email             VARCHAR(100)      NULL, +        creator_author_hon               VARCHAR(100)      NULL, +        creator_author_nationality       VARCHAR(100)      NULL, +        creator_editor                   VARCHAR(600)      NULL, +        creator_contributor              VARCHAR(600)      NULL, +        creator_illustrator              VARCHAR(600)      NULL, +        creator_photographer             VARCHAR(600)      NULL, +        creator_translator               VARCHAR(600)      NULL, +        creator_prepared_by              VARCHAR(600)      NULL, +        creator_digitized_by             VARCHAR(600)      NULL, +        creator_audio                    VARCHAR(600)      NULL, +        creator_video                    VARCHAR(600)      NULL, +        language_document                VARCHAR(100)      NULL, +        language_document_char           VARCHAR(6)    NOT NULL, +        language_original                VARCHAR(100)      NULL, +        language_original_char           VARCHAR(6)        NULL, +        date_added_to_site               VARCHAR(10)       NULL, +        date_available                   VARCHAR(10)       NULL, +        date_created                     VARCHAR(10)       NULL, +        date_issued                      VARCHAR(10)       NULL, +        date_modified                    VARCHAR(10)       NULL, +        date_published                   VARCHAR(10)       NULL, +        date_valid                       VARCHAR(10)       NULL, +        date_translated                  VARCHAR(10)       NULL, +        date_original_publication        VARCHAR(10)       NULL, +        date_generated                   VARCHAR(10)       NULL, +        publisher                        VARCHAR(600)      NULL, +        original_publisher               VARCHAR(600)      NULL, +        original_language                VARCHAR(100)      NULL, +        original_language_char           VARCHAR(6)        NULL, +        original_source                  VARCHAR(600)      NULL, +        original_institution             VARCHAR(600)      NULL, +        original_nationality             VARCHAR(100)      NULL, +        original_title                   VARCHAR(800)      NULL, +        rights_copyright                 VARCHAR(2500)     NULL, +        rights_copyright_audio           VARCHAR(2500)     NULL, +        rights_copyright_cover           VARCHAR(2500)     NULL, +        rights_copyright_illustrations   VARCHAR(2500)     NULL, +        rights_copyright_photographs     VARCHAR(2500)     NULL, +        rights_copyright_text            VARCHAR(2500)     NULL, +        rights_copyright_translation     VARCHAR(2500)     NULL, +        rights_copyright_video           VARCHAR(2500)     NULL, +        rights_license                   VARCHAR(2500)     NULL, +        identifier_oclc                  VARCHAR(30)       NULL, +        identifier_isbn                  VARCHAR(16)       NULL, +        classify_topic_register          VARCHAR(2500)     NULL, +        classify_subject                 VARCHAR(600)      NULL, +        classify_loc                     VARCHAR(30)       NULL, +        classify_dewey                   VARCHAR(30)       NULL, +        classify_keywords                VARCHAR(600)      NULL, +        notes_abstract                   TEXT              NULL, +        notes_description                TEXT              NULL, +        notes_comment                    TEXT              NULL, +        notes_coverage                   VARCHAR(200)      NULL, +        notes_relation                   VARCHAR(200)      NULL, +        notes_history                    VARCHAR(600)      NULL, +        notes_type                       VARCHAR(600)      NULL, +        notes_format                     VARCHAR(600)      NULL, +        notes_prefix                     TEXT              NULL, +        notes_prefix_a                   TEXT              NULL, +        notes_prefix_b                   TEXT              NULL, +        notes_suffix                     TEXT              NULL, +        src_filename                     VARCHAR(256)  NOT NULL, +        src_fingerprint                  VARCHAR(256)      NULL, +        src_filesize                     VARCHAR(10)       NULL, +        src_wordcount                    VARCHAR(10)       NULL, +        pod_name                         VARCHAR(256)      NULL, /* zipped pod, work to be done here */ +        pod_fingerprint                  VARCHAR(256)      NULL, /* zipped pod, work to be done here */ +        pod_size                         VARCHAR(10)       NULL, /* zipped pod, work to be done here */ +        src_text                         TEXT              NULL, +        fulltext                         TEXT              NULL, +        links                            TEXT              NULL +      ); +      CREATE TABLE doc_objects ( +        lid                              BIGINT            PRIMARY KEY, +        uid_metadata_and_text            VARCHAR(256)      REFERENCES metadata_and_text(uid) ON DELETE CASCADE, +        ocn                              SMALLINT, +        ocnd                             VARCHAR(6), +        ocns                             VARCHAR(6), +        clean                            TEXT              NULL, +        body                             TEXT              NULL, +        seg                              VARCHAR(256)      NULL, +        lev_an                           VARCHAR(1), +        lev                              SMALLINT          NULL, +        is_of_type                       VARCHAR(16), +        is_a                             VARCHAR(16), +        node                             VARCHAR(16)       NULL, +        parent                           VARCHAR(16)       NULL, +        last_decendant                   VARCHAR(16)       NULL, /* headings only */ +        digest_clean                     CHAR(256), +        digest_all                       CHAR(256), +        types                            CHAR(1)           NULL +      ); +      CREATE INDEX idx_ocn ON doc_objects(ocn); +      CREATE INDEX idx_digest_clean ON doc_objects(digest_clean); +      CREATE INDEX idx_digest_all ON doc_objects(digest_all); +      CREATE INDEX idx_clean ON doc_objects(clean); +      CREATE INDEX idx_title ON metadata_and_text(title); +      CREATE INDEX idx_author ON metadata_and_text(creator_author); +      CREATE INDEX idx_uid ON metadata_and_text(uid); +      CREATE INDEX idx_filename ON metadata_and_text(src_filename); +      CREATE INDEX idx_language ON metadata_and_text(language_document_char); +      CREATE INDEX idx_topics ON metadata_and_text(classify_topic_register); +    ¶",); +    return _sql_instruct; +  } +} +template SQLiteDeleteDocument() { +  string SQLiteDeleteDocument(I)( +    I doc_matters, +  ) { +    string _uid = doc_matters.src.doc_uid; +    string _delete_uid = format(q"¶ +    DELETE FROM metadata_and_text +    WHERE uid = '%s'; +    DELETE FROM doc_objects +    WHERE uid_metadata_and_text = '%s'; +    ¶", +      _uid, +      _uid, +    ); +    return _delete_uid; +  } +} +template SQLiteInsertMetadata() { +  string SQLiteInsertMetadata(I)( +    I doc_matters, +  ) { +    string _uid = SQLinsertDelimiter!()(doc_matters.src.doc_uid); +    string _insert_metadata = format(q"¶ +      INSERT INTO metadata_and_text ( +        uid, +        src_filename, +        src_composite_id_per_txt, +        src_composite_id_per_pod, +        title, +        title_main, +        title_sub, +        title_short, +        title_edition, +        title_language, +        classify_dewey, +        classify_keywords, +        classify_loc, +        classify_subject, +        classify_topic_register, +        creator_author, +        creator_author_email, +        creator_illustrator, +        creator_translator, +        date_added_to_site, +        date_available, +        date_created, +        date_issued, +        date_modified, +        date_published, +        date_valid, +        identifier_isbn, +        identifier_oclc, +        language_document, +        language_document_char, +        notes_abstract, +        notes_description, +        original_publisher, +        original_language, +        original_language_char, +        original_source, +        original_title, +        publisher, +        rights_copyright, +        rights_copyright_audio, +        rights_copyright_cover, +        rights_copyright_illustrations, +        rights_copyright_photographs, +        rights_copyright_text, +        rights_copyright_translation, +        rights_copyright_video, +        rights_license +      ) +      VALUES ( +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s', +        '%s' +      ); +    ¶", +      _uid, +      SQLinsertDelimiter!()(doc_matters.src.filename), +      SQLinsertDelimiter!()(doc_matters.src.docname_composite_unique_per_src_doc), +      SQLinsertDelimiter!()(doc_matters.src.docname_composite_unique_per_src_pod), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_full), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_main), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_subtitle), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_short), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_edition), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_language), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.classify_dewey), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.classify_keywords), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.classify_loc), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.classify_subject), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.classify_topic_register), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.creator_author), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.creator_author_email), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.creator_illustrator), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.creator_translator), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_added_to_site), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_available), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_created), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_issued), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_modified), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_published), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_valid), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.identifier_isbn), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.identifier_oclc), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.language_document), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.language_document_char), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.notes_abstract), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.notes_description), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.original_publisher), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.original_language), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.original_language_char), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.original_source), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.original_title), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.publisher), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_audio), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_cover), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_illustrations), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_photographs), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_text), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_translation), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_video), +      SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_license) +    ); +    return _insert_metadata; +  } +} +template SQLiteInsertDocObjectsLoop() { +  string SQLiteInsertDocObjectsLoop(D,I)( +    D    doc_abstraction, +    I    doc_matters, +  ) { +    string _uid = SQLinsertDelimiter!()(doc_matters.src.doc_uid); +    string insertDocObjectsRow(O)(O obj) { +      string _insert_doc_objects_row = format(q"¶ +        INSERT INTO doc_objects ( +          uid_metadata_and_text, +          ocn, +          clean, +          body, +          lev, +          is_of_type, +          is_a +        ) +        VALUES ( +          '%s', +          %s, +          '%s', +          '%s', +          %s, +          '%s', +          '%s' +        ); +      ¶", +        _uid, +        obj.metainfo.ocn, +        SQLinsertDelimiter!()(obj_txt["text"]), +        SQLinsertDelimiter!()(obj_txt["html"]), +        obj.metainfo.heading_lev_markup, +        obj.metainfo.is_of_type, +        obj.metainfo.is_a, +      ); +      return _insert_doc_objects_row; +    } +    auto format_and_sqlite_load = SQLiteFormatAndLoadObject!()(doc_matters); +    string[string] obj_txt; +    string doc_text; +    string[] _insert_doc_objects; +    foreach (part; doc_matters.xml.keys_seq.sql) { +      foreach (obj; doc_abstraction[part]) { +        switch (obj.metainfo.is_of_part) { +        case "frontmatter":              assert(part == "head", part); +          switch (obj.metainfo.is_of_type) { +          case "para": +            switch (obj.metainfo.is_a) { +            case "heading": +              obj_txt = format_and_sqlite_load.heading(obj); +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +              } +              break; +            } +            break; +          default: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +            } +            break; +          } +          break; +        case "body": //                    assert(part == "body", part); +          switch (obj.metainfo.is_of_type) { +          case "para": +            switch (obj.metainfo.is_a) { +            case "heading": +              debug (asserts) { +                if (part != "body") { +                  writeln(__LINE__, ": ", obj.text); +                } +              } +              obj_txt = format_and_sqlite_load.heading(obj); +              break; +            case "para": +              obj_txt = format_and_sqlite_load.para(obj); +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +              } +              break; +            } +            break; +          case "block": +            switch (obj.metainfo.is_a) { +            case "quote": +              obj_txt = format_and_sqlite_load.quote(obj); +              break; +            case "group": +              obj_txt = format_and_sqlite_load.group(obj); +              break; +            case "block": +              obj_txt = format_and_sqlite_load.block(obj); +              break; +            case "poem":                        // double check on keeping both poem & verse +              break; +            case "verse": +              obj_txt = format_and_sqlite_load.verse(obj); +              break; +            case "code": +              obj_txt = format_and_sqlite_load.code(obj); +              break; +            case "table": +              obj_txt = format_and_sqlite_load.table(obj); +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +              } +              break; +            } +            break; +          default: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +            } +            break; +          } +          break; +        case "backmatter": +          assert(part == "glossary" || "bibliography" || "bookindex_seg" || "blurb" || "tail", part); +          switch (obj.metainfo.is_of_type) { +          case "para": +            switch (obj.metainfo.is_a) { +            case "heading": +              obj_txt = format_and_sqlite_load.heading(obj); +              break; +            case "glossary":             assert(part == "glossary", part); +              obj_txt = format_and_sqlite_load.para(obj); +              break; +            case "bibliography":         assert(part == "bibliography", part); +              obj_txt = format_and_sqlite_load.para(obj); +              break; +            case "bookindex":            assert(part == "bookindex_seg", part); +              obj_txt = format_and_sqlite_load.para(obj); +              break; +            case "blurb":                assert(part == "blurb", part); +              obj_txt = format_and_sqlite_load.para(obj); +              break; +            default: +              if ((doc_matters.opt.action.debug_do)) { +                writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +              } +              break; +            } +            break; +          default: +            if ((doc_matters.opt.action.debug_do)) { +              writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); +            } +            break; +          } +          break; +        case "comment": +          break; +        default: +          if ((doc_matters.opt.action.debug_do)) { +            writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_part); // check where empty value could come from +            writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); +            writeln(__FILE__, ":", __LINE__, ": ", obj.text); // check where empty value could come from +          } +          break; +        } +        if (obj.metainfo.is_a == "heading") { +          if ((doc_matters.opt.action.very_verbose)) { +            writeln( +              "markup: ", obj.metainfo.heading_lev_markup, +              "> ", obj.metainfo.dom_structure_markedup_tags_status, +              "; collapsed: ", obj.metainfo.heading_lev_collapsed, +              "> ", obj.metainfo.dom_structure_collapsed_tags_status, +              "; ocn: ", obj.metainfo.ocn, +              " node: ", obj.metainfo.node, +              "; parent: ", obj.metainfo.parent_lev_markup, +              "; ocn: ", obj.metainfo.parent_ocn, +              "; ", +            ); +          } +        } +        if (!(obj.metainfo.is_a == "comment")) { +          _insert_doc_objects ~= insertDocObjectsRow(obj); +        } +      } // loop closes +    } +    return _insert_doc_objects.join.to!(char[]).toUTF8; +  } +} +template SQLiteTablesCreate() { +  void SQLiteTablesCreate(E,O)(E env, O opt_action) { +    import d2sqlite3; +    template SQLiteTablesReCreate() { +      string SQLiteTablesReCreate()() { +        string _sql_instruct; +        _sql_instruct = format(q"¶ +          DROP INDEX IF EXISTS idx_ocn; +          DROP INDEX IF EXISTS idx_uid; +          DROP INDEX IF EXISTS idx_digest_clean; +          DROP INDEX IF EXISTS idx_digest_all; +          DROP INDEX IF EXISTS idx_clean; +          DROP INDEX IF EXISTS idx_title; +          DROP INDEX IF EXISTS idx_creator_author; +          DROP INDEX IF EXISTS src_filename; +          DROP INDEX IF EXISTS idx_language_document_char; +          DROP INDEX IF EXISTS idx_classify_topic_register; +          DROP TABLE IF EXISTS metadata_and_text; +          DROP TABLE IF EXISTS doc_objects; +          DROP TABLE IF EXISTS urls; +          CREATE TABLE metadata_and_text ( +            uid                              VARCHAR(256)      UNIQUE, /* filename, language char, pod/txt (decide on delimiter [,;:/]) */ +            src_composite_id_per_txt         VARCHAR(256)  NOT NULL,   /* UNIQUE, /* z pod name if any + src filename + language code */ +            src_composite_id_per_pod         VARCHAR(256)  NOT NULL,   /* z pod name if any + src filename */ +            title                            VARCHAR(800)  NOT NULL, +            title_main                       VARCHAR(400)  NOT NULL, +            title_sub                        VARCHAR(400)      NULL, +            title_short                      VARCHAR(400)      NULL, +            title_edition                    VARCHAR(10)       NULL, +            title_note                       VARCHAR(2500)     NULL, +            title_language                   VARCHAR(100)      NULL, +            title_language_char              VARCHAR(6)        NULL, +            creator_author                   VARCHAR(600)  NOT NULL, +            creator_author_email             VARCHAR(100)      NULL, +            creator_author_hon               VARCHAR(100)      NULL, +            creator_author_nationality       VARCHAR(100)      NULL, +            creator_editor                   VARCHAR(600)      NULL, +            creator_contributor              VARCHAR(600)      NULL, +            creator_illustrator              VARCHAR(600)      NULL, +            creator_photographer             VARCHAR(600)      NULL, +            creator_translator               VARCHAR(600)      NULL, +            creator_prepared_by              VARCHAR(600)      NULL, +            creator_digitized_by             VARCHAR(600)      NULL, +            creator_audio                    VARCHAR(600)      NULL, +            creator_video                    VARCHAR(600)      NULL, +            language_document                VARCHAR(100)      NULL, +            language_document_char           VARCHAR(6)    NOT NULL, +            language_original                VARCHAR(100)      NULL, +            language_original_char           VARCHAR(6)        NULL, +            date_added_to_site               VARCHAR(10)       NULL, +            date_available                   VARCHAR(10)       NULL, +            date_created                     VARCHAR(10)       NULL, +            date_issued                      VARCHAR(10)       NULL, +            date_modified                    VARCHAR(10)       NULL, +            date_published                   VARCHAR(10)       NULL, +            date_valid                       VARCHAR(10)       NULL, +            date_translated                  VARCHAR(10)       NULL, +            date_original_publication        VARCHAR(10)       NULL, +            date_generated                   VARCHAR(10)       NULL, +            publisher                        VARCHAR(600)      NULL, +            original_publisher               VARCHAR(600)      NULL, +            original_language                VARCHAR(100)      NULL, +            original_language_char           VARCHAR(6)        NULL, +            original_source                  VARCHAR(600)      NULL, +            original_institution             VARCHAR(600)      NULL, +            original_nationality             VARCHAR(100)      NULL, +            original_title                   VARCHAR(800)      NULL, +            rights_copyright                 VARCHAR(2500)     NULL, +            rights_copyright_audio           VARCHAR(2500)     NULL, +            rights_copyright_cover           VARCHAR(2500)     NULL, +            rights_copyright_illustrations   VARCHAR(2500)     NULL, +            rights_copyright_photographs     VARCHAR(2500)     NULL, +            rights_copyright_text            VARCHAR(2500)     NULL, +            rights_copyright_translation     VARCHAR(2500)     NULL, +            rights_copyright_video           VARCHAR(2500)     NULL, +            rights_license                   VARCHAR(2500)     NULL, +            identifier_oclc                  VARCHAR(30)       NULL, +            identifier_isbn                  VARCHAR(16)       NULL, +            classify_topic_register          VARCHAR(2500)     NULL, +            classify_subject                 VARCHAR(600)      NULL, +            classify_loc                     VARCHAR(30)       NULL, +            classify_dewey                   VARCHAR(30)       NULL, +            classify_keywords                VARCHAR(600)      NULL, +            notes_abstract                   TEXT              NULL, +            notes_description                TEXT              NULL, +            notes_comment                    TEXT              NULL, +            notes_coverage                   VARCHAR(200)      NULL, +            notes_relation                   VARCHAR(200)      NULL, +            notes_history                    VARCHAR(600)      NULL, +            notes_type                       VARCHAR(600)      NULL, +            notes_format                     VARCHAR(600)      NULL, +            notes_prefix                     TEXT              NULL, +            notes_prefix_a                   TEXT              NULL, +            notes_prefix_b                   TEXT              NULL, +            notes_suffix                     TEXT              NULL, +            src_filename                     VARCHAR(256)  NOT NULL, +            src_fingerprint                  VARCHAR(256)      NULL, +            src_filesize                     VARCHAR(10)       NULL, +            src_wordcount                    VARCHAR(10)       NULL, +            pod_name                         VARCHAR(256)      NULL, /* zipped pod, work to be done here */ +            pod_fingerprint                  VARCHAR(256)      NULL, /* zipped pod, work to be done here */ +            pod_size                         VARCHAR(10)       NULL, /* zipped pod, work to be done here */ +            src_text                         TEXT              NULL, +            fulltext                         TEXT              NULL, +            links                            TEXT              NULL +          ); +          CREATE TABLE doc_objects ( +            lid                              BIGINT            PRIMARY KEY, +            uid_metadata_and_text            VARCHAR(256)      REFERENCES metadata_and_text(uid) ON DELETE CASCADE, +            ocn                              SMALLINT, +            ocnd                             VARCHAR(6), +            ocns                             VARCHAR(6), +            clean                            TEXT              NULL, +            body                             TEXT              NULL, +            seg                              VARCHAR(256)      NULL, +            lev_an                           VARCHAR(1), +            lev                              SMALLINT          NULL, +            is_of_type                       VARCHAR(16), +            is_a                             VARCHAR(16), +            node                             VARCHAR(16)       NULL, +            parent                           VARCHAR(16)       NULL, +            last_decendant                   VARCHAR(16)       NULL, /* headings only */ +            digest_clean                     CHAR(256), +            digest_all                       CHAR(256), +            types                            CHAR(1)           NULL +          ); +          CREATE INDEX idx_ocn ON doc_objects(ocn); +          CREATE INDEX idx_digest_clean ON doc_objects(digest_clean); +          CREATE INDEX idx_digest_all ON doc_objects(digest_all); +          CREATE INDEX idx_clean ON doc_objects(clean); +          CREATE INDEX idx_title ON metadata_and_text(title); +          CREATE INDEX idx_author ON metadata_and_text(creator_author); +          CREATE INDEX idx_uid ON metadata_and_text(uid); +          CREATE INDEX idx_filename ON metadata_and_text(src_filename); +          CREATE INDEX idx_language ON metadata_and_text(language_document_char); +          CREATE INDEX idx_topics ON metadata_and_text(classify_topic_register); +        ¶",); +        return _sql_instruct; +      } +    } +    if (opt_action.sqlite_db_create) { +      string _db_statement; +      auto pth_sqlite = SiSUpathsSQLite!()(opt_action.sqlite_filename, opt_action.output_dir_set); +      pth_sqlite.base.mkdirRecurse; +      auto db = Database(pth_sqlite.sqlite_file); +      { +        _db_statement ~= SQLiteTablesReCreate!()(); +      } +      SQLiteDbRun!()(db, _db_statement, opt_action, "TABLE RE-CREATE"); +    } +  } +} +template SQLiteDbDrop() { +  void SQLiteDbDrop(O)(O opt_action) { +    writeln("db drop"); +    if ((opt_action.sqlite_db_drop)) { +      auto pth_sqlite = SiSUpathsSQLite!()(opt_action.sqlite_filename, opt_action.output_dir_set); +      writeln("remove(", pth_sqlite.sqlite_file, ")"); +      try { +        remove(pth_sqlite.sqlite_file); +      } catch (FileException ex) { +        // handle error +      } +    } +  } +} diff --git a/src/doc_reform/output/xmls.d b/src/doc_reform/output/xmls.d new file mode 100644 index 0000000..8428204 --- /dev/null +++ b/src/doc_reform/output/xmls.d @@ -0,0 +1,1036 @@ +module doc_reform.output.xmls; +template outputXHTMLs() { +  import doc_reform.output; +  import +    std.digest.sha, +    std.file, +    std.outbuffer, +    std.zip, +    std.conv : to; +  import +    doc_reform.output.create_zip_file, +    doc_reform.output.xmls, +    doc_reform.output.xmls_css; +  mixin SiSUoutputRgxInit; +  struct outputXHTMLs { +    static auto rgx = Rgx(); +    string div_delimit( +      string                     part, +      return ref string          previous_part +    ){ +      string delimit = ""; +      string delimit_ = ""; +      if (part != previous_part) { +        switch (part) { +        case "head": +          delimit_ ~= "\n<div class=\"doc_title\">\n" ; +          break; +        case "toc_seg": +          delimit_ ~= "\n<div class=\"doc_toc\">\n" ; +          break; +        case "toc_scroll": +          delimit_ ~= "\n<div class=\"doc_toc\">\n" ; +          break; +        case "bookindex_seg": +          delimit_ ~= "\n<div class=\"doc_bookindex\">\n" ; +          break; +        case "bookindex_scroll": +          delimit_ ~= "\n<div class=\"doc_bookindex\">\n" ; +          break; +        default: +          delimit_ ~= "\n<div class=\"doc_" ~ part ~ "\">\n" ; +          break; +        } +        if (previous_part.length > 0) { +          delimit ~= "\n</div>"; +        } +        previous_part = part; +        delimit ~=  delimit_; +      } +      // you also need to close the last div, introduce a footer? +      return delimit; +    } +    string special_characters(O)( +      const  O         obj, +      string           _txt +    ){ +      _txt = (_txt) +        .replaceAll(rgx.xhtml_ampersand,    "&") +        .replaceAll(rgx.xhtml_quotation,    """) +        .replaceAll(rgx.xhtml_less_than,    "<") +        .replaceAll(rgx.xhtml_greater_than, ">") +        .replaceAll(rgx.nbsp_char,          " "); +      if (!(obj.metainfo.is_a == "code")) { +        _txt = (_txt) +          .replaceAll(rgx.xhtml_line_break,   "<br />"); +      } +      return _txt; +    } +    string special_characters_text(string _txt){ +      _txt = (_txt) +        .replaceAll(rgx.xhtml_ampersand,    "&") +        .replaceAll(rgx.xhtml_quotation,    """) +        .replaceAll(rgx.xhtml_less_than,    "<") +        .replaceAll(rgx.xhtml_greater_than, ">") +        .replaceAll(rgx.nbsp_char,          " "); +      return _txt; +    } +    string font_face(string _txt){ +      _txt = (_txt) +        .replaceAll(rgx.inline_emphasis,    ("<em>$1</em>")) +        .replaceAll(rgx.inline_bold,        ("<b>$1</b>")) +        .replaceAll(rgx.inline_underscore,  ("<u>$1</u>")) +        .replaceAll(rgx.inline_italics,     ("<i>$1</i>")) +        .replaceAll(rgx.inline_superscript, ("<sup>$1</sup>")) +        .replaceAll(rgx.inline_subscript,   ("<sub>$1</sub>")) +        .replaceAll(rgx.inline_strike,      ("<del>$1</del>")) +        .replaceAll(rgx.inline_insert,      ("<ins>$1</ins>")) +        .replaceAll(rgx.inline_mono,        ("<tt>$1</tt>")) +        .replaceAll(rgx.inline_cite,        ("<cite>$1</cite>")); +      return _txt; +    } +    string _xhtml_anchor_tags(const(string[]) anchor_tags) { +      string tags=""; +      if (anchor_tags.length > 0) { +        foreach (tag; anchor_tags) { +          if (!(tag.empty)) { +            tags ~= "<a name=\"" ~ tag ~ "\"></a>"; +          } +        } +      } +      return tags; +    } +    auto header_metadata(M)( +      M  doc_matters, +    ) { +      string _title="Title"; +      string _author="Author"; +      string _publisher="Publisher"; +      string _date="Date"; +      string _date_created="Date"; +      string _date_issued="Date"; +      string _date_available="Date"; +      string _date_valid="Date"; +      string _date_modified="Date"; +      string _language="en"; +      string _rights="Copyright: Copyright (C) year holder"; +      string _generator="doc_reform [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)"; +      string _generator_home="http://www.sisudoc.org"; +      string o; +      o = format(q"¶<!-- SiSU header metadata --> +    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> +    <meta name="dc.title" content="%s" /> +    <meta name="dc.author" content="%s" /> +    <meta name="dc.publisher" content="%s" /> +    <meta name="dc.date" content="%s" /> +    <meta name="dc.date.created" content="%s" /> +    <meta name="dc.date.issued" content="%syear" /> +    <meta name="dc.date.available" content="%syear" /> +    <meta name="dc.date.valid" content="%syear" /> +    <meta name="dc.date.modified" content="%syear" /> +    <meta name="dc.language" content="%s" /> +    <meta name="dc.rights" content="%s" /> +    <meta name="generator" content="%s" /> +    <link rel="generator" href="%s" /> +    <!-- SiSU header metadata -->¶", +      _title, +      _author, +      _publisher, +      _date, +      _date_created, +      _date_issued, +      _date_available, +      _date_valid, +      _date_modified, +      _language, +      _rights, +      _generator, +      _generator_home, +      ); +      return o; +    } +    auto site_info_button(M)( +      M  doc_matters, +    ) { +      string _locations; +      if (doc_matters.conf_make_meta.make.home_button_text.length > 0) { +        _locations = (doc_matters.conf_make_meta.make.home_button_text) +          .replaceAll( +            rgx.inline_link, +            ("<p class=\"tiny_left\"><a href=\"$2\">$1</a></p>")) +          .replaceAll( +            rgx.br_line, "") +          .replaceAll( +            rgx.br_nl, ""); +      } else { +         _locations = "<p class=\"tiny_left\"><a href=\"http://www.sisudoc.org\">SiSU</a></p>\n<p class=\"tiny_left\"><a href=\"http://www.sisudoc.org\">www.sisudoc.org</a></p>\n<p class=\"tiny_left\"><a href=\"http://git.sisudoc.org/gitweb/\">sources / git</a></p>"; +      } +      string o; +      o = format(q"¶<div class="flex-menu-option"> +          %s +        </div>¶", +      _locations, +      ); +      return o; +    } +    auto inline_search_form(M)( +      M  doc_matters, +    ) { +      string _action="http://www.sisudoc.org/cgi-bin/search.cgi"; +      string _db="SiSU.7a.manual"; +      string o; +      o = format(q"¶<div class="flex-menu-option"> +          <a name="search"></a> +          <form method="get" action="%s" target="_top"> +          <font size="2"> +          <input type="text" name="s1" size="24" maxlength="255" /> +          <input type="hidden" name="db" value="%s" /> +          <input type="hidden" name="ltd" value="1000" /> +          <input type="hidden" name="off" value="0" /> +          <input type="hidden" name="doc" value="live-manual" /><br /> +          <input type="submit" name="search" value="search doc" /> +          <input type="submit" name="search" value="search db" /> +          </font></form> +        </div>¶", +      _action, +      _db, +      ); +      return o; +    } +    auto html_head(M)( +      M  doc_matters, +      string type, +    ) { +      string o; +      o = format(q"¶<!DOCTYPE html> +    <html> +    <head> +      <meta charset="utf-8" /> +      <title> +        %s%s +      </title> +      <!-- metadata --> +      %s +      <!-- metadata --> +      <link rel="generator" href="http://www.sisudoc.org/" /> +      <link rel="shortcut icon" href="%s" /> +      <link href="%s" rel="stylesheet" /> +    </head> +    <body lang="%s"> +    <a name="top" id="top"></a> +    <div class='delimit headband'> +      <div class="flex-menu-bar"> +        %s +        <div class="flex-menu-option"> +          <a href="../../manifest/sisu.en.html" target="_top"> +            <font face="verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman" size="2"> +              [ document manifest ] +            </font> +          </a> +        </div> +        %s%s¶", +        doc_matters.conf_make_meta.meta.title_full, +        (doc_matters.conf_make_meta.meta.creator_author.empty) ? "" +          : ", " ~ doc_matters.conf_make_meta.meta.creator_author, +        header_metadata(doc_matters), +        ((type == "seg") ? "../../../" : "../../") ~ "image/rb7.ico", +        ((type == "seg") +          ? "../../../css/html_seg.css" +          : "../../css/html_scroll.css"), +        doc_matters.src.language, +        site_info_button(doc_matters), +        inline_search_form(doc_matters), +        ((type == "seg") ? "" : "\n</div>"), +      ); +      return o; +    } +    auto epub3_seg_head(M)( +      M  doc_matters, +    ) { +      string html_base = format(q"¶<!DOCTYPE html> +    <html>¶", +    ); +      string html_simple = format(q"¶<!DOCTYPE html> +    <html +      xmlns="http://www.w3.org/1999/xhtml" +      xmlns:epub="http://www.idpf.org/2007/ops" +      lang="%s" xml:lang="%s">¶", +        doc_matters.src.language, +        doc_matters.src.language, +      ); +      string html_strict = format(q"¶<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" +         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +    <html xmlns="http://www.w3.org/1999/xhtml" +      xmlns:epub="http://www.idpf.org/2007/ops" +      lang="%s" xml:lang="%s">¶", +        doc_matters.src.language, +        doc_matters.src.language, +      ); +      string o; +      o = format(q"¶%s +    <head> +      <title> +        %s%s +      </title> +      <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> +      <meta name="dc.title" content="%s" /> +      <meta name="dc.author" content="%s" /> +      <meta name="dc.publisher" content="SiSU http://www.jus.uio.no/sisu (this copy)" /> +      <meta name="dc.date" content="year" /> +      <meta name="dc.date.created" content="year" /> +      <meta name="dc.date.issued" content="year" /> +      <meta name="dc.date.available" content="year" /> +      <meta name="dc.date.valid" content="year" /> +      <meta name="dc.date.modified" content="year" /> +      <meta name="dc.language" content="US" /> +      <meta name="dc.rights" content="Copyright: Copyright (C) year holder" /> +      <meta name="generator" content="doc_reform [SiSU 7.1.8 of 2016w08/5 (2016-02-26)] (n*x and D)" /> +      <link rel="generator" href="http://www.sisudoc.org/" /> +      <link rel="shortcut icon" href="../_sisu/image/rb7.ico" /> +      <link rel="stylesheet" href="css/epub.css" type="text/css" id="main-css" /> +    </head> +    <body lang="%s"> +    <a name="top" id="top"></a>¶", +        html_simple, +        doc_matters.conf_make_meta.meta.title_full, +        (doc_matters.conf_make_meta.meta.creator_author.empty) ? "" +          : ", " ~ doc_matters.conf_make_meta.meta.creator_author, +        doc_matters.conf_make_meta.meta.title_full, +        (doc_matters.conf_make_meta.meta.creator_author.empty) ? "" +          : ", " ~ doc_matters.conf_make_meta.meta.creator_author, +        doc_matters.src.language, +      ); +      return o; +    } +    auto tail() { +      string o; +      o = format(q"¶  </div> +      <a name="bottom" id="bottom"></a> +      <a name="end" id="end"></a> +    </body> +    </html>¶"); +      return o; +    } +    auto inline_images(O)( +      const  O         obj, +      string           _txt, +      string           _suffix    = ".html", +      string           _xml_type = "seg", +    ) { +      string _img_pth; +      if (_xml_type == "epub") { +        _img_pth = "image/"; +      } else if (_xml_type == "scroll") { +        _img_pth = "../../image/"; +      } else if (_xml_type == "seg") { +        _img_pth = "../../../image/"; +      } +      if (_txt.match(rgx.inline_image)) { +        _txt = _txt.replaceAll( +            rgx.inline_image, +            ("$1<img src=\"" +              ~ _img_pth +              ~ "$3\" width=\"$4\" height=\"$5\" naturalsizeflag=\"0\" align=\"bottom\" border=\"0\" /> $6")); +      } +      return _txt; +    } +    auto inline_links(O)( +      const  O         obj, +      string           _txt, +      string           _suffix    = ".html", +      string           _xml_type = "seg", +    ) { +      if (obj.has.inline_links) { +        if ((_txt.match(rgx.mark_internal_site_lnk)) +        && (_xml_type == "scroll")) { // conditions reversed to avoid: gdc compiled program run segfault +          _txt = (_txt).replaceAll( +            rgx.inline_seg_link, +            "$1"); +        } +        _txt = (_txt) +          .replaceAll( +            rgx.inline_link_fn_suffix, +            ("$1" ~ _suffix)) +          .replaceAll( +            rgx.inline_link, +            ("<a href=\"$2\">$1</a>")) +          .replaceAll( +            rgx.mark_internal_site_lnk, +            ""); +      } +      debug(markup_links) { +        if (_txt.match(rgx.inline_link)) { +          writeln(__LINE__, +            " (missed) markup link identified (", +            obj.has.inline_links, +            "): ", obj.metainfo.is_a, ": ", +            obj.text +          ); +        } +      } +      debug(markup) { +        if (_txt.match(rgx.inline_link)) { +          writeln(__LINE__, +            " (missed) markup link identified (", +            obj.has.inline_links, +            "): ", obj.metainfo.is_a, ": ", +            obj.text +          ); +        } +      } +      return _txt; +    } +    auto inline_notes_scroll(O)( +      const  O         obj, +      string           _txt, +    ) { +      if (obj.has.inline_notes_reg) { +        _txt = font_face(_txt); +        _txt = (_txt).replaceAll( +          rgx.inline_notes_delimiter_al_regular_number_note, +          ("<a href=\"#note_$1\"><note id=\"noteref_$1\"> <sup>$1</sup> </note></a>") +        ); +      } +      debug(markup_endnotes) { +        if (_txt.match(rgx.inline_notes_delimiter_al_regular_number_note)) { +          writeln(__LINE__, " (missed) markup endnote: ", obj.metainfo.is_a, ": ", obj.text); +        } +      } +      debug(markup) { +        if (_txt.match(rgx.inline_notes_delimiter_al_regular_number_note)) { +          writeln(__LINE__, " (missed) markup endnote: ", obj.metainfo.is_a, ": ", obj.text); +        } +      } +      return _txt; +    } +    auto inline_notes_seg(O)( +      const  O         obj, +      string           _txt, +    ) { +      string[] _endnotes; +      if (obj.has.inline_notes_reg) { +        _txt = font_face(_txt); +        /+ need markup for text, and separated footnote +/ +        foreach(m; _txt.matchAll(rgx.inline_notes_delimiter_al_regular_number_note)) { +          _endnotes ~= format( +            "%s%s%s%s\n  %s%s%s%s%s\n  %s\n%s", +            "<p class=\"endnote\">", +            "<a href=\"#noteref_", +            m.captures[1], +            "\">", +            "<note id=\"note_", +            m.captures[1], +            "\"> <sup>", +            m.captures[1], +            ".</sup></note></a>", +            m.captures[2], +            "</p>" +          ); +        } +        _txt = (_txt).replaceAll( +          rgx.inline_notes_delimiter_al_regular_number_note, +          ("<a href=\"#note_$1\"><note id=\"noteref_$1\"> <sup>$1</sup> </note></a>") +        ); +      } else if (_txt.match(rgx.inline_notes_delimiter_al_regular_number_note)) { +        debug(markup) { +          writeln(__LINE__, " endnote: ", obj.metainfo.is_a, ": ", obj.text); +        } +      } +      auto t = tuple( +        _txt, +        _endnotes, +      ); +      return t; +    } +    auto inline_markup_scroll(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +    ) { +      _txt = inline_images(obj, _txt, _suffix, "scroll"); +      _txt = inline_links(obj, _txt, _suffix, "scroll"); +      _txt = inline_notes_scroll(obj, _txt); +      return _txt; +    } +    auto inline_markup_seg(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +      string           _xml_type = "seg", +    ) { +      _txt = inline_images(obj, _txt, _suffix, _xml_type); +      _txt = inline_links(obj, _txt, _suffix, _xml_type); +      auto t = inline_notes_seg(obj, _txt); +      return t; +    } +    string lev4_heading_subtoc(O)( +      const  O         obj, +    ) { +      char[] lev4_subtoc; +      lev4_subtoc ~= "  <div class=\"nav\">\n"; +      foreach (subtoc; obj.tags.lev4_subtoc) { +        if (auto m = subtoc.match(rgx.inline_link_subtoc)) { +          auto indent = m.captures[1].to!string; +          auto text = m.captures[2].to!string; +          text = font_face(text); +          auto link = m.captures[3].to!string; +          lev4_subtoc ~= subtoc.replaceFirst(rgx.inline_link_subtoc, +            format(q"¶    <p class="minitoc" indent="h%si%s"> +          <a href="%s">%s</a> +        </p> +    ¶", +              indent, +              indent, +              link, +              text, +          )); +        } +      } +      lev4_subtoc ~= "  </div>\n"; +      return lev4_subtoc.to!string; +    } +    auto nav_pre_next_svg(O)( +      const  O         obj, +    ) { +      string prev, next, toc; +      if (obj.tags.segment_anchor_tag == "toc") { +        toc = ""; +        prev = ""; +      } else { +        toc = format(q"¶<a href="toc.html" target="_top"> +              <div class="toc-button menu"> +                <svg viewbox="0 0 100 100"> +                  <path d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z M28,14H4c-1.104,0-2,0.896-2,2  s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2  S29.104,22,28,22z"/> +                </svg> +              </div> +            </a>¶", +        ); +      } +      if (obj.tags.segname_prev == "") { +        prev = ""; +      } else { +        prev = format(q"¶<a href="%s.html" target="_top"> +              <div class="prev-next-button previous"> +                <svg viewbox="0 0 100 100"> +                  <path class="arrow" d="M 50,0 L 60,10 L 20,50 L 60,90 L 50,100 L 0,50 Z" transform=" translate(15,0)"> +                </svg> +              </div> +            </a>¶", +          obj.tags.segname_prev, +        ); +      } +      if (obj.tags.segname_next == "") { +        next = ""; +      } else { +        next = format(q"¶<a href="%s.html" target="_top"> +              <div class="prev-next-button next"> +                <svg viewbox="0 0 100 100"> +                  <path class="arrow" d="M 50,0 L 60,10 L 20,50 L 60,90 L 50,100 L 0,50 Z "transform="translate(85,100) rotate(180) "> +                </svg> +              </div> +            </a>¶", +          obj.tags.segname_next, +        ); +      } +      string _toc_pre_next = format(q"¶        <div class="flex-menu-option"> +          <div class="nav-bar"> +            %s +            %s +            %s +          </div> +        </div> +      </div> +    </div>¶", +        toc, +        prev, +        next, +      ); +      string _pre_next = format(q"¶        <div class="flex-menu-option"> +          <div class="nav-bar"> +            %s +            %s +          </div> +        </div> +      </div> +    </div>¶", +        prev, +        next, +      ); +      struct bar { +        string toc_pre_next() { +          return _toc_pre_next; +        } +        string pre_next() { +          return _pre_next; +        } +      } +      return bar(); +    } +    auto heading(O)( +      const  O         obj, +      string           _txt, +      string           _xml_type = "html", +    ) { +      auto tags = _xhtml_anchor_tags(obj.tags.anchor_tags); +      string _horizontal_rule = "<hr />"; +      if ((_xml_type != "html") +      || (obj.metainfo.heading_lev_markup == 0 || obj.metainfo.heading_lev_markup > 4)) { +        _horizontal_rule = ""; +      } +      _txt = font_face(_txt); +      string o; +      if (obj.metainfo.object_number.empty) { +        o = format(q"¶%s +      <div class="substance"> +        <h%s class="%s">%s +          %s +        </h%s> +      </div>¶", +          _horizontal_rule, +          obj.metainfo.heading_lev_markup, +          obj.metainfo.is_a, +          tags, +          _txt, +          obj.metainfo.heading_lev_markup, +        ); +      } else { +        o = format(q"¶%s +      <div class="substance"> +        <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label> +        <h%s class="%s" id="%s"><a name="%s"></a>%s +          %s +        </h%s> +      </div>¶", +        _horizontal_rule, +        obj.metainfo.object_number, +        obj.metainfo.object_number, +        obj.metainfo.heading_lev_markup, +        obj.metainfo.is_a, +        obj.metainfo.object_number, +        obj.metainfo.object_number, +        tags, +        _txt, +        obj.metainfo.heading_lev_markup, +        ); +      } +      return o; +    } +    auto heading_scroll(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +    ) { +      auto tags = _xhtml_anchor_tags(obj.tags.anchor_tags); +      _txt = inline_markup_scroll(obj, _txt, _suffix); +      string o = heading(obj, _txt); +      return o; +    } +    auto heading_seg(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +      string           _xml_type = "html", +    ) { +      auto t = inline_markup_seg(obj, _txt, _suffix, _xml_type); +      _txt = t[0]; +      string[] _endnotes = t[1]; +      string o = heading(obj, _txt, _xml_type); +      auto u = tuple( +        o, +        _endnotes, +      ); +      return u; +    } +    auto para(O)( +      const  O         obj, +      string           _txt, +    ) { +      auto tags = _xhtml_anchor_tags(obj.tags.anchor_tags); +      _txt = font_face(_txt); +      string o; +      _txt = (obj.attrib.bullet) ? ("●  " ~ _txt) : _txt; +      if (obj.metainfo.object_number.empty) { +        o = format(q"¶  <div class="substance"> +      <p class="%s" indent="h%si%s">%s +        %s +      </p> +    </div>¶", +          obj.metainfo.is_a, +          obj.attrib.indent_hang, +          obj.attrib.indent_base, +          tags, +          _txt +        ); +      } else { +        o = format(q"¶  <div class="substance"> +      <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label> +      <p class="%s" indent="h%si%s" id="%s">%s +        %s +      </p> +    </div>¶", +          obj.metainfo.object_number, +          obj.metainfo.object_number, +          obj.metainfo.is_a, +          obj.attrib.indent_hang, +          obj.attrib.indent_base, +          obj.metainfo.object_number, +          tags, +          _txt +        ); +      } +      return o; +    } +    auto para_scroll(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +    ) { +      auto tags = _xhtml_anchor_tags(obj.tags.anchor_tags); +      _txt = inline_markup_scroll(obj, _txt, _suffix); +      string o = para(obj, _txt); +      return o; +    } +    auto para_seg(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +      string           _xml_type = "html", +    ) { +      auto t = inline_markup_seg(obj, _txt, _suffix, _xml_type); +      _txt = t[0].to!string; +      string[] _endnotes = t[1]; +      string o = para(obj, _txt); +      auto u = tuple( +        o, +        _endnotes, +      ); +      return u; +    } +    auto quote(O)( +      const  O         obj, +      string           _txt, +    ) { +      _txt = font_face(_txt); +      string o; +      if (obj.metainfo.object_number.empty) { +        o = format(q"¶  <div class="substance"> +      <p class="%s"> +        %s +      </p> +    </div>¶", +          obj.metainfo.is_a, +          _txt +        ); +      } else { +        o = format(q"¶  <div class="substance"> +      <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label> +      <p class="%s" id="%s"> +        %s +      </p> +    </div>¶", +          obj.metainfo.object_number, +          obj.metainfo.object_number, +          obj.metainfo.is_a, +          obj.metainfo.object_number, +          _txt +        ); +      } +      return o; +    } +    auto quote_scroll(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +    ) { +      auto tags = _xhtml_anchor_tags(obj.tags.anchor_tags); +      _txt = inline_markup_scroll(obj, _txt, _suffix); +      string o = quote(obj, _txt); +      return o; +    } +    auto quote_seg(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +      string           _xml_type = "html", +    ) { +      auto t = inline_markup_seg(obj, _txt, _suffix, _xml_type); +      _txt = t[0].to!string; +      string[] _endnotes = t[1]; +      string o = quote(obj, _txt); +      auto u = tuple( +        o, +        _endnotes, +      ); +      return u; +    } +    auto group(O)( +      const  O         obj, +      string           _txt, +    ) { +      _txt = font_face(_txt); +      string o; +      if (obj.metainfo.object_number.empty) { +        o = format(q"¶  <div class="substance"> +      <p class="%s"> +        %s +      </p> +    </div>¶", +          obj.metainfo.is_a, +          _txt +        ); +      } else { +        o = format(q"¶  <div class="substance"> +      <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label> +      <p class="%s" id="%s"> +        %s +      </p> +    </div>¶", +          obj.metainfo.object_number, +          obj.metainfo.object_number, +          obj.metainfo.is_a, +          obj.metainfo.object_number, +          _txt +        ); +      } +      return o; +    } +    auto group_scroll(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +      string           _xml_type = "html", +    ) { +      auto tags = _xhtml_anchor_tags(obj.tags.anchor_tags); +      _txt = inline_markup_scroll(obj, _txt, _suffix); +      string o = group(obj, _txt); +      return o; +    } +    auto group_seg(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +      string           _xml_type = "html", +    ) { +      auto t = inline_markup_seg(obj, _txt, _suffix, _xml_type); +      _txt = t[0].to!string; +      string[] _endnotes = t[1]; +      string o = group(obj, _txt); +      auto u = tuple( +        o, +        _endnotes, +      ); +      return u; +    } +    auto block(O)( +      const  O         obj, +      string           _txt, +    ) { +      _txt = font_face(_txt); +      string o; +      if (obj.metainfo.object_number.empty) { +        o = format(q"¶  <div class="substance"> +      <p class="%s">%s</p> +    </div>¶", +          obj.metainfo.is_a, +          _txt.stripRight +        ); +      } else { +        o = format(q"¶  <div class="substance"> +      <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label> +      <p class="%s" id="%s">%s</p> +    </div>¶", +          obj.metainfo.object_number, +          obj.metainfo.object_number, +          obj.metainfo.is_a, +          obj.metainfo.object_number, +          _txt.stripRight +        ); +      } +      return o; +    } +    auto block_scroll(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +      string           _xml_type = "html", +    ) { +      auto tags = _xhtml_anchor_tags(obj.tags.anchor_tags); +      _txt = inline_markup_scroll(obj, _txt, _suffix); +      string o = block(obj, _txt); +      return o; +    } +    auto block_seg(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +      string           _xml_type = "html", +    ) { +      auto t = inline_markup_seg(obj, _txt, _suffix, _xml_type); +      _txt = t[0].to!string; +      string[] _endnotes = t[1]; +      string o = block(obj, _txt); +      auto u = tuple( +        o, +        _endnotes, +      ); +      return u; +    } +    auto verse(O)( +      const  O         obj, +      string           _txt, +    ) { +      _txt = font_face(_txt); +      string o; +      if (obj.metainfo.object_number.empty) { +          o = format(q"¶  <div class="substance"> +            <p class="%s">%s</p> +        </div>¶", +          obj.metainfo.is_a, +          _txt +        ); +      } else { +        o = format(q"¶  <div class="substance"> +          <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label> +          <p class="%s" id="%s">%s</p> +        </div>¶", +          obj.metainfo.object_number, +          obj.metainfo.object_number, +          obj.metainfo.is_a, +          obj.metainfo.object_number, +          _txt +        ); +      } +      return o; +    } +    auto verse_scroll(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +      string           _xml_type = "html", +    ) { +      auto tags = _xhtml_anchor_tags(obj.tags.anchor_tags); +      _txt = inline_markup_scroll(obj, _txt, _suffix); +      string o = verse(obj, _txt); +      return o; +    } +    auto verse_seg(O)( +      const  O         obj, +      string           _txt, +      string           _suffix = ".html", +      string           _xml_type = "html", +    ) { +      auto t = inline_markup_seg(obj, _txt, _suffix, _xml_type); +      _txt = t[0].to!string; +      string[] _endnotes = t[1]; +      string o = verse(obj, _txt); +      auto u = tuple( +        o, +        _endnotes, +      ); +      return u; +    } +    auto tablarize(O)( +      const  O         obj, +      string           _txt, +    ) { +      string[] _table_rows = (_txt).split(rgx.table_delimiter_row); +      string[] _table_cols; +      string _table; +      string _tablenote; +      foreach(row_idx, row; _table_rows) { +        _table_cols = row.split(rgx.table_delimiter_col); +          _table ~= "<tr>"; +          foreach(col_idx, cell; _table_cols) { +            if ((_table_cols.length == 1) +            && (_table_rows.length <= row_idx+2)) { +              _tablenote ~= cell; +            } else { +              string _col_is = (row_idx == 0 && obj.table.heading) ? "th" : "td"; +              string _align = ("style=\"text-align:" +              ~ ((obj.table.column_aligns[col_idx] == "l") +              ? "left\"" : "right\"")); +              _table ~= "<" ~ _col_is ~ " width=\"" ~ obj.table.column_widths[col_idx].to!string ~ "%\" " ~ _align ~ ">"; +              _table ~= cell; +              _table ~= "</" ~ _col_is ~ ">"; +            } +          } +          _table ~= "</tr>"; +        } +      auto t = tuple( +        _table, +        _tablenote, +      ); +      return t; +    } +    auto table(O)( +      const  O         obj, +      string           _txt, +    ) { +      auto tags = _xhtml_anchor_tags(obj.tags.anchor_tags); +      _txt = font_face(_txt); +      auto t = tablarize(obj, _txt); +      _txt = t[0]; +      string _note = t[1]; +      string o; +      o = format(q"¶  <div class="substance"> +      <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label> +      <p class="%s" id="%s">%s +        <table summary="normal text css" width="95%%" border="0" bgcolor="white" cellpadding="2" align="center"> +          %s +        </table> +        %s +      </p> +    </div>¶", +        obj.metainfo.object_number, +        obj.metainfo.object_number, +        obj.metainfo.is_a, +        obj.metainfo.object_number, +        tags, +        _txt, +        _note +      ); +      return o; +    } +    auto endnote(O)( +      const O          obj, +      string           _txt, +    ) { +      string o; +      o = format(q"¶    <p class="%s" indent="h%si%s"> +      %s +    </p>¶", +        obj.metainfo.is_a, +        obj.attrib.indent_hang, +        obj.attrib.indent_base, +        _txt +      ); +      return o; +    } +    auto code(O)( +      const  O         obj, +      string           _txt, +    ) { +      string o; +      if (obj.metainfo.object_number.empty) { +          o = format(q"¶  <div class="substance"> +        <p class="%s">%s</p> +    </div>¶", +          obj.metainfo.is_a, +          _txt +        ); +      } else { +        o = format(q"¶  <div class="substance"> +      <label class="ocn"><a href="#%s" class="lnkocn">%s</a></label> +      <p class="%s" id="%s">%s</p> +    </div>¶", +          obj.metainfo.object_number, +          obj.metainfo.object_number, +          obj.metainfo.is_a, +          obj.metainfo.object_number, +          _txt +        ); +      } +      return o; +    } +  } +} diff --git a/src/doc_reform/output/xmls_css.d b/src/doc_reform/output/xmls_css.d new file mode 100644 index 0000000..f3c0545 --- /dev/null +++ b/src/doc_reform/output/xmls_css.d @@ -0,0 +1,2871 @@ +/++ +  default css settings ++/ +module doc_reform.output.xmls_css; +template SiSUcss() { +  auto SiSUcss() { +    string _css_html_seg=" +  *{ +    padding: 0px; +    margin: 0px; +  } +  body { +    height: 100vh; +    background-color: #ffffff; +  } +  body { +    color: black; +    background: #ffffff; +    background-color: #ffffff; +  } +  a:link { +    color: #003399; +    text-decoration: none; +  } +  a:visited { +    color: #003399; +    text-decoration: none; +  } +  a:hover { +    color: #000000; +    background-color: #f9f9aa; +  } +  a.lnkocn:link { +    color: #777777; +    text-decoration: none; +  } +  a:hover img { +    background-color: #ffffff; +  } +  a:active { +    color: #003399; +    text-decoration: underline; +  } +  div { +    margin-left: 0; +    margin-right: 0; +  } +  div.p { +    margin-left: 5%; +    margin-right: 1%; +  } +  div.substance { +    width: 100%; +    background-color: #ffffff; +  } +  div.ocn { +    width: 5%; +    float: right; +    top: 0; +    background-color: #ffffff; +  } +  div.endnote { +    width: 95%; +    background-color: #fffffff; +  } +  div.toc { +    position: absolute; +    float: left; +    margin: 0; +    padding: 0; +    padding-top: 0.5em; +    border: 0; +    width: 13em; +    background-color: #eeeeee; +    margin-right:1em; +  } +  div.summary { +    margin: 0; +    padding: 0; +    border-left: 13em solid #eeeeee; +    padding-left: 1em; +    background-color: #eeeeee; +  } +  div.content, div.main_column { +    margin: 0; +    padding: 0; +    border-left: 13em solid #ffffff; +    padding-left: 1em; +    padding-right: 1em; +  } +  div.content0, div.main_column0 { +    margin: 0; +    padding: 0; +    border-left: 0% solid #ffffff; +    padding-left: 5%; +  } +  div.scroll { +    margin: 0; +    padding: 0; +    padding-left: 1em; +    padding-right: 1em; +  } +  div.content:after { +    content:' '; +    clear:both; +    display:block; +    height:0; +    overflow:hidden +  } +  div.footer { +    clear:left; +    padding: 0.5em; +    font-size: 80%; +    margin: 0; +  } +  div.toc ul { +    list-style: none; +    padding: 0; +    margin: 0; +  } +  div.toc li ul a, li ul span.currentlink +  { +    font-weight: normal; +    font-size: 90%; +    padding-left: 2em; +    background-color: #eeeeee; +  } +  div.toc a, span.currentlink{ +    display:block; +    text-decoration: none; +    padding-left: 0.5em; +    color: #0000aa; +  } +  hr { +    width: 90%; +    margin-top: 1.8em; +    margin-bottom: 1.8em; +  } +  span.currentlink { +    text-decoration: none; +    background-color: #aaaaf9; +  } +  div.toc a:visited { +    color: #0000aa; +  } +  div.toc a:hover { +    color: #000000; +    background-color: #f9f9aa; +  } +  nav#toc ol { +    list-style-type: none; +  } +  .norm, .bold, .verse, .group, .block, .alt { +    line-height: 133%; +    margin-left: 0em; +    margin-right: 2em; +    margin-top: 12px; +    margin-bottom: 0px; +    padding-left: 0em; +    text-indent: 0em; +  } +  p, h0, h1, h2, h3, h4, h5, h6, h7 { +    display: block; +    font-family: verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman; +    font-size: 100%; +    font-weight: normal; +    line-height: 133%; +    text-align: justify; +    margin-left: 0em; +    margin-right: 2em; +    text-indent: 0mm; +    margin-top: 0.8em; +    margin-bottom: 0.8em; +  } +  img { max-width: 100%; height: auto; } +  /* spaced */ +  p.spaced { white-space: pre; } +  p.block { +    white-space: pre; +  } +  p.group { } +  p.alt { } +  p.verse { +    white-space: pre; +    margin-bottom: 6px; +  } +  p.code { +    font-family: inconsolata, andale mono, courier new, courier, monospace; +    font-size: 90%; +    text-align: left; +    background-color: #eeeeee; +    white-space: pre; +    margin-top: 0px; +    margin-bottom: 0px; +  } +  p.caption { +    text-align: left; +    font-size: 80%; +    display: inline; +  } +  p.endnote { +    font-size: 96%; +    line-height: 120%; +    text-align: left; +    margin-right: 15mm; +  } +  p.endnote_indent { +    font-size: 96%; +    line-height: 120%; +    text-align: left; +    margin-left: 2em; +    margin-right: 15mm; +  } +  p.center { +    text-align: center; +  } +  p.bold { +    font-weight: bold; +  } +  p.bold_left { +    font-weight: bold; +    text-align: left; +  } +  p.centerbold { +    text-align: center; +    font-weight: bold; +  } +  p.em { +    font-weight: bold; +    font-style: normal; +    background: #fff3b6; +  } +  p.small { +    font-size: 80%; +    margin-top: 0px; +    margin-bottom: 0px; +    margin-right: 6px; +    text-align: left; +  } +  .tiny, .tiny_left, .tiny_right, .tiny_center { +    font-size: 10px; +    margin-top: 0px; +    margin-bottom: 0px; +    color: #777777; +    margin-right: 6px; +    text-align: left; +  } +  p.tiny { } +  p.tiny_left { +    margin-left: 0px; +    margin-right: 0px; +    text-align: left; +  } +  p.tiny_right { +    margin-right: 1em; +    text-align: right; +  } +  p.tiny_center { +    margin-left: 0px; +    margin-right: 0px; +    text-align: center; +  } +  p.concordance_word { +    line-height: 150%; +    font-weight: bold; +    display: inline; +    margin-top: 4px; +    margin-bottom: 1px; +  } +  p.concordance_count { +    font-size: 80%; +    color: #777777; +    display: inline; +    margin-left: 0em; +  } +  p.concordance_object { +    font-size: 80%; +    line-height: 120%; +    text-align: left; +    margin-left: 3em; +    margin-top: 1px; +    margin-bottom: 3px; +  } +  p.book_index_lev1 { +    line-height: 100%; +    margin-top: 4px; +    margin-bottom: 1px; +  } +  p.book_index_lev2 { +    line-height: 100%; +    text-align: left; +    margin-left: 3em; +    margin-top: 1px; +    margin-bottom: 3px; +  } +  tt { +    font-family: inconsolata, andale mono, courier new, courier, monospace; +    background-color: #eeeeee; +  } +  /* indent */ +  p.norm { } +  p.i1 { padding-left: 1em; } +  p.i2 { padding-left: 2em; } +  p.i3 { padding-left: 3em; } +  p.i4 { padding-left: 4em; } +  p.i5 { padding-left: 5em; } +  p.i6 { padding-left: 6em; } +  p.i7 { padding-left: 7em; } +  p.i8 { padding-left: 8em; } +  p.i9 { padding-left: 9em; } +  /* hanging indent */ +  p[indent=\"h0i0\"] { +    padding-left: 0em; +    text-indent:  0em; +  } +  p[indent=\"h0i1\"] { +    padding-left: 1em; +    text-indent: -1em; +  } +  p[indent=\"h0i2\"] { +    padding-left: 2em; +    text-indent: -2em; +  } +  p[indent=\"h0i3\"] { +    padding-left: 3em; +    text-indent: -3em; +  } +  p[indent=\"h0i4\"] { +    padding-left: 4em; +    text-indent: -4em; +  } +  p[indent=\"h0i5\"] { +    padding-left: 5em; +    text-indent: -5em; +  } +  p[indent=\"h0i6\"] { +    padding-left: 6em; +    text-indent: -6em; +  } +  p[indent=\"h0i7\"] { +    padding-left: 7em; +    text-indent: -7em; +  } +  p[indent=\"h0i8\"] { +    padding-left: 8em; +    text-indent: -8em; +  } +  p[indent=\"h0i9\"] { +    padding-left: 9em; +    text-indent: -9em; +  } +  p[indent=\"h1i0\"] { +    padding-left: 0em; +    text-indent:  1em; +  } +  p[indent=\"h1i1\"] { +    padding-left: 1em; +    text-indent:  0em; +  } +  p[indent=\"h1i2\"] { +    padding-left: 2em; +    text-indent: -1em; +  } +  p[indent=\"h1i3\"] { +    padding-left: 3em; +    text-indent: -2em; +  } +  p[indent=\"h1i4\"] { +    padding-left: 4em; +    text-indent: -3em; +  } +  p[indent=\"h1i5\"] { +    padding-left: 5em; +    text-indent: -4em; +  } +  p[indent=\"h1i6\"] { +    padding-left: 6em; +    text-indent: -5em; +  } +  p[indent=\"h1i7\"] { +    padding-left: 7em; +    text-indent: -6em; +  } +  p[indent=\"h1i8\"] { +    padding-left: 8em; +    text-indent: -7em; +  } +  p[indent=\"h1i9\"] { +    padding-left: 9em; +    text-indent: -8em; +  } +  p[indent=\"h2i0\"] { +    padding-left: 0em; +    text-indent:  2em; +  } +  p[indent=\"h2i1\"] { +    padding-left: 1em; +    text-indent:  1em; +  } +  p[indent=\"h2i2\"] { +    padding-left: 2em; +    text-indent:  0em; +  } +  p[indent=\"h2i3\"] { +    padding-left: 3em; +    text-indent: -1em; +  } +  p[indent=\"h2i4\"] { +    padding-left: 4em; +    text-indent: -2em; +  } +  p[indent=\"h2i5\"] { +    padding-left: 5em; +    text-indent: -3em; +  } +  p[indent=\"h2i6\"] { +    padding-left: 6em; +    text-indent: -4em; +  } +  p[indent=\"h2i7\"] { +    padding-left: 7em; +    text-indent: -5em; +  } +  p[indent=\"h2i8\"] { +    padding-left: 8em; +    text-indent: -6em; +  } +  p[indent=\"h2i9\"] { +    padding-left: 9em; +    text-indent: -7em; +  } +  p[indent=\"h3i0\"] { +    padding-left: 0em; +    text-indent:  3em; +  } +  p[indent=\"h3i1\"] { +    padding-left: 1em; +    text-indent:  2em; +  } +  p[indent=\"h3i2\"] { +    padding-left: 2em; +    text-indent:  1em; +  } +  p[indent=\"h3i3\"] { +    padding-left: 3em; +    text-indent:  0em; +  } +  p[indent=\"h3i4\"] { +    padding-left: 4em; +    text-indent: -1em; +  } +  p[indent=\"h3i5\"] { +    padding-left: 5em; +    text-indent: -2em; +  } +  p[indent=\"h3i6\"] { +    padding-left: 6em; +    text-indent: -3em; +  } +  p[indent=\"h3i7\"] { +    padding-left: 7em; +    text-indent: -4em; +  } +  p[indent=\"h3i8\"] { +    padding-left: 8em; +    text-indent: -5em; +  } +  p[indent=\"h3i9\"] { +    padding-left: 9em; +    text-indent: -6em; +  } +  p[indent=\"h4i0\"] { +    padding-left: 0em; +    text-indent:  4em; +  } +  p[indent=\"h4i1\"] { +    padding-left: 1em; +    text-indent:  3em; +  } +  p[indent=\"h4i2\"] { +    padding-left: 2em; +    text-indent:  2em; +  } +  p[indent=\"h4i3\"] { +    padding-left: 3em; +    text-indent:  1em; +  } +  p[indent=\"h4i4\"] { +    padding-left: 4em; +    text-indent:  0em; +  } +  p[indent=\"h4i5\"] { +    padding-left: 5em; +    text-indent: -1em; +  } +  p[indent=\"h4i6\"] { +    padding-left: 6em; +    text-indent: -2em; +  } +  p[indent=\"h4i7\"] { +    padding-left: 7em; +    text-indent: -3em; +  } +  p[indent=\"h4i8\"] { +    padding-left: 8em; +    text-indent: -4em; +  } +  p[indent=\"h4i9\"] { +    padding-left: 9em; +    text-indent: -5em; +  } +  p[indent=\"h5i0\"] { +    padding-left: 0em; +    text-indent:  5em; +  } +  p[indent=\"h5i1\"] { +    padding-left: 1em; +    text-indent:  4em; +  } +  p[indent=\"h5i2\"] { +    padding-left: 2em; +    text-indent:  3em; +  } +  p[indent=\"h5i3\"] { +    padding-left: 3em; +    text-indent:  2em; +  } +  p[indent=\"h5i4\"] { +    padding-left: 4em; +    text-indent:  1em; +  } +  p[indent=\"h5i5\"] { +    padding-left: 5em; +    text-indent:  0em; +  } +  p[indent=\"h5i6\"] { +    padding-left: 6em; +    text-indent: -1em; +  } +  p[indent=\"h5i7\"] { +    padding-left: 7em; +    text-indent: -2em; +  } +  p[indent=\"h5i8\"] { +    padding-left: 8em; +    text-indent: -3em; +  } +  p[indent=\"h5i9\"] { +    padding-left: 9em; +    text-indent: -4em; +  } +  p[indent=\"h6i0\"] { +    padding-left: 0em; +    text-indent:  6em; +  } +  p[indent=\"h6i1\"] { +    padding-left: 1em; +    text-indent:  5em; +  } +  p[indent=\"h6i2\"] { +    padding-left: 2em; +    text-indent:  4em; +  } +  p[indent=\"h6i3\"] { +    padding-left: 3em; +    text-indent:  3em; +  } +  p[indent=\"h6i4\"] { +    padding-left: 4em; +    text-indent:  2em; +  } +  p[indent=\"h6i5\"] { +    padding-left: 5em; +    text-indent:  1em; +  } +  p[indent=\"h6i6\"] { +    padding-left: 6em; +    text-indent:  0em; +  } +  p[indent=\"h6i7\"] { +    padding-left: 7em; +    text-indent: -1em; +  } +  p[indent=\"h6i8\"] { +    padding-left: 8em; +    text-indent: -2em; +  } +  p[indent=\"h6i9\"] { +    padding-left: 9em; +    text-indent: -3em; +  } +  p[indent=\"h7i0\"] { +    padding-left: 0em; +    text-indent:  7em; +  } +  p[indent=\"h7i1\"] { +    padding-left: 1em; +    text-indent:  6em; +  } +  p[indent=\"h7i2\"] { +    padding-left: 2em; +    text-indent:  5em; +  } +  p[indent=\"h7i3\"] { +    padding-left: 3em; +    text-indent:  4em; +  } +  p[indent=\"h7i4\"] { +    padding-left: 4em; +    text-indent:  3em; +  } +  p[indent=\"h7i5\"] { +    padding-left: 5em; +    text-indent:  2em; +  } +  p[indent=\"h7i6\"] { +    padding-left: 6em; +    text-indent:  1em; +  } +  p[indent=\"h7i7\"] { +    padding-left: 7em; +    text-indent:  0em; +  } +  p[indent=\"h7i8\"] { +    padding-left: 8em; +    text-indent: -1em; +  } +  p[indent=\"h7i9\"] { +    padding-left: 9em; +    text-indent: -2em; +  } +  p[indent=\"h8i0\"] { +    padding-left: 0em; +    text-indent:  8em; +  } +  p[indent=\"h8i1\"] { +    padding-left: 1em; +    text-indent:  7em; +  } +  p[indent=\"h8i2\"] { +    padding-left: 2em; +    text-indent:  6em; +  } +  p[indent=\"h8i3\"] { +    padding-left: 3em; +    text-indent:  5em; +  } +  p[indent=\"h8i4\"] { +    padding-left: 4em; +    text-indent:  4em; +  } +  p[indent=\"h8i5\"] { +    padding-left: 5em; +    text-indent:  3em; +  } +  p[indent=\"h8i6\"] { +    padding-left: 6em; +    text-indent:  2em; +  } +  p[indent=\"h8i7\"] { +    padding-left: 7em; +    text-indent:  1em; +  } +  p[indent=\"h8i8\"] { +    padding-left: 8em; +    text-indent:  0em; +  } +  p[indent=\"h8i9\"] { +    padding-left: 9em; +    text-indent: -1em; +  } +  p[indent=\"h9i0\"] { +    padding-left: 0em; +    text-indent:  9em; +  } +  p[indent=\"h9i1\"] { +    padding-left: 1em; +    text-indent:  8em; +  } +  p[indent=\"h9i2\"] { +    padding-left: 2em; +    text-indent:  7em; +  } +  p[indent=\"h9i3\"] { +    padding-left: 3em; +    text-indent:  6em; +  } +  p[indent=\"h9i4\"] { +    padding-left: 4em; +    text-indent:  5em; +  } +  p[indent=\"h9i5\"] { +    padding-left: 5em; +    text-indent:  4em; +  } +  p[indent=\"h9i6\"] { +    padding-left: 6em; +    text-indent:  3em; +  } +  p[indent=\"h9i7\"] { +    padding-left: 7em; +    text-indent:  2em; +  } +  p[indent=\"h9i8\"] { +    padding-left: 8em; +    text-indent:  1em; +  } +  p[indent=\"h9i9\"] { +    padding-left: 9em; +    text-indent:  0em; +  } +  note { white-space: pre; } +  label.ocn { +    width: 2%; +    float: right; +    top: 0; +    font-size: 10px; +    margin-top: 0px; +    margin-bottom: 5px; +    color: #777777; +    margin-right: 5px; +    text-align: right; +    background-color: #ffffff; +  } +  table { } +  tr { } +  th,td { +    vertical-align: top; +    text-align: left; +  } +  th { +    font-weight: bold; +  } +  em { +    font-weight: bold; +    font-style: italic; +  } +  p.left,th.left,td.left { +    text-align: left; +  } +  p.small_left,th.small_left,td.small_left { +    text-align: left; +    font-size: 80%; +  } +  p.right,th.right,td.right { +    text-align: right; +  } +  ul, li { +    list-style-type: none; +    list-style: none; +    padding-left: 20px; +    display: block; +    font-family: verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman; +    font-weight: normal; +    line-height: 150%; +    text-align: left; +    text-indent: 0mm; +    margin-left: 1em; +    margin-right: 2em; +    margin-top: 3px; +    margin-bottom: 3px; +  } +  li { +    background: url(../image_sys/bullet_09.png) no-repeat 0px 6px; +  } +  ul { +  } +  h0, h1, h2, h3, h4, h5, h6, h7 { +    font-weight: bold; +    line-height: 120%; +    text-align: left; +    margin-top: 20px; +    margin-bottom: 10px; +  } +  h4.norm, h5.norm, h6.norm, h7.norm { +    margin-top: 10px; +    margin-bottom: 0px; +  } +  h0 { font-size: 125%; } +  h1 { font-size: 120%; } +  h2 { font-size: 115%; } +  h3 { font-size: 110%; } +  h4 { font-size: 105%; } +  h5 { font-size: 100%; } +  h6 { font-size: 100%; } +  h7 { font-size: 100%; } +  h0, h1, h2, h3, h4, h5, h6, h7 { text-shadow: .2em .2em .3em gray; } +  h1.i { margin-left: 2em; } +  h2.i { margin-left: 3em; } +  h3.i { margin-left: 4em; } +  h4.i { margin-left: 5em; } +  h5.i { margin-left: 6em; } +  h6.i { margin-left: 7em; } +  h7.i { margin-left: 8em; } +  h8.i { margin-left: 9em; } +  h9.i { margin-left: 10em; } +  .toc { +    font-weight: normal; +    margin-top: 6px; +    margin-bottom: 6px; +  } +  h0.toc { +    margin-left: 1em; +    font-size: 120%; +    line-height: 150%; +  } +  h1.toc { +    margin-left: 1em; +    font-size: 115%; +    line-height: 150%; +  } +  h2.toc { +    margin-left: 2em; +    font-size: 110%; +    line-height: 140%; +  } +  h3.toc { +    margin-left: 3em; +    font-size: 105%; +    line-height: 120%; +  } +  h4.toc { +    margin-left: 4em; +    font-size: 100%; +    line-height: 120%; +  } +  h5.toc { +    margin-left: 5em; +    font-size: 95%; +    line-height: 110%; +  } +  h6.toc { +    margin-left: 6em; +    font-size: 90%; +    line-height: 110%; +  } +  h7.toc { +    margin-left: 7em; +    font-size: 85%; +    line-height: 100%; +  } +  .subtoc { +    margin-right: 34%; +    font-weight: normal; +  } +  h5.subtoc { +    margin-left: 2em; +    font-size: 80%; +    margin-top: 2px; +    margin-bottom: 2px; +  } +  h6.subtoc { +    margin-left: 3em; +    font-size: 75%; +    margin-top: 0px; +    margin-bottom: 0px; +  } +  h7.subtoc { +    margin-left: 4em; +    font-size: 70%; +    margin-top: 0px; +    margin-bottom: 0px; +  } +  .icon-bar { +    width: 100%; +    overflow: auto; +    margin: 0em 0em 0em; +  } +  .left-bar { +    width: 85%; +    float: left; +    display: inline; +    overflow: auto; +  } +  .toc-button { +    position: absolute; +    top: 8px; +    width: 2em; +    height: 2em; +    border-radius: 50%; +    background: #cccccc; +  } +  .toc-button svg { +    position: relative; +    left: 25%; +    top: 25%; +    width: 150%; +    height: 150%; +  } +  .toc-button p { +    vertical-align: center; +    font-size: 120%; +  } +  .prev-next-button { +    position: absolute; +    top: 8px; +    width: 2em; +    height: 2em; +    border-radius: 50%; +    background: #cccccc; +  } +  .prev-next-button svg { +    position: relative; +    left: 20%; +    top: 20%; +    width: 60%; +    height: 60%; +  } +  .menu { +    right: 6em; +   } +  .previous { +    right: 3em; +   } +  .next { +    right: 0em; +   } +  .arrow { fill: #333333; } +  /* flex */ +  .flex-menu-bar { +    display: -webkit-flex; +    display: flex; +    -webkit-flex-wrap: wrap; +    -webkit-align-items: center; +    align-items: center; +    width: 100%; +    background-color: #ffffff; +  } +  .flex-menu-option { +    background-color: white; +    margin: 8px; +  } +  .flex-list { +    display: -webkit-flex; +    display: flex; +    -webkit-align-items: center; +    display: block; +    align-items: center; +    width: 100%; +    background-color: #ffffff; +  } +  .flex-list-item { +    background-color: white; +    margin: 4px; +  } +  /* grid */ +  .wrapper { +    display: grid; +    grid-template-columns: 100%; +    grid-template-areas: +      \"headband\" +      \"doc_header\" +      \"doc_title\" +      \"doc_toc\" +      \"doc_prefix\" +      \"doc_intro\" +      \"doc_body\" +      \"doc_endnotes\" +      \"doc_glossary\" +      \"doc_biblio\" +      \"doc_bookindex\" +      \"doc_blurb\" +      \"doc_suffix\"; +    margin: 0px; +    padding: 0px; +    background-color: #ffffff; +  } +  .delimit { +    border-style: none; +    border-color: white; +    padding: 10px; +  } +  .headband { +    grid-area: headband; +    background-color: #ffffff; +  } +  .doc_header { +    grid-area: doc_header; +  } +  .doc_title { +    grid-area: doc_title; +  } +  .doc_toc { +    grid-area: doc_toc; +  } +  .doc_prefix { +    grid-area: doc_prefix; +  } +  .doc_intro { +    grid-area: doc_intro; +  } +  .doc_body { +    grid-area: doc_body; +  } +  .doc_endnotes { +    grid-area: doc_endnotes; +  } +  .doc_glossary { +    grid-area: doc_glossary; +  } +  .doc_biblio { +    grid-area: doc_biblio; +  } +  .doc_bookindex { +    grid-area: doc_bookindex; +  } +  .doc_blurb { +    grid-area: doc_blurb; +  } +  .doc_suffix { +    grid-area: doc_suffix; +  } +  .nav-ul { +    list-style: none; +    float: left; +  } +  .nav-li { +    float: left; +    padding-right: 0.7em; +  } +  .nav-li a { +    text-decoration: none; +    color: white; +  } +  footer { +    background-color: #00704e; +  } +"; +    string _css_html_scroll=" +  *{ +    padding: 0px; +    margin: 0px; +  } +  body { +    height: 100vh; +    background-color: #ffffff; +  } +  body { +    color: black; +    background: #ffffff; +    background-color: #ffffff; +  } +  a:link { +    color: #003399; +    text-decoration: none; +  } +  a:visited { +    color: #003399; +    text-decoration: none; +  } +  a:hover { +    color: #000000; +    background-color: #f9f9aa; +  } +  a.lnkocn:link { +    color: #777777; +    text-decoration: none; +  } +  a:hover img { +    background-color: #ffffff; +  } +  a:active { +    color: #003399; +    text-decoration: underline; +  } +  div { +    margin-left: 0; +    margin-right: 0; +  } +  div.p { +    margin-left: 5%; +    margin-right: 1%; +  } +  div.substance { +    width: 100%; +    background-color: #ffffff; +  } +  div.ocn { +    width: 5%; +    float: right; +    top: 0; +    background-color: #ffffff; +  } +  div.endnote { +    width: 95%; +    background-color: #fffffff; +  } +  div.toc { +    position: absolute; +    float: left; +    margin: 0; +    padding: 0; +    padding-top: 0.5em; +    border: 0; +    width: 13em; +    background-color: #eeeeee; +    margin-right:1em; +  } +  div.summary { +    margin: 0; +    padding: 0; +    border-left: 13em solid #eeeeee; +    padding-left: 1em; +    background-color: #eeeeee; +  } +  div.content, div.main_column { +    margin: 0; +    padding: 0; +    border-left: 13em solid #ffffff; +    padding-left: 1em; +    padding-right: 1em; +  } +  div.content0, div.main_column0 { +    margin: 0; +    padding: 0; +    border-left: 0% solid #ffffff; +    padding-left: 5%; +  } +  div.scroll { +    margin: 0; +    padding: 0; +    padding-left: 1em; +    padding-right: 1em; +  } +  div.content:after { +    content:' '; +    clear:both; +    display:block; +    height:0; +    overflow:hidden +  } +  div.footer { +    clear:left; +    padding: 0.5em; +    font-size: 80%; +    margin: 0; +  } +  div.toc ul { +    list-style: none; +    padding: 0; +    margin: 0; +  } +  div.toc li ul a, li ul span.currentlink +  { +    font-weight: normal; +    font-size: 90%; +    padding-left: 2em; +    background-color: #eeeeee; +  } +  div.toc a, span.currentlink{ +    display:block; +    text-decoration: none; +    padding-left: 0.5em; +    color: #0000aa; +  } +  hr { +    width: 90%; +    margin-top: 1.8em; +    margin-bottom: 1.8em; +  } +  span.currentlink { +    text-decoration: none; +    background-color: #aaaaf9; +  } +  div.toc a:visited { +    color: #0000aa; +  } +  div.toc a:hover { +    color: #000000; +    background-color: #f9f9aa; +  } +  nav#toc ol { +    list-style-type: none; +  } +  .norm, .bold, .verse, .group, .block, .alt { +    line-height: 133%; +    margin-left: 0em; +    margin-right: 2em; +    margin-top: 12px; +    margin-bottom: 0px; +    padding-left: 0em; +    text-indent: 0em; +  } +  p, h0, h1, h2, h3, h4, h5, h6, h7 { +    display: block; +    font-family: verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman; +    font-size: 100%; +    font-weight: normal; +    line-height: 133%; +    text-align: justify; +    margin-left: 0em; +    margin-right: 2em; +    text-indent: 0mm; +    margin-top: 0.8em; +    margin-bottom: 0.8em; +  } +  img { max-width: 100%; height: auto; } +  /* spaced */ +  p.spaced { white-space: pre; } +  p.block { +    white-space: pre; +  } +  p.group { } +  p.alt { } +  p.verse { +    white-space: pre; +    margin-bottom: 6px; +  } +  p.code { +    font-family: inconsolata, andale mono, courier new, courier, monospace; +    font-size: 90%; +    text-align: left; +    background-color: #eeeeee; +    white-space: pre; +    margin-top: 0px; +    margin-bottom: 0px; +  } +  p.caption { +    text-align: left; +    font-size: 80%; +    display: inline; +  } +  p.endnote { +    font-size: 96%; +    line-height: 120%; +    text-align: left; +    margin-right: 15mm; +  } +  p.endnote_indent { +    font-size: 96%; +    line-height: 120%; +    text-align: left; +    margin-left: 2em; +    margin-right: 15mm; +  } +  p.center { +    text-align: center; +  } +  p.bold { +    font-weight: bold; +  } +  p.bold_left { +    font-weight: bold; +    text-align: left; +  } +  p.centerbold { +    text-align: center; +    font-weight: bold; +  } +  p.em { +    font-weight: bold; +    font-style: normal; +    background: #fff3b6; +  } +  p.small { +    font-size: 80%; +    margin-top: 0px; +    margin-bottom: 0px; +    margin-right: 6px; +    text-align: left; +  } +  .tiny, .tiny_left, .tiny_right, .tiny_center { +    font-size: 10px; +    margin-top: 0px; +    margin-bottom: 0px; +    color: #777777; +    margin-right: 6px; +    text-align: left; +  } +  p.tiny { } +  p.tiny_left { +    margin-left: 0px; +    margin-right: 0px; +    text-align: left; +  } +  p.tiny_right { +    margin-right: 1em; +    text-align: right; +  } +  p.tiny_center { +    margin-left: 0px; +    margin-right: 0px; +    text-align: center; +  } +  p.concordance_word { +    line-height: 150%; +    font-weight: bold; +    display: inline; +    margin-top: 4px; +    margin-bottom: 1px; +  } +  p.concordance_count { +    font-size: 80%; +    color: #777777; +    display: inline; +    margin-left: 0em; +  } +  p.concordance_object { +    font-size: 80%; +    line-height: 120%; +    text-align: left; +    margin-left: 3em; +    margin-top: 1px; +    margin-bottom: 3px; +  } +  p.book_index_lev1 { +    line-height: 100%; +    margin-top: 4px; +    margin-bottom: 1px; +  } +  p.book_index_lev2 { +    line-height: 100%; +    text-align: left; +    margin-left: 3em; +    margin-top: 1px; +    margin-bottom: 3px; +  } +  tt { +    font-family: inconsolata, andale mono, courier new, courier, monospace; +    background-color: #eeeeee; +  } +  /* indent */ +  p.norm { } +  p.i1 { padding-left: 1em; } +  p.i2 { padding-left: 2em; } +  p.i3 { padding-left: 3em; } +  p.i4 { padding-left: 4em; } +  p.i5 { padding-left: 5em; } +  p.i6 { padding-left: 6em; } +  p.i7 { padding-left: 7em; } +  p.i8 { padding-left: 8em; } +  p.i9 { padding-left: 9em; } +  /* hanging indent */ +  p[indent=\"h0i0\"] { +    padding-left: 0em; +    text-indent:  0em; +  } +  p[indent=\"h0i1\"] { +    padding-left: 1em; +    text-indent: -1em; +  } +  p[indent=\"h0i2\"] { +    padding-left: 2em; +    text-indent: -2em; +  } +  p[indent=\"h0i3\"] { +    padding-left: 3em; +    text-indent: -3em; +  } +  p[indent=\"h0i4\"] { +    padding-left: 4em; +    text-indent: -4em; +  } +  p[indent=\"h0i5\"] { +    padding-left: 5em; +    text-indent: -5em; +  } +  p[indent=\"h0i6\"] { +    padding-left: 6em; +    text-indent: -6em; +  } +  p[indent=\"h0i7\"] { +    padding-left: 7em; +    text-indent: -7em; +  } +  p[indent=\"h0i8\"] { +    padding-left: 8em; +    text-indent: -8em; +  } +  p[indent=\"h0i9\"] { +    padding-left: 9em; +    text-indent: -9em; +  } +  p[indent=\"h1i0\"] { +    padding-left: 0em; +    text-indent:  1em; +  } +  p[indent=\"h1i1\"] { +    padding-left: 1em; +    text-indent:  0em; +  } +  p[indent=\"h1i2\"] { +    padding-left: 2em; +    text-indent: -1em; +  } +  p[indent=\"h1i3\"] { +    padding-left: 3em; +    text-indent: -2em; +  } +  p[indent=\"h1i4\"] { +    padding-left: 4em; +    text-indent: -3em; +  } +  p[indent=\"h1i5\"] { +    padding-left: 5em; +    text-indent: -4em; +  } +  p[indent=\"h1i6\"] { +    padding-left: 6em; +    text-indent: -5em; +  } +  p[indent=\"h1i7\"] { +    padding-left: 7em; +    text-indent: -6em; +  } +  p[indent=\"h1i8\"] { +    padding-left: 8em; +    text-indent: -7em; +  } +  p[indent=\"h1i9\"] { +    padding-left: 9em; +    text-indent: -8em; +  } +  p[indent=\"h2i0\"] { +    padding-left: 0em; +    text-indent:  2em; +  } +  p[indent=\"h2i1\"] { +    padding-left: 1em; +    text-indent:  1em; +  } +  p[indent=\"h2i2\"] { +    padding-left: 2em; +    text-indent:  0em; +  } +  p[indent=\"h2i3\"] { +    padding-left: 3em; +    text-indent: -1em; +  } +  p[indent=\"h2i4\"] { +    padding-left: 4em; +    text-indent: -2em; +  } +  p[indent=\"h2i5\"] { +    padding-left: 5em; +    text-indent: -3em; +  } +  p[indent=\"h2i6\"] { +    padding-left: 6em; +    text-indent: -4em; +  } +  p[indent=\"h2i7\"] { +    padding-left: 7em; +    text-indent: -5em; +  } +  p[indent=\"h2i8\"] { +    padding-left: 8em; +    text-indent: -6em; +  } +  p[indent=\"h2i9\"] { +    padding-left: 9em; +    text-indent: -7em; +  } +  p[indent=\"h3i0\"] { +    padding-left: 0em; +    text-indent:  3em; +  } +  p[indent=\"h3i1\"] { +    padding-left: 1em; +    text-indent:  2em; +  } +  p[indent=\"h3i2\"] { +    padding-left: 2em; +    text-indent:  1em; +  } +  p[indent=\"h3i3\"] { +    padding-left: 3em; +    text-indent:  0em; +  } +  p[indent=\"h3i4\"] { +    padding-left: 4em; +    text-indent: -1em; +  } +  p[indent=\"h3i5\"] { +    padding-left: 5em; +    text-indent: -2em; +  } +  p[indent=\"h3i6\"] { +    padding-left: 6em; +    text-indent: -3em; +  } +  p[indent=\"h3i7\"] { +    padding-left: 7em; +    text-indent: -4em; +  } +  p[indent=\"h3i8\"] { +    padding-left: 8em; +    text-indent: -5em; +  } +  p[indent=\"h3i9\"] { +    padding-left: 9em; +    text-indent: -6em; +  } +  p[indent=\"h4i0\"] { +    padding-left: 0em; +    text-indent:  4em; +  } +  p[indent=\"h4i1\"] { +    padding-left: 1em; +    text-indent:  3em; +  } +  p[indent=\"h4i2\"] { +    padding-left: 2em; +    text-indent:  2em; +  } +  p[indent=\"h4i3\"] { +    padding-left: 3em; +    text-indent:  1em; +  } +  p[indent=\"h4i4\"] { +    padding-left: 4em; +    text-indent:  0em; +  } +  p[indent=\"h4i5\"] { +    padding-left: 5em; +    text-indent: -1em; +  } +  p[indent=\"h4i6\"] { +    padding-left: 6em; +    text-indent: -2em; +  } +  p[indent=\"h4i7\"] { +    padding-left: 7em; +    text-indent: -3em; +  } +  p[indent=\"h4i8\"] { +    padding-left: 8em; +    text-indent: -4em; +  } +  p[indent=\"h4i9\"] { +    padding-left: 9em; +    text-indent: -5em; +  } +  p[indent=\"h5i0\"] { +    padding-left: 0em; +    text-indent:  5em; +  } +  p[indent=\"h5i1\"] { +    padding-left: 1em; +    text-indent:  4em; +  } +  p[indent=\"h5i2\"] { +    padding-left: 2em; +    text-indent:  3em; +  } +  p[indent=\"h5i3\"] { +    padding-left: 3em; +    text-indent:  2em; +  } +  p[indent=\"h5i4\"] { +    padding-left: 4em; +    text-indent:  1em; +  } +  p[indent=\"h5i5\"] { +    padding-left: 5em; +    text-indent:  0em; +  } +  p[indent=\"h5i6\"] { +    padding-left: 6em; +    text-indent: -1em; +  } +  p[indent=\"h5i7\"] { +    padding-left: 7em; +    text-indent: -2em; +  } +  p[indent=\"h5i8\"] { +    padding-left: 8em; +    text-indent: -3em; +  } +  p[indent=\"h5i9\"] { +    padding-left: 9em; +    text-indent: -4em; +  } +  p[indent=\"h6i0\"] { +    padding-left: 0em; +    text-indent:  6em; +  } +  p[indent=\"h6i1\"] { +    padding-left: 1em; +    text-indent:  5em; +  } +  p[indent=\"h6i2\"] { +    padding-left: 2em; +    text-indent:  4em; +  } +  p[indent=\"h6i3\"] { +    padding-left: 3em; +    text-indent:  3em; +  } +  p[indent=\"h6i4\"] { +    padding-left: 4em; +    text-indent:  2em; +  } +  p[indent=\"h6i5\"] { +    padding-left: 5em; +    text-indent:  1em; +  } +  p[indent=\"h6i6\"] { +    padding-left: 6em; +    text-indent:  0em; +  } +  p[indent=\"h6i7\"] { +    padding-left: 7em; +    text-indent: -1em; +  } +  p[indent=\"h6i8\"] { +    padding-left: 8em; +    text-indent: -2em; +  } +  p[indent=\"h6i9\"] { +    padding-left: 9em; +    text-indent: -3em; +  } +  p[indent=\"h7i0\"] { +    padding-left: 0em; +    text-indent:  7em; +  } +  p[indent=\"h7i1\"] { +    padding-left: 1em; +    text-indent:  6em; +  } +  p[indent=\"h7i2\"] { +    padding-left: 2em; +    text-indent:  5em; +  } +  p[indent=\"h7i3\"] { +    padding-left: 3em; +    text-indent:  4em; +  } +  p[indent=\"h7i4\"] { +    padding-left: 4em; +    text-indent:  3em; +  } +  p[indent=\"h7i5\"] { +    padding-left: 5em; +    text-indent:  2em; +  } +  p[indent=\"h7i6\"] { +    padding-left: 6em; +    text-indent:  1em; +  } +  p[indent=\"h7i7\"] { +    padding-left: 7em; +    text-indent:  0em; +  } +  p[indent=\"h7i8\"] { +    padding-left: 8em; +    text-indent: -1em; +  } +  p[indent=\"h7i9\"] { +    padding-left: 9em; +    text-indent: -2em; +  } +  p[indent=\"h8i0\"] { +    padding-left: 0em; +    text-indent:  8em; +  } +  p[indent=\"h8i1\"] { +    padding-left: 1em; +    text-indent:  7em; +  } +  p[indent=\"h8i2\"] { +    padding-left: 2em; +    text-indent:  6em; +  } +  p[indent=\"h8i3\"] { +    padding-left: 3em; +    text-indent:  5em; +  } +  p[indent=\"h8i4\"] { +    padding-left: 4em; +    text-indent:  4em; +  } +  p[indent=\"h8i5\"] { +    padding-left: 5em; +    text-indent:  3em; +  } +  p[indent=\"h8i6\"] { +    padding-left: 6em; +    text-indent:  2em; +  } +  p[indent=\"h8i7\"] { +    padding-left: 7em; +    text-indent:  1em; +  } +  p[indent=\"h8i8\"] { +    padding-left: 8em; +    text-indent:  0em; +  } +  p[indent=\"h8i9\"] { +    padding-left: 9em; +    text-indent: -1em; +  } +  p[indent=\"h9i0\"] { +    padding-left: 0em; +    text-indent:  9em; +  } +  p[indent=\"h9i1\"] { +    padding-left: 1em; +    text-indent:  8em; +  } +  p[indent=\"h9i2\"] { +    padding-left: 2em; +    text-indent:  7em; +  } +  p[indent=\"h9i3\"] { +    padding-left: 3em; +    text-indent:  6em; +  } +  p[indent=\"h9i4\"] { +    padding-left: 4em; +    text-indent:  5em; +  } +  p[indent=\"h9i5\"] { +    padding-left: 5em; +    text-indent:  4em; +  } +  p[indent=\"h9i6\"] { +    padding-left: 6em; +    text-indent:  3em; +  } +  p[indent=\"h9i7\"] { +    padding-left: 7em; +    text-indent:  2em; +  } +  p[indent=\"h9i8\"] { +    padding-left: 8em; +    text-indent:  1em; +  } +  p[indent=\"h9i9\"] { +    padding-left: 9em; +    text-indent:  0em; +  } +  note { white-space: pre; } +  label.ocn { +    width: 2%; +    float: right; +    top: 0; +    font-size: 10px; +    margin-top: 0px; +    margin-bottom: 5px; +    color: #777777; +    margin-right: 5px; +    text-align: right; +    background-color: #ffffff; +  } +  table { } +  tr { } +  th,td { +    vertical-align: top; +    text-align: left; +  } +  th { +    font-weight: bold; +  } +  em { +    font-weight: bold; +    font-style: italic; +  } +  p.left,th.left,td.left { +    text-align: left; +  } +  p.small_left,th.small_left,td.small_left { +    text-align: left; +    font-size: 80%; +  } +  p.right,th.right,td.right { +    text-align: right; +  } +  ul, li { +    list-style-type: none; +    list-style: none; +    padding-left: 20px; +    display: block; +    font-family: verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman; +    font-weight: normal; +    line-height: 150%; +    text-align: left; +    text-indent: 0mm; +    margin-left: 1em; +    margin-right: 2em; +    margin-top: 3px; +    margin-bottom: 3px; +  } +  li { +    background: url(../image_sys/bullet_09.png) no-repeat 0px 6px; +  } +  ul { +  } +  h0, h1, h2, h3, h4, h5, h6, h7 { +    font-weight: bold; +    line-height: 120%; +    text-align: left; +    margin-top: 20px; +    margin-bottom: 10px; +  } +  h4.norm, h5.norm, h6.norm, h7.norm { +    margin-top: 10px; +    margin-bottom: 0px; +  } +  h0 { font-size: 125%; } +  h1 { font-size: 120%; } +  h2 { font-size: 115%; } +  h3 { font-size: 110%; } +  h4 { font-size: 105%; } +  h5 { font-size: 100%; } +  h6 { font-size: 100%; } +  h7 { font-size: 100%; } +  h0, h1, h2, h3, h4, h5, h6, h7 { text-shadow: .2em .2em .3em gray; } +  h1.i { margin-left: 2em; } +  h2.i { margin-left: 3em; } +  h3.i { margin-left: 4em; } +  h4.i { margin-left: 5em; } +  h5.i { margin-left: 6em; } +  h6.i { margin-left: 7em; } +  h7.i { margin-left: 8em; } +  h8.i { margin-left: 9em; } +  h9.i { margin-left: 10em; } +  .toc { +    font-weight: normal; +    margin-top: 6px; +    margin-bottom: 6px; +  } +  h0.toc { +    margin-left: 1em; +    font-size: 120%; +    line-height: 150%; +  } +  h1.toc { +    margin-left: 1em; +    font-size: 115%; +    line-height: 150%; +  } +  h2.toc { +    margin-left: 2em; +    font-size: 110%; +    line-height: 140%; +  } +  h3.toc { +    margin-left: 3em; +    font-size: 105%; +    line-height: 120%; +  } +  h4.toc { +    margin-left: 4em; +    font-size: 100%; +    line-height: 120%; +  } +  h5.toc { +    margin-left: 5em; +    font-size: 95%; +    line-height: 110%; +  } +  h6.toc { +    margin-left: 6em; +    font-size: 90%; +    line-height: 110%; +  } +  h7.toc { +    margin-left: 7em; +    font-size: 85%; +    line-height: 100%; +  } +  .subtoc { +    margin-right: 34%; +    font-weight: normal; +  } +  h5.subtoc { +    margin-left: 2em; +    font-size: 80%; +    margin-top: 2px; +    margin-bottom: 2px; +  } +  h6.subtoc { +    margin-left: 3em; +    font-size: 75%; +    margin-top: 0px; +    margin-bottom: 0px; +  } +  h7.subtoc { +    margin-left: 4em; +    font-size: 70%; +    margin-top: 0px; +    margin-bottom: 0px; +  } +  /* flex */ +  .flex-menu-bar { +    display: -webkit-flex; +    display: flex; +    -webkit-flex-wrap: wrap; +    -webkit-align-items: center; +    align-items: center; +    width: 100%; +    background-color: #ffffff; +  } +  .flex-menu-option { +    background-color: white; +    margin: 8px; +  } +  .flex-list { +    display: -webkit-flex; +    display: flex; +    -webkit-align-items: center; +    display: block; +    align-items: center; +    width: 100%; +    background-color: #ffffff; +  } +  .flex-list-item { +    background-color: white; +    margin: 4px; +  } +  /* grid */ +  .wrapper { +    display: grid; +    grid-template-columns: 100%; +    grid-template-areas: +      \"headband\" +      \"doc_header\" +      \"doc_title\" +      \"doc_toc\" +      \"doc_prefix\" +      \"doc_intro\" +      \"doc_body\" +      \"doc_endnotes\" +      \"doc_glossary\" +      \"doc_biblio\" +      \"doc_bookindex\" +      \"doc_blurb\" +      \"doc_suffix\"; +    margin: 0px; +    padding: 0px; +    background-color: #ffffff; +  } +  .delimit { +    border-style: none; +    border-color: white; +    padding: 10px; +  } +  .headband { +    grid-area: headband; +    background-color: #ffffff; +  } +  .doc_header { +    grid-area: doc_header; +  } +  .doc_title { +    grid-area: doc_title; +  } +  .doc_toc { +    grid-area: doc_toc; +  } +  .doc_prefix { +    grid-area: doc_prefix; +  } +  .doc_intro { +    grid-area: doc_intro; +  } +  .doc_body { +    grid-area: doc_body; +  } +  .doc_endnotes { +    grid-area: doc_endnotes; +  } +  .doc_glossary { +    grid-area: doc_glossary; +  } +  .doc_biblio { +    grid-area: doc_biblio; +  } +  .doc_bookindex { +    grid-area: doc_bookindex; +  } +  .doc_blurb { +    grid-area: doc_blurb; +  } +  .doc_suffix { +    grid-area: doc_suffix; +  } +  .nav-ul { +    list-style: none; +    float: left; +  } +  .nav-li { +    float: left; +    padding-right: 0.7em; +  } +  .nav-li a { +    text-decoration: none; +    color: white; +  } +  footer { +    background-color: #00704e; +  } +"; +    string _css_epub=" +  *{ +    padding: 0px; +    margin: 0px; +  } +  body { +    height: 100vh; +    background-color: #ffffff; +  } +  body { +    color: black; +    background: #ffffff; +    background-color: #ffffff; +  } +  a:link { +    color: #003399; +    text-decoration: none; +  } +  a:visited { +    color: #003399; +    text-decoration: none; +  } +  a:hover { +    color: #000000; +    background-color: #f9f9aa; +  } +  a.lnkocn:link { +    color: #777777; +    text-decoration: none; +  } +  a:hover img { +    background-color: #ffffff; +  } +  a:active { +    color: #003399; +    text-decoration: underline; +  } +  div { +    margin-left: 0; +    margin-right: 0; +  } +  div.p { +    margin-left: 5%; +    margin-right: 1%; +  } +  div.substance { +    width: 100%; +    background-color: #ffffff; +  } +  div.ocn { +    width: 5%; +    float: right; +    top: 0; +    background-color: #ffffff; +  } +  div.endnote { +    width: 95%; +    background-color: #fffffff; +  } +  div.toc { +    position: absolute; +    float: left; +    margin: 0; +    padding: 0; +    padding-top: 0.5em; +    border: 0; +    width: 13em; +    background-color: #eeeeee; +    margin-right:1em; +  } +  div.summary { +    margin: 0; +    padding: 0; +    border-left: 13em solid #eeeeee; +    padding-left: 1em; +    background-color: #eeeeee; +  } +  div.content, div.main_column { +    margin: 0; +    padding: 0; +    border-left: 13em solid #ffffff; +    padding-left: 1em; +    padding-right: 1em; +  } +  div.content0, div.main_column0 { +    margin: 0; +    padding: 0; +    border-left: 0% solid #ffffff; +    padding-left: 5%; +  } +  div.scroll { +    margin: 0; +    padding: 0; +    padding-left: 1em; +    padding-right: 1em; +  } +  div.content:after { +    content:' '; +    clear:both; +    display:block; +    height:0; +    overflow:hidden +  } +  div.footer { +    clear:left; +    padding: 0.5em; +    font-size: 80%; +    margin: 0; +  } +  div.toc ul { +    list-style: none; +    padding: 0; +    margin: 0; +  } +  div.toc li ul a, li ul span.currentlink +  { +    font-weight: normal; +    font-size: 90%; +    padding-left: 2em; +    background-color: #eeeeee; +  } +  div.toc a, span.currentlink{ +    display:block; +    text-decoration: none; +    padding-left: 0.5em; +    color: #0000aa; +  } +  hr { +    width: 90%; +    margin-top: 1.8em; +    margin-bottom: 1.8em; +  } +  span.currentlink { +    text-decoration: none; +    background-color: #aaaaf9; +  } +  div.toc a:visited { +    color: #0000aa; +  } +  div.toc a:hover { +    color: #000000; +    background-color: #f9f9aa; +  } +  nav#toc ol { +    list-style-type: none; +  } +  .norm, .bold, .verse, .group, .block, .alt { +    line-height: 133%; +    margin-left: 0em; +    margin-right: 2em; +    margin-top: 12px; +    margin-bottom: 0px; +    padding-left: 0em; +    text-indent: 0em; +  } +  p, h0, h1, h2, h3, h4, h5, h6, h7 { +    display: block; +    font-family: verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman; +    font-size: 100%; +    font-weight: normal; +    line-height: 133%; +    text-align: justify; +    margin-left: 0em; +    margin-right: 2em; +    text-indent: 0mm; +    margin-top: 0.8em; +    margin-bottom: 0.8em; +  } +  img { max-width: 100%; height: auto; } +  /* spaced */ +  p.spaced { white-space: pre; } +  p.block { +    white-space: pre; +  } +  p.group { } +  p.alt { } +  p.verse { +    white-space: pre; +    margin-bottom: 6px; +  } +  p.code { +    font-family: inconsolata, andale mono, courier new, courier, monospace; +    font-size: 90%; +    text-align: left; +    background-color: #eeeeee; +    white-space: pre; +    margin-top: 0px; +    margin-bottom: 0px; +  } +  p.caption { +    text-align: left; +    font-size: 80%; +    display: inline; +  } +  p.endnote { +    font-size: 96%; +    line-height: 120%; +    text-align: left; +    margin-right: 15mm; +  } +  p.endnote_indent { +    font-size: 96%; +    line-height: 120%; +    text-align: left; +    margin-left: 2em; +    margin-right: 15mm; +  } +  p.center { +    text-align: center; +  } +  p.bold { +    font-weight: bold; +  } +  p.bold_left { +    font-weight: bold; +    text-align: left; +  } +  p.centerbold { +    text-align: center; +    font-weight: bold; +  } +  p.em { +    font-weight: bold; +    font-style: normal; +    background: #fff3b6; +  } +  p.small { +    font-size: 80%; +    margin-top: 0px; +    margin-bottom: 0px; +    margin-right: 6px; +    text-align: left; +  } +  .tiny, .tiny_left, .tiny_right, .tiny_center { +    font-size: 10px; +    margin-top: 0px; +    margin-bottom: 0px; +    color: #777777; +    margin-right: 6px; +    text-align: left; +  } +  p.tiny { } +  p.tiny_left { +    margin-left: 0px; +    margin-right: 0px; +    text-align: left; +  } +  p.tiny_right { +    margin-right: 1em; +    text-align: right; +  } +  p.tiny_center { +    margin-left: 0px; +    margin-right: 0px; +    text-align: center; +  } +  p.concordance_word { +    line-height: 150%; +    font-weight: bold; +    display: inline; +    margin-top: 4px; +    margin-bottom: 1px; +  } +  p.concordance_count { +    font-size: 80%; +    color: #777777; +    display: inline; +    margin-left: 0em; +  } +  p.concordance_object { +    font-size: 80%; +    line-height: 120%; +    text-align: left; +    margin-left: 3em; +    margin-top: 1px; +    margin-bottom: 3px; +  } +  p.book_index_lev1 { +    line-height: 100%; +    margin-top: 4px; +    margin-bottom: 1px; +  } +  p.book_index_lev2 { +    line-height: 100%; +    text-align: left; +    margin-left: 3em; +    margin-top: 1px; +    margin-bottom: 3px; +  } +  tt { +    font-family: inconsolata, andale mono, courier new, courier, monospace; +    background-color: #eeeeee; +  } +  /* indent */ +  p.norm { } +  p.i1 { padding-left: 1em; } +  p.i2 { padding-left: 2em; } +  p.i3 { padding-left: 3em; } +  p.i4 { padding-left: 4em; } +  p.i5 { padding-left: 5em; } +  p.i6 { padding-left: 6em; } +  p.i7 { padding-left: 7em; } +  p.i8 { padding-left: 8em; } +  p.i9 { padding-left: 9em; } +  /* hanging indent */ +  p[indent=\"h0i0\"] { +    padding-left: 0em; +    text-indent:  0em; +  } +  p[indent=\"h0i1\"] { +    padding-left: 1em; +    text-indent: -1em; +  } +  p[indent=\"h0i2\"] { +    padding-left: 2em; +    text-indent: -2em; +  } +  p[indent=\"h0i3\"] { +    padding-left: 3em; +    text-indent: -3em; +  } +  p[indent=\"h0i4\"] { +    padding-left: 4em; +    text-indent: -4em; +  } +  p[indent=\"h0i5\"] { +    padding-left: 5em; +    text-indent: -5em; +  } +  p[indent=\"h0i6\"] { +    padding-left: 6em; +    text-indent: -6em; +  } +  p[indent=\"h0i7\"] { +    padding-left: 7em; +    text-indent: -7em; +  } +  p[indent=\"h0i8\"] { +    padding-left: 8em; +    text-indent: -8em; +  } +  p[indent=\"h0i9\"] { +    padding-left: 9em; +    text-indent: -9em; +  } +  p[indent=\"h1i0\"] { +    padding-left: 0em; +    text-indent:  1em; +  } +  p[indent=\"h1i1\"] { +    padding-left: 1em; +    text-indent:  0em; +  } +  p[indent=\"h1i2\"] { +    padding-left: 2em; +    text-indent: -1em; +  } +  p[indent=\"h1i3\"] { +    padding-left: 3em; +    text-indent: -2em; +  } +  p[indent=\"h1i4\"] { +    padding-left: 4em; +    text-indent: -3em; +  } +  p[indent=\"h1i5\"] { +    padding-left: 5em; +    text-indent: -4em; +  } +  p[indent=\"h1i6\"] { +    padding-left: 6em; +    text-indent: -5em; +  } +  p[indent=\"h1i7\"] { +    padding-left: 7em; +    text-indent: -6em; +  } +  p[indent=\"h1i8\"] { +    padding-left: 8em; +    text-indent: -7em; +  } +  p[indent=\"h1i9\"] { +    padding-left: 9em; +    text-indent: -8em; +  } +  p[indent=\"h2i0\"] { +    padding-left: 0em; +    text-indent:  2em; +  } +  p[indent=\"h2i1\"] { +    padding-left: 1em; +    text-indent:  1em; +  } +  p[indent=\"h2i2\"] { +    padding-left: 2em; +    text-indent:  0em; +  } +  p[indent=\"h2i3\"] { +    padding-left: 3em; +    text-indent: -1em; +  } +  p[indent=\"h2i4\"] { +    padding-left: 4em; +    text-indent: -2em; +  } +  p[indent=\"h2i5\"] { +    padding-left: 5em; +    text-indent: -3em; +  } +  p[indent=\"h2i6\"] { +    padding-left: 6em; +    text-indent: -4em; +  } +  p[indent=\"h2i7\"] { +    padding-left: 7em; +    text-indent: -5em; +  } +  p[indent=\"h2i8\"] { +    padding-left: 8em; +    text-indent: -6em; +  } +  p[indent=\"h2i9\"] { +    padding-left: 9em; +    text-indent: -7em; +  } +  p[indent=\"h3i0\"] { +    padding-left: 0em; +    text-indent:  3em; +  } +  p[indent=\"h3i1\"] { +    padding-left: 1em; +    text-indent:  2em; +  } +  p[indent=\"h3i2\"] { +    padding-left: 2em; +    text-indent:  1em; +  } +  p[indent=\"h3i3\"] { +    padding-left: 3em; +    text-indent:  0em; +  } +  p[indent=\"h3i4\"] { +    padding-left: 4em; +    text-indent: -1em; +  } +  p[indent=\"h3i5\"] { +    padding-left: 5em; +    text-indent: -2em; +  } +  p[indent=\"h3i6\"] { +    padding-left: 6em; +    text-indent: -3em; +  } +  p[indent=\"h3i7\"] { +    padding-left: 7em; +    text-indent: -4em; +  } +  p[indent=\"h3i8\"] { +    padding-left: 8em; +    text-indent: -5em; +  } +  p[indent=\"h3i9\"] { +    padding-left: 9em; +    text-indent: -6em; +  } +  p[indent=\"h4i0\"] { +    padding-left: 0em; +    text-indent:  4em; +  } +  p[indent=\"h4i1\"] { +    padding-left: 1em; +    text-indent:  3em; +  } +  p[indent=\"h4i2\"] { +    padding-left: 2em; +    text-indent:  2em; +  } +  p[indent=\"h4i3\"] { +    padding-left: 3em; +    text-indent:  1em; +  } +  p[indent=\"h4i4\"] { +    padding-left: 4em; +    text-indent:  0em; +  } +  p[indent=\"h4i5\"] { +    padding-left: 5em; +    text-indent: -1em; +  } +  p[indent=\"h4i6\"] { +    padding-left: 6em; +    text-indent: -2em; +  } +  p[indent=\"h4i7\"] { +    padding-left: 7em; +    text-indent: -3em; +  } +  p[indent=\"h4i8\"] { +    padding-left: 8em; +    text-indent: -4em; +  } +  p[indent=\"h4i9\"] { +    padding-left: 9em; +    text-indent: -5em; +  } +  p[indent=\"h5i0\"] { +    padding-left: 0em; +    text-indent:  5em; +  } +  p[indent=\"h5i1\"] { +    padding-left: 1em; +    text-indent:  4em; +  } +  p[indent=\"h5i2\"] { +    padding-left: 2em; +    text-indent:  3em; +  } +  p[indent=\"h5i3\"] { +    padding-left: 3em; +    text-indent:  2em; +  } +  p[indent=\"h5i4\"] { +    padding-left: 4em; +    text-indent:  1em; +  } +  p[indent=\"h5i5\"] { +    padding-left: 5em; +    text-indent:  0em; +  } +  p[indent=\"h5i6\"] { +    padding-left: 6em; +    text-indent: -1em; +  } +  p[indent=\"h5i7\"] { +    padding-left: 7em; +    text-indent: -2em; +  } +  p[indent=\"h5i8\"] { +    padding-left: 8em; +    text-indent: -3em; +  } +  p[indent=\"h5i9\"] { +    padding-left: 9em; +    text-indent: -4em; +  } +  p[indent=\"h6i0\"] { +    padding-left: 0em; +    text-indent:  6em; +  } +  p[indent=\"h6i1\"] { +    padding-left: 1em; +    text-indent:  5em; +  } +  p[indent=\"h6i2\"] { +    padding-left: 2em; +    text-indent:  4em; +  } +  p[indent=\"h6i3\"] { +    padding-left: 3em; +    text-indent:  3em; +  } +  p[indent=\"h6i4\"] { +    padding-left: 4em; +    text-indent:  2em; +  } +  p[indent=\"h6i5\"] { +    padding-left: 5em; +    text-indent:  1em; +  } +  p[indent=\"h6i6\"] { +    padding-left: 6em; +    text-indent:  0em; +  } +  p[indent=\"h6i7\"] { +    padding-left: 7em; +    text-indent: -1em; +  } +  p[indent=\"h6i8\"] { +    padding-left: 8em; +    text-indent: -2em; +  } +  p[indent=\"h6i9\"] { +    padding-left: 9em; +    text-indent: -3em; +  } +  p[indent=\"h7i0\"] { +    padding-left: 0em; +    text-indent:  7em; +  } +  p[indent=\"h7i1\"] { +    padding-left: 1em; +    text-indent:  6em; +  } +  p[indent=\"h7i2\"] { +    padding-left: 2em; +    text-indent:  5em; +  } +  p[indent=\"h7i3\"] { +    padding-left: 3em; +    text-indent:  4em; +  } +  p[indent=\"h7i4\"] { +    padding-left: 4em; +    text-indent:  3em; +  } +  p[indent=\"h7i5\"] { +    padding-left: 5em; +    text-indent:  2em; +  } +  p[indent=\"h7i6\"] { +    padding-left: 6em; +    text-indent:  1em; +  } +  p[indent=\"h7i7\"] { +    padding-left: 7em; +    text-indent:  0em; +  } +  p[indent=\"h7i8\"] { +    padding-left: 8em; +    text-indent: -1em; +  } +  p[indent=\"h7i9\"] { +    padding-left: 9em; +    text-indent: -2em; +  } +  p[indent=\"h8i0\"] { +    padding-left: 0em; +    text-indent:  8em; +  } +  p[indent=\"h8i1\"] { +    padding-left: 1em; +    text-indent:  7em; +  } +  p[indent=\"h8i2\"] { +    padding-left: 2em; +    text-indent:  6em; +  } +  p[indent=\"h8i3\"] { +    padding-left: 3em; +    text-indent:  5em; +  } +  p[indent=\"h8i4\"] { +    padding-left: 4em; +    text-indent:  4em; +  } +  p[indent=\"h8i5\"] { +    padding-left: 5em; +    text-indent:  3em; +  } +  p[indent=\"h8i6\"] { +    padding-left: 6em; +    text-indent:  2em; +  } +  p[indent=\"h8i7\"] { +    padding-left: 7em; +    text-indent:  1em; +  } +  p[indent=\"h8i8\"] { +    padding-left: 8em; +    text-indent:  0em; +  } +  p[indent=\"h8i9\"] { +    padding-left: 9em; +    text-indent: -1em; +  } +  p[indent=\"h9i0\"] { +    padding-left: 0em; +    text-indent:  9em; +  } +  p[indent=\"h9i1\"] { +    padding-left: 1em; +    text-indent:  8em; +  } +  p[indent=\"h9i2\"] { +    padding-left: 2em; +    text-indent:  7em; +  } +  p[indent=\"h9i3\"] { +    padding-left: 3em; +    text-indent:  6em; +  } +  p[indent=\"h9i4\"] { +    padding-left: 4em; +    text-indent:  5em; +  } +  p[indent=\"h9i5\"] { +    padding-left: 5em; +    text-indent:  4em; +  } +  p[indent=\"h9i6\"] { +    padding-left: 6em; +    text-indent:  3em; +  } +  p[indent=\"h9i7\"] { +    padding-left: 7em; +    text-indent:  2em; +  } +  p[indent=\"h9i8\"] { +    padding-left: 8em; +    text-indent:  1em; +  } +  p[indent=\"h9i9\"] { +    padding-left: 9em; +    text-indent:  0em; +  } +  note { white-space: pre; } +  label.ocn { +    width: 2%; +    float: right; +    top: 0; +    font-size: 10px; +    margin-top: 0px; +    margin-bottom: 5px; +    color: #777777; +    margin-right: 5px; +    text-align: right; +    background-color: #ffffff; +  } +  table { } +  tr { } +  th,td { +    vertical-align: top; +    text-align: left; +  } +  th { +    font-weight: bold; +  } +  em { +    font-weight: bold; +    font-style: italic; +  } +  p.left,th.left,td.left { +    text-align: left; +  } +  p.small_left,th.small_left,td.small_left { +    text-align: left; +    font-size: 80%; +  } +  p.right,th.right,td.right { +    text-align: right; +  } +  ul, li { +    list-style-type: none; +    list-style: none; +    padding-left: 20px; +    display: block; +    font-family: verdana, arial, georgia, tahoma, sans-serif, helvetica, times, roman; +    font-weight: normal; +    line-height: 150%; +    text-align: left; +    text-indent: 0mm; +    margin-left: 1em; +    margin-right: 2em; +    margin-top: 3px; +    margin-bottom: 3px; +  } +  li { +    background: url(../image_sys/bullet_09.png) no-repeat 0px 6px; +  } +  ul { +  } +  h0, h1, h2, h3, h4, h5, h6, h7 { +    font-weight: bold; +    line-height: 120%; +    text-align: left; +    margin-top: 20px; +    margin-bottom: 10px; +  } +  h4.norm, h5.norm, h6.norm, h7.norm { +    margin-top: 10px; +    margin-bottom: 0px; +  } +  h0 { font-size: 125%; } +  h1 { font-size: 120%; } +  h2 { font-size: 115%; } +  h3 { font-size: 110%; } +  h4 { font-size: 105%; } +  h5 { font-size: 100%; } +  h6 { font-size: 100%; } +  h7 { font-size: 100%; } +  h0, h1, h2, h3, h4, h5, h6, h7 { text-shadow: .2em .2em .3em gray; } +  h1.i { margin-left: 2em; } +  h2.i { margin-left: 3em; } +  h3.i { margin-left: 4em; } +  h4.i { margin-left: 5em; } +  h5.i { margin-left: 6em; } +  h6.i { margin-left: 7em; } +  h7.i { margin-left: 8em; } +  h8.i { margin-left: 9em; } +  h9.i { margin-left: 10em; } +  .toc { +    font-weight: normal; +    margin-top: 6px; +    margin-bottom: 6px; +  } +  h0.toc { +    margin-left: 1em; +    font-size: 120%; +    line-height: 150%; +  } +  h1.toc { +    margin-left: 1em; +    font-size: 115%; +    line-height: 150%; +  } +  h2.toc { +    margin-left: 2em; +    font-size: 110%; +    line-height: 140%; +  } +  h3.toc { +    margin-left: 3em; +    font-size: 105%; +    line-height: 120%; +  } +  h4.toc { +    margin-left: 4em; +    font-size: 100%; +    line-height: 120%; +  } +  h5.toc { +    margin-left: 5em; +    font-size: 95%; +    line-height: 110%; +  } +  h6.toc { +    margin-left: 6em; +    font-size: 90%; +    line-height: 110%; +  } +  h7.toc { +    margin-left: 7em; +    font-size: 85%; +    line-height: 100%; +  } +  .subtoc { +    margin-right: 34%; +    font-weight: normal; +  } +  h5.subtoc { +    margin-left: 2em; +    font-size: 80%; +    margin-top: 2px; +    margin-bottom: 2px; +  } +  h6.subtoc { +    margin-left: 3em; +    font-size: 75%; +    margin-top: 0px; +    margin-bottom: 0px; +  } +  h7.subtoc { +    margin-left: 4em; +    font-size: 70%; +    margin-top: 0px; +    margin-bottom: 0px; +  } + +"; +    struct _css { +      auto html_seg_css() { +        string _css = "/* SiSU css html seg stylesheet */\n" ~ _css_html_seg; +        return _css; +      } +      auto html_scroll_css() { +        string _css = "/* SiSU css html scroll stylesheet */\n" ~ _css_html_scroll; +        return _css; +      } +      auto epub_css() { +        string _css = "/* SiSU css epub stylesheet */\n" ~ _css_epub; +        return _css; +      } +    } +    return _css(); +  } +} diff --git a/src/doc_reform/share/defaults.d b/src/doc_reform/share/defaults.d new file mode 100644 index 0000000..ee0dbcb --- /dev/null +++ b/src/doc_reform/share/defaults.d @@ -0,0 +1,22 @@ +/++ +  shared default settings ++/ +module doc_reform.share.defaults; +template Msg() { +  import std.stdio; +  auto Msg(I)(I doc_matters) { +    struct Msg_ { +      void v()(string message) { +        if (!(doc_matters.opt.action.quiet) && doc_matters.opt.action.verbose) { +          writeln(message); +        } +      } +      void vv()(string message) { +        if (!(doc_matters.opt.action.quiet) && doc_matters.opt.action.very_verbose) { +          writeln(message); +        } +      } +    } +    return Msg_(); +  } +} diff --git a/src/doc_reform/source/paths_source.d b/src/doc_reform/source/paths_source.d new file mode 100644 index 0000000..dc2928f --- /dev/null +++ b/src/doc_reform/source/paths_source.d @@ -0,0 +1,787 @@ +/++ +  read configuration files<BR> +  - read config files<BR> +  meta_config_files.d ++/ +module doc_reform.source.paths_source; +import std.array, +  std.file, +  std.path, +  std.regex, +  std.stdio, +  std.conv : to; +import doc_reform.meta.rgx; +template PodManifest() { +  mixin SiSUrgxInit; +  static auto rgx = Rgx(); +  auto PodManifest(P)( +    P   _pth +  ) { +    struct ManifestFile_ { +      string pod_manifest_filename() { +        return "sisupod.manifest"; +      } +      string pod_manifest_path() { +        string _manifest_path; +        if ((isValidPath(_pth) && exists(_pth)!=0 && _pth.isDir) +        && (exists(_pth.chainPath(pod_manifest_filename).array)!=0 +        && (_pth.chainPath(pod_manifest_filename).array).isFile)) { +          _manifest_path = _pth; +        } else if (_pth.match(rgx.src_pth_contents) +        && exists(_pth)!=0 && _pth.isFile) { +          _manifest_path = _pth.dirName; +        } else if (_pth.match(rgx.src_pth_pod_sst_or_ssm) +        && exists(_pth)!=0 && (_pth.isFile)) { +          if (auto m = _pth.match(rgx.src_pth_pod_sst_or_ssm)) { +            _manifest_path = m.captures["podpath"]; +          } +        } else  { +          writeln("WARNING, issue with manifest_path: ", _pth); // remove? +          _manifest_path = null; // _manifest_path = ""; +        } +        return _manifest_path; +      } +      string pod_manifest_file_with_path() { +        string _k; +        if  (exists(pod_manifest_path.chainPath(pod_manifest_filename).array)!=0) { +          _k = pod_manifest_path.chainPath(pod_manifest_filename).array; +        } else if (exists(pod_manifest_path)!=0) { +          _k = pod_manifest_path; +        } +        if (exists(_k)==0) { +          writeln("ERROR >> Processing Skipped! Manifest not found: ", _k); +          _k = null; +        } +        return _k; +      } +    } +    return ManifestFile_(); +  } +} +template PathMatters() { +  mixin SiSUrgxInit; +  static auto rgx = Rgx(); +  auto PathMatters(O,E)( +    O        _opt_actions, +    E        _env, +    string   _pth, +    string   _fns              = "", +    char[][] _manifest_fn_list = [[]], +  ) { +    auto _manifest = PodManifest!()(_pth); +    struct ManifestMatters_ { +      auto env() { +        auto _env = _env; +        struct Env_ { +          auto pwd() { +            return _env["pwd"]; +          } +          auto home() { +            return _env["home"]; +          } +        } +        return Env_(); +      } +      auto opt() { +        auto _opt_actions = _opt_actions; +        struct Opt_ { +          auto action() { // redundant +            return _opt_actions; +          } +        } +        return Opt_(); +      } +      bool src_is_pod() { +        return (_manifest.pod_manifest_path.length > 0) ? true : false; +      } +      auto pod() { +        struct Pod_ { +          bool src_is_pod() { +            return (_manifest.pod_manifest_path.length > 0) ? true : false; +          } +          auto collection_root() { +            auto _collection_root = asNormalizedPath(chainPath(_manifest.pod_manifest_path, "..")).array; +            if (auto m = (_collection_root).match(rgx.src_pth_pod_root)) { +            // consider testing for last dir in path name being sisupod, and giving warning if not +            } else { +              writeln("WARNING, collection_root not named \"sisupod\""); +            } +            return _collection_root; +          } +          string manifest_filename() { +            return _manifest.pod_manifest_filename; +          } +          string manifest_path() { +            return _manifest.pod_manifest_path; +          } +          string pod_name() { +            return _manifest.pod_manifest_path.baseName; +          } +          string manifest_file_with_path() { +            return _manifest.pod_manifest_file_with_path; +          } +          string[] config_sisu_document_make_dirs() { +            string[] _config_dirs; +            return _config_dirs; +          } +          string[] config_local_site_dirs() { +            string[] _config_dirs; +            return _config_dirs; +          } +          string[] image_dirs() { +            string[] _image_dirs; +            return _image_dirs; +          } +          auto manifest_list_of_filenames() { +            return _manifest_fn_list; +          } +          string[] manifest_list_of_languages() { +            string[] _lngs; +            foreach (filename_; manifest_list_of_filenames) { +              string _k = "en"; +              if (auto m = (filename_).match(rgx.language_code_and_filename)) { +                _k = m.captures[1].to!string; +              } +              _lngs ~= _k; // all the languages from the manifest list of filenames with paths +            } +            return _lngs; +          } +        } +        return Pod_(); +      } +      auto src() { +        string _fns = _fns; // required here by dmd & not by ldc (for D:2078) +        auto _opt_actions = _opt_actions; +        auto _env = _env; +        string _sep = "␣"; +        struct SRC_ { +          bool is_pod() { +            return (_manifest.pod_manifest_path.length > 0) ? true : false; +          } +          string path_and_fn() { +            return _fns; +          } +          string pod_name() { +            return (is_pod) ? _manifest.pod_manifest_path : ""; +          } +          string filename() { +            return path_and_fn.baseName; +          } +          string filename_base() { +            return filename.stripExtension; +          } +          string filename_extension() { +            return filename.match(rgx.src_pth_sst_or_ssm).captures["extension"]; +          } +          string lng() { +            string _k; +            if (auto m = path_and_fn.match(rgx.language_code_and_filename)) { +              _k = m.captures[1]; +            } else {_k = "en"; } +            return _k; +          } +          string doc_uid() { +            string _uid; +            if (is_pod && !(pod_name.empty)) { +              if (pod_name.baseName == filename_base) { +                _uid = filename_base ~ "." ~ filename_extension ~ _sep ~ lng; +              } else { +                _uid = pod_name.baseName ~ _sep ~ filename_base ~ "." ~ filename_extension ~ _sep ~ lng; +              } +            } else { +              _uid = _sep ~ filename_base ~ "." ~ filename_extension ~ _sep ~ lng; +            } +            return _uid; +          } +          string docname_composite_unique_per_src_doc() { +          /+ +            z pod name if any + src filename + lng code +             filename ~ "." ~  lng +             * unique per src doc +             used by +             - sqlite discrete index (multilingual, each language of a document) +          +/ +            string _fn; +            if (pod_name.baseName == filename_base) { +              _fn = filename_base ~ _sep ~ filename_extension ~ _sep ~ lng; +            } else if (!(pod_name.empty)) { +              _fn = pod_name.baseName ~ _sep ~ filename_base ~ _sep ~ filename_extension ~ _sep ~ lng; +            } else { +              _fn = "_" ~ _sep ~ filename_base ~ _sep ~ filename_extension ~ _sep ~ lng; +            } +            return _fn; +          } +          string docname_composite_unique_per_src_pod() { +          /+ +            z pod name if any + src filename (without lng code) +             filename ~ _sep ~ lng +             * unique per src pod +             used by +             - sisupod (multilingual collection) +             - sqlite discrete index (multilingual collection) +          +/ +            string _fn; +            if (pod_name.baseName == filename_base) { +              _fn = filename_base ~ _sep ~ filename_extension; +            } else if (!(pod_name.empty)) { +              _fn = pod_name.baseName ~ _sep ~ filename_base ~ _sep ~ filename_extension; +            } else { +              _fn = "_" ~ _sep ~ filename_base ~ _sep ~ filename_extension; +            } +            return _fn; +          } +          string language() { +            return lng(); +          } +          string file_with_absolute_path() { +            return _env["pwd"].chainPath(path_and_fn).array; +          } +          string absolute_path_to_src() { +            return (_env["pwd"].chainPath(path_and_fn)).dirName.array; +          } +          string base_dir() { +            string _dir; +            if ( +              auto m = (absolute_path_to_src) +              .match(regex(r"[/](?P<dir>(?:[a-zA-Z0-9._-]+))/sisupod/" ~ filename.stripExtension)) +            ) { +              _dir = asNormalizedPath(path_and_fn.chainPath("../../")).array; +              assert(_dir == m.captures["dir"]); +            } else { +              _dir = asNormalizedPath(path_and_fn.chainPath("../../../")).array; +              assert(_dir == absolute_path_to_src +                .match(rgx.src_base_parent_dir_name).captures["dir"]); +            } +            if ((_opt_actions.debug_do)) { +              writeln("--> (base_dir)  ", _dir); +            } +            return _dir; +          } +          string base_parent_dir_path() { +            string _dir; +            if ( +              auto m = (absolute_path_to_src) +              .match(regex(r"[/](?P<dir>(?:[a-zA-Z0-9._-]+))/sisupod/" ~ filename.stripExtension)) +            ) { +              _dir = asNormalizedPath(path_and_fn.chainPath("../../")).array; +            } else { +              _dir = asNormalizedPath(path_and_fn.chainPath("../../../")).array; +            } +            return _dir; +          } +          string base_dir_path() { +            string _dir; +            if ( +              auto m = (absolute_path_to_src) +              .match(rgx.src_formalised_file_path_parts) +            ) { +              _dir = asNormalizedPath(m.captures["pth"]).array; +            } else if ( +             auto m = (absolute_path_to_src) +             .match(regex(r"[/](?P<dir>(?:[a-zA-Z0-9._-]+))/sisupod/" ~ filename.stripExtension)) +            ) { +              _dir = asNormalizedPath(path_and_fn.chainPath("../")).array; +            } else { +              _dir = asNormalizedPath(path_and_fn.chainPath("../../")).array; +            } +            if ((_opt_actions.debug_do)) { +              writeln("--> (base_dir_path) ", _dir); +            } +            return _dir; +          } +          string media_dir_path() { +            string _dir = asNormalizedPath(base_dir_path.chainPath("media")).array; +            return _dir; +          } +          string image_dir_path() { +            string _paths; +            string[] _possible_img_pths = [ "./image", "../image", "../../image" ]; +            string _img_pth_found = ""; +            if (is_pod) { +              _img_pth_found = asNormalizedPath(file_with_absolute_path.dirName ~ "/../../image").array; +            } else { +              string _img_pth(string _possible_img_pth) { +                return asNormalizedPath(file_with_absolute_path.dirName ~ "/" ~ _possible_img_pth).array; +              } +              foreach(_possible_img_pth; _possible_img_pths) { +                if (exists(_img_pth(_possible_img_pth))) { +                  _img_pth_found = _img_pth(_possible_img_pth); +                  break; +                } else { +                  _paths ~= " " ~ _img_pth(_possible_img_pth); +                } +              } +            } +            if (_img_pth_found.empty) { +              writeln("WARNING not image path found, searched: ", _paths); +            } +            return _img_pth_found; +          } +          auto conf_dir_path() { +            return asNormalizedPath(base_dir_path.chainPath("conf")).array; +          } +          auto base_parent_dir() { +            string _dir; +            if ( +              auto m = (absolute_path_to_src) +              .match(regex(r"[/](?P<dir>(?:[a-zA-Z0-9._-]+))/sisupod/" ~ filename.stripExtension)) +            ) { +              _dir = m.captures["dir"]; +            } else { +              _dir = (absolute_path_to_src).match(rgx.src_base_parent_dir_name).captures["dir"]; +            } +            if ((_opt_actions.debug_do)) { +              writeln("--> (base_parent_dir) ", _dir); +            } +            return _dir; +          } +          string[] config_dirs() { +            string[] _config_dirs; +            if (is_pod) { +            } else {} +            return _config_dirs; +          } +          string[] image_dirs() { +            string[] _image_dirs; +            if (is_pod) { +            } else {} +            return _image_dirs; +          } +        } +        return SRC_(); +      } +      auto output() { +        auto _opt_actions = _opt_actions; +        auto _env = _env; +        struct Out_ { +          auto path() { +            auto _output_path = _env["pwd"]; +            if ((_opt_actions.output_dir_set.length > 0) +              && isValidPath(_opt_actions.output_dir_set) +            ) { +              _output_path = asNormalizedPath(_opt_actions.output_dir_set).array; +              if (!exists(_output_path)) { +                try { +                  _output_path.mkdirRecurse; +                } +                // catch (ErrnoException ex) { +                catch (Exception ex) { +                  // Handle error +                } +              } +              assert(_output_path.isDir, +                "not a directory: " ~ _output_path); +              // TODO always test that is a directory and it is writable +            } +            return _output_path; +          } +        } +        return Out_(); +      } +    } +    return ManifestMatters_(); +  } +} +template ConfigFilePaths() { +  mixin SiSUrgxInit; +  static auto rgx = Rgx(); +  auto ConfigFilePaths(M,E)( +    M   _manifest, +    E   _env, +  ) { +    struct ConfFilePaths { +      string config_filename_document_toml() { +        return "sisu_document_make"; +      } +      string config_filename_site_toml() { +        return "config_local_site"; +      } +      auto possible_config_path_locations() { +        struct _ConfFilePaths { +          string[] sisu_document_make() { +            /+ FIX clean up conf paths ↓ +/ +            /+ config local site (file system only, not in pod) +/ +            /+ return paths +/ +            string[] _possible_config_path_locations; +            if (_manifest.src.is_pod) { +              /+ config document in pod +/ +              string _sisudoc_conf_pod; // +              string _sisudoc_conf_pod_text; // +              _sisudoc_conf_pod = asNormalizedPath(chainPath( +                to!string(_env["pwd"]), +                _manifest.pod.manifest_path ~ "/conf" +              )).array; +              _sisudoc_conf_pod_text = asNormalizedPath(chainPath( +                to!string(_env["pwd"]), +                _manifest.pod.manifest_path ~ "/media/text/" ~ _manifest.src.lng ~ "/conf" +              )).array; +              /+ return paths +/ +              _possible_config_path_locations = [ +                _sisudoc_conf_pod_text, +                _sisudoc_conf_pod, +              ]; +            } else { +              /+ config document (& or local site) on filesystem +/ +              string _sisudoc_conf_pwd   = asNormalizedPath(chainPath(to!string(_env["pwd"]), "sisudoc/conf")).array; // think about +              string _sisudoc_conf_pwd_a = asNormalizedPath(chainPath(to!string(_env["pwd"]), "conf")).array; +              string _sisudoc_conf_pwd_b = asNormalizedPath(chainPath(to!string(_env["pwd"]), "../conf")).array; +              string _sisudoc_conf_pwd_c = asNormalizedPath(chainPath(to!string(_env["pwd"]), "../../conf")).array; +              string _sisudoc_conf_pwd_d = asNormalizedPath(chainPath(to!string(_env["pwd"]), "../../../conf")).array; +              /+ return paths +/ +              _possible_config_path_locations = [ +                _sisudoc_conf_pwd, +                _sisudoc_conf_pwd_a, +                _sisudoc_conf_pwd_b, +                _sisudoc_conf_pwd_c, +                _sisudoc_conf_pwd_d, +              ]; +            } +            /+ FIX clean up conf paths ↑ +            (compare pwd to doc path location, and build config path) +            +/ +            return _possible_config_path_locations; +          } +          string[] config_local_site() { +            /+ FIX clean up conf paths ↓ +/ +            /+ config local site (file system only, not in pod) +/ +            string _dot_pwd        = asNormalizedPath(chainPath(to!string(_env["pwd"]), ".sisu")).array; +            string _underscore_pwd = asNormalizedPath(chainPath(to!string(_env["pwd"]), "_sisu")).array; +            string _dot_home       = asNormalizedPath(chainPath(to!string(_env["home"]), ".sisu")).array; +            /+ return paths +/ +            string[] _possible_config_path_locations; +            if (_manifest.src.is_pod) { +              string _collection_root_a = asNormalizedPath(chainPath(to!string(_manifest.pod.collection_root.to!string), ".sisu")).array; +              string _collection_root_b = asNormalizedPath(chainPath(to!string(_manifest.pod.collection_root.to!string), "_sisu")).array; +              _possible_config_path_locations = [ +                _dot_pwd, +                _underscore_pwd, +                _dot_home, +                "/etc/sisu", +                _collection_root_a, // set priority higher? +                _collection_root_b // set priority higher? +              ]; +            } else { +              /+ config document (& or local site) on filesystem +/ +              string _sisudoc_conf_pwd   = asNormalizedPath(chainPath(to!string(_env["pwd"]), "sisudoc/conf")).array; // think about +              string _sisudoc_conf_pwd_a = asNormalizedPath(chainPath(to!string(_env["pwd"]), "conf")).array; +              string _sisudoc_conf_pwd_b = asNormalizedPath(chainPath(to!string(_env["pwd"]), "../conf")).array; +              string _sisudoc_conf_pwd_c = asNormalizedPath(chainPath(to!string(_env["pwd"]), "../../conf")).array; +              string _sisudoc_conf_pwd_d = asNormalizedPath(chainPath(to!string(_env["pwd"]), "../../../conf")).array; +              _possible_config_path_locations = [ +                _sisudoc_conf_pwd, +                _sisudoc_conf_pwd_a, +                _sisudoc_conf_pwd_b, +                _sisudoc_conf_pwd_c, +                _sisudoc_conf_pwd_d, +                _dot_pwd, +                _underscore_pwd, +                _dot_home, +                "/etc/sisu" +              ]; +            } +            /+ FIX clean up conf paths ↑ +            (compare pwd to doc path location, and build config path) +            +/ +            return _possible_config_path_locations; +          } +        } +        return _ConfFilePaths(); +      } +    } +    return ConfFilePaths(); +  } +} +template SiSUpathsSRC() { +  mixin SiSUrgxInit; +  static auto rgx = Rgx(); +  auto SiSUpathsSRC(D,Fn)( +    D   _pwd, +    Fn  _fn_src_and_path, +  ) { +    struct SisuSrcPaths { +      auto pwd() { +        return _pwd; +      } +      string language() { +        // use command line info as well? +        string _k; +        if (auto m = _fn_src_and_path.match(rgx.language_code_and_filename)) { +          _k = m.captures[1]; +        } else { /+ unknown until doc_meta read, (could provide & use command line info?) +/ +          _k = "xx"; // original default was "en" but is not known +        } +        return _k; +      } +      string doc_root() { +        return "sisudoc"; +      } +      auto media_root() { +        return asNormalizedPath(doc_root.chainPath("media")).array; +      } +      auto conf_root() { +        return asNormalizedPath(doc_root.chainPath("conf")).array; +      } +      auto text_root() { +        return asNormalizedPath(media_root.chainPath("text")).array; +      } +      auto image_root() { +        return asNormalizedPath(media_root.chainPath("image")).array; +      } +      auto doc_src_fn_with_path_for_text_root_and_lng() { +        return asNormalizedPath(text_root.chainPath(language)).array; +      } +      auto doc_src_fn() { +        return asNormalizedPath(_fn_src_and_path.baseName).array; +      } +      auto doc_src_with_path() { +        return asNormalizedPath(pwd.chainPath(_fn_src_and_path)).array; +      } +    } +    return SisuSrcPaths(); +  } +} + + +template SiSUpathsSisupods() { +  mixin SiSUrgxInit; +  static auto rgx = Rgx(); +  string _suffix = ".zip"; +  auto SiSUpathsSisupods(Dm)(Dm doc_matters) { +    string _base_dir_pod = (doc_matters.output_path.length > 0) +    ? doc_matters.output_path ~ "/sisupod" +    : "/sisupod"; +    string _base_dir_doc = "sisudoc"; +    struct _PodPaths { +      string base_filename_(string fn_src) { +        auto pth = fn_src.baseName.stripExtension; +        return pth; +      } +      string sisupod_dir_() { +        auto pth = _base_dir_pod; +        return pth; +      } +      string sisudoc_dir_() { +        auto pth = _base_dir_doc; +        return pth; +      } +      string sisupod_filename_(string fn_src) { +        string pth = _base_dir_pod.chainPath(base_filename_(fn_src) ~ _suffix).array; +        return pth; +      } +      string base_filesystem_(string fn_src) { +        string pth = _base_dir_pod.chainPath(base_filename_(fn_src)).array; +        assert(pth == _base_dir_pod ~ "/"  ~ base_filename_(fn_src), +          pth ~ " == "  ~ _base_dir_pod ~ "/" ~ base_filename_(fn_src) ~ "?"); +        return pth; +      } +      string base_pod_(string fn_src) { +        string pth = _base_dir_pod.chainPath(base_filename_(fn_src)).array; // change this +        return pth; +      } +      auto base_filename(string fn_src) { +        auto pth_1_ = base_filename_(fn_src); +        auto pth_2_ = base_filename_(fn_src); +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto sisupod_filename(string fn_src) { +        auto pth_1_ = sisupod_filename_(fn_src); +        auto pth_2_ = sisupod_filename_(fn_src); +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto base(string fn_src) { +        auto pth_1_ = ""; +        auto pth_2_ = base_filesystem_(fn_src); +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto pod_root(string fn_src) { +        auto pth_1_ = ""; +        auto pth_2_ = asNormalizedPath(base(fn_src).filesystem_open_zpod.chainPath("")).array; // "sisudoc" +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto conf_root(string fn_src) { +        auto pod_root_ = pod_root(fn_src); +        auto pth_1_ = "conf"; +        auto pth_2_ = asNormalizedPath(pod_root(fn_src).filesystem_open_zpod.chainPath("conf")).array; +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_); +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto css(string fn_src) { +        auto pod_root_ = pod_root(fn_src); +        auto pth_1_ = asNormalizedPath(conf_root(fn_src).zpod.chainPath("css")).array; +        auto pth_2_ = asNormalizedPath(conf_root(fn_src).filesystem_open_zpod.chainPath("css")).array; +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_); +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto media_root(string fn_src) { +        auto pod_root_ = pod_root(fn_src); +        auto pth_1_ = "media"; +        auto pth_2_ = asNormalizedPath(pod_root(fn_src).filesystem_open_zpod.chainPath("media")).array; +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_); +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto text_root(string fn_src) { +        auto pod_root_ = pod_root(fn_src); +        auto pth_1_ = asNormalizedPath(media_root(fn_src).zpod.chainPath("text")).array; +        auto pth_2_ = asNormalizedPath(media_root(fn_src).filesystem_open_zpod.chainPath("text")).array; +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_); +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto doc(string fn_src) { +        auto pod_root_ = pod_root(fn_src); +        auto pth_1_ = text_root(fn_src).zpod; +        auto pth_2_ = text_root(fn_src).filesystem_open_zpod; +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_); +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto doc_lng(string fn_src, string lng) { +        auto pod_root_ = pod_root(fn_src); +        auto pth_1_ = asNormalizedPath(text_root(fn_src).zpod.chainPath(lng)).array; +        auto pth_2_ = asNormalizedPath(text_root(fn_src).filesystem_open_zpod.chainPath(lng)).array; +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_); +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto image_root(string fn_src) { +        auto pod_root_ = pod_root(fn_src); +        auto pth_1_ = asNormalizedPath(media_root(fn_src).zpod.chainPath("image")).array; +        auto pth_2_ = asNormalizedPath(media_root(fn_src).filesystem_open_zpod.chainPath("image")).array; +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_); +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto fn_pod_filelist(string fn_src) { +        auto pod_root_ = pod_root(fn_src); +        auto _manifest = PodManifest!()(fn_src).pod_manifest_filename; +        auto pth_1_ = _manifest; +        auto pth_2_ = asNormalizedPath(pod_root(fn_src).filesystem_open_zpod.chainPath(_manifest)).array; +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_); +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto fn_doc(string fn_src, string lng) { +        auto pod_root_ = pod_root(fn_src); +        auto pth_1_ = asNormalizedPath(doc_lng(fn_src, lng).zpod.chainPath(fn_src.baseName)).array; +        auto pth_2_ = asNormalizedPath(doc_lng(fn_src, lng).filesystem_open_zpod.chainPath(fn_src.baseName)).array; +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_); +            return pth_2_; +          } +        } +        return _pods(); +      } +      auto fn_doc_insert(string fn_src, string fn_insert, string lng) { +        auto pod_root_ = pod_root(fn_src); +        auto pth_1_ = asNormalizedPath(doc_lng(fn_src, lng).zpod.chainPath(fn_insert.baseName)).array; +        auto pth_2_ = asNormalizedPath(doc_lng(fn_src, lng).filesystem_open_zpod.chainPath(fn_insert.baseName)).array; +        struct _pods { +          auto zpod() { +            return pth_1_; +          } +          auto filesystem_open_zpod() { +            assert(pod_root_.filesystem_open_zpod.chainPath(zpod).array == pth_2_); +            return pth_2_; +          } +        } +        return _pods(); +      } +    } +    return _PodPaths(); +  } +} diff --git a/src/doc_reform/source/read_config_files.d b/src/doc_reform/source/read_config_files.d new file mode 100644 index 0000000..fc5ce2f --- /dev/null +++ b/src/doc_reform/source/read_config_files.d @@ -0,0 +1,218 @@ +/++ +  read configuration files<BR> +  - read config files<BR> +  meta_config_files.d ++/ +module doc_reform.source.read_config_files; +static template configReadInSiteTOML() { +  import +    doc_reform.meta, +    doc_reform.source.paths_source, +    std.file, +    std.path; +  final string configReadInSiteTOML(M,E)(M manifest, E env) { +    auto conf_file_details = ConfigFilePaths!()(manifest, env); +    string conf_toml = conf_file_details.config_filename_site_toml; +    auto possible_config_path_locations = conf_file_details.possible_config_path_locations.config_local_site; +    string config_file_str; +    debug(io) { +      writeln("WARNING (io debug) in config filename: ", conf_toml); +      writeln("WARNING (io debug) in config possible path locations: ", possible_config_path_locations); +    } +    foreach(pth; possible_config_path_locations) { +      auto conf_file = asNormalizedPath(chainPath(pth.to!string, conf_toml)).array; +      if (config_file_str.length > 0) { +        break; +      } +      try { +        if (exists(conf_file)) { +          debug(io) { +            writeln("WARNING (io debug) in config file found: ", conf_file); +          } +          config_file_str = conf_file.readText; +          break; +        } +      } catch (ErrnoException ex) { +      } catch (FileException ex) { +      } +    } +    return config_file_str; +  } +} +static template configReadInDocTOML() { +  import +    doc_reform.meta, +    doc_reform.source.paths_source, +    std.file, +    std.path; +  final string configReadInDocTOML(M,E)(M manifest, E env) { +    auto conf_file_details = ConfigFilePaths!()(manifest, env); +    string conf_toml = conf_file_details.config_filename_document_toml; +    auto possible_config_path_locations = conf_file_details.possible_config_path_locations.sisu_document_make; +    string config_file_str; +    debug(io) { +      writeln("WARNING (io debug) in config filename: ", conf_toml); +      writeln("WARNING (io debug) in config possible path locations: ", possible_config_path_locations); +    } +    foreach(pth; possible_config_path_locations) { +      auto conf_file = asNormalizedPath(chainPath(pth.to!string, conf_toml)).array; +      if (config_file_str.length > 0) { +        break; +      } +      try { +        if (exists(conf_file)) { +          debug(io) { +            writeln("WARNING (io debug) in config file found: ", conf_file); +          } +          config_file_str = conf_file.readText; +          break; +        } +      } catch (ErrnoException ex) { +      } catch (FileException ex) { +      } +    } +    return config_file_str; +  } +} +static template configTOML() { +  import toml; // +  import +    doc_reform.meta, +    doc_reform.source.paths_source, +    std.file, +    std.path; +  auto configTOML(string configuration, string conf_toml_filename) { +    TOMLDocument _toml_conf; +    try { +      _toml_conf = parseTOML(configuration); // parseTOML(cast(string)(configuration)); +    } catch(ErrnoException e) { +      stderr.writeln("Toml problem with content for ", conf_toml_filename); +      stderr.writeln(e.msg); +    } +    return _toml_conf; +  } +} +static template readConfigSite() { +  import +    doc_reform.meta, +    doc_reform.source.paths_source, +    std.file, +    std.path; +  final auto readConfigSite(M,E)(M _manifest, E _env) { +    string config_file_str; +    string conf_filename = "NONE"; +    auto _conf_file_details = ConfigFilePaths!()(_manifest, _env); +    auto possible_config_path_locations = _conf_file_details.possible_config_path_locations.config_local_site; +    foreach(conf_fn; [_conf_file_details.config_filename_site_toml]) { +      foreach(pth; possible_config_path_locations) { +        auto conf_file = asNormalizedPath(chainPath(pth.to!string, conf_fn)).array; +        conf_filename = conf_fn; +        if (config_file_str.length > 0) { +          // conf_filename = conf_fn; +          break; +        } +        try { +          if (exists(conf_file)) { +            debug(io) { +              writeln("WARNING (io debug) in config file found: ", conf_file); +            } +            config_file_str = conf_file.readText; +            break; +          } +        } catch (ErrnoException ex) { +        } catch (FileException ex) { +        } +      } +      if (config_file_str.length > 0) { break; } +    } +    struct _ConfContent { +      string filename() { +        return conf_filename; +      } +      string filetype() { +        return conf_filename.extension.chompPrefix("."); +      } +      auto content() { +        return config_file_str; +      } +    } +    return _ConfContent(); +  } +} +static template readConfigDoc() { +  import +    doc_reform.meta, +    doc_reform.source.paths_source, +    std.file, +    std.path; +  final auto readConfigDoc(M,E)(M _manifest, E _env) { +    string config_file_str; +    string conf_filename = "NONE"; +    auto _conf_file_details = ConfigFilePaths!()(_manifest, _env); +    auto possible_config_path_locations = _conf_file_details.possible_config_path_locations.sisu_document_make; +    foreach(conf_fn; [_conf_file_details.config_filename_document_toml]) { +      foreach(pth; possible_config_path_locations) { +        auto conf_file = asNormalizedPath(chainPath(pth.to!string, conf_fn)).array; +        conf_filename = conf_fn; +        if (config_file_str.length > 0) { +          // conf_filename = conf_fn; +          break; +        } +        try { +          if (exists(conf_file)) { +            debug(io) { +              writeln("WARNING (io debug) in config file found: ", conf_file); +            } +            config_file_str = conf_file.readText; +            break; +          } +        } catch (ErrnoException ex) { +        } catch (FileException ex) { +        } +      } +      if (config_file_str.length > 0) { break; } +    } +    struct _ConfContent { +      string filename() { +        return conf_filename; +      } +      string filetype() { +        return conf_filename.extension.chompPrefix("."); +      } +      auto content() { +        return config_file_str; +      } +    } +    return _ConfContent(); +  } +} +static template configReadSiteTOML() { +  import +    doc_reform.meta, +    doc_reform.source.paths_source, +    std.file, +    std.path; +  import toml; +  final auto configReadSiteTOML(M,E)(M _manifest, E _env) { +    auto _configuration = configReadInSiteTOML!()(_manifest, _env); +    auto _conf_file_details = ConfigFilePaths!()(_manifest, _env); +    string _conf_toml = _conf_file_details.config_filename_site_toml; +    auto _toml_conf = configTOML!()(_configuration, _conf_toml); +    return _toml_conf; +  } +} +static template configReadDocTOML() { +  import +    doc_reform.meta, +    doc_reform.source.paths_source, +    std.file, +    std.path; +  import toml; +  final auto configReadDocTOML(M,E)(M _manifest, E _env) { +    auto _configuration = configReadInDocTOML!()(_manifest, _env); +    auto _conf_file_details = ConfigFilePaths!()(_manifest, _env); +    string _conf_toml = _conf_file_details.config_filename_document_toml; +    auto _toml_conf = configTOML!()(_configuration, _conf_toml); +    return _toml_conf; +  } +} diff --git a/src/doc_reform/source/read_source_files.d b/src/doc_reform/source/read_source_files.d new file mode 100644 index 0000000..294b081 --- /dev/null +++ b/src/doc_reform/source/read_source_files.d @@ -0,0 +1,350 @@ +/++ +  module source_read_source_files;<BR> +  - open markup files<BR> +  - if master file scan for addional files to import/insert ++/ +module doc_reform.source.read_source_files; +static template SiSUrawMarkupContent() { +  import +    doc_reform.meta.rgx; +  import +    doc_reform.meta, +    doc_reform.source.paths_source, +    std.file, +    std.path; +  mixin SiSUrgxInit; +  static auto rgx = Rgx(); +  string[] _images=[]; +  auto _extract_images(S)(S content_block) { +    string[] images_; +    auto _content_block = content_block.to!string; +    if (auto m = _content_block.matchAll(rgx.image)) { +      images_ ~= m.captures[1].to!string; +    } +    return images_; +  } +  auto rawsrc = RawMarkupContent(); +  auto SiSUrawMarkupContent(O,Fn)(O _opt_action, Fn fn_src) { +    auto _0_header_1_body_content_2_insert_filelist_tuple +      = rawsrc.sourceContentSplitIntoHeaderAndBody(_opt_action, rawsrc.sourceContent(fn_src), fn_src); +    return _0_header_1_body_content_2_insert_filelist_tuple; +  } +  struct RawMarkupContent { +    final sourceContent(in string fn_src) { +      auto raw = MarkupRawUnit(); +      auto source_txt_str +        = raw.markupSourceReadIn(fn_src); +      return source_txt_str; +    } +    final auto sourceContentSplitIntoHeaderAndBody(O)(O _opt_action, in string source_txt_str, in string fn_src="") { +      auto raw = MarkupRawUnit(); +      string[] insert_file_list; +      string[] images_list; +      auto t +        = raw.markupSourceHeaderContentRawLineTupleArray(source_txt_str); +      auto header_raw = t[0]; +      auto sourcefile_body_content = t[1]; +      if (fn_src.match(rgx.src_fn_master)) { // filename with path needed if master file (.ssm) not otherwise +        auto ins = Inserts(); +        auto tu +          = ins.scan_master_src_for_insert_files_and_import_content(_opt_action, sourcefile_body_content, fn_src); +        static assert(!isTypeTuple!(tu)); +        sourcefile_body_content = tu[0]; +        insert_file_list = tu[1].dup; +        images_list = tu[2].dup; +      } else if (_opt_action.source || _opt_action.sisupod) { +        auto ins = Inserts(); +        auto tu +          = ins.scan_master_src_for_insert_files_and_import_content(_opt_action, sourcefile_body_content, fn_src); +        static assert(!isTypeTuple!(tu)); +        images_list = tu[2].dup; +      } +      t = tuple( +        header_raw, +        sourcefile_body_content, +        insert_file_list, +        images_list +      ); +      static assert(t.length==4); +      return t; +    } +  } +  struct MarkupRawUnit { +    import std.file; +    final private string readInMarkupSource(in char[] fn_src) { +      enforce( +        exists(fn_src)!=0, +        "file not found: «" ~ +        fn_src ~ "»" +      ); +      string source_txt_str; +      try { +        if (exists(fn_src)) { +          debug(io) { +            writeln("in src, markup source file found: ", fn_src); +          } +          source_txt_str = fn_src.readText; +        } +      } catch (ErrnoException ex) { +      } catch (UTFException ex) { +        // Handle validation errors +      } catch (FileException ex) { +        // Handle errors +      } +      std.utf.validate(source_txt_str); +      return source_txt_str; +    } +    final private char[][] header0Content1(in string src_text) { +      /+ split string on _first_ match of "^:?A~\s" into [header, content] array/tuple +/ +      char[][] header_and_content; +      auto m = (cast(char[]) src_text).matchFirst(rgx.heading_a); +      header_and_content ~= m.pre; +      header_and_content ~= m.hit ~ m.post; +      assert(header_and_content.length == 2, +        "document markup is broken, header body split == " +        ~ header_and_content.length.to!string +        ~ "; (header / body array split should == 2 (split is on level A~))" +      ); +      return header_and_content; +    } +    final private char[][] markupSourceLineArray(in char[] src_text) { +      char[][] source_line_arr +        = (cast(char[]) src_text).split(rgx.newline_eol_strip_preceding); +      return source_line_arr; +    } +    auto markupSourceReadIn(in string fn_src) { +      static auto rgx = Rgx(); +      enforce( +        fn_src.match(rgx.src_pth_sst_or_ssm), +        "not a sisu markup filename: «" ~ +        fn_src ~ "»" +      ); +      auto source_txt_str = readInMarkupSource(fn_src); +      return source_txt_str; +    } +    auto markupSourceHeaderContentRawLineTupleArray(in string source_txt_str) { +      string[] file_insert_list = []; +      string[] images_list = []; +      auto hc = header0Content1(source_txt_str); +      auto header = hc[0]; +      char[] source_txt = hc[1]; +      auto source_line_arr = markupSourceLineArray(source_txt); +      auto t = tuple( +        header, +        source_line_arr, +        file_insert_list, +        images_list +      ); +      return t; +    } +    final char[][] getInsertMarkupSourceContentRawLineArray( +      in char[]    fn_src_insert, +      Regex!(char) rgx_file +    ) { +      enforce( +        fn_src_insert.match(rgx_file), +        "not a sisu markup filename: «" ~ +        fn_src_insert  ~ "»" +      ); +      auto source_txt_str = readInMarkupSource(fn_src_insert); +      auto source_line_arr = markupSourceLineArray(source_txt_str); +      return source_line_arr; +    } +  } +  struct Inserts { +    auto scan_subdoc_source(O)( +      O        _opt_action, +      char[][] markup_sourcefile_insert_content, +      string   fn_src +    ) { +      mixin SiSUrgxInitFlags; +      char[][] contents_insert; +      auto type1 = flags_type_init; +      auto fn_pth_full = fn_src.match(rgx.src_pth_sst_or_ssm); +      auto markup_src_file_path = fn_pth_full.captures[1]; +      foreach (line; markup_sourcefile_insert_content) { +        if (type1["curly_code"] == 1) { +          type1["header_make"] = 0; +          type1["header_meta"] = 0; +          if (line.matchFirst(rgx.block_curly_code_close)) { +            type1["curly_code"] = 0; +          } +          contents_insert ~= line; +        } else if (line.matchFirst(rgx.block_curly_code_open)) { +          type1["curly_code"] = 1; +          type1["header_make"] = 0; +          type1["header_meta"] = 0; +          contents_insert ~= line; +        } else if (type1["tic_code"] == 1) { +          type1["header_make"] = 0; +          type1["header_meta"] = 0; +          if (line.matchFirst(rgx.block_tic_close)) { +            type1["tic_code"] = 0; +          } +          contents_insert ~= line; +        } else if (line.matchFirst(rgx.block_tic_code_open)) { +          type1["tic_code"] = 1; +          type1["header_make"] = 0; +          type1["header_meta"] = 0; +          contents_insert ~= line; +        } else if ( +          (type1["header_make"] == 1) +          && line.matchFirst(rgx.native_header_sub) +        ) { +            type1["header_make"] = 1; +            type1["header_meta"] = 0; +        } else if ( +          (type1["header_meta"] == 1) +          && line.matchFirst(rgx.native_header_sub) +        ) { +            type1["header_meta"] = 1; +            type1["header_make"] = 0; +        } else if (auto m = line.match(rgx.insert_src_fn_ssi_or_sst)) { +          type1["header_make"] = 0; +          type1["header_meta"] = 0; +          auto insert_fn = m.captures[2]; +          auto insert_sub_pth = m.captures[1]; +          auto fn_src_insert +            = chainPath(markup_src_file_path, insert_sub_pth ~ insert_fn).array; +          auto raw = MarkupRawUnit(); +          auto markup_sourcesubfile_insert_content +            = raw.getInsertMarkupSourceContentRawLineArray(fn_src_insert, rgx.src_fn_find_inserts); +          debug(insert_file) { +            writeln(line); +            writeln(fn_src_insert); +            writeln( +              "  length contents insert array: ", +              markup_sourcesubfile_insert_content.length +            ); +          } +          if (_opt_action.source || _opt_action.sisupod) { +            _images ~= _extract_images(markup_sourcesubfile_insert_content); +          } +          auto ins = Inserts(); +          /+ +            - 1. load file +            - 2. read lines +            - 3. scan lines +              - a. if filename insert, and insert filename +                 - repeat 1 +              - b. else +                 - add line to new array; +                 - build image list, search for any image files to add to image list +          +/ +        } else { +          type1["header_make"] = 0; +          type1["header_meta"] = 0; +          contents_insert ~= line; // images to extract for image list? +          if (_opt_action.source || _opt_action.sisupod) { +            auto _image_linelist = _extract_images(line); +            if (_image_linelist.length > 0) { +              _images ~= _image_linelist; +            } +          } +        } +      } // end src subdoc (inserts) loop +      auto t = tuple( +        contents_insert, +        _images +      ); +      return t; +    } +    auto scan_master_src_for_insert_files_and_import_content(O)( +      O        _opt_action, +      char[][] sourcefile_body_content, +      string   fn_src +    ) { +      import std.algorithm; +      mixin SiSUrgxInitFlags; +      char[][] contents; +      auto type = flags_type_init; +      auto fn_pth_full = fn_src.match(rgx.src_pth_sst_or_ssm); +      auto markup_src_file_path = fn_pth_full.captures[1]; +      char[][] contents_insert; +      string[] _images =[]; +      string[] insert_file_list =[]; +      foreach (line; sourcefile_body_content) { +        if (type["curly_code"] == 1) { +          if (line.matchFirst(rgx.block_curly_code_close)) { +            type["curly_code"] = 0; +          } +          contents ~= line; +        } else if (line.matchFirst(rgx.block_curly_code_open)) { +          type["curly_code"] = 1; +          contents ~= line; +        } else if (type["tic_code"] == 1) { +          if (line.matchFirst(rgx.block_tic_close)) { +            type["tic_code"] = 0; +          } +          contents ~= line; +        } else if (line.matchFirst(rgx.block_tic_code_open)) { +          type["tic_code"] = 1; +          contents ~= line; +        } else if (auto m = line.match(rgx.insert_src_fn_ssi_or_sst)) { +          auto insert_fn = m.captures[2]; +          auto insert_sub_pth = m.captures[1]; +          auto fn_src_insert +            = chainPath(markup_src_file_path, insert_sub_pth ~ insert_fn).array; +            insert_file_list ~= fn_src_insert.to!string; +          auto raw = MarkupRawUnit(); +          /+ TODO +/ +          auto markup_sourcefile_insert_content +            = raw.getInsertMarkupSourceContentRawLineArray(fn_src_insert, rgx.src_fn_find_inserts); +          debug(insert_file) { +            writeln(line); +            writeln(fn_src_insert); +            writeln( +              "  length contents insert array: ", +              markup_sourcefile_insert_content.length +            ); +          } +          auto ins = Inserts(); +          auto contents_insert_tu = ins.scan_subdoc_source( +            _opt_action, +            markup_sourcefile_insert_content, +            fn_src_insert.to!string +          ); +          contents ~= contents_insert_tu[0]; // images to extract for image list? +          if (_opt_action.source || _opt_action.sisupod) { +            auto _image_linelist = _extract_images(contents_insert_tu[0]); +            if (_image_linelist.length > 0) { +              _images ~= _image_linelist; +            } +          } +          /+ +            - 1. load file +            - 2. read lines +            - 3. scan lines +              - a. if filename insert, and insert filename +                 - repeat 1 +              - b. else +                 - add line to new array; +                 - build image list, search for any image files to add to image list +          +/ +        } else { +          contents ~= line; +          if (_opt_action.source || _opt_action.sisupod) { +            auto _image_linelist = _extract_images(line); +            if (_image_linelist.length > 0) { +              _images ~= _image_linelist; +            } +          } +        } +      } // end src doc loop +      string[] images = []; +      foreach(i; uniq(_images.sort())) { +        images ~= i; +      } +      debug(insert_file) { +        writeln(__LINE__); +        writeln(contents.length); +      } +      auto t = tuple( +        contents, +        insert_file_list, +        images +      ); +      return t; +    } +  } +}  | 
