diff options
| author | Ralph Amissah <ralph@amissah.com> | 2017-07-13 07:44:03 -0400 | 
|---|---|---|
| committer | Ralph Amissah <ralph@amissah.com> | 2019-04-10 15:14:14 -0400 | 
| commit | 22cea68385b57a1593f5751e49cfdd41d8067997 (patch) | |
| tree | 9e61339eb58679977c24962b1cfd2f50aa7f2998 /src/sdp/meta | |
| parent | sdl extract and composite conf (make) (diff) | |
0.18.0 rename meta from ao (considered adr)
Diffstat (limited to 'src/sdp/meta')
| -rw-r--r-- | src/sdp/meta/composite_make.d | 109 | ||||
| -rw-r--r-- | src/sdp/meta/conf_make_meta.d | 49 | ||||
| -rw-r--r-- | src/sdp/meta/conf_make_meta_native.d | 330 | ||||
| -rw-r--r-- | src/sdp/meta/conf_make_meta_sdlang.d | 155 | ||||
| -rw-r--r-- | src/sdp/meta/defaults.d | 489 | ||||
| -rw-r--r-- | src/sdp/meta/doc_debugs.d | 659 | ||||
| -rw-r--r-- | src/sdp/meta/metadoc.d | 141 | ||||
| -rw-r--r-- | src/sdp/meta/metadoc_from_src.d | 5590 | ||||
| -rw-r--r-- | src/sdp/meta/metadoc_summary.d | 81 | ||||
| -rw-r--r-- | src/sdp/meta/object_setter.d | 65 | ||||
| -rw-r--r-- | src/sdp/meta/package.d | 17 | ||||
| -rw-r--r-- | src/sdp/meta/read_config_files.d | 80 | ||||
| -rw-r--r-- | src/sdp/meta/read_source_files.d | 294 | ||||
| -rw-r--r-- | src/sdp/meta/rgx.d | 256 | 
14 files changed, 8315 insertions, 0 deletions
| diff --git a/src/sdp/meta/composite_make.d b/src/sdp/meta/composite_make.d new file mode 100644 index 0000000..dc28206 --- /dev/null +++ b/src/sdp/meta/composite_make.d @@ -0,0 +1,109 @@ +/++ +  output hub<BR> +  check & generate output types requested ++/ +module sdp.meta.composite_make; +template compositeMkCnf() { +  import sdp.meta; +  import std.array; +  mixin SiSUrgxInit; +  string[] _substitutions; +  string[string][] _sub; +  string _bold; +  string _italics; +  string _emphasis; +  auto compositeMkCnf(Mks...)(Mks makes) { +    foreach (make; makes) { +      auto rgx = Rgx(); +      if (auto z = "make" in make) { +        if (auto x = "substitute" in *z) { +          foreach (m; (*x).matchAll(rgx.make_simple_substitutions_d)) { +            _sub ~= ["match": (m["match"]), "replace": (m["replace"])]; +            _substitutions ~= format("`%s`,\"%s\"", +              m["match"], +              m["replace"], +            ); +          } +          foreach (m; (*x).matchAll(rgx.make_simple_substitutions_rb)) { +            _sub ~= ["match": (m["match"]), "replace": (m["replace"])]; +            _substitutions ~= format("`%s`,\"%s\"", +              m["match"], +              m["replace"], +            ); +          } +        } +        if (auto x = "bold" in *z) { +          _bold = (*x).to!string; +        } +        if (auto x = "italics" in *z) { +          _italics = (*x).to!string; +        } +        if (auto x = "emphasis" in *z) { +          _emphasis = (*x).to!string; +        } +      } +    } +    struct _composite_make { +      auto substitutions() { +        auto _k = _sub; +        return _k; +      } +      auto substitute() { +        auto _k = _substitutions; +        return _k; +      } +      auto italics() { +        auto _k = _italics; +        return _k; +      } +      auto bold() { +        auto _k = _bold; +        return _k; +      } +      auto emphasis() { +        auto _k = _emphasis; +        return _k; +      } +    } +    return _composite_make(); +  } +} +/++ +  output hub<BR> +  check & generate output types requested ++/ +template compositeMkCnfAA() { +  import sdp.meta; +  import std.array; +  mixin SiSUrgxInit; +  string[] _substitutions; +  string[string][] _sub; +  auto rgx = Rgx(); +  auto compositeMkCnfAA(Mks...)(Mks makes) { +    /+ +     - skip.first_make which is the "composite make output" +     - pass config files as associative arrays, +     - skip.last_make which is getopt, treat separately +    +/ +    auto _composite_make = makes[0]; +    auto _opts = makes[$-1]; +    foreach (make; makes[1..$-1]) { +      if (auto z = "make" in make) { // document head: make (part of individual document) +        if (auto x = "substitute" in *z) { +          _composite_make["make"]["substitute"] = *x; +        } +        if (auto x = "italics" in *z) { +          _composite_make["make"]["italics"] = *x; +        } +        if (auto x = "bold" in *z) { +          _composite_make["make"]["bold"] = *x; +        } +        if (auto x = "emphasis" in *z) { +          _composite_make["make"]["emphasis"] = *x; +        } +      } +    } +    /+ logic for adding _opts make instructions to _composite make +/ +    return _composite_make; +  } +} diff --git a/src/sdp/meta/conf_make_meta.d b/src/sdp/meta/conf_make_meta.d new file mode 100644 index 0000000..5beeae2 --- /dev/null +++ b/src/sdp/meta/conf_make_meta.d @@ -0,0 +1,49 @@ +/++ +  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 sdp.meta.conf_make_meta; +template docHeaderMakeAndMetaTupExtractAndConvertToAA() { +  import +    std.exception, +    std.regex, +    std.stdio, +    std.traits, +    std.typecons, +    std.utf, +    std.conv : to; +  import sdlang; +  import +    sdp.meta.conf_make_meta_native, +    sdp.meta.conf_make_meta_sdlang, +    sdp.meta.rgx; +  mixin SiSUrgxInit; +  mixin SiSUheaderExtractNative; +  mixin SiSUextractSDLang; +  auto rgx = Rgx(); +  auto docHeaderMakeAndMetaTupExtractAndConvertToAA(DocMake, Src)( +    DocMake conf_doc_make_aa, +    Src     header_src, +  ) { +    debug(asserts){ +      static assert(is(typeof(header_src)       == char[])); +      static assert(is(typeof(conf_doc_make_aa) == string[string][string])); +    } +    auto head_native = HeaderDocMetadataAndMakeNativeToAA(); +    auto header_sdlang_tag = (!(header_src.match(rgx.native_header_meta_title))) +    ? extractSDL().docHeaderSDLtagGet(header_src) // sdlang.ast.Tag +    : null; +    auto header_make_and_meta_tuple = (header_src.match(rgx.native_header_meta_title)) +    ? (head_native.headerNativeToAA(header_src)) +    : (extractSDL().docHeaderSDLtoAA(conf_doc_make_aa, header_sdlang_tag)); +    static assert(!isTypeTuple!(header_make_and_meta_tuple)); +    static assert(header_make_and_meta_tuple.length==2); +    return header_make_and_meta_tuple; +  } +} diff --git a/src/sdp/meta/conf_make_meta_native.d b/src/sdp/meta/conf_make_meta_native.d new file mode 100644 index 0000000..fc7912f --- /dev/null +++ b/src/sdp/meta/conf_make_meta_native.d @@ -0,0 +1,330 @@ +/++ +  native headers using<br>@title:<BR>:subtitle:<BR>type tags<BR> +  extract native/orig header return associative array ++/ +module sdp.meta.conf_make_meta_native; +template SiSUheaderExtractNative() { +  import +    std.exception, +    std.regex, +    std.stdio, +    std.string, +    std.traits, +    std.typecons, +    std.utf, +    std.conv : to; +  import +    sdp.meta.defaults, +    sdp.meta.rgx; +  struct HeaderDocMetadataAndMakeNativeToAA { +    mixin SiSUregisters; +    mixin SiSUrgxInitFlags; +    mixin SiSUrgxInit; +    auto rgx = Rgx(); +    enum State { off, on } +    string hm, hs; +    auto header_metadata_and_make_aa(H,Me,Ma)( +      H  header, +      Me dochead_meta, +      Ma dochead_make +    ) +    in { +      debug(asserts){ +        static assert(is(typeof(header)       == string)); +        static assert(is(typeof(dochead_meta) == string[string][string])); +        static assert(is(typeof(dochead_make) == string[string][string])); +      } +    } +    body { +      scope(exit) { +        destroy(header); +        destroy(dochead_meta); +        destroy(dochead_make); +      } +      if (auto t = header.match(rgx.native_header_main)) { +        char[][] header_obj_spl = +          (cast(char[]) header).split(rgx.line_delimiter_ws_strip); +        auto hm = to!string(t.captures[1]); +        if (hm.match(rgx.main_headers)) { +          foreach (line; header_obj_spl) { +            if (auto m = line.match(rgx.native_header_main)) { +              if (!empty(m.captures[2])) { +                if (hm == "creator") { +                  dochead_meta[hm]["author"] = +                    to!string(m.captures[2]); +                } else if (hm == "title") { +                  dochead_meta[hm]["main"] = +                    to!string(m.captures[2]); +                } else if (hm == "publisher") { +                  dochead_meta[hm]["name"] = +                    to!string(m.captures[2]); +                } +              } +            } else if (auto s = match(line, rgx.native_header_sub)) { +              if (!empty(s.captures[2])) { +                auto hs = to!string(s.captures[1]); +                if ((hm == "make" ) +                && (dochead_make[hm])) { +                  switch (hm) { +                  case "make": +                    if (hs.match(rgx.native_subhead_make)) { +                      if (dochead_make[hm][hs]) { +                        dochead_make[hm][hs] = to!string(s.captures[2]); +                      } +                    } else { +                      writeln("not a valid header type:", hm, ":", hs); +                      destroy(hm); +                      destroy(hs); +                    } +                    break; +                  default: +                    break; +                  } +                } else if (dochead_meta[hm]) { +                  switch (hm) { +                  case "creator": +                    if (hs.match(rgx.native_subhead_creator)) { +                      if (dochead_meta[hm][hs]) { +                        dochead_meta[hm][hs] = +                          to!string(s.captures[2]); +                      } +                    } else { +                      writeln("not a valid header type:", hm, ":", hs); +                      destroy(hm); +                      destroy(hs); +                    } +                    break; +                  case "title": +                    if (hs.match(rgx.native_subhead_title)) { +                      if ((hs == "subtitle") +                      && (dochead_meta[hm]["sub"])) { +                        dochead_meta[hm]["sub"] = +                          to!string(s.captures[2]); +                      } else if (dochead_meta[hm][hs]) { +                        dochead_meta[hm][hs] = +                          to!string(s.captures[2]); +                      } +                    } else { +                      writeln("not a valid header type:", hm, ":", hs); +                      destroy(hm); +                      destroy(hs); +                    } +                    break; +                  case "rights": +                    if (hs.match(rgx.native_subhead_rights)) { +                      if (dochead_meta[hm][hs]) { +                        dochead_meta[hm][hs] = +                          to!string(s.captures[2]); +                      } +                    } else { +                      writeln("not a valid header type:", hm, ":", hs); +                      destroy(hm); +                      destroy(hs); +                    } +                    break; +                  case "date": +                    if (hs.match(rgx.native_subhead_date)) { +                      if (dochead_meta[hm][hs]) { +                        dochead_meta[hm][hs] = +                          to!string(s.captures[2]); +                      } +                    } else { +                      writeln("not a valid header type:", hm, ":", hs); +                      destroy(hm); +                      destroy(hs); +                    } +                    break; +                  case "original": +                    if (hs.match(rgx.native_subhead_original)) { +                      if (dochead_meta[hm][hs]) { +                        dochead_meta[hm][hs] = +                          to!string(s.captures[2]); +                      } +                    } else { +                      writeln("not a valid header type:", hm, ":", hs); +                      destroy(hm); +                      destroy(hs); +                    } +                    break; +                  case "classify": +                    if (hs.match(rgx.native_subhead_classify)) { +                      if (dochead_meta[hm][hs]) { +                        dochead_meta[hm][hs] = +                          to!string(s.captures[2]); +                      } +                    } else { +                      writeln("not a valid header type:", hm, ":", hs); +                      destroy(hm); +                      destroy(hs); +                    } +                    break; +                  case "identifier": +                    if (hs.match(rgx.native_subhead_identifier)) { +                      if (dochead_meta[hm][hs]) { +                        dochead_meta[hm][hs] = +                          to!string(s.captures[2]); +                      } +                    } else { +                      writeln("not a valid header type:", hm, ":", hs); +                      destroy(hm); +                      destroy(hs); +                    } +                    break; +                  case "notes": +                    if (hs.match(rgx.native_subhead_notes)) { +                      if (dochead_meta[hm][hs]) { +                        dochead_meta[hm][hs] = +                          to!string(s.captures[2]); +                      } +                    } else { +                      writeln("not a valid header type:", hm, ":", hs); +                      destroy(hm); +                      destroy(hs); +                    } +                    break; +                  case "publisher": +                    if (hs.match(rgx.native_subhead_publisher)) { +                      if (dochead_meta[hm][hs]) { +                        dochead_meta[hm][hs] = +                          to!string(s.captures[2]); +                      } +                    } else { +                      writeln("not a valid header type:", hm, ":", hs); +                      destroy(hm); +                      destroy(hs); +                    } +                    break; +                  case "links": +                    destroy(hm); +                    destroy(hs); +                    break; +                  default: +                    break; +                  } +                } +              } +            } +          } +        } else { +          writeln("not a valid header type:", hm); +        } +      } +      auto t = tuple(dochead_meta, dochead_make); +      static assert(t.length==2); +      return t; +    } +    private auto native_header_extract(L,Lo,O,T)( +      L                line, +      return ref Lo    line_occur, +      return ref O     an_object, +      return ref T     type +    ) { +      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(type)       == int[string])); +      } +      if (line.matchFirst(rgx.native_header_make)) {   /+ matched header_make +/ +        debug(header1) { /+ writeln(line); +/ } +        type["header"]      = State.on; +        type["header_make"] = State.on; +        type["header_meta"] = State.off; +        ++line_occur["header_make"]; +        an_object["body_nugget"] ~= line ~= "\n"; +      } else if (line.matchFirst(rgx.native_header)) { /+ matched header_metadata +/ +        /+ (generic header match and not previously caught by header_make) +/ +        debug(header1) { /+ writeln(line); +/ } +        type["header"]      = State.on; +        type["header_make"] = State.off; +        type["header_meta"] = State.on; +        ++line_occur["header_meta"]; +        an_object["body_nugget"] ~= line ~= "\n"; +      } else if (type["header_make"] == State.on +      && (line_occur["header_make"] > State.off)) {     /+ header_make flag set +/ +        if (line.matchFirst(rgx.native_header_sub)) {  /+ sub-header +/ +          debug(header1) { /+ writeln(line); +/ } +          ++line_occur["header_make"]; +          an_object["body_nugget"] ~= line ~= "\n"; +        } +      } else if (type["header_meta"] == State.on +      && (line_occur["header_meta"] > State.off)) {     /+ header_metadata flag set +/ +        if (line.matchFirst(rgx.native_header_sub)) {  /+ sub-header +/ +          debug(header1) { /+ writeln(line); +/ } +          ++line_occur["header_meta"]; +          an_object["body_nugget"] ~= line ~= "\n"; +        } +      } +      return an_object; +    } +    auto header_reset_states_common(Lo,O,T)( +      return ref Lo    line_occur, +      return ref O     an_object, +      return ref T     type +    ) { +      debug(asserts){ +        static assert(is(typeof(line_occur) == int[string])); +        static assert(is(typeof(an_object)  == string[string])); +        static assert(is(typeof(type)       == int[string])); +      } +      line_occur["header_make"] = State.off; +      line_occur["header_meta"] = State.off; +      type["header"] = State.off; +      an_object.remove("body_nugget"); +      an_object.remove("is"); +      an_object.remove("attrib"); +    } +    private auto headerNativeToAA(Hn)(Hn src_header) { +      debug(asserts){ +        static assert(is(typeof(src_header) == char[])); +      } +      auto type = flags_type_init; +      type = [ +       "header"          : State.off, +       "header_make"     : State.off, +       "header_meta"     : State.off, +      ]; +      string[string] an_object; +      int[string] line_occur; +      auto dochead_make = conf_aa_empty; +      auto dochead_meta = meta_aa_empty; +      auto set_header = HeaderDocMetadataAndMakeNativeToAA(); +      char[][] source_header_arr = +        (cast(char[]) src_header).split(rgx.newline_eol_delimiter); +      foreach(header_line; source_header_arr) { +        if (auto m = header_line.matchFirst(rgx.comment)) { +          /+ matched comment +/ +          debug(comment) { +          } +          header_reset_states_common(line_occur, an_object, type); +        } else if ((header_line.matchFirst(rgx.native_header)) +        || (type["header_make"] == State.on +        && (line_occur["header_make"] > State.off)) +        || (type["header_meta"] == State.on +        && (line_occur["header_meta"] > State.off))) { +          if (header_line.length == 0) { +            /+ header_make instructions (current line empty) +/ +            auto dochead_metadata_and_make = +              set_header.header_metadata_and_make_aa(strip(an_object["body_nugget"]), dochead_meta, dochead_make); +            static assert(!isTypeTuple!(dochead_metadata_and_make)); +            dochead_meta = dochead_metadata_and_make[0]; +            dochead_make = dochead_metadata_and_make[1]; +            header_reset_states_common(line_occur, an_object, type); +            type["header_make"] = State.off; +            type["header_meta"] = State.off; +            debug(headersdlang) { +              writeln(dochead_metadata_and_make); +            } +          } else { +            an_object = native_header_extract(header_line, line_occur, an_object, type); +          } +        } +      } +      auto t = tuple( +        dochead_make, +        dochead_meta, +      ); +      return t; +    } +  } +} diff --git a/src/sdp/meta/conf_make_meta_sdlang.d b/src/sdp/meta/conf_make_meta_sdlang.d new file mode 100644 index 0000000..f4af643 --- /dev/null +++ b/src/sdp/meta/conf_make_meta_sdlang.d @@ -0,0 +1,155 @@ +/++ +  sdlang headers<BR> +  extract sdlang header return sdlang ++/ +module sdp.meta.conf_make_meta_sdlang; +template SiSUextractSDLang() { +  import +    std.exception, +    std.regex, +    std.stdio, +    std.string, +    std.traits, +    std.typecons, +    std.utf, +    std.conv : to; +  import +    sdp.meta.defaults, +    sdp.meta.rgx; +  struct extractSDL { +    mixin SiSUregisters; +    mixin SiSUrgxInit; +    auto rgx = Rgx(); +    private auto docHeaderSDLtagGet(Hs)(Hs src_header) { +      debug(asserts){ +        static assert(is(typeof(src_header) == char[])); +      } +      char[][] source_header_arr = +        (cast(char[]) src_header).split(rgx.newline_eol_delimiter); +      char[] _src_header; +      foreach(header_line; source_header_arr) { +        if (!match(header_line, rgx.comments)) { +          _src_header ~= header_line ~ "\n"; +        } +      } +      scope(failure) { +        stderr.writefln( +          "%s\n%s\n%s:%s failed here:\n  _src_header: %s", +          __MODULE__, __FUNCTION__, +          __FILE__, __LINE__, +          _src_header, +        ); +      } +      Tag sdl_root_header; +      try { +        sdl_root_header = parseSource(_src_header.to!string); +      } +      catch(ParseException e) { +        stderr.writeln("SDLang problem with this document header:"); +        stderr.writeln(_src_header); +        // Error messages of the form: +        // myFile.sdl(5:28): Error: Invalid integer suffix. +        stderr.writeln(e.msg); +      } +      debug(sdlang) { +        writeln("header SDL:"); +        writeln(__LINE__, ": ",  sdl_root_header.toSDLDocument()); +        writeln(__LINE__, ": ",  sdl_root_header.maybe.namespaces); +        writeln("header make sdlang: ", sdl_root_header.toSDLDocument()); +        writeln(__LINE__, ": ", sdl_root_header.getTagValues("title")); +        writeln(__LINE__, ": ", sdl_root_header.getTagValues("creator")); +        Tag creator = sdl_root_header.getTag("creator"); +        if (creator !is null) { +          if ("author" in creator.maybe.tags) { +            writeln(__LINE__, ": ", creator.getTagValues("author")); +          } else if ("author" in creator.maybe.attributes) { +            writeln(__LINE__, ": ", creator.maybe.attributes["author"][0].value); +          } +        } +      } +      return sdl_root_header; // sdlang.ast.Tag +    } +    private auto sdlangToAA(C,Tag)(C conf, Tag conf_sdlang) { +      debug(asserts){ +        static assert(is(typeof(conf) == string[string][string])); +      } +      foreach (maintag, subtags; conf) { +        /+ writeln(__LINE__, ": ", maintag, ":- ", subtags); +/ +        foreach (subtag, content; subtags) { +          if (maintag in conf_sdlang.maybe.tags) { +            Tag _maintag = conf_sdlang.getTag(maintag); +            if ((subtag in _maintag.maybe.tags) +            && (_maintag.getTagValues(subtag).length > 0)) { +              debug(headersdlang) { +                writeln(__LINE__, ": ", maintag, ":", subtag, ": ", _maintag.getTagValues(subtag)[0]); +              } +              if (_maintag.getTagValues(subtag).length == 1) { +                conf[maintag][subtag] = +                  (_maintag.getTagValues(subtag)[0]).to!string; +              } else if (_maintag.getTagValues(subtag).length > 1) { +                foreach (st; _maintag.getTagValues(subtag)) { +                  conf[maintag][subtag] ~= +                    st.to!string ~ ";"; +                } +              } +            } else if ((subtag in _maintag.maybe.attributes) +            && (_maintag.maybe.attributes[subtag][0].value.length > 0)) { +              debug(headersdlang) { +                writeln(__LINE__, ": ", maintag, ":", subtag, ": ", conf_sdlang.tags[maintag][0].attributes[subtag][0].value); +              } +              conf[maintag][subtag] = +                (conf_sdlang.tags[maintag][0].attributes[subtag][0].value).to!string; +            } +          } +        } +      } +      return conf; +    } +    private auto docHeaderSDLtoAA(Ma, Tag)(Ma dochead_make, Tag header_sdlang) { +      debug(asserts){ +        static assert(is(typeof(dochead_make) == string[string][string])); +      } +      dochead_make = sdlangToAA(dochead_make, header_sdlang); +      auto dochead_meta = sdlangToAA(meta_aa_empty, header_sdlang); +      if (dochead_meta["title"]["main"].empty) { +        { +          Tag _maintag = header_sdlang.getTag("title"); +          if (_maintag !is null) { +            if ("main" in _maintag.maybe.tags) { +              dochead_meta["title"]["main"] = +                to!string(_maintag.getTagValues("main")); +            } else if ("main" !in _maintag.maybe.attributes) { +              writeln(__LINE__, ": ", _maintag.values[0]); +              dochead_meta["title"]["main"] = +                (_maintag.values[0]).to!string; // test that this exists +            } +          } +        } +      } +      if (!(dochead_meta["title"]["subtitle"].empty) +      && (dochead_meta["title"]["sub"].empty)) { +        dochead_meta["title"]["sub"] ~= dochead_meta["title"]["subtitle"]; +      } +      dochead_meta["title"].remove("subtitle"); +      if (dochead_meta["title"]["sub"].empty) { +        dochead_meta["title"]["full"] ~= dochead_meta["title"]["main"]; +      } else { +        dochead_meta["title"]["full"] ~= format( +          "%s - %s", +          dochead_meta["title"]["main"], +          dochead_meta["title"]["sub"], +        ); +      } +      dochead_meta["creator"]["author_raw"] = dochead_meta["creator"]["author"]; +      string[] authors_arr; +      auto authors_raw_arr = dochead_meta["creator"]["author"].split(rgx.arr_delimiter); +      foreach (author_raw; authors_raw_arr) { +        authors_arr ~= author_raw.replace(rgx.raw_author_munge, "$2 $1"); +      } +      dochead_meta["creator"]["author"] = join(authors_arr, ", ").chomp.chomp; +      auto t = tuple(dochead_make, dochead_meta); +      static assert(t.length==2); +      return t; +    } +  } +} diff --git a/src/sdp/meta/defaults.d b/src/sdp/meta/defaults.d new file mode 100644 index 0000000..fb95e3a --- /dev/null +++ b/src/sdp/meta/defaults.d @@ -0,0 +1,489 @@ +/++ +  default settings ++/ +module sdp.meta.defaults; +template SiSUregisters() { +  import +    std.algorithm, +    std.array, +    std.container, +    std.exception, +    std.file, +    std.getopt, +    std.json, +    std.path, +    std.process, +    std.range, +    std.regex, +    std.stdio, +    std.string, +    std.traits, +    std.typecons, +    std.uni, +    std.utf, +    std.conv : to; +  string[string][string] conf_aa_empty() { +    auto conf_ = [ +      "webserv": [ +         "url_root"         : "", +         "path"             : "~/sdp_www" , +         "images"           : "" , +         "cgi"              : "/usr/local/lib/sdp-cgi" +      ], +      "webserv_cgi": [ +         "host"             : "localhost", +         "base_path"        : "", +         "port"             : "8081", +         "user"             : "", +         "file_links"       : "www.sisudoc.org" +      ], +      "processing": [ +         "path"             : "~", +         "dir"              : "_sisu_processing", +         "concord_max"      : "400000" +      ], +      "flag": [ +         "act0"             : "--digest --qrcode --text --html --epub --concordance --pdf --odf --docbook --xhtml --xml-sax --xml-dom --sqlite --manifest --verbose", +         "act1"             : "--digest --text --html --manifest", +         "act2"             : "--digest --text --html --epub --pdf --manifest", +         "act3"             : "--digest --qrcode --text --html --epub --concordance --pdf --manifest", +         "act4"             : "--digest --qrcode --text --html --epub --concordance --pdf --odf --docbook --manifest", +         "act5"             : "--digest --qrcode --text --html --epub --concordance --pdf --odf --docbook --sqlite --manifest", +         "act6"             : "--digest --qrcode --text --html --epub --concordance --pdf --odf --docbook --xhtml --xml-sax --xml-dom --sqlite --manifest", +         "act7"             : "--digest --qrcode --text --html --epub --concordance --pdf --odf --docbook --xhtml --xml-sax --xml-dom --sqlite --source --sisupod --manifest", +         "act8"             : "--digest --qrcode --text --html --epub --concordance --pdf --odf --docbook --xhtml --xml-sax --xml-dom --pg --update --manifest", +         "act9"             : "--digest --qrcode --text --html --epub --concordance --pdf --odf --docbook --xhtml --xml-sax --xml-dom --pg --update --source --sisupod --manifest" +      ], +      "default": [ +         "papersize"        : "a4,letter", +         "text_wrap"        : "78", +         "emphasis"         : "bold", +         "language"         : "en", +         "digest"           : "sha256" +      ], +      "permission": [ +         "share_source"     : "" +       ], +      "program_select": [ +         "editor"           : "vim", +         "epub_viewer"      : "ebook-viewer", +         "html_viewer"      : "xombrero", +         "odf_viewer"       : "lowriter", +         "pdf_viewer"       : "evince", +         "xml_viewer"       : "xml-viewer" +      ], +      "search": [ +         "flag"             : "", +         "action"           : "", +         "db"               : "", +         "title"            : "" +      ], +      "make": [ +        "bold"              : "", +        "breaks"            : "", +        "cover_image"       : "", +        "css"               : "", +        "emphasis"          : "", +        "footer"            : "", +        "headings"          : "", +        "home_button_image" : "", +        "home_button_text"  : "", +        "italics"           : "", +        "num_top"           : "", +        "num_depth"         : "", +        "substitute"        : "", +        "texpdf_font"       : "" +      ], +    ]; +    return conf_; +  } +  string[string][string] meta_aa_empty() { +    auto meta_ = [ +      "classify": [ +        "dewey"             : "", +        "keywords"          : "", +        "loc"               : "", +        "subject"           : "", +        "topic_register"    : "" +      ], +      "creator": [ +        "author"            : "", +        "author_email"      : "", +        "illustrator"       : "", +        "translator"        : "" +      ], +      "date": [ +        "added_to_site"     : "", +        "available"         : "", +        "created"           : "", +        "issued"            : "", +        "modified"          : "", +        "published"         : "", +        "valid"             : "" +      ], +      "identifier": [ +        "isbn"              : "", +        "oclc"              : "", +        "pg"                : "" +      ], +      "links": [ +        "link"              : "" +      ], +      "notes": [ +        "abstract"          : "", +        "description"       : "" +      ], +      "original": [ +        "language"          : "", +        "source"            : "", +        "title"             : "" +      ], +      "publisher": [ +        "name"              : "" +      ], +      "rights": [ +        "copyright"         : "", +        "cover"             : "", +        "illustrations"     : "", +        "license"           : "" +      ], +      "title": [ +        "edition"           : "", +        "full"              : "", +        "language"          : "", +        "main"              : "", +        "note"              : "", +        "sub"               : "", +        "subtitle"          : "" +      ] +    ]; +    return meta_; +  } +  auto ptr_head_main = +    [ +      "classify", +      "creator", +      "date", +      "identifier", +      "links", +      "make", +      "original", +      "notes", +      "rights", +      "title" +    ]; +  auto ptr_head_sub_classify = +    [ +      "dewey", +      "keywords", +      "loc", +      "subject", +      "topic_register" +    ]; +  auto ptr_head_sub_creator = +    [ +      "author", +      "author_email", +      "cover", +      "illustrator", +      "translator" +    ]; +  auto ptr_head_sub_date = +    [ +      "added_to_site", +      "available", +      "created", +      "issued", +      "modified", +      "published", +      "valid" +    ]; +  auto ptr_head_sub_identifier = +    [ +      "isbn", +      "oclc", +      "pg" +    ]; +  /+ make +/ +  auto ptr_head_sub_make = +    [ +      "cover_image", +      "home_button_image", +      "home_button_text", +      "footer", "headings", +      "num_top", "num_depth", +      "breaks", +      "substitute", +      "bold", +      "italics", +      "emphasis", +      "texpdf_font", +      "css" +    ]; +  auto ptr_head_sub_notes = +    [ +      "abstract", +      "description" +    ]; +  auto ptr_head_sub_original = +    [ +      "language", +      "source", +      "title" +    ]; +  auto ptr_head_sub_publisher = +    [ "name" ]; +  auto ptr_head_sub_rights = +    [ +      "copyright", +      "cover", +      "illustrations", +      "license" +    ]; +  auto ptr_head_sub_title = +    [ +      "edition", +      "full", +      "language", +      "main", +      "note", +      "sub" +    ]; +  auto config_jsonstr = `{ +  }`; +} +template SiSUrgxInitFlags() { +  /+ regex flags +/ +  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 obj_cite_number; 1 no obj_cite_number; 2 no obj_cite_number & dummy headings +      "ocn_status_multi_obj"       : 0, // 0 obj_cite_number; 1 no obj_cite_number; 2 no obj_cite_number & dummy headings +      "book_index"                 : 0, +    ]; +    return flags_type_init; +  } +} +template SiSUnode() { +  string[string] node_metadata_heading_str() { +    auto _node = [ +        "is"                            : "", +        "ocn"                           : "", +        "marked_up_lev"                 : "", +        "segment_anchor_tag"            : "", +        "attrib"                        : "", +    ]; +    return _node; +  } +  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; +  } +  string[string] node_metadata_para_str() { +    auto _node = [ +        "is"                            : "", +        "ocn"                           : "", +        "attrib"                        : "", +    ]; +    return _node; +  } +  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 { +    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() { +  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 = "■"; +    string indent_by_spaces_provided(int indent, string _indent_spaces ="░░") { +      _indent_spaces = replicate(_indent_spaces, indent); +      return _indent_spaces; +    } +    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 { +    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; +    } +    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; +    } +    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; +    } +    auto codes_() { +      return "(" ~ join(code_arr,"|") ~ ")"; +    } +    auto codes_regex() { +      return regex(codes_); +    } +  } +} diff --git a/src/sdp/meta/doc_debugs.d b/src/sdp/meta/doc_debugs.d new file mode 100644 index 0000000..6d94b05 --- /dev/null +++ b/src/sdp/meta/doc_debugs.d @@ -0,0 +1,659 @@ +/++ +  output debugs ++/ +module sdp.meta.doc_debugs; +template SiSUdebugs() { +  import +    sdp.meta.defaults, +    sdp.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)( +    auto return ref const S  contents, +    auto return ref T        doc_matters, +  ) { +    mixin SiSUrgxInit; +    mixin InternalMarkup; +    auto rgx = Rgx(); +    auto markup = InlineMarkup(); +    string key; +    debug(parent) { +      writefln( +        "%s:%s", +        __FILE__, +        __LINE__, +      ); +      foreach (key; doc_matters.keys_seq.seg) { +        foreach (obj; contents[key]) { +          if (obj.use != "empty") { +            if (obj.is_a == "heading") { +              writefln( +                "%s node: %s heading: %s %s", +                obj.obj_cite_number, +                obj.node, +                obj.heading_lev_markup, +                obj.text, +              ); +            } +          } +        } +      } +    } +    debug(dumpdoc) { +      writefln( +        "%s\n%s:%s", +        "-------------------------------", +        __FILE__, +        __LINE__, +      ); +      foreach (obj; contents[key]) { +        if (obj.use != "empty") { +          writefln( +            "[%s][%s]\n%s", +            obj.obj_cite_number, +            obj.is_a, +            obj.text +          ); +        } +      } +    } +    debug(section_head) { +      key="head"; +      if (contents[key].length > 1) { +        foreach (obj; contents[key]) { +          writefln( +            "[%s][%s]\n%s", +            obj.obj_cite_number, +            obj.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.obj_cite_number, +            obj.is_a, +            obj.text +          ); +        } +      } +    } +    debug(toc_nav_dom) { +      enum DomTags { none, open, close, close_and_open, open_still, } +      foreach (sect; doc_matters.keys_seq.seg) { +        foreach (obj; contents[sect]) { +          if (obj.is_a == "heading") { +            foreach_reverse (k; 0 .. 7) { +              switch (obj.dom_markedup[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.keys_seq.seg) { +        foreach (obj; contents[sect]) { +          if (obj.is_a == "heading") { +            foreach_reverse (k; 0 .. 7) { +              switch (obj.dom_collapsed[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(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.obj_cite_number, +            obj.is_a, +            obj.text +          ); +        } +      } +    } +    debug(section_bibliography) { +      key="bibliography"; +      if (contents[key].length > 1) { +        foreach (obj; contents[key]) { +          writefln( +            "[%s][%s]\n%s", +            obj.obj_cite_number, +            obj.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.obj_cite_number, +            obj.is_a, +            obj.text +          ); +        } +      } +    } +    debug(objects) { +      writefln( +        "%s\n%s:%s", +        "-------------------------------", +        __FILE__, +        __LINE__, +      ); +      foreach (obj; contents[key]) { +        if (obj.use != "empty") { +          writefln( +            "* [%s][%s] %s", +            obj.obj_cite_number, +            obj.is_a, +            obj.text +          ); +        } +      } +    } +    debug(headermakejson) { +      writefln( +        "%s\n%s\n%s", +        "document header, metadata & make instructions:", +        doc_matters.dochead_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.dochead_meta[main_header][sub_header].to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.dochead_meta[main_header][sub_header] +              ); +            } +          } +          break; +        default: +          break; +        } +      } +    } +    debug(headermetadatajson) { +      writefln( +        "%s\n%s\n%s", +        "document header, metadata & make instructions:", +        doc_matters.dochead_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.dochead_meta[main_header][sub_header].to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.dochead_meta[main_header][sub_header] +              ); +            } +          } +          break; +        case "title": +          foreach (sub_header; ptr_head_sub_title) { +            if (doc_matters.dochead_meta[main_header][sub_header].to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.dochead_meta[main_header][sub_header] +              ); +            } +          } +          break; +        case "rights": +          foreach (sub_header; ptr_head_sub_rights) { +            if (doc_matters.dochead_meta[main_header][sub_header].to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.dochead_meta[main_header][sub_header] +              ); +            } +          } +          break; +        case "date": +          foreach (sub_header; ptr_head_sub_date) { +            if (doc_matters.dochead_meta[main_header][sub_header].to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.dochead_meta[main_header][sub_header] +              ); +            } +          } +          break; +        case "original": +          foreach (sub_header; ptr_head_sub_original) { +            if (doc_matters.dochead_meta[main_header][sub_header].to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.dochead_meta[main_header][sub_header] +              ); +            } +          } +          break; +        case "classify": +          foreach (sub_header; ptr_head_sub_classify) { +            if (doc_matters.dochead_meta[main_header][sub_header].to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.dochead_meta[main_header][sub_header] +              ); +            } +          } +          break; +        case "identifier": +          foreach (sub_header; ptr_head_sub_identifier) { +            if (doc_matters.dochead_meta[main_header][sub_header].to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.dochead_meta[main_header][sub_header] +              ); +            } +          } +          break; +        case "notes": +          foreach (sub_header; ptr_head_sub_notes) { +            if (doc_matters.dochead_meta[main_header][sub_header].to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.dochead_meta[main_header][sub_header] +              ); +            } +          } +          break; +        case "publisher": +          foreach (sub_header; ptr_head_sub_publisher) { +            if (doc_matters.dochead_meta[main_header][sub_header].to!string.length > 2) { +              writefln( +                "%s:%s: %s", +                main_header, +                sub_header, +                doc_matters.dochead_meta[main_header][sub_header] +              ); +            } +          } +          break; +        default: +          break; +        } +      } +    } +    debug(anchor) { +      writefln( +        "%s\n%s:%s", +        "-------------------------------", +        __FILE__, +        __LINE__, +      ); +      foreach (k; doc_matters.keys_seq.seg) { +        foreach (obj; contents[k]) { +          if (obj.is_a == "heading") { +            writefln( +              "%s~ [%s] %s %s", +              obj.marked_up_level, +              obj.obj_cite_number, +              obj.anchor_tags, +              // "[", obj["is"], "] ", +              obj.text +            ); +          } +        } +      } +    } +    debug(heading) {                         // heading +      foreach (k; doc_matters.keys_seq.seg) { +        foreach (o; contents[k]) { +          if (o.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\n%s:%s", +        "-------------------------------", +        __FILE__, +        __LINE__, +      ); +      foreach (k; doc_matters.keys_seq.seg) { +        foreach (obj; contents[k]) { +          if (obj.is_a == "heading") { +            writefln( +              "%s~ [%s] %s", +              obj.marked_up_level, +              obj.obj_cite_number, +              // "[", obj["is"], "] ", +              obj.text +            ); +          } +        } +      } +    } +    debug(summary) { +      string[string] check = [ +        "last_obj_cite_number" : "NA [debug \"checkdoc\" not run]", +      ]; +    } +    debug(checkdoc) { +      if ((doc_matters.opt_action["debug"])) { +        debug(checkdoc) { +          if (auto mfn=match(doc_matters.source_filename, rgx.src_fn)) { +            if (doc_matters.opt_action["assertions"]) { +              switch (mfn.captures[2]) { +              // live manual: +              case "live-manual.ssm": +                assert(check["last_obj_cite_number"] == +                  "1019","last obj_cite_number should be: 1019 (check test, document is frequently updated)"); // ok +                break; +              // sisu_markup: +              case "sisu_markup.sst": +                assert(check["last_obj_cite_number"] == +                  "297","last obj_cite_number expected to be: 297 rather than " ~ check["last_obj_cite_number"]); // ok +                // assert(check["last_obj_cite_number"] == "297","last obj_cite_number expected to be: 297 rather than " ~ check["last_obj_cite_number"]); +                // notes for first divergance study sisu headings 247 250 +                // sisu has issue with code that contains heading 1~ which results in no obj_cite_number! ?? +                // sisu currently has incorrect last body obj_cite_number of 294! +                // bug in sisu? attend +                break; +              // sisu-markup-samples: +              case "accelerando.charles_stross.sst": +                assert(check["last_obj_cite_number"] == +                  "2861","last obj_cite_number expected to be: 2861 rather than " ~ check["last_obj_cite_number"]); // ok +                break; +              case "alices_adventures_in_wonderland.lewis_carroll.sst": +                assert(check["last_obj_cite_number"] == +                  "805","last obj_cite_number expected to be: 805 rather than " ~ check["last_obj_cite_number"]); // 808 +                break; +              case "autonomy_markup0.sst": +                assert(check["last_obj_cite_number"] == +                  "77","last obj_cite_number expected to be: 77 rather than " ~ check["last_obj_cite_number"]); // ok endnotes +                // assert(check["last_obj_cite_number"] == "78","last obj_cite_number expected to be: 78 rather than " ~ check["last_obj_cite_number"]); +                break; +              case "content.cory_doctorow.sst": +                assert(check["last_obj_cite_number"] == +                  "953","last obj_cite_number expected to be: 953 rather than " ~ check["last_obj_cite_number"]); // 1007 way off, check obj_cite_number off switches +                // assert(check["last_obj_cite_number"] == "953","last obj_cite_number expected to be: 953 rather than " ~ check["last_obj_cite_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_obj_cite_number"] == +                  "905","last obj_cite_number expected to be: 905 rather than " ~ check["last_obj_cite_number"]); // 911 +                break; +              case "down_and_out_in_the_magic_kingdom.cory_doctorow.sst": +                assert(check["last_obj_cite_number"] == +                  "1417","last obj_cite_number expected to be: 1417 rather than " ~ check["last_obj_cite_number"]); // 1455 check obj_cite_number off switches +                break; +              case "for_the_win.cory_doctorow.sst": +                assert(check["last_obj_cite_number"] == +                  "3510","last obj_cite_number expected to be: 3510 rather than " ~ check["last_obj_cite_number"]); // 3569 check obj_cite_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_obj_cite_number"] == +                  "1082","last obj_cite_number expected to be: 1082 rather than " ~ check["last_obj_cite_number"]); // check 1079 too few +                break; +              case "free_culture.lawrence_lessig.sst": +                assert(check["last_obj_cite_number"] == +                  "1330","last obj_cite_number expected to be: 1330 rather than " ~ check["last_obj_cite_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_obj_cite_number"] == +                  "1559","last obj_cite_number expected to be: 1559 rather than " ~ check["last_obj_cite_number"]); // 1560, check obj_cite_number off switches, has endnotes so 2 too many +                // assert(check["last_obj_cite_number"] == "1559","last obj_cite_number expected to be: 1559 rather than " ~ check["last_obj_cite_number"]); +                break; +              case "gpl2.fsf.sst": +                assert(check["last_obj_cite_number"] == +                  "65","last obj_cite_number expected to be: 65 rather than " ~ check["last_obj_cite_number"]); // ok endnotes? check +                // assert(check["last_obj_cite_number"] == "66","last obj_cite_number expected to be: 66 rather than " ~ check["last_obj_cite_number"]); +                break; +              case "gpl3.fsf.sst": +                assert(check["last_obj_cite_number"] == +                  "123","last obj_cite_number expected to be: 123 rather than " ~ check["last_obj_cite_number"]); // ok +                break; +              case "gullivers_travels.jonathan_swift.sst": +                assert(check["last_obj_cite_number"] == +                  "668","last obj_cite_number expected to be: 668 rather than " ~ check["last_obj_cite_number"]); // 674 +                break; +              case "little_brother.cory_doctorow.sst": +                assert(check["last_obj_cite_number"] == +                  "3130","last obj_cite_number expected to be: 3130 rather than " ~ check["last_obj_cite_number"]); // 3204, check obj_cite_number off switches +                break; +              case "the_cathedral_and_the_bazaar.eric_s_raymond.sst": +                assert(check["last_obj_cite_number"] == +                  "258","last obj_cite_number expected to be: 258 rather than " ~ check["last_obj_cite_number"]); // ok +                break; +              case "the_public_domain.james_boyle.sst": +                assert(check["last_obj_cite_number"] == +                  "970","last obj_cite_number expected to be: 970 rather than " ~ check["last_obj_cite_number"]); // 978 +                break; +              case "the_wealth_of_networks.yochai_benkler.sst": // endnotes, bookindex +                assert(check["last_obj_cite_number"] == +                  "829","last obj_cite_number expected to be: 829 rather than " ~ check["last_obj_cite_number"]); // ok +                // assert(check["last_obj_cite_number"] == "832","last obj_cite_number expected to be: 832 rather than " ~ check["last_obj_cite_number"]); +                // has endnotes and bookindex, issue with sisu.rb +                break; +              case "through_the_looking_glass.lewis_carroll.sst": +                assert(check["last_obj_cite_number"] == +                  "949","last obj_cite_number expected to be: 949 rather than " ~ check["last_obj_cite_number"]); // 955 +                break; +              case "two_bits.christopher_kelty.sst": // endnotes, bookindex, biblio +                assert(check["last_obj_cite_number"] == +                  "1190","last obj_cite_number expected to be: 1190 rather than " ~ check["last_obj_cite_number"]); // 1191 +                // assert(check["last_obj_cite_number"] == "1193","last obj_cite_number expected to be: 1193 rather than " ~ check["last_obj_cite_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_obj_cite_number"] == +                  "377","last obj_cite_number expected to be: 377 rather than " ~ check["last_obj_cite_number"]); // ok +                break; +              case "viral_spiral.david_bollier.sst": // endnotes, bookindex +                assert(check["last_obj_cite_number"] == +                  "1078","last obj_cite_number expected to be: 1078 rather than " ~ check["last_obj_cite_number"]); // 1100 +                // fixed ERROR! range violation! +                // error in bookindex ... (ch7 ... building the cc machine, an extra semi colon) +                break; +              default: +                writeln(doc_matters.source_filename); +                break; +              } +            } +          } +        } +        debug(checkdoc) { +          void out_segnames(S,T)( +            auto return ref const S  contents, +            auto return ref T        doc_matters, +          ) { +            foreach (key; doc_matters.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.segnames[obj.ptr_html_segnames], ") -> ",  obj.text); +                  } +                } +              } +            } +          } +        } +        debug(checkdoc) { +          void out_toc(S)( +            auto return ref 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)( +            auto return ref const S  contents, +            string                   key, +          ) { +            if (contents[key].length > 1) { +              foreach (obj; contents[key]) { +                writefln( +                  "[%s]\n%s", +                  obj.is_a, +                  obj.text +                ); +              } +            } +          } +        } +        debug(checkdoc) { +          void out_bookindex(S)( +            auto return ref const S  contents, +            string                   key, +          ) { +            if (contents[key].length > 1) { +              foreach (obj; contents[key]) { +                writefln( +                  "[%s][%s]\n%s", +                  obj.obj_cite_number, +                  obj.is_a, +                  obj.text +                ); +              } +            } +          } +        } +      } +    } +  } +} diff --git a/src/sdp/meta/metadoc.d b/src/sdp/meta/metadoc.d new file mode 100644 index 0000000..4174b67 --- /dev/null +++ b/src/sdp/meta/metadoc.d @@ -0,0 +1,141 @@ +module sdp.meta.metadoc; +template SiSUabstraction() { +  /+ sdp: sisu document parser, see http://sisudoc.org +/ +  import sdp.meta; +  import +    std.getopt, +    std.process; +  import +    sdp.meta.metadoc_summary, +    sdp.meta.metadoc_from_src, +    sdp.meta.composite_make, +    sdp.meta.conf_make_meta, +    // sdp.meta.conf_make_meta_native, +    sdp.meta.conf_make_meta_sdlang, +    sdp.meta.defaults, +    sdp.meta.doc_debugs, +    sdp.meta.read_config_files, +    sdp.meta.read_source_files, +    sdp.meta.rgx, +    sdp.output.hub, +    sdp.output.paths_source; +  mixin SiSUrgxInit; +  mixin SiSUregisters; +  mixin SiSUextractSDLang; +  mixin SiSUnode; +  mixin SiSUbiblio; +  mixin SiSUrgxInitFlags; +  mixin outputHub; +  enum headBody { header, body_content, insert_filelist } +  enum makeMeta { make, meta } +  enum docAbst  { doc_abstraction, section_keys, segnames, segnames_0_4, images } +  auto rgx = Rgx(); +  auto SiSUabstraction(Fn,O,E)(Fn fn_src, O opts, E env){ +    auto sdl_root_config_share = configRead!()("config_local", env); +    auto sdl_root_config_local = configRead!()("config_share", env); +    auto conf_composite_static_aa = extractSDL().sdlangToAA(conf_aa_empty, sdl_root_config_share); +    conf_composite_static_aa = extractSDL().sdlangToAA(conf_composite_static_aa, sdl_root_config_local); +    /+ ↓ read file (filename with path) +/ +    /+ ↓ file tuple of header and content +/ +    auto _header_body_inserts = +      SiSUrawMarkupContent!()(fn_src); +    static assert(!isTypeTuple!(_header_body_inserts)); +    static assert(_header_body_inserts.length==3); +    debug(header_and_body) { +      writeln(header); +      writeln(_header_body_inserts.length); +      writeln(_header_body_inserts.length[headBody.body_content][0]); +    } +    /+ ↓ split header into make and meta +/ +    auto _make_and_meta_tup = +      docHeaderMakeAndMetaTupExtractAndConvertToAA!()(conf_composite_static_aa, _header_body_inserts[headBody.header]); +    static assert(!isTypeTuple!(_make_and_meta_tup)); +    static assert(_make_and_meta_tup.length==2); +    auto _make_config = compositeMkCnf!()( +      conf_composite_static_aa, +      _make_and_meta_tup[makeMeta.make], +      // opts, +    ); +    auto _make_and_conf_composite_static_plus_docheader_aa = compositeMkCnfAA!()( +      conf_aa_empty, +      conf_composite_static_aa, +      _make_and_meta_tup[makeMeta.make], +      opts, +    ); +    /+ ↓ document abstraction: process document, return abstraction as tuple +/ +    auto da = SiSUdocAbstraction!()( +      _header_body_inserts[headBody.body_content], +      _make_and_meta_tup[makeMeta.make], +      _make_and_meta_tup[makeMeta.meta], +      opts +    ); +    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]; +    struct DocumentMatters { +      auto keys_seq() { +        /+ contains .seg & .scroll sequences +/ +        auto _k = _document_section_keys_sequenced; +        return _k; +      } +      string[] segnames() { +        string[] _k = _doc_html_segnames; +        return _k; +      } +      string[] segnames_lv_0_to_4() { +        string[] _k = _doc_epub_segnames_0_4; +        return _k; +      } +      auto dochead_meta() { +        string[string][string] _k = _make_and_meta_tup[makeMeta.meta]; +        return _k; +      } +      auto dochead_make() { +        string[string][string] _k = _make_and_meta_tup[makeMeta.make]; +        return _k; +      } +      auto source_filename() { +        string _k = fn_src; +        return _k; +      } +      auto src_path_info() { +        string _pwd = env["pwd"]; +        auto _k = SiSUpathsSRC!()(_pwd, fn_src); +        return _k; +      } +      auto opt_action() { +        bool[string] _k = opts; +        return _k; +      } +      auto environment() { +        auto _k = env; +        return _k; +      } +      auto language() { +        string _k; +        if (auto m = fn_src.match(rgx.language_code_and_filename)) { +          _k = m.captures[1]; +        } else { +          _k = "en"; +        } +        return _k; +      } +      auto file_insert_list() { +        string[] _k = _header_body_inserts[headBody.insert_filelist]; +        return _k; +      } +      auto image_list() { +        auto _k = _images; +        return _k; +      } +    } +    auto doc_matters = DocumentMatters(); +    auto t = tuple(doc_abstraction, doc_matters); +    static assert(t.length==2); +    return t; +  } +} diff --git a/src/sdp/meta/metadoc_from_src.d b/src/sdp/meta/metadoc_from_src.d new file mode 100644 index 0000000..ab7f883 --- /dev/null +++ b/src/sdp/meta/metadoc_from_src.d @@ -0,0 +1,5590 @@ +/++ +  document abstraction: +  abstraction of sisu markup for downstream processing +  meta_metadoc_from_src.d ++/ +module sdp.meta.metadoc_from_src; +template SiSUdocAbstraction() { +  /+ ↓ abstraction imports +/ +  import sdp.meta; +  import +    std.algorithm, +    std.container, +    std.file, +    std.json, +    std.path; +  import +    sdp.meta.defaults, +    sdp.meta.object_setter, +    sdp.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 +  /+ 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"; +  auto obj_im = ObjInlineMarkup(); +  auto obj_att = ObjAttributes(); +  /+ ocn +/ +  int obj_cite_number, obj_cite_number_; +  auto object_citation_number = OCNemitter(); +  int[] dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +  int[] dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +  int[] dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +  int[] dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +  enum DomTags { none, open, close, close_and_open, open_still, } +  auto obj_heading_ancestors(O)( +    O          obj, +    string[]   lv_ancestors_txt, +  ) { +    switch (obj.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.heading_ancestors_text = lv_ancestors_txt.dup; +    } +    return obj; +  } +  auto obj_dom_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.dom_markedup = dom.dup; +    return obj; +  } +  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.dom_collapsed = dom.dup; +    return obj; +  } +  int 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 } +  /+ ↓ abstract marked up document +/ +  auto SiSUdocAbstraction(Src,Make,Meta,Opt)( +    Src                  markup_sourcefile_content, +    Make                 dochead_make_aa, +    Meta                 dochead_meta_aa, +    Opt                  opt_action, +  ) { +    auto rgx = Rgx(); +    debug(asserts) { +      static assert(is(typeof(markup_sourcefile_content) == char[][])); +      static assert(is(typeof(dochead_make_aa)           == string[string][string])); +      static assert(is(typeof(dochead_meta_aa)           == string[string][string])); +      static assert(is(typeof(opt_action)                == bool[string])); +    } +    /+ ↓ 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 type = flags_type_init; +    string[string] obj_cite_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_.use                   = "frontmatter"; +    comp_obj_heading_.is_of                 = "para"; +    comp_obj_heading_.is_a                  = "heading"; +    comp_obj_heading_.text                  = "Table of Contents"; +    comp_obj_heading_.ocn                   = 0; +    comp_obj_heading_.obj_cite_number       = ""; +    comp_obj_heading_.segment_anchor_tag    = "toc"; +    comp_obj_heading_.marked_up_level       = "1"; +    comp_obj_heading_.heading_lev_markup    = 4; +    comp_obj_heading_.heading_lev_collapsed = 1; +    comp_obj_heading_.parent_ocn            = 1; +    comp_obj_heading_.parent_lev_markup     = 0; +    comp_obj_heading_.ptr_html_segnames     = html_segnames_ptr; +    comp_obj_heading_.anchor_tags           = ["toc"]; +    comp_obj_heading_.dom_markedup          = [ 1, 1, 0, 0, 1, 0, 0, 0]; +    comp_obj_heading_.dom_collapsed         = [ 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], +    ]; +    auto mkup = InlineMarkup(); +    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 ↑ +/ +    /+ ↓ loop markup document/text line by line +/ +    srcDocLoop: +    foreach (line; markup_sourcefile_content) { +      /+ ↓ 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) {                                  // source lines +        writeln(line); +      } +      debug(srclines) { +        if (!line.empty) {                             // source lines, not empty +          writefln( +            "* %s", +            line +          ); +        } +      } +      if (!line.empty) { +        _check_ocn_status_(line, type); +      } +      if (type["code"] == TriState.on) { +        /+ block object: code +/ +        _code_block_(line, an_object, type); +        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) +        || (type["biblio_section"] == State.on +        && (!(line.matchFirst(rgx.heading_blurb_glossary))) +        && (!(line.matchFirst(rgx.heading))) +        && (!(line.matchFirst(rgx.comment))))) { +          /+ within section (block object): biblio +/ +          type["glossary_section"] = State.off; +          type["biblio_section"] = State.on; +          type["blurb_section"] = State.off; +          if (opt_action["backmatter"] && opt_action["section_biblio"]) { +            _biblio_block_(line, type, 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) +        || (type["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); +          } +          type["glossary_section"] = State.on; +          type["biblio_section"] = State.off; +          type["blurb_section"] = State.off; +          if (opt_action["backmatter"] && opt_action["section_glossary"]) { +            indent=[ +              "hang_position" : 0, +              "base_position" : 0, +            ]; +            bullet = false; +            type["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_.use                   = "backmatter"; +              comp_obj_heading_.is_of                 = "para"; +              comp_obj_heading_.is_a                  = "heading"; +              comp_obj_heading_.text                  = "Glossary"; +              comp_obj_heading_.ocn                   = 0; +              comp_obj_heading_.obj_cite_number       = ""; +              comp_obj_heading_.segment_anchor_tag    = "_part_glossary"; +              comp_obj_heading_.marked_up_level       = "B"; +              comp_obj_heading_.heading_lev_markup    = 1; +              comp_obj_heading_.heading_lev_collapsed = 1; +              comp_obj_heading_.parent_ocn            = 1; +              comp_obj_heading_.parent_lev_markup     = 0; +              comp_obj_heading_.dom_markedup          = [ 1, 1, 0, 0, 0, 0, 0, 0]; +              comp_obj_heading_.dom_collapsed         = [ 1, 1, 0, 0, 0, 0, 0, 0]; +              the_glossary_section                    ~= comp_obj_heading_; +              comp_obj_heading_                       = comp_obj_heading_.init; +              comp_obj_heading_.use                   = "backmatter"; +              comp_obj_heading_.is_of                 = "para"; +              comp_obj_heading_.is_a                  = "heading"; +              comp_obj_heading_.text                  = "Glossary"; +              comp_obj_heading_.ocn                   = 0; +              comp_obj_heading_.obj_cite_number       = ""; +              comp_obj_heading_.segment_anchor_tag    = "glossary"; +              comp_obj_heading_.marked_up_level       = "1"; +              comp_obj_heading_.heading_lev_markup    = 4; +              comp_obj_heading_.heading_lev_collapsed = 2; +              comp_obj_heading_.parent_ocn            = 1; +              comp_obj_heading_.parent_lev_markup     = 0; +              comp_obj_heading_.dom_markedup          = [ 1, 1, 0, 0, 1, 0, 0, 0]; +              comp_obj_heading_.dom_collapsed         = [ 1, 1, 1, 0, 0, 0, 0, 0]; +              comp_obj_heading_.anchor_tags           = ["glossary"]; +              the_glossary_section                    ~= comp_obj_heading_; +            } else { +              _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur); +              comp_obj_para                       = comp_obj_para.init; +              comp_obj_para.use                   = "backmatter"; +              comp_obj_para.is_of                 = "para"; +              comp_obj_para.is_a                  = "glossary"; +              comp_obj_para.text                  = line.to!string.strip; +              comp_obj_para.ocn                   = 0; +              comp_obj_para.obj_cite_number       = ""; +              comp_obj_para.indent_hang           = indent["hang_position"]; +              comp_obj_para.indent_base           = indent["base_position"]; +              comp_obj_para.bullet                = bullet; +              the_glossary_section                ~= comp_obj_para; +            } +            type["ocn_status"] = TriState.off; +          } +          continue; +        } else if (line.matchFirst(rgx.heading_blurb) +        || (type["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); +          } +          type["glossary_section"] = State.off; +          type["biblio_section"] = State.off; +          type["blurb_section"] = State.on; +          if (opt_action["backmatter"] && opt_action["section_blurb"]) { +            indent=[ +              "hang_position" : 0, +              "base_position" : 0, +            ]; +            bullet = false; +            type["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_.use                   = "backmatter"; +              comp_obj_heading_.is_of                 = "para"; +              comp_obj_heading_.is_a                  = "heading"; +              comp_obj_heading_.text                  = "Blurb"; +              comp_obj_heading_.ocn                   = 0; +              comp_obj_heading_.obj_cite_number       = ""; +              comp_obj_heading_.segment_anchor_tag    = "_part_blurb"; +              comp_obj_heading_.marked_up_level       = "B"; +              comp_obj_heading_.heading_lev_markup    = 1; +              comp_obj_heading_.heading_lev_collapsed = 1; +              comp_obj_heading_.parent_ocn            = 1; +              comp_obj_heading_.parent_lev_markup     = 0; +              comp_obj_heading_.dom_markedup          = [ 1, 1, 0, 0, 0, 0, 0, 0]; +              comp_obj_heading_.dom_collapsed         = [ 1, 1, 0, 0, 0, 0, 0, 0]; +              the_blurb_section                       ~= comp_obj_heading_; +              comp_obj_heading_                       = comp_obj_heading_.init; +              comp_obj_heading_.use                   = "backmatter"; +              comp_obj_heading_.is_of                 = "para"; +              comp_obj_heading_.is_a                  = "heading"; +              comp_obj_heading_.text                  = "Blurb"; +              comp_obj_heading_.ocn                   = 0; +              comp_obj_heading_.obj_cite_number       = ""; +              comp_obj_heading_.segment_anchor_tag    = "blurb"; +              comp_obj_heading_.marked_up_level       = "1"; +              comp_obj_heading_.heading_lev_markup    = 4; +              comp_obj_heading_.heading_lev_collapsed = 2; +              comp_obj_heading_.parent_ocn            = 1; +              comp_obj_heading_.parent_lev_markup     = 0; +              comp_obj_heading_.anchor_tags           = ["blurb"]; +              comp_obj_heading_.dom_markedup          = [ 1, 1, 0, 0, 1, 0, 0, 0]; +              comp_obj_heading_.dom_collapsed         = [ 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_.use                   = "backmatter"; +              comp_obj_heading_.is_of                 = "para"; +              comp_obj_heading_.is_a                  = "heading"; +              comp_obj_heading_.text                  = line.to!string; +              comp_obj_heading_.ocn                   = 0; +              comp_obj_heading_.obj_cite_number       = ""; +              comp_obj_heading_.segment_anchor_tag    = "blurb"; +              comp_obj_heading_.marked_up_level       = an_object["lev"].to!string; +              comp_obj_heading_.heading_lev_markup    = an_object["lev_markup_number"].to!int;    // make int, remove need to conv +              comp_obj_heading_.heading_lev_collapsed = an_object["lev_collapsed_number"].to!int; // make int, remove need to conv +              comp_obj_heading_.parent_ocn            = 1; +              comp_obj_heading_.parent_lev_markup     = 0; +              the_blurb_section                   ~= comp_obj_heading_; +            } else { +              _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur); +              comp_obj_para                       = comp_obj_para.init; +              comp_obj_para.use                   = "backmatter"; +              comp_obj_para.is_of                 = "para"; +              comp_obj_para.is_a                  = "blurb"; +              comp_obj_para.text                  = line.to!string.strip; +              comp_obj_para.ocn                   = 0; +              comp_obj_para.obj_cite_number       = ""; +              comp_obj_para.indent_hang           = indent["hang_position"]; +              comp_obj_para.indent_base           = indent["base_position"]; +              comp_obj_para.bullet                = bullet; +              the_blurb_section                   ~= comp_obj_para; +            } +            type["ocn_status"] = TriState.off; +          } +          continue; +        } else if (type["quote"] == TriState.on) { +          /+ within block object: quote +/ +          _quote_block_(line, an_object, type); +          continue; +        /+ within block object: group +/ +        } else if (type["group"] == TriState.on) { +          /+ within block object: group +/ +          line = (line) +            .replaceAll(rgx.para_delimiter, mkup.br_paragraph ~ "$1"); +          _group_block_(line, an_object, type); +          continue; +        } else if (type["block"] == TriState.on) { +          /+ within block object: block +/ +          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, type); +          continue; +        } else if (type["poem"] == TriState.on) { +          /+ within block object: poem +/ +          _poem_block_(line, an_object, type, cntr, obj_cite_number_poem, dochead_make_aa); +          continue; +        } else if (type["table"] == TriState.on) { +          /+ within block object: table +/ +          _table_block_(line, an_object, type, dochead_make_aa); +          continue; +        } else { +          /+ not within a block group +/ +          assert( +            (type["blocks"] == TriState.off) +            || (type["blocks"] == TriState.closing), +            "block status: none or closed" +          ); +          assertions_flag_types_block_status_none_or_closed(type); +          if (line.matchFirst(rgx.block_open)) { +            if (line.matchFirst(rgx.block_poem_open)) { +              /+ poem to verse exceptions! +/ +              object_reset(an_object); +              processing.remove("verse"); +              obj_cite_number_poem["start"] = obj_cite_number.to!string; +            } +            _start_block_(line, type, obj_cite_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( +              (type["blocks"] == TriState.off) +              || (type["blocks"] == TriState.closing), +              "code block status: none or closed" +            ); +            if (type["blocks"] == TriState.closing) { +              debug(check) {                           // block +                writeln(__LINE__); +                writeln(line); +              } +              assert( +                line.matchFirst(rgx.book_index) +                || line.matchFirst(rgx.book_index_open) +                || type["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) +            || type["book_index"] == State.on )  { +              /+ book_index +/ +              _book_index_(line, book_idx_tmp, an_object, type, 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.use               = "comment"; +                comp_obj_comment.is_of             = "comment"; +                comp_obj_comment.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, type); +                processing.remove("verse"); +                ++cntr; +              } else if (((line_occur["para"] == State.off) +              && (line_occur["heading"] == State.off)) +              && ((type["para"] == State.off) +              && (type["heading"] == State.off))) { +                /+ heading or para but neither flag nor line exists +/ +                if ((dochead_make_aa["make"]["headings"].length > 2) +                && (type["make_headings"] == State.off)) { +                  /+ heading found +/ +                  _heading_found_(line, dochead_make_aa["make"]["headings"], heading_match_str, heading_match_rgx, type); +                } +                if ((type["make_headings"] == State.on) +                && ((line_occur["para"] == State.off) +                && (line_occur["heading"] == State.off)) +                && ((type["para"] == State.off) +                && (type["heading"] == State.off))) { +                  /+ heading make set +/ +                  line = _heading_make_set_(line, line_occur, heading_match_rgx, type); +                } +                /+ 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 +/ +                  _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa); +                } else if (line_occur["para"] == State.off) { +                  /+ para match +/ +                  an_object_key="body_nugget"; +                  _para_match_(line, an_object, an_object_key, indent, bullet, type, 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); +                } +                an_object[an_object_key] ~= " " ~ line; +                ++line_occur["para"]; +              } +            } +          } else if (type["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_number, +              comp_obj_heading, +              cntr, +              type, +              obj_cite_number_poem, +              dochead_make_aa +            ); +          } else { +            /+ line.empty, post contents, empty variables: +/ +            assert( +              line.empty, +              "\nline should be empty:\n  \"" +              ~ line ~ "\"" +            ); +            assert( +              (type["blocks"] == State.off), +              "code block status: none" +            ); +            if ((type["heading"] == State.on) +            && (line_occur["heading"] > State.off)) { +              /+ heading object (current line empty) +/ +              obj_cite_number = (an_object["lev_markup_number"].to!int == 0) +              ? (ocn_emit(3)) +              : (obj_cite_number = ocn_emit(type["ocn_status"])); +              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, dochead_make_aa); +              an_object["substantive"] = substantive_object_and_anchor_tags_tuple[sObj.content]; +              anchor_tags = substantive_object_and_anchor_tags_tuple[sObj.anchor_tags]; +              if (an_object["lev_markup_number"].to!int == 4) { +                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_number.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_number, segment_anchor_tag_that_object_belongs_to); +              /+ (incrementally build toc) table of contents here! +/ +              _anchor_tag=to!string(obj_cite_number); +              the_table_of_contents_section = obj_im.table_of_contents_gather_headings( +                an_object, +                dochead_make_aa, +                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"],                             // string +                  an_object["lev_markup_number"],               // string +                  an_object["lev_collapsed_number"],            // string +                  segment_anchor_tag_that_object_belongs_to,    // string +                  obj_cite_number,                              // int +                  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, type); +              an_object.remove("lev"); +              an_object.remove("lev_markup_number"); +              processing.remove("verse"); +              ++cntr; +            } else if ((type["para"] == State.on) +            && (line_occur["para"] > State.off)) { +              /+ paragraph object (current line empty) +/ +              obj_cite_number = ocn_emit(type["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_number, 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_number, +                  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, dochead_make_aa); +              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.use                   = "body"; +              comp_obj_para.is_of                 = "para"; +              comp_obj_para.is_a                  = "para"; +              comp_obj_para.text                  = an_object["substantive"].to!string.strip; +              comp_obj_para.ocn                   = obj_cite_number; +              comp_obj_para.obj_cite_number       = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +              comp_obj_para.indent_hang           = indent["hang_position"]; +              comp_obj_para.indent_base           = indent["base_position"]; +              comp_obj_para.bullet                = bullet; +              comp_obj_para.anchor_tags           = anchor_tags; +              comp_obj_para.inline_notes_reg      = substantive_obj_misc_tuple[sObj.notes_reg]; +              comp_obj_para.inline_notes_star     = substantive_obj_misc_tuple[sObj.notes_star]; +              comp_obj_para.inline_links          = substantive_obj_misc_tuple[sObj.links]; +              the_document_body_section           ~= comp_obj_para; +              _common_reset_(line_occur, an_object, type); +              indent=[ +                "hang_position" : 0, +                "base_position" : 0, +              ]; +              bullet = false; +              processing.remove("verse"); +              ++cntr; +            } else { +              assert( +                line == null, +                "line variable should be empty, should not occur" +              ); +            } +          } // 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].is_a == "para") +          || (the_document_body_section[$-1].is_a == "heading") +          || (the_document_body_section[$-1].is_a == "quote") +          || (the_document_body_section[$-1].is_a == "group") +          || (the_document_body_section[$-1].is_a == "block") +          || (the_document_body_section[$-1].is_a == "verse")) +        && (the_document_body_section.length > previous_length)) { +          if ((the_document_body_section[$-1].is_a == "heading") +          && (the_document_body_section[$-1].heading_lev_markup < 5)) { +            type["biblio_section"] = State.off; +            type["glossary_section"] = State.off; +            type["blurb_section"] = State.off; +          } +          if (the_document_body_section[$-1].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].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, +                    to!int(i), +                  ); +                } +              } +            } +          } 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, +                to!int(the_document_body_section.length-1), +              ); +            } +          } +          previous_length = the_document_body_section.length.to!int; +        } +      } +    } /+ ← closed: loop markup document/text line by line +/ +    /+ ↓ post loop markup document/text +/ +    auto en_tuple = +      note_section.endnote_objects(obj_cite_number, opt_action); +    static assert(!isTypeTuple!(en_tuple)); +    auto the_endnotes_section = en_tuple[0]; +    obj_cite_number = 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_.use                   = "empty"; +      comp_obj_heading_.is_of                 = "para"; +      comp_obj_heading_.is_a                  = "heading"; +      comp_obj_heading_.text                  = "(skip) there is no Glossary section"; +      comp_obj_heading_.ocn                   = 0; +      comp_obj_heading_.obj_cite_number       = ""; +      comp_obj_heading_.marked_up_level       = "B"; +      comp_obj_heading_.heading_lev_markup    = 1; +      comp_obj_heading_.heading_lev_collapsed = 1; +      comp_obj_heading_.parent_ocn            = 1; +      comp_obj_heading_.parent_lev_markup     = 0; +      the_glossary_section                    ~= comp_obj_heading_; +    } else { +      writeln("gloss"); +    } +    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_.use                   = "backmatter"; +      comp_obj_heading_.is_of                 = "para"; +      comp_obj_heading_.is_a                  = "heading"; +      comp_obj_heading_.text                  = "Bibliography"; +      comp_obj_heading_.ocn                   = 0; +      comp_obj_heading_.obj_cite_number       = ""; +      comp_obj_heading_.segment_anchor_tag    = "_part_bibliography"; +      comp_obj_heading_.marked_up_level       = "B"; +      comp_obj_heading_.heading_lev_markup    = 1; +      comp_obj_heading_.heading_lev_collapsed = 1; +      comp_obj_heading_.parent_ocn            = 1; +      comp_obj_heading_.parent_lev_markup     = 0; +      the_bibliography_section                ~= comp_obj_heading_; +      comp_obj_heading_                       = comp_obj_heading_.init; +      comp_obj_heading_.use                   = "backmatter"; +      comp_obj_heading_.is_of                 = "para"; +      comp_obj_heading_.is_a                  = "heading"; +      comp_obj_heading_.text                  = "Bibliography"; +      comp_obj_heading_.ocn                   = 0; +      comp_obj_heading_.obj_cite_number       = ""; +      comp_obj_heading_.segment_anchor_tag    = "bibliography"; +      comp_obj_heading_.marked_up_level       = "1"; +      comp_obj_heading_.heading_lev_markup    = 4; +      comp_obj_heading_.heading_lev_collapsed = 2; +      comp_obj_heading_.parent_ocn            = 1; +      comp_obj_heading_.parent_lev_markup     = 0; +      comp_obj_heading_.anchor_tags           = ["bibliography"]; +      the_bibliography_section                ~= comp_obj_heading_; +    } else { +      comp_obj_heading_                       = comp_obj_heading_.init; +      comp_obj_heading_.use                   = "empty"; +      comp_obj_heading_.is_of                 = "para"; +      comp_obj_heading_.is_a                  = "heading"; +      comp_obj_heading_.text                  = "(skip) there is no Bibliography"; +      comp_obj_heading_.ocn                   = 0; +      comp_obj_heading_.obj_cite_number       = ""; +      comp_obj_heading_.marked_up_level       = "B"; +      comp_obj_heading_.heading_lev_markup    = 1; +      comp_obj_heading_.heading_lev_collapsed = 1; +      comp_obj_heading_.parent_ocn            = 1; +      comp_obj_heading_.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.use                   = "backmatter"; +      comp_obj_para.is_of                 = "para"; +      comp_obj_para.is_a                  = "bibliography"; +      comp_obj_para.text                  = out_.to!string.strip; +      comp_obj_para.ocn                   = 0; +      comp_obj_para.obj_cite_number       = ""; +      comp_obj_para.indent_hang           = 0; +      comp_obj_para.indent_base           = 1; +      comp_obj_para.bullet                = bullet; +      comp_obj_para.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_number, +        opt_action, +      ); +    destroy(bookindex_unordered_hashes); +    static assert(!isTypeTuple!(bi_tuple)); +    auto the_bookindex_section = bi_tuple[0]; +    obj_cite_number = 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_.use                   = "empty"; +      comp_obj_heading_.is_of                 = "para"; +      comp_obj_heading_.is_a                  = "heading"; +      comp_obj_heading_.text                  = "(skip) there is no Blurb section"; +      comp_obj_heading_.ocn                   = 0; +      comp_obj_para.obj_cite_number           = ""; +      comp_obj_heading_.segment_anchor_tag    = ""; +      comp_obj_heading_.marked_up_level       = "B"; +      comp_obj_heading_.heading_lev_markup    = 1; +      comp_obj_heading_.heading_lev_collapsed = 1; +      comp_obj_heading_.parent_ocn            = 1; +      comp_obj_heading_.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.use                   = "frontmatter"; +    comp_obj_toc.is_of                 = "para"; +    comp_obj_toc.is_a                  = "toc"; +    comp_obj_toc.ocn                   = 0; +    comp_obj_toc.obj_cite_number       = ""; +    comp_obj_toc.indent_hang           = indent["hang_position"]; +    comp_obj_toc.indent_base           = indent["base_position"]; +    comp_obj_toc.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.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.inline_links               = true; +      the_table_of_contents_section["seg"]    ~= comp_obj_toc; +      toc_txt_ = format( +        "{ %s }#%s", +        "Glossary", +        "glossary",               // _anchor_tag +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.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.inline_links               = true; +      the_table_of_contents_section["seg"]    ~= comp_obj_toc; +     +      toc_txt_ = format( +        "{ %s }#%s", +        "Bibliography", +        "bibliography",           // _anchor_tag +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.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.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",              // _anchor_tag +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.text                       = toc_txt_.to!string.strip; +      comp_obj_toc.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.inline_links               = true; +      the_table_of_contents_section["seg"]    ~= comp_obj_toc; +      toc_txt_ = format( +        "{ %s }#%s", +        "Blurb", +        "blurb",                  // _anchor_tag +      ); +      toc_txt_= munge.url_links(toc_txt_); +      comp_obj_toc.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.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.indent_hang), toc_linked_heading.text); +      } +    } +    the_document_head_section ~= the_document_body_section[0]; +    the_document_body_section=the_document_body_section[1..$]; +    if (the_endnotes_section.length > 1) { +      html_segnames ~= "endnotes"; +      html_segnames_ptr = html_segnames_ptr_cntr; +      foreach (ref section; the_endnotes_section) { +        if (section.heading_lev_markup == 4) { +          section.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 section; the_glossary_section) { +        if (section.heading_lev_markup == 4) { +          section.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 section; the_bibliography_section) { +        if (section.heading_lev_markup == 4) { +          section.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 section; the_bookindex_section["scroll"]) { +        if (section.heading_lev_markup == 4) { +          section.ptr_html_segnames = html_segnames_ptr; +          break; +        } +      } +      foreach (ref section; the_bookindex_section["seg"]) { +        if (section.heading_lev_markup == 4) { +          section.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 section; the_blurb_section) { +        if (section.heading_lev_markup == 4) { +          section.ptr_html_segnames = html_segnames_ptr; +          break; +        } +      } +      html_segnames_ptr_cntr++; +    } +    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; +    foreach (ref obj; the_document_head_section) { +      if (obj.is_a == "heading") { +        debug(dom) { +          writeln(obj.text); +        } +        if (obj.heading_lev_markup <= 4) { +          segnames_0_4 ~= obj.segment_anchor_tag; +        } +        /+ dom structure (marked up & collapsed) +/ +        if ((opt_action["html"]) +        || (opt_action["html-scroll"]) +        || (opt_action["html-seg"]) +        || (opt_action["epub"]) +        || (opt_action["sqlite"]) +        || (opt_action["postgresql"])) { +          obj = obj_dom_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); +          obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); +        } +        obj = obj_heading_ancestors(obj, lv_ancestors_txt); +      } +    } +    if (the_table_of_contents_section["scroll"].length > 1) { +      /+ scroll +/ +      dom_markedup_buffer = dom_markedup.dup; +      dom_collapsed_buffer = dom_collapsed.dup; +      foreach (ref obj; the_table_of_contents_section["scroll"]) { +        if (obj.is_a == "heading") { +          if (obj.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.segment_anchor_tag; +            if (obj.heading_lev_markup == 4) { +              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; +              assert(obj.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"]) +          || (opt_action["postgresql"])) { +            obj = obj_dom_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } +      } +      /+ seg +/ +      dom_markedup = dom_markedup_buffer.dup; +      dom_collapsed = dom_collapsed_buffer.dup; +      foreach (ref obj; the_table_of_contents_section["seg"]) { +        if (obj.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          if (obj.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.segment_anchor_tag; +            if (obj.heading_lev_markup == 4) { +              obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; +              assert(obj.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_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.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.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          if (obj.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.segment_anchor_tag; +            if (obj.heading_lev_markup == 4) { +              obj.lev4_subtoc = lev4_subtoc[obj.segment_anchor_tag]; +              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; +              if (html_segnames.length > obj.ptr_html_segnames + 1) { +                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; +              } +              assert(obj.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"]) +          || (opt_action["postgresql"])) { +            obj = obj_dom_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } else if (obj.is_a == "para") { +           _images ~= extract_images(obj.text); +        } +      } +    } +    auto images=uniq(_images.sort()); +    /+ optional only one 1~ level +/ +    if (the_endnotes_section.length > 1) { +      dom_markedup_buffer = dom_markedup.dup; +      dom_collapsed_buffer = dom_collapsed.dup; +      dom_markedup = dom_markedup_buffer.dup; +      dom_collapsed = dom_collapsed_buffer.dup; +      foreach (ref obj; the_endnotes_section) { +        if (obj.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          if (obj.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.segment_anchor_tag; +            if (obj.heading_lev_markup == 4) { +              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; +              if (html_segnames.length > obj.ptr_html_segnames + 1) { +                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; +              } +              assert(obj.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"]) +          || (opt_action["postgresql"])) { +            obj = obj_dom_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.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.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          if (obj.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.segment_anchor_tag; +            if (obj.heading_lev_markup == 4) { +              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; +              if (html_segnames.length > obj.ptr_html_segnames + 1) { +                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; +              } +              assert(obj.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"]) +          || (opt_action["postgresql"])) { +            obj = obj_dom_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } +      } +    } +    /+ optional only one 1~ level +/ +    if (the_bibliography_section.length > 1) { +      foreach (ref obj; the_bibliography_section) { +        if (obj.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          if (obj.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.segment_anchor_tag; +            if (obj.heading_lev_markup == 4) { +              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; +              if (html_segnames.length > obj.ptr_html_segnames + 1) { +                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; +              } +              assert(obj.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"]) +          || (opt_action["postgresql"])) { +            obj = obj_dom_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } +      } +    } +    /+ optional only one 1~ level +/ +    if (the_bookindex_section["scroll"].length > 1) { +      /+ scroll +/ +      dom_markedup_buffer = dom_markedup.dup; +      dom_collapsed_buffer = dom_collapsed.dup; +      foreach (ref obj; the_bookindex_section["scroll"]) { +        if (obj.is_a == "heading") { +          debug(dom) { +          } +          if (obj.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.segment_anchor_tag; +            if (obj.heading_lev_markup == 4) { +              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; +              if (html_segnames.length > obj.ptr_html_segnames + 1) { +                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; +              } +              assert(obj.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"]) +          || (opt_action["postgresql"])) { +            obj = obj_dom_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } +      } +      /+ seg +/ +      dom_markedup = dom_markedup_buffer.dup; +      dom_collapsed = dom_collapsed_buffer.dup; +      foreach (ref obj; the_bookindex_section["seg"]) { +        if (obj.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          if (obj.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.segment_anchor_tag; +            if (obj.heading_lev_markup == 4) { +              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; +              if (html_segnames.length > obj.ptr_html_segnames + 1) { +                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; +              } +              assert(obj.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"]) +          || (opt_action["postgresql"])) { +            obj = obj_dom_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } +      } +    } +    /+ optional only one 1~ level +/ +    if (the_blurb_section.length > 1) { +      foreach (ref obj; the_blurb_section) { +        if (obj.is_a == "heading") { +          debug(dom) { +            writeln(obj.text); +          } +          if (obj.heading_lev_markup <= 4) { +            segnames_0_4 ~= obj.segment_anchor_tag; +            if (obj.heading_lev_markup == 4) { +              obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; +              if (html_segnames.length > obj.ptr_html_segnames + 1) { +                obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; +              } +              assert(obj.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"]) +          || (opt_action["postgresql"])) { +            obj = obj_dom_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); +            obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); +          } +          obj = obj_heading_ancestors(obj, lv_ancestors_txt); +        } +      } +    } +      /+ TODO +        - note create/insert heading object sole purpose eof close all open tags +          sort out: +          - obj.dom_markedup = dom_markedup; +          - obj.dom_collapsed = dom_collapsed; +      +/ +    comp_obj_heading_                       = comp_obj_heading_.init; +    comp_obj_heading_.use                   = "empty"; +    comp_obj_heading_.is_of                 = "para"; +    comp_obj_heading_.is_a                  = "heading"; +    comp_obj_heading_.ocn                   = 0; +    comp_obj_para.obj_cite_number           = ""; +    comp_obj_heading_.segment_anchor_tag    = ""; +    comp_obj_heading_.marked_up_level       = ""; +    comp_obj_heading_.heading_lev_markup    = 9; +    comp_obj_heading_.heading_lev_collapsed = 9; +    comp_obj_heading_.parent_ocn            = 0; +    comp_obj_heading_.parent_lev_markup     = 0; +    comp_obj_heading_.dom_markedup          = dom_markedup.dup; +    comp_obj_heading_.dom_collapsed         = dom_collapsed.dup; +    obj_dom_set_markup_tags(comp_obj_heading_, dom_markedup, 0); +    obj_dom_set_collapsed_tags(comp_obj_heading_, dom_collapsed, 0); +    obj_heading_ancestors(comp_obj_heading_, lv_ancestors_txt); +    comp_obj_heading_ = obj_dom_set_markup_tags(comp_obj_heading_, dom_markedup, 0); +    comp_obj_heading_ = obj_dom_set_collapsed_tags(comp_obj_heading_, dom_collapsed, 0); +    comp_obj_heading_ = obj_heading_ancestors(comp_obj_heading_, lv_ancestors_txt); +    the_dom_tail_section                    ~= comp_obj_heading_; +    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 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); +    biblio_arr_json = []; +    obj_cite_number=0; +    obj_cite_number_=0; +    html_segnames_ptr=0; +    html_segnames_ptr_cntr=0; +    content_non_header = "8"; +    dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +    dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +    dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +    dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; +    auto t = tuple( +      document_the, +      docSectKeysSeq!()(document_section_keys_sequenced), +      segnames, +      segnames_0_4, +      images, +    ); +    return t; +    /+ post loop markup document/text ↑ +/ +  } /+ ← closed: abstract doc source +/ +  /+ ↓ abstraction functions +/ +  auto object_reset(O)(ref 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"); +  } +  auto _common_reset_(L,O,T)( +    return ref L line_occur, +    return ref O an_object, +    return ref T type +  ) { +    debug(asserts) { +      static assert(is(typeof(line_occur) == int[string])); +      static assert(is(typeof(an_object)  == string[string])); +      static assert(is(typeof(type)       == int[string])); +    } +    line_occur["heading"] = State.off; +    line_occur["para"]    = State.off; +    type["heading"]       = State.off; +    type["para"]          = State.off; +    object_reset(an_object); +  } +  void _check_ocn_status_(L,T)( +    L            line, +    return ref T type +  ) { +    debug(asserts) { +      static assert(is(typeof(line) == char[])); +      static assert(is(typeof(type) == int[string])); +    } +    auto rgx = Rgx(); +    if ((!line.empty) && (type["ocn_status_multi_obj"] == TriState.off)) { +      /+ not multi-line object, check whether obj_cite_number is on or turned off +/ +      if (line.matchFirst(rgx.obj_cite_number_block_marks)) { +        /+ switch off obj_cite_number +/ +        if (line.matchFirst(rgx.obj_cite_number_off_block)) { +          type["ocn_status_multi_obj"] = TriState.on; +          debug(ocnoff) { +            writeln(line); +          } +        } +        if (line.matchFirst(rgx.obj_cite_number_off_block_dh)) { +          type["ocn_status_multi_obj"] = TriState.closing; +          debug(ocnoff) { +            writeln(line); +          } +        } +      } else { +        if (type["ocn_status_multi_obj"] == TriState.off) { +          if (line.matchFirst(rgx.obj_cite_number_off)) { +            type["ocn_status"] = TriState.on; +          } else if (line.matchFirst(rgx.obj_cite_number_off_dh)) { +            type["ocn_status"] = TriState.closing; +          } else { +            type["ocn_status"] = TriState.off; +          } +        } else { +          type["ocn_status"] = +            type["ocn_status_multi_obj"]; +        } +      } +    } else if ((!line.empty) && (type["ocn_status_multi_obj"] > TriState.off)) { +      if (line.matchFirst(rgx.obj_cite_number_off_block_close)) { +        type["ocn_status_multi_obj"] = TriState.off; +        type["ocn_status"] = TriState.off; +        debug(ocnoff) { +          writeln(line); +        } +      } +    } +  } +  void _start_block_(L,T,N)( +    L            line, +    return ref T type, +    N            obj_cite_number_poem +  ) { +    debug(asserts) { +      static assert(is(typeof(line)                 == char[])); +      static assert(is(typeof(type)                 == int[string])); +      static assert(is(typeof(obj_cite_number_poem) == string[string])); +    } +    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 +        ); +      } +      type["blocks"] = TriState.on; +      type["code"] = TriState.on; +      type["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 +        ); +      } +      obj_cite_number_poem["start"] = +        obj_cite_number.to!string; +      type["blocks"] = TriState.on; +      type["verse_new"] = State.on; +      type["poem"] = TriState.on; +      type["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 +        ); +      } +      type["blocks"] = TriState.on; +      type["group"] = TriState.on; +      type["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 +        ); +      } +      type["blocks"] = TriState.on; +      type["block"] = TriState.on; +      type["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 +        ); +      } +      type["blocks"] = TriState.on; +      type["quote"] = TriState.on; +      type["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"; +      type["blocks"]                     = TriState.on; +      type["table"]                      = TriState.on; +      type["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"; +      type["blocks"]                     = TriState.on; +      type["table"]                      = TriState.on; +      type["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 +        ); +      } +      type["blocks"] = TriState.on; +      type["code"] = TriState.on; +      type["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 +        ); +      } +      obj_cite_number_poem["start"] = obj_cite_number.to!string; +      type["blocks"] = TriState.on; +      type["verse_new"] = State.on; +      type["poem"] = TriState.on; +      type["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 +        ); +      } +      type["blocks"] = TriState.on; +      type["group"] = TriState.on; +      type["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 +        ); +      } +      type["blocks"] = TriState.on; +      type["block"] = TriState.on; +      type["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 +        ); +      } +      type["blocks"] = TriState.on; +      type["quote"] = TriState.on; +      type["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"; +      type["blocks"]                     = TriState.on; +      type["table"]                      = TriState.on; +      type["tic_table"]                  = TriState.on; +    } +  } +  void _quote_block_(L,O,T)( +    return ref L line, +    return ref O an_object, +    return ref T type +  ) { +    debug(asserts) { +      static assert(is(typeof(line)      == char[])); +      static assert(is(typeof(an_object) == string[string])); +      static assert(is(typeof(type)      == int[string])); +    } +    auto rgx = Rgx(); +    if (type["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; +        type["blocks"]      = TriState.closing; +        type["quote"]       = TriState.closing; +        type["curly_quote"] = TriState.off; +      } else { +        debug(quote) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";   // build quote array (or string) +      } +    } else if (type["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; +        type["blocks"]    = TriState.closing; +        type["quote"]     = TriState.closing; +        type["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)( +    return ref L line, +    return ref O an_object, +    return ref T type +  ) { +    debug(asserts) { +      static assert(is(typeof(line)      == char[])); +      static assert(is(typeof(an_object) == string[string])); +      static assert(is(typeof(type)      == int[string])); +    } +    auto rgx = Rgx(); +    if (type["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; +        type["blocks"]      = TriState.closing; +        type["group"]       = TriState.closing; +        type["curly_group"] = TriState.off; +      } else { +        debug(group) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";   // build group array (or string) +      } +    } else if (type["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; +        type["blocks"]    = TriState.closing; +        type["group"]     = TriState.closing; +        type["tic_group"] = TriState.off; +      } else { +        debug(group) {                              // group +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";   // build group array (or string) +      } +    } +  } +  void _block_block_(L,O,T)( +    return ref L line, +    return ref O an_object, +    return ref T type +  ) { +    debug(asserts) { +      static assert(is(typeof(line)      == char[])); +      static assert(is(typeof(an_object) == string[string])); +      static assert(is(typeof(type)      == int[string])); +    } +    auto rgx = Rgx(); +    if (type["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; +        type["blocks"]      = TriState.closing; +        type["block"]       = TriState.closing; +        type["curly_block"] = TriState.off; +      } else { +        debug(block) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";   // build block array (or string) +      } +    } else if (type["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; +        type["blocks"]    = TriState.closing; +        type["block"]     = TriState.closing; +        type["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,Ma)( +    L     line, +    return ref O an_object, +    return ref T type, +    return ref C cntr, +    N            obj_cite_number_poem, +    Ma           dochead_make_aa, +  ) { +    debug(asserts) { +      static assert(is(typeof(line)                 == char[])); +      static assert(is(typeof(an_object)            == string[string])); +      static assert(is(typeof(type)                 == int[string])); +      static assert(is(typeof(cntr)                 == int)); +      static assert(is(typeof(obj_cite_number_poem) == string[string])); +      static assert(is(typeof(dochead_make_aa)      == string[string][string])); +    } +    auto rgx = Rgx(); +    if (type["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) {                               // poem (curly) close +            writefln( +              "* [poem curly] %s", +              line +            ); +          } +          if (processing.length > 0) { +            an_object[an_object_key] = processing["verse"]; +          } +          debug(poem) {                               // poem (curly) close +            writeln(__LINE__); +            writefln( +              "* %s %s", +              obj_cite_number, +              line +            ); +          } +          if (an_object.length > 0) { +            debug(poem) {                             // poem (curly) close +              writeln( +                obj_cite_number, +                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, dochead_make_aa); +            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.use                        = "body"; +            comp_obj_block.is_of                      = "block"; +            comp_obj_block.is_a                       = "verse"; +            comp_obj_block.ocn                        = obj_cite_number; +            comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +            comp_obj_block.text                       = an_object["substantive"]; +            comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg]; +            comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star]; +            comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links]; +            the_document_body_section                 ~= comp_obj_block; +          } +          object_reset(an_object); +          processing.remove("verse"); +          ++cntr; +        } +        obj_cite_number_poem["end"] = +          obj_cite_number.to!string; +        type["blocks"] = TriState.closing; +        type["poem"] = TriState.closing; +        type["curly_poem"] = TriState.off; +      } else { +        processing["verse"] ~= line ~= "\n"; +        if (type["verse_new"] == State.on) { +          obj_cite_number = +            ocn_emit(type["ocn_status"]); +          type["verse_new"] = State.off; +        } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) { +          processing["verse"] = processing["verse"].stripRight; +          verse_line = TriState.off; +          type["verse_new"] = State.on; +        } +        if (type["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_number, +              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_number, +            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, dochead_make_aa); +          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.use                        = "body"; +          comp_obj_block.is_of                      = "block"; +          comp_obj_block.is_a                       = "verse"; +          comp_obj_block.ocn                        = obj_cite_number; +          comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +          comp_obj_block.text                       = an_object["substantive"]; +          comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg]; +          comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star]; +          comp_obj_block.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 (type["tic_poem"] == TriState.on) { +      if (auto m = line.matchFirst(rgx.block_tic_close)) { // tic_poem_close +        an_object[an_object_key]="verse"; +        debug(poem) {                                       // poem (curly) close +          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_number, 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, dochead_make_aa); +          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.use                        = "body"; +          comp_obj_block.is_of                      = "block"; +          comp_obj_block.is_a                       = "verse"; +          comp_obj_block.ocn                        = obj_cite_number; +          comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +          comp_obj_block.text                       = an_object["substantive"]; +          comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg]; +          comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star]; +          comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links]; +          the_document_body_section                 ~= comp_obj_block; +          obj_cite_number_poem["end"]               = obj_cite_number.to!string; +          object_reset(an_object); +          processing.remove("verse"); +          ++cntr; +        } +        type["blocks"] = TriState.closing; +        type["poem"] = TriState.closing; +        type["tic_poem"] = TriState.off; +      } else { +        processing["verse"] ~= line ~= "\n"; +        if (type["verse_new"] == State.on) { +          obj_cite_number = +            ocn_emit(type["ocn_status"]); +          type["verse_new"] = State.off; +        } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) { +          processing["verse"] = processing["verse"].stripRight; +          type["verse_new"] = State.on; +          verse_line = TriState.off; +        } +        if (type["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_number, +              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_number, +              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, dochead_make_aa); +          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.use                        = "body"; +          comp_obj_block.is_of                      = "block"; +          comp_obj_block.is_a                       = "verse"; +          comp_obj_block.ocn                        = obj_cite_number; +          comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +          comp_obj_block.text                       = an_object["substantive"]; +          comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg]; +          comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star]; +          comp_obj_block.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)( +    return ref L line, +    return ref O an_object, +    return ref T type +  ) { +    debug(asserts) { +      static assert(is(typeof(line)      == char[])); +      static assert(is(typeof(an_object) == string[string])); +      static assert(is(typeof(type)      == int[string])); +    } +    auto rgx = Rgx(); +    if (type["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; +        type["blocks"] = TriState.closing; +        type["code"] = TriState.closing; +        type["curly_code"] = TriState.off; +      } else { +        debug(code) {                                    // code (curly) line +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";        // code (curly) line +      } +    } else if (type["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; +        type["blocks"] = TriState.closing; +        type["code"] = TriState.closing; +        type["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,Ma)( +    return ref L line, +    return ref O an_object, +    return ref T type, +    return ref Ma dochead_make_aa +  ) { +    debug(asserts) { +      static assert(is(typeof(line)      == char[])); +      static assert(is(typeof(an_object) == string[string])); +      static assert(is(typeof(type)      == int[string])); +    } +    auto rgx = Rgx(); +    if (type["curly_table"] == TriState.on) { +      if (line.matchFirst(rgx.block_curly_table_close)) { +        debug(table) {                           // table (curly) close +          writeln(line); +        } +        type["blocks"] = TriState.closing; +        type["table"] = TriState.closing; +        type["curly_table"] = TriState.off; +      } else { +        debug(table) {                           // table +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n";           // build table array (or string) +      } +    } else if (type["curly_table_special_markup"] == TriState.on) { +      if (line.empty) { +        type["blocks"]                     = TriState.off; +        type["table"]                      = TriState.off; +        type["curly_table_special_markup"] = TriState.off; +        _table_closed_make_special_notation_table_( +          line, +          an_object, +          the_document_body_section, +          obj_cite_number, +          comp_obj_heading, +          cntr, +          type, +          dochead_make_aa +        ); +      } else { +        debug(table) { +          writeln(line); +        } +        an_object[an_object_key] ~= line ~= "\n"; +      } +    } else if (type["tic_table"] == TriState.on) { +      if (line.matchFirst(rgx.block_tic_close)) { +        debug(table) {                           // table (tic) close +          writeln(line); +        } +        type["blocks"] = TriState.closing; +        type["table"] = TriState.closing; +        type["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] type, +    return ref int         bib_entry, +    return ref string      biblio_entry_str_json, +    return ref string[]    biblio_arr_json +  ) { +    mixin SiSUbiblio; +    auto jsn = BibJsnStr(); +    auto rgx = Rgx(); +    if (line.matchFirst(rgx.heading_biblio)) { +      type["biblio_section"] = TriState.on; +      type["blurb_section"] = State.off; +      type["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_( +    char[]                           line, +    return ref string[string]        an_object, +    return ref ObjGenericComposite[] the_document_body_section, +    return ref int                   obj_cite_number, +    return ref ObjGenericComposite   _comp_obj_heading, +    return ref int                   cntr, +    return ref int[string]           type, +    string[string][string]           dochead_make_aa, +  ) { +      comp_obj_block = comp_obj_block.init; +      obj_cite_number = +        ocn_emit(type["ocn_status"]); +      auto comp_obj_location = +        node_construct.node_location_emitter( +          content_non_header, +          segment_anchor_tag_that_object_belongs_to, +          obj_cite_number, +          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", dochead_make_aa); +      an_object["substantive"]         = substantive_obj_misc_tuple[sObj.content]; +      comp_obj_block.ocn               = obj_cite_number; +      comp_obj_block.obj_cite_number   = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +      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)( +    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 int                      obj_cite_number, +    return ref ObjGenericComposite      _comp_obj_heading, +    return ref int                      cntr, +    return ref int[string]              type, +    string[string]                      obj_cite_number_poem, +    string[string][string]              dochead_make_aa, +  ) { +    assert( +      line.empty, +      "\nline should be empty:\n  \"" +      ~ line ~ "\"" +    ); +    assert( +      (type["blocks"] == TriState.closing), +      "code block status: closed" +    ); +    assertions_flag_types_block_status_none_or_closed(type); +    if (type["quote"] == TriState.closing) { +      obj_cite_number = +        ocn_emit(type["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_number, +          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_number, +          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, dochead_make_aa); +      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.use                        = "body"; +      comp_obj_block.is_of                      = "block"; +      comp_obj_block.is_a                       = "quote"; +      comp_obj_block.ocn                        = obj_cite_number; +      comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +      comp_obj_block.text                       = an_object["substantive"]; +      comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg]; +      comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star]; +      comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links]; +      the_document_body_section                 ~= comp_obj_block; +      type["blocks"]                            = TriState.off; +      type["quote"]                             = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +      ++cntr; +    } else if (type["group"] == TriState.closing) { +      obj_cite_number = +        ocn_emit(type["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_number, +          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_number, +          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, dochead_make_aa); +      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.use                        = "body"; +      comp_obj_block.is_of                      = "block"; +      comp_obj_block.is_a                       = "group"; +      comp_obj_block.ocn                        = obj_cite_number; +      comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +      comp_obj_block.text                       = an_object["substantive"]; +      comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg]; +      comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star]; +      comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links]; +      the_document_body_section                 ~= comp_obj_block; +      type["blocks"]                            = TriState.off; +      type["group"]                             = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +      ++cntr; +    } else if (type["block"] == TriState.closing) { +      obj_cite_number = ocn_emit(type["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_number, +          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_number, +          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, dochead_make_aa); +      an_object["substantive"]                  = substantive_obj_misc_tuple[sObj.content]; +      comp_obj_block                            = comp_obj_block.init; +      comp_obj_block.use                        = "body"; +      comp_obj_block.is_of                      = "block"; +      comp_obj_block.is_a                       = "block"; +      comp_obj_block.ocn                        = obj_cite_number; +      comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +      comp_obj_block.text                       = an_object["substantive"]; +      comp_obj_block.inline_notes_reg           = substantive_obj_misc_tuple[sObj.notes_reg]; +      comp_obj_block.inline_notes_star          = substantive_obj_misc_tuple[sObj.notes_star]; +      comp_obj_block.inline_links               = substantive_obj_misc_tuple[sObj.links]; +      the_document_body_section                 ~= comp_obj_block; +      type["blocks"]                            = TriState.off; +      type["block"]                             = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +      ++cntr; +    } else if (type["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_number, +          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_number, +          cntr, +          heading_ptr-1, +          an_object["is"] +        ); +      comp_obj_poem_ocn                         = comp_obj_poem_ocn.init; +      comp_obj_poem_ocn.use                     = "body"; +      comp_obj_poem_ocn.is_of                   = "block"; +      comp_obj_poem_ocn.is_a                    = "poem"; +      comp_obj_poem_ocn.ocn                     = obj_cite_number; +      comp_obj_poem_ocn.obj_cite_number         = (obj_cite_number_poem["start"], obj_cite_number_poem["end"]); +      comp_obj_poem_ocn.text                    = ""; +      the_document_body_section                 ~= comp_obj_poem_ocn; +      type["blocks"]                            = TriState.off; +      type["poem"]                              = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +    } else if (type["code"] == TriState.closing) { +      obj_cite_number = +        ocn_emit(type["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_number, +          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_number, +          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, dochead_make_aa); +      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.use                         = "body"; +      comp_obj_code.is_of                       = "block"; +      comp_obj_code.is_a                        = "code"; +      comp_obj_code.ocn                         = obj_cite_number; +      comp_obj_code.obj_cite_number             = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +      comp_obj_code.text                        = an_object["substantive"]; +      comp_obj_code.inline_notes_reg            = substantive_obj_misc_tuple[sObj.notes_reg]; +      comp_obj_code.inline_notes_star           = substantive_obj_misc_tuple[sObj.notes_star]; +      comp_obj_code.inline_links                = substantive_obj_misc_tuple[sObj.links]; +      the_document_body_section                 ~= comp_obj_code; +      type["blocks"]                            = TriState.off; +      type["code"]                              = TriState.off; +      object_reset(an_object); +      processing.remove("verse"); +      ++cntr; +    } else if (type["table"] == TriState.closing) { +      comp_obj_block = comp_obj_block.init; +      obj_cite_number = +        ocn_emit(type["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_number, +          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_number, +          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, dochead_make_aa); +      an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; +      comp_obj_block                            = comp_obj_block.init; +      comp_obj_block.ocn                        = obj_cite_number; +      comp_obj_block.obj_cite_number            = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +      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; +      type["blocks"]                            = TriState.off; +      type["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  type, +    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(type)            == int[string])); +      static assert(is(typeof(opt_action)      == bool[string])); +    } +    auto rgx = Rgx(); +    if (auto m = line.match(rgx.book_index)) { +      /+ match book_index +/ +      debug(bookindexmatch) {                       // book index +        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 +/ +      type["book_index"] = State.on; +      if (opt_action["backmatter"] && opt_action["section_bookindex"]) { +        book_idx_tmp = m.captures[1].to!string; +        debug(bookindexmatch) {                       // book index +          writefln( +            "* [bookindex] %s\n", +            book_idx_tmp, +          ); +        } +      } +    } else if (type["book_index"] == State.on )  { +      /+ book_index flag set +/ +      if (auto m = line.match(rgx.book_index_close))  { +        type["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) {                     // book index +            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     dochead_make_identify_unmarked_headings, +    return ref H heading_match_str, +    return ref R heading_match_rgx, +    return ref T type +  ) { +    debug(asserts) { +      static assert(is(typeof(line)                                    == char[])); +      static assert(is(typeof(dochead_make_identify_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(type)                                    == int[string])); +    } +    auto rgx = Rgx(); +    if ((dochead_make_identify_unmarked_headings.length > 2) +    && (type["make_headings"] == State.off)) { +      /+ headings found +/ +      debug(headingsfound) { +        writeln(dochead_make_identify_unmarked_headings); +      } +      char[][] make_headings_spl = +        (cast(char[]) dochead_make_identify_unmarked_headings) +          .split(rgx.make_heading_delimiter); +      debug(headingsfound) { +        writeln(make_headings_spl.length); +        writeln(make_headings_spl); +      } +      switch (make_headings_spl.length) { +      case 7 : +        if (!empty(make_headings_spl[6])) { +          heading_match_str["h_4"] = +            "^(" ~ make_headings_spl[6].to!string ~ ")"; +          heading_match_rgx["h_4"] = +            regex(heading_match_str["h_4"]); +        } +        goto case; +      case 6 : +        if (!empty(make_headings_spl[5])) { +          heading_match_str["h_3"] = +            "^(" ~ make_headings_spl[5].to!string ~ ")"; +          heading_match_rgx["h_3"] = +            regex(heading_match_str["h_3"]); +        } +        goto case; +      case 5 : +        if (!empty(make_headings_spl[4])) { +          heading_match_str["h_2"] = +            "^(" ~ make_headings_spl[4].to!string ~ ")"; +          heading_match_rgx["h_2"] = +            regex(heading_match_str["h_2"]); +        } +        goto case; +      case 4 : +        if (!empty(make_headings_spl[3])) { +          heading_match_str["h_1"] = +            "^(" ~ make_headings_spl[3].to!string ~ ")"; +          heading_match_rgx["h_1"] = +            regex(heading_match_str["h_1"]); +        } +        goto case; +      case 3 : +        if (!empty(make_headings_spl[2])) { +          heading_match_str["h_D"] = +            "^(" ~ make_headings_spl[2].to!string ~ ")"; +          heading_match_rgx["h_D"] = +            regex(heading_match_str["h_D"]); +        } +        goto case; +      case 2 : +        if (!empty(make_headings_spl[1])) { +          heading_match_str["h_C"] = +            "^(" ~ make_headings_spl[1].to!string ~ ")"; +          heading_match_rgx["h_C"] = +            regex(heading_match_str["h_C"]); +        } +        goto case; +      case 1 : +        if (!empty(make_headings_spl[0])) { +          heading_match_str["h_B"] = +            "^(" ~ make_headings_spl[0].to!string ~ ")"; +          heading_match_rgx["h_B"] = +            regex(heading_match_str["h_B"]); +        } +        break; +      default: +        break; +      } +      type["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 type +  ) { +    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(type)              == int[string])); +    } +    if ((type["make_headings"] == State.on) +    && ((line_occur["para"] == State.off) +    && (line_occur["heading"] == State.off)) +    && ((type["para"] == State.off) +    && (type["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,Me)( +    return ref 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  type, +    return ref Me dochead_meta_aa, +  ) { +    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(type)            == int[string])); +      static assert(is(typeof(dochead_meta_aa) == string[string][string])); +    } +    auto rgx = Rgx(); +    if (auto m = line.match(rgx.heading)) { +      /+ heading match +/ +      type["heading"] = State.on; +      if (line.match(rgx.heading_seg_and_above)) { +        type["biblio_section"] = State.off; +        type["glossary_section"] = State.off; +        type["blurb_section"] = State.off; +      } +      type["para"] = State.off; +      ++line_occur["heading"]; +      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": +        an_object[an_object_key]=(an_object[an_object_key]) +          .replaceFirst(rgx.variable_doc_title, +            (dochead_meta_aa["title"]["full"] ~ ",")) +          .replaceFirst(rgx.variable_doc_author, +            dochead_meta_aa["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) {                         // heading +        writeln(line.strip); +      } +    } +  } +  void _para_match_(L,O,K,I,B,T,C)( +    return ref L  line, +    return ref O  an_object, +    return ref K  an_object_key, +    return ref I  indent, +    return ref B  bullet, +    return ref T  type, +    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(type)          == int[string])); +      static assert(is(typeof(line_occur)    == int[string])); +    } +    auto rgx = Rgx(); +    if (line_occur["para"] == State.off) { +      line = font_faces_line(line); +      /+ para matches +/ +      type["para"] = State.on; +      an_object[an_object_key] ~= line;        // body_nugget +      indent=[ +        "hang_position" : 0, +        "base_position" : 0, +      ]; +      bullet = false; +      if (auto m = line.matchFirst(rgx.para_indent)) { +        debug(paraindent) {                    // para indent +          writeln(line); +        } +        indent["hang_position"] = (m.captures[1]).to!int; +        indent["base_position"] = 0; +      } else if (line.matchFirst(rgx.para_bullet)) { +        debug(parabullet) {                    // para bullet +          writeln(line); +        } +        bullet = true; +      } else if (auto m = line.matchFirst(rgx.para_indent_hang)) { +        debug(paraindenthang) {                // para indent hang +          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) {              // para bullet indent +          writeln(line); +        } +        indent=[ +          "hang_position" : (m.captures[1]).to!int, +          "base_position" : 0, +        ]; +        bullet = true; +      } +      ++line_occur["para"]; +    } +  } +  auto font_faces_line(T)( +    return ref T  textline, +  ) { +    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, +  ) { +    auto rgx = Rgx(); +    table_object.use               = "body"; +    table_object.is_of             = "block"; +    table_object.is_a              = "table"; +    table_object.inline_notes_reg  = false; +    table_object.inline_notes_star = false; +    table_object.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, +  ) { +    auto rgx = Rgx(); +    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 (idx_r == 1 && col.match(rgx.numeric_col)) { +          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, +  ) { +    auto rgx = Rgx(); +    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, +  ) { +    auto rgx = Rgx(); +    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, +  ) { +    auto rgx = Rgx(); +    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 +/ +  struct OCNemitter { +    int obj_cite_number, obj_cite_number_; +    int ocn_emitter(int ocn_status_flag) +    in { assert(ocn_status_flag <= 3); } +    body { +      if (ocn_status_flag == 3) { +        obj_cite_number = obj_cite_number_ = 1; +      } else { +        obj_cite_number=(ocn_status_flag == 0) +        ? ++obj_cite_number_ +        : 0; +      } +      assert(obj_cite_number >= 0); +      return obj_cite_number; +    } +    invariant() { +    } +  } +  /+ +/ +  struct ObjInlineMarkupMunge { +    string[string] obj_txt; +    int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus; +    string asterisks_; +    string obj_txt_out, tail, note; +    auto rgx = Rgx(); +    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; +    } +    string url_links(Ot)(Ot obj_txt_in) { +      debug(asserts) { +        static assert(is(typeof(obj_txt_in) == string)); +      } +      auto mng = InlineMarkup(); +      obj_txt_in = obj_txt_in.replaceAll(rgx.inline_mono, (mng.mono ~ "{$1}" ~ mng.mono)); +      /+ url matched +/ +      if (obj_txt_in.match(rgx.inline_url_generic)) { +        /+ link: naked url: http://url +/ +        if (obj_txt_in.match(rgx.inline_link_naked_url)) { +          obj_txt_in = (obj_txt_in).replaceAll( +              rgx.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.inline_link_endnote_url_helper)) { +          obj_txt_in = (obj_txt_in).replaceAll( +            rgx.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") +          ); +          obj_txt_in = (obj_txt_in).replaceAll( +            rgx.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.inline_link_markup_regular)) { +          obj_txt_in = (obj_txt_in).replaceAll( +            rgx.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; +    } +    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; +      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_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, +      ); +      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; +      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) +        ); +      /+ url matched +/ +      if (obj_txt_in.match(rgx.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], +        urls, +      ); +      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.obj_cite_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.obj_cite_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() { +    } +  } +  struct ObjInlineMarkup { +    auto rgx = Rgx(); +    auto munge = ObjInlineMarkupMunge(); +    string[string] obj_txt; +    auto obj_inline_markup_and_anchor_tags_and_misc(O,K,Ma)( +      O  obj_, +      K  obj_key_, +      Ma dochead_make_aa +    ) +    in { +      debug(asserts) { +        static assert(is(typeof(obj_)            == string[string])); +        static assert(is(typeof(obj_key_)        == string)); +        static assert(is(typeof(dochead_make_aa) == string[string][string])); +      } +    } +    body { +      obj_txt["munge"] = obj_[obj_key_].dup; +      obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`))) +      ? obj_txt["munge"] +      : strip(obj_txt["munge"]); +      static __gshared string[] 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; +      switch (obj_["is"]) { +      case "heading": +        static __gshared string anchor_tag = ""; +        obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, dochead_make_aa); +        obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"]); +        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["links"]      = x[3]; +        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"], +      ); +      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,Ma,Ts,Ta,X,Toc)( +      O            obj_, +      Ma           dochead_make_aa, +      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(dochead_make_aa)                           == string[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; +      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.use                   = "frontmatter"; +        comp_obj_toc.is_of                 = "para"; +        comp_obj_toc.is_a                  = "toc"; +        comp_obj_toc.ocn                   = 0; +        comp_obj_toc.obj_cite_number       = ""; +        comp_obj_toc.indent_hang           = indent["hang_position"]; +        comp_obj_toc.indent_base           = indent["base_position"]; +        comp_obj_toc.bullet                = false; +        comp_obj_toc.text                  = toc_txt_.to!string.strip; +        comp_obj_toc.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.use                   = "frontmatter"; +        comp_obj_toc.is_of                 = "para"; +        comp_obj_toc.is_a                  = "toc"; +        comp_obj_toc.ocn                   = 0; +        comp_obj_toc.obj_cite_number       = ""; +        comp_obj_toc.indent_hang           = indent["hang_position"]; +        comp_obj_toc.indent_base           = indent["base_position"]; +        comp_obj_toc.bullet                = false; +        comp_obj_toc.text                  = "Table of Contents"; +        comp_obj_toc.inline_links          = true; +        the_table_of_contents_section["scroll"] ~= comp_obj_toc; +      } +      comp_obj_toc                       = comp_obj_toc.init; +      comp_obj_toc.use                   = "frontmatter"; +      comp_obj_toc.is_of                 = "para"; +      comp_obj_toc.is_a                  = "toc"; +      comp_obj_toc.ocn                   = 0; +      comp_obj_toc.obj_cite_number       = ""; +      comp_obj_toc.bullet                = false; +      comp_obj_toc.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.indent_hang             = indent["hang_position"]; +        comp_obj_toc.indent_base             = indent["base_position"]; +        comp_obj_toc.text                    = toc_txt_.to!string.strip; +        comp_obj_toc.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.indent_hang             = indent["hang_position"]; +        comp_obj_toc.indent_base             = indent["base_position"]; +        comp_obj_toc.text                    = toc_txt_.to!string.strip; +        comp_obj_toc.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.indent_hang             = indent["hang_position"]; +        comp_obj_toc.indent_base             = indent["base_position"]; +        comp_obj_toc.text                    = toc_txt_.to!string.strip; +        comp_obj_toc.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.indent_hang             = indent["hang_position"]; +        comp_obj_toc.indent_base             = indent["base_position"]; +        comp_obj_toc.text                    = toc_txt_.to!string.strip; +        comp_obj_toc.inline_links            = true; +        the_table_of_contents_section["seg"] ~= comp_obj_toc; +        break; +      default: +        break; +      } +      return the_table_of_contents_section; +    } +    invariant() { +    } +  private: +    static string _configured_auto_heading_numbering_and_segment_anchor_tags(M,O,Ma)( +      M  munge_, +      O  obj_, +      Ma dochead_make_aa +    ) { +      debug(asserts) { +        static assert(is(typeof(munge_)          == string)); +        static assert(is(typeof(obj_)            == string[string])); +        static assert(is(typeof(dochead_make_aa) == string[string][string])); +      } +      if (dochead_make_aa["make"]["num_top"].length > 0) { +        static __gshared int heading_num_top_level=9; +        static __gshared int heading_num_depth=2; +        static __gshared int heading_num_0 = 0; +        static __gshared int heading_num_1 = 0; +        static __gshared int heading_num_2 = 0; +        static __gshared int heading_num_3 = 0; +        static __gshared string heading_number_auto_composite = ""; +        if (heading_num_top_level==9) { +          if (dochead_make_aa["make"]["num_depth"].length > 0) { +            heading_num_depth = dochead_make_aa["make"]["num_depth"].to!uint; +          } +          switch (dochead_make_aa["make"]["num_top"]) { +          case "A": +            break; +          case "B": +            heading_num_top_level=1; +            break; +          case "C": +            heading_num_top_level=2; +            break; +          case "D": +            heading_num_top_level=3; +            break; +          case "1": +            heading_num_top_level=4; +            break; +          case "2": +            heading_num_top_level=5; +            break; +          case "3": +            heading_num_top_level=6; +            break; +          case "4": +            heading_num_top_level=7; +            break; +          default: +            break; +          } +        } +        /+ num_depth minimum 0 +           (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement +/ +        if ( +          heading_num_top_level +          > obj_["lev_markup_number"].to!uint +        ) { +          heading_num_1 = 0; +          heading_num_2 = 0; +          heading_num_3 = 0; +        } else if ( +          heading_num_top_level +          == obj_["lev_markup_number"].to!uint +        ) { +          heading_num_0 ++; +          heading_num_1 = 0; +          heading_num_2 = 0; +          heading_num_3 = 0; +        } else if ( +          heading_num_top_level +          == (obj_["lev_markup_number"].to!uint - 1) +        ) { +          heading_num_1 ++; +          heading_num_2 = 0; +          heading_num_3 = 0; +        } else if ( +          heading_num_top_level +          == (obj_["lev_markup_number"].to!uint - 2) +        ) { +          heading_num_2 ++; +          heading_num_3 = 0; +        } else if ( +          heading_num_top_level +          == (obj_["lev_markup_number"].to!uint - 3) +        ) { +          heading_num_3 ++; +        } +        if (heading_num_3 > 0) { +          heading_number_auto_composite = +            (heading_num_depth == 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 = +            ((heading_num_depth >= 2) +            && (heading_num_depth <= 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 = +            ((heading_num_depth >= 1) +            && (heading_num_depth <= 3)) +            ? ( heading_num_0.to!string ~ "." +                 ~ heading_num_1.to!string +               ) +            : ""; +        } else if (heading_num_0 > 0) { +          heading_number_auto_composite = +            ((heading_num_depth >= 0) +            && (heading_num_depth <= 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 >= heading_num_top_level)) { +          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 string _make_segment_anchor_tags_if_none_provided(M,Lv)(M munge_, Lv lev_) { +      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] ~ " "); +          } 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" +          static __gshared int 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(), +            "; obj_cite_number: ", oa_j["obj_cite_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["obj_cite_number"] = _comp_obj_heading.ocn; +        oa_j.object["lev_markup_number"] = _comp_obj_heading.heading_lev_markup; +        oa_j.object["lev_collapsed_number"] = _comp_obj_heading.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_obj_cite_number"] = _comp_obj_heading.parent_ocn; +      oa_j.object["parent_lev_markup_number"] = _comp_obj_heading.parent_lev_markup; +      _obj_attrib = oa_j.toString(); +      return _obj_attrib; +    } +  } +  /+ +/ +  struct BookIndexNuggetHash { +    string main_term, sub_term, sub_term_bits; +    int obj_cite_number_offset, obj_cite_number_endpoint; +    string[] obj_cite_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_number, +      S  segment_anchor_tag, +    ) +    in { +      debug(asserts) { +        static assert(is(typeof(bookindex_section) == string)); +        static assert(is(typeof(obj_cite_number)   == int)); +      } +      debug(bookindexraw) { +        if (!bookindex_section.empty) { +          writeln( +            "* [bookindex] ", +            "[", obj_cite_number.to!string, ": ", segment_anchor_tag, "] ", bookindex_section +          ); +        } +      } +    } +    body { +      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_obj_cite_numbers_match) +          ) { +            main_term = m.captures[1].strip; +            obj_cite_number_offset = m.captures[2].to!int; +            obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset); +            obj_cite_numbers ~= (obj_cite_number.to!string ~ "-" ~ to!string(obj_cite_number_endpoint) +            ~ ":" ~ segment_anchor_tag); +          } else { +            main_term = bi_main_term_and_rest[0].strip; +            obj_cite_numbers ~= obj_cite_number.to!string +            ~ ":" ~ segment_anchor_tag; +          } +          bi[main_term]["_a"] ~= obj_cite_numbers; +          obj_cite_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_obj_cite_number_offset_split +              ); +            foreach (sub_terms_bits; bi_sub_terms_split_arr) { +              if (auto m = sub_terms_bits.match(rgx.bi_term_and_obj_cite_numbers_match)) { +                sub_term = m.captures[1].strip; +                obj_cite_number_offset = m.captures[2].to!int; +                obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset); +                obj_cite_numbers ~= (obj_cite_number.to!string ~ " - " ~ to!string(obj_cite_number_endpoint) +                ~ ":" ~ segment_anchor_tag); +              } else { +                sub_term = sub_terms_bits.strip; +                obj_cite_numbers ~= to!string(obj_cite_number) +                ~ ":" ~ segment_anchor_tag; +              } +              if (!empty(sub_term)) { +                bi[main_term][sub_term] ~= obj_cite_numbers; +              } +              obj_cite_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; +    auto rgx = Rgx(); +    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_number, +      B  opt_action, +    ) { +      debug(asserts) { +        static assert(is(typeof(bookindex_unordered_hashes)                == string[][string][string])); +        static assert(is(typeof(obj_cite_number)                           == int)); +        static assert(is(typeof(opt_action)                                == bool[string])); +      } +      mixin SiSUnode; +      mixin InternalMarkup; +      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_.use                   = "backmatter"; +        comp_obj_heading_.is_of                 = "para"; +        comp_obj_heading_.is_a                  = "heading"; +        comp_obj_heading_.text                  = "Book Index"; +        comp_obj_heading_.ocn                   = 0; +        comp_obj_heading_.obj_cite_number       = ""; +        comp_obj_heading_.segment_anchor_tag    = "_part_book_index"; +        comp_obj_heading_.marked_up_level       = "B"; +        comp_obj_heading_.heading_lev_markup    = 1; +        comp_obj_heading_.heading_lev_collapsed = 1; +        comp_obj_heading_.parent_ocn            = 1; +        comp_obj_heading_.parent_lev_markup     = 0; +        comp_obj_heading.inline_links           = true; +        bookindex_section["scroll"]             ~= comp_obj_heading_; +        bookindex_section["seg"]                ~= comp_obj_heading_; +        ++obj_cite_number; +        ++mkn; +        comp_obj_heading_                       = comp_obj_heading_.init; +        comp_obj_heading_.use                   = "backmatter"; +        comp_obj_heading_.is_of                 = "para"; +        comp_obj_heading_.is_a                  = "heading"; +        comp_obj_heading_.text                  = "Index"; +        comp_obj_heading_.ocn                   = 0; +        comp_obj_heading_.obj_cite_number       = ""; +        comp_obj_heading_.segment_anchor_tag    = "bookindex"; +        comp_obj_heading_.marked_up_level       = "1"; +        comp_obj_heading_.heading_lev_markup    = 4; +        comp_obj_heading_.heading_lev_collapsed = 2; +        comp_obj_heading_.parent_ocn            = 1; +        comp_obj_heading_.parent_lev_markup     = 0; +        comp_obj_heading.inline_links           = false; +        comp_obj_heading_.anchor_tags           = ["bookindex"]; +        bookindex_section["scroll"]             ~= comp_obj_heading_; +        bookindex_section["seg"]                ~= comp_obj_heading_; +        ++obj_cite_number; +        ++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.use                   = "backmatter"; +          comp_obj_para.is_of                 = "para"; +          comp_obj_para.is_a                  = "bookindex"; +          comp_obj_para.text                  = bi_tmp_scroll.to!string.strip; +          comp_obj_para.ocn                   = obj_cite_number; +          comp_obj_para.obj_cite_number       = (obj_cite_number==0) ? "" : to!string(obj_cite_number); +          comp_obj_para.anchor_tags           = bi_tmp_tags; +          comp_obj_para.indent_hang           = 0; +          comp_obj_para.indent_base           = 1; +          comp_obj_para.bullet                = false; +          comp_obj_para.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; +          ++obj_cite_number; +          ++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_.ocn                   = 0; +        comp_obj_heading_.obj_cite_number       = ""; +        comp_obj_heading_.marked_up_level       = "B"; +        comp_obj_heading_.heading_lev_markup    = 1; +        comp_obj_heading_.heading_lev_collapsed = 1; +        comp_obj_heading_.parent_ocn            = 1; +        comp_obj_heading_.parent_lev_markup     = 0; +        bookindex_section["scroll"]             ~= comp_obj_heading_; +        bookindex_section["seg"]                ~= comp_obj_heading_; +      } +      auto t = tuple(bookindex_section, obj_cite_number); +      return t; +    } +  } +  /+ +/ +  struct NotesSection { +    string[string] object_notes; +    int previous_count; +    int mkn; +    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].is_a == "para") +      || (contents_am[cntr].is_a == "heading") +      || (contents_am[cntr].is_a == "quote") +      || (contents_am[cntr].is_a == "group") +      || (contents_am[cntr].is_a == "block") +      || (contents_am[cntr].is_a == "verse")); +      assert(cntr >= previous_count); +      previous_count=cntr; +      assert( +        (contents_am[cntr].text).match( +        rgx.inline_notes_delimiter_al_regular_number_note) +      ); +    } +    body { +      mixin InternalMarkup; +      auto mkup = InlineMarkup(); +      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) +        } +        // TODO NEXT 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( +      int            obj_cite_number, +      bool[string]   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_.use                   = "backmatter"; +        comp_obj_heading_.is_of                 = "para"; +        comp_obj_heading_.is_a                  = "heading"; +        comp_obj_heading_.text                  = "Endnotes"; +        comp_obj_heading_.ocn                   = 0; +        comp_obj_heading_.obj_cite_number       = ""; +        comp_obj_heading_.segment_anchor_tag    = "_part_endnotes"; +        comp_obj_heading_.marked_up_level       = "B"; +        comp_obj_heading_.heading_lev_markup    = 1; +        comp_obj_heading_.heading_lev_collapsed = 1; +        comp_obj_heading_.parent_ocn            = 1; +        comp_obj_heading_.parent_lev_markup     = 0; +        the_endnotes_section                    ~= comp_obj_heading_; +        ++obj_cite_number; +        ++mkn; +        comp_obj_heading_                       = comp_obj_heading_.init; +        comp_obj_heading_.use                   = "backmatter"; +        comp_obj_heading_.is_of                 = "para"; +        comp_obj_heading_.is_a                  = "heading"; +        comp_obj_heading_.text                  = "Endnotes"; +        comp_obj_heading_.ocn                   = 0; +        comp_obj_heading_.obj_cite_number       = ""; +        comp_obj_heading_.segment_anchor_tag    = "endnotes"; +        comp_obj_heading_.marked_up_level       = "1"; +        comp_obj_heading_.heading_lev_markup    = 4; +        comp_obj_heading_.heading_lev_collapsed = 2; +        comp_obj_heading_.parent_ocn            = 1; +        comp_obj_heading_.parent_lev_markup     = 0; +        comp_obj_heading_.anchor_tags           = ["endnotes"]; +        the_endnotes_section                    ~= comp_obj_heading_; +        ++obj_cite_number; +        ++mkn; +      } else { +        comp_obj_heading_                       = comp_obj_heading_.init; +        comp_obj_heading_.use                   = "empty"; +        comp_obj_heading_.is_of                 = "para"; +        comp_obj_heading_.is_a                  = "heading"; +        comp_obj_heading_.text                  = "(skip) there are no Endnotes"; +        comp_obj_heading_.ocn                   = 0; +        comp_obj_heading_.obj_cite_number       = ""; +        comp_obj_heading_.marked_up_level       = "B"; +        comp_obj_heading_.heading_lev_markup    = 1; +        comp_obj_heading_.heading_lev_collapsed = 1; +        comp_obj_heading_.parent_ocn            = 1; +        comp_obj_heading_.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_.use                   = "backmatter"; +        comp_obj_endnote_.is_of                 = "para"; +        comp_obj_endnote_.is_a                  = "endnote"; +        comp_obj_endnote_.ocn                   = 0; +        comp_obj_heading_.obj_cite_number       = ""; +        comp_obj_endnote_.indent_hang           = 0; +        comp_obj_endnote_.indent_base           = 0; +        comp_obj_endnote_.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_.anchor_tags         = [ endnotes_["anchor"][i] ]; +          comp_obj_endnote_.inline_links        = true; +          comp_obj_endnote_.text                = endnote.strip; +          the_endnotes_section                  ~= comp_obj_endnote_; +        } +      } +      auto t = tuple(the_endnotes_section, obj_cite_number); +      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_number; +    int[string] p_; // p_ parent_ +    auto rgx = Rgx(); +    ObjGenericComposite node_location_emitter(Lv,Ta,N,C,P,I)( +      Lv lev_markup_number, +      Ta segment_anchor_tag, +      N  obj_cite_number_, +      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_number_)   == 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_number_.to!int >= 0); +    } +    body { +      assert(is_ != "heading"); // should not be necessary +      assert(obj_cite_number_.to!int >= 0); // should not be necessary +      int obj_cite_number = obj_cite_number_.to!int; +      if (lv7 > State.off) { +        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_4; +        p_["obj_cite_number"] = lv7; +      } else if (lv6 > State.off) { +        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3; +        p_["obj_cite_number"] = lv6; +      } else if (lv5 > State.off) { +        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2; +        p_["obj_cite_number"] = lv5; +      } else { +        p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1; +        p_["obj_cite_number"] = lv4; +      } +      ObjGenericComposite comp_obj_location; +      comp_obj_location                       = comp_obj_location.init; +      comp_obj_location.is_a                  = is_; +      comp_obj_location.ocn                   = obj_cite_number_; +      comp_obj_location.segment_anchor_tag    = segment_anchor_tag.to!string; +      comp_obj_location.parent_ocn            = p_["obj_cite_number"]; +      comp_obj_location.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.parent_lev_markup >= 4); +      assert(comp_obj_location.parent_lev_markup <= 7); +      assert(comp_obj_location.parent_ocn >= 0); +      return comp_obj_location; +    } +    invariant() { +    } +    ObjGenericComposite node_emitter_heading(T,L,Lm,Lc,Ta,N,C,P,LA,I,PSn,fNr,fNs,fL)( +      T   _text, +      L   lev, +      Lm  lev_markup_number, +      Lc  lev_collapsed_number, +      Ta  segment_anchor_tag, +      N   obj_cite_number_, +      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_number_)     == 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(to!int(obj_cite_number_) >= 0); +      assert( +        lev_markup_number.match(rgx.levels_numbered), +        ("not a valid heading level: " ~ lev_markup_number ~ " at " ~ obj_cite_number_.to!string) +      ); +      if (lev_markup_number.match(rgx.levels_numbered)) { +        if (lev_markup_number.to!int == 0) { +          assert(obj_cite_number_.to!int == 1); +        } +      } +    } +    body { +      int obj_cite_number = obj_cite_number_.to!int; +      switch (lev_markup_number.to!int) { +      case 0: +        lv = DocStructMarkupHeading.h_sect_A; +        lv0 = obj_cite_number; +        lv1=0; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; +        p_["lev_markup_number"] = 0; +        p_["obj_cite_number"] = 0; +        break; +      case 1: +        lv = DocStructMarkupHeading.h_sect_B; +        lv1 = obj_cite_number; +        lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; +        p_["lev_markup_number"] = +          DocStructMarkupHeading.h_sect_A; +        p_["obj_cite_number"] = lv0; +        break; +      case 2: +        lv = DocStructMarkupHeading.h_sect_C; +        lv2 = obj_cite_number; +        lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; +        p_["lev_markup_number"] = +          DocStructMarkupHeading.h_sect_B; +        p_["obj_cite_number"] = lv1; +        break; +      case 3: +        lv = DocStructMarkupHeading.h_sect_D; +        lv3=obj_cite_number; +        lv4=0; lv5=0; lv6=0; lv7=0; +        p_["lev_markup_number"] = +          DocStructMarkupHeading.h_sect_C; +        p_["obj_cite_number"] = lv2; +        break; +      case 4: +        lv = DocStructMarkupHeading.h_text_1; +        lv4 = obj_cite_number; +        lv5=0; lv6=0; lv7=0; +        if (lv3 > State.off) { +          p_["lev_markup_number"] = +            DocStructMarkupHeading.h_sect_D; +          p_["obj_cite_number"] = lv3; +        } else if (lv2 > State.off) { +          p_["lev_markup_number"] = +            DocStructMarkupHeading.h_sect_C; +          p_["obj_cite_number"] = lv2; +        } else if (lv1 > State.off) { +          p_["lev_markup_number"] = +            DocStructMarkupHeading.h_sect_B; +          p_["obj_cite_number"] = lv1; +        } else { +          p_["lev_markup_number"] = +            DocStructMarkupHeading.h_sect_A; +          p_["obj_cite_number"] = lv0; +        } +        break; +      case 5: +        lv = DocStructMarkupHeading.h_text_2; +        lv5 = obj_cite_number; +        lv6=0; lv7=0; +        p_["lev_markup_number"] = +          DocStructMarkupHeading.h_text_1; +        p_["obj_cite_number"] = lv4; +        break; +      case 6: +        lv = DocStructMarkupHeading.h_text_3; +        lv6 = obj_cite_number; +        lv7=0; +        p_["lev_markup_number"] = +          DocStructMarkupHeading.h_text_2; +        p_["obj_cite_number"] = lv5; +        break; +      case 7: +        lv = DocStructMarkupHeading.h_text_4; +        lv7 = obj_cite_number; +        p_["lev_markup_number"] = +          DocStructMarkupHeading.h_text_3; +        p_["obj_cite_number"] = lv6; +        break; +      default: +        break; +      } +      ObjGenericComposite _comp_obj_heading_; +      _comp_obj_heading_                           = _comp_obj_heading_.init; +      _comp_obj_heading_.use                       = "body"; +      _comp_obj_heading_.is_of                     = "para"; +      _comp_obj_heading_.is_a                      = "heading"; +      _comp_obj_heading_.text                      = _text.to!string.strip; +      _comp_obj_heading_.ocn                       = obj_cite_number_; +      _comp_obj_heading_.obj_cite_number           = (obj_cite_number==0) ? "" : obj_cite_number.to!string; +      _comp_obj_heading_.segment_anchor_tag        = segment_anchor_tag.to!string; +      _comp_obj_heading_.marked_up_level           = lev; +      _comp_obj_heading_.heading_lev_markup        = (!(lev_markup_number.empty) ? lev_markup_number.to!int : 0); +      _comp_obj_heading_.heading_lev_collapsed     = (!(lev_collapsed_number.empty) ? lev_collapsed_number.to!int : 0); +      _comp_obj_heading_.parent_ocn                = p_["obj_cite_number"]; +      _comp_obj_heading_.parent_lev_markup         = p_["lev_markup_number"]; +      _comp_obj_heading_.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_.inline_notes_reg          = flag_notes_reg; +      _comp_obj_heading_.inline_notes_star         = flag_notes_star; +      _comp_obj_heading_.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_.parent_lev_markup <= 7); +      assert(_comp_obj_heading_.parent_ocn >= 0); +      if (lev_markup_number.match(rgx.levels_numbered_headings)) { +        assert(_comp_obj_heading_.heading_lev_markup <= 7); +        assert(_comp_obj_heading_.ocn >= 0); +        if (_comp_obj_heading_.parent_lev_markup > 0) { +          assert(_comp_obj_heading_.parent_lev_markup < _comp_obj_heading_.heading_lev_markup); +          if (_comp_obj_heading_.ocn != 0) { +            assert(_comp_obj_heading_.parent_ocn < _comp_obj_heading_.ocn); +          } +        } +        if (_comp_obj_heading_.heading_lev_markup == 0) { +          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A); +        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_B) { +          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A); +        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_C) { +          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_B); +        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_D) { +          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_C); +        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_1) { +          assert(_comp_obj_heading_.parent_lev_markup <= DocStructMarkupHeading.h_sect_D); +        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_2) { +          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_1); +        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_3) { +          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_2); +        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_4) { +          assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_3); +        } else if  (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_5) { +        } +      } +      return _comp_obj_heading_; +    } +    invariant() { +    } +  } +  /+ abstraction functions emitters ↑ +/ +  /+ ↓ abstraction functions assertions +/ +  auto 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; +    } +  } +  auto assertions_flag_types_block_status_none_or_closed(T)(T type) { +    debug(asserts) { +      static assert(is(typeof(type) == int[string])); +    } +    assert( +      (type["code"] == TriState.off) +      || (type["code"] == TriState.closing), +      "code block status: off or closing"); +    assert( +      (type["poem"] == TriState.off) +      || (type["poem"] == TriState.closing), +      "poem status: off or closing"); +    assert( +      (type["table"] == TriState.off) +      || (type["table"] == TriState.closing), +      "table status: off or closing"); +    assert( +      (type["group"] == TriState.off) +      || (type["group"] == TriState.closing), +      "group block status: off or closing"); +    assert( +      (type["block"] == TriState.off) +      || (type["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/sdp/meta/metadoc_summary.d b/src/sdp/meta/metadoc_summary.d new file mode 100644 index 0000000..e2b85b8 --- /dev/null +++ b/src/sdp/meta/metadoc_summary.d @@ -0,0 +1,81 @@ +module sdp.meta.metadoc_summary; +template SiSUabstractionSummary() { +  auto SiSUabstractionSummary(S,T)( +    auto return ref const S  doc_abstraction, +    auto return ref T        doc_matters, +  ) { +    import +      sdp.meta.defaults, +      sdp.meta.rgx; +    import +      std.array, +      std.exception, +      std.stdio, +      std.regex, +      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_obj_cite_number" : "NA [debug \"checkdoc\" not run]", +      ]; +      foreach (k; doc_matters.keys_seq.seg) { +        foreach (obj; doc_abstraction[k]) { +          if (obj.use != "empty") { +            if (!empty(obj.obj_cite_number)) { +              check["last_obj_cite_number"] = obj.obj_cite_number; +            } +          } +        } +      } +      auto min_repeat_number = 66; +      auto char_repeat_number = (doc_matters.dochead_meta["title"]["full"].length +        + doc_matters.dochead_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(%s: %s)\n%s", +        markup.repeat_character_by_number_provided("-", char_repeat_number), +        doc_matters.dochead_meta["title"]["full"], +        doc_matters.dochead_meta["creator"]["author"], +        doc_matters.source_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 obj_cite_number:", +        to!int(check["last_obj_cite_number"]), +        "length endnotes:", +        (doc_abstraction["endnotes"].length > 1) +        ? (to!int(doc_abstraction["endnotes"].length)) +        : 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, +        "length blurb:", +        (doc_abstraction["blurb"].length > 1) +        ? (to!int(doc_abstraction["blurb"].length)) +        : 0, +        __FILE__, +        __LINE__, +        markup.repeat_character_by_number_provided("-", min_repeat_number), +      ); +    } +  } +} diff --git a/src/sdp/meta/object_setter.d b/src/sdp/meta/object_setter.d new file mode 100644 index 0000000..385c3d2 --- /dev/null +++ b/src/sdp/meta/object_setter.d @@ -0,0 +1,65 @@ +/++ +  object setter: +  setting of sisu objects for downstream processing +  meta_object_setter.d ++/ +module sdp.meta.object_setter; +template ObjectSetter() { +  /+ structs +/ +  struct HeadingAttrib { +    string lev                            = "9"; +    int    heading_lev_markup             = 9; +    int    heading_lev_collapsed          = 9; +    int[]  closes_lev_collapsed           = []; +    int[]  closes_lev_markup              = []; +    int    array_ptr                      = 0; +    int    heading_array_ptr_segments     = 0; +  } +  struct ObjGenericComposite { +    // size_t id; +    string                 use                          = ""; +    string                 is_of                        = ""; +    string                 is_a                         = ""; +    string                 text                         = ""; +    string                 obj_cite_number              = ""; +    string[]               anchor_tags                  = []; +    int                    indent_base                  = 0; +    int                    indent_hang                  = 0; +    bool                   bullet                       = false; +    bool                   inline_links                 = false; +    bool                   inline_notes_reg             = false; +    bool                   inline_notes_star            = false; +    string                 language                     = ""; // not implemented, consider +    string                 code_block_syntax            = ""; +    int                    table_number_of_columns      = 0; +    double[]               table_column_widths          = []; +    string[]               table_column_aligns          = []; +    bool                   table_heading                = false; +    bool                   table_walls                  = false; // not implemented +    int                    ocn                          = 0; +    string                 segment_anchor_tag           = ""; +    string                 segname_prev                 = ""; +    string                 segname_next                 = ""; +    int                    parent_lev_markup            = 0; +    int                    parent_ocn                   = 0; +    int[]                  ancestors                    = []; +    string                 marked_up_level              = "9"; +    int                    heading_lev_markup           = 9; +    int                    heading_lev_collapsed        = 9; +    int[]                  dom_markedup                 = [ 0, 0, 0, 0, 0, 0, 0, 0,]; +    int[]                  dom_collapsed                = [ 0, 0, 0, 0, 0, 0, 0, 0,]; +    int[]                  heading_ancestors            = [ 0, 0, 0, 0, 0, 0, 0, 0,]; +    string[]               heading_ancestors_text       = [ "", "", "", "", "", "", "", "", ]; +    string[]               lev4_subtoc                  = []; +    int                    heading_array_ptr            = 0; +    int                    ptr_doc_object               = 0; +    int                    ptr_html_segnames            = 0; +    int                    ptr_heading                  = 0; +    int                    array_ptr                    = 0; +    int                    heading_array_ptr_segments   = 0; +    string[string][string] node; +  } +  struct TheObjects { +    ObjGenericComposite[] oca; +  } +} diff --git a/src/sdp/meta/package.d b/src/sdp/meta/package.d new file mode 100644 index 0000000..fcc6b13 --- /dev/null +++ b/src/sdp/meta/package.d @@ -0,0 +1,17 @@ +module sdp.meta; +public import +  sdp.meta.defaults, +  sdp.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/sdp/meta/read_config_files.d b/src/sdp/meta/read_config_files.d new file mode 100644 index 0000000..2410316 --- /dev/null +++ b/src/sdp/meta/read_config_files.d @@ -0,0 +1,80 @@ +/++ +  read configuration files<BR> +  - read config files<BR> +  meta_config_files.d ++/ +module sdp.meta.read_config_files; +template configIn() { +  import +    sdp.meta, +    std.file, +    std.path; +  final string configIn(C,E)(C conf_sdl, E env) { +    string dot_pwd = chainPath(to!string(env["pwd"]), ".sisu").array; +    string underscore_pwd = chainPath(to!string(env["pwd"]), "_sisu").array; +    string dot_home = chainPath(to!string(env["home"]), ".sisu").array; +    string[] possible_config_path_locations = [ +      dot_pwd, +      underscore_pwd, +      dot_home, +      "/etc/sisu" +    ]; +    string config_file_str; +    foreach(pth; possible_config_path_locations) { +      auto conf_file = format( +        "%s/%s", +        pth, +        conf_sdl, +      ); +      try { +        if (exists(conf_file)) { +          debug(configfile) { +            writeln(conf_file); +          } +          config_file_str = conf_file.readText; +          break; +        } +      } +      catch (ErrnoException ex) { +      } +      catch (FileException ex) { +      } +    } +    return config_file_str; +  } +} +/+ + ++/ +template ConfigSDLang() { +  import sdlang; +  import +    sdp.meta, +    std.file, +    std.path; +  auto ConfigSDLang(string configuration, string conf_sdl_filename) { +    Tag sdl_root_conf; +    try { +      sdl_root_conf = parseSource(configuration); +    } +    catch(ParseException e) { +      stderr.writeln("SDLang problem with content for ", conf_sdl_filename); +      stderr.writeln(e.msg); +    } +    return sdl_root_conf; +  } +} +/+ ++/ +template configRead() { +  import +    sdp.meta, +    std.file, +    std.path; +   +  final auto configRead(C,E)(C conf_sdl, E env) { +    auto configuration = configIn!()(conf_sdl, env); +    auto sdl_root = ConfigSDLang!()(configuration, conf_sdl); +    return sdl_root; +  } +} diff --git a/src/sdp/meta/read_source_files.d b/src/sdp/meta/read_source_files.d new file mode 100644 index 0000000..60f0777 --- /dev/null +++ b/src/sdp/meta/read_source_files.d @@ -0,0 +1,294 @@ +/++ +  module meta_read_source_files;<BR> +  - open markup files<BR> +  - if master file scan for addional files to import/insert ++/ +module sdp.meta.read_source_files; +template SiSUrawMarkupContent() { +  import +    sdp.meta.rgx; +  import +    sdp.meta, +    std.file, +    std.path; +  mixin SiSUrgxInit; +  auto rgx = Rgx(); +  auto rawsrc = RawMarkupContent(); +  auto SiSUrawMarkupContent(Fn)(Fn fn_src) { +    auto _0_header_1_body_content_2_insert_filelist_tuple = +      rawsrc.sourceContentSplitIntoHeaderAndBody(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(in string source_txt_str, in string fn_src="") { +      auto raw = MarkupRawUnit(); +      string[] insert_file_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(sourcefile_body_content, fn_src); +        static assert(!isTypeTuple!(tu)); +        sourcefile_body_content = tu[0]; +        insert_file_list = tu[1].dup; +      } +      t = tuple( +        header_raw, +        sourcefile_body_content, +        insert_file_list +      ); +      static assert(t.length==3); +      return t; +    } +  } +  struct MarkupRawUnit { +    import std.file; +    final private string readInMarkupSource(in char[] fn_src) { +      enforce( +        exists(fn_src)!=0, +        "file not found" +      ); +      string source_txt_str; +      try { +        if (exists(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) { +      auto rgx = Rgx(); +      enforce( +        fn_src.match(rgx.src_pth), +        "not a sisu markup filename" +      ); +      auto source_txt_str = readInMarkupSource(fn_src); +      return source_txt_str; +    } +    auto markupSourceHeaderContentRawLineTupleArray(in string source_txt_str) { +      string[] file_insert_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 +      ); +      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" +      ); +      auto source_txt_str = readInMarkupSource(fn_src_insert); +      auto source_line_arr = markupSourceLineArray(source_txt_str); +      return source_line_arr; +    } +  } +  struct Inserts { +    import sdp.meta.defaults; +    auto scan_subdoc_source( +      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); +      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 +            ); +          } +          auto ins = Inserts(); +          /+ +            1. load file, +            2. read lines; +            3. scan lines, +            4. if filename insert, and insert filename +            5.   repeat 1 +            6. else +            7.   add line to new array; +          +/ +        } else { +          type1["header_make"] = 0; +          type1["header_meta"] = 0; +          contents_insert ~= line; +        } +      } // end src subdoc (inserts) loop +      return contents_insert; +    } +    auto scan_master_src_for_insert_files_and_import_content( +      char[][] sourcefile_body_content, +      string fn_src +    ) { +      mixin SiSUrgxInitFlags; +      char[][] contents; +      auto type = flags_type_init; +      auto fn_pth_full = fn_src.match(rgx.src_pth); +      auto markup_src_file_path = fn_pth_full.captures[1]; +      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 ~= to!string(fn_src_insert); +          auto raw = MarkupRawUnit(); +          /+ TODO +/ +          if (auto ma = line.match(rgx.src_fn_text)) { +            /+ .sst when inserted, not used: headers and heading level ^:?A~ so remove +/ +            writeln(__LINE__); writeln(ma); +          } +          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 = ins.scan_subdoc_source( +            markup_sourcefile_insert_content, +            to!string(fn_src_insert) +          ); +          contents ~= contents_insert; +          /+ +            1. load file, +            2. read lines; +            3. scan lines, +            4. if filename insert, and insert filename +            5.   repeat 1 +            6. else +            7.   add line to new array; +          +/ +        } else { +          contents ~= line; +        } +      } // end src doc loop +      debug(insert_file) { +        writeln(__LINE__); +        writeln(contents.length); +      } +      auto t = tuple( +        contents, +        insert_file_list +      ); +      return t; +    } +  } +} diff --git a/src/sdp/meta/rgx.d b/src/sdp/meta/rgx.d new file mode 100644 index 0000000..854e9cc --- /dev/null +++ b/src/sdp/meta/rgx.d @@ -0,0 +1,256 @@ +/++ +  regex: regular expressions used in sisu document parser ++/ +module sdp.meta.rgx; +template SiSUrgxInit() { +  import sdp.meta.defaults; +  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"); +    /+ 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|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_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 inline_url_generic                              = ctRegex!(`(?:^|[}(\[ ])(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_#]`, "mg"); +    static inline_url                                      = ctRegex!(`((?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)[a-zA-Z0-9_]\S*)`, "mg"); +    static inline_link_naked_url                           = ctRegex!(`(?P<before>^|[ ])(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!'"]?(?:[ ]|$))`, "mg"); +    static inline_link_markup_regular                      = ctRegex!(`(?P<before>^|[ ])\{\s*(?P<content>.+?)\s*\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!]?(?:[ ]|$))`, "mg"); +    static inline_link_endnote_url_helper_punctuated       = ctRegex!(`\{~\^\s+(?P<content>.+?)\}(?P<link>(?:(?:https?|git):\/\/|¤?\.\.\/|¤?\.\/|¤|#)\S+?)(?P<after>[.,;:?!]?(?:[ ]|$))`, "mg"); +    static 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"); +    /+ inline markup book index +/ +    static book_index                                     = ctRegex!(`^=\{\s*(.+?)\}$`, "m"); +    static book_index_open                                = ctRegex!(`^=\{\s*([^}]+?)$`); +    static book_index_close                               = ctRegex!(`^(.*?)\}$`, "m"); +    /+ no obj_cite_number object +/ +    static obj_cite_number_off                            = ctRegex!(`~#$`, "m"); +    static obj_cite_number_off_dh                         = ctRegex!(`-#$`, "m"); +    static obj_cite_number_off_all                        = ctRegex!(`[~-]#$`, "m"); +    /+ no obj_cite_number block +/ +    static obj_cite_number_off_block                      = ctRegex!(`^--~#$`); +    static obj_cite_number_off_block_dh                   = ctRegex!(`^---#$`); +    static obj_cite_number_off_block_close                = ctRegex!(`^--\+#$`); +    static obj_cite_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]+)`); +    /+ 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_obj_cite_number_offset_split = ctRegex!(`\s*\|\s*`); +    static bi_term_and_obj_cite_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 src_pth                                        = ctRegex!(`^(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[tm])$`); +    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])$`); +    /+ inline markup footnotes endnotes +/ +    static inline_notes_al                                = ctRegex!(`【(?:[*+]\s+|\s*)(.+?)】`, "mg"); +    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_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"); +    /+ 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"); +    /+ table delimiters +/ +    static table_delimiter_col                           = ctRegex!("[ ]*[┊][ ]*", "mg"); +    static table_delimiter_row                           = ctRegex!("[ ]*\n", "mg"); +  } +} | 
