diff options
| author | Ralph Amissah <ralph@amissah.com> | 2016-04-25 23:13:35 -0400 | 
|---|---|---|
| committer | Ralph Amissah <ralph@amissah.com> | 2016-04-26 07:37:25 -0400 | 
| commit | 44a42f6d4f68742914c0b5b5976593ae8c67a693 (patch) | |
| tree | b406c5b98ff755dbebe7309422b75b19594720a5 /src | |
| parent | step3 (diff) | |
dub config
Diffstat (limited to 'src')
| -rwxr-xr-x | src/sdp.d | 186 | ||||
| -rw-r--r-- | src/sdp/ao_abstract_doc_source.d | 3743 | ||||
| -rw-r--r-- | src/sdp/ao_ansi_colors.d | 74 | ||||
| -rw-r--r-- | src/sdp/ao_defaults.d | 311 | ||||
| -rw-r--r-- | src/sdp/ao_object_setter.d | 124 | ||||
| -rw-r--r-- | src/sdp/ao_output_debugs.d | 413 | ||||
| -rw-r--r-- | src/sdp/ao_read_source_files.d | 281 | ||||
| -rw-r--r-- | src/sdp/ao_rgx.d | 181 | ||||
| -rw-r--r-- | src/sdp/compile_time_info.d | 38 | 
9 files changed, 5351 insertions, 0 deletions
| diff --git a/src/sdp.d b/src/sdp.d new file mode 100755 index 0000000..725c018 --- /dev/null +++ b/src/sdp.d @@ -0,0 +1,186 @@ +#!/usr/bin/env rdmd +/+ +  sdp +  sdp.d ++/ +/+ sdp  sisu document parser +/ +private import +  std.getopt, +  std.process, +  std.stdio, +  std.algorithm, +  std.array, +  std.container, +  std.exception, +  std.json, +  // std.path, +  std.range, +  std.regex, +  // std.stdio, +  std.string, +  std.traits, +  std.typecons, +  std.utf, +  // std.variant, +  std.conv : to; +/+ sdp  sisu document parser +/ +import +  compile_time_info,            // compile_time_info.d +  ao_abstract_doc_source,       // ao_abstract_doc_source.d +  ao_defaults,                  // ao_defaults.d +  ao_read_source_files,         // ao_read_source_files.d +  ao_output_debugs,             // ao_output_debugs.d +  ao_rgx,                       // ao_rgx.d +  ao_ansi_colors;               // ao_ansi_colors.d +  // std.conv; +mixin(import("version.txt")); +mixin CompileTimeInfo; +mixin RgxInit; +void main(string[] args) { +   +  mixin SiSUheader; +  mixin SiSUbiblio; +  mixin SiSUrgxInitFlags; +  mixin SiSUmarkupRaw; +  mixin SiSUdocAbstraction; +  mixin SiSUoutputDebugs; +  mixin ScreenTxtColors; +  auto raw = MarkupRaw(); +  auto abs = Abstraction(); +  auto dbg = SDPoutputDebugs(); +  /+ +  struct DocumentParts { +    string[string][] contents; +    JSONValue[string] metadata_json; +    JSONValue[string] make_json; +    string[][string][string] bookindex_unordered_hashes; +    JSONValue[] biblio; +  } +  +/ +  string[] fns_src; +  string flag_action; +  string arg_unrecognized; +  auto rgx = Rgx(); +  scope(success) { +    debug(checkdoc) { +      writefln( +        "%s~ run complete, ok ~ %s (sdp-%s.%s.%s, %s v%s, %s %s)", +        scr_txt_color["cyan"], scr_txt_color["off"], +        ver.major, ver.minor, ver.patch, +        __VENDOR__, __VERSION__, +        bits, os, +      ); +    } +    // stderr.writeln("0"); +  } +  scope(failure) { +    debug(checkdoc) { +      stderr.writefln( +        "%s~ run failure ~%s", +         scr_txt_color["fuchsia"], scr_txt_color["off"], +      ); +    } +  } +   +  bool[string] opt_action_bool = [ +    "assertions"          : false, +    "html"                : false, +    "no_obj_cite_number"  : false, +    "verbose"             : false, +  ]; +  auto helpInfo = getopt(args, +    std.getopt.config.passThrough, +    "assert",    "--assert set optional assertions on",          &opt_action_bool["assertions"], +    "html",      "--html process html output",                   &opt_action_bool["html"], +    "no-ocn",    "--no-ocn suppress object cite number output",  &opt_action_bool["no_obj_cite_number"], +    "verbose|v", "--verbose output to terminal",                 &opt_action_bool["verbose"], +  ); +  if (helpInfo.helpWanted) { +    defaultGetoptPrinter("Some information about the program.", helpInfo.options); +  } +  foreach(arg; args) { +    if (match(arg, rgx.flag_action)) { +      flag_action ~= " " ~ arg;   // flags not taken by getopt +    } else if (match(arg, rgx.src_pth)) { +      fns_src ~= arg;             // gather input markup source file names for processing +    } else {                      // anything remaining, unused +      arg_unrecognized ~= " " ~ arg; +    } +  } +  foreach(fn_src; fns_src) { +  // foreach(fn_src; fns_src) { +    if (!empty(fn_src)) { +      scope(success) { +        debug(checkdoc) { +          writefln( +            "%s~ document complete, ok ~%s", +            scr_txt_color["green"], scr_txt_color["off"], +          ); +        } +        // stderr.writeln("0"); +      } +      scope(failure) { +        debug(checkdoc) { +          stderr.writefln( +            "%s~ document run failure ~%s (%s  v%s)\n\t%s", +            scr_txt_color["red"], scr_txt_color["off"], +            __VENDOR__, __VERSION__, +            fn_src +          ); +        } +        // stderr.writeln("1"); +      } +      enforce( +        match(fn_src, rgx.src_pth), +        "not a sisu markup filename" +      ); +      /+ ↓ read file +/ +      auto sourcefile_content = +        raw.sourceContent(fn_src); +      /+ ↓ porcess document, return abstraction as tuple +/ +      auto t = +        abs.abstract_doc_source(sourcefile_content); +      static assert(!isTypeTuple!(t)); +      auto doc_ao_contents = t[0]; // contents ~ endnotes ~ bookindex; +      // static assert(!isIterable!(doc_ao_contents)); +      auto doc_ao_metadata_json = t[1]; +      auto doc_ao_make_json = t[2]; +      auto doc_ao_bookindex_unordered_hashes = t[3]; +      auto doc_ao_biblio = t[4]; +      // destroy(t); +      /+ ↓ document parts +/ +      debug(checkdoc) { // checkbook & dumpdoc +        dbg.abstract_doc_source_debugs( +          doc_ao_contents, +          doc_ao_make_json, +          doc_ao_metadata_json, +          doc_ao_bookindex_unordered_hashes, +          doc_ao_biblio, +          fn_src, +          opt_action_bool +        ); +      } +      scope(exit) { +        debug(checkdoc) { +          writefln( +            "processed file: %s", +            fn_src +          ); +        } +        destroy(sourcefile_content); +        destroy(t); +        destroy(doc_ao_contents); +        destroy(doc_ao_make_json); +        destroy(doc_ao_metadata_json); +        destroy(doc_ao_bookindex_unordered_hashes); +        destroy(doc_ao_biblio); +        destroy(fn_src); +      } +    } else { +      /+ no recognized filename provided +/ +      writeln("no recognized filename"); +      break; +      // terminate, stop +    } +  } +} diff --git a/src/sdp/ao_abstract_doc_source.d b/src/sdp/ao_abstract_doc_source.d new file mode 100644 index 0000000..c1566d2 --- /dev/null +++ b/src/sdp/ao_abstract_doc_source.d @@ -0,0 +1,3743 @@ +/+ +  document abstraction +  ao_abstract_doc_source.d ++/ +template SiSUdocAbstraction() { +  private: +  struct Abstraction { + +    /+ ↓ abstraction imports +/ +    import +      ao_defaults,                  // sdp/ao_defaults.d +      ao_object_setter,             // sdp/ao_object_setter.d +      ao_rgx,                       // sdp/ao_rgx.d +      ao_ansi_colors;               // sdp/ao_ansi_colors.d + +    /+ ↓ abstraction mixins +/ +    mixin ObjectSetter; +    mixin InternalMarkup; +    // // mixin SiSUrgxInitFlags; +    // // mixin AssertionsOnBlocks; +    // mixin SiSUbiblio; // issue +    // mixin SiSUheader; + +    /+ ↓ abstraction struct init +/ +    /+ initialize +/ +     +    auto rgx = Rgx(); +    ObjComposite[] contents_the_objects; +     +    string[string] an_object, processing; +    auto set_abstract_object = ObjectAbstractSet(); +    auto set_header = HeaderDocMetadataMakeJson(); +    auto note_section = NotesSection(); +     +    /+ enum +/ +    enum State { off, on } +    enum TriState { off, on, closing } // make aware, possibility of third state +    enum DocStructMarkupHeading { +      h_sect_A, +      h_sect_B, +      h_sect_C, +      h_sect_D, +      h_text_1, +      h_text_2, +      h_text_3, +      h_text_4, +      h_text_5, // extra level, drop +      content_non_header +    } // header section A-D; header text 1-4 +    enum DocStructCollapsedHeading { lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7 } // not yet used +     +    /+ biblio variables +/ +    string biblio_tag_name, biblio_tag_entry, st; +    string[] biblio_arr_json; +    JSONValue[] bib_arr_json; +    int bib_entry; +     +    /+ counters +/ +    long counter, previous_count; +    int[string] line_occur; +    int verse_line, heading_pointer; +     +    /+ paragraph attributes +/ +    string[string] indent; +    bool bullet = true; +    string content_non_header = "8"; +     +    auto obj_im = ObjInlineMarkup(); +    auto obj_att = ObjAttrib(); +     +    /+ ocn +/ +    int obj_cite_number, obj_cite_number_; +    auto object_citation_number = OCNemitter(); +    int obj_cite_number_emit(int obj_cite_number_status_flag) { +      return object_citation_number.obj_cite_number_emitter(obj_cite_number_status_flag); +    } +     +    /+ book index variables +/ +    string book_idx_tmp; +    string[][string][string] bookindex_unordered_hashes; +    auto bookindex_extract_hash = BookIndexNuggetHash(); +    string[][string][string] bkidx_hash(string bookindex_section, int obj_cite_number) { +      return bookindex_extract_hash.bookindex_nugget_hash(bookindex_section, obj_cite_number); +    } +     +    /+ node +/ +    string node; +    auto node_construct = NodeStructureMetadata(); +    string node_jstr( +      string lev_markup_number, +      int obj_cite_number_, +      long counter, +      int heading_pointer, +      string is_ +    ) { +      return node_construct.node_emitter( +        lev_markup_number, +        obj_cite_number_, +        counter, +        heading_pointer, +        is_ +      ); +    } +    string node_jstr_heading( +      string lev_markup_number, +      string lev_collapsed_number, +      int obj_cite_number_, +      long counter, +      int heading_pointer, +      string is_ +    ) { +      return node_construct.node_emitter_heading( +        lev_markup_number, +        lev_collapsed_number, +        obj_cite_number_, +        counter, +        heading_pointer, +        is_ +      ); +    } +    // mixin SiSUdocAbstractionFunctions; + +    /+ ↓ abstract marked up document +/ +    auto abstract_doc_source(char[][] markup_sourcefile_content) { + +      /+ ↓ abstraction init +/ +      scope(success) { +      } +      scope(failure) { +      } +      scope(exit) { +        destroy(contents_the_objects); +        destroy(an_object); +        destroy(processing); +        destroy(biblio_arr_json); +      } +      auto type = flags_type_init; +      auto dochead_make = parseJSON(header_make_jsonstr).object; +      auto dochead_metadata = parseJSON(header_metadata_jsonstr).object; +      mixin ScreenTxtColors; +      int tell_lo(string color, int obj_cite_number, in char[] line) { +        writefln( +          "%s%s %s", +          scr_txt_marker[color], +          to!string(obj_cite_number), +          to!string(line) +        ); +        return 0; +      } +      int tell_l(string color, in char[] line) { +        writefln( +          "%s%s", +          scr_txt_marker[color], +          line +        ); +        return 0; +      } +      string[string] obj_cite_number_poem = [ +        "start" : "", +        "end"   : "" +      ]; +      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_collapsed_number" : 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)") +      ]; +      /+ 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 = replaceAll(line, rgx.true_dollar, "$$$$"); +          // dollar represented as $$ needed to stop submatching on $ +          // (substitutions using ${identifiers} must take into account (e.g. happen earlier)) +        debug(source) {                                  // source lines +          writeln(line); +          // writeln(scr_txt_marker["green"], line); +        } +        debug(srclines) { +          if (!line.empty) {                             // source lines, not empty +            writefln( +              "%s%s", +              scr_txt_marker["green"], +              line +            ); +          } +        } +        if (!line.empty) { +          check_obj_cite_number_status(line, type); +        } +        if (type["code"] == TriState.on) { +          /+ block object: code +/ +          code_block(line, an_object, type); +          continue; +        } else if (!match(line, rgx.regular_parse_skip)) { +          /+ object other than code block object (includes regular text paragraph) +/ +          if (((match(line, rgx.heading_biblio) +          || (type["heading_biblio"] == State.on))) +          && (!match(line, rgx.heading)) +          && (!match(line, rgx.comment))) { +            /+ within block object: biblio +/ +            biblio_block(line, type, bib_entry, biblio_arr_json); +            continue; +          } else if (type["poem"] == TriState.on) { +            /+ within block object: poem +/ +            poem_block(line, an_object, type, counter, obj_cite_number_poem); +            continue; +          /+ within block object: group +/ +          } else if (type["group"] == TriState.on) { +            /+ within block object: group +/ +            group_block(line, an_object, type); +            continue; +          } else if (type["block"] == TriState.on) { +            /+ within block object: block +/ +            block_block(line, an_object, type); +            continue; +          } else if (type["quote"] == TriState.on) { +            /+ within block object: quote +/ +            quote_block(line, an_object, type); +            continue; +          } else if (type["table"] == TriState.on) { +            /+ within block object: table +/ +            table_block(line, an_object, type); +            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 (match(line, rgx.block_open)) { +              if (match(line, (rgx.block_poem_open))) { +                /+ poem to verse exceptions! +/ +                object_reset(an_object); +                processing.remove("verse"); +                obj_cite_number_poem["start"] = to!string(obj_cite_number); +              } +              start_block(line, type, obj_cite_number_poem); +              continue; +            } else if (!line.empty) { +              /+ line not empty +/ +              /+ non blocks (headers, paragraphs) & closed blocks +/ +              assert( +                !line.empty, +                "line tested, line not empty surely" +              ); +              assert( +                (type["blocks"] == TriState.off) +                || (type["blocks"] == TriState.closing), +                "code block status: none or closed" +              ); +              if (type["blocks"] == TriState.closing) { +                // blocks closed, unless followed by book index +                debug(check) {                           // block +                  writeln(__LINE__); +                  tell_l("red", line); +                } +                assert( +                  match(line, rgx.book_index) +                  || match(line, rgx.book_index_open) +                  || type["book_index"] == State.on +                ); +              } +              if ((match(line, rgx.book_index)) +              || (match(line, rgx.book_index_open)) +              || (type["book_index"] == State.on ))  { +                /+ book_index +/ +                book_index(line, book_idx_tmp, an_object, type); +              } else { +                /+ not book_index +/ +                if (auto m = match(line, rgx.comment)) { +                  /+ matched comment +/ +                  debug(comment) { +                    tell_l("blue", line); +                  } +                  an_object["obj"] ~= line ~= "\n"; +                  contents_the_objects ~= +                    set_abstract_object.contents_comment(strip(an_object["obj"])); +                  header_set_common(line_occur, an_object, type); +                  processing.remove("verse"); +                  type["header_make"] = State.off; +                  type["header_metadata"] = State.off; +                  ++counter; +                } else if ((match(line, rgx.header_make)) +                  || (match(line, rgx.header_metadata)) +                  || (type["header_make"] == State.on +                  && (line_occur["header_make"] > State.off)) +                  || (type["header_metadata"] == State.on +                  && (line_occur["header_metadata"] > State.off))) { +                    header_extract(line, line_occur, an_object, type); +                } 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 ((to!string(dochead_make["make"]["headings"]).length > 2) +                  && (type["make_headings"] == State.off)) { +                    /+ heading found +/ +                    auto dochead_make_headings = +                      to!string(dochead_make["make"]["headings"]); +                    heading_found(line, dochead_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 +/ +                    heading_make_set(line, line_occur, heading_match_rgx, type); +                  } +                  if (auto m = match(line, rgx.heading)) { +                    /+ heading match +/ +                    heading_match(line, line_occur, an_object, lv, collapsed_lev, type); +                  } else if (line_occur["para"] == State.off) { +                    /+ para match +/ +                    para_match(line, an_object, indent, bullet, type); +                  } +                } else if (line_occur["header_make"] > State.off) { +                  /+ header_make +/ +                  // should be caught by sub-header +                  debug(header) { +                    tell_l("red", line); +                  } +                  an_object["obj"] ~= line ~= "\n"; +                  ++line_occur["header_make"]; +                } else if (line_occur["header_metadata"] > State.off) { +                  /+ header_metadata +/ +                  // should be caught by sub-header +                  debug(header) {                          // para +                    tell_l("red", line); +                  } +                  an_object["obj"] ~= line ~= "\n"; +                  ++line_occur["header_metadata"]; +                } else if (line_occur["heading"] > State.off) { +                  /+ heading +/ +                  debug(heading) {                         // heading +                    tell_l("blue", line); +                  } +                  an_object["obj"] ~= line ~= "\n"; +                  ++line_occur["heading"]; +                } else if (line_occur["para"] > State.off) { +                  /+ paragraph +/ +                  debug(para) { +                    tell_l("blue", line); +                  } +                  an_object["obj"] ~= line; +                  ++line_occur["para"]; +                } +              } +            } else if (type["blocks"] == TriState.closing) { +              /+ line empty, with blocks flag +/ +              block_flag_line_empty(line, an_object, contents_the_objects, bookindex_unordered_hashes, obj_cite_number, node, counter, type, obj_cite_number_poem); // watch +            } else { +            /+ line empty +/ +              /+ line.empty, post contents, empty variables: +/ +              assert( +                line.empty, +                "line should be empty" +              ); +              assert( +                (type["blocks"] == State.off), +                "code block status: none" +              ); +              if ((type["header_make"] == State.on) +              && (line_occur["header_make"] > State.off)) { +                /+ header_make instructions (current line empty) +/ +                auto dochead_metadata_and_make = +                  set_header.header_metadata_and_make_jsonstr(strip(an_object["obj"]), dochead_metadata, dochead_make); +                static assert(!isTypeTuple!(dochead_metadata_and_make)); +                dochead_metadata = dochead_metadata_and_make[0]; +                dochead_make = dochead_metadata_and_make[1]; +                header_set_common(line_occur, an_object, type); +                processing.remove("verse"); +              } else if ((type["header_metadata"] == State.on) +              && (line_occur["header_metadata"] > State.off)) { +                /+ header_metadata (current line empty) +/ +                auto dochead_metadata_and_make = +                  set_header.header_metadata_and_make_jsonstr(strip(an_object["obj"]), dochead_metadata, dochead_make); +                static assert(!isTypeTuple!(dochead_metadata_and_make)); +                dochead_metadata = dochead_metadata_and_make[0]; +                dochead_make = dochead_metadata_and_make[1]; +                header_set_common(line_occur, an_object, type); +                type["header_make"] = State.off; +                type["header_metadata"] = State.off; +                processing.remove("verse"); +              } else if ((type["heading"] == State.on) +              && (line_occur["heading"] > State.off)) { +                /+ heading object (current line empty) +/ +                obj_cite_number = obj_cite_number_emit(type["obj_cite_number_status"]); +                an_object["bookindex"] = +                  ("bookindex" in an_object) ? an_object["bookindex"] : ""; +                bookindex_unordered_hashes = +                  bkidx_hash(an_object["bookindex"], obj_cite_number); +                an_object["is"] = "heading"; +                node = +                  node_jstr_heading( +                    an_object["lev_markup_number"], +                    an_object["lev_collapsed_number"], +                    obj_cite_number, +                    counter, +                    heading_pointer, +                    an_object["is"] +                  ); // heading +                an_object["substantive"] = +                  obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +                an_object["attrib"] = +                  obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +                ++heading_pointer; +                contents_the_objects ~= +                  set_abstract_object.contents_heading( +                    an_object["substantive"], +                    an_object["attrib"], +                    obj_cite_number, +                    to!int(an_object["lev_markup_number"]), +                    to!int(an_object["lev_collapsed_number"]) +                  ); +                // track previous heading and make assertions +                debug(objectrelated1) { // check +                  tell_l("blue", line); +                  // writeln(an_object["obj"]); +                  // writeln(contents_am[counter]["obj_cite_number"], " ", contents_am[counter]["obj"]); +                  // writeln(m.hit, "\n"); +                } +                header_set_common(line_occur, an_object, type); +                type["header_make"] = State.off; +                type["header_metadata"] = State.off; +                an_object.remove("lev"); +                an_object.remove("lev_markup_number"); +                // an_object["lev_markup_number"]="9"; +                processing.remove("verse"); +                ++counter; +              } else if ((type["para"] == State.on) && (line_occur["para"] > State.off)) { +                /+ paragraph object (current line empty) +/ +                obj_cite_number = obj_cite_number_emit(type["obj_cite_number_status"]); +                an_object["bookindex"] = +                  ("bookindex" in an_object) ? an_object["bookindex"] : ""; +                bookindex_unordered_hashes = +                  bkidx_hash(an_object["bookindex"], obj_cite_number); +                an_object["is"] = "para"; +                node = +                  node_jstr( +                    content_non_header, +                    obj_cite_number, +                    counter, +                    heading_pointer-1, +                    an_object["is"] +                  ); +                an_object["substantive"] = +                  obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +                an_object["attrib"] = +                  obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +                contents_the_objects ~= +                  set_abstract_object.contents_para( +                    an_object["is"], +                    an_object["substantive"], +                    an_object["attrib"], +                    obj_cite_number, +                    indent, +                    bullet +                  ); +                // contents_the_objects ~= +                //   set_abstract_object.contents_para( +                //     an_object, +                //     obj_cite_number, +                //     indent, +                //     bullet +                //   ); +                header_set_common(line_occur, an_object, type); +                type["header_make"] = State.off; +                type["header_metadata"] = State.off; +                indent["first"] = "0"; +                indent["second"] = "0"; +                bullet = false; +                processing.remove("verse"); +                ++counter; +              } else { +                assert( +                  line == null, +                  "line variable should be empty, should not occur" +                ); +                // check what happens when paragraph separated by 2 newlines +              } +            } // close else for line empty +          } // close else for not the above +        } // close after non code, other blocks or regular text +        if (((contents_the_objects[$-1].is_a == "para") +        || (contents_the_objects[$-1].is_a == "heading")) +        && (counter-1 > previous_count)) { +          if (match(contents_the_objects[$-1].object, +          rgx.inline_notes_delimiter_al_regular_number_note)) { +            // endnotes/ footnotes for +            // doc objects other than paragraphs & headings +            // various forms of grouped text +            previous_count=contents_the_objects.length -1; +            note_section.gather_notes_for_endnote_section( +              contents_the_objects, +              contents_the_objects.length -1 +            ); +            // notes[notepoint]=note_section.notes_section(contents_the_objects, counter-1); +            // notepoint +=1; +          } +        } +      } /+ ← closed: loop markup document/text line by line +/ + +      /+ ↓ post loop markup document/text +/ +      debug(objectrelated2) { // check +          tell_l("blue", line); +        // writeln(__FILE__, ":", __LINE__); +        // writeln(counter); +        // // contents_am[0..counter] +        // writeln(contents_am.length); +      } +      /+ +        Backmatter: +        * endnotes +        * glossary +        * references / bibliography +        * book index +      +/ +      obj_im.obj_inline_markup("doc_end_reset", ""); +      auto en_tuple = +        note_section.endnote_objects(obj_cite_number); +      static assert(!isTypeTuple!(en_tuple)); +      auto endnotes_section = en_tuple[0]; +      obj_cite_number = en_tuple[1]; +      debug(endnotes) { +        writefln( +          "%s %s", +          __LINE__, +          endnotes_section.length +        ); +        foreach (n; endnotes_section) { +          writeln(n); +        } +      } +      auto biblio_unsorted_incomplete = biblio_arr_json.dup; +      // destroy(biblio_arr_json); +      auto biblio = Bibliography(); +      auto biblio_ordered = +        biblio.bibliography(biblio_unsorted_incomplete, bib_arr_json); +      auto bi = BookIndexReportSection(); +      auto bi_tuple = +        bi.bookindex_build_section(bookindex_unordered_hashes, obj_cite_number); +      static assert(!isTypeTuple!(bi_tuple)); +      auto bookindex_section = bi_tuple[0]; +      obj_cite_number = bi_tuple[1]; +      debug(bookindex) {                         // bookindex +        foreach (bi_entry; bookindex_section) { +          writeln(bi_entry["obj"]); +        } +      } +      auto document_the = +        contents_the_objects ~ endnotes_section ~ bookindex_section; +      debug(heading) {                         // heading +        string spc; +        foreach (o; document_the) { +          if (o["is"] == "heading") { +            switch (o["lev_markup_number"]) { +            case "0": +            // case to!string(DocStructMarkupHeading.h_sect_A): +              spc=""; +              break; +            case "1": +            // case to!string(DocStructMarkupHeading.h_sect_B): +              spc="  "; +              break; +            case "2": +            // case to!string(DocStructMarkupHeading.h_sect_C): +              spc="    "; +              break; +            case "3": +            // case to!string(DocStructMarkupHeading.h_sect_D): +              spc="      "; +              break; +            case "4": +            // case to!string(DocStructMarkupHeading.h_text_1): +              spc="        "; +              break; +            case "5": +            // case to!string(DocStructMarkupHeading.h_text_2): +              spc="          "; +              break; +            case "6": +            // case to!string(DocStructMarkupHeading.h_text_3): +              spc="            "; +              break; +            case "7": +            // case to!string(DocStructMarkupHeading.h_text_4): +              spc="              "; +              break; +            case "8": +            // case to!string(DocStructMarkupHeading.h_text_5): +              spc="                "; +              break; +            default: +              spc=""; +              break; +            } +            // writeln( +            //   spc, "* ", " ", +            //   o +            // ); +            writefln( +              "%s*  $s\n            %s", +              spc, +              strip(o["obj"]), +              o["attrib"] +            ); +            // writeln(spc, "* ", to!string(o["lev_collapsed_number"]), " ", strip(o["obj"])); +            // tell_l("yellow", spc, strip(o["obj"])); +          } +        } +      } +      destroy(contents_the_objects); +      destroy(endnotes_section); +      destroy(bookindex_section); +      // struct Document { +      //   char content; +      //   char head_make; +      //   char head_metadata; +      //   char bookindex_section; +      //   char biblio; +      // } +      // struct Document { +      //   char content; +      //   char head_make; +      //   char head_metadata; +      //   char bookindex_section; +      //   char biblio; +      // } +      auto t = +        tuple( +          document_the, +          dochead_make, +          dochead_metadata, +          bookindex_unordered_hashes, +          biblio_ordered +        ); +      return t; +      /+ post loop markup document/text ↑ +/ + +    } /+ ← closed: abstract doc source +/ + +    /+ ↓ abstraction functions +/ +    auto object_reset(ref string[string] an_object) { +      an_object.remove("obj"); +      an_object.remove("substantive"); +      an_object.remove("is"); +      an_object.remove("attrib"); +      an_object.remove("bookindex"); +    } +    auto header_set_common( +      ref int[string] line_occur, +      ref string[string] an_object, +      ref int[string] type +    ) { +      // line_occur["header"] = State.off; +      line_occur["header_make"] = State.off; +      line_occur["header_metadata"] = State.off; +      line_occur["heading"] = State.off; +      line_occur["para"]= State.off; +      type["header"] = State.off; +      // type["header_make"] = State.off; +      // type["header_metadata"] = State.off; +      type["heading"] = State.off; +      type["para"] = State.off; +      object_reset(an_object); +    } +    auto check_obj_cite_number_status(char[] line, ref int[string] type) { +      if ((!line.empty) && (type["obj_cite_number_status_multi_obj"] == TriState.off)) { +        /+ not multi-line object, check whether obj_cite_number is on or turned off +/ +        if (match(line, rgx.obj_cite_number_block_marks)) { +          /+ switch off obj_cite_number +/ +          if (match(line, rgx.obj_cite_number_off_block)) { +            type["obj_cite_number_status_multi_obj"] = TriState.on; +            debug(ocnoff) { +              tell_l("fuchsia", line); +            } +          } +          if (match(line, rgx.obj_cite_number_off_block_dh)) { +            type["obj_cite_number_status_multi_obj"] = TriState.closing; +            debug(ocnoff) { +              tell_l("fuchsia", line); +            } +          } +        } else { +          if (type["obj_cite_number_status_multi_obj"] == TriState.off) { +            if (match(line, rgx.obj_cite_number_off)) { +              type["obj_cite_number_status"] = TriState.on; +            } else if (match(line, rgx.obj_cite_number_off_dh)) { +              type["obj_cite_number_status"] = TriState.closing; +            } else { +              // type["obj_cite_number_status"] = TriState.closing; +              type["obj_cite_number_status"] = TriState.off; +            } +          } else { +            type["obj_cite_number_status"] = +              type["obj_cite_number_status_multi_obj"]; +          } +        } +      } else if ((!line.empty) && (type["obj_cite_number_status_multi_obj"] > TriState.off)) { +        if (auto m = match(line, rgx.obj_cite_number_off_block_close)) { +          type["obj_cite_number_status_multi_obj"] = TriState.off; +          type["obj_cite_number_status"] = TriState.off; +          debug(ocnoff) { +            tell_l("green", line); +          } +        } +      } +      return 0; +    } +    auto start_block( +      char[] line, +      ref int[string] type, +      string[string] obj_cite_number_poem +    ) { +      if (match(line, rgx.block_curly_code_open)) { +        /+ curly code open +/ +        debug(code) {                              // code (curly) open +          writefln( +            "%s* [code curly] %s%s", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            line +          ); +        } +        type["blocks"] = TriState.on; +        type["code"] = TriState.on; +        type["curly_code"] = TriState.on; +      } else if (match(line, rgx.block_curly_poem_open)) { +        /+ curly poem open +/ +        debug(poem) {                              // poem (curly) open +          writefln( +            "%s* [poem curly] %s%s", +            scr_txt_color["red"], +            scr_txt_color["off"], +            line +          ); +        } +        obj_cite_number_poem["start"] = +          to!string(obj_cite_number); +        type["blocks"] = TriState.on; +        type["verse_new"] = State.on; +        type["poem"] = TriState.on; +        type["curly_poem"] = TriState.on; +      } else if (match(line, rgx.block_curly_group_open)) { +        /+ curly group open +/ +        debug(group) {                             // group (curly) open +          writefln( +            "%s* [group curly] %s%s", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            line +          ); +        } +        type["blocks"] = TriState.on; +        type["group"] = TriState.on; +        type["curly_group"] = TriState.on; +      } else if (match(line, rgx.block_curly_block_open)) { +        /+ curly block open +/ +        debug(block) {                             // block (curly) open +          writefln( +            "%s* [block curly] %s%s", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            line +          ); +        } +        type["blocks"] = TriState.on; +        type["block"] = TriState.on; +        type["curly_block"] = TriState.on; +      } else if (match(line, rgx.block_curly_quote_open)) { +        /+ curly quote open +/ +        debug(quote) {                             // quote (curly) open +          writefln( +            "%s* [quote curly] %s%s", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            line +          ); +        } +        type["blocks"] = TriState.on; +        type["quote"] = TriState.on; +        type["curly_quote"] = TriState.on; +      } else if (match(line, rgx.block_curly_table_open)) { +        /+ curly table open +/ +        debug(table) {                             // table (curly) open +          writefln( +            "%s* [table curly] %s%s", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            line +          ); +        } +        type["blocks"] = TriState.on; +        type["table"] = TriState.on; +        type["curly_table"] = TriState.on; +      } else if (match(line, rgx.block_tic_code_open)) { +        /+ tic code open +/ +        debug(code) {                              // code (tic) open +          writefln( +            "%s* [code tic] %s%s", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            line +          ); +        } +        type["blocks"] = TriState.on; +        type["code"] = TriState.on; +        type["tic_code"] = TriState.on; +      } else if (match(line, rgx.block_tic_poem_open)) { +        /+ tic poem open +/ +        debug(poem) {                              // poem (tic) open +          writefln( +            "%s* [poem tic] %s%s", +            scr_txt_color["red"], +            scr_txt_color["off"], +            line +          ); +        } +        obj_cite_number_poem["start"] = to!string(obj_cite_number); +        type["blocks"] = TriState.on; +        type["verse_new"] = State.on; +        type["poem"] = TriState.on; +        type["tic_poem"] = TriState.on; +      } else if (match(line, rgx.block_tic_group_open)) { +        /+ tic group open +/ +        debug(group) {                             // group (tic) open +          writefln( +            "%s* [group tic] %s%s", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            line +          ); +        } +        type["blocks"] = TriState.on; +        type["group"] = TriState.on; +        type["tic_group"] = TriState.on; +      } else if (match(line, rgx.block_tic_block_open)) { +        /+ tic block open +/ +        debug(block) {                             // block (tic) open +          writefln( +            "%s* [block tic] %s%s", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            line +          ); +        } +        type["blocks"] = TriState.on; +        type["block"] = TriState.on; +        type["tic_block"] = TriState.on; +      } else if (match(line, rgx.block_tic_quote_open)) { +        /+ tic quote open +/ +        debug(quote) {                             // quote (tic) open +          writefln( +            "%s* [quote tic] %s%s", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            line +          ); +        } +        type["blocks"] = TriState.on; +        type["quote"] = TriState.on; +        type["tic_quote"] = TriState.on; +      } else if (match(line, rgx.block_tic_table_open)) { +        /+ tic table open +/ +        debug(table) {                             // table (tic) open +          writefln( +            "%s* [table tic] %s%s", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            line +          ); +        } +        type["blocks"] = TriState.on; +        type["table"] = TriState.on; +        type["tic_table"] = TriState.on; +      } +      return 0; +    } +    auto code_block( +      char[] line, +      ref string[string] an_object, +      ref int[string] type +    ) { +      if (type["curly_code"] == TriState.on) { +        if (auto m = match(line, rgx.block_curly_code_close)) { +          debug(code) {                              // code (curly) close +            tell_l("blue", line); +          } +          type["blocks"] = TriState.closing; +          type["code"] = TriState.closing; +          type["curly_code"] = TriState.off; +        } else { +          debug(code) {                              // code (curly) line +            tell_l("blue", line); +          } +          an_object["obj"] ~= line ~= "\n";                       // code (curly) line +        } +      } else if (type["tic_code"] == TriState.on) { +        if (auto m = match(line, rgx.block_tic_close)) { +          debug(code) {                              // code (tic) close +            tell_l("blue", line); +          } +          type["blocks"] = TriState.closing; +          type["code"] = TriState.closing; +          type["tic_code"] = TriState.off; +        } else { +          debug(code) {                              // code (tic) line +            tell_l("blue", line); +          } +          an_object["obj"] ~= line ~= "\n";                       // code (tic) line +        } +      } +      return 0; +    } +    final string biblio_tag_map(string abr) { +      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]; +    } +    auto biblio_block( +      char[] line, +      ref int[string] type, +      ref int bib_entry, +      ref string[] biblio_arr_json +    ) { +      if (match(line, rgx.heading_biblio)) { +        type["heading_biblio"] = TriState.on; +      } +      if (empty(line) && (bib_entry == TriState.off)) { +        biblio_arr_json ~= biblio_entry_tags_jsonstr; +        bib_entry = TriState.on; +      } +      debug(biblio) { +        writefln( +          "%s * %s %s", +          scr_txt_color["yellow"], +          scr_txt_color["off"], +          line +        ); +      } +      if (match(line, rgx.biblio_tags)) { +        auto bt = match(line, rgx.biblio_tags); +        bib_entry = 0; +        st=to!string(bt.captures[1]); +        biblio_tag_entry=to!string(bt.captures[2]); +        JSONValue j = parseJSON(biblio_arr_json[$-1]); +        biblio_tag_name = (match(st, rgx.biblio_abbreviations)) +          ? (biblio_tag_map(st)) +          : st; +        j.object[biblio_tag_name] = biblio_tag_entry; +        auto header_tag_value=to!string(bt.captures[2]); +        switch (biblio_tag_name) { +        case "author_raw": // author_arr author (fn sn) +          j["author_arr"] = +            split(header_tag_value, rgx.arr_delimiter); +          string tmp; +          biblioAuthorLoop: +          foreach (au; j["author_arr"].array) { +            if (auto x = match(au.str, rgx.name_delimiter)) { +              tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", "; +            } else { +              tmp ~= au.str; +            } +          } +          tmp = replace(tmp, rgx.trailing_comma, ""); +          // tmp = replace(tmp, regex(r"(,[ ]*)$","g"), ""); +          j["author"].str = tmp; +          break; +        case "editor_raw": // editor_arr editor (fn sn) +          j["editor_arr"] = +            split(header_tag_value, rgx.arr_delimiter); +          string tmp; +          biblioEditorLoop: +          foreach (ed; j["editor_arr"].array) { +            if (auto x = match(ed.str, rgx.name_delimiter)) { +              tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", "; +            } else { +              tmp ~= ed.str; +            } +          } +          tmp = replace(tmp, rgx.trailing_comma, ""); +          // tmp = replace(tmp, regex(r"(,[ ]*)$","g"), ""); +          j["editor"].str = tmp; +          break; +        case "fulltitle": // title & subtitle +          break; +        default: +          break; +        } +        // header_tag_value=""; +        auto s = to!string(j); +        s = j.toString(); +        debug(biblio) { +          writefln( +            "%s* %s%s: %s\n%s", +            scr_txt_color["red"], +            scr_txt_color["off"], +            biblio_tag_name, +            biblio_tag_entry, +            j[biblio_tag_name] +          ); +        } +        biblio_arr_json ~= s; +        biblio_tag_entry=""; +      } +      return 0; +    } +    auto poem_block( +      char[] line, +      ref string[string] an_object, +      ref int[string] type, +      ref long counter, +      string[string] obj_cite_number_poem +    ) { +      if (type["curly_poem"] == TriState.on) { +        if (auto m = match(line, rgx.block_curly_poem_close)) { +          an_object["obj"]="verse"; // check that this is as you please +          debug(poem) {                            // poem (curly) close +            writefln( +              "%s* [poem curly] %s%s", +              scr_txt_color["red"], +              scr_txt_color["off"], +              line +            ); +          } +          if (processing.length > 0) { +            an_object["obj"] = processing["verse"]; +          } +          debug(poem) {                            // poem (curly) close +            writeln(__LINE__); +            writefln( +              "%s%s %s", +              scr_txt_marker["fuchsia"], +              obj_cite_number, +              line +            ); +            // writeln(an_object.keys); +            // writeln(an_object.length); +          } +          if (an_object.length > 0) { +            debug(poem) {                            // poem (curly) close +              tell_lo( +                "fuchsia", +                obj_cite_number, +                an_object["obj"] +              ); +            } +            an_object["is"] = "verse"; +            an_object["substantive"] = +              obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +            an_object["attrib"] = +              obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +            contents_the_objects ~= +              set_abstract_object.contents_block( +                an_object["is"], +                an_object["substantive"], +                an_object["attrib"], +                obj_cite_number +              ); +            object_reset(an_object); +            processing.remove("verse"); +            ++counter; +          } +          obj_cite_number_poem["end"] = +            to!string(obj_cite_number); +          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 = +              obj_cite_number_emit(type["obj_cite_number_status"]); +            type["verse_new"] = State.off; +          } else if (match(line, rgx.line_delimiter_only)) { +            verse_line = TriState.off; +            type["verse_new"] = State.on; +          } +          if (type["verse_new"] == State.on) { +            verse_line=1; +            an_object["obj"] = processing["verse"]; +            debug(poem) {                          // poem verse +              writefln( +                "%s%s curly\n%s", +                scr_txt_marker["green"], +                obj_cite_number, +                an_object["obj"] +              ); +            } +            processing.remove("verse"); +            an_object["is"] = "verse"; +            node = node_jstr( +              content_non_header, +              obj_cite_number, +              counter, +              heading_pointer-1, +              an_object["is"] +            ); +            an_object["substantive"] = +              obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +            an_object["attrib"] = +              obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +            contents_the_objects ~= +              set_abstract_object.contents_block( +                an_object["is"], +                an_object["substantive"], +                an_object["attrib"], +                obj_cite_number +              ); +            object_reset(an_object); +            processing.remove("verse"); +            ++counter; +          } +        } +      } else if (type["tic_poem"] == TriState.on) { +        if (auto m = match(line, rgx.block_tic_close)) { // tic_poem_close +          an_object["obj"]="verse"; // check that this is as you please +          debug(poem) {                            // poem (curly) close +            writefln( +              "%s* [poem tic] %s%s", +              scr_txt_color["red"], +              scr_txt_color["off"], +              line +            ); +          } +          if (processing.length > 0) {       // needs looking at +            an_object["obj"] = processing["verse"]; +          } +          if (an_object.length > 0) { +            debug(poem) {                            // poem (tic) close +              writeln(__LINE__); +              tell_lo("fuchsia", obj_cite_number, line); +            } +            processing.remove("verse"); +            an_object["is"] = "verse"; +            an_object["substantive"] = +              obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +            an_object["attrib"] = +              obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +            contents_the_objects ~= +              set_abstract_object.contents_block( +                an_object["is"], +                an_object["substantive"], +                an_object["attrib"], +                obj_cite_number +              ); +            obj_cite_number_poem["end"] = to!string(obj_cite_number); +            object_reset(an_object); +            processing.remove("verse"); +            ++counter; +          } +          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 = +              obj_cite_number_emit(type["obj_cite_number_status"]); +            type["verse_new"] = State.off; +          } else if (match(line, rgx.line_delimiter_only)) { +            type["verse_new"] = State.on; +            verse_line = TriState.off; +          } +          if (type["verse_new"] == State.on) { +            verse_line=1; +            an_object["obj"] = processing["verse"]; +            debug(poem) {                            // poem (tic) close +              writefln( +                "%s%s tic\n%s", +                scr_txt_marker["green"], +                obj_cite_number, +                an_object["obj"] +              ); +            } +            processing.remove("verse"); +            an_object["is"] = "verse"; +            node = +              node_jstr( +                content_non_header, +                obj_cite_number, +                counter, +                heading_pointer-1, +                an_object["is"] +              ); +            an_object["substantive"] = +              obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +            an_object["attrib"] = +              obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +            contents_the_objects ~= +              set_abstract_object.contents_block( +                an_object["is"], +                an_object["substantive"], +                an_object["attrib"], +                obj_cite_number +              ); +            object_reset(an_object); +            processing.remove("verse"); +            ++counter; +          } +        } +      } +      return 0; +    } +    auto group_block( +      char[] line, +      ref string[string] an_object, +      ref int[string] type +    ) { +      if (type["curly_group"] == State.on) { +        if (match(line, rgx.block_curly_group_close)) { +          debug(group) {                           // group (curly) close +            tell_l("blue", line); +          } +          type["blocks"] = TriState.closing; +          type["group"] = TriState.closing; +          type["curly_group"] = TriState.off; +        } else { +          debug(group) {                           // group +            tell_l("blue", line); +          } +          an_object["obj"] ~= line ~= "\n";           // build group array (or string) +        } +      } else if (type["tic_group"] == TriState.on) { +        if (match(line, rgx.block_tic_close)) { +          debug(group) {                           // group (tic) close +            tell_l("blue", line); +          } +          type["blocks"] = TriState.closing; +          type["group"] = TriState.closing; +          type["tic_group"] = TriState.off; +        } else { +          debug(group) {                           // group +            tell_l("blue", line); +          } +          an_object["obj"] ~= line ~= "\n";           // build group array (or string) +        } +      } +      return 0; +    } +    auto block_block( +      char[] line, +      ref string[string] an_object, +      ref int[string] type +    ) { +      if (type["curly_block"] == TriState.on) { +        if (match(line, rgx.block_curly_block_close)) { +          debug(block) {                           // block (curly) close +            tell_l("blue", line); +          } +          type["blocks"] = TriState.closing; +          type["block"] = TriState.closing; +          type["curly_block"] = TriState.off; +        } else { +          debug(block) {                           // block +            tell_l("blue", line); +          } +          an_object["obj"] ~= line ~= "\n";           // build block array (or string) +        } +      } else if (type["tic_block"] == TriState.on) { +        if (match(line, rgx.block_tic_close)) { +          debug(block) {                           // block (tic) close +            tell_l("blue", line); +          } +          type["blocks"] = TriState.closing; +          type["block"] = TriState.closing; +          type["tic_block"] = TriState.off; +        } else { +          debug(block) {                           // block +            tell_l("blue", line); +          } +          an_object["obj"] ~= line ~= "\n";           // build block array (or string) +        } +      } +      return 0; +    } +    auto quote_block(char[] line, ref string[string] an_object, ref int[string] type) { +      if (type["curly_quote"] == TriState.on) { +        if (match(line, rgx.block_curly_quote_close)) { +          debug(quote) {                           // quote (curly) close +            tell_l("blue", line); +          } +          type["blocks"] = TriState.closing; +          type["quote"] = TriState.closing; +          type["curly_quote"] = TriState.off; +        } else { +          debug(quote) {                           // quote +            tell_l("blue", line); +          } +          an_object["obj"] ~= line ~= "\n";           // build quote array (or string) +        } +      } else if (type["tic_quote"] == TriState.on) { +        if (match(line, rgx.block_tic_close)) { +          debug(quote) {                           // quote (tic) close +            tell_l("blue", line); +          } +          type["blocks"] = TriState.closing; +          type["quote"] = TriState.closing; +          type["tic_quote"] = TriState.off; +        } else { +          debug(quote) {                           // quote +            tell_l("blue", line); +          } +          an_object["obj"] ~= line ~= "\n";           // build quote array (or string) +        } +      } +      return 0; +    } +    auto table_block(char[] line, ref string[string] an_object, ref int[string] type) { +      if (type["curly_table"] == TriState.on) { +        if (match(line, rgx.block_curly_table_close)) { +          debug(table) {                           // table (curly) close +            tell_l("blue", line); +          } +          type["blocks"] = TriState.closing; +          type["table"] = TriState.closing; +          type["curly_table"] = TriState.off; +        } else { +          debug(table) {                           // table +            tell_l("blue", line); +          } +          an_object["obj"] ~= line ~= "\n";           // build table array (or string) +        } +      } else if (type["tic_table"] == TriState.on) { +        if (match(line, rgx.block_tic_close)) { +          debug(table) {                           // table (tic) close +            tell_l("blue", line); +          } +          type["blocks"] = TriState.closing; +          type["table"] = TriState.closing; +          type["tic_table"] = TriState.off; +        } else { +          debug(table) {                           // table +            tell_l("blue", line); +          } +          an_object["obj"] ~= line ~= "\n";           // build table array (or string) +        } +      } +      return 0; +    } +    auto block_flag_line_empty( +      char[] line, +      ref string[string] an_object, +      ref ObjComposite[] contents_the_objects, +      ref string[][string][string] bookindex_unordered_hashes, +      ref int obj_cite_number, +      ref string node, +      ref long counter, +      ref int[string] type, +      string[string] obj_cite_number_poem +    ) { +      // line.empty, post contents, empty variables --------------- +      assert( +        line.empty, +        "line should be empty" +      ); +      assert( +        (type["blocks"] == TriState.closing), +        "code block status: closed" +      ); +      assertions_flag_types_block_status_none_or_closed(type); +      if (type["code"] == TriState.closing) { +        obj_cite_number = +          obj_cite_number_emit(type["obj_cite_number_status"]); +        an_object["bookindex"] = +          ("bookindex" in an_object) ? an_object["bookindex"] : ""; +        bookindex_unordered_hashes = +          bkidx_hash(an_object["bookindex"], obj_cite_number); +        an_object["is"] = "code"; +        node = +          node_jstr( +            content_non_header, +            obj_cite_number, +            counter, +            heading_pointer-1, +            an_object["is"] +          ); +        an_object["substantive"] = +          obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +        an_object["attrib"] = +          obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +        contents_the_objects ~= +          set_abstract_object.contents_block( +            an_object["is"], +            an_object["substantive"], +            an_object["attrib"], +            obj_cite_number +          ); +        object_reset(an_object); +        processing.remove("verse"); +        ++counter; +        type["blocks"] = TriState.off; +        type["code"] = TriState.off; +      } else if (type["poem"] == TriState.closing) { +        an_object["bookindex"] = +          ("bookindex" in an_object) ? an_object["bookindex"] : ""; +        bookindex_unordered_hashes = +          bkidx_hash(an_object["bookindex"], obj_cite_number); +        // obj_cite_number = obj_cite_number_emit(type["obj_cite_number_status"]); +        an_object["is"] = "verse"; // check also +        node = +          node_jstr( +            content_non_header, +            obj_cite_number, +            counter, +            heading_pointer-1, +            an_object["is"] +            // "verse" +          ); +        contents_the_objects ~= +          set_abstract_object.contents_block_obj_cite_number_string( +            "poem", +            "", +            (obj_cite_number_poem["start"], obj_cite_number_poem["end"]), +            node +          ); // bookindex +        object_reset(an_object); +        processing.remove("verse"); +        // ++obj_cite_number; +        type["blocks"] = TriState.off; +        type["poem"] = TriState.off; +      } else if (type["table"] == TriState.closing) { +        obj_cite_number = +          obj_cite_number_emit(type["obj_cite_number_status"]); +        an_object["bookindex"] = +          ("bookindex" in an_object) ? an_object["bookindex"] : ""; +        bookindex_unordered_hashes = +          bkidx_hash(an_object["bookindex"], obj_cite_number); +        an_object["is"] = "table"; +        node = +          node_jstr( +            content_non_header, +            obj_cite_number, +            counter, +            heading_pointer-1, +            an_object["is"] +          ); +        an_object["substantive"] = +          obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +        an_object["attrib"] = +          obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +        contents_the_objects ~= +          set_abstract_object.contents_block( +            an_object["is"], +            an_object["substantive"], +            an_object["attrib"], +            obj_cite_number +          ); +        object_reset(an_object); +        processing.remove("verse"); +        ++counter; +        type["blocks"] = TriState.off; +        type["table"] = TriState.off; +      } else if (type["group"] == TriState.closing) { +        obj_cite_number = +          obj_cite_number_emit(type["obj_cite_number_status"]); +        an_object["bookindex"] = +          ("bookindex" in an_object) ? an_object["bookindex"] : ""; +        bookindex_unordered_hashes = +          bkidx_hash(an_object["bookindex"], obj_cite_number); +        an_object["is"] = "group"; +        node = +          node_jstr( +            content_non_header, +            obj_cite_number, +            counter, +            heading_pointer-1, +            an_object["is"] +          ); +        an_object["substantive"] = +          obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +        an_object["attrib"] = +          obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +        contents_the_objects ~= +          set_abstract_object.contents_block( +            an_object["is"], +            an_object["substantive"], +            an_object["attrib"], +            obj_cite_number +          ); +        object_reset(an_object); +        processing.remove("verse"); +        ++counter; +        type["blocks"] = TriState.off; +        type["group"] = TriState.off; +      } else if (type["block"] == TriState.closing) { +        obj_cite_number = obj_cite_number_emit(type["obj_cite_number_status"]); +        an_object["bookindex"] = +          ("bookindex" in an_object) ? an_object["bookindex"] : ""; +        bookindex_unordered_hashes = +          bkidx_hash(an_object["bookindex"], obj_cite_number); +        an_object["is"] = "block"; +        node = +          node_jstr( +            content_non_header, +            obj_cite_number, +            counter, +            heading_pointer-1, +            an_object["is"] +           ); +        an_object["substantive"] = +          obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +        an_object["attrib"] = +          obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +        contents_the_objects ~= +          set_abstract_object.contents_block( +            an_object["is"], +            an_object["substantive"], +            an_object["attrib"], +            obj_cite_number +          ); +        object_reset(an_object); +        processing.remove("verse"); +        ++counter; +        type["blocks"] = TriState.off; +        type["block"] = TriState.off; +      } else if (type["quote"] == TriState.closing) { +        obj_cite_number = +          obj_cite_number_emit(type["obj_cite_number_status"]); +        an_object["bookindex"] = +          ("bookindex" in an_object) ? an_object["bookindex"] : ""; +        bookindex_unordered_hashes = +          bkidx_hash(an_object["bookindex"], obj_cite_number); +        an_object["is"] = "quote"; +        node = +          node_jstr( +            content_non_header, +            obj_cite_number, +            counter, +            heading_pointer-1, +            an_object["is"] +          ); +        an_object["substantive"] = +          obj_im.obj_inline_markup(an_object["is"], an_object["obj"]); +        an_object["attrib"] = +          obj_att.obj_attributes(an_object["is"], an_object["obj"], node); +        contents_the_objects ~= +          set_abstract_object.contents_block( +            an_object["is"], +            an_object["substantive"], +            an_object["attrib"], +            obj_cite_number +          ); +        object_reset(an_object); +        processing.remove("verse"); +        ++counter; +        type["blocks"] = TriState.off; +        type["quote"] = TriState.off; +      } +      return 0; +    } +    auto book_index( +      char[] line, +      ref string book_idx_tmp, +      ref string[string] an_object, +      ref int[string] type +    ) { +      if (auto m = match(line, rgx.book_index)) { +        /+ match book_index +/ +        debug(bookindexmatch) {                       // book index +          writefln( +            "%s* [bookindex] %s%s\n", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            to!string(m.captures[1]), +          ); +          // writeln(scr_txt_marker["blue"], to!string(m.captures[1]), "\n"); +        } +        an_object["bookindex"] = to!string(m.captures[1]); +      } else if (auto m = match(line, rgx.book_index_open))  { +        /+ match open book_index +/ +        type["book_index"] = State.on; +        book_idx_tmp = to!string(m.captures[1]); +        debug(bookindexmatch) {                       // book index +          writefln( +            "%s* [bookindex] %s%s\n", +            scr_txt_color["blue"], +            scr_txt_color["off"], +            book_idx_tmp, +          ); +          // writeln(scr_txt_marker["blue"], book_idx_tmp, "\n"); +        } +      } else if (type["book_index"] == State.on )  { +        /+ book_index flag set +/ +        if (auto m = match(line, rgx.book_index_close))  { +          type["book_index"] = State.off; +          an_object["bookindex"] = book_idx_tmp ~ to!string(m.captures[1]); +          debug(bookindexmatch) {                     // book index +            writefln( +              "%s* [bookindex] %s%s\n", +              scr_txt_color["blue"], +              scr_txt_color["off"], +              book_idx_tmp, +            ); +            // writeln(scr_txt_marker["blue"], book_idx_tmp, "\n"); +          } +          book_idx_tmp = ""; +        } else { +          book_idx_tmp ~= line; +        } +      } +    } +    auto header_extract( +      char[] line, +      ref int[string] line_occur, +      ref string[string] an_object, +      ref int[string] type +    ) { +      if (auto m = match(line, rgx.header_make)) { +        /+ matched header_make +/ +        debug(header1) {                          // header +          tell_l("yellow", line); +        } +        type["header"] = State.on; +        type["header_make"] = State.on; +        type["header_metadata"] = State.off; +        type["heading"] = State.off; +        type["para"] = State.off; +        ++line_occur["header_make"]; +        an_object["obj"] ~= line ~= "\n"; +      } else if (auto m = match(line, rgx.header_metadata)) { +        /+ matched header_metadata +/ +        debug(header1) {                          // header +          tell_l("yellow", line); +        } +        type["header"] = State.on; +        type["header_make"] = State.off; +        type["header_metadata"] = State.on; +        type["heading"] = State.off; +        type["para"] = State.off; +        ++line_occur["header_metadata"]; +        an_object["obj"] ~= line ~= "\n"; +      } else if (type["header_make"] == State.on +      && (line_occur["header_make"] > State.off)) { +        /+ header_make flag set +/ +        if (auto m = match(line, rgx.header_sub)) { +          /+ sub-header +/ +          debug(header1) { +            tell_l("yellow", line); +          } +          // type["header"] = State.on; +          ++line_occur["header_make"]; +          an_object["obj"] ~= line ~= "\n"; +        } +      } else if (type["header_metadata"] == State.on +      && (line_occur["header_metadata"] > State.off)) { +        /+ header_metadata flag set +/ +        if (auto m = match(line, rgx.header_sub)) { +          /+ sub-header +/ +          debug(header1) { +            tell_l("yellow", line); +          } +          ++line_occur["header_metadata"]; +          an_object["obj"] ~= line ~= "\n"; +        } +      } +      return 0; +    } +    auto heading_found( +      char[] line, +      string dochead_make_headings, +      ref string[string] heading_match_str, +      ref Regex!(char)[string] heading_match_rgx, +      ref int[string] type +    ) { +      if ((to!string(dochead_make_headings).length > 2) +      && (type["make_headings"] == State.off)) { +        /+ headings found +/ +        debug(headingsfound) { +          writeln(dochead_make_headings); +        } +        auto make_headings_txt = +          match( +            to!string(dochead_make_headings), +            rgx.within_quotes); +        char[][] make_headings_spl = +          split( +            cast(char[]) make_headings_txt.captures[1], +            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"] = +              "^(" ~ to!string(make_headings_spl[6]) ~ ")"; +            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"] = +              "^(" ~ to!string(make_headings_spl[5]) ~ ")"; +            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"] = +              "^(" ~ to!string(make_headings_spl[4]) ~ ")"; +            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"] = +              "^(" ~ to!string(make_headings_spl[3]) ~ ")"; +            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"] = +              "^(" ~ to!string(make_headings_spl[2]) ~ ")"; +            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"] = +              "^(" ~ to!string(make_headings_spl[1]) ~ ")"; +            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"] = +              "^(" ~ to!string(make_headings_spl[0]) ~ ")"; +            heading_match_rgx["h_B"] = +              regex(heading_match_str["h_B"]); +          } +          break; +        default: +          break; +        } +        type["make_headings"] = State.on; +      } +    } +    auto heading_make_set( +      ref char[] line, +      ref int[string] line_occur, +      ref Regex!(char)[string] heading_match_rgx, +      ref int[string] 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 +/ +        if (match(line, heading_match_rgx["h_B"])) { +          line = "B~ " ~ line; +          debug(headingsfound) { +            writeln(line); +          } +        } +        if (match(line, heading_match_rgx["h_C"])) { +          line = "C~ " ~ line; +          debug(headingsfound) { +            writeln(line); +          } +        } +        if (match(line, heading_match_rgx["h_D"])) { +          line = "D~ " ~ line; +          debug(headingsfound) { +            writeln(line); +          } +        } +        if (match(line, heading_match_rgx["h_1"])) { +          line = "1~ " ~ line; +          debug(headingsfound) { +            writeln(line); +          } +        } +        if (match(line, heading_match_rgx["h_2"])) { +          line = "2~ " ~ line; +          debug(headingsfound) { +            writeln(line); +          } +        } +        if (match(line, heading_match_rgx["h_3"])) { +          line = "3~ " ~ line; +          debug(headingsfound) { +            writeln(line); +          } +        } +        if (match(line, heading_match_rgx["h_4"])) { +          line = "4~ " ~ line; +          debug(headingsfound) { +            writeln(line); +          } +        } +      } +    } +    auto heading_match( +      char[] line, +      ref int[string] line_occur, +      ref string[string] an_object, +      ref int[string] lv, +      ref int[string] collapsed_lev, +      ref int[string] type +    ) { +      if (auto m = match(line, rgx.heading)) { +        /+ heading match +/ +        type["heading"] = State.on; +        type["header"] = State.off; +        type["header_make"] = State.off; +        type["header_metadata"] = State.off; +        type["heading_biblio"] = State.off; +        type["para"] = State.off; +        ++line_occur["heading"]; +        an_object["obj"] ~= 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": +          collapsed_lev["h0"] = 1; +          an_object["lev_collapsed_number"] = +            to!string(collapsed_lev["h0"]); +          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"] = +            to!string(collapsed_lev["h1"]); +          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"] = +            to!string(collapsed_lev["h2"]); +          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"] = +            to!string(collapsed_lev["h3"]); +          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"] = +            to!string(collapsed_lev["h4"]); +          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"] = +              to!string(collapsed_lev["h5"]); +          } else if (lv["h4"] > State.off) { +            collapsed_lev["h5"] = collapsed_lev["h4"] + 1; +            an_object["lev_collapsed_number"] = +              to!string(collapsed_lev["h5"]); +          } +          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"] = +              to!string(collapsed_lev["h6"]); +          } else if (lv["h5"] > State.off) { +            collapsed_lev["h6"] = collapsed_lev["h5"] + 1; +            an_object["lev_collapsed_number"] = +              to!string(collapsed_lev["h6"]); +          } +          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"] = +              to!string(collapsed_lev["h7"]); +          } else if (lv["h6"] > State.off) { +            collapsed_lev["h7"] = collapsed_lev["h6"] + 1; +            an_object["lev_collapsed_number"] = +              to!string(collapsed_lev["h7"]); +          } +          lv["lv"] = DocStructMarkupHeading.h_text_4; +          ++lv["h7"]; +          goto default; +        default: +          an_object["lev_markup_number"] = to!string(lv["lv"]); +        } +        debug(heading) {                         // heading +          // writeln(m.captures[1], " ", m.captures[2], "\n");      // figure inclusion of post capture text +          // writeln(m.hit, "\n"); +          tell_l("yellow", strip(line)); +        } +      } +    } +    auto para_match( +      char[] line, +      ref string[string] an_object, +      ref string[string] indent, +      ref bool bullet, +      ref int[string] type +    ) { +      if (line_occur["para"] == State.off) { +        /+ para matches +/ +          // paragraphs +          // (fl  ag_type["heading"] = true) && +        if (auto m = match(line, rgx.para_indent)) { +          debug(paraindent) {                    // para indent +            tell_l("blue", line); +          } +          type["para"] = State.on; +          an_object["obj"] ~= line ~= "\n"; +          indent["first"] = to!string(m.captures[1]); +          indent["second"] = "0"; +          bullet = false; +        } else if (auto m = match(line, rgx.para_bullet)) { +          debug(parabullet) {                    // para bullet +            tell_l("blue", line); +          } +          type["para"] = State.on; +          an_object["obj"] ~= line; +          indent["first"] = "0"; +          indent["second"] = "0"; +          bullet = true; +        } else if (auto m = match(line, rgx.para_indent_hang)) { +          debug(paraindenthang) {                // para indent hang +            tell_l("blue", line); +          } +          type["para"] = State.on; +          an_object["obj"] ~= line; +          indent["first"] = to!string(m.captures[1]); +          indent["second"] = to!string(m.captures[2]); +          bullet = false; +        } else if (auto m = match(line, rgx.para_bullet_indent)) { +          debug(parabulletindent) {              // para bullet indent +            tell_l("blue", line); +          } +          type["para"] = State.on; +          an_object["obj"] ~= line; +          indent["first"] = to!string(m.captures[1]); +          indent["second"] = "0"; +          bullet = true; +        } else { +          // !line.empty +          type["para"] = State.on; +          an_object["obj"] ~= line; +          indent["first"] = "0"; +          indent["second"] = "0"; +          bullet = false; +        } +        ++line_occur["para"]; +      } +    } +    /+ abstraction functions ↑ +/ + +    /+ ↓ abstraction function emitters +/ +    struct OCNemitter { +    // class OCNemitter : AssertOCN { +      int obj_cite_number, obj_cite_number_; +      int obj_cite_number_emitter(int obj_cite_number_status_flag) +      in { assert(obj_cite_number_status_flag <= 2); } +      body { +        if (obj_cite_number_status_flag == 0) { +          obj_cite_number=++obj_cite_number_; +        } else { +          obj_cite_number=0; +        } +        assert(obj_cite_number >= 0); +        return obj_cite_number; +      } +      invariant() { +      } +    } +    struct ObjAttributes { +    // class ObjAttributes : AssertObjAttributes { +      string[string] obj_txt; +      string para_and_blocks(string obj_txt_in) +      in { } +      body { +        auto rgx = Rgx(); +        obj_txt["munge"]=obj_txt_in; +        if (match(obj_txt_in, rgx.para_bullet)) { +          obj_txt["attrib"] =" \"bullet\": \"true\"," +          ~ " \"indent_first\": 0," +          ~ " \"indent_rest\": 0,"; +        } else if (auto m = match(obj_txt_in, rgx.para_bullet_indent)) { +          obj_txt["attrib"] =" \"bullet\": \"true\"," +          ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ "," +          ~ " \"indent_rest\": " ~ to!string(m.captures[1]) ~ ","; +        } else if (auto m = match(obj_txt_in, rgx.para_indent_hang)) { +          obj_txt["attrib"] =" \"bullet\": \"false\"," +          ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ "," +          ~ " \"indent_rest\": " ~  to!string(m.captures[2]) ~ ","; +        } else if (auto m = match(obj_txt_in, rgx.para_indent)) { +          obj_txt["attrib"] =" \"bullet\": \"false\"," +          ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ "," +          ~ " \"indent_rest\": " ~ to!string(m.captures[1]) ~ ","; +        } else { +          obj_txt["attrib"] =" \"bullet\": \"false\"," +          ~ " \"indent_first\": 0," +          ~ " \"indent_rest\": 0,"; +        } +        return obj_txt["attrib"]; +      } +      string para(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"content\"," +        ~ " \"of\": \"para\"," +        ~ " \"is\": \"para\""; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +      string heading(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"content\"," +        ~ " \"of\": \"para\"," +        ~ " \"is\": \"heading\""; +        // obj_txt["struct"]=; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +      string header_make(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"head\"," +        ~ " \"of\": \"header\"," +        ~ " \"is\": \"header_make\""; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +      string header_metadata(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"head\"," +        ~ " \"of\": \"header\"," +        ~ " \"is\": \"header_metadata\""; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +      string code(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"content\"," +        ~ " \"of\": \"block\"," +        ~ " \"is\": \"code\""; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +      string group(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"content\"," +        ~ " \"of\": \"block\"," +        ~ " \"is\": \"group\""; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +      string block(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"content\"," +        ~ " \"of\": \"block\"," +        ~ " \"is\": \"block\""; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +      string verse(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"content\"," +        ~ " \"of\": \"block\"," +        ~ " \"is\": \"verse\""; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +      string quote(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"content\"," +        ~ " \"of\": \"block\"," +        ~ " \"is\": \"quote\""; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +      string table(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"content\"," +        ~ " \"of\": \"block\"," +        ~ " \"is\": \"table\""; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +      string comment(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["attrib"] = " \"use\": \"comment\"," +        ~ " \"of\": \"comment\"," +        ~ " \"is\": \"comment\""; +        return obj_txt["attrib"]; +      } +      invariant() { +      } +    } +    struct ObjInlineMarkupMunge { +    // struct ObjInlineMarkupMunge : AssertObjInlineMarkup { +      string[string] obj_txt; +      int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus; +      string obj_txt_out, tail, note; +      private auto initialize_note_numbers() { +        n_foot = 0; +        n_foot_reg = 0; +        n_foot_sp_asterisk = 0; +        n_foot_sp_plus = 0; +      } +      private auto object_notes_(string obj_txt_in) +      in { } +      body { +        auto rgx = Rgx(); +        auto mkup = InlineMarkup(); +        obj_txt_out = ""; +        tail = ""; +        obj_txt_in = replaceAll( +          obj_txt_in, +          rgx.inline_notes_curly_sp_asterisk, +          (mkup.en_a_o ~ "*" ~ " $1" ~ mkup.en_a_c) +        ); +        obj_txt_in = +          replaceAll( +            obj_txt_in, +            rgx.inline_notes_curly_sp_plus, +            (mkup.en_a_o ~ "+" ~ " $1" ~ mkup.en_a_c) +          ); +        obj_txt_in = +          replaceAll( +            obj_txt_in, +            rgx.inline_notes_curly, +            (mkup.en_a_o ~ " $1" ~ mkup.en_a_c) +          ); +        if (match(obj_txt_in, rgx.inline_notes_al_gen)) { +          foreach(m; matchAll(obj_txt_in, rgx.inline_text_and_note_al)) { +            if (match(obj_txt_in, rgx.inline_al_delimiter_open_asterisk)) { +              ++n_foot_sp_asterisk; +              n_foot=n_foot_sp_asterisk; +            } else if (match(obj_txt_in, rgx.inline_al_delimiter_open_plus)) { +              ++n_foot_sp_plus; +              n_foot=n_foot_sp_plus; +            } else { +              ++n_foot_reg; +              n_foot=n_foot_reg; +            } +            obj_txt_out ~= replaceFirst( +              m.hit, +              rgx.inline_al_delimiter_open_regular, +              (mkup.en_a_o ~ to!string(n_foot)) +            ); +            tail = m.post; +            // if (!empty(m.post)) { +            //   tail = m.post; +            // } else { +            //   tail = ""; +            // } +          } +        } else { +          obj_txt_out = obj_txt_in; +        } +        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); +          } +        } +        return obj_txt_out; +      } +      string para(string obj_txt_in) +      in { } +      body { +        auto rgx = Rgx(); +        obj_txt["munge"]=obj_txt_in; +        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.para_attribs, ""); +        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.obj_cite_number_off_all, ""); +        obj_txt["munge"]=object_notes_(obj_txt["munge"]); +        debug(munge) { +          writeln(__LINE__); +          writeln(obj_txt_in); +          writeln(__LINE__); +          writeln(to!string(obj_txt["munge"])); +        } +        return obj_txt["munge"]; +      } +      string heading(string obj_txt_in) +      in { } +      body { +        auto rgx = Rgx(); +        obj_txt["munge"]=obj_txt_in; +        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.heading, ""); +        obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.obj_cite_number_off_all, ""); +        obj_txt["munge"]=object_notes_(obj_txt["munge"]); +        debug(munge) { +          writeln(__LINE__); +          writeln(obj_txt_in); +          writeln(__LINE__); +          writeln(to!string(obj_txt["munge"])); +        } +        return obj_txt["munge"]; +      } +      invariant() { +      } +      string header_make(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        return obj_txt["munge"]; +      } +      invariant() { +      } +      string header_metadata(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        return obj_txt["munge"]; +      } +      invariant() { +      } +      string code(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        return obj_txt["munge"]; +      } +      invariant() { +      } +      string group(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["munge"]=object_notes_(obj_txt["munge"]); +        return obj_txt["munge"]; +      } +      invariant() { +      } +      string block(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["munge"]=object_notes_(obj_txt["munge"]); +        return obj_txt["munge"]; +      } +      invariant() { +      } +      string verse(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        obj_txt["munge"]=object_notes_(obj_txt["munge"]); +        return obj_txt["munge"]; +      } +      invariant() { +      } +      string quote(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        return obj_txt["munge"]; +      } +      invariant() { +      } +      string table(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        return obj_txt["munge"]; +      } +      invariant() { +      } +      string comment(string obj_txt_in) +      in { } +      body { +        obj_txt["munge"]=obj_txt_in; +        return obj_txt["munge"]; +      } +      invariant() { +      } +    } +    struct ObjInlineMarkup { +    // struct ObjInlineMarkup : AssertObjInlineMarkup { +      auto munge = ObjInlineMarkupMunge(); +      string[string] obj_txt; +      string obj_inline_markup(string obj_is_, string obj_raw) +      in { } +      body { +        obj_txt["munge"]=obj_raw.dup; +        obj_txt["munge"]=(match(obj_is_, ctRegex!(`verse|code`))) +          ? obj_txt["munge"] +          : strip(obj_txt["munge"]); +        switch (obj_is_) { +        case "header_make": +          obj_txt["munge"]=munge.header_make(obj_txt["munge"]); +          break; +        case "header_metadata": +          obj_txt["munge"]=munge.header_metadata(obj_txt["munge"]); +          break; +        case "heading": +          obj_txt["munge"]=munge.heading(obj_txt["munge"]); +          break; +        case "para": +          obj_txt["munge"]=munge.para(obj_txt["munge"]); +          break; +        case "code": +          obj_txt["munge"]=munge.code(obj_txt["munge"]); +          break; +        case "group": +          obj_txt["munge"]=munge.group(obj_txt["munge"]); +          break; +        case "block": +          obj_txt["munge"]=munge.block(obj_txt["munge"]); +          break; +        case "verse": +          obj_txt["munge"]=munge.verse(obj_txt["munge"]); +          break; +        case "quote": +          obj_txt["munge"]=munge.quote(obj_txt["munge"]); +          break; +        case "table": +          obj_txt["munge"]=munge.table(obj_txt["munge"]); +          break; +        case "comment": +          obj_txt["munge"]=munge.comment(obj_txt["munge"]); +          break; +        case "doc_end_reset": +          munge.initialize_note_numbers(); +          break; +        default: +          break; +        } +        return obj_txt["munge"]; +      } +      invariant() { +      } +    } +    struct ObjAttrib { +    // struct ObjAttrib : AssertObjAttrib { +    // auto sink = appender!(char[])(); +      auto attrib = ObjAttributes(); +      string[string] obj_attrib; +      string obj_attributes(string obj_is_, string obj_raw, string node) +      in { } +      body { +        // string s = "{ \"language\": \"D\", \"rating\": 3.14, \"code\": \"42\" }"; +        scope(exit) { +          // destroy(obj_is_); +          destroy(obj_raw); +          destroy(node); +        } +        JSONValue node_j = parseJSON(node); +        obj_attrib.remove("json"); +        obj_attrib["json"] ="{"; +        switch (obj_is_) { +        case "header_make": +          obj_attrib["json"] ~= attrib.header_make(obj_raw); +          break; +        case "header_metadata": +          obj_attrib["json"] ~= attrib.header_metadata(obj_raw); +          break; +        case "heading": +          obj_attrib["json"] ~= attrib.heading(obj_raw); // +          break; +        case "para": +          obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw) +          ~ attrib.para(obj_raw); +          break; +        case "code": +          obj_attrib["json"] ~= attrib.code(obj_raw); +          break; +        case "group": +          obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw) +          ~ attrib.group(obj_raw); +          break; +        case "block": +          obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw) +          ~ attrib.block(obj_raw); +          break; +        case "verse": +          obj_attrib["json"] ~= attrib.verse(obj_raw); +          break; +        case "quote": +          obj_attrib["json"] ~= attrib.quote(obj_raw); +          break; +        case "table": +          obj_attrib["json"] ~= attrib.table(obj_raw); +          break; +        case "comment": +          obj_attrib["json"] ~= attrib.comment(obj_raw); +          break; +        default: +          obj_attrib["json"] ~= attrib.para(obj_raw); +          break; +        } +        obj_attrib["json"] ~=" }"; +        JSONValue oa_j = parseJSON(obj_attrib["json"]); +        assert( +          (oa_j.type == JSON_TYPE.OBJECT) && +          (node_j.type == JSON_TYPE.OBJECT) +        ); +        if (obj_is_ == "heading") { +          oa_j.object["obj_cite_number"] = node_j["obj_cite_number"]; +          oa_j.object["lev_markup_number"] = node_j["lev_markup_number"]; +          oa_j.object["lev_collapsed_number"] = node_j["lev_collapsed_number"]; +          oa_j.object["heading_pointer"] = +            node_j["heading_pointer"]; // check +          oa_j.object["doc_object_pointer"] = +            node_j["doc_object_pointer"]; // check +        } +        oa_j.object["parent_obj_cite_number"] = node_j["parent_obj_cite_number"]; +        oa_j.object["parent_lev_markup_number"] = node_j["parent_lev_markup_number"]; +        obj_attrib["json"] = oa_j.toString(); +        debug(structattrib) { +          if (oa_j["is"].str() == "heading") { +            // writeln(__LINE__); +            writeln(obj_attrib["json"]); +            // writeln(node); +            writeln( +              "is: ", oa_j["is"].str(), +              "; obj_cite_number: ", oa_j["obj_cite_number"].integer() +            ); +          } +        } +        // obj_attrib["json"]="{}"; +        return obj_attrib["json"]; +      } +      invariant() { +      } +    } +    struct HeaderDocMetadataMakeJson { +    // class HeaderMetadataMakeHash : AssertHeaderMetadataMakeJson { +      auto rgx = Rgx(); +      string hm, hs; +      auto header_metadata_and_make_jsonstr( +        string header, +        JSONValue[string] dochead_metadata, +        JSONValue[string] dochead_make +      ) +      in { } +      body { +        scope(exit) { +          destroy(header); +          destroy(dochead_metadata); +          destroy(dochead_make); +        } +        if (auto t = match(header, rgx.head_main)) { +          char[][] obj_spl = split( +            cast(char[]) header, +            rgx.line_delimiter_ws_strip +          ); +          auto hm = to!string(t.captures[1]); +          if (match(hm, rgx.main_headers)) { +            foreach (line; obj_spl) { +              if (auto m = match(line, rgx.head_main)) { +                if (!empty(m.captures[2])) { +                  if (hm == "creator") { +                    dochead_metadata[hm]["author"].str = +                      to!string(m.captures[2]); +                  } else if (hm == "title") { +                    dochead_metadata[hm]["main"].str = +                      to!string(m.captures[2]); +                  } else if (hm == "publisher") { +                    dochead_metadata[hm]["name"].str = +                      to!string(m.captures[2]); +                  } +                } +              } else if (auto s = match(line, rgx.head_sub)) { +                if (!empty(s.captures[2])) { +                  auto hs = to!string(s.captures[1]); +                  if ((hm == "make" ) +                  && (dochead_make[hm].type() == JSON_TYPE.OBJECT)) { +                    switch (hm) { +                    case "make": +                      if (match(hs, rgx.subhead_make)) { +                        if (dochead_make[hm][hs].type() == JSON_TYPE.STRING) { +                          dochead_make[hm][hs].str = to!string(s.captures[2]); +                        } +                      } else { +                        writeln("not a valid header type:", hm, ":", hs); +                        destroy(hm); +                        destroy(hs); +                      } +                      break; +                    default: +                      break; +                    } +                  } else if (dochead_metadata[hm].type() == JSON_TYPE.OBJECT) { +                    switch (hm) { +                    case "creator": +                      if (match(hs, rgx.subhead_creator)) { +                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { +                          dochead_metadata[hm][hs].str = +                            to!string(s.captures[2]); +                        } +                      } else { +                        writeln("not a valid header type:", hm, ":", hs); +                        destroy(hm); +                        destroy(hs); +                      } +                      break; +                    case "title": +                      if (match(hs, rgx.subhead_title)) { +                        if ((hs == "subtitle") +                        && (dochead_metadata[hm]["sub"].type() == JSON_TYPE.STRING)) { +                          dochead_metadata[hm]["sub"].str = +                            to!string(s.captures[2]); +                        } else if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { +                          dochead_metadata[hm][hs].str = +                            to!string(s.captures[2]); +                        } +                      } else { +                        writeln("not a valid header type:", hm, ":", hs); +                        destroy(hm); +                        destroy(hs); +                      } +                      break; +                    case "rights": +                      if (match(hs, rgx.subhead_rights)) { +                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { +                          dochead_metadata[hm][hs].str = +                            to!string(s.captures[2]); +                        } +                      } else { +                        writeln("not a valid header type:", hm, ":", hs); +                        destroy(hm); +                        destroy(hs); +                      } +                      break; +                    case "date": +                      if (match(hs, rgx.subhead_date)) { +                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { +                          dochead_metadata[hm][hs].str = +                            to!string(s.captures[2]); +                        } +                      } else { +                        writeln("not a valid header type:", hm, ":", hs); +                        destroy(hm); +                        destroy(hs); +                      } +                      break; +                    case "original": +                      if (match(hs, rgx.subhead_original)) { +                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { +                          dochead_metadata[hm][hs].str = +                            to!string(s.captures[2]); +                        } +                      } else { +                        writeln("not a valid header type:", hm, ":", hs); +                        destroy(hm); +                        destroy(hs); +                      } +                      break; +                    case "classify": +                      if (match(hs, rgx.subhead_classify)) { +                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { +                          dochead_metadata[hm][hs].str = +                            to!string(s.captures[2]); +                        } +                      } else { +                        writeln("not a valid header type:", hm, ":", hs); +                        destroy(hm); +                        destroy(hs); +                      } +                      break; +                    case "identifier": +                      if (match(hs, rgx.subhead_identifier)) { +                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { +                          dochead_metadata[hm][hs].str = +                            to!string(s.captures[2]); +                        } +                      } else { +                        writeln("not a valid header type:", hm, ":", hs); +                        destroy(hm); +                        destroy(hs); +                      } +                      break; +                    case "notes": +                      if (match(hs, rgx.subhead_notes)) { +                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { +                          dochead_metadata[hm][hs].str = +                            to!string(s.captures[2]); +                        } +                      } else { +                        writeln("not a valid header type:", hm, ":", hs); +                        destroy(hm); +                        destroy(hs); +                      } +                      break; +                    case "publisher": +                      if (match(hs, rgx.subhead_publisher)) { +                        if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { +                          dochead_metadata[hm][hs].str = +                            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); +                      // if (match(hs, rgx.subhead_links)) { +                      //   if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { +                      //     dochead_metadata[hm][hs].str = to!string(s.captures[2]); +                      //   } +                      // } else { +                      //   writeln("not a valid header type:", hm, ":", hs); +                      //   destroy(hm); +                      //   destroy(hs); +                      // } +                      break; +                    default: +                      break; +                    } +                  } +                } +              } +            } +          } else { +            writeln("not a valid header type:", hm); +          } +        } +        auto t = tuple(dochead_metadata, dochead_make); +        static assert(!isTypeTuple!(t)); +        return t; +      } +      // invariant() { +      // } +    } +    class HeaderMetadataMakeHash { +    // class HeaderMetadataMakeHash : AssertHeaderMetadataMakeHash { +      auto rgx = Rgx(); +      string header_main; +      string[string] head; +      string[string] header_topic_hash(string header) +      in { } +      body { +        if (auto t = match(header, rgx.head_main)) { +          char[][] obj_spl = split( +            cast(char[]) header, +            rgx.line_delimiter_ws_strip +          ); +          auto header_main = to!string(t.captures[1]); +          head[header_main] = "{"; +          foreach (line; obj_spl) { +            if (auto m = match(line, rgx.head_main)) { +              if (!empty(m.captures[2])) { +                head[header_main] ~= +                  "\"" ~ header_main ~ +                  "\": \"" ~ +                  to!string(m.captures[2]) ~ +                  "\","; +              } +            } else if (auto s = match(line, rgx.head_sub)) { +              head[header_main] ~= "\"" ~ s.captures[1] ~ "\":"; +              if (!empty(s.captures[2])) { +                head[header_main] ~= "\"" ~ s.captures[2] ~ "\","; +              } +            } +          } +          head[header_main] = replaceFirst( +            head[header_main], +            rgx.tailing_comma, +            "" +          ); +          head[header_main] ~= "}"; +          debug(headerjson) { +            JSONValue j = parseJSON(head[header_main]); +            assert( +              (j.type == JSON_TYPE.OBJECT) +            ); +          } +        } +        return head; +      } +      invariant() { +      } +    } +    struct BookIndexNuggetHash { +    // class BookIndexNuggetHash : AssertBookIndexNuggetHash { +      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(string bookindex_section, int obj_cite_number) +      in { +        debug(bookindexraw) { +          mixin ScreenTxtColors; +          if (!bookindex_section.empty) { +            writeln( +              scr_txt_color["blue"], "* [bookindex] ", scr_txt_color["off"], +              "[", to!string(obj_cite_number), "] ", bookindex_section +            ); +          } +        } +      } +      body { +        auto rgx = Rgx(); +        if (!bookindex_section.empty) { +          auto bi_main_terms_split_arr = +            split(bookindex_section, rgx.bi_main_terms_split); +          foreach (bi_main_terms_content; bi_main_terms_split_arr) { +            auto bi_main_term_and_rest = +              split(bi_main_terms_content, rgx.bi_main_term_plus_rest_split); +            if (auto m = match( +              bi_main_term_and_rest[0], +              rgx.bi_term_and_obj_cite_numbers_match) +            ) { +              main_term = strip(m.captures[1]); +              obj_cite_number_offset = to!int(m.captures[2]); +              obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset); +              obj_cite_numbers ~= (to!string(obj_cite_number) ~ "-" ~ to!string(obj_cite_number_endpoint)); +            } else { +              main_term = strip(bi_main_term_and_rest[0]); +              obj_cite_numbers ~= to!string(obj_cite_number); +            } +            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 = +                split( +                  bi_main_term_and_rest[1], +                  rgx.bi_sub_terms_plus_obj_cite_number_offset_split +                ); +              foreach (sub_terms_bits; bi_sub_terms_split_arr) { +                if (auto m = match(sub_terms_bits, rgx.bi_term_and_obj_cite_numbers_match)) { +                  sub_term = strip(m.captures[1]); +                  obj_cite_number_offset = to!int(m.captures[2]); +                  obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset); +                  obj_cite_numbers ~= (to!string(obj_cite_number) ~ " - " ~ to!string(obj_cite_number_endpoint)); +                } else { +                  sub_term = strip(sub_terms_bits); +                  obj_cite_numbers ~= to!string(obj_cite_number); +                } +                if (!empty(sub_term)) { +                  bi[main_term][sub_term] ~= obj_cite_numbers; +                } +                obj_cite_numbers=null; +              } +            } +          } +        } +        hash_nugget = bi; +        return hash_nugget; +      } +      invariant() { +      } +    } +    struct BookIndexReport { +    // class BookIndexReport : AssertBookIndexReport { +      int mkn, skn; +      auto bookindex_report_sorted( +        string[][string][string] bookindex_unordered_hashes +      ) { +        auto mainkeys=bookindex_unordered_hashes.byKey.array. +          sort!("toLower(a) < toLower(b)", SwapStrategy.stable).release; +        foreach (mainkey; mainkeys) { +          auto subkeys=bookindex_unordered_hashes[mainkey].byKey.array. +            sort!("toLower(a) < toLower(b)", SwapStrategy.stable).release; +          foreach (subkey; subkeys) { +            debug(bookindex) { +              writeln( +                mainkey, ": ", +                subkey, ": ", +                to!string(bookindex_unordered_hashes[mainkey][subkey]) +              ); +            } +            ++skn; +          } +          ++mkn; +        } +        // return bookindex_the; +      } +    } +    struct BookIndexReportIndent { +      int mkn, skn; +      auto bookindex_report_indented( +        string[][string][string] bookindex_unordered_hashes +      ) { +        auto mainkeys= +          bookindex_unordered_hashes.byKey.array.sort().release; +        foreach (mainkey; mainkeys) { +          debug(bookindex) { +            writeln(mainkey); +          } +          auto subkeys= +            bookindex_unordered_hashes[mainkey].byKey.array.sort().release; +          foreach (subkey; subkeys) { +            debug(bookindex) { +              writeln("  ", subkey); +              writeln("    ", to!string( +                bookindex_unordered_hashes[mainkey][subkey] +              )); +            } +            // bookindex_the[mkn][mainkey][skn][subkey] ~= (bookindex_unordered_hashes[mainkey][subkey]); +            ++skn; +          } +          ++mkn; +        } +      } +    } +    struct BookIndexReportSection { +      int mkn, skn; +      auto rgx = Rgx(); +      auto bookindex_write_section( +        string[][string][string] bookindex_unordered_hashes +      ) { +        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 = replaceAll(ref_, 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 = replaceAll(ref_, rgx.book_index_go, "$1"); +              write(" {", ref_, "}#", go, ", "); +            } +            writeln(" \\\\"); +            ++skn; +          } +          ++mkn; +        } +      } +      auto bookindex_build_section( +        string[][string][string] bookindex_unordered_hashes, +        int obj_cite_number +      ) { +        string type; +        string lev, lev_markup_number, lev_collapsed_number; +        string attrib; +        string[string] indent; +        auto set_abstract_object = ObjectAbstractSet(); +        auto mainkeys = +          bookindex_unordered_hashes.byKey.array.sort().release; +        string bi_tmp; +        ObjComposite[] bookindex_section; +        // writeln(mainkeys.length); +        // B~ Book Index +        attrib=""; +        lev="B"; +        lev_markup_number="1"; +        lev_collapsed_number="1"; +        bookindex_section ~= +          set_abstract_object.contents_heading( +            "Book Index", +            attrib, +            obj_cite_number, +            to!int(lev_markup_number), +            to!int(lev_collapsed_number) +          ); +        ++obj_cite_number; +        ++mkn; +        // 1~ Index +        attrib=""; +        lev="1"; +        lev_markup_number="4"; +        lev_collapsed_number="2"; +        bookindex_section ~= +          set_abstract_object.contents_heading( +            "Index", +            attrib, +            obj_cite_number, +            to!int(lev_markup_number), +            to!int(lev_collapsed_number) +          ); +        ++obj_cite_number; +        ++mkn; +        foreach (mainkey; mainkeys) { +          bi_tmp = "!{" ~ mainkey ~ "}! "; +          // bi_tmp = "_0_1 !{" ~ mainkey ~ "}! "; +          foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { +            auto go = replaceAll(ref_, rgx.book_index_go, "$1"); +            bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", "; +          } +          bi_tmp ~= " \\\\\n    "; +          bookindex_unordered_hashes[mainkey].remove("_a"); +          auto subkeys = +            bookindex_unordered_hashes[mainkey].byKey.array.sort().release; +          foreach (subkey; subkeys) { +            bi_tmp ~= subkey ~ ", "; +            foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { +              auto go = replaceAll(ref_, rgx.book_index_go, "$1"); +              bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", "; +            } +            bi_tmp ~= " \\\\\n    "; +            ++skn; +          } +          bi_tmp = replaceFirst(bi_tmp, rgx.trailing_linebreak, ""); +          type="para"; +          attrib=""; +          indent["first"] = "0"; +          indent["second"] = "1"; +          attrib=""; +          // bookindex_section ~= +          //   set_abstract_object.contents_para( +          //     obj, +          //     obj_cite_number, +          //     indent, +          //     false +          //   ); +          bookindex_section ~= +            set_abstract_object.contents_para( +              type, +              bi_tmp, +              attrib, +              obj_cite_number, +              indent, +              false +            ); +          ++obj_cite_number; +          ++mkn; +        } +        auto t = tuple(bookindex_section, obj_cite_number); +        return t; +      } +      auto bookindex_build_section_( +        string[][string][string] bookindex_unordered_hashes +      ) { +        auto mainkeys = +          bookindex_unordered_hashes.byKey.array.sort().release; +        string bi_tmp; +        string[] bookindex_section; +        // int bi_num; +        // writeln(mainkeys.length); +        foreach (mainkey; mainkeys) { +          bi_tmp = "_0_1 !{" ~ mainkey ~ "}! "; +          foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { +            auto go = replaceAll(ref_, rgx.book_index_go, "$1"); +            bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", "; +          } +          bi_tmp ~= " \\\\\n    "; +          bookindex_unordered_hashes[mainkey].remove("_a"); +          auto subkeys = +            bookindex_unordered_hashes[mainkey].byKey.array.sort().release; +          foreach (subkey; subkeys) { +            bi_tmp ~= subkey ~ ", "; +            // bi_tmp ~= "  " ~ subkey ~ ", "; +            foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { +              auto go = replaceAll(ref_, rgx.book_index_go, "$1"); +              bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", "; +            } +            bi_tmp ~= " \\\\\n    "; +            ++skn; +          } +          bi_tmp = replaceFirst(bi_tmp, rgx.trailing_linebreak, ""); +          bookindex_section ~= bi_tmp; +          ++mkn; +        } +        return bookindex_section; +      } +    } +    struct NotesSection { +      string object_notes; +      long previous_count; +      int mkn; +      auto rgx = Rgx(); +      private auto gather_notes_for_endnote_section( +        ObjComposite[] contents_am, +        ulong counter +      ) +      in { +        // endnotes/ footnotes for +        // doc objects other than paragraphs & headings +        // various forms of grouped text +        assert((contents_am[counter].is_a == "para") +        || (contents_am[counter].is_a == "heading")); +        assert(counter > previous_count); +        previous_count=counter; +        assert( +          match(contents_am[counter].object, +          rgx.inline_notes_delimiter_al_regular_number_note) +        ); +      } +      body { +        foreach(m; +        matchAll(contents_am[counter].object, +        rgx.inline_notes_delimiter_al_regular_number_note)) { +          debug(endnotes_build) { +            writeln( +              "{^{", m.captures[1], ".}^}#noteref_", m.captures[1], " ", +              m.captures[2]); // sometimes need segment name (segmented html & epub) +            // writeln("{^{", m.captures[1], ".}^}#", contents_am[counter]["obj_cite_number"], " ", m.captures[2]); +          } +          object_notes ~= +            "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~ +            m.captures[1] ~ " " ~ m.captures[2] ~ "』"; +        } +        return object_notes; +      } +      private auto gathered_notes() +      in { +      } +      body { +        string[] endnotes_; +        if (object_notes.length > 1) { +          endnotes_ = (split(object_notes, rgx.break_string))[0..$-1]; +        } +        return endnotes_; +      } +      private auto endnote_objects(int obj_cite_number) +      in { +      } +      body { +        auto set_abstract_object = ObjectAbstractSet(); +        ObjComposite[] endnotes_section; +        auto endnotes_ = gathered_notes(); +        // auto endnotes_ = (split(object_notes, rgx.break_string))[0..$-1]; +        string type; +        string lev, lev_markup_number, lev_collapsed_number; +        string attrib; +        string[string] indent; +        // B~ Endnotes +        attrib=""; +        lev="B"; +        lev_markup_number="1"; +        lev_collapsed_number="1"; +        endnotes_section ~= +          set_abstract_object.contents_heading( +            "Endnotes", +            attrib, +            obj_cite_number, +            to!int(lev_markup_number), +            to!int(lev_collapsed_number) +          ); +        ++obj_cite_number; +        ++mkn; +        // 1~ Endnotes +        attrib=""; +        lev="1"; +        lev_markup_number="4"; +        lev_collapsed_number="2"; +        endnotes_section ~= +          set_abstract_object.contents_heading( +            "Endnotes", +            attrib, +            obj_cite_number, +            to!int(lev_markup_number), +            to!int(lev_collapsed_number) +          ); +        ++obj_cite_number; +        ++mkn; +        foreach (endnote; endnotes_) { +          type="para"; +          attrib=""; +          indent["first"] = "0"; +          indent["second"] = "0"; +          attrib=""; +          // endnotes ~= +          //   set_abstract_object.contents_para( +          //     obj, +          //     obj_cite_number, +          //     indent, +          //     false +          //   ); +          endnotes_section ~= +            set_abstract_object.contents_para( +              type, +              endnote, +              attrib, +              obj_cite_number, +              indent, +              false +            ); +          ++obj_cite_number; +          ++mkn; +        } +        auto t = tuple(endnotes_section, obj_cite_number); +        return t; +      } +    } +    struct Bibliography { +      public JSONValue[] bibliography(ref string[] biblio_unsorted_incomplete, ref JSONValue[] bib_arr_json) +      in { } +      body { +        JSONValue[] biblio_unsorted = +          biblio_unsorted_complete(biblio_unsorted_incomplete, bib_arr_json); +        JSONValue[] biblio_sorted = biblio_sort(biblio_unsorted); +        biblio_debug(biblio_sorted); +        return biblio_sorted; +      } +      final private JSONValue[] biblio_unsorted_complete( +        string[] biblio_unordered, +        ref JSONValue[] bib_arr_json +      ) { +        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; +        return biblio_unsorted_array_of_json_objects; +      } +      final private JSONValue[] biblio_sort(JSONValue[] biblio_unordered) { +        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"]); +              // writeln(j["deemed_author"], " (", j["author"], ") ",  j["fulltitle"]); +            } +          } +        } +        return biblio_sorted; +      } +      auto biblio_debug(JSONValue[] biblio_sorted) { +        debug(biblio) { +          foreach (j; biblio_sorted) { +            if (!empty(j["fulltitle"].str)) { +              writeln(j["sortby_deemed_author_year_title"]); +            } +          } +        } +      } +    } +    struct NodeStructureMetadata { +    // class NodeStructureMetadata : AssertNodeJSON { +      int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7; +      int obj_cite_number; +      int[string] p_; // p_ parent_ +      string node; +      string node_emitter( +        string lev_markup_number, +        int obj_cite_number_, +        long counter_, +        int pointer_, +        string is_ +      ) +      in { +        auto rgx = Rgx(); +        assert(is_ != "heading"); +        assert(to!int(obj_cite_number_) >= 0); +      } +      body { +        // scope(failure) { +        //   writeln(__FILE__, ":", __LINE__, " failed here:"); +        //   writeln("  is  : ", is_); +        //   writeln("  node: ", node); +        // } +        assert(is_ != "heading"); // should not be necessary +        assert(to!int(obj_cite_number_) >= 0); // should not be necessary +        int obj_cite_number=to!int(obj_cite_number_); +        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; +        } +        node=("{ " ~ +          "\"is\": \"" ~ is_ ~ "\"" ~ +          ", \"heading_pointer\": " ~ to!string(pointer_) ~ +          ", \"doc_object_pointer\": " ~ to!string(counter_) ~ +          ", \"obj_cite_number\": " ~ to!string(obj_cite_number_) ~ +          ", \"parent_obj_cite_number\": " ~ to!string(p_["obj_cite_number"]) ~ +          ", \"parent_lev_markup_number\": " ~ to!string(p_["lev_markup_number"]) ~ +          " }" +        ); +        debug(node) { +          mixin ScreenTxtColors; +          if (match(lev_markup_number, rgx.levels_numbered_headings)) { +            writeln(scr_txt_marker["yellow"], to!string(node)); +          } else { +            writeln(scr_txt_marker["white"], to!string(node)); +          } +        } +        JSONValue j = parseJSON(node); +        assert(j["parent_lev_markup_number"].integer >= 4); +        assert(j["parent_lev_markup_number"].integer <= 7); +        assert(j["parent_obj_cite_number"].integer >= 0); +        return node; +      } +      invariant() { +      } +      string node_emitter_heading( +        string lev_markup_number, +        string lev_collapsed_number, +        int obj_cite_number_, +        long counter_, +        int pointer_, +        string is_ +      ) +      in { +        auto rgx = Rgx(); +        assert(is_ == "heading"); +        assert(to!int(obj_cite_number_) >= 0); +        assert( +          match(lev_markup_number, rgx.levels_numbered), +          ("not a valid heading level: " ~ lev_markup_number ~ " at " ~ to!string(obj_cite_number_)) +        ); +        // assert(to!int(obj_cite_number_) >= 0); +        if (match(lev_markup_number, rgx.levels_numbered)) { +          if (to!int(lev_markup_number) == 0) { +            assert(to!int(obj_cite_number_) == 1); +            // writeln(lev_markup_number); +          } +        } +      } +      body { +        // scope(failure) { +        //   writeln(__FILE__, ":", __LINE__, " failed here:"); +        //   writeln("  is  : ", is_); +        //   writeln("  node: ", node); +        // } +        auto rgx = Rgx(); +        int obj_cite_number = to!int(obj_cite_number_); +        switch (lev_markup_number) { // switch (to!string(lv)) { +        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: +          // if (lv7 > State.off) { +          //   p_["lev_markup_number"] = 7; p_["obj_cite_number"] = lv7; +          // } else if (lv6 > State.off) { +          //   p_["lev_markup_number"] = 6; p_["obj_cite_number"] = lv6; +          // } else if (lv5 > State.off) { +          //   p_["lev_markup_number"] = 5; p_["obj_cite_number"] = lv5; +          // } else { +          //   p_["lev_markup_number"] = 4; p_["obj_cite_number"] = lv4; +          // } +          break; +        } +        node=("{ " ~ +          "\"is\": \"" ~ is_ ~ "\"" ~ +          ", \"heading_pointer\": " ~ to!string(pointer_) ~ +          ", \"doc_object_pointer\": " ~ to!string(counter_) ~ +          ", \"obj_cite_number\": " ~ to!string(obj_cite_number_) ~ +          ",  \"lev_markup_number\": " ~ to!string(lev_markup_number) ~ +          ",  \"lev_collapsed_number\": " ~ to!string(lev_collapsed_number) ~ +          ", \"parent_obj_cite_number\": " ~ to!string(p_["obj_cite_number"]) ~ +          ", \"parent_lev_markup_number\": " ~ to!string(p_["lev_markup_number"]) ~ +          " }" +        ); +        debug(heading) { +          mixin ScreenTxtColors; +          if (match(lev_markup_number, rgx.levels_numbered_headings)) { +            writeln(scr_txt_marker["yellow"], to!string(node)); +          } +        } +        debug(node) { +          mixin ScreenTxtColors; +          if (match(lev_markup_number, rgx.levels_numbered_headings)) { +            writeln(scr_txt_marker["yellow"], to!string(node)); +          } else { +            writeln(scr_txt_marker["white"], to!string(node)); +          } +        } +        JSONValue j = parseJSON(node); +        assert(j["parent_lev_markup_number"].integer <= 7); +        assert(j["parent_obj_cite_number"].integer >= 0); +        if (match(lev_markup_number, rgx.levels_numbered_headings)) { +          assert(j["lev_markup_number"].integer <= 7); +          assert(j["obj_cite_number"].integer >= 0); +          if (j["parent_lev_markup_number"].integer > 0) { +            assert(j["parent_lev_markup_number"].integer < j["lev_markup_number"].integer); +            if (j["obj_cite_number"].integer != 0) { +              assert(j["parent_obj_cite_number"].integer < j["obj_cite_number"].integer); +            } +          } +          if (j["lev_markup_number"].integer == 0) { +            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_sect_A); +          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_sect_B) { +            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_sect_A); +          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_sect_C) { +            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_sect_B); +          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_sect_D) { +            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_sect_C); +          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_text_1) { +            assert(j["parent_lev_markup_number"].integer <= DocStructMarkupHeading.h_sect_D); +          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_text_2) { +            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_text_1); +          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_text_3) { +            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_text_2); +          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_text_4) { +            assert(j["parent_lev_markup_number"].integer == DocStructMarkupHeading.h_text_3); +          } else if  (j["lev_markup_number"].integer == DocStructMarkupHeading.h_text_5) { +            // writeln(j["parent_lev_markup_number"].integer); +            // assert(j["parent_lev_markup_number"].integer >= 4); +            // assert(j["parent_lev_markup_number"].integer <= 7); +          } +        } +        return node; +      } +      invariant() { +      } +    } +    /+ abstraction functions emitters ↑ +/ + +    /+ ↓ abstraction functions assertions +/ +    auto assertions_doc_structure(string[string] an_object, int[string] lv) { +      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 (to!string(an_object["lev"])) { +      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(int[string] type) { +      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: struct Abstraction +/ + +} /+ ← closed: template SiSUdocAbstraction +/ diff --git a/src/sdp/ao_ansi_colors.d b/src/sdp/ao_ansi_colors.d new file mode 100644 index 0000000..e5a46f9 --- /dev/null +++ b/src/sdp/ao_ansi_colors.d @@ -0,0 +1,74 @@ +/+ +  utils +  ao_util.d ++/ +template ScreenTxtColors() { +  string[string] scr_txt_color = [ +    "off"           : "\033[0m", +    "white"         : "\033[37m", +    "white_bold"    : "\033[1m", +    "marker"        : "\033[42m", +    "bold"          : "\033[1m", +    "underline"     : "\033[4m", +    "invert"        : "\033[7m", +    "darkgrey_hi"   : "\033[100m", +    "grey_hi"       : "\033[47m", +    "pink_hi"       : "\033[105m", +    "fuchsia_hi"    : "\033[45m", +    "red_hi"        : "\033[41m", +    "orange_hi"     : "\033[101m", +    "yellow_hi"     : "\033[103m", +    "brown_hi"      : "\033[43m", +    "lightgreen_hi" : "\033[102m", +    "green_hi"      : "\033[42m", +    "cyan_hi"       : "\033[106m", +    "blue_hi"       : "\033[104m", +    "navy_hi"       : "\033[44m", +    "grey"          : "\033[90m", +    "pink"          : "\033[95m", +    "fuchsia"       : "\033[35m", +    "ruby"          : "\033[31m", +    "red"           : "\033[91m", +    "orange"        : "\033[91m", +    "yellow"        : "\033[93m", +    "brown"         : "\033[33m", +    "green"         : "\033[92m", +    "darkgreen"     : "\033[32m", +    "cyan"          : "\033[36m", +    "blue"          : "\033[94m", +    "navy"          : "\033[34m", +    "black"         : "\033[30m" +  ]; +  string[string] scr_txt_marker = [ +    "white"         : "\033[37m*\033[0m ", +    "bold"          : "\033[1m*\033[0m ", +    "invert"        : "\033[7m*\033[0m ", +    "darkgrey_hi"   : "\033[100m*\033[0m ", +    "grey_hi"       : "\033[47m*\033[0m ", +    "pink_hi"       : "\033[105m*\033[0m ", +    "fuchsia_hi"    : "\033[45m*\033[0m ", +    "red_hi"        : "\033[41m*\033[0m ", +    "orange_hi"     : "\033[101m*\033[0m ", +    "yellow_hi"     : "\033[103m*\033[0m ", +    "brown_hi"      : "\033[43m*\033[0m ", +    "lightgreen_hi" : "\033[102m*\033[0m ", +    "green_hi"      : "\033[42m*\033[0m ", +    "cyan_hi"       : "\033[106m*\033[0m ", +    "blue_hi"       : "\033[104m*\033[0m ", +    "navy_hi"       : "\033[44m*\033[0m ", +    "grey"          : "\033[90m*\033[0m ", +    "pink"          : "\033[95m*\033[0m ", +    "fuchsia"       : "\033[35m*\033[0m ", +    "ruby"          : "\033[31m*\033[0m ", +    "red"           : "\033[91m*\033[0m ", +    "orange"        : "\033[91m*\033[0m ", +    "yellow"        : "\033[93m*\033[0m ", +    "brown"         : "\033[33m*\033[0m ", +    "green"         : "\033[92m*\033[0m ", +    "darkgreen"     : "\033[32m*\033[0m ", +    "cyan"          : "\033[36m*\033[0m ", +    "blue"          : "\033[94m*\033[0m ", +    "navy"          : "\033[34m*\033[0m ", +    "black"         : "\033[30m*\033[0m " +  ]; +} diff --git a/src/sdp/ao_defaults.d b/src/sdp/ao_defaults.d new file mode 100644 index 0000000..314635c --- /dev/null +++ b/src/sdp/ao_defaults.d @@ -0,0 +1,311 @@ +/+ +  defaults +  ao_defaults.d ++/ +template SiSUheader() { +  auto header_make_jsonstr = `{ +    "make": { +      "cover_image"        : "", +      "home_button_image"  : "", +      "home_button_text"   : "", +      "footer"             : "", +      "headings"           : "", +      "num_top"            : "", +      "breaks"             : "", +      "substitute"         : "", +      "bold"               : "", +      "italics"            : "", +      "emphasis"           : "", +      "texpdf_font"        : "", +      "css"                : "" +    } +  }`; +  auto header_metadata_jsonstr = `{ +    "creator": { +      "author"             : "", +      "translator"         : "", +      "illustrator"        : "" +    }, +    "title": { +      "main"               : "", +      "sub"                : "", +      "full"               : "", +      "language"           : "", +      "edition"            : "", +      "note"               : "" +    }, +    "rights": { +      "copyright"          : "", +      "illustrations"      : "", +      "license"            : "", +      "cover"              : "" +    }, +    "date": { +      "published"          : "", +      "created"            : "", +      "issued"             : "", +      "available"          : "", +      "valid"              : "", +      "modified"           : "", +      "added_to_site"      : "" +    }, +    "original": { +      "title"              : "", +      "language"           : "", +      "source"             : "" +    }, +    "classify": { +      "topic_register"     : "", +      "subject"            : "", +      "keywords"           : "", +      "loc"                : "", +      "dewey"              : "" +    }, +    "identifier": { +      "oclc"               : "", +      "pg"                 : "", +      "isbn"               : "" +    }, +    "notes": { +      "abstract"           : "", +      "description"        : "" +    }, +    "publisher": { +      "name"               : "" +    }, +    "links": { +    } +  }`; // links +  auto pointer_head_main = +    [ +      "creator", +      "title", +      "rights", +      "date", +      "original", +      "classify", +      "identifier", +      "notes", +      "make", +      "links" +    ]; +  auto pointer_head_sub_creator = +    [ +      "author", +      "translator", +      "illustrator", +      "cover" +    ]; +  auto pointer_head_sub_title = +    [ +      "main", +      "sub", +      "full", +      "language", +      "edition", +      "note" +    ]; +  auto pointer_head_sub_rights = +    [ +      "copyright", +      "illustrations", +      "license" +    ]; +  auto pointer_head_sub_date = +    [ +      "published", +      "created", +      "issued", +      "valid", +      "modified", +      "added_to_site" +    ]; +  auto pointer_head_sub_original = +    [ +      "title", +      "language", +      "source" +    ]; +  auto pointer_head_sub_classify = +    [ +      "topic_register", +      "subject", +      "keywords", +      "loc", +      "dewey" +    ]; +  auto pointer_head_sub_identifier = +    [ +      "oclc", +      "pg", +      "isbn" +    ]; +  auto pointer_head_sub_notes = +    [ +      "abstract", +      "description" +    ]; +  auto pointer_head_sub_publisher = +    [ "name" ]; +  auto pointer_head_sub_make = +    [ +      "cover_image", +      "home_button_image", +      "home_button_text", +      "footer", "headings", +      "num_top", +      "breaks", +      "substitute", +      "bold", +      "italics", +      "emphasis", +      "texpdf_font", +      "css" +    ]; +  auto config_jsonstr = `{ +  }`; +} +/+ regex flags +/ +template SiSUrgxInitFlags() { +  int[string] flags_type_init() { +    int[string] flags_type_init = [ +      "make_headings"        : 0, +      "header_make"          : 0, +      "header_metadata"      : 0, +      "heading"              : 0, +      "heading_biblio"       : 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_table"          : 0, +      "curly_group"          : 0, +      "curly_block"          : 0, +      "curly_quote"          : 0, +      "tic_code"             : 0, +      "tic_poem"             : 0, +      "tic_table"            : 0, +      "tic_group"            : 0, +      "tic_block"            : 0, +      "tic_quote"            : 0, +      "obj_cite_number_status"           : 0, // 0 obj_cite_number; 1 no obj_cite_number; 2 no obj_cite_number & dummy headings +      "obj_cite_number_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 SiSUbiblio() { +  auto biblio_entry_tags_jsonstr =  `{ +    "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 +} +template InternalMarkup() { +  struct InlineMarkup { +  // endnote en_a_o: '~{'; en_a_c: '}~' +    auto en_a_o = "【"; auto en_a_c = "】"; +  // endnote en_b_o: '~['; en_b_c: ']~' +    auto en_b_o = "〖"; auto en_b_c = "〗"; +    // auto segname_prefix_auto_num_extract = "c"; +    // auto segname_prefix_auto_num_provide = "s"; +    // auto segname_prefix_auto_num_other = "x"; +    // auto obj_cite_number_id_char = "";                                              //'o'; now as before; remove for html5 +    // auto note = "note_"; +    // auto note_ref = "noteref_"; +    // auto note_astx = "note_astx_"; +    // auto note_ref_astx = "noteref_astx_"; +    // auto note_plus = "note_plus_"; +    // auto note_ref_plus = "noteref_plus_"; +    // auto meta_o = "〔@"; auto meta_c = "〕"; +    // auto lv_o_0 = 0; +    // auto lv_o_1 = 1; +    // auto lv_o_2 = 2; +    // auto lv_o_3 = 3; +    // auto lv_o_4 = 4; +    // auto lv_o_5 = 5; +    // auto lv_o_6 = 6; +    // auto lv_o_7 = 7; +    // auto lv_o_8 = 8; +    // auto lv_o_9 = 9; +    // auto lv_o = "〔"; auto lv_c = "〕"; +    // auto bl_o = "〔"; auto bl_c = "〕";          // block text mark +    // auto gr_o = "〔"; auto gr_c = "〕";          // group text mark #REPLACE & RETIRE +    // auto id_o = "〔"; auto id_c = "〕";          // object id mark +    // auto tc_o = "『"; auto tc_c = "』";          // table row mark #Mx[:tc_c]="』\n" +    // auto tc_p = "┆'" +    // auto pa_o = "〔"; auto pa_c = "〕";          // affects paragraph mark +    // auto mk_o = "〔"; auto mk_c = "〕";          // generic mark +    // auto gl_o = "〔"; auto gl_c = "〕";          // glyph +    // auto fa_o = "〔"; auto fa_o_c = "¤"; auto fa_c_o = "¤"; auto fa_c = "〕"; +    // auto idx_o = "▩"; auto idx_c = "▩"; +    // auto nbsp = "░";                                              // '▭ ' +    // auto br_line = "╱";                                              // lB ▌  9612 ┘ ¶ +    // auto br_nl = "╲";                                              // lB ▌ 』  ┘ +    // auto br_paragraph = "█";                                              // FB █  9608 # PP ∥  8741 #▐  #'┘' #'¶' #FB █  9608  lB ▌  9612   RB ▐  9616 +    // auto br_obj = "break_obj"; +    // auto br_page_line = "▭"; +    // auto br_page = "┼"; +    // auto br_page_new = "╋"; +    // auto lnk_o = "⌠";          lnk_c = "⌡";           // '⌈' '⌋' '⌠' '⌡' #Mx[:lnk_o= '◁'; Mx[:lnk_c= '▷' #‹ › +    // auto url_o = "◘"; auto url_c = "◙"; +    // auto rel_o = "⌈"; auto rel_c = "⌋"; +    // auto tag_o = "⌊"; auto tag_c = "⌉"; +    // auto sm_set_o = "◢"; auto sm_set_c = "◣"; +    // auto sm_subset_o = "◢"; auto sm_subset_c = "◣"; +    // auto vline = "┆";                                              //   ¦ | +    // auto src_bold_o = "!{"; auto src_bold_c = "}!"; +    // auto src_italics_o = "/{"; auto src_italics_c = "}/"; +    // auto src_underscore_o = "_{"; auto src_underscore_c = "}_"; +    // auto src_cite_o = ""{"; auto src_cite_c = "}""; +    // auto src_insert_o = "+{"; auto src_insert_c = "}+"; +    // auto src_strike_o = "-{"; auto src_strike_c = "}-"; +    // auto src_superscript_o = "^{"; auto src_superscript_c = "}^"; +    // auto src_subscript_o = ";{"; auto src_subscript_c = "}'" +    // auto src_hilite_o = "*{"; auto src_hilite_c = "}*"; +    // auto src_monospace_o = "#{"; auto src_monospace_c = "}#"; +    // auto srcrgx_bold_o = "\\!\\{";  auto srcrgx_bold_c = "\\}\\!"; +    // auto srcrgx_italics_o = "\\/\\{";  auto srcrgx_italics_c = "\\}\\/"; +    // auto srcrgx_underscore_o = "_\\{"; auto srcrgx_underscore_c = "\\}_"; +    // auto srcrgx_cite_o = "\"\\{"; auto srcrgx_cite_c = "\\}\""; +    // auto srcrgx_insert_o = "\\+\\{";  auto srcrgx_insert_c = "\\}\\+"; +    // auto srcrgx_strike_o = "\\-\\{";  auto srcrgx_strike_c = "\\}\\-"; +    // auto srcrgx_superscript_o = "\\^\\{";  auto srcrgx_superscript_c = "\\}\\^"; +    // auto srcrgx_subscript_o = ",\\{"; auto srcrgx_subscript_c = "\\},"; +    // auto srcrgx_hilite_o = "\\*\\{";  auto srcrgx_hilite_c = "\\}\\*"; +    // auto srcrgx_monospace_o = "\\#\\{";  auto srcrgx_monospace_c = "\\}\\#"; +    // ⊹ +  } +} diff --git a/src/sdp/ao_object_setter.d b/src/sdp/ao_object_setter.d new file mode 100644 index 0000000..4492e8a --- /dev/null +++ b/src/sdp/ao_object_setter.d @@ -0,0 +1,124 @@ +/+ +  object setter +  ao_object_setter.d ++/ +template ObjectSetter() { +  /+ structs +/ +  struct HeadingAttrib { +    int lev                   = 9;   // use of enum should make this redundant, remove +    int lev_markup_number     = 9; +    int lev_collapsed_number  = 9; +  } +  struct ParaAttrib { +    int indent_first          = 0; +    int indent_second         = 0; +    bool bullet               = false; +  } +  struct BlockAttrib { +  } +  struct Comment { +    // no .attrib and no .obj_cite_number +  } +  struct Node { +    int ocn                    = 0; +    int parent_lev             = 0; +    int parent_ocn             = 0; +    string node                = ""; +  } +  struct ObjComposite { +    // size_t id; +    string use                 = ""; +    string of                  = ""; +    string is_a                = ""; +    string object              = ""; +    string obj_cite_number     = "";  // not used for calculations? output only? else int +    HeadingAttrib heading_attrib; +    ParaAttrib para_attrib; +    BlockAttrib block_attrib; +    Node node_structure; +  } +  struct ObjCompositeArr { +    ObjComposite[] oca; +  } + +  /+ structs setter +/ +  struct ObjectAbstractSet { +    import std.conv : to; +    auto contents_comment(in string object) { +      ObjComposite object_set; +      object_set.use                  = "comment"; +      object_set.of                   = "comment"; +      object_set.is_a                 = "comment"; +      object_set.object               = object; +      return object_set; +    } +    auto contents_heading( +      in string object, +      in string attrib, +      in int obj_cite_number, +      in int lev_markup_number, +      in int lev_collapsed_number, +    ) { +      ObjComposite object_set; +      object_set.use                                 = "content"; +      object_set.of                                  = "para"; +      object_set.is_a                                = "heading"; +      object_set.object                              = object; +      object_set.obj_cite_number                     = (obj_cite_number==0) ? "" : to!string(obj_cite_number); +      object_set.heading_attrib.lev_markup_number    = lev_markup_number; +      object_set.heading_attrib.lev_collapsed_number = lev_collapsed_number; +      // object_set.node_structure.node               = node; +      return object_set; +    } +    auto contents_para( +      in string is_a, +      in string object, +      in string attrib, +      in int obj_cite_number, +      in string[string] indent, +      in bool bullet +    ) { +      ObjComposite object_set; +      object_set.use                 = "content"; +      object_set.of                  = "para"; +      object_set.is_a                = "para"; +      object_set.object              = object; +      object_set.obj_cite_number     = (obj_cite_number==0) ? "" : to!string(obj_cite_number); +      object_set.para_attrib.indent_first   = 0; // indent["first"]; +      object_set.para_attrib.indent_second  = 0; // indent["second"]; +      object_set.para_attrib.bullet         = false; +      // object_set.node_structure.node               = node; +      return object_set; +    } +    auto contents_block( +      in string type, +      in string object, +      in string attrib, +      in int obj_cite_number +    ) { +      ObjComposite object_set; +      object_set.use                 = "content"; +      object_set.of                  = "block"; +      object_set.is_a                = type; +      object_set.object              = object; +      object_set.obj_cite_number     = (obj_cite_number==0) ? "" : to!string(obj_cite_number); +      // object_set.node_structure.node               = node; +      return object_set; +    } +    auto contents_block_obj_cite_number_string( +      in string type, +      in string object, +      in string obj_cite_number, +      in string node +    ) { +      ObjComposite object_set; +      object_set.use                               = "content"; +      object_set.of                                = "block"; +      object_set.is_a                              = type; +      object_set.object                            = object; +      object_set.obj_cite_number                   = obj_cite_number; +      object_set.node_structure.node               = node; +      return object_set; +    } +  } +} diff --git a/src/sdp/ao_output_debugs.d b/src/sdp/ao_output_debugs.d new file mode 100644 index 0000000..8c655e8 --- /dev/null +++ b/src/sdp/ao_output_debugs.d @@ -0,0 +1,413 @@ +/+ +  output debugs +  ao_output_debugs.d ++/ +template SiSUoutputDebugs() { +  struct SDPoutputDebugs { +    auto abstract_doc_source_debugs(S)( +      auto ref const S         contents, +      JSONValue[string]        docmake, +      JSONValue[string]        dochead, +      string[][string][string] bookindex_unordered_hashes, +      JSONValue[]              biblio, +      string                   fn_src, +      bool[string]             opt_action_bool +    ) { +      mixin RgxInit; +      mixin ScreenTxtColors; +      auto rgx = Rgx(); +      debug(parent) { +        writefln( +          "%s:%s", +          __FILE__, +          __LINE__, +        ); +        foreach (obj; contents) { +          if (obj.use == "content") { +            if (obj.is_a == "heading") { +              writefln( +                "%s%s node: %s heading: %s %s", +                scr_txt_marker["cyan"], +                obj.obj_cite_number, +                obj.node, +                obj.lev_markup_number, +                obj.object, +              ); +            } else { +            } +          } +        } +      } +      debug(dumpdoc) { +        writefln( +          "%s\n%s:%s", +          "-------------------------------", +          __FILE__, +          __LINE__, +        ); +        foreach (obj; contents) { +          if (obj.use == "content") { +            writefln( +              "[%s][%s]\n%s", +              obj.obj_cite_number, +              obj.is_a, +              obj.object +            ); +          } +        } +      } +      debug(objects) { +        writefln( +          "%s\n%s:%s", +          "-------------------------------", +          __FILE__, +          __LINE__, +        ); +        foreach (obj; contents) { +          if (obj.use == "content") { +            writefln( +              "%s* [%s][%s] %s%s", +              scr_txt_color["green"], +              obj.obj_cite_number, +              obj.is_a, +              scr_txt_color["off"], +              obj.object +            ); +          } +        } +      } +      debug(headermakejson) { +        writefln( +          "%s\n%s\n%s", +          "document header, metadata & make instructions:", +          dochead, +          pointer_head_main, +        ); +        foreach (main_header; pointer_head_main) { +          switch (main_header) { +          case "make": +            foreach (sub_header; pointer_head_sub_make) { +              if (to!string(dochead[main_header][sub_header]).length > 2) { +                writefln( +                  "%s:%s: %s", +                  main_header, +                  sub_header, +                  dochead[main_header][sub_header] +                ); +              } +            } +            break; +          default: +            break; +          } +        } +      } +      debug(headermetadatajson) { +        writefln( +          "%s\n%s\n%s", +          "document header, metadata & make instructions:", +          dochead, +          pointer_head_main, +        ); +        foreach (main_header; pointer_head_main) { +          switch (main_header) { +          case "creator": +            foreach (sub_header; pointer_head_sub_creator) { +              if (to!string(dochead[main_header][sub_header]).length > 2) { +                writefln( +                  "%s:%s: %s", +                  main_header, +                  sub_header, +                  dochead[main_header][sub_header] +                ); +              } +            } +            break; +          case "title": +            foreach (sub_header; pointer_head_sub_title) { +              if (to!string(dochead[main_header][sub_header]).length > 2) { +                writefln( +                  "%s:%s: %s", +                  main_header, +                  sub_header, +                  dochead[main_header][sub_header] +                ); +              } +            } +            break; +          case "rights": +            foreach (sub_header; pointer_head_sub_rights) { +              if (to!string(dochead[main_header][sub_header]).length > 2) { +                writefln( +                  "%s:%s: %s", +                  main_header, +                  sub_header, +                  dochead[main_header][sub_header] +                ); +              } +            } +            break; +          case "date": +            foreach (sub_header; pointer_head_sub_date) { +              if (to!string(dochead[main_header][sub_header]).length > 2) { +                writefln( +                  "%s:%s: %s", +                  main_header, +                  sub_header, +                  dochead[main_header][sub_header] +                ); +              } +            } +            break; +          case "original": +            foreach (sub_header; pointer_head_sub_original) { +              if (to!string(dochead[main_header][sub_header]).length > 2) { +                writefln( +                  "%s:%s: %s", +                  main_header, +                  sub_header, +                  dochead[main_header][sub_header] +                ); +              } +            } +            break; +          case "classify": +            foreach (sub_header; pointer_head_sub_classify) { +              if (to!string(dochead[main_header][sub_header]).length > 2) { +                writefln( +                  "%s:%s: %s", +                  main_header, +                  sub_header, +                  dochead[main_header][sub_header] +                ); +              } +            } +            break; +          case "identifier": +            foreach (sub_header; pointer_head_sub_identifier) { +              if (to!string(dochead[main_header][sub_header]).length > 2) { +                writefln( +                  "%s:%s: %s", +                  main_header, +                  sub_header, +                  dochead[main_header][sub_header] +                ); +              } +            } +            break; +          case "notes": +            foreach (sub_header; pointer_head_sub_notes) { +              if (to!string(dochead[main_header][sub_header]).length > 2) { +                writefln( +                  "%s:%s: %s", +                  main_header, +                  sub_header, +                  dochead[main_header][sub_header] +                ); +              } +            } +            break; +          case "publisher": +            foreach (sub_header; pointer_head_sub_publisher) { +              if (to!string(dochead[main_header][sub_header]).length > 2) { +                writefln( +                  "%s:%s: %s", +                  main_header, +                  sub_header, +                  dochead[main_header][sub_header] +                ); +              } +            } +            break; +          default: +            break; +          } +        } +      } +      debug(bookindex) { +        writefln( +          "%s\n%s:%s", +          "-------------------------------", +          __FILE__, +          __LINE__, +        ); +        auto bookindex = BookIndexReport(); +        bookindex.bookindex_report_sorted(bookindex_unordered_hashes); +      } +      debug(summary) { +        string[string] check = [ +          "last_obj_cite_number" : "NA [debug \"checkdoc\" not run]", +        ]; +        debug(checkdoc) { +          foreach (obj; contents) { +            if (obj.use == "content") { +              if (!empty(obj.obj_cite_number)) { +                check["last_obj_cite_number"] = obj.obj_cite_number; +              } +            } +          } +        } +        debug(headings) { +          writefln( +            "%s\n%s:%s", +            "-------------------------------", +            __FILE__, +            __LINE__, +          ); +          foreach (obj; contents) { +            if (obj.is_a == "heading") { +              writefln( +                "%s%s~ [%s] %s", +                scr_txt_marker["yellow"], +                obj.heading_attrib.lev, +                obj.obj_cite_number, +                // "[", obj["is"], "] ", +                obj.object +              ); +            } +          } +        } +        writefln( +          "%s%s%s\n%s\n%s%s\n%s%s\n%s%s\n%s:%s", +          scr_txt_color["green"], +          "-------------------------------", +          scr_txt_color["off"], +          fn_src, +          "length contents array: ", +          contents.length, +          "last obj_cite_number: ", +          check["last_obj_cite_number"], +          "length bookindex: ", +          bookindex_unordered_hashes.length, +          __FILE__, +          __LINE__, +        ); +        debug(checkdoc) { +          if (auto mfn=match(fn_src, rgx.src_fn)) { +            if (opt_action_bool["assertions"]) { +              switch (mfn.captures[2]) { +              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; +              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(fn_src); +                break; +              } +            } +          } +        } +      } +    } +  } +} diff --git a/src/sdp/ao_read_source_files.d b/src/sdp/ao_read_source_files.d new file mode 100644 index 0000000..a5ca084 --- /dev/null +++ b/src/sdp/ao_read_source_files.d @@ -0,0 +1,281 @@ +/+ +  ao_read_source_files.d +  - open markup files +  - if master file scan for addional files to import/insert ++/ +// module ao_read_source_files; +template SiSUmarkupRaw() { +  private import +    std.exception, +    std.regex, +    std.stdio, +    std.utf, +    std.conv : to; +  private import +    ao_rgx;       // ao_defaults.d +  mixin RgxInit; +  auto rgx = Rgx(); +  struct MarkupRaw { +    final char[][] sourceContent(in string fn_src) { +      auto raw = MarkupRawUnit(); +      auto sourcefile_content = +        raw.markupSourceContentRawLineArray(fn_src, rgx.src_pth); +      if (match(fn_src, rgx.src_fn_master)) { +        auto ins = Inserts(); +        sourcefile_content = +          ins.scan_master_doc_source_for_insert_filenames(sourcefile_content, fn_src); +        // auto ins = SiSUdocInserts.Inserts(); +      } +      return sourcefile_content; +    } +  } +  private +  struct MarkupRawUnit { +    private import std.file; +    final private string readInMarkupSource(in string fn_src) { +      enforce( +        exists(fn_src)!=0, +        "file not found" +      ); +      string source_txt_str; +      try { +        if (exists(fn_src)) { +          source_txt_str = readText(fn_src); +        } +      } +      catch (ErrnoException ex) { +      //// Handle errors +      // switch(ex.errno) { +      // case EPERM: +      // case EACCES: +      //   // Permission denied +      //   break; +      // case ENOENT: +      //   // File does not exist +      //   break; +      // default: +      //   // Handle other errors +      //   break; +      // } +      } +      catch (UTFException ex) { +        // Handle validation errors +      } +      catch (FileException ex) { +        // Handle errors +      } +      std.utf.validate(source_txt_str); +      return source_txt_str; +    } +    final private char[][] markupSourceLineArray(in string src_text) { +      char[][] source_line_arr = +        split(cast(char[]) src_text, rgx.line_delimiter); +      return source_line_arr; +    } +    final char[][] markupSourceContentRawLineArray(in string fn_src, Regex!(char) rgx_file ) { +      enforce( +        match(fn_src, rgx_file), +        "not a sisu markup filename" +      ); +      auto source_txt_str = readInMarkupSource(fn_src); +      auto source_line_arr = markupSourceLineArray(source_txt_str); +      return source_line_arr; +    } +  } +  struct Inserts { +    private import ao_defaults;    // ao_defaults.d +    private import ao_ansi_colors; // ao_ansi_colors.d +    auto scan_subdoc_source( +      char[][] markup_sourcefile_insert_content, +      string fn_src +    ) { +      mixin SiSUrgxInitFlags; +      char[][] contents_insert; +      auto type1 = flags_type_init; +      mixin ScreenTxtColors; +      int tell_l(string color, in char[] line) { +        writeln(scr_txt_marker[color], line); +        return 0; +      } +      auto fn_pth_full = match(fn_src, 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_metadata"] = 0; +          if (auto m = match(line, rgx.block_curly_code_close)) { +            type1["curly_code"] = 0; +          } +          contents_insert ~= line; +        } else if (auto m = match(line, rgx.block_curly_code_open)) { +          type1["curly_code"] = 1; +          type1["header_make"] = 0; +          type1["header_metadata"] = 0; +          contents_insert ~= line; +        } else if (type1["tic_code"] == 1) { +          type1["header_make"] = 0; +          type1["header_metadata"] = 0; +          if (auto m = match(line, rgx.block_tic_close)) { +            type1["tic_code"] = 0; +          } +          contents_insert ~= line; +        } else if (auto m = match(line, rgx.block_tic_code_open)) { +          type1["tic_code"] = 1; +          type1["header_make"] = 0; +          type1["header_metadata"] = 0; +          contents_insert ~= line; +        } else if ( +          (type1["header_make"] == 1) +          && match(line, rgx.header_sub) +        ) { +            type1["header_make"] = 1; +            type1["header_metadata"] = 0; +            // cont_dynamic_array ~= "% " ~ line; +        } else if ( +          (type1["header_metadata"] == 1) +          && match(line, rgx.header_sub) +        ) { +            type1["header_metadata"] = 1; +            type1["header_make"] = 0; +            // cont_dynamic_array ~= "% " ~ line; +        } else if (auto m = match(line, rgx.insert_src_fn_ssi_or_sst)) { +          type1["header_make"] = 0; +          type1["header_metadata"] = 0; +          auto insert_fn = m.captures[2]; +          auto insert_sub_pth = m.captures[1]; +          auto fn_src_insert = +            to!string(markup_src_file_path ~ insert_sub_pth ~ insert_fn); +          auto raw = MarkupRawUnit(); +          auto markup_sourcesubfile_insert_content = +            raw.markupSourceContentRawLineArray(fn_src_insert, rgx.src_fn_find_inserts); +          debug(insert) {                              // 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_metadata"] = 0; +          contents_insert ~= line; +        } +      } // end src subdoc (inserts) loop +      return contents_insert; +    } +    auto scan_master_doc_source_for_insert_filenames( +      char[][] sourcefile_content, +      string fn_src +    ) { +      mixin SiSUrgxInitFlags; +      char[][] contents; +      auto type = flags_type_init; +      mixin ScreenTxtColors; +      int tell_l(string color, in char[] line) { +        writeln(scr_txt_marker[color], line); +        return 0; +      } +      auto fn_pth_full = match(fn_src, rgx.src_pth); +      auto markup_src_file_path = fn_pth_full.captures[1]; +      foreach (line; sourcefile_content) { +        if (type["curly_code"] == 1) { +          type["header_make"] = 0; +          type["header_metadata"] = 0; +          if (auto m = match(line, rgx.block_curly_code_close)) { +            type["curly_code"] = 0; +          } +          contents ~= line; +        } else if (auto m = match(line, rgx.block_curly_code_open)) { +          type["curly_code"] = 1; +          type["header_make"] = 0; +          type["header_metadata"] = 0; +          contents ~= line; +        } else if (type["tic_code"] == 1) { +          type["header_make"] = 0; +          type["header_metadata"] = 0; +          if (auto m = match(line, rgx.block_tic_close)) { +            type["tic_code"] = 0; +          } +          contents ~= line; +        } else if (auto m = match(line, rgx.block_tic_code_open)) { +          type["tic_code"] = 1; +          type["header_make"] = 0; +          type["header_metadata"] = 0; +          contents ~= line; +        } else if ( +          (type["header_make"] == 1) +          && match(line, rgx.header_sub) +        ) { +          contents ~= line; +        } else if ( +          (type["header_metadata"] == 1) +          && match(line, rgx.header_sub) +        ) { +          contents ~= line; +        } else if (auto m = match(line, rgx.header_make)) { +          type["header_make"] = 1; +          type["header_metadata"] = 0; +          contents ~= line; +        } else if (auto m = match(line, rgx.header_metadata)) { +          type["header_make"] = 0; +          type["header_metadata"] = 1; +          contents ~= line; +        } else if (auto m = match(line, rgx.insert_src_fn_ssi_or_sst)) { +          type["header_make"] = 0; +          type["header_metadata"] = 0; +          auto insert_fn = m.captures[2]; +          auto insert_sub_pth = m.captures[1]; +          auto fn_src_insert = +            to!string(markup_src_file_path ~ insert_sub_pth ~ insert_fn); +          auto raw = MarkupRawUnit(); +          auto markup_sourcefile_insert_content = +            raw.markupSourceContentRawLineArray(fn_src_insert, rgx.src_fn_find_inserts); +          debug(insert) {                              // 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 { +          type["header_make"] = 0; +          type["header_metadata"] = 0; +          contents ~= line; +        } +      } // end src doc loop +      debug(insert) {                              // insert file +        writeln(__LINE__); +        writeln(contents.length); +      } +      return contents; +    } +  } +} diff --git a/src/sdp/ao_rgx.d b/src/sdp/ao_rgx.d new file mode 100644 index 0000000..e675ca1 --- /dev/null +++ b/src/sdp/ao_rgx.d @@ -0,0 +1,181 @@ +/+ +  regex +  ao_rgx.d ++/ +template RgxInit() { +  struct Rgx { +    /+ misc +/ +    static flag_action               = ctRegex!(`^(--[a-z][a-z0-9-]+)$`); +    static flag_action_str           = ctRegex!(` (--[a-z][a-z0-9-]+)`); +    static src_pth                   = ctRegex!(`^([a-zA-Z0-9._-]+/)*([a-zA-Z0-9._-]+[.]ss[tm])$`); +    static src_fn                    = ctRegex!(`^([a-zA-Z0-9._-]+/)*([a-zA-Z0-9._-]+[.]ss[tm])$`); +    static src_fn_master             = ctRegex!(`^([a-zA-Z0-9._-]+/)*([a-zA-Z0-9._-]+[.]ssm)$`); +    static src_fn_find_inserts       = ctRegex!(`^([a-zA-Z0-9._-]+/)*([a-zA-Z0-9._-]+[.]ss[im])$`); +    // static ssm_fn                    = ctRegex!(`^[a-zA-Z0-9._-]+[.]ssm$`); +    static line_delimiter            = ctRegex!("\n"); +    // static arr_delimiter             = ctRegex!(`\s*[;]\s*`); +    static within_quotes             = ctRegex!(`"(.+?)"`); +    static make_heading_delimiter    = ctRegex!(`[;][ ]*`); +    static arr_delimiter             = ctRegex!(`[ ]*[;][ ]*`); +    static name_delimiter            = ctRegex!(`^([^,]+)[ ]*,[ ]+(.+?)$`); +    // static name_delimiter            = ctRegex!(`^(.+?)[ ]*,[ ]*(.+?)$`); +    static book_index_go             = ctRegex!("([0-9]+)(?:-[0-9]+)?"); +    static trailing_comma            = ctRegex!(",[ ]*$"); +    static trailing_linebreak        = ctRegex!(",[ ]{1,2}\\\\\\\\\n[ ]{4}$","m"); +    static line_delimiter_ws_strip   = ctRegex!("[ ]*\n[ ]*"); +    static line_delimiter_only       = ctRegex!("^\n"); +    static para_delimiter            = ctRegex!("\n[ ]*\n+"); +    static levels_markup             = ctRegex!(`^[A-D1-4]$`); +    static levels_numbered           = ctRegex!(`^[0-9]$`); +    static levels_numbered_headings  = ctRegex!(`^[0-7]$`); +    /+ insert markup file +/ +    // static insert_src_fn_ssi_or_sst  = ctRegex!(`^<<\s*([a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`); +    static insert_src_fn_ssi_or_sst  = ctRegex!(`^<<\s*(?P<path>[a-zA-Z0-9._-]+/)*(?P<filename>[a-zA-Z0-9._-]+[.]ss[ti])$`); +    // static insert_ssi_or_sst_fn      = ctRegex!(`^<<\s*[a-zA-Z0-9._-]+[.]ss[ti]`); +    /+ comments +/ +    static comment                   = ctRegex!(`^%+ `); +    /+ header +/ +    static header                    = ctRegex!(`^@([a-z_]+):(?:\s|$)`); +    static header_make               = ctRegex!(`^@(make):(?:\s|$)`); +    static header_metadata           = ctRegex!(`^@([a-z_]+):(?:\s|$)`); +    static header_sub                = ctRegex!(`^[ ]+:([a-z_]+):\s`); +    static head_main                 = ctRegex!(`^@([a-z_]+):\s*(.*)`, "m"); +    static head_sub                  = ctRegex!(`^[ ]*:([a-z_]+):\s+(.+)`, "m"); +    /+ heading & paragraph operators +/ +    static heading            = ctRegex!(`^:?([A-D1-4])[~]([a-z0-9_.-]*[?]?) `); +    static heading_marker     = 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+(.+?)$`); // test, particularly [2] name/hashtag which may or may not be, does this affect title [3] +    static heading_biblio     = ctRegex!(`^:?(1)[~][!](biblio(?:graphy)?|references?)`); +    static heading_glossary   = ctRegex!(`^:?(1)[~][!](glossary)`); +    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|poem|group|block|quote|table)[{].*?$)|^`{3} (code|poem|group|block|quote|table)"); +    // static block_open_less_code      = ctRegex!("^(((poem|group|block|quote|table)[{].*?$)|`{3} (poem|group|block|quote|table))"); +    static block_poem_open                = ctRegex!("^((poem[{].*?$)|`{3} poem)"); +    /+ blocked markup tics +/ +    static block_tic_open            = ctRegex!("^`{3} (code|poem|group|block|quote|table)"); +    // static block_tic_open_less_code  = ctRegex!("^`{3} (poem|group|block|quote|table)"); +    static block_tic_code_open       = ctRegex!("^`{3} (code)"); +    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|poem|group|block|quote|table)[{].*?$)`); +    // static block_curly_open_less_code = ctRegex!(`^((poem|group|block|quote|table)[{].*?$)`); +    static block_curly_code_open     = ctRegex!(`^(code[{].*?$)`); +    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)`); +    /+ inline markup font face mod +/ +    static inline_emphasis           = ctRegex!(`\*\{(?P<text>.+?)\}\*`); +    static inline_bold               = ctRegex!(`!\{(?P<text>.+?)\}!`); +    static inline_italics            = ctRegex!(`/\{(?P<text>.+?)\}/`); +    static inline_superscript        = ctRegex!(`\^\{(?P<text>.+?)\}\^`); +    static inline_subscript          = ctRegex!(`,\{(?P<text>.+?)\},`); +    static inline_strike             = ctRegex!(`-\{(?P<text>.+?)\}-`); +    static inline_insert             = ctRegex!(`\+\{(?P<text>.+?)\}\+`); +    static inline_mono               = ctRegex!(`#\{(?P<text>.+?)\}#`); +    /+ inline markup footnotes +/ +    static true_dollar                           = ctRegex!(`\$`, "gm"); +    static inline_notes_al                       = ctRegex!(`【(?:[*+]\s+|\s*)(.+?)】`, "mg"); +    static inline_notes_al_gen                   = ctRegex!(`【.+?】`, "m"); +    static inline_notes_curly_gen                = ctRegex!(`~\{.+?\}~`, "m"); +    static inline_notes_curly                    = ctRegex!(`~\{\s*(.+?)\}~`, "mg"); +    // static inline_notes_curly                    = ctRegex!(`~\{(?:[*+]\s+|\s*)(.+?)\}~`, "mg"); +    static inline_al_delimiter_open_regular             = ctRegex!(`【`, "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!(`【(.+?)】`, "m"); +    static inline_notes_delimiter_al_regular_number_note = ctRegex!(`【(\d+)\s+(.+?)】`, "m"); +     +    static inline_al_delimiter_open_asterisk         = ctRegex!(`【\*`, "m"); +    static inline_al_delimiter_open_plus             = ctRegex!(`【\+`, "m"); +     +    static inline_curly_delimiter_open_regular             = ctRegex!(`~\{\s*`, "m"); +    static inline_curly_delimiter_close_regular            = ctRegex!(`\s*\}~`, "m"); +    static inline_curly_delimiter_open_and_close_regular   = ctRegex!(`~\{\s*|\s*\}~`, "m"); +    static inline_notes_delimiter_curly_regular            = ctRegex!(`~\{[ ]*(.+?)\}~`, "m"); +    // static inline_notes_curly_regular            = ctRegex!(`(?:[~][{][ ]*)(.+?)(?:[}][~])`, "m"); +    // static inline_notes_curly_regular            = ctRegex!(`~\{\s*(.+?)\}~`, "m"); +    // static inline_notes_curly                    = ctRegex!(`~\{(?:[*+]\s+|\s*)(.+?)\}~`, "mg"); +    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_text_and_note_curly            = ctRegex!(`(.+?)~\{(?:[*+]\s+|\s*)(.+?)\}~`, "mg"); +    static inline_text_and_note_al               = ctRegex!(`(?P<text>.+?)【(?:[*+ ]*)(?P<note>.+?)】`, "mg"); +    static inline_text_and_note_curly            = ctRegex!(`(?P<text>.+?)(?:(?:[~])[{][*+ ]*)(?P<note>.+?)(?:[}][~])`, "mg"); +    // static inline_text_and_note_curly            = ctRegex!(`(?P<text>.+?)~\{(?:[*+]\s+|\s*)(?P<note>.+?)\}~`, "mg"); +    // static inline_text_and_note_curly_sp         = ctRegex!(`(.+?)~\{[*+]+\s+(.+?)\}~`, "mg"); +    // static inline_text_and_note_curly_sp_asterisk = ctRegex!(`(.+?)~\{[*]+\s+(.+?)\}~`, "mg"); +    // static inline_text_and_note_curly_sp_plus    = ctRegex!(`(.+?)~\{[+]+\s+(.+?)\}~`, "mg"); +    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"); +    /+ inline markup book index +/ +    static book_index                = ctRegex!(`^=\{\s*(.+?)\}$`, "m"); +    static book_index_open           = ctRegex!(`^=\{\s*([^}]+?)$`); +    static book_index_close          = ctRegex!(`^(.*?)\}$`, "m"); // strip +    /+ 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 auto_obj_cite_number_ignore           = ctRegex!(`^[+~*$-]{3,}$`); // reminder +    static obj_cite_number_block_marks           = ctRegex!(`^--[+~-]#$`); +    /+ ignore outside code blocks +/ +    static regular_parse_skip        = ctRegex!(`^(--[+~-]#|-[\\]{2}-|=[.\\]{2}=)$`); // not structural info +    /+ line & page breaks +/ +    static break_line_within_object  = ctRegex!(`[\\]{2}( |$)`); +    // static break_line_break_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!(`』`); +    // ancestry, parent +    static parent                    = ctRegex!(`([0-7]):([0-9]+)`); +    /+ json +/ +    static tailing_comma             = ctRegex!(`,$`, "m"); +    /+ head +/ +    static main_headers              = ctRegex!(`^(?:creator|title|rights|date|original|classify|identifier|notes|publisher|make|links)$`, "m"); +    static subhead_creator           = ctRegex!(`^(?:author|translator|illustrator)$`, "m"); +    static subhead_title             = ctRegex!(`^(?:main|sub(?:title)?|full|language|edition|note)$`, "m"); +    static subhead_rights            = ctRegex!(`^(?:copyright|illustrations|license|cover)$`, "m"); +    static subhead_date              = ctRegex!(`^(?:published|created|issued|available|valid|modified|added_to_site)$`, "m"); +    static subhead_original          = ctRegex!(`^(?:title|language|source)$`, "m"); +    static subhead_classify          = ctRegex!(`^(?:topic_register|subject|keywords|loc|dewey)$`, "m"); +    static subhead_identifier        = ctRegex!(`^(?:oclc|pg|isbn)$`, "m"); +    static subhead_notes             = ctRegex!(`^(?:abstract|description)$`, "m"); +    static subhead_publisher         = ctRegex!(`^(?:name)$`, "m"); +    static subhead_make              = ctRegex!(`^(?:cover_image|home_button_image|home_button_text|footer|headings|num_top|breaks|substitute|bold|italics|emphasis|texpdf_font|css)$`, "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)$`); +    // static biblio_tags               = ctRegex!(`^(is|author_raw|author|author_arr|editor_raw|editor_arr|title|subtitle|fulltitle|language|trans|src|journal|in|volume|edition|year|place|publisher|url|pages|note|short_name|id):\s+(.+)`); +    /+ 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+)`); +  } +} diff --git a/src/sdp/compile_time_info.d b/src/sdp/compile_time_info.d new file mode 100644 index 0000000..783ac62 --- /dev/null +++ b/src/sdp/compile_time_info.d @@ -0,0 +1,38 @@ +/+ +  compile_time_info +  compile_time_info.d ++/ +template CompileTimeInfo() { +  version(Windows) { +    pragma(msg, "[ Windows compilation ]"); +    enum os = "Windows"; +  } else version(OSX) { +    pragma(msg, "[ Mac OS X POSIX System compilation ]"); +    enum os = "OSX"; +  } else version(linux) { +    pragma(msg, "[ Linux POSIX System compilation ]"); +    enum os = "Linux"; +  } else version(FreeBSD) { +    pragma(msg, "[ FreeBSD POSIX System compilation ]"); +    enum os = "FreeBSD"; +  } else version(OpenBSD) { +    pragma(msg, "[ OpenBSD POSIX System compilation ]"); +    enum os = "OpenBSD"; +  } else version(NetBSD) { +    pragma(msg, "[ NetBSD POSIX System compilation ]"); +    enum os = "NetBSD"; +  } else version(DragonFlyBSD) { +    pragma(msg, "[ DragonFlyBSD POSIX System compilation ]"); +    enum os = "DragonFlyBSD"; +  } else version(POSIX) { +    pragma(msg, "[ POSIX System compilation ]"); +    enum os = "POSIX"; +  } else { +    static assert(0, "OS not listed"); +  } +  version(D_LP64) { +    enum bits = "64 bit"; +  } else { +    enum bits = "32 bit"; +  } +} | 
