aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sisudoc/spine.d
diff options
context:
space:
mode:
Diffstat (limited to 'src/sisudoc/spine.d')
-rwxr-xr-xsrc/sisudoc/spine.d1272
1 files changed, 1272 insertions, 0 deletions
diff --git a/src/sisudoc/spine.d b/src/sisudoc/spine.d
new file mode 100755
index 0000000..b79bc54
--- /dev/null
+++ b/src/sisudoc/spine.d
@@ -0,0 +1,1272 @@
+#!/usr/bin/env rdmd
+/+
+- Name: SisuDoc Spine, Doc Reform [a part of]
+ - Description: documents, structuring, processing, publishing, search
+ - static content generator
+
+ - Author: Ralph Amissah
+ [ralph.amissah@gmail.com]
+
+ - Copyright: (C) 2015 - 2024 Ralph Amissah, All Rights Reserved.
+
+ - License: AGPL 3 or later:
+
+ Spine (SiSU), a framework for document structuring, publishing and
+ search
+
+ Copyright (C) Ralph Amissah
+
+ This program is free software: you can redistribute it and/or modify it
+ under the terms of the GNU AFERO General Public License as published by the
+ Free Software Foundation, either version 3 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see [https://www.gnu.org/licenses/].
+
+ If you have Internet connection, the latest version of the AGPL should be
+ available at these locations:
+ [https://www.fsf.org/licensing/licenses/agpl.html]
+ [https://www.gnu.org/licenses/agpl.html]
+
+ - Spine (by Doc Reform, related to SiSU) uses standard:
+ - docReform markup syntax
+ - standard SiSU markup syntax with modified headers and minor modifications
+ - docReform object numbering
+ - standard SiSU object citation numbering & system
+
+ - Homepages:
+ [https://www.sisudoc.org]
+ [https://www.doc-reform.org]
+
+ - Git
+ [https://git.sisudoc.org/]
+
++/
+module sisudoc.sisu_document_parser;
+/++
+name "spine"
+description "A SiSU inspired document parser written in D."
+homepage "https://sisudoc.org"
++/
+@safe:
+import
+ std.algorithm,
+ std.datetime,
+ std.getopt,
+ std.file,
+ std.path,
+ std.process;
+import
+ sisudoc.conf.compile_time_info,
+ sisudoc.meta,
+ sisudoc.meta.metadoc,
+ sisudoc.meta.metadoc_curate,
+ sisudoc.meta.metadoc_curate_authors,
+ sisudoc.meta.metadoc_curate_topics,
+ sisudoc.meta.metadoc_from_src,
+ sisudoc.meta.conf_make_meta_structs,
+ sisudoc.meta.conf_make_meta_json,
+ sisudoc.meta.defaults,
+ sisudoc.meta.doc_debugs,
+ sisudoc.meta.rgx,
+ sisudoc.meta.rgx_yaml,
+ sisudoc.meta.rgx_files,
+ sisudoc.io_in.paths_source,
+ sisudoc.io_in.read_config_files,
+ sisudoc.io_in.read_source_files,
+ sisudoc.io_out.hub;
+mixin(import("version.txt"));
+mixin(import("configuration.txt"));
+mixin CompileTimeInfo;
+string project_name = "spine";
+string program_name = "spine";
+@system void main(string[] args) {
+ mixin spineRgxIn;
+ mixin spineRgxYamlTags;
+ mixin spineRgxFiles;
+ mixin spineBiblio;
+ mixin outputHub;
+ auto hvst = spineCurateMetadata!();
+ string flag_action;
+ string arg_unrecognized;
+ enum dAM { abstraction, matters }
+ static auto rgx = RgxI();
+ static auto rgx_y = RgxYaml();
+ static auto rgx_files = RgxFiles();
+ scope(success) {
+ writefln(
+ "~ run complete, ok ~ (%s-%s.%s.%s, %s D:%s, %s %s)",
+ program_name,
+ _ver.major, _ver.minor, _ver.patch,
+ __VENDOR__, __VERSION__,
+ bits, os,
+ );
+ }
+ scope(failure) {
+ debug(checkdoc) {
+ stderr.writefln(
+ "run failure",
+ );
+ }
+ }
+ bool[string] opts = [
+ "abstraction" : false,
+ "allow-downloads" : false,
+ "assertions" : false,
+ "concordance" : false,
+ "dark" : false,
+ "debug" : false,
+ "debug-curate" : false,
+ "debug-curate-authors" : false,
+ "debug-curate-topics" : false,
+ "debug-epub" : false,
+ "debug-harvest" : false,
+ "debug-html" : false,
+ "debug-latex" : false,
+ "debug-manifest" : false,
+ "debug-metadata" : false,
+ "debug-pod" : false,
+ "debug-sqlite" : false,
+ "debug-stages" : false,
+ "digest" : false,
+ "epub" : false,
+ "generated-by" : false,
+ "curate" : false,
+ "curate-authors" : false,
+ "curate-topics" : false,
+ "html" : false,
+ "html-link-curate" : false,
+ "html-link-markup" : false,
+ "html-link-pdf" : false,
+ "html-link-pdf-a4" : false,
+ "html-link-pdf-letter" : false,
+ "html-link-search" : false,
+ "html-seg" : false,
+ "html-scroll" : false,
+ "latex" : false,
+ "latex-color-links" : false,
+ "latex-init" : false,
+ "latex-header-sty" : false,
+ "light" : false,
+ "manifest" : false,
+ "hide-ocn" : false,
+ "ocn-off" : false,
+ "odf" : false,
+ "odt" : false,
+ "parallel" : false,
+ "parallel-subprocesses" : false,
+ "pdf" : false,
+ "pdf-color-links" : false,
+ "pdf-init" : false,
+ "pod" : false,
+ "serial" : false,
+ "show-config" : false,
+ "show-curate" : false,
+ "show-curate-authors" : false,
+ "show-curate-topics" : false,
+ "show-epub" : false,
+ "show-html" : false,
+ "show-latex" : false,
+ "show-make" : false,
+ "show-manifest" : false,
+ "show-metadata" : false,
+ "show-pod" : false,
+ "show-sqlite" : false,
+ "show-summary" : 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,
+ "vox_is0" : false,
+ "vox_gt1" : false,
+ "vox_gt2" : 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,
+ "theme-dark" : false,
+ "theme-light" : false,
+ "workon" : false,
+ ];
+ string[string] settings = [
+ "output" : "",
+ "www-http" : "",
+ "www-host" : "",
+ "www-host-doc-root" : "",
+ "www-url-doc-root" : "",
+ "cgi-http" : "",
+ "cgi-host" : "",
+ "cgi-bin-root" : "",
+ "cgi-sqlite-search-filename" : "",
+ "cgi-url-root" : "",
+ "cgi-url-action" : "",
+ "cgi-search-title" : "",
+ "config" : "",
+ "lang" : "all",
+ "set-papersize" : "",
+ "set-textwrap" : "",
+ "set-digest" : "",
+ "sqlite-db-path" : "",
+ "sqlite-db-filename" : "",
+ ];
+ auto helpInfo = getopt(args,
+ std.getopt.config.passThrough,
+ "abstraction", "document abstraction", &opts["abstraction"],
+ "allow-downloads", "allow downloads (includes cgi.d from github)", &opts["allow-downloads"],
+ "assert", "set optional assertions on", &opts["assertions"],
+ "cgi-bin-root", "path to cgi-bin directory", &settings["cgi-bin-root"],
+ "cgi-url-root", "url to cgi-bin (to find cgi-bin)", &settings["cgi-url-root"],
+ "cgi-url-action", "url to post to cgi-bin search form", &settings["cgi-url-action"],
+ "cgi-search-title", "if generating a cgi search form the title to use for it", &settings["cgi-search-title"],
+ "cgi-sqlite-search-filename", "=[filename] default is spine-search", &settings["cgi-sqlite-search-filename"],
+ "concordance", "file for document", &opts["concordance"],
+ "curate", "extract info on authors & topics from document header metadata", &opts["curate"],
+ "curate-authors", "extract info on authors from document header metadata", &opts["curate-authors"],
+ "curate-topics", "extract info on topics from document header metadata", &opts["curate-topics"],
+ "dark", "alternative dark theme", &opts["dark"],
+ "digest", "hash digest for each object", &opts["digest"],
+ "epub", "process epub output", &opts["epub"],
+ "generated-by", "generated by headers (software version & time)", &opts["generated-by"],
+ "hide-ocn", "object cite numbers", &opts["hide-ocn"],
+ "html", "process html output", &opts["html"],
+ "html-link-curate", "place links back to curate in segmented html", &opts["html-link-curate"],
+ "html-link-markup", "provide html link to markup source, shared optionally", &opts["html-link-markup"],
+ "html-link-pdf", "provide html link to pdf a4 & letter output", &opts["html-link-pdf"],
+ "html-link-pdf-a4", "provide html link to pdf a4 output", &opts["html-link-pdf-a4"],
+ "html-link-pdf-letter", "provide html link to pdf letter size output", &opts["html-link-pdf-letter"],
+ "html-link-search", "html embedded search submission", &opts["html-link-search"],
+ "html-seg", "process html output", &opts["html-seg"],
+ "html-scroll", "process html output", &opts["html-scroll"],
+ "lang", "=[lang code e.g. =en or =en,es]", &settings["lang"],
+ "latex", "latex output (for pdfs)", &opts["latex"],
+ "latex-color-links", "mono or color links for pdfs", &opts["latex-color-links"],
+ "latex-init", "initialise latex shared files (see latex-header-sty)", &opts["latex-init"],
+ "latex-header-sty", "latex document header sty files", &opts["latex-header-sty"],
+ "light", "default light theme", &opts["light"],
+ "manifest", "process manifest output", &opts["manifest"],
+ "ocn-off", "object cite numbers", &opts["ocn-off"],
+ "odf", "open document format text (--odt)", &opts["odf"],
+ "odt", "open document format text", &opts["odt"],
+ "output", "=/path/to/output/dir specify where to place output", &settings["output"],
+ "parallel", "parallelisation", &opts["parallel"],
+ "parallel-subprocesses", "nested parallelisation", &opts["parallel-subprocesses"],
+ "pdf", "latex output for pdfs", &opts["pdf"],
+ "pdf-color-links", "mono or color links for pdfs", &opts["pdf-color-links"],
+ "pdf-init", "initialise latex shared files (see latex-header-sty)", &opts["pdf-init"],
+ "pod", "spine (doc reform) pod source content bundled", &opts["pod"],
+ "quiet|q", "output to terminal", &opts["vox_is0"],
+ "section-backmatter", "document backmatter (default)" , &opts["backmatter"],
+ "section-biblio", "document biblio (default)", &opts["section_biblio"],
+ "section-blurb", "document blurb (default)", &opts["section_blurb"],
+ "section-body", "document body (default)", &opts["section_body"],
+ "section-bookindex", "document bookindex (default)", &opts["section_bookindex"],
+ "section-endnotes", "document endnotes (default)", &opts["section_endnotes"],
+ "section-glossary", "document glossary (default)", &opts["section_glossary"],
+ "section-toc", "table of contents (default)", &opts["section_toc"],
+ "serial", "serial processing", &opts["serial"],
+ "skip-output", "skip output", &opts["skip-output"],
+ "show-config", "show config", &opts["show-config"],
+ "show-curate", "show curate", &opts["show-curate"],
+ "show-curate-authors", "show curate authors", &opts["show-curate-authors"],
+ "show-curate-topics", "show curate topics", &opts["show-curate-topics"],
+ "show-epub", "show epub", &opts["show-epub"],
+ "show-html", "show html", &opts["show-html"],
+ "show-latex", "show latex", &opts["show-latex"],
+ "show-make", "show make", &opts["show-make"],
+ "show-manifest", "show manifest", &opts["show-manifest"],
+ "show-metadata", "show metadata", &opts["show-metadata"],
+ "show-pod", "show pod", &opts["show-pod"],
+ "show-sqlite", "show sqlite", &opts["show-sqlite"],
+ "show-summary", "show summary", &opts["show-summary"],
+ "source", "document markup source", &opts["source"],
+ "set-digest", "default hash digest type (e.g. sha256)", &settings["set-digest"],
+ "set-papersize", "default papersize (latex pdf eg. a4 or a5 or b4 or letter)", &settings["set-papersize"],
+ "set-textwrap", "default textwrap (e.g. 80 (characters)", &settings["set-textwrap"],
+ "sqlite-discrete", "process discrete sqlite output", &opts["sqlite-discrete"],
+ "sqlite-db-create", "create db, create tables", &opts["sqlite-db-create"],
+ "sqlite-db-drop", "drop tables & db", &opts["sqlite-db-drop"],
+ "sqlite-db-filename", "sqlite db to create, populate & make available for search", &settings["sqlite-db-filename"],
+ "sqlite-db-path", "sqlite db path", &settings["sqlite-db-path"],
+ "sqlite-db-recreate", "create db, create tables", &opts["sqlite-db-recreate"],
+ "sqlite-delete", "sqlite output", &opts["sqlite-delete"],
+ "sqlite-insert", "sqlite output", &opts["sqlite-insert"],
+ "sqlite-update", "sqlite output", &opts["sqlite-update"],
+ "www-http", "http or https", &settings["www-http"],
+ "www-host", "web server host (domain) name", &settings["www-host"],
+ "www-host-doc-root", "web host host (domain) name with path to doc root", &settings["www-host-doc-root"],
+ "www-url-doc-root", "e.g. http://localhost", &settings["www-url-doc-root"],
+ "text", "text output", &opts["text"],
+ "theme-dark", "alternative dark theme", &opts["theme-dark"],
+ "theme-light", "default light theme", &opts["theme-light"],
+ "txt", "text output", &opts["text"],
+ "verbose|v", "output to terminal", &opts["vox_gt1"],
+ "very-verbose", "output to terminal", &opts["vox_gt2"],
+ "workon", "(reserved for some matters under development & testing)", &opts["workon"],
+ "xhtml", "xhtml output", &opts["xhtml"],
+ "config", "=/path/to/config/file/including/filename", &settings["config"],
+ "debug", "debug", &opts["debug"],
+ "debug-curate", "debug curate", &opts["debug-curate"],
+ "debug-curate-authors", "debug curate authors", &opts["debug-curate-authors"],
+ "debug-curate-topics", "debug curate topics", &opts["debug-curate-topics"],
+ "debug-epub", "debug epub", &opts["debug-epub"],
+ "debug-harvest", "debug harvest", &opts["debug-harvest"],
+ "debug-html", "debug html", &opts["debug-html"],
+ "debug-latex", "debug latex", &opts["debug-latex"],
+ "debug-manifest", "debug manifest", &opts["debug-manifest"],
+ "debug-metadata", "debug metadata", &opts["debug-metadata"],
+ "debug-pod", "debug pod", &opts["debug-pod"],
+ "debug-sqlite", "debug sqlite", &opts["debug-sqlite"],
+ "debug-stages", "debug stages", &opts["debug-stages"],
+ // "sqlite-db-filename", "=[filename].sql.db", &settings["sqlite-db-filename"],
+ );
+ if (helpInfo.helpWanted) {
+ defaultGetoptPrinter("Some information about the program.", helpInfo.options);
+ }
+ enum outTask { source_or_pod, sqlite, sqlite_multi, latex, odt, epub, html_scroll, html_seg, html_stuff }
+ struct OptActions {
+ @trusted bool allow_downloads() {
+ return opts["allow-downloads"];
+ }
+ @trusted bool assertions() {
+ return opts["assertions"];
+ }
+ @trusted bool concordance() {
+ return opts["concordance"];
+ }
+ @trusted string config_path_set() {
+ return settings["config"];
+ }
+ @trusted bool css_theme_default() {
+ bool _is_light;
+ if (opts["light"] || opts["theme-light"]) {
+ _is_light = true;
+ } else if (opts["dark"] || opts["theme-dark"]) {
+ _is_light = false;
+ } else {
+ _is_light = true;
+ }
+ return _is_light;
+ }
+ @trusted bool debug_do() {
+ bool _dbg;
+ if (opts["debug"]) {
+ _dbg = true;
+ } else { _dbg = false; }
+ return _dbg;
+ }
+ @trusted bool debug_do_curate() {
+ return (opts["debug"] || opts["debug-curate"]) ? true : false;
+ }
+ @trusted bool debug_do_curate_authors() {
+ return (opts["debug"] || opts["debug-curate"] || opts["debug-curate-authors"]) ? true : false;
+ }
+ @trusted bool debug_do_curate_topics() {
+ return (opts["debug"] || opts["debug-curate"] || opts["debug-curate-topics"]) ? true : false;
+ }
+ @trusted bool debug_do_epub() {
+ return (opts["debug"] || opts["debug-epub"]) ? true : false;
+ }
+ @trusted bool debug_do_harvest() {
+ return (opts["debug"] || opts["debug-harvest"]) ? true : false;
+ }
+ @trusted bool debug_do_html() {
+ return (opts["debug"] || opts["debug-html"]) ? true : false;
+ }
+ @trusted bool debug_do_latex() {
+ return (opts["debug"] || opts["debug-latex"]) ? true : false;
+ }
+ @trusted bool debug_do_manifest() {
+ return (opts["debug"] || opts["debug-manifest"]) ? true : false;
+ }
+ @trusted bool debug_do_metadata() {
+ return (opts["debug"] || opts["debug-metadata"]) ? true : false;
+ }
+ @trusted bool debug_do_pod() {
+ return (opts["debug"] || opts["debug-pod"]) ? true : false;
+ }
+ @trusted bool debug_do_sqlite() {
+ return (opts["debug"] || opts["debug-sqlite"]) ? true : false;
+ }
+ @trusted bool debug_do_stages() {
+ return (opts["debug"] || opts["debug-stages"]) ? true : false;
+ }
+ @trusted bool debug_do_xmls() {
+ return (opts["debug"] || opts["debug-html"] || opts["debug-epub"]) ? true : false;
+ }
+ @trusted bool curate() {
+ return (opts["curate"] || opts["curate-authors"] || opts["curate-topics"]) ? true : false;
+ }
+ @trusted bool curate_authors() {
+ return (opts["curate"] || opts["curate-authors"]) ? true : false;
+ }
+ @trusted bool curate_topics() {
+ return (opts["curate"] || opts["curate-topics"]) ? true : false;
+ }
+ @trusted bool digest() {
+ return opts["digest"];
+ }
+ @trusted bool epub() {
+ return opts["epub"];
+ }
+ @trusted bool generated_by() {
+ return opts["generated-by"];
+ }
+ @trusted bool html_link_curate() {
+ return (opts["html-link-curate"]) ? true : false;
+ }
+ @trusted bool html_link_markup_source() {
+ return (opts["html-link-markup"]) ? true : false;
+ }
+ @trusted bool html_link_pdf() {
+ return (opts["html-link-pdf"]) ? true : false;
+ }
+ @trusted bool html_link_pdf_a4() {
+ return (opts["html-link-pdf-a4"]) ? true : false;
+ }
+ @trusted bool html_link_pdf_letter() {
+ return (opts["html-link-pdf-letter"]) ? true : false;
+ }
+ @trusted bool html_link_search() {
+ return (opts["html-link-search"]) ? true : false;
+ }
+ @trusted bool html() {
+ return (opts["html"] || opts["html-seg"] || opts["html-scroll"]) ? true : false;
+ }
+ @trusted bool html_seg() {
+ return (opts["html"] || opts["html-seg"]) ? true : false;
+ }
+ @trusted bool html_scroll() {
+ return (opts["html"] || opts["html-scroll"]) ? true : false;
+ }
+ @trusted bool html_stuff() {
+ return (opts["html"] || opts["html-scroll"] || opts["html-seg"]) ? true : false;
+ }
+ @trusted bool latex() {
+ return (opts["latex"] || opts["pdf"]) ? true : false;
+ }
+ @trusted bool latex_color_links() {
+ return (opts["latex-color-links"] || opts["pdf-color-links"]) ? true : false;
+ }
+ @trusted bool latex_document_header_sty() {
+ return (opts["latex-init"] || opts["latex-header-sty"] || opts["pdf-init"]) ? true : false;
+ }
+ @trusted bool manifest() {
+ return opts["manifest"];
+ }
+ @trusted bool odt() {
+ return (opts["odf"] || opts["odt"]) ? true : false;
+ }
+ @trusted bool ocn_hidden() {
+ return opts["hide-ocn"];
+ }
+ @trusted bool ocn_off() {
+ return opts["ocn-off"];
+ }
+ @trusted bool pod() {
+ return opts["pod"];
+ }
+ @trusted bool show_config() {
+ return opts["show-config"];
+ }
+ @trusted bool show_curate() {
+ return opts["show-curate"];
+ }
+ @trusted bool show_curate_authors() {
+ return (opts["show-curate"] || opts["show-curate-authors"] || opts["vox_gt1"] || opts["vox_gt2"]) ? true : false;
+ }
+ @trusted bool show_curate_topics() {
+ return (opts["show-curate"] || opts["show-curate-topics"] || opts["vox_gt2"]) ? true : false;
+ }
+ @trusted bool show_epub() {
+ return opts["show-epub"];
+ }
+ @trusted bool show_html() {
+ return opts["show-html"];
+ }
+ @trusted bool show_latex() {
+ return opts["show-latex"];
+ }
+ @trusted bool show_make() {
+ return opts["show-make"];
+ }
+ @trusted bool show_manifest() {
+ return opts["show-manifest"];
+ }
+ @trusted bool show_metadata() {
+ return opts["show-metadata"];
+ }
+ @trusted bool show_pod() {
+ return opts["show-pod"];
+ }
+ @trusted bool show_sqlite() {
+ return (opts["show-sqlite"] || opts["vox_gt2"]) ? true : false;
+ }
+ @trusted bool show_summary() {
+ return (opts["show-summary"] || opts["vox_gt1"] || opts["vox_gt2"]) ? true : false;
+ }
+ @trusted bool source() {
+ return opts["source"];
+ }
+ @trusted bool source_or_pod() {
+ return (opts["pod"] || opts["source"]) ? true : false;
+ }
+ @trusted bool sqlite_discrete() {
+ return opts["sqlite-discrete"];
+ }
+ @trusted bool sqlite_db_drop() {
+ return (opts["sqlite-db-recreate"] || opts["sqlite-db-drop"]) ? true : false;
+ }
+ @trusted bool sqlite_db_create() {
+ return (opts["sqlite-db-recreate"] || opts["sqlite-db-create"]) ? true : false;
+ }
+ @trusted bool sqlite_delete() {
+ return opts["sqlite-delete"];
+ }
+ @trusted bool sqlite_update() {
+ return (opts["sqlite-update"] || opts["sqlite-insert"]) ? true : false;
+ }
+ @trusted bool sqlite_shared_db_action() {
+ return (
+ opts["sqlite-db-recreate"]
+ || opts["sqlite-db-create"]
+ || opts["sqlite-delete"]
+ || opts["sqlite-insert"]
+ || opts["sqlite-update"]
+ ) ? true : false;
+ }
+ @trusted bool vox_is0() { // --quiet -q
+ return opts["vox_is0"];
+ }
+ @trusted bool vox_gt0() { // normal, minimal, without flag
+ return (!(opts["vox_is0"]) || opts["vox_gt1"] || opts["vox_gt2"]) ? true : false;
+ }
+ @trusted bool vox_gt1() { // -- verbose -v
+ return (opts["vox_gt1"] || opts["vox_gt2"]) ? true : false;
+ }
+ @trusted bool vox_gt2() { // --very-verbose
+ return opts["vox_gt2"];
+ }
+ @trusted bool text() {
+ return opts["text"];
+ }
+ @trusted bool xhtml() {
+ return opts["xhtml"];
+ }
+ @trusted bool section_toc() {
+ return opts["section_toc"];
+ }
+ @trusted bool section_body() {
+ return opts["section_body"];
+ }
+ @trusted bool section_endnotes() {
+ return opts["section_endnotes"];
+ }
+ @trusted bool section_glossary() {
+ return opts["section_glossary"];
+ }
+ @trusted bool section_biblio() {
+ return opts["section_biblio"];
+ }
+ @trusted bool section_bookindex() {
+ return opts["section_bookindex"];
+ }
+ @trusted bool section_blurb() {
+ return opts["section_blurb"];
+ }
+ @trusted bool backmatter() {
+ return opts["backmatter"];
+ }
+ @trusted bool skip_output() {
+ return opts["skip-output"];
+ }
+ @trusted bool workon() {
+ return opts["workon"];
+ }
+ @trusted string[] languages_set() {
+ return settings["lang"].split(",");
+ }
+ @trusted string output_dir_set() {
+ return settings["output"];
+ }
+ @trusted string sqliteDB_filename() {
+ return settings["sqlite-db-filename"];
+ }
+ @trusted string sqliteDB_path() {
+ return settings["sqlite-db-path"];
+ }
+ @trusted string cgi_bin_root() {
+ return settings["cgi-bin-root"];
+ }
+ @trusted string cgi_search_title() {
+ return settings["cgi-search-title"];
+ }
+ @trusted string cgi_sqlite_search_filename() {
+ return settings["cgi-sqlite-search-filename"];
+ }
+ @trusted string cgi_sqlite_search_filename_d() {
+ return (settings["cgi-sqlite-search-filename"].length > 0)
+ ? (settings["cgi-sqlite-search-filename"].translate(['-' : "_"]) ~ ".d")
+ : "";
+ }
+ @trusted string cgi_url_root() {
+ return settings["cgi-url-root"];
+ }
+ @trusted string cgi_url_action() {
+ return settings["cgi-url-action"];
+ }
+ @trusted string hash_digest_type() {
+ return settings["set-digest"];
+ }
+ @trusted string text_wrap() {
+ return settings["set-textwrap"];
+ }
+ @trusted string latex_papersize() {
+ return settings["set-papersize"];
+ }
+ @trusted string webserver_host_name() {
+ return settings["www-host"];
+ }
+ @trusted string webserver_host_doc_root() {
+ return settings["www-host-doc-root"];
+ }
+ @trusted string webserver_url_doc_root() {
+ return settings["www-url-doc-root"];
+ }
+ @trusted string webserver_http() {
+ return settings["www-http"];
+ }
+ @trusted bool parallelise() {
+ bool _is;
+ if (opts["serial"] == true) {
+ _is = false;
+ } else if (sqlite_shared_db_action) {
+ _is = false;
+ } else if (opts["parallel"] == true) {
+ _is = true;
+ if (sqlite_shared_db_action) { _is = false; }
+ } else if (
+ opts["abstraction"]
+ || concordance
+ || curate
+ || html
+ || epub
+ || odt
+ || latex
+ || manifest
+ || source_or_pod
+ || sqlite_discrete
+ ) {
+ _is = true;
+ } else { _is = false; }
+ return _is;
+ }
+ @trusted bool parallelise_subprocesses() {
+ return opts["parallel-subprocesses"];
+ }
+ auto output_task_scheduler() {
+ int[] schedule;
+ if (source_or_pod) {
+ schedule ~= outTask.source_or_pod;
+ }
+ 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;
+ }
+ if (odt) {
+ schedule ~= outTask.odt;
+ }
+ if (latex) {
+ schedule ~= outTask.latex;
+ }
+ return schedule.sort().uniq;
+ }
+ @trusted bool abstraction() {
+ return (
+ opts["abstraction"]
+ || concordance
+ || source_or_pod
+ || curate
+ || html
+ || epub
+ || odt
+ || latex
+ || manifest
+ || sqlite_discrete
+ || sqlite_delete
+ || sqlite_update
+ ) ? true : false;
+ }
+ @trusted bool require_processing_files() {
+ return (
+ opts["abstraction"]
+ || epub
+ || curate
+ || html
+ || html_seg
+ || html_scroll
+ || latex
+ || odt
+ || manifest
+ || show_make
+ || show_metadata
+ || show_summary
+ || source_or_pod
+ || sqlite_discrete
+ || sqlite_update
+ || text
+ || xhtml
+ ) ? true : false;
+ }
+ @trusted bool meta_processing_general() {
+ return (
+ opts["abstraction"]
+ || curate
+ || html
+ || epub
+ || odt
+ || latex
+ || sqlite_discrete
+ || sqlite_update
+ ) ? true :false;
+ }
+ @trusted bool meta_processing_xml_dom() {
+ return (
+ opts["abstraction"]
+ || html
+ || epub
+ || odt
+ || sqlite_discrete
+ || sqlite_update
+ ) ? true : false;
+ }
+ }
+ OptActions _opt_action = OptActions();
+ auto program_info() {
+ struct ProgramInfo {
+ string project() {
+ return project_name;
+ }
+ string name() {
+ return program_name;
+ }
+ string ver() {
+ return format("%s.%s.%s",
+ _ver.major, _ver.minor, _ver.patch,
+ );
+ }
+ string compiler() {
+ return format ("%s D:%s, %s %s",
+ __VENDOR__, __VERSION__,
+ bits, os,
+ );
+ }
+ @trusted string name_and_version() {
+ return format("%s-%s", name, ver);
+ }
+ @trusted string name_version_and_compiler() {
+ return format("%s-%s (%s)", name, ver, compiler);
+ }
+ auto time_output_generated() {
+ auto _st = Clock.currTime(UTC());
+ auto _t = TimeOfDay(_st.hour, _st.minute, _st.second);
+ auto _time = _st.year.to!string
+ ~ "-" ~ _st.month.to!int.to!string // prefer as month number
+ ~ "-" ~ _st.day.to!string
+ ~ " [" ~ _st.isoWeek.to!string ~ "/" ~ _st.dayOfWeek.to!int.to!string ~ "]"
+ ~ " - " ~ _t.toISOExtString
+ // ~ " " ~ _st.hour.to!string ~ ":" ~ _st.minute.to!string ~ ":" ~ _st.second.to!string
+ ~ " UTC";
+ return _time;
+ // return _st.toISOExtString();
+ }
+ }
+ return ProgramInfo();
+ }
+ auto _env = [
+ "pwd" : environment["PWD"],
+ "home" : environment["HOME"],
+ ];
+ auto _manifested = PathMatters!()(_opt_action, _env, "");
+ auto _manifests = [ _manifested ];
+ auto _conf_file_details = configFilePaths!()(_manifested, _env, _opt_action.config_path_set);
+ ConfComposite _siteConfig;
+ if (
+ _opt_action.require_processing_files
+ && _opt_action.config_path_set.empty
+ ) {
+ foreach(arg; args[1..$]) {
+ if (!(arg.match(rgx.flag_action))) { /+ cli markup source path +/ // get first input markup source file names for processing
+ _manifested = PathMatters!()(_opt_action, _env, arg);
+ { /+ local site config +/
+ _conf_file_details = configFilePaths!()(_manifested, _env, _opt_action.config_path_set);
+ auto _config_local_site_struct = readConfigSite!()(_conf_file_details, _opt_action, _cfg);
+ import sisudoc.meta.conf_make_meta_yaml;
+ _siteConfig = _config_local_site_struct.configParseYAMLreturnSpineStruct!()(_siteConfig, _manifested, _opt_action, _cfg); // - get local site config
+ break;
+ }
+ }
+ }
+ } else { /+ local site config +/
+ auto _config_local_site_struct = readConfigSite!()(_conf_file_details, _opt_action, _cfg);
+ import sisudoc.meta.conf_make_meta_yaml;
+ _siteConfig = _config_local_site_struct.configParseYAMLreturnSpineStruct!()(_siteConfig, _manifested, _opt_action, _cfg); // - get local site config
+ }
+ if (_opt_action.show_config) {
+ import sisudoc.meta.metadoc_show_config;
+ spineShowSiteConfig!()(_opt_action, _siteConfig);
+ }
+ if (!(_opt_action.skip_output)) {
+ if ((_opt_action.debug_do)
+ || (_opt_action.debug_do_stages)
+ ) {
+ writeln("step0 commence → (without processing files)");
+ }
+ outputHubOp!()(_env, _opt_action, _siteConfig);
+ if ((_opt_action.debug_do)
+ || (_opt_action.debug_do_stages)
+ ) {
+ writeln("- step0 complete");
+ }
+ }
+ ConfComposite _make_and_meta_struct = _siteConfig;
+ destroy(_siteConfig);
+ foreach(arg; args[1..$]) {
+ if (arg.match(rgx.flag_action)) { /+ cli instruction, flag do +/
+ flag_action ~= " " ~ arg; // flags not taken by getopt
+ } else if (_opt_action.require_processing_files) { /+ cli, assumed to be path to source files +/
+ auto _manifest_start = PodManifest!()(_opt_action, arg);
+ if ( /+ pod files +/
+ !(arg.match(rgx_files.src_pth_sst_or_ssm))
+ && _manifest_start.pod_manifest_file_with_path
+ && _opt_action.abstraction
+ ) {
+ string pod_manifest_root_content_paths_to_markup_location_raw_;
+ string markup_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_)) {
+ import dyaml;
+ try {
+ Node pod_manifest_yaml;
+ try {
+ pod_manifest_yaml = Loader.fromFile(sisudoc_txt_).load();
+ } catch (ErrnoException ex) {
+ } catch (FileException ex) {
+ writeln("ERROR failed to read config file");
+ } catch (Throwable) {
+ writeln("ERROR failed to read config file content, not parsed as yaml");
+ }
+ if ("doc" in pod_manifest_yaml) {
+ if (pod_manifest_yaml["doc"].type.mapping
+ && pod_manifest_yaml["doc"].tag.match(rgx_y.yaml_tag_is_map)
+ ) {
+ if ("path" in pod_manifest_yaml["doc"]) {
+ if (pod_manifest_yaml["doc"]["path"].tag.match(rgx_y.yaml_tag_is_seq)) {
+ foreach (string _path; pod_manifest_yaml["doc"]["path"]) {
+ markup_contents_location_ ~= _path ~ "\n";
+ pod_manifest_root_content_paths_to_markup_location_raw_ ~=
+ _path ~ "\n";
+ }
+ } else if (
+ pod_manifest_yaml["doc"]["path"].type.string
+ && pod_manifest_yaml["doc"]["path"].tag.match(rgx_y.yaml_tag_is_str)
+ ) {
+ markup_contents_location_ = pod_manifest_yaml["doc"]["path"].get!string;
+ pod_manifest_root_content_paths_to_markup_location_raw_ =
+ pod_manifest_yaml["doc"]["path"].get!string;
+ }
+ }
+ if ("filename" in pod_manifest_yaml["doc"]) {
+ if (pod_manifest_yaml["doc"]["filename"].tag.match(rgx_y.yaml_tag_is_seq)) {
+ foreach (string _filename; pod_manifest_yaml["doc"]["filename"]) {
+ if ("language" in pod_manifest_yaml["doc"]) {
+ if (pod_manifest_yaml["doc"]["language"].tag.match(rgx_y.yaml_tag_is_seq)) {
+ foreach (string _lang; pod_manifest_yaml["doc"]["language"]) {
+ markup_contents_location_ ~=
+ "media/text/"
+ ~ _lang ~ "/"
+ ~ _filename ~ "\n";
+ }
+ } else if (pod_manifest_yaml["doc"]["language"].tag.match(rgx_y.yaml_tag_is_str)
+ ) {
+ markup_contents_location_ =
+ "media/text/"
+ ~ pod_manifest_yaml["doc"]["language"].get!string
+ ~ "/" ~ _filename ~ "\n";
+ } else {
+ string _lang_default = "en";
+ markup_contents_location_ ~=
+ "media/text/"
+ ~ _lang_default ~ "/"
+ ~ pod_manifest_yaml["doc"]["filename"].get!string ~ "\n";
+ }
+ } else {
+ string _lang_default = "en";
+ markup_contents_location_ ~=
+ "media/text/"
+ ~ _lang_default ~ "/"
+ ~ pod_manifest_yaml["doc"]["filename"].get!string ~ "\n";
+ }
+ }
+ } else if (
+ pod_manifest_yaml["doc"]["filename"].type.string
+ && pod_manifest_yaml["doc"]["filename"].tag.match(rgx_y.yaml_tag_is_str)
+ ) {
+ if ("language" in pod_manifest_yaml["doc"]) {
+ if (pod_manifest_yaml["doc"]["language"].tag.match(rgx_y.yaml_tag_is_seq)) {
+ foreach (string _lang; pod_manifest_yaml["doc"]["language"]) {
+ markup_contents_location_ ~=
+ "media/text/"
+ ~ _lang ~ "/"
+ ~ pod_manifest_yaml["doc"]["filename"].get!string ~ "\n";
+ }
+ } else if (pod_manifest_yaml["doc"]["language"].tag.match(rgx_y.yaml_tag_is_str)) {
+ markup_contents_location_ =
+ "media/text/"
+ ~ pod_manifest_yaml["doc"]["language"].get!string
+ ~ "/" ~ pod_manifest_yaml["doc"]["filename"].get!string ~ "\n";
+ } else {
+ string _lang_default = "en";
+ markup_contents_location_ ~=
+ "media/text/"
+ ~ _lang_default ~ "/"
+ ~ pod_manifest_yaml["doc"]["filename"].get!string ~ "\n";
+ }
+ } else {
+ string _lang_default = "en";
+ markup_contents_location_ ~=
+ "media/text/"
+ ~ _lang_default ~ "/"
+ ~ pod_manifest_yaml["doc"]["filename"].get!string ~ "\n";
+ }
+ }
+ }
+ }
+ }
+ } catch (ErrnoException ex) {
+ }
+ }
+ } catch (ErrnoException ex) {
+ } catch (FileException ex) {
+ // Handle errors
+ }
+ } else {
+ writeln("manifest not found: ", sisudoc_txt_);
+ }
+ auto markup_contents_locations_arr
+ = (cast(char[]) markup_contents_location_).split;
+ auto tmp_dir_ = (sisudoc_txt_).dirName.array;
+ foreach (markup_contents_location; markup_contents_locations_arr) {
+ assert(markup_contents_location.match(rgx_files.src_pth_sst_or_ssm),
+ "not a recognised file: «" ~
+ markup_contents_location ~ "»"
+ );
+ auto markup_contents_location_pth_ = (markup_contents_location).to!string;
+ Regex!(char) lang_rgx_ = regex(r"/(" ~ _opt_action.languages_set.join("|") ~ ")/");
+ if (_opt_action.languages_set[0] == "all"
+ || (markup_contents_location_pth_).match(lang_rgx_)
+ ) {
+ auto _fns = (((tmp_dir_).chainPath(markup_contents_location_pth_)).array).to!string;
+ _manifested = PathMatters!()(_opt_action, _env, arg, _fns, markup_contents_locations_arr);
+ _manifests ~= _manifested;
+ }
+ }
+ } else if (arg.match(rgx_files.src_pth_sst_or_ssm)) { /+ markup txt files +/
+ if (exists(arg)==0) {
+ writeln("ERROR >> Processing Skipped! File not found: ", arg);
+ } else {
+ _manifested = PathMatters!()(_opt_action, _env, arg, arg);
+ _manifests ~= _manifested;
+ }
+ } else if (arg.match(rgx_files.src_pth_zip)) {
+ // fns_src ~= arg; // gather input markup source file names for processing
+ } else { // anything remaining, unused
+ arg_unrecognized ~= " " ~ arg;
+ }
+ }
+ }
+ if (_manifests.length > 1 // _manifests[0] initialized dummy element
+ && _opt_action.abstraction) {
+ /+ ↓ output hub +/
+ if (!(_opt_action.skip_output)) {
+ outputHubInitialize!()(_opt_action, program_info);
+ }
+ if (_opt_action.parallelise) { // see else
+ import std.parallelism;
+ foreach(manifest; parallel(_manifests[1..$])) {
+ if (!empty(manifest.src.filename)) {
+ scope(success) {
+ if (_opt_action.vox_gt0) {
+ writefln(
+ "%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_files.src_pth_types),
+ "not a sisu markup filename: «" ~
+ manifest.src.filename ~ "»"
+ );
+ if ((_opt_action.debug_do)
+ || (_opt_action.debug_do_stages)
+ ) {
+ writeln("--->\nstepX commence → (document abstraction) [", manifest.src.filename, "]");
+ }
+ auto t = spineAbstraction!()(_env, program_info, _opt_action, _cfg, manifest, _make_and_meta_struct);
+ static assert(t.length==2);
+ auto doc_abstraction = t[dAM.abstraction];
+ auto doc_matters = t[dAM.matters];
+ if ((doc_matters.opt.action.debug_do)
+ || (_opt_action.debug_do_stages)
+ ) {
+ writeln("- stepX complete for [", manifest.src.filename, "]");
+ }
+ /+ ↓ debugs +/
+ if (doc_matters.opt.action.show_summary) {
+ import sisudoc.meta.metadoc_show_summary;
+ spineMetaDocSummary!()(doc_abstraction, doc_matters);
+ }
+ /+ ↓ debugs +/
+ if (doc_matters.opt.action.show_metadata) {
+ import sisudoc.meta.metadoc_show_metadata;
+ spineShowMetaData!()(doc_matters);
+ }
+ /+ ↓ debugs +/
+ if (doc_matters.opt.action.show_make) {
+ import sisudoc.meta.metadoc_show_make;
+ spineShowMake!()(doc_matters);
+ }
+ /+ ↓ debugs +/
+ if (doc_matters.opt.action.show_config) {
+ import sisudoc.meta.metadoc_show_config;
+ spineShowConfig!()(doc_matters);
+ }
+ if (doc_matters.opt.action.curate) {
+ auto _hvst = spineMetaDocCurate!()(doc_matters, hvst);
+ if (
+ _hvst.title.length > 0
+ && _hvst.author_surname_fn.length > 0
+ ) {
+ hvst.curates ~= _hvst;
+ } else {
+ if ((doc_matters.opt.action.debug_do)
+ || (_opt_action.debug_do_curate)
+ || (doc_matters.opt.action.vox_gt2)
+ ) {
+ writeln("WARNING curate: document header yaml does not contain information related to: title or author: ", _hvst.path_html_segtoc);
+ }
+ }
+ }
+ /+ ↓ debugs +/
+ if (doc_matters.opt.action.debug_do) {
+ spineDebugs!()(doc_abstraction, doc_matters);
+ }
+ /+ ↓ output hub +/
+ if (!(doc_matters.opt.action.skip_output)) {
+ if ((_opt_action.debug_do)
+ || (_opt_action.debug_do_stages)
+ ) {
+ writeln("step5 commence → (process outputs) [", manifest.src.filename, "]");
+ }
+ doc_abstraction.outputHub!()(doc_matters);
+ if ((_opt_action.debug_do)
+ || (_opt_action.debug_do_stages)
+ ) {
+ writeln("- step5 complete for [", manifest.src.filename, "]");
+ }
+ }
+ scope(exit) {
+ if (_opt_action.vox_gt0) {
+ writefln(
+ "processed file: %s [%s]",
+ manifest.src.filename,
+ manifest.src.language
+ );
+ }
+ destroy(manifest);
+ }
+ } else {
+ /+ no recognized filename provided +/
+ writeln("no recognized filename");
+ break; // terminate, stop
+ }
+ }
+ } else { // note cannot parallelise sqlite shared db
+ foreach(manifest; _manifests[1..$]) {
+ if (_opt_action.vox_gt2) {
+ writeln("parallelisation off: actions include sqlite shared db");
+ }
+ if (!empty(manifest.src.filename)) {
+ scope(success) {
+ if (_opt_action.vox_gt0) {
+ writefln(
+ "%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_files.src_pth_types),
+ "not a sisu markup filename: «" ~
+ manifest.src.filename ~ "»"
+ );
+ if ((_opt_action.debug_do)
+ || (_opt_action.debug_do_stages)
+ ) {
+ writeln("--->\nstepX commence → (document abstraction) [", manifest.src.filename, "]");
+ }
+ auto t = spineAbstraction!()(_env, program_info, _opt_action, _cfg, manifest, _make_and_meta_struct);
+ static assert(t.length==2);
+ auto doc_abstraction = t[dAM.abstraction];
+ auto doc_matters = t[dAM.matters];
+ if ((doc_matters.opt.action.debug_do)
+ || (_opt_action.debug_do_stages)
+ ) {
+ writeln("- stepX complete for [", manifest.src.filename, "]");
+ }
+ /+ ↓ debugs +/
+ if (doc_matters.opt.action.show_summary) {
+ import sisudoc.meta.metadoc_show_summary;
+ spineMetaDocSummary!()(doc_abstraction, doc_matters);
+ }
+ /+ ↓ debugs +/
+ if (doc_matters.opt.action.show_metadata) {
+ import sisudoc.meta.metadoc_show_metadata;
+ spineShowMetaData!()(doc_matters);
+ }
+ /+ ↓ debugs +/
+ if (doc_matters.opt.action.show_make) {
+ import sisudoc.meta.metadoc_show_make;
+ spineShowMake!()(doc_matters);
+ }
+ /+ ↓ debugs +/
+ if (doc_matters.opt.action.show_config) {
+ import sisudoc.meta.metadoc_show_config;
+ spineShowConfig!()(doc_matters);
+ }
+ if (doc_matters.opt.action.curate) {
+ auto _hvst = spineMetaDocCurate!()(doc_matters, hvst);
+ if (
+ _hvst.title.length > 0
+ && _hvst.author_surname_fn.length > 0
+ ) {
+ hvst.curates ~= _hvst;
+ } else {
+ if ((doc_matters.opt.action.debug_do)
+ || (_opt_action.debug_do_curate)
+ || (doc_matters.opt.action.vox_gt2)
+ ) {
+ writeln("WARNING curate: document header yaml does not contain information related to: title or author: ", _hvst.path_html_segtoc);
+ }
+ }
+ }
+ /+ ↓ debugs +/
+ if (doc_matters.opt.action.debug_do) {
+ spineDebugs!()(doc_abstraction, doc_matters);
+ }
+ /+ ↓ output hub +/
+ if (!(doc_matters.opt.action.skip_output)) {
+ if ((_opt_action.debug_do)
+ || (_opt_action.debug_do_stages)
+ ) {
+ writeln("step5 commence → (process outputs) [", manifest.src.filename, "]");
+ }
+ doc_abstraction.outputHub!()(doc_matters);
+ if ((_opt_action.debug_do)
+ || (_opt_action.debug_do_stages)
+ ) {
+ writeln("- step5 complete for [", manifest.src.filename, "]");
+ }
+ }
+ scope(exit) {
+ if (_opt_action.vox_gt0) {
+ writefln(
+ "processed file: %s [%s]",
+ manifest.src.filename,
+ manifest.src.language
+ );
+ }
+ destroy(manifest);
+ }
+ } else {
+ /+ no recognized filename provided +/
+ writeln("no recognized filename");
+ break; // terminate, stop
+ }
+ }
+ }
+ }
+ if (hvst.curates.length > 0) {
+ if (_opt_action.curate_topics) {
+ spineMetaDocCuratesTopics!()(hvst, _make_and_meta_struct, _opt_action);
+ }
+ if (_opt_action.curate_authors) {
+ spineMetaDocCuratesAuthors!()(hvst.curates, _make_and_meta_struct, _opt_action);
+ }
+ if (_opt_action.vox_gt0) {
+ import sisudoc.io_out.paths_output;
+ auto out_pth = spinePathsHTML!()(_make_and_meta_struct.conf.output_path, "");
+ if (_opt_action.curate_authors) {
+ writeln("- ", out_pth.curate("authors.html"));
+ }
+ if (_opt_action.curate_topics) {
+ writeln("- ", out_pth.curate("topics.html"));
+ }
+ }
+ } // else { writeln("NO METADATA CURATED"); }
+}