#+TITLE: sdp document abstraction #+AUTHOR: Ralph Amissah #+EMAIL: ralph.amissah@gmail.com #+STARTUP: indent #+LANGUAGE: en #+OPTIONS: H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc #+OPTIONS: author:nil email:nil creator:nil timestamp:nil #+PROPERTY: header-args :padline no :exports code :noweb yes #+EXPORT_SELECT_TAGS: export #+EXPORT_EXCLUDE_TAGS: noexport #+FILETAGS: :sdp:rel:ao: #+TAGS: assert(a) class(c) debug(d) mixin(m) sdp(s) tangle(T) template(t) WEB(W) noexport(n) [[./sdp.org][sdp]] [[./][org/]] * 0. Code Skeleton / Outline / Structure (tangles) :tangle:io:file: ** 1. ao abstract doc source: :ao_abstract_doc_source: #+BEGIN_SRC d :tangle ../src/sdp/ao_abstract_doc_source.d /++ document abstraction: abstraction of sisu markup for downstream processing ao_abstract_doc_source.d +/ template SiSUdocAbstraction() { private: struct Abstraction { /+ ↓ abstraction imports +/ <> /+ ↓ abstraction mixins +/ <> /+ ↓ abstraction struct init +/ <> /+ ↓ abstract marked up document +/ auto abstract_doc_source( char[][] markup_sourcefile_content, string[string][string] dochead_make_aa, string[string][string] dochead_meta_aa, bool[string] opt_action_bool, ) { /+ ↓ abstraction init +/ <> /+ abstraction init ↑ +/ /+ ↓ loop markup document/text line by line +/ srcDocLoop: foreach (line; markup_sourcefile_content) { /+ ↓ markup document/text line by line +/ <> if (type["code"] == TriState.on) { <> } else if (!matchFirst(line, rgx.skip_from_regular_parse)) { /+ object other than "code block" object (includes regular text paragraph, headings & blocks other than code) +/ <> } else { /+ not within a block group +/ <> if (matchFirst(line, rgx.block_open)) { <> } else if (!line.empty) { /+ line not empty +/ /+ non blocks (headings, paragraphs) & closed blocks +/ <> } else if (type["blocks"] == TriState.closing) { /+ line empty, with blocks flag +/ <> } else { /+ line.empty, post contents, empty variables: +/ <> } // close else for line empty } // close else for not the above } // close after non code, other blocks or regular text <> } /+ ← closed: loop markup document/text line by line +/ /+ ↓ post loop markup document/text +/ <> /+ post loop markup document/text ↑ +/ } /+ ← closed: abstract doc source +/ /+ ↓ abstraction functions +/ <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> /+ abstraction functions ↑ +/ /+ ↓ abstraction function emitters +/ <> /+ +/ <> <> <> <> <> <> <> /+ +/ <> <> <> <> <> <> /+ +/ <> <> <> /+ +/ <> /+ +/ <> /+ +/ <> /+ abstraction functions emitters ↑ +/ /+ ↓ abstraction functions assertions +/ <> /+ abstraction functions assertions ↑ +/ } /+ ← closed: struct Abstraction +/ } /+ ← closed: template SiSUdocAbstraction +/ #+END_SRC ** 2. ao object setter: :ao_object_setter: #+BEGIN_SRC d :tangle ../src/sdp/ao_object_setter.d /++ object setter: setting of sisu objects for downstream processing ao_object_setter.d +/ template ObjectSetter() { /+ structs +/ <> } #+END_SRC * 1. Document Abstraction :abstract:process: Process markup document, create document abstraction. ** _1. pre loop processing_ :pre: *** imports :imports: [[./ao_defaults.org][ao_defaults]] #+name: abs_imports #+BEGIN_SRC d import ao_defaults, // sdp/ao_defaults.d ao_object_setter, // sdp/ao_object_setter.d ao_rgx; // sdp/ao_rgx.d #+END_SRC *** mixins :mixins: #+name: abs_mixins #+BEGIN_SRC d mixin ObjectSetter; mixin InternalMarkup; #+END_SRC *** initialize :initialize: #+name: abs_init_struct #+BEGIN_SRC d /+ initialize +/ auto rgx = Rgx(); ObjGenericComposite[][string] the_table_of_contents_section; ObjGenericComposite[] the_document_head_section, the_document_body_section, the_bibliography_section, the_glossary_section, the_blurb_section; ObjGenericComposite[] the_dom_tail_section; string[string] an_object, processing; string an_object_key; string[] anchor_tags; string anchor_tag_; string segment_anchor_tag_that_object_belongs_to; string segment_anchor_tag_that_object_belongs_to_uri; 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 } /+ biblio variables +/ string biblio_tag_name, biblio_tag_entry, st; string[] biblio_arr_json; string biblio_entry_str_json; JSONValue[] bib_arr_json; int bib_entry; /+ counters +/ int cntr, previous_count, previous_length; int[string] line_occur; string[] html_segnames=["toc"]; int html_segnames_ptr=0; int html_segnames_ptr_cntr=0; int verse_line, heading_ptr; /+ paragraph attributes +/ int[string] indent; bool bullet = true; string content_non_header = "8"; auto obj_im = ObjInlineMarkup(); auto obj_att = ObjAttributes(); /+ ocn +/ int obj_cite_number, obj_cite_number_; auto object_citation_number = OCNemitter(); int[] dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; enum DomTags { none, open, close, close_and_open, open_still, } void heading_ancestors(O)( auto ref O obj, ref string[] lv_ancestors, ) { switch (obj.heading_lev_markup) { case 0: lv_ancestors[0] = to!string(obj.text); foreach(k; 1..8) { lv_ancestors[k] = ""; } goto default; case 1: lv_ancestors[1] = to!string(obj.text); foreach(k; 2..8) { lv_ancestors[k] = ""; } goto default; case 2: lv_ancestors[2] = to!string(obj.text); foreach(k; 3..8) { lv_ancestors[k] = ""; } goto default; case 3: lv_ancestors[3] = to!string(obj.text); foreach(k; 4..8) { lv_ancestors[k] = ""; } goto default; case 4: lv_ancestors[4] = to!string(obj.text); foreach(k; 5..8) { lv_ancestors[k] = ""; } goto default; case 5: lv_ancestors[5] = to!string(obj.text); foreach(k; 6..8) { lv_ancestors[k] = ""; } goto default; case 6: lv_ancestors[6] = to!string(obj.text); lv_ancestors[7] = ""; goto default; case 7: lv_ancestors[7] = to!string(obj.text); goto default; default: obj.heading_ancestors_text = lv_ancestors.dup; } } auto dom_set_markup_tags(int[] dom, int lev) { foreach (i; 0 .. 8) { if (i < lev) { if (dom[i] == DomTags.open || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.open_still; } else if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } } else if (i == lev) { if (lev == 0 && dom[i] == DomTags.open_still ) { dom[i] = DomTags.close; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close_and_open; } else { dom[i] = DomTags.open; } } else if (i > lev) { if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close; } } } debug(dom) { writeln(lev, ": ", dom); } return dom; } auto dom_set_collapsed_tags(int[] dom, int lev) { foreach (i; 0 .. 8) { if (i < lev) { if (dom[i] == DomTags.open || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.open_still; } else if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } } else if (i == lev) { if (lev == 0 && dom[i] == DomTags.open_still ) { dom[i] = DomTags.close; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close_and_open; } else { dom[i] = DomTags.open; } } else if (i > lev) { if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close; } } } debug(dom) { writeln(lev, ": ", dom); } return dom; } int ocn_emit(int ocn_status_flag) { return object_citation_number.ocn_emitter(ocn_status_flag); } /+ book index variables +/ string book_idx_tmp; string[][string][string] bookindex_unordered_hashes; 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 +/ ObjGenericComposite comp_obj_heading, comp_obj_location, comp_obj_block, comp_obj_code, comp_obj_poem_ocn, comp_obj_comment; auto node_construct = NodeStructureMetadata(); #+END_SRC *** scope #+name: abs_init_rest #+BEGIN_SRC d scope(success) { } scope(failure) { } scope(exit) { destroy(the_document_head_section); destroy(the_table_of_contents_section); destroy(the_document_body_section); destroy(the_bibliography_section); destroy(an_object); destroy(processing); destroy(biblio_arr_json); } #+END_SRC *** init rest #+name: abs_init_rest #+BEGIN_SRC d auto node_para_int_ = node_metadata_para_int; auto node_para_str_ = node_metadata_para_str; ObjGenericComposite comp_obj_heading_, comp_obj_para, comp_obj_toc; line_occur = [ "heading" : 0, "para" : 0, "glossary" : 0, "blurb" : 0, ]; auto type = flags_type_init; string[string] obj_cite_number_poem = [ "start" : "", "end" : "" ]; string[] lv_ancestors = [ "", "", "", "", "", "", "", "", ]; int[string] lv = [ "lv" : State.off, "h0" : State.off, "h1" : State.off, "h2" : State.off, "h3" : State.off, "h4" : State.off, "h5" : State.off, "h6" : State.off, "h7" : State.off, "lev_int_collapsed" : 0, ]; int[string] collapsed_lev = [ "h0" : State.off, "h1" : State.off, "h2" : State.off, "h3" : State.off, "h4" : State.off, "h5" : State.off, "h6" : State.off, "h7" : State.off ]; string[string] heading_match_str = [ "h_A": "^(none)", "h_B": "^(none)", "h_C": "^(none)", "h_D": "^(none)", "h_1": "^(none)", "h_2": "^(none)", "h_3": "^(none)", "h_4": "^(none)" ]; auto heading_match_rgx = [ "h_A": regex(r"^(none)"), "h_B": regex(r"^(none)"), "h_C": regex(r"^(none)"), "h_D": regex(r"^(none)"), "h_1": regex(r"^(none)"), "h_2": regex(r"^(none)"), "h_3": regex(r"^(none)"), "h_4": regex(r"^(none)") ]; string _anchor_tag; string toc_txt_; an_object["glossary_nugget"] = ""; an_object["blurb_nugget"] = ""; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "frontmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Table of Contents"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "toc"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.ptr_html_segnames = html_segnames_ptr; comp_obj_heading_.anchor_tags = ["toc"]; auto toc_head = comp_obj_heading_; html_segnames_ptr_cntr++; the_table_of_contents_section = [ "seg": [toc_head], "scroll": [toc_head], ]; auto mkup = InlineMarkup(); auto munge = ObjInlineMarkupMunge(); string[][string] lev4_subtoc; #+END_SRC ** _2. loop: process document body_ [+6] :loop: *** loop scope :scope: #+name: abs_in_loop_body_00 #+BEGIN_SRC d /+ 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 (i.e. happen earlier)) debug(source) { // source lines writeln(line); } debug(srclines) { if (!line.empty) { // source lines, not empty writefln( "* %s", line ); } } #+END_SRC *** check whether obj_cite_number is on or turned off :ocn: #+name: abs_in_loop_body_00 #+BEGIN_SRC d if (!line.empty) { _check_ocn_status_(line, type); } #+END_SRC *** [#A] separate regular markup text from code blocks [+5] **** code blocks :block:code: #+name: abs_in_loop_body_00_code_block #+BEGIN_SRC d /+ block object: code +/ _code_block_(line, an_object, type); continue; #+END_SRC **** non code objects (other blocks or regular text) [+4] :non_code: ***** in section (biblio, glossary, blurb) (block group) [+1] :block:active: ****** within section: biblio :biblio: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d if ((matchFirst(line, rgx.heading_biblio) || (type["biblio_section"] == State.on && (!matchFirst(line, rgx.heading_blurb_glossary)))) && (!matchFirst(line, rgx.heading)) && (!matchFirst(line, rgx.comment))) { /+ within section (block object): biblio +/ type["glossary_section"] = State.off; type["biblio_section"] = State.on; type["blurb_section"] = State.off; if (opt_action_bool["backmatter"] && opt_action_bool["section_biblio"]) { _biblio_block_(line, type, bib_entry, biblio_entry_str_json, biblio_arr_json); // debug(bibliobuild) { writeln("- ", biblio_entry_str_json); writeln("-> ", biblio_arr_json.length); } } continue; #+END_SRC ****** within section: glossary :glossary: if there is a glossary section you need to: - extract it - create standard headings - markup contents in standard way like regular paragraphs - need indentation and regular paragraph inline markup - reconstitute the document with the glossary section following the endnotes #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if ((matchFirst(line, rgx.heading_glossary) || (type["glossary_section"] == State.on && (!matchFirst(line, rgx.heading_biblio_blurb)))) && (!matchFirst(line, rgx.heading)) && (!matchFirst(line, rgx.comment))) { /+ within section (block object): glossary +/ debug(glossary) { writeln(__LINE__); writeln(line); } // _glossary_block_(line, type); type["glossary_section"] = State.on; type["biblio_section"] = State.off; type["blurb_section"] = State.off; if (opt_action_bool["backmatter"] && opt_action_bool["section_glossary"]) { indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; type["para"] = State.on; line_occur["para"] = State.off; an_object_key="glossary_nugget"; // if (matchFirst(line, rgx.heading_glossary)) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Glossary"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_glossary_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Glossary"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "glossary"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.anchor_tags = ["glossary"]; the_glossary_section ~= comp_obj_heading_; // } else if (matchFirst(line, rgx.heading)) { // _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa); // levels? } else { _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur); comp_obj_para = comp_obj_para.init; comp_obj_para.use = "backmatter"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "glossary"; comp_obj_para.text = to!string(line).strip; comp_obj_para.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.indent_hang = indent["hang_position"]; comp_obj_para.indent_base = indent["base_position"]; comp_obj_para.bullet = bullet; the_glossary_section ~= comp_obj_para; } type["ocn_status"] = TriState.off; } continue; #+END_SRC ****** within section: blurb :blurb: if there is a blurb section you need to: - extract it - create standard headings (or use line provided in 1~ heading) - markup contents in standard way like regular paragraphs - need regular paragraph inline markup - reconstitute the document with the blurb section at the very end of the doucment #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if ((matchFirst(line, rgx.heading_blurb) || (type["blurb_section"] == State.on && (!matchFirst(line, rgx.heading_biblio_glossary)))) && (!matchFirst(line, rgx.heading)) && (!matchFirst(line, rgx.comment))) { /+ within section (block object): blurb +/ debug(blurb) { writeln(__LINE__); writeln(line); } // _blurb_block_(line, type); type["glossary_section"] = State.off; type["biblio_section"] = State.off; type["blurb_section"] = State.on; if (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"]) { indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; type["para"] = State.on; line_occur["para"] = State.off; an_object_key="blurb_nugget"; if (matchFirst(line, rgx.heading_blurb)) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Blurb"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_blurb_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Blurb"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "blurb"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.anchor_tags = ["blurb"]; the_blurb_section ~= comp_obj_heading_; } else if ((matchFirst(line, rgx.heading)) && (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"])) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = to!string(line); comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "blurb"; comp_obj_heading_.marked_up_level = to!string(an_object["lev"]); comp_obj_heading_.heading_lev_markup = to!int(an_object["lev_markup_number"]); // make int, remove need to conv comp_obj_heading_.heading_lev_collapsed = to!int(an_object["lev_collapsed_number"]); // make int, remove need to conv comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_blurb_section ~= comp_obj_heading_; } else { _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur); comp_obj_para = comp_obj_para.init; comp_obj_para.use = "backmatter"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "blurb"; comp_obj_para.text = to!string(line).strip; comp_obj_para.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.indent_hang = indent["hang_position"]; comp_obj_para.indent_base = indent["base_position"]; comp_obj_para.bullet = bullet; the_blurb_section ~= comp_obj_para; } type["ocn_status"] = TriState.off; } continue; #+END_SRC ***** in blocks [+1] :block:active: ****** within block: poem :poem: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (type["poem"] == TriState.on) { /+ within block object: poem +/ _poem_block_(line, an_object, type, cntr, obj_cite_number_poem, dochead_make_aa); continue; #+END_SRC ****** within block: group :group: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d /+ within block object: group +/ } else if (type["group"] == TriState.on) { /+ within block object: group +/ _group_block_(line, an_object, type); continue; #+END_SRC ****** within block: block :block: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (type["block"] == TriState.on) { /+ within block object: block +/ _block_block_(line, an_object, type); continue; #+END_SRC ****** within block: quote :quote: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (type["quote"] == TriState.on) { /+ within block object: quote +/ _quote_block_(line, an_object, type); continue; #+END_SRC ****** within block: table :table: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (type["table"] == TriState.on) { /+ within block object: table +/ _table_block_(line, an_object, type); continue; #+END_SRC ***** not identified as being within block group (could still be, or not) [+3] ****** assert #+name: abs_in_loop_body_open_block_obj_assert #+BEGIN_SRC d assert( (type["blocks"] == TriState.off) || (type["blocks"] == TriState.closing), "block status: none or closed" ); assertions_flag_types_block_status_none_or_closed(type); #+END_SRC ****** block open #+name: abs_in_loop_body_open_block_obj #+BEGIN_SRC d if (matchFirst(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; #+END_SRC ****** line not empty [+2] ******* asserts :assert: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d 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__); writeln(line); } assert( matchFirst(line, rgx.book_index) || matchFirst(line, rgx.book_index_open) || type["book_index"] == State.on ); } #+END_SRC ******* book index :bookindex: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d if ((matchFirst(line, rgx.book_index)) || (matchFirst(line, rgx.book_index_open)) || (type["book_index"] == State.on )) { /+ book_index +/ _book_index_(line, book_idx_tmp, an_object, type, opt_action_bool); #+END_SRC ******* not book index [+1] #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d } else { /+ not book_index +/ #+END_SRC ******** matched: comment :comment:match: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d an_object_key="body_nugget"; if (auto m = matchFirst(line, rgx.comment)) { /+ matched comment +/ debug(comment) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; comp_obj_comment = comp_obj_comment.init; comp_obj_comment.use = "comment"; comp_obj_comment.is_of = "comment"; comp_obj_comment.is_a = "comment"; comp_obj_comment.text = an_object[an_object_key].strip; the_document_body_section ~= comp_obj_comment; _common_reset_(line_occur, an_object, type); processing.remove("verse"); ++cntr; #+END_SRC ******** flag not set & line not exist: heading or para :heading:paragraph: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d } else if (((line_occur["para"] == State.off) && (line_occur["heading"] == State.off)) && ((type["para"] == State.off) && (type["heading"] == State.off))) { /+ heading or para but neither flag nor line exists +/ if ((dochead_make_aa["make"]["headings"].length > 2) && (type["make_headings"] == State.off)) { /+ heading found +/ _heading_found_(line, dochead_make_aa["make"]["headings"], heading_match_str, heading_match_rgx, type); } if ((type["make_headings"] == State.on) && ((line_occur["para"] == State.off) && (line_occur["heading"] == State.off)) && ((type["para"] == State.off) && (type["heading"] == State.off))) { /+ heading make set +/ _heading_make_set_(line, line_occur, heading_match_rgx, type); } /+ TODO node info: all headings identified at this point, - extract node info here?? - how long can it wait? - should be incorporated in composite objects - should happen before endnote links set (they need to be moved down?) // node_construct.node_emitter_heading segment anchor tag +/ if (matchFirst(line, rgx.heading)) { /+ heading match +/ _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa); } else if (line_occur["para"] == State.off) { /+ para match +/ an_object_key="body_nugget"; _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur); } #+END_SRC ******** line exist: heading :heading: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d } else if (line_occur["heading"] > State.off) { /+ heading +/ debug(heading) { // heading writeln(line); } an_object[an_object_key] ~= line ~= "\n"; ++line_occur["heading"]; #+END_SRC ******** line exist: para :para: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d } else if (line_occur["para"] > State.off) { /+ paragraph +/ debug(para) { writeln(line); } an_object[an_object_key] ~= " " ~ line; ++line_occur["para"]; } } #+END_SRC ****** line empty, with block flag #+name: abs_in_loop_body_not_block_obj_line_empty_blocks_flags #+BEGIN_SRC d _block_flag_line_empty_( line, an_object, the_document_body_section, bookindex_unordered_hashes, obj_cite_number, comp_obj_heading, cntr, type, obj_cite_number_poem, dochead_make_aa ); #+END_SRC ****** line empty [+1] ******* assert line empty :assert: #+name: abs_in_loop_body_not_block_obj_line_empty #+BEGIN_SRC d assert( line.empty, "line should be empty" ); assert( (type["blocks"] == State.off), "code block status: none" ); #+END_SRC ******* heading object :heading:object: #+name: abs_in_loop_body_not_block_obj_line_empty #+BEGIN_SRC d if ((type["heading"] == State.on) && (line_occur["heading"] > State.off)) { /+ heading object (current line empty) +/ obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bkidx_hash(an_object["bookindex_nugget"], obj_cite_number); an_object["is"] = "heading"; an_object_key="body_nugget"; auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); // tuple this with anchor tags? an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; if (to!int(an_object["lev_markup_number"]) == 4) { segment_anchor_tag_that_object_belongs_to = anchor_tags[0]; segment_anchor_tag_that_object_belongs_to_uri = anchor_tags[0] ~ ".fnSuffix"; anchor_tag_ = anchor_tags[0]; } else if (to!int(an_object["lev_markup_number"]) > 4) { segment_anchor_tag_that_object_belongs_to = anchor_tag_; segment_anchor_tag_that_object_belongs_to_uri = anchor_tag_ ~ ".fnSuffix#" ~ to!string(obj_cite_number); } else if (to!int(an_object["lev_markup_number"]) < 4) { segment_anchor_tag_that_object_belongs_to = ""; segment_anchor_tag_that_object_belongs_to_uri = ""; } /+ (incrementally build toc) table of contents here! +/ _anchor_tag=to!string(obj_cite_number); the_table_of_contents_section = obj_im.table_of_contents_gather_headings( an_object, dochead_make_aa, segment_anchor_tag_that_object_belongs_to, _anchor_tag, lev4_subtoc, the_table_of_contents_section, ); if (an_object["lev_markup_number"] == "4") { html_segnames ~= segment_anchor_tag_that_object_belongs_to; html_segnames_ptr = html_segnames_ptr_cntr; html_segnames_ptr_cntr++; } auto comp_obj_heading = node_construct.node_emitter_heading( an_object["substantive"], // string an_object["lev"], // string an_object["lev_markup_number"], // string an_object["lev_collapsed_number"], // string segment_anchor_tag_that_object_belongs_to, // string obj_cite_number, // int cntr, // int heading_ptr, // int lv_ancestors, // string[] an_object["is"], // string html_segnames_ptr, // int ); ++heading_ptr; debug(segments) { writeln(an_object["lev_markup_number"]); writeln(segment_anchor_tag_that_object_belongs_to); } the_document_body_section ~= comp_obj_heading; // track previous heading and make assertions debug(objectrelated1) { // check writeln(line); } _common_reset_(line_occur, an_object, type); an_object.remove("lev"); an_object.remove("lev_markup_number"); processing.remove("verse"); ++cntr; #+END_SRC ******* paragraph object :paragraph:object: #+name: abs_in_loop_body_not_block_obj_line_empty #+BEGIN_SRC d } else if ((type["para"] == State.on) && (line_occur["para"] > State.off)) { /+ paragraph object (current line empty) +/ obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bkidx_hash(an_object["bookindex_nugget"], obj_cite_number); an_object["is"] = "para"; auto comp_obj_heading = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"], ); auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); // ... an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; comp_obj_para = comp_obj_para.init; comp_obj_para.use = "body"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "para"; comp_obj_para.text = to!string(an_object["substantive"]).strip; comp_obj_para.ocn = obj_cite_number; comp_obj_para.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_para.indent_hang = indent["hang_position"]; comp_obj_para.indent_base = indent["base_position"]; comp_obj_para.bullet = bullet; comp_obj_para.anchor_tags = anchor_tags; the_document_body_section ~= comp_obj_para; _common_reset_(line_occur, an_object, type); indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; processing.remove("verse"); ++cntr; } else { assert( line == null, "line variable should be empty, should not occur" ); // check what happens when paragraph separated by 2 newlines } #+END_SRC *** close non code objects (regular text) *** regular text objects :text:paragraph: #+name: abs_in_loop_body_01 #+BEGIN_SRC d /+ unless (the_document_body_section.length == 0) ? +/ if (the_document_body_section.length > 0) { if (((the_document_body_section[$-1].is_a == "para") || (the_document_body_section[$-1].is_a == "heading") || (the_document_body_section[$-1].is_a == "group")) && (the_document_body_section.length > previous_length) ) { if ((the_document_body_section[$-1].is_a == "heading") && (the_document_body_section[$-1].heading_lev_markup < 5)) { type["biblio_section"] = State.off; type["glossary_section"] = State.off; type["blurb_section"] = State.off; } previous_length = to!int(the_document_body_section.length); if ( match(the_document_body_section[$-1].text, rgx.inline_notes_delimiter_al_regular_number_note) ) { previous_count=to!int(the_document_body_section.length -1); note_section.gather_notes_for_endnote_section( the_document_body_section, segment_anchor_tag_that_object_belongs_to, to!int(the_document_body_section.length-1), ); } } } #+END_SRC ** _3. post main-loop processing_ :post: *** misc #+name: abs_post #+BEGIN_SRC d debug(objectrelated2) { // check writeln(line); } /+ Backmatter: - endnotes - glossary - bibliography / references - book index - blurb +/ // TODO FIGURE OUT, you need this possibility // obj_im.obj_inline_markup_and_anchor_tags("doc_end_reset", an_object_key, "", dochead_make_aa); #+END_SRC *** tie up preparation of document sections **** endnotes section (scroll & seg) :endnotes: #+name: abs_post #+BEGIN_SRC d auto en_tuple = note_section.endnote_objects(obj_cite_number, opt_action_bool); static assert(!isTypeTuple!(en_tuple)); auto the_endnotes_section = en_tuple[0]; obj_cite_number = en_tuple[1]; debug(endnotes) { writefln( "%s %s", __LINE__, the_endnotes_section.length ); foreach (o; the_endnotes_section) { writeln(o); } } #+END_SRC **** no glossary section? :glossary: #+name: abs_post #+BEGIN_SRC d if (an_object["glossary_nugget"].length == 0) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "(skip) there is no Glossary section"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_glossary_section ~= comp_obj_heading_; } else { writeln("gloss"); } debug(glossary) { foreach (gloss; the_glossary_section) { writeln(gloss.text); } } #+END_SRC **** bibliography section (objects) :bibliography: #+name: abs_post #+BEGIN_SRC d 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); #+END_SRC #+name: abs_post #+BEGIN_SRC d if (biblio_ordered.length > 0) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Bibliography"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_bibliography_section ~= comp_obj_heading_; // --- comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Bibliography"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "bibliography"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.anchor_tags = ["bibliography"]; the_bibliography_section ~= comp_obj_heading_; } else { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "(skip) there is no Bibliography"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_bibliography_section ~= comp_obj_heading_; } #+END_SRC ***** format biblio string #+name: abs_post #+BEGIN_SRC d string out_; foreach (entry; biblio_ordered) { out_ = format( "%s \"%s\"%s%s%s%s%s%s%s%s%s.", ((entry["author"].str.empty) ? entry["editor"].str : entry["author"].str), entry["fulltitle"].str, ((entry["journal"].str.empty) ? "" : ", /{" ~ entry["journal"].str ~ "}/"), ((entry["volume"].str.empty) ? "" : ", " ~ entry["volume"].str), ((entry["in"].str.empty) ? "" : ", " ~ entry["in"].str), ((!(entry["author"].str.empty) && (!(entry["editor"].str.empty))) ? entry["editor"].str : ""), ", " ~ entry["year"].str, ((entry["pages"].str.empty) ? "" : ", " ~ entry["pages"].str), ((entry["publisher"].str.empty) ? "" : ", " ~ entry["publisher"].str), ((entry["place"].str.empty) ? "" : ", " ~ entry["place"].str), ((entry["url"].str.empty) ? "" : ", [" ~ entry["url"].str ~ "]"), ); comp_obj_para = comp_obj_para.init; comp_obj_para.use = "backmatter"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "bibliography"; comp_obj_para.text = to!string(out_).strip; comp_obj_para.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.indent_hang = 0; comp_obj_para.indent_base = 1; comp_obj_para.bullet = bullet; comp_obj_para.anchor_tags = anchor_tags; the_bibliography_section ~= comp_obj_para; } #+END_SRC #+name: abs_post #+BEGIN_SRC d debug(bibliosection) { foreach (o; the_bibliography_section) { writeln(o.text); } } #+END_SRC ***** bibliography components 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 **** bookindex section (scroll & seg) :book:index: #+name: abs_post #+BEGIN_SRC d auto bi = BookIndexReportSection(); auto bi_tuple = bi.bookindex_build_abstraction_section( bookindex_unordered_hashes, obj_cite_number, segment_anchor_tag_that_object_belongs_to, opt_action_bool, ); static assert(!isTypeTuple!(bi_tuple)); auto the_bookindex_section = bi_tuple[0]; obj_cite_number = bi_tuple[1]; debug(bookindex) { // bookindex foreach (bi_entry; the_bookindex_section["seg"]) { writeln(bi_entry); } } #+END_SRC **** no blurb section? :blurb: #+name: abs_post #+BEGIN_SRC d if (an_object["blurb_nugget"].length == 0) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "(skip) there is no Blurb section"; comp_obj_heading_.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_blurb_section ~= comp_obj_heading_; } else { writeln("blurb"); } debug(blurb) { foreach (blurb; the_blurb_section) { writeln(blurb.text); } } #+END_SRC **** toc backmatter, table of contents backmatter (scroll & seg) :contents: #+name: abs_post #+BEGIN_SRC d indent=[ "hang_position" : 1, "base_position" : 1, ]; comp_obj_toc = comp_obj_toc.init; comp_obj_toc.use = "frontmatter"; comp_obj_toc.is_of = "para"; comp_obj_toc.is_a = "toc"; comp_obj_toc.ocn = 0; comp_obj_toc.obj_cite_number = ""; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.bullet = false; if (the_endnotes_section.length > 1) { toc_txt_ = format( "{ %s }%s../%s.fnSuffix", "Endnotes", mkup.mark_internal_site_lnk, "endnotes", // segment_anchor_tag_that_object_belongs_to ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["seg"] ~= comp_obj_toc; } if (the_glossary_section.length > 1) { toc_txt_ = format( "{ %s }%s../%s.fnSuffixs", "Glossary", mkup.mark_internal_site_lnk, "glossary", // segment_anchor_tag_that_object_belongs_to ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Glossary", "glossary", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } if (the_bibliography_section.length > 1){ toc_txt_ = format( "{ %s }%s../%s.fnSuffix", "Bibliography", mkup.mark_internal_site_lnk, "bibliography", // segment_anchor_tag_that_object_belongs_to ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Bibliography", "bibliography", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } if (the_bookindex_section["seg"].length > 1) { toc_txt_ = format( "{ %s }%s../%s.fnSuffix", "Book Index", mkup.mark_internal_site_lnk, "bookindex", // segment_anchor_tag_that_object_belongs_to ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["seg"] ~= comp_obj_toc; } if (the_bookindex_section["scroll"].length > 1) { toc_txt_ = format( "{ %s }#%s", "Book Index", "bookindex", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } if (the_blurb_section.length > 1) { toc_txt_ = format( "{ %s }%s../%s.fnSuffix", "Blurb", mkup.mark_internal_site_lnk, "blurb", // segment_anchor_tag_that_object_belongs_to ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Blurb", "blurb", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } debug(toc) { writefln( "%s %s", __LINE__, the_table_of_contents_section["seg"].length ); foreach (toc_linked_heading; the_table_of_contents_section["seg"]) { writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text); } } debug(tocscroll) { writefln( "%s %s", __LINE__, the_table_of_contents_section["seg"].length ); foreach (toc_linked_heading; the_table_of_contents_section["scroll"]) { writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text); } } #+END_SRC **** doc head (separate document head from body, make space for toc) #+name: abs_post #+BEGIN_SRC d the_document_head_section ~= the_document_body_section[0]; the_document_body_section=the_document_body_section[1..$]; #+END_SRC *** TODO minor loops :post: **** 1. loop: backmatter loop up to lev4: html_segnames, set backmatter pointers could optimise by - skipping second and third pass unless the output html seg or epub is being made! NOTE there are issues attempting to do this on first pass - as - backmatter is created out of sequence and - it is not certain which are present it is quite neat to have all in one place as we have here: #+name: abs_post #+BEGIN_SRC d if (the_endnotes_section.length > 1) { html_segnames ~= "endnotes"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref section; the_endnotes_section) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_glossary_section.length > 1) { html_segnames ~= "glossary"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref section; the_glossary_section) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_bibliography_section.length > 1) { html_segnames ~= "bibliography"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref section; the_bibliography_section) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_bookindex_section["scroll"].length > 1) { html_segnames ~= "bookindex"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref section; the_bookindex_section["scroll"]) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } foreach (ref section; the_bookindex_section["seg"]) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_blurb_section.length > 1) { html_segnames ~= "blurb"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref section; the_blurb_section) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } #+END_SRC **** 2. loop: all objects structural relationships (sections, segments, objects) needed for DOM structure, segnames & subtoc, backmatter pointers if used minimally only for DOM structure, segnames, subtoc, could optimise by - skipping second and third pass unless the output html seg or epub is being made! or could conveniently be used more extensively for ancestors as well (though this can be extracted earlier) Build here: - DOM structure - ancestors and decendants (as needed) up to document heading 1~, lev4 html: during the third pass all previous and next segment names are known next are not yet known for backmatter during the second pass #+name: abs_post #+BEGIN_SRC d foreach (ref obj; the_document_head_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } if (the_table_of_contents_section["scroll"].length > 1) { dom_markedup_buffer = dom_markedup.dup; dom_collapsed_buffer = dom_collapsed.dup; foreach (ref obj; the_table_of_contents_section["scroll"]) { if (obj.is_a == "heading") { debug(dom) { // writeln(obj.text); } if (obj.heading_lev_markup == 4) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } dom_markedup = dom_markedup_buffer.dup; dom_collapsed = dom_collapsed_buffer.dup; foreach (ref obj; the_table_of_contents_section["seg"]) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup == 4) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ multiple 1~ levels, loop through document body +/ if (the_document_body_section.length > 1) { foreach (ref obj; the_document_body_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup == 4) { obj.lev4_subtoc = lev4_subtoc[obj.segment_anchor_tag]; obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ optional only one 1~ level +/ if (the_endnotes_section.length > 1) { dom_markedup_buffer = dom_markedup.dup; dom_collapsed_buffer = dom_collapsed.dup; dom_markedup = dom_markedup_buffer.dup; dom_collapsed = dom_collapsed_buffer.dup; foreach (ref obj; the_endnotes_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ optional only one 1~ level +/ if (the_glossary_section.length > 1) { foreach (ref obj; the_glossary_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ optional only one 1~ level +/ if (the_bibliography_section.length > 1) { foreach (ref obj; the_bibliography_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ optional only one 1~ level +/ if (the_bookindex_section["scroll"].length > 1) { dom_markedup_buffer = dom_markedup.dup; dom_collapsed_buffer = dom_collapsed.dup; foreach (ref obj; the_bookindex_section["scroll"]) { if (obj.is_a == "heading") { debug(dom) { // writeln(obj.text); } if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } dom_markedup = dom_markedup_buffer.dup; dom_collapsed = dom_collapsed_buffer.dup; foreach (ref obj; the_bookindex_section["seg"]) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ optional only one 1~ level +/ if (the_blurb_section.length > 1) { foreach (ref obj; the_blurb_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } /+ TODO - note create/insert heading object sole purpose eof close all open tags sort out: - obj.dom_markedup = dom_markedup; - obj.dom_collapsed = dom_collapsed; +/ dom_markedup = dom_set_markup_tags(dom_markedup, 0); dom_collapsed = dom_set_collapsed_tags(dom_collapsed, 0); comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; // comp_obj_heading_.text = "(skip) this is the DOM tail"; comp_obj_heading_.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = ""; comp_obj_heading_.marked_up_level = ""; comp_obj_heading_.heading_lev_markup = 9; comp_obj_heading_.heading_lev_collapsed = 9; comp_obj_heading_.parent_ocn = 0; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.dom_markedup = dom_markedup.dup; comp_obj_heading_.dom_collapsed = dom_collapsed.dup; the_dom_tail_section ~= comp_obj_heading_; } #+END_SRC ** _4. return document tuple_ :post: *** the document :document: #+name: abs_post #+BEGIN_SRC d auto document_the = [ "head": the_document_head_section, "toc_seg": the_table_of_contents_section["seg"], "toc_scroll": the_table_of_contents_section["scroll"], /+ substantive/body: +/ "body": the_document_body_section, /+ backmatter: +/ "endnotes": the_endnotes_section, "glossary": the_glossary_section, "bibliography": the_bibliography_section, "bookindex_scroll": the_bookindex_section["scroll"], "bookindex_seg": the_bookindex_section["seg"], "blurb": the_blurb_section, /+ dom tail only +/ "tail": the_dom_tail_section, ]; #+END_SRC *** document _section keys_ sequence #+name: abs_post #+BEGIN_SRC d string[][string] document_section_keys_sequenced = [ "seg": ["head", "toc_seg", "body",], "scroll": ["head", "toc_scroll", "body",] ]; if (document_the["endnotes"].length > 1) { document_section_keys_sequenced["seg"] ~= "endnotes"; document_section_keys_sequenced["scroll"] ~= "endnotes"; } if (document_the["glossary"].length > 1) { document_section_keys_sequenced["seg"] ~= "glossary"; document_section_keys_sequenced["scroll"] ~= "glossary"; } if (document_the["bibliography"].length > 1) { document_section_keys_sequenced["seg"] ~= "bibliography"; document_section_keys_sequenced["scroll"] ~= "bibliography"; } if (document_the["bookindex_seg"].length > 1) { document_section_keys_sequenced["seg"] ~= "bookindex_seg"; } if (document_the["bookindex_scroll"].length > 1) { document_section_keys_sequenced["scroll"] ~= "bookindex_scroll"; } if (document_the["blurb"].length > 1) { document_section_keys_sequenced["seg"] ~= "blurb"; document_section_keys_sequenced["scroll"] ~= "blurb"; } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { document_section_keys_sequenced["seg"] ~= "tail"; document_section_keys_sequenced["scroll"] ~= "tail"; } #+END_SRC *** clean out structure #+name: abs_post destroy(the_document_head_section); destroy(the_document_table_of_contents_section); destroy(the_document_body_section); destroy(the_endnotes_section); destroy(the_glossary_section); destroy(the_bibliography_section); destroy(the_bookindex_section); destroy(the_blurb_section); #+END_SRC *** _return document tuple_ :return:tuple: #+name: abs_post #+BEGIN_SRC d auto t = tuple( document_the, document_section_keys_sequenced, html_segnames, ); return t; #+END_SRC ** 5. Functions :abstract:function: functions used in document abstraction *** set & resets :reset: **** object reset: remove (clean) :object:remove: #+name: abs_functions_object_reset #+BEGIN_SRC d auto object_reset(ref string[string] an_object) { an_object.remove("body_nugget"); an_object.remove("substantive"); an_object.remove("is"); an_object.remove("attrib"); an_object.remove("bookindex_nugget"); } #+END_SRC **** set, initialize or re-initialize :set: #+name: abs_functions_header_set_common #+BEGIN_SRC d auto _common_reset_( ref int[string] line_occur, ref string[string] an_object, ref int[string] type ) { line_occur["heading"] = State.off; line_occur["para"] = State.off; type["heading"] = State.off; type["para"] = State.off; object_reset(an_object); } #+END_SRC *** check obj_cite_number status in document :ocn: #+name: abs_functions_ocn_status #+BEGIN_SRC d void _check_ocn_status_( char[] line, ref int[string] type ) { if ((!line.empty) && (type["ocn_status_multi_obj"] == TriState.off)) { /+ not multi-line object, check whether obj_cite_number is on or turned off +/ if (matchFirst(line, rgx.obj_cite_number_block_marks)) { /+ switch off obj_cite_number +/ if (matchFirst(line, rgx.obj_cite_number_off_block)) { type["ocn_status_multi_obj"] = TriState.on; debug(ocnoff) { writeln(line); } } if (matchFirst(line, rgx.obj_cite_number_off_block_dh)) { type["ocn_status_multi_obj"] = TriState.closing; debug(ocnoff) { writeln(line); } } } else { if (type["ocn_status_multi_obj"] == TriState.off) { if (matchFirst(line, rgx.obj_cite_number_off)) { type["ocn_status"] = TriState.on; } else if (matchFirst(line, rgx.obj_cite_number_off_dh)) { type["ocn_status"] = TriState.closing; } else { type["ocn_status"] = TriState.off; } } else { type["ocn_status"] = type["ocn_status_multi_obj"]; } } } else if ((!line.empty) && (type["ocn_status_multi_obj"] > TriState.off)) { if (matchFirst(line, rgx.obj_cite_number_off_block_close)) { type["ocn_status_multi_obj"] = TriState.off; type["ocn_status"] = TriState.off; debug(ocnoff) { writeln(line); } } } } #+END_SRC *** block :block: **** block start (open) block :start: ***** function open for block starts #+name: abs_functions_block #+BEGIN_SRC d void _start_block_( char[] line, ref int[string] type, string[string] obj_cite_number_poem ) { #+END_SRC ***** block (various) curly open :curly: #+name: abs_functions_block #+BEGIN_SRC d if (matchFirst(line, rgx.block_curly_code_open)) { /+ curly code open +/ debug(code) { // code (curly) open writefln( "* [code curly] %s", line ); } type["blocks"] = TriState.on; type["code"] = TriState.on; type["curly_code"] = TriState.on; } else if (matchFirst(line, rgx.block_curly_poem_open)) { /+ curly poem open +/ debug(poem) { // poem (curly) open writefln( "* [poem curly] %s", 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 (matchFirst(line, rgx.block_curly_group_open)) { /+ curly group open +/ debug(group) { // group (curly) open writefln( "* [group curly] %s", line ); } type["blocks"] = TriState.on; type["group"] = TriState.on; type["curly_group"] = TriState.on; } else if (matchFirst(line, rgx.block_curly_block_open)) { /+ curly block open +/ debug(block) { // block (curly) open writefln( "* [block curly] %s", line ); } type["blocks"] = TriState.on; type["block"] = TriState.on; type["curly_block"] = TriState.on; } else if (matchFirst(line, rgx.block_curly_quote_open)) { /+ curly quote open +/ debug(quote) { // quote (curly) open writefln( "* [quote curly] %s", line ); } type["blocks"] = TriState.on; type["quote"] = TriState.on; type["curly_quote"] = TriState.on; } else if (matchFirst(line, rgx.block_curly_table_open)) { /+ curly table open +/ debug(table) { // table (curly) open writefln( "* [table curly] %s", line ); } type["blocks"] = TriState.on; type["table"] = TriState.on; type["curly_table"] = TriState.on; #+END_SRC ***** block (various) tic open :tic: #+name: abs_functions_block #+BEGIN_SRC d } else if (matchFirst(line, rgx.block_tic_code_open)) { /+ tic code open +/ debug(code) { // code (tic) open writefln( "* [code tic] %s", line ); } type["blocks"] = TriState.on; type["code"] = TriState.on; type["tic_code"] = TriState.on; } else if (matchFirst(line, rgx.block_tic_poem_open)) { /+ tic poem open +/ debug(poem) { // poem (tic) open writefln( "* [poem tic] %s", 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 (matchFirst(line, rgx.block_tic_group_open)) { /+ tic group open +/ debug(group) { // group (tic) open writefln( "* [group tic] %s", line ); } type["blocks"] = TriState.on; type["group"] = TriState.on; type["tic_group"] = TriState.on; } else if (matchFirst(line, rgx.block_tic_block_open)) { /+ tic block open +/ debug(block) { // block (tic) open writefln( "* [block tic] %s", line ); } type["blocks"] = TriState.on; type["block"] = TriState.on; type["tic_block"] = TriState.on; } else if (matchFirst(line, rgx.block_tic_quote_open)) { /+ tic quote open +/ debug(quote) { // quote (tic) open writefln( "* [quote tic] %s", line ); } type["blocks"] = TriState.on; type["quote"] = TriState.on; type["tic_quote"] = TriState.on; } else if (matchFirst(line, rgx.block_tic_table_open)) { /+ tic table open +/ debug(table) { // table (tic) open writefln( "* [table tic] %s", line ); } type["blocks"] = TriState.on; type["table"] = TriState.on; type["tic_table"] = TriState.on; } #+END_SRC ***** function close for block starts #+name: abs_functions_block #+BEGIN_SRC d } #+END_SRC **** block continue (an open block) :continue: ***** code block (special status, deal with first) :code: #+name: abs_functions_block_code #+BEGIN_SRC d void _code_block_( char[] line, ref string[string] an_object, ref int[string] type ) { if (type["curly_code"] == TriState.on) { if (matchFirst(line, rgx.block_curly_code_close)) { debug(code) { // code (curly) close writeln(line); } type["blocks"] = TriState.closing; type["code"] = TriState.closing; type["curly_code"] = TriState.off; } else { debug(code) { // code (curly) line writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // code (curly) line } } else if (type["tic_code"] == TriState.on) { if (matchFirst(line, rgx.block_tic_close)) { debug(code) { // code (tic) close writeln(line); } type["blocks"] = TriState.closing; type["code"] = TriState.closing; type["tic_code"] = TriState.off; } else { debug(code) { // code (tic) line writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // code (tic) line } } } #+END_SRC ***** biblio block :biblio: ****** biblio tag map #+name: abs_functions_block_biblio #+BEGIN_SRC d 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]; } #+END_SRC ******* +consider+ #+name: none #+BEGIN_SRC d final string biblio_tag_map_(string abr) { string name; switch (abr) { case "au": name="author_raw"; break; case "ed": name="editor_raw"; break; case "ti": name="fulltitle"; break; case "lng": name="language"; break; case "jo": name="journal"; break; case "vol": name="volume"; break; case "edn": name="edition"; break; case "yr": name="year"; break; case "pl": name="place"; break; case "pb": name="publisher"; break; case "pub": name="publisher"; break; case "pg": name="pages"; break; case "pgs": name="pages"; break; case "sn": name="short_name"; break; default: name=abr; break; } return name; } #+END_SRC ****** biblio block #+name: abs_functions_block_biblio #+BEGIN_SRC d void _biblio_block_( char[] line, ref int[string] type, ref int bib_entry, ref string biblio_entry_str_json, ref string[] biblio_arr_json ) { if (matchFirst(line, rgx.heading_biblio)) { type["biblio_section"] = TriState.on; type["blurb_section"] = State.off; type["glossary_section"] = State.off; } if (line.empty) { debug { debug(biblioblock) { writeln("---"); } debug(biblioblockinclude) { writeln(biblio_entry_str_json.length); } } if ((bib_entry == State.off) && (biblio_entry_str_json.empty)) { bib_entry = State.on; biblio_entry_str_json = biblio_entry_tags_jsonstr; } else if (!(biblio_entry_str_json.empty)) { bib_entry = State.off; if (!(biblio_entry_str_json == biblio_entry_tags_jsonstr)) { auto biblio_entry = parseJSON(biblio_entry_str_json); if (biblio_entry["fulltitle"].str.empty) { writeln("check problem entry (Title missing): ", biblio_entry_str_json); } else if ((biblio_entry["author_raw"].str.empty) && (biblio_entry["editor_raw"].str.empty)) { writeln("check problem entry (No author and no editor): ", biblio_entry_str_json); } else { biblio_arr_json ~= biblio_entry_str_json; } biblio_entry_str_json = biblio_entry_tags_jsonstr; } } else { // CHECK ERROR writeln("?? 2. ERROR ", biblio_entry_str_json, "??"); biblio_entry_str_json = ""; } } else if (matchFirst(line, rgx.biblio_tags)) { debug(biblioblock) { writeln(line); } auto bt = match(line, rgx.biblio_tags); bib_entry = State.off; st=to!string(bt.captures[1]); auto header_tag_value=to!string(bt.captures[2]); JSONValue j = parseJSON(biblio_entry_str_json); biblio_tag_name = (match(st, rgx.biblio_abbreviations)) ? (biblio_tag_map(st)) : st; j.object[biblio_tag_name] = header_tag_value; debug(bibliounsortedcheckduplicates) { writeln(biblio_tag_name, ": ", header_tag_value); writeln("--"); } switch (biblio_tag_name) { case "author_raw": // author_arr author (fn sn) j["author_arr"] = 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, ""); j["author"].str = tmp; goto default; 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, ""); j["editor"].str = tmp; goto default; case "fulltitle": // title & subtitle goto default; default: break; } auto s = j.toString(); debug(biblio1) { writefln( "* %s: %s\n%s", biblio_tag_name, biblio_tag_entry, j[biblio_tag_name] ); } if ((match(line, rgx.comment))) { writeln("ERROR", line, "COMMENT"); writeln("ERROR", s, "%%"); } if (!(match(line, rgx.comment))) { debug(biblioblockinclude) { writeln(line); } biblio_entry_str_json = s; } else { biblio_entry_str_json = ""; } header_tag_value=""; } } #+END_SRC ***** TODO poem block, verse objects :poem:verse: why extra object stuff only in poem/verse? #+name: abs_functions_block_poem #+BEGIN_SRC d void _poem_block_( char[] line, ref string[string] an_object, ref int[string] type, ref int cntr, string[string] obj_cite_number_poem, string[string][string] dochead_make_aa, ) { if (type["curly_poem"] == TriState.on) { if (matchFirst(line, rgx.block_curly_poem_close)) { an_object[an_object_key]="verse"; // check that this is as you please debug(poem) { // poem (curly) close writefln( "* [poem curly] %s", line ); } if (processing.length > 0) { an_object[an_object_key] = processing["verse"]; } debug(poem) { // poem (curly) close writeln(__LINE__); writefln( "* %s %s", obj_cite_number, line ); } if (an_object.length > 0) { debug(poem) { // poem (curly) close writeln( obj_cite_number, an_object[an_object_key] ); } an_object["is"] = "verse"; auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_block.text = an_object["substantive"]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; } 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 = ocn_emit(type["ocn_status"]); type["verse_new"] = State.off; } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) { verse_line = TriState.off; type["verse_new"] = State.on; } if (type["verse_new"] == State.on) { verse_line=1; an_object[an_object_key] = processing["verse"]; debug(poem) { // poem verse writefln( "* %s curly\n%s", obj_cite_number, an_object[an_object_key] ); } processing.remove("verse"); an_object["is"] = "verse"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_block.text = an_object["substantive"]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; } } } else if (type["tic_poem"] == TriState.on) { if (auto m = matchFirst(line, rgx.block_tic_close)) { // tic_poem_close an_object[an_object_key]="verse"; // check that this is as you please debug(poem) { // poem (curly) close writefln( "* [poem tic] %s", line ); } if (processing.length > 0) { // needs looking at an_object[an_object_key] = processing["verse"]; } if (an_object.length > 0) { debug(poem) { // poem (tic) close writeln(__LINE__); writeln(obj_cite_number, line); } processing.remove("verse"); an_object["is"] = "verse"; auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_block.text = an_object["substantive"]; the_document_body_section ~= comp_obj_block; obj_cite_number_poem["end"] = to!string(obj_cite_number); object_reset(an_object); processing.remove("verse"); ++cntr; } type["blocks"] = TriState.closing; type["poem"] = TriState.closing; type["tic_poem"] = TriState.off; } else { processing["verse"] ~= line ~= "\n"; if (type["verse_new"] == State.on) { obj_cite_number = ocn_emit(type["ocn_status"]); type["verse_new"] = State.off; } else if (matchFirst(line, rgx.newline_eol_delimiter_only)) { type["verse_new"] = State.on; verse_line = TriState.off; } if (type["verse_new"] == State.on) { verse_line=1; an_object[an_object_key] = processing["verse"]; debug(poem) { // poem (tic) close writefln( "* %s tic\n%s", obj_cite_number, an_object[an_object_key] ); } processing.remove("verse"); an_object["is"] = "verse"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_block.text = an_object["substantive"]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; } } } } #+END_SRC ***** group block :group: #+name: abs_functions_block_group #+BEGIN_SRC d void _group_block_( char[] line, ref string[string] an_object, ref int[string] type ) { if (type["curly_group"] == State.on) { if (matchFirst(line, rgx.block_curly_group_close)) { debug(group) { // group (curly) close writeln(line); } type["blocks"] = TriState.closing; type["group"] = TriState.closing; type["curly_group"] = TriState.off; } else { debug(group) { // group writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build group array (or string) } } else if (type["tic_group"] == TriState.on) { if (matchFirst(line, rgx.block_tic_close)) { debug(group) { // group (tic) close writeln(line); } type["blocks"] = TriState.closing; type["group"] = TriState.closing; type["tic_group"] = TriState.off; } else { debug(group) { // group writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build group array (or string) } } } #+END_SRC ***** block block :block: #+name: abs_functions_block_block #+BEGIN_SRC d void _block_block_( char[] line, ref string[string] an_object, ref int[string] type ) { if (type["curly_block"] == TriState.on) { if (matchFirst(line, rgx.block_curly_block_close)) { debug(block) { // block (curly) close writeln(line); } type["blocks"] = TriState.closing; type["block"] = TriState.closing; type["curly_block"] = TriState.off; } else { debug(block) { // block writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build block array (or string) } } else if (type["tic_block"] == TriState.on) { if (matchFirst(line, rgx.block_tic_close)) { debug(block) { // block (tic) close writeln(line); } type["blocks"] = TriState.closing; type["block"] = TriState.closing; type["tic_block"] = TriState.off; } else { debug(block) { // block writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build block array (or string) } } } #+END_SRC ***** quote block :quote: #+name: abs_functions_block_quote #+BEGIN_SRC d void _quote_block_( char[] line, ref string[string] an_object, ref int[string] type ) { if (type["curly_quote"] == TriState.on) { if (matchFirst(line, rgx.block_curly_quote_close)) { debug(quote) { // quote (curly) close writeln(line); } type["blocks"] = TriState.closing; type["quote"] = TriState.closing; type["curly_quote"] = TriState.off; } else { debug(quote) { // quote writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build quote array (or string) } } else if (type["tic_quote"] == TriState.on) { if (matchFirst(line, rgx.block_tic_close)) { debug(quote) { // quote (tic) close writeln(line); } type["blocks"] = TriState.closing; type["quote"] = TriState.closing; type["tic_quote"] = TriState.off; } else { debug(quote) { // quote writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build quote array (or string) } } } #+END_SRC ***** table block :table: #+name: abs_functions_block_table #+BEGIN_SRC d void _table_block_( char[] line, ref string[string] an_object, ref int[string] type ) { if (type["curly_table"] == TriState.on) { if (matchFirst(line, rgx.block_curly_table_close)) { debug(table) { // table (curly) close writeln(line); } type["blocks"] = TriState.closing; type["table"] = TriState.closing; type["curly_table"] = TriState.off; } else { debug(table) { // table writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build table array (or string) } } else if (type["tic_table"] == TriState.on) { if (matchFirst(line, rgx.block_tic_close)) { debug(table) { // table (tic) close writeln(line); } type["blocks"] = TriState.closing; type["table"] = TriState.closing; type["tic_table"] = TriState.off; } else { debug(table) { // table writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build table array (or string) } } } #+END_SRC **** block end (close an open block): line empty, block flag :close: #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d void _block_flag_line_empty_( char[] line, ref string[string] an_object, ref ObjGenericComposite[] the_document_body_section, ref string[][string][string] bookindex_unordered_hashes, ref int obj_cite_number, ref ObjGenericComposite _comp_obj_heading, ref int cntr, ref int[string] type, string[string] obj_cite_number_poem, string[string][string] dochead_make_aa, ) { // 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 = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bkidx_hash(an_object["bookindex_nugget"], obj_cite_number); an_object["is"] = "code"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; comp_obj_code = comp_obj_code.init; comp_obj_code.use = "body"; comp_obj_code.is_of = "block"; comp_obj_code.is_a = "code"; comp_obj_code.ocn = obj_cite_number; comp_obj_code.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_code.text = an_object["substantive"]; the_document_body_section ~= comp_obj_code; object_reset(an_object); processing.remove("verse"); ++cntr; type["blocks"] = TriState.off; type["code"] = TriState.off; } else if (type["poem"] == TriState.closing) { an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bkidx_hash(an_object["bookindex_nugget"], obj_cite_number); an_object["is"] = "verse"; // check also auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); comp_obj_poem_ocn = comp_obj_poem_ocn.init; comp_obj_poem_ocn.use = "body"; comp_obj_poem_ocn.is_of = "block"; comp_obj_poem_ocn.is_a = "poem"; comp_obj_poem_ocn.ocn = obj_cite_number; comp_obj_poem_ocn.obj_cite_number = (obj_cite_number_poem["start"], obj_cite_number_poem["end"]); // not sure about this comp_obj_poem_ocn.text = ""; // an_object["substantive"]; the_document_body_section ~= comp_obj_poem_ocn; object_reset(an_object); processing.remove("verse"); type["blocks"] = TriState.off; type["poem"] = TriState.off; } else if (type["table"] == TriState.closing) { obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bkidx_hash(an_object["bookindex_nugget"], obj_cite_number); an_object["is"] = "table"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "table"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_block.text = an_object["substantive"]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; type["blocks"] = TriState.off; type["table"] = TriState.off; } else if (type["group"] == TriState.closing) { obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bkidx_hash(an_object["bookindex_nugget"], obj_cite_number); an_object["is"] = "group"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "group"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_block.text = an_object["substantive"]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; type["blocks"] = TriState.off; type["group"] = TriState.off; } else if (type["block"] == TriState.closing) { obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bkidx_hash(an_object["bookindex_nugget"], obj_cite_number); an_object["is"] = "block"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "block"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_block.text = an_object["substantive"]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; type["blocks"] = TriState.off; type["block"] = TriState.off; } else if (type["quote"] == TriState.closing) { obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bkidx_hash(an_object["bookindex_nugget"], obj_cite_number); an_object["is"] = "quote"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[0]; anchor_tags = substantive_object_and_anchor_tags_tuple[1]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "quote"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_block.text = an_object["substantive"]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; type["blocks"] = TriState.off; type["quote"] = TriState.off; } } #+END_SRC *** book index :bookindex: #+name: abs_functions_book_index #+BEGIN_SRC d auto _book_index_( char[] line, ref string book_idx_tmp, ref string[string] an_object, ref int[string] type, bool[string] opt_action_bool, ) { if (auto m = match(line, rgx.book_index)) { /+ match book_index +/ debug(bookindexmatch) { // book index writefln( "* [bookindex] %s\n", to!string(m.captures[1]), ); } an_object["bookindex_nugget"] = to!string(m.captures[1]); } else if (auto m = match(line, rgx.book_index_open)) { /+ match open book_index +/ type["book_index"] = State.on; if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) { book_idx_tmp = to!string(m.captures[1]); debug(bookindexmatch) { // book index writefln( "* [bookindex] %s\n", book_idx_tmp, ); } } } else if (type["book_index"] == State.on ) { /+ book_index flag set +/ if (auto m = match(line, rgx.book_index_close)) { type["book_index"] = State.off; if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) { an_object["bookindex_nugget"] = book_idx_tmp ~ to!string(m.captures[1]); debug(bookindexmatch) { // book index writefln( "* [bookindex] %s\n", book_idx_tmp, ); } } book_idx_tmp = ""; } else { if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) { book_idx_tmp ~= line; } } } } #+END_SRC *** heading or paragraph :heading:paragraph: **** heading found :heading: #+name: abs_functions_heading #+BEGIN_SRC d auto _heading_found_( char[] line, string dochead_make_identify_unmarked_headings, ref string[string] heading_match_str, ref Regex!(char)[string] heading_match_rgx, ref int[string] type ) { if ((dochead_make_identify_unmarked_headings.length > 2) && (type["make_headings"] == State.off)) { /+ headings found +/ debug(headingsfound) { writeln(dochead_make_identify_unmarked_headings); } char[][] make_headings_spl = split( cast(char[]) dochead_make_identify_unmarked_headings, 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; } } #+END_SRC **** TODO heading make set :heading: #+name: abs_functions_heading #+BEGIN_SRC d 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 (matchFirst(line, heading_match_rgx["h_B"])) { line = "B~ " ~ line; debug(headingsfound) { writeln(line); } } if (matchFirst(line, heading_match_rgx["h_C"])) { line = "C~ " ~ line; debug(headingsfound) { writeln(line); } } if (matchFirst(line, heading_match_rgx["h_D"])) { line = "D~ " ~ line; debug(headingsfound) { writeln(line); } } if (matchFirst(line, heading_match_rgx["h_1"])) { line = "1~ " ~ line; debug(headingsfound) { writeln(line); } } if (matchFirst(line, heading_match_rgx["h_2"])) { line = "2~ " ~ line; debug(headingsfound) { writeln(line); } } if (matchFirst(line, heading_match_rgx["h_3"])) { line = "3~ " ~ line; debug(headingsfound) { writeln(line); } } if (matchFirst(line, heading_match_rgx["h_4"])) { line = "4~ " ~ line; debug(headingsfound) { writeln(line); } } } } #+END_SRC **** heading match :heading: #+name: abs_functions_heading #+BEGIN_SRC d auto _heading_matched_( char[] line, ref int[string] line_occur, ref string[string] an_object, ref string an_object_key, ref int[string] lv, ref int[string] collapsed_lev, ref int[string] type, ref string[string][string] dochead_meta_aa ) { if (auto m = match(line, rgx.heading)) { /+ heading match +/ type["heading"] = State.on; if (match(line, rgx.heading_seg_and_above)) { type["biblio_section"] = State.off; type["glossary_section"] = State.off; type["blurb_section"] = State.off; } type["para"] = State.off; ++line_occur["heading"]; an_object[an_object_key] ~= line ~= "\n"; an_object["lev"] ~= m.captures[1]; assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels switch (an_object["lev"]) { case "A": an_object[an_object_key]=replaceFirst(an_object[an_object_key], rgx.variable_doc_title, (dochead_meta_aa["title"]["full"] ~ ",")); an_object[an_object_key]=replaceFirst(an_object[an_object_key], rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]); collapsed_lev["h0"] = 0; 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(strip(line)); } } } #+END_SRC **** para match :para: #+name: abs_functions_para #+BEGIN_SRC d auto _para_match_( char[] line, ref string[string] an_object, ref string an_object_key, ref int[string] indent, ref bool bullet, ref int[string] type, ref int[string] line_occur, ) { if (line_occur["para"] == State.off) { /+ para matches +/ type["para"] = State.on; an_object[an_object_key] ~= line; // body_nugget indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; if (auto m = matchFirst(line, rgx.para_indent)) { debug(paraindent) { // para indent writeln(line); } indent["hang_position"] = to!int(m.captures[1]); indent["base_position"] = 0; } else if (matchFirst(line, rgx.para_bullet)) { debug(parabullet) { // para bullet writeln(line); } bullet = true; } else if (auto m = matchFirst(line, rgx.para_indent_hang)) { debug(paraindenthang) { // para indent hang writeln(line); } indent=[ "hang_position" : to!int(m.captures[1]), "base_position" : to!int(m.captures[2]), ]; } else if (auto m = matchFirst(line, rgx.para_bullet_indent)) { debug(parabulletindent) { // para bullet indent writeln(line); } indent=[ "hang_position" : to!int(m.captures[1]), "base_position" : 0, ]; bullet = true; } ++line_occur["para"]; } } #+END_SRC *** function emitters :emitters: **** object :object: ***** ocn :ocn: #+name: ao_emitters_ocn #+BEGIN_SRC d struct OCNemitter { int obj_cite_number, obj_cite_number_; int ocn_emitter(int ocn_status_flag) in { assert(ocn_status_flag <= 2); } body { obj_cite_number=(ocn_status_flag == 0) ? ++obj_cite_number_ : 0; assert(obj_cite_number >= 0); return obj_cite_number; } invariant() { } } #+END_SRC ***** object inline markup munge :markup:inline: #+name: ao_emitters_obj_inline_markup_munge #+BEGIN_SRC d struct ObjInlineMarkupMunge { string[string] obj_txt; int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus; string asterisks_; string obj_txt_out, tail, note; auto rgx = Rgx(); auto mkup = InlineMarkup(); private auto initialize_note_numbers() { n_foot = 0; n_foot_reg = 0; n_foot_sp_asterisk = 0; n_foot_sp_plus = 0; } string url_links(string obj_txt_in) { /+ url matched +/ if (auto m = matchAll(obj_txt_in, rgx.inline_url)) { /+ link: naked url: http://url +/ if (match(obj_txt_in, rgx.inline_link_naked_url)) { obj_txt_in = replaceAll( obj_txt_in, rgx.inline_link_naked_url, ("$1" ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "$3") // ("$1{ $2 }$2$3") ); } /+ link with helper for endnote including the url: {~^ link which includes url as footnote }http://url maps to: { link which includes url as footnote }http://url~{ { http://url }http://url }~ +/ if (match(obj_txt_in, rgx.inline_link_endnote_url_helper)) { obj_txt_in = replaceAll( obj_txt_in, rgx.inline_link_endnote_url_helper_punctuated, (mkup.lnk_o ~ " $1 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3") ); obj_txt_in = replaceAll( obj_txt_in, rgx.inline_link_endnote_url_helper, (mkup.lnk_o ~ " $1 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ " }~") // ("{ $1 }$2~{ { $2 }$2 }~") ); } /+ link with regular markup: { linked text or image }http://url +/ if (match(obj_txt_in, rgx.inline_link_markup_regular)) { obj_txt_in = replaceAll( obj_txt_in, rgx.inline_link_markup_regular, ("$1" ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$3" ~ mkup.url_c ~ "$4") // ("$1{ $2 }$3$4") ); } } return obj_txt_in; } string footnotes_endnotes_markup_and_number_or_stars(string obj_txt_in) { /+ endnotes (regular) +/ 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)) { if (auto m = matchAll(obj_txt_in, rgx.inline_text_and_note_al_)) { foreach(n; m) { if (match(to!string(n.hit), rgx.inline_al_delimiter_open_symbol_star)) { ++n_foot_sp_asterisk; asterisks_ = "*"; n_foot=n_foot_sp_asterisk; obj_txt_out ~= (replaceFirst( to!string(n.hit), rgx.inline_al_delimiter_open_symbol_star, (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ") ) ~ "\n"); } else if (match(to!string(n.hit), rgx.inline_al_delimiter_open_regular)) { ++n_foot_reg; n_foot=n_foot_reg; obj_txt_out ~= (replaceFirst( to!string(n.hit), rgx.inline_al_delimiter_open_regular, (mkup.en_a_o ~ to!string(n_foot) ~ " ") ) ~ "\n"); } else { obj_txt_out ~= to!string(n.hit) ~ "\n"; } } } } else { obj_txt_out = obj_txt_in; } return obj_txt_out; } private auto object_notes_(string obj_txt_in) in { } body { obj_txt_out = ""; tail = ""; /+ special endnotes +/ 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) ); /+ url matched +/ if (auto m = matchAll(obj_txt_in, rgx.inline_url)) { obj_txt_in = url_links(obj_txt_in); } obj_txt_out = footnotes_endnotes_markup_and_number_or_stars(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"]=strip(obj_txt["munge"]); 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() { } /+ revisit +/ 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() { } } #+END_SRC ***** toc, tags, object inline markup :markup:inline: ****** open #+name: ao_emitters_obj_inline_markup #+BEGIN_SRC d struct ObjInlineMarkup { auto munge = ObjInlineMarkupMunge(); string[string] obj_txt; #+END_SRC ****** object inline markup and anchor tags :markup:inline: #+name: ao_emitters_obj_inline_markup_and_anchor_tags #+BEGIN_SRC d auto obj_inline_markup_and_anchor_tags( string[string] obj_, string obj_key_, string[string][string] dochead_make_aa ) in { } body { obj_txt["munge"]=obj_[obj_key_].dup; obj_txt["munge"]=(match(obj_["is"], ctRegex!(`verse|code`))) ? obj_txt["munge"] : strip(obj_txt["munge"]); static __gshared string[] anchor_tags_ = []; switch (obj_["is"]) { case "heading": static __gshared string anchor_tag = ""; // TODO WORK ON, you still need to ensure that level 1 anchor_tags are unique obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, dochead_make_aa); obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"]); if (auto m = match(obj_txt["munge"], rgx.heading_anchor_tag)) { anchor_tag = m.captures[1]; anchor_tags_ ~=anchor_tag; } else if (obj_["lev"] == "1") { writeln("heading anchor tag missing: ", obj_txt["munge"]); } 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; } auto t = tuple( obj_txt["munge"], anchor_tags_, ); anchor_tags_=[]; return t; } invariant() { } #+END_SRC ****** toc, table of contents build, gather headings :markup:inline: #+name: ao_emitters_obj_inline_markup_table_of_contents #+BEGIN_SRC d auto _clean_heading_toc_( char[] heading_toc_, ) { auto m = matchFirst(cast(char[]) heading_toc_, rgx.heading); heading_toc_ = replaceAll( m.post, rgx.inline_notes_curly_gen, ("") ); return heading_toc_; }; auto table_of_contents_gather_headings( string[string] obj_, string[string][string] dochead_make_aa, string segment_anchor_tag_that_object_belongs_to, string _anchor_tag, ref string[][string] lev4_subtoc, ObjGenericComposite[][string] the_table_of_contents_section, ) in { } body { ObjGenericComposite comp_obj_toc; mixin InternalMarkup; auto mkup = InlineMarkup(); char[] heading_toc_ = to!(char[])(obj_["body_nugget"].dup.strip); heading_toc_ = _clean_heading_toc_(heading_toc_); auto attrib=""; string toc_txt_, subtoc_txt_; int[string] indent; if (to!int(obj_["lev_markup_number"]) > 0) { indent=[ "hang_position" : to!int(obj_["lev_markup_number"]), "base_position" : to!int(obj_["lev_markup_number"]), ]; toc_txt_ = format( "{ %s }#%s", heading_toc_, _anchor_tag, ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc = comp_obj_toc.init; comp_obj_toc.use = "frontmatter"; comp_obj_toc.is_of = "para"; comp_obj_toc.is_a = "toc"; comp_obj_toc.ocn = 0; comp_obj_toc.obj_cite_number = ""; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.bullet = false; comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } else { indent=[ "hang_position" : 0, "base_position" : 0, ]; comp_obj_toc = comp_obj_toc.init; comp_obj_toc.use = "frontmatter"; comp_obj_toc.is_of = "para"; comp_obj_toc.is_a = "toc"; comp_obj_toc.ocn = 0; comp_obj_toc.obj_cite_number = ""; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.bullet = false; comp_obj_toc.text = "Table of Contents"; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } comp_obj_toc = comp_obj_toc.init; comp_obj_toc.use = "frontmatter"; comp_obj_toc.is_of = "para"; comp_obj_toc.is_a = "toc"; comp_obj_toc.ocn = 0; comp_obj_toc.obj_cite_number = ""; comp_obj_toc.bullet = false; switch (to!int(obj_["lev_markup_number"])) { case 0: indent=[ "hang_position" : 0, "base_position" : 0, ]; toc_txt_ = "{ Table of Contents }" ~ mkup.mark_internal_site_lnk ~ "../toc.fnSuffix"; toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; case 1: .. case 3: indent=[ "hang_position" : to!int(obj_["lev_markup_number"]), "base_position" : to!int(obj_["lev_markup_number"]), ]; toc_txt_ = format( "%s", heading_toc_, ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; case 4: toc_txt_ = format( "{ %s }%s../%s.fnSuffix", heading_toc_, mkup.mark_internal_site_lnk, segment_anchor_tag_that_object_belongs_to, ); lev4_subtoc[segment_anchor_tag_that_object_belongs_to] = []; toc_txt_= munge.url_links(toc_txt_); indent=[ "hang_position" : to!int(obj_["lev_markup_number"]), "base_position" : to!int(obj_["lev_markup_number"]), ]; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; case 5: .. case 7: toc_txt_ = format( "{ %s }%s../%s.fnSuffix#%s", heading_toc_, mkup.mark_internal_site_lnk, segment_anchor_tag_that_object_belongs_to, _anchor_tag, ); subtoc_txt_ = format( "{ %s }#%s", heading_toc_, _anchor_tag, ); lev4_subtoc[segment_anchor_tag_that_object_belongs_to] ~= obj_["lev_markup_number"] ~ "~ " ~ to!string(subtoc_txt_).strip; toc_txt_= munge.url_links(toc_txt_); indent=[ "hang_position" : to!int(obj_["lev_markup_number"]), "base_position" : to!int(obj_["lev_markup_number"]), ]; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = to!string(toc_txt_).strip; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; default: break; } return the_table_of_contents_section; } invariant() { } #+END_SRC ****** private: #+name: ao_emitters_obj_inline_markup_private #+BEGIN_SRC d private: #+END_SRC ******* make heading number and segment anchor tags if instructed :markup:inline:segment:anchor:tags: #+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags #+BEGIN_SRC d static string _configured_auto_heading_numbering_and_segment_anchor_tags( string munge_, string[string] obj_, string[string][string] dochead_make_aa ) { if (dochead_make_aa["make"]["num_top"].length > 0) { if (!(match(munge_, rgx.heading_anchor_tag))) { static __gshared int heading_num_top_level=9; static __gshared int heading_num_depth=2; static __gshared int heading_num_0 = 0; static __gshared int heading_num_1 = 0; static __gshared int heading_num_2 = 0; static __gshared int heading_num_3 = 0; static __gshared string heading_number_auto_composite = ""; if (heading_num_top_level==9) { if (dochead_make_aa["make"]["num_depth"].length > 0) { heading_num_depth = to!uint(dochead_make_aa["make"]["num_depth"]); } switch (dochead_make_aa["make"]["num_top"]) { case "A": break; case "B": heading_num_top_level=1; break; case "C": heading_num_top_level=2; break; case "D": heading_num_top_level=3; break; case "1": heading_num_top_level=4; break; case "2": heading_num_top_level=5; break; case "3": heading_num_top_level=6; break; case "4": heading_num_top_level=7; break; default: break; } } /+ num_depth minimum 0 (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement +/ if (heading_num_top_level > to!uint(obj_["lev_markup_number"])) { heading_num_0 = 0; heading_num_1 = 0; heading_num_2 = 0; heading_num_3 = 0; } else if (heading_num_top_level == to!uint(obj_["lev_markup_number"])) { heading_num_0 ++; heading_num_1 = 0; heading_num_2 = 0; heading_num_3 = 0; } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 1)) { heading_num_1 ++; heading_num_2 = 0; heading_num_3 = 0; } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 2)) { heading_num_2 ++; heading_num_3 = 0; } else if (heading_num_top_level == (to!uint(obj_["lev_markup_number"]) - 3)) { heading_num_3 ++; } if (heading_num_3 > 0) { heading_number_auto_composite = (heading_num_depth == 3) ? ( to!string(heading_num_0) ~ "." ~ to!string(heading_num_1) ~ "." ~ to!string(heading_num_2) ~ "." ~ to!string(heading_num_3) ) : ""; } else if (heading_num_2 > 0) { heading_number_auto_composite = ((heading_num_depth >= 2) && (heading_num_depth <= 3)) ? ( to!string(heading_num_0) ~ "." ~ to!string(heading_num_1) ~ "." ~ to!string(heading_num_2) ) : ""; } else if (heading_num_1 > 0) { heading_number_auto_composite = ((heading_num_depth >= 1) && (heading_num_depth <= 3)) ? ( to!string(heading_num_0) ~ "." ~ to!string(heading_num_1) ) : ""; } else if (heading_num_0 > 0) { heading_number_auto_composite = ((heading_num_depth >= 0) && (heading_num_depth <= 3)) ? (to!string(heading_num_0)) : ""; } else { heading_number_auto_composite = ""; } debug(heading_number_auto) { writeln(heading_number_auto_composite); } if (!empty(heading_number_auto_composite)) { munge_=replaceFirst(munge_, rgx.heading, "$1~$2 " ~ heading_number_auto_composite ~ ". "); munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag, "$1~" ~ heading_number_auto_composite ~ " "); } } } return munge_; } #+END_SRC ******** unittests #+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags #+BEGIN_SRC d #+END_SRC ******* make segment anchor tags if not provided :markup:inline:segment:anchor:tags: #+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags #+BEGIN_SRC d static string _make_segment_anchor_tags_if_none_provided(string munge_, string lev_) { if (!(match(munge_, rgx.heading_anchor_tag))) { // if (anchor_tags_.length == 0) { if (match(munge_, rgx.heading_identify_anchor_tag)) { if (auto m = match(munge_, rgx.heading_extract_named_anchor_tag)) { munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag, "$1~" ~ toLower(m.captures[1]) ~ "_" ~ m.captures[2] ~ " "); } else if (auto m = match(munge_, rgx.heading_extract_unnamed_anchor_tag)) { munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag, "$1~" ~ "s" ~ m.captures[1] ~ " "); } } else if (lev_ == "1") { // (if not successful) manufacture a unique anchor tag for lev=="1" static __gshared int heading_num_lev1 = 0; heading_num_lev1 ++; munge_=replaceFirst(munge_, rgx.heading_marker_missing_tag, "$1~" ~ "x" ~ to!string(heading_num_lev1) ~ " "); } } return munge_; } #+END_SRC ******** unittests #+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags #+BEGIN_SRC d unittest { string txt_lev="1"; string txt_in, txt_out; txt_in = "1~copyright Copyright"; txt_out ="1~copyright Copyright"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in = "1~ 6. Writing Copyright Licenses"; txt_out ="1~s6 6. Writing Copyright Licenses"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ 1. Reinforcing trends"; txt_out= "1~s1 1. Reinforcing trends"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ 11 SCIENCE AS A COMMONS"; txt_out= "1~s11 11 SCIENCE AS A COMMONS"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ Chapter 1"; txt_out="1~chapter_1 Chapter 1"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ Chapter 1."; txt_out="1~chapter_1 Chapter 1."; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ Chapter 1: Done"; txt_out="1~chapter_1 Chapter 1: Done"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment"; txt_out= "1~chapter_11 Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ CHAPTER I."; txt_out="1~x1 CHAPTER I."; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ CHAPTER II."; txt_out="1~x2 CHAPTER II."; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); } #+END_SRC ****** close #+name: ao_emitters_obj_inline_markup_close #+BEGIN_SRC d } #+END_SRC ***** object attrib :attributes: ****** attributes structure open, public #+name: ao_emitters_obj_attributes #+BEGIN_SRC d struct ObjAttributes { string[string] _obj_attrib; #+END_SRC ****** attributes structure open, public #+name: ao_emitters_obj_attributes_public #+BEGIN_SRC d string obj_attributes( string obj_is_, string obj_raw, ObjGenericComposite _comp_obj_heading, ) in { } body { scope(exit) { destroy(obj_is_); destroy(obj_raw); destroy(_comp_obj_heading); } _obj_attrib["json"] ="{"; switch (obj_is_) { case "heading": _obj_attrib["json"] ~= _heading(obj_raw); break; case "para": _obj_attrib["json"] ~= _para_and_blocks(obj_raw) ~ _para(obj_raw); break; case "code": _obj_attrib["json"] ~= _code(obj_raw); break; case "group": _obj_attrib["json"] ~= _para_and_blocks(obj_raw) ~ _group(obj_raw); break; case "block": _obj_attrib["json"] ~= _para_and_blocks(obj_raw) ~ _block(obj_raw); break; case "verse": _obj_attrib["json"] ~= _verse(obj_raw); break; case "quote": _obj_attrib["json"] ~= _quote(obj_raw); break; case "table": _obj_attrib["json"] ~= _table(obj_raw); break; case "comment": _obj_attrib["json"] ~= _comment(obj_raw); break; default: _obj_attrib["json"] ~= _para(obj_raw); break; } _obj_attrib["json"] ~=" }"; _obj_attrib["json"]=_set_additional_values_parse_as_json(_obj_attrib["json"], obj_is_, _comp_obj_heading); // check debug(structattrib) { if (oa_j["is"].str() == "heading") { writeln(_obj_attrib["json"]); writeln( "is: ", oa_j["is"].str(), "; obj_cite_number: ", oa_j["obj_cite_number"].integer() ); } } return _obj_attrib["json"]; } invariant() { } #+END_SRC ****** private #+name: ao_emitters_obj_attributes_private #+BEGIN_SRC d private: string _obj_attributes; #+END_SRC ******* attrubutes ******** para and block #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _para_and_blocks(string obj_txt_in) in { } body { auto rgx = Rgx(); if (matchFirst(obj_txt_in, rgx.para_bullet)) { _obj_attributes =" \"bullet\": \"true\"," ~ " \"indent_hang\": 0," ~ " \"indent_base\": 0,"; } else if (auto m = matchFirst(obj_txt_in, rgx.para_bullet_indent)) { _obj_attributes =" \"bullet\": \"true\"," ~ " \"indent_hang\": " ~ to!string(m.captures[1]) ~ "," ~ " \"indent_base\": " ~ to!string(m.captures[1]) ~ ","; } else if (auto m = matchFirst(obj_txt_in, rgx.para_indent_hang)) { _obj_attributes =" \"bullet\": \"false\"," ~ " \"indent_hang\": " ~ to!string(m.captures[1]) ~ "," ~ " \"indent_base\": " ~ to!string(m.captures[2]) ~ ","; } else if (auto m = matchFirst(obj_txt_in, rgx.para_indent)) { _obj_attributes =" \"bullet\": \"false\"," ~ " \"indent_hang\": " ~ to!string(m.captures[1]) ~ "," ~ " \"indent_base\": " ~ to!string(m.captures[1]) ~ ","; } else { _obj_attributes =" \"bullet\": \"false\"," ~ " \"indent_hang\": 0," ~ " \"indent_base\": 0,"; } return _obj_attributes; } #+END_SRC ******** para #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _para(string obj_txt_in) in { } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"para\"," ~ " \"is\": \"para\""; return _obj_attributes; } invariant() { } #+END_SRC ******** heading #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _heading(string obj_txt_in) in { } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"para\"," ~ " \"is\": \"heading\""; return _obj_attributes; } invariant() { } #+END_SRC ******** code #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _code(string obj_txt_in) in { } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"code\""; return _obj_attributes; } invariant() { } #+END_SRC ******** group #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _group(string obj_txt_in) in { } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"group\""; return _obj_attributes; } invariant() { } #+END_SRC ******** block #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _block(string obj_txt_in) in { } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"block\""; return _obj_attributes; } invariant() { } #+END_SRC ******** verse #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _verse(string obj_txt_in) in { } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"verse\""; return _obj_attributes; } invariant() { } #+END_SRC ******** quote #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _quote(string obj_txt_in) in { } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"quote\""; return _obj_attributes; } invariant() { } #+END_SRC ******** table #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _table(string obj_txt_in) in { } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"table\""; return _obj_attributes; } invariant() { } #+END_SRC ******** comment #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _comment(string obj_txt_in) in { } body { _obj_attributes = " \"use\": \"comment\"," ~ " \"of\": \"comment\"," ~ " \"is\": \"comment\""; return _obj_attributes; } invariant() { } #+END_SRC ******* set additional attribute values, parse as json #+name: ao_emitters_obj_attributes_private_json #+BEGIN_SRC d string _set_additional_values_parse_as_json( string _obj_attrib, string obj_is_, ObjGenericComposite _comp_obj_heading, ) { // JSONValue oa_j = parseJSON(_obj_attrib); assert( (oa_j.type == JSON_TYPE.OBJECT) ); if (obj_is_ == "heading") { oa_j.object["obj_cite_number"] = _comp_obj_heading.ocn; oa_j.object["lev_markup_number"] = _comp_obj_heading.heading_lev_markup; oa_j.object["lev_collapsed_number"] = _comp_obj_heading.heading_lev_collapsed; oa_j.object["heading_ptr"] = _comp_obj_heading.ptr_heading; oa_j.object["doc_object_ptr"] = _comp_obj_heading.ptr_doc_object; } oa_j.object["parent_obj_cite_number"] = _comp_obj_heading.parent_ocn; oa_j.object["parent_lev_markup_number"] = _comp_obj_heading.parent_lev_markup; _obj_attrib = oa_j.toString(); return _obj_attrib; } #+END_SRC ****** close #+name: ao_emitters_obj_attributes_private_close #+BEGIN_SRC d } #+END_SRC **** book index :book:index: ***** book index nugget hash :hash:nugget: #+name: ao_emitters_book_index_nugget #+BEGIN_SRC d struct BookIndexNuggetHash { string main_term, sub_term, sub_term_bits; int obj_cite_number_offset, obj_cite_number_endpoint; string[] obj_cite_numbers; string[][string][string] bi; string[][string][string] hash_nugget; string[] bi_main_terms_split_arr; string[][string][string] bookindex_nugget_hash( string bookindex_section, int obj_cite_number ) in { debug(bookindexraw) { if (!bookindex_section.empty) { writeln( "* [bookindex] ", "[", 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() { } } #+END_SRC ***** book index (sort &) report indented :report:indented: #+name: ao_emitters_book_index_report_indented #+BEGIN_SRC d 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] )); } ++skn; } ++mkn; } } } #+END_SRC ***** book index (sort &) report section :report:section: ****** book index struct open #+name: ao_emitters_book_index_report_section #+BEGIN_SRC d struct BookIndexReportSection { int mkn, skn; auto rgx = Rgx(); auto munge = ObjInlineMarkupMunge(); #+END_SRC ****** bookindex write section #+name: ao_emitters_book_index_report_section #+BEGIN_SRC d 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; } } #+END_SRC ****** book index (sort &) build section :report:section: #+name: ao_emitters_book_index_report_section #+BEGIN_SRC d auto bookindex_build_abstraction_section( string[][string][string] bookindex_unordered_hashes, int obj_cite_number, string segment_anchor_tag_that_object_belongs_to, bool[string] opt_action_bool, ) { mixin SiSUnode; mixin InternalMarkup; auto mkup = InlineMarkup(); string type_is; string lev; int heading_lev_markup, heading_lev_collapsed; string attrib; int[string] indent; auto mainkeys = bookindex_unordered_hashes.byKey.array.sort().release; ObjGenericComposite[][string] bookindex_section; ObjGenericComposite comp_obj_heading_, comp_obj_para; auto node_para_int_ = node_metadata_para_int; auto node_para_str_ = node_metadata_para_str; if ((mainkeys.length > 0) && (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"])) { string bi_tmp_seg, bi_tmp_scroll; string[] bi_tmp_tags; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Book Index"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; bookindex_section["scroll"] ~= comp_obj_heading_; bookindex_section["seg"] ~= comp_obj_heading_; ++obj_cite_number; ++mkn; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Index"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "bookindex"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.anchor_tags = ["bookindex"]; bookindex_section["scroll"] ~= comp_obj_heading_; bookindex_section["seg"] ~= comp_obj_heading_; ++obj_cite_number; ++mkn; import std.array : appender; auto buffer = appender!(char[])(); string[dchar] transTable = [' ' : "_"]; foreach (mainkey; mainkeys) { bi_tmp_tags = [""]; bi_tmp_scroll = "!{" ~ mainkey ~ "}! "; buffer.clear(); bi_tmp_tags ~= translate(mainkey, transTable); bi_tmp_seg = "!{" ~ mainkey ~ "}! "; foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { auto go = replaceAll(ref_, rgx.book_index_go, "$1"); bi_tmp_scroll ~= munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", "); bi_tmp_seg ~= (segment_anchor_tag_that_object_belongs_to.empty) ? munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ") : munge.url_links(" {" ~ ref_ ~ "}" ~ mkup.mark_internal_site_lnk ~ "../" ~ segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#" ~ go ~ ", "); } bi_tmp_scroll ~= " \\\\\n "; bi_tmp_seg ~= " \\\\\n "; bookindex_unordered_hashes[mainkey].remove("_a"); auto subkeys = bookindex_unordered_hashes[mainkey].byKey.array.sort().release; foreach (subkey; subkeys) { bi_tmp_scroll ~= subkey ~ ", "; buffer.clear(); bi_tmp_tags ~= translate(subkey, transTable); bi_tmp_seg ~= subkey ~ ", "; foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { auto go = replaceAll(ref_, rgx.book_index_go, "$1"); bi_tmp_scroll ~= munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", "); bi_tmp_seg ~= (segment_anchor_tag_that_object_belongs_to.empty) ? munge.url_links(" {" ~ ref_ ~ "}#" ~ go ~ ", ") : munge.url_links(" {" ~ ref_ ~ "}" ~ mkup.mark_internal_site_lnk ~ "../" ~ segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#" ~ go ~ ", "); } bi_tmp_scroll ~= " \\\\\n "; bi_tmp_seg ~= " \\\\\n "; ++skn; } bi_tmp_scroll = replaceFirst(bi_tmp_scroll, rgx.trailing_linebreak, ""); bi_tmp_seg = replaceFirst(bi_tmp_seg, rgx.trailing_linebreak, ""); comp_obj_para = comp_obj_para.init; comp_obj_para.use = "backmatter"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "bookindex"; comp_obj_para.text = to!string(bi_tmp_scroll).strip; comp_obj_para.ocn = obj_cite_number; comp_obj_para.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_para.anchor_tags = bi_tmp_tags; comp_obj_para.indent_hang = 0; comp_obj_para.indent_base = 1; comp_obj_para.bullet = false; bookindex_section["scroll"] ~= comp_obj_para; comp_obj_para.text = to!string(bi_tmp_seg).strip; bookindex_section["seg"] ~= comp_obj_para; ++obj_cite_number; ++mkn; } } else { // no book index, (figure out what to do here) comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.text = "(skip) there is no Book Index"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; bookindex_section["scroll"] ~= comp_obj_heading_; bookindex_section["seg"] ~= comp_obj_heading_; } auto t = tuple(bookindex_section, obj_cite_number); return t; } #+END_SRC ****** book index struct close #+name: ao_emitters_book_index_report_section #+BEGIN_SRC d } #+END_SRC **** (end)notes section :endnotes:section: #+name: ao_emitters_endnotes #+BEGIN_SRC d struct NotesSection { string[string] object_notes; int previous_count; int mkn; auto rgx = Rgx(); #+END_SRC ***** gather notes for endnote section struct open #+name: ao_emitters_endnotes #+BEGIN_SRC d private auto gather_notes_for_endnote_section( ObjGenericComposite[] contents_am, string segment_anchor_tag_that_object_belongs_to, int cntr, ) in { // endnotes/ footnotes for // doc objects other than paragraphs & headings // various forms of grouped text assert((contents_am[cntr].is_a == "para") || (contents_am[cntr].is_a == "heading") || (contents_am[cntr].is_a == "group")); assert(cntr >= previous_count); previous_count=cntr; assert( match(contents_am[cntr].text, rgx.inline_notes_delimiter_al_regular_number_note) ); } body { mixin InternalMarkup; auto mkup = InlineMarkup(); auto munge = ObjInlineMarkupMunge(); foreach( m; matchAll( contents_am[cntr].text, rgx.inline_notes_delimiter_al_regular_number_note ) ) { debug(endnotes_build) { writeln( "{^{", m.captures[1], ".}^}" ~ mkup.mark_internal_site_lnk ~ "../", segment_anchor_tag_that_object_belongs_to, ".fnSuffix#noteref_\n ", m.captures[1], " ", m.captures[2]); // sometimes need segment name (segmented html & epub) } // TODO NEXT you need anchor for segments at this point -> object_notes["anchor"] ~= "#note_" ~ m.captures[1] ~ "』"; object_notes["notes"] ~= (segment_anchor_tag_that_object_belongs_to.empty) ? (munge.url_links( "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~ m.captures[1]) ~ " " ~ m.captures[2] ~ "』" ) : (munge.url_links( "{^{" ~ m.captures[1] ~ ".}^}" ~ mkup.mark_internal_site_lnk ~ "../" ~ segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#noteref_" ~ m.captures[1]) ~ " " ~ m.captures[2] ~ "』" ); } return object_notes; } #+END_SRC ***** gathered notes #+name: ao_emitters_endnotes #+BEGIN_SRC d private auto gathered_notes() in { } body { string[][string] endnotes_; if (object_notes.length > 1) { endnotes_["notes"] = (split(object_notes["notes"], rgx.break_string))[0..$-1]; endnotes_["anchor"] = (split(object_notes["anchor"], rgx.break_string))[0..$-1]; } else { endnotes_["notes"] = []; endnotes_["anchor"] = []; } return endnotes_; } #+END_SRC ***** endnote objects #+name: ao_emitters_endnotes #+BEGIN_SRC d private auto endnote_objects( int obj_cite_number, bool[string] opt_action_bool, ) in { } body { mixin SiSUnode; ObjGenericComposite[] the_endnotes_section; auto endnotes_ = gathered_notes(); string type_is; string lev, lev_markup_number, lev_collapsed_number; string attrib; int[string] indent; ObjGenericComposite comp_obj_heading_; if ((endnotes_["notes"].length > 0) && (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"])) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Endnotes"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_endnotes_section ~= comp_obj_heading_; ++obj_cite_number; ++mkn; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Endnotes"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "endnotes"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.anchor_tags = ["endnotes"]; the_endnotes_section ~= comp_obj_heading_; ++obj_cite_number; ++mkn; } else { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "(skip) there are no Endnotes"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_endnotes_section ~= comp_obj_heading_; } if (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"]) { ObjGenericComposite comp_obj_endnote_; comp_obj_endnote_ = comp_obj_endnote_.init; comp_obj_endnote_.use = "backmatter"; comp_obj_endnote_.is_of = "para"; comp_obj_endnote_.is_a = "endnote"; comp_obj_endnote_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_endnote_.indent_hang = 0; comp_obj_endnote_.indent_base = 0; comp_obj_endnote_.bullet = false; foreach (i, endnote; endnotes_["notes"]) { auto m = (matchFirst(endnote, rgx.note_ref)); string notenumber = to!string(m.captures[1]); string anchor_tag = "note_" ~ notenumber; comp_obj_endnote_.anchor_tags ~= [ endnotes_["anchor"][i] ]; // fix comp_obj_endnote_.text = endnote.strip; the_endnotes_section ~= comp_obj_endnote_; } } auto t = tuple(the_endnotes_section, obj_cite_number); return t; } #+END_SRC ***** gather notes for endnote section struct close #+name: ao_emitters_endnotes #+BEGIN_SRC d } #+END_SRC **** bibliography :bibliography: ***** biblio struct open #+name: ao_emitters_bibliography #+BEGIN_SRC d struct Bibliography { #+END_SRC ***** biblio #+name: ao_emitters_bibliography #+BEGIN_SRC d 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__); debug(biblio0) { writeln("---"); writeln("unsorted incomplete: ", biblio_unsorted_incomplete.length); writeln("json: ", bib_arr_json.length); writeln("unsorted: ", biblio_unsorted.length); writeln("sorted: ", biblio_sorted__.length); int cntr; int[7] x; while (cntr < x.length) { writeln(cntr, ": ", biblio_sorted__[cntr]["fulltitle"]); cntr++; } } return biblio_sorted__; } #+END_SRC ***** biblio unsorted complete #+name: ao_emitters_bibliography #+BEGIN_SRC d 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; } #+END_SRC ***** biblio sort #+name: ao_emitters_bibliography #+BEGIN_SRC d 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"]); } } } return biblio_sorted_; } #+END_SRC ***** biblio debug #+name: ao_emitters_bibliography #+BEGIN_SRC d void biblio_debug(JSONValue[] biblio_sorted) { debug(biblio0) { foreach (j; biblio_sorted) { if (!empty(j["fulltitle"].str)) { writeln(j["sortby_deemed_author_year_title"]); } } } } #+END_SRC ***** biblio struct close #+name: ao_emitters_bibliography #+BEGIN_SRC d } #+END_SRC **** node structure metadata :structure:metadata:node: ***** metadata node struct open #+name: ao_emitters_metadata #+BEGIN_SRC d struct NodeStructureMetadata { int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7; int obj_cite_number; int[string] p_; // p_ parent_ #+END_SRC ***** TODO node metadata emitter #+name: ao_emitters_metadata #+BEGIN_SRC d ObjGenericComposite node_location_emitter( string lev_markup_number, string segment_anchor_tag, int obj_cite_number_, int cntr_, int ptr_, string is_ ) in { auto rgx = Rgx(); assert(is_ != "heading"); assert(to!int(obj_cite_number_) >= 0); } body { 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; } ObjGenericComposite comp_obj_location; comp_obj_location = comp_obj_location.init; comp_obj_location.is_a = is_; comp_obj_location.ocn = obj_cite_number_; comp_obj_location.segment_anchor_tag = to!string(segment_anchor_tag); comp_obj_location.parent_ocn = p_["obj_cite_number"]; comp_obj_location.parent_lev_markup = p_["lev_markup_number"]; debug(node) { if (match(lev_markup_number, rgx.levels_numbered_headings)) { writeln("x ", to!string(_node)); } else { writeln("- ", to!string(_node)); } } assert(comp_obj_location.parent_lev_markup >= 4); assert(comp_obj_location.parent_lev_markup <= 7); assert(comp_obj_location.parent_ocn >= 0); return comp_obj_location; } invariant() { } #+END_SRC ***** TODO node metadata emitter heading, (including most segnames & their pointers) #+name: ao_emitters_metadata #+BEGIN_SRC d ObjGenericComposite node_emitter_heading( string _text, string lev, string lev_markup_number, string lev_collapsed_number, string segment_anchor_tag, int obj_cite_number_, int cntr_, int ptr_, string[] lv_ancestors, string is_, int html_segnames_ptr, ) 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_)) ); if (match(lev_markup_number, rgx.levels_numbered)) { if (to!int(lev_markup_number) == 0) { assert(to!int(obj_cite_number_) == 1); } } } body { auto rgx = Rgx(); int obj_cite_number = to!int(obj_cite_number_); switch (to!int(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: break; } ObjGenericComposite _comp_obj_heading_; _comp_obj_heading_ = _comp_obj_heading_.init; _comp_obj_heading_.use = "body"; _comp_obj_heading_.is_of = "para"; _comp_obj_heading_.is_a = "heading"; // _node_heading_.is_a = is_; // check whether needed, constant??? _comp_obj_heading_.text = to!string(_text).strip; _comp_obj_heading_.ocn = obj_cite_number_; _comp_obj_heading_.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); _comp_obj_heading_.segment_anchor_tag = to!string(segment_anchor_tag); _comp_obj_heading_.marked_up_level = lev; _comp_obj_heading_.heading_lev_markup = (!(lev_markup_number.empty) ? to!int(lev_markup_number) : 0); _comp_obj_heading_.heading_lev_collapsed = (!(lev_collapsed_number.empty) ? to!int(lev_collapsed_number) : 0); _comp_obj_heading_.parent_ocn = p_["obj_cite_number"]; _comp_obj_heading_.parent_lev_markup = p_["lev_markup_number"]; _comp_obj_heading_.heading_ancestors_text = lv_ancestors; _comp_obj_heading_.ptr_doc_object = cntr_; _comp_obj_heading_.ptr_html_segnames = ((lev_markup_number == "4") ? html_segnames_ptr : 0); _comp_obj_heading_.ptr_heading = ptr_; debug(node) { if (match(lev_markup_number, rgx.levels_numbered_headings)) { writeln("* ", to!string(_node)); } } debug(nodeheading) { if (match(lev_markup_number, rgx.levels_numbered_headings)) { writeln("* ", to!string(_node)); } } assert(_comp_obj_heading_.parent_lev_markup <= 7); assert(_comp_obj_heading_.parent_ocn >= 0); if (match(lev_markup_number, rgx.levels_numbered_headings)) { assert(_comp_obj_heading_.heading_lev_markup <= 7); assert(_comp_obj_heading_.ocn >= 0); if (_comp_obj_heading_.parent_lev_markup > 0) { assert(_comp_obj_heading_.parent_lev_markup < _comp_obj_heading_.heading_lev_markup); if (_comp_obj_heading_.ocn != 0) { assert(_comp_obj_heading_.parent_ocn < _comp_obj_heading_.ocn); } } if (_comp_obj_heading_.heading_lev_markup == 0) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_B) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_C) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_B); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_D) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_C); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_1) { assert(_comp_obj_heading_.parent_lev_markup <= DocStructMarkupHeading.h_sect_D); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_2) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_1); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_3) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_2); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_4) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_3); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_5) { } } return _comp_obj_heading_; } invariant() { } #+END_SRC ***** metadata node struct close #+name: ao_emitters_metadata #+BEGIN_SRC d } #+END_SRC *** function assertions :assertions: **** mixin template: assertions on markup document structure :doc_structure: #+name: abs_functions_assertions #+BEGIN_SRC d 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; } } #+END_SRC **** mixin template: assertions on blocks :blocks: #+name: abs_functions_assertions #+BEGIN_SRC d 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"); } #+END_SRC * 2. Object Setter :abstract:object: set abstracted objects for downstream processing ** initialize structs :struct: *** heading attribute #+name: ao_structs_init #+BEGIN_SRC d struct HeadingAttrib { string lev = "9"; int heading_lev_markup = 9; int heading_lev_collapsed = 9; int[] closes_lev_collapsed = []; int[] closes_lev_markup = []; int array_ptr = 0; int heading_array_ptr_segments = 0; } #+END_SRC *** TODO composite object #+name: ao_structs_init #+BEGIN_SRC d struct ObjGenericComposite { // size_t id; string use = ""; string is_of = ""; string is_a = ""; string text = ""; string obj_cite_number = ""; string[] anchor_tags = []; string marked_up_level = "9"; int[] closes_lev_collapsed = []; int[] closes_lev_markup = []; int indent_base = 0; int indent_hang = 0; bool bullet = false; string syntax = ""; int ocn = 0; string segment_anchor_tag = ""; string segname_prev = ""; string segname_next = ""; int parent_lev_markup = 0; int parent_ocn = 0; int[] ancestors = []; int heading_lev_markup = 9; int heading_lev_collapsed = 9; int[] heading_closes_lev_collapsed = []; int[] heading_closes_lev_markup = []; string[] heading_ancestors_text = [ "", "", "", "", "", "", "", "", ]; int heading_array_ptr = 0; int ptr_doc_object = 0; int ptr_html_segnames = 0; int ptr_heading = 0; int array_ptr = 0; int heading_array_ptr_segments = 0; string[] lev4_subtoc = []; string[string][string] node; int[] dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0,]; } #+END_SRC *** The Objects: generic composite object array #+name: ao_structs_init #+BEGIN_SRC d struct TheObjects { ObjGenericComposite[] oca; } #+END_SRC