From ae23669169b32d4986af06c1ae9483cc9c52d39d Mon Sep 17 00:00:00 2001
From: Ralph Amissah <ralph@amissah.com>
Date: Sat, 7 Jul 2018 13:55:43 -0400
Subject: 0.26.4 file renames, cleaning, reorganisation

---
 src/sdp/source/paths_source.d      | 774 +++++++++++++++++++++++++++++++++++++
 src/sdp/source/read_config_files.d | 226 +++++++++++
 src/sdp/source/read_source_files.d | 354 +++++++++++++++++
 3 files changed, 1354 insertions(+)
 create mode 100644 src/sdp/source/paths_source.d
 create mode 100644 src/sdp/source/read_config_files.d
 create mode 100644 src/sdp/source/read_source_files.d

(limited to 'src/sdp/source')

diff --git a/src/sdp/source/paths_source.d b/src/sdp/source/paths_source.d
new file mode 100644
index 0000000..8d3aefe
--- /dev/null
+++ b/src/sdp/source/paths_source.d
@@ -0,0 +1,774 @@
+/++
+  read configuration files<BR>
+  - read config files<BR>
+  meta_config_files.d
++/
+module sdp.source.paths_source;
+import std.array,
+  std.file,
+  std.path,
+  std.regex,
+  std.stdio,
+  std.conv : to;
+import sdp.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 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 ( // TODO this should catch generated --source sisupod, untested, needs manifest
+              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 ( // TODO this should catch generated --source sisupod, untested, needs manifest
+              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 ( // TODO this should catch generated --source sisupod, untested, needs manifest
+             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 ( // TODO this should catch generated --source sisupod, untested, needs manifest
+              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/sdp/source/read_config_files.d b/src/sdp/source/read_config_files.d
new file mode 100644
index 0000000..9d976a5
--- /dev/null
+++ b/src/sdp/source/read_config_files.d
@@ -0,0 +1,226 @@
+/++
+  read configuration files<BR>
+  - read config files<BR>
+  meta_config_files.d
++/
+module sdp.source.read_config_files;
+static template configReadInSiteTOML() {
+  import
+    sdp.meta,
+    sdp.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
+    sdp.meta,
+    sdp.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
+    sdp.meta,
+    sdp.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
+    sdp.meta,
+    sdp.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);
+              // writeln(__LINE__, ": found: ", conf_file, " in ", pth);
+            }
+            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
+    sdp.meta,
+    sdp.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
+    sdp.meta,
+    sdp.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
+    sdp.meta,
+    sdp.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/sdp/source/read_source_files.d b/src/sdp/source/read_source_files.d
new file mode 100644
index 0000000..28a660a
--- /dev/null
+++ b/src/sdp/source/read_source_files.d
@@ -0,0 +1,354 @@
+/++
+  module source_read_source_files;<BR>
+  - open markup files<BR>
+  - if master file scan for addional files to import/insert
++/
+module sdp.source.read_source_files;
+static template SiSUrawMarkupContent() {
+  import
+    sdp.meta.rgx;
+  import
+    sdp.meta,
+    sdp.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) {
+            tell_l("red", line);
+            tell_l("red", fn_src_insert);
+            tell_l("fuchsia", "ERROR");
+            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) {
+            tell_l("red", line);
+            tell_l("red", 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;
+    }
+  }
+}
-- 
cgit v1.2.3