#+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/]] * 1. Document Abstraction :abstract:process: Process markup document, create document abstraction. ** 0. 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() { /+ ↓ abstraction imports +/ <> /+ ↓ abstraction mixins +/ <> /+ ↓ abstraction struct init +/ <> /+ ↓ abstract marked up document +/ auto SiSUdocAbstraction(Src,Make,Meta,Opt)( Src markup_sourcefile_content, Make dochead_make_aa, Meta dochead_meta_aa, Opt opt_action_bool, ) { auto rgx = Rgx(); debug(asserts){ static assert(is(typeof(markup_sourcefile_content) == char[][])); static assert(is(typeof(dochead_make_aa) == string[string][string])); static assert(is(typeof(dochead_meta_aa) == string[string][string])); static assert(is(typeof(opt_action_bool) == bool[string])); } /+ ↓ 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: template SiSUdocAbstraction +/ #+END_SRC ** 1. _pre loop processing_ :pre: *** imports :imports: [[./ao_defaults.org][ao_defaults]] #+name: abs_imports #+BEGIN_SRC d import ao_object_setter, ao_defaults, ao_rgx, output_hub; private import std.algorithm, std.array, std.container, std.exception, std.file, std.getopt, std.json, std.path, std.process, std.range, std.regex, std.stdio, std.string, std.traits, std.typecons, std.uni, std.utf, std.conv : to; #+END_SRC *** mixins :mixins: #+name: abs_mixins #+BEGIN_SRC d mixin ObjectSetter; mixin InternalMarkup; mixin SiSUrgxInit; #+END_SRC *** initialize :initialize: **** initialize general #+name: abs_init_struct #+BEGIN_SRC d /+ initialize +/ ObjGenericComposite[][string] the_table_of_contents_section; ObjGenericComposite[] the_document_head_section, the_document_body_section, the_bibliography_section, the_glossary_section, the_blurb_section; ObjGenericComposite[] the_dom_tail_section; string[string] an_object, processing; string an_object_key; string[] anchor_tags; string anchor_tag_; string segment_anchor_tag_that_object_belongs_to; string segment_anchor_tag_that_object_belongs_to_uri; auto note_section = NotesSection(); /+ enum +/ enum State { off, on } enum TriState { off, on, closing } enum DocStructMarkupHeading { h_sect_A, h_sect_B, h_sect_C, h_sect_D, h_text_1, h_text_2, h_text_3, h_text_4, h_text_5, // extra level, drop content_non_header } // header section A-D; header text 1-4 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, } #+END_SRC **** initialize heading ancestors #+name: abs_init_struct #+BEGIN_SRC d 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; } } #+END_SRC **** initialize dom markup tags #+name: abs_init_struct #+BEGIN_SRC d 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; } #+END_SRC **** initialize dom collapsed tags #+name: abs_init_struct #+BEGIN_SRC d 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; } #+END_SRC **** initialize ocn emit #+name: abs_init_struct #+BEGIN_SRC d 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 mixin SiSUrgxInitFlags; mixin SiSUnode; auto node_para_int_ = node_metadata_para_int; auto node_para_str_ = node_metadata_para_str; ObjGenericComposite comp_obj_heading_, comp_obj_para, comp_obj_toc; line_occur = [ "heading" : 0, "para" : 0, "glossary" : 0, "blurb" : 0, ]; auto type = flags_type_init; string[string] obj_cite_number_poem = [ "start" : "", "end" : "" ]; string[] lv_ancestors = [ "", "", "", "", "", "", "", "", ]; 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 { _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); } 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) { 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 = (to!int(an_object["lev_markup_number"]) == 0) ? (ocn_emit(3)) : (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); 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 *** 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: /+ Backmatter: - endnotes - glossary - bibliography / references - book index - blurb +/ *** 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; 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) { 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_; } 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 & unique image list 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 string[] _images; auto extract_images(S)(S content_block) { string[] images_; if (auto m = matchAll(content_block, rgx.image)) { images_ ~= m.captures[1]; } return images_; } 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") { 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); } else if (obj.is_a == "para") { _images ~= extract_images(obj.text); } } } auto images=uniq(_images.sort()); /+ optional only one 1~ level +/ if (the_endnotes_section.length > 1) { dom_markedup_buffer = dom_markedup.dup; dom_collapsed_buffer = dom_collapsed.dup; dom_markedup = dom_markedup_buffer.dup; dom_collapsed = dom_collapsed_buffer.dup; foreach (ref obj; the_endnotes_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup == 4) { 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 *** [#A] _return document tuple_ :return:tuple: #+name: abs_post #+BEGIN_SRC d auto t = tuple( document_the, document_section_keys_sequenced, html_segnames, images, ); 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(O)(ref O an_object) { debug(asserts){ static assert(is(typeof(an_object) == string[string])); } an_object.remove("body_nugget"); an_object.remove("substantive"); an_object.remove("is"); an_object.remove("attrib"); an_object.remove("bookindex_nugget"); } #+END_SRC **** set, initialize or re-initialize :set: #+name: abs_functions_header_set_common #+BEGIN_SRC d auto _common_reset_(L,O,T)( ref L line_occur, ref O an_object, ref T type ) { debug(asserts){ static assert(is(typeof(line_occur) == int[string])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } line_occur["heading"] = State.off; line_occur["para"] = State.off; type["heading"] = State.off; type["para"] = State.off; object_reset(an_object); } #+END_SRC *** check obj_cite_number status in document :ocn: #+name: abs_functions_ocn_status #+BEGIN_SRC d void _check_ocn_status_(L,T)( L line, ref T type ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if ((!line.empty) && (type["ocn_status_multi_obj"] == TriState.off)) { /+ not multi-line object, check whether obj_cite_number is on or turned off +/ if (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_(L,T,N)( L line, ref T type, N obj_cite_number_poem ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(type) == int[string])); static assert(is(typeof(obj_cite_number_poem) == string[string])); } #+END_SRC ***** block (various) curly open :curly: #+name: abs_functions_block #+BEGIN_SRC d auto rgx = Rgx(); 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_(L,O,T)( ref L line, ref O an_object, ref T type ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if (type["curly_code"] == TriState.on) { if (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(A)(A abr) { debug(asserts){ static assert(is(typeof(abr) == string)); } auto btm = [ "au" : "author_raw", "ed" : "editor_raw", "ti" : "fulltitle", "lng" : "language", "jo" : "journal", "vol" : "volume", "edn" : "edition", "yr" : "year", "pl" : "place", "pb" : "publisher", "pub" : "publisher", "pg" : "pages", "pgs" : "pages", "sn" : "short_name" ]; return btm[abr]; } #+END_SRC ******* +consider+ #+name: none #+BEGIN_SRC d final string biblio_tag_map_(A)(A abr) { debug(asserts){ static assert(is(typeof(abr) == string)); } 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 ) { mixin SiSUbiblio; auto jsn = BibJsnStr(); auto rgx = Rgx(); 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 = jsn.biblio_entry_tags_jsonstr; } else if (!(biblio_entry_str_json.empty)) { bib_entry = State.off; if (!(biblio_entry_str_json == jsn.biblio_entry_tags_jsonstr)) { auto biblio_entry = parseJSON(biblio_entry_str_json); if (biblio_entry["fulltitle"].str.empty) { writeln("check problem entry (Title missing): ", biblio_entry_str_json); } else if ((biblio_entry["author_raw"].str.empty) && (biblio_entry["editor_raw"].str.empty)) { writeln("check problem entry (No author and no editor): ", biblio_entry_str_json); } else { biblio_arr_json ~= biblio_entry_str_json; } biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr; } } else { // CHECK ERROR writeln("?? 2. ERROR ", biblio_entry_str_json, "??"); biblio_entry_str_json = ""; } } else if (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_(L,O,T,C,N,Ma)( L line, ref O an_object, ref T type, ref C cntr, N obj_cite_number_poem, Ma dochead_make_aa, ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); static assert(is(typeof(cntr) == int)); static assert(is(typeof(obj_cite_number_poem) == string[string])); static assert(is(typeof(dochead_make_aa) == string[string][string])); } auto rgx = Rgx(); if (type["curly_poem"] == TriState.on) { if (matchFirst(line, rgx.block_curly_poem_close)) { an_object[an_object_key]="verse"; 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"; debug(poem) { // poem (curly) close writefln( "* [poem tic] %s", line ); } if (processing.length > 0) { an_object[an_object_key] = processing["verse"]; } if (an_object.length > 0) { debug(poem) { // poem (tic) close writeln(__LINE__); writeln(obj_cite_number, line); } processing.remove("verse"); an_object["is"] = "verse"; auto substantive_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_(L,O,T)( ref L line, ref O an_object, ref T type ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if (type["curly_group"] == State.on) { if (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_(L,O,T)( ref L line, ref O an_object, ref T type ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if (type["curly_block"] == TriState.on) { if (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_(L,O,T)( ref L line, ref O an_object, ref T type ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if (type["curly_quote"] == TriState.on) { if (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) { 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) { 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_(L,O,T)( ref L line, ref O an_object, ref T type ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if (type["curly_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"]); 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_(L,I,O,T,B)( L line, ref I book_idx_tmp, ref O an_object, ref T type, B opt_action_bool, ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(book_idx_tmp) == string)); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); static assert(is(typeof(opt_action_bool) == bool[string])); } auto rgx = Rgx(); 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_(L,X,H,R,T)( L line, X dochead_make_identify_unmarked_headings, ref H heading_match_str, ref R heading_match_rgx, ref T type ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(dochead_make_identify_unmarked_headings) == string)); static assert(is(typeof(heading_match_str) == string[string])); static assert(is(typeof(heading_match_rgx) == Regex!(char)[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if ((dochead_make_identify_unmarked_headings.length > 2) && (type["make_headings"] == State.off)) { /+ headings found +/ debug(headingsfound) { writeln(dochead_make_identify_unmarked_headings); } char[][] make_headings_spl = 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 **** heading make set :heading: #+name: abs_functions_heading #+BEGIN_SRC d auto _heading_make_set_(L,C,R,T)( L line, C line_occur, ref R heading_match_rgx, ref T type ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(line_occur) == int[string])); static assert(is(typeof(heading_match_rgx) == Regex!(char)[string])); static assert(is(typeof(type) == int[string])); } if ((type["make_headings"] == State.on) && ((line_occur["para"] == State.off) && (line_occur["heading"] == State.off)) && ((type["para"] == State.off) && (type["heading"] == State.off))) { /+ heading make set +/ if (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_(L,C,O,K,Lv,Lc,T,Me)( ref L line, ref C line_occur, ref O an_object, ref K an_object_key, ref Lv lv, ref Lc collapsed_lev, ref T type, ref Me dochead_meta_aa, ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(line_occur) == int[string])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(an_object_key) == string)); static assert(is(typeof(lv) == int[string])); static assert(is(typeof(collapsed_lev) == int[string])); static assert(is(typeof(type) == int[string])); static assert(is(typeof(dochead_meta_aa) == string[string][string])); } auto rgx = Rgx(); if (auto m = 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_(L,O,K,I,B,T,C)( ref L line, ref O an_object, ref K an_object_key, ref I indent, ref B bullet, ref T type, ref C line_occur, ) { debug(asserts){ static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(an_object_key) == string)); static assert(is(typeof(indent) == int[string])); static assert(is(typeof(bullet) == bool)); static assert(is(typeof(type) == int[string])); static assert(is(typeof(line_occur) == int[string])); } auto rgx = Rgx(); if (line_occur["para"] == State.off) { /+ 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 <= 3); } body { if (ocn_status_flag == 3) { obj_cite_number = obj_cite_number_ = 1; } else { obj_cite_number=(ocn_status_flag == 0) ? ++obj_cite_number_ : 0; } assert(obj_cite_number >= 0); return obj_cite_number; } invariant() { } } #+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(Ot)(Ot obj_txt_in) { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } /+ 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(Ot)(Ot obj_txt_in) { // here endnotes are marked up debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } /+ 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(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { 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(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { 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(Ot)(Ot obj_txt_in) in { debug(asserts){ assert(is(typeof(obj_txt_in) == string)); } } 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(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=obj_txt_in; obj_txt["munge"]=object_notes_(obj_txt["munge"]); return obj_txt["munge"]; } invariant() { } string verse(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=obj_txt_in; obj_txt["munge"]=object_notes_(obj_txt["munge"]); return obj_txt["munge"]; } invariant() { } string quote(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } string table(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } string comment(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } } #+END_SRC ***** toc, tags, object inline markup :markup:inline: ****** open #+name: ao_emitters_obj_inline_markup #+BEGIN_SRC d struct ObjInlineMarkup { auto rgx = Rgx(); 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(O,K,Ma)( O obj_, K obj_key_, Ma dochead_make_aa ) in { debug(asserts){ static assert(is(typeof(obj_) == string[string])); static assert(is(typeof(obj_key_) == string)); static assert(is(typeof(dochead_make_aa) == string[string][string])); } } body { obj_txt["munge"]=obj_[obj_key_].dup; obj_txt["munge"]=(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_(Toc)( Toc heading_toc_, ) { debug(asserts){ static assert(is(typeof(heading_toc_) == char[])); } 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(O,Ma,Ts,Ta,X,Toc)( O obj_, Ma dochead_make_aa, Ts segment_anchor_tag_that_object_belongs_to, Ta _anchor_tag, ref X lev4_subtoc, Toc the_table_of_contents_section, ) in { debug(asserts){ static assert(is(typeof(obj_) == string[string])); static assert(is(typeof(dochead_make_aa) == string[string][string])); static assert(is(typeof(segment_anchor_tag_that_object_belongs_to) == string)); static assert(is(typeof(_anchor_tag) == string)); static assert(is(typeof(lev4_subtoc) == string[][string])); static assert(is(typeof(the_table_of_contents_section) == ObjGenericComposite[][string])); } } body { ObjGenericComposite comp_obj_toc; mixin InternalMarkup; auto mkup = InlineMarkup(); char[] heading_toc_ = 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(M,O,Ma)( M munge_, O obj_, Ma dochead_make_aa ) { debug(asserts){ static assert(is(typeof(munge_) == string)); static assert(is(typeof(obj_) == string[string])); static assert(is(typeof(dochead_make_aa) == string[string][string])); } if (dochead_make_aa["make"]["num_top"].length > 0) { 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(M,Lv)(M munge_, Lv lev_) { debug(asserts){ static assert(is(typeof(munge_) == string)); static assert(is(typeof(lev_) == string)); } 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(Oi,OR,OH)( Oi obj_is_, OR obj_raw, OH _comp_obj_heading, ) in { debug(asserts){ static assert(is(typeof(obj_is_) == string)); static assert(is(typeof(obj_raw) == string)); static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite)); } } body { scope(exit) { destroy(obj_is_); destroy(obj_raw); destroy(_comp_obj_heading); } _obj_attrib["json"] ="{"; switch (obj_is_) { case "heading": _obj_attrib["json"] ~= _heading(obj_raw); break; case "para": _obj_attrib["json"] ~= _para_and_blocks(obj_raw) ~ _para(obj_raw); break; case "code": _obj_attrib["json"] ~= _code(obj_raw); break; case "group": _obj_attrib["json"] ~= _para_and_blocks(obj_raw) ~ _group(obj_raw); break; case "block": _obj_attrib["json"] ~= _para_and_blocks(obj_raw) ~ _block(obj_raw); break; case "verse": _obj_attrib["json"] ~= _verse(obj_raw); break; case "quote": _obj_attrib["json"] ~= _quote(obj_raw); break; case "table": _obj_attrib["json"] ~= _table(obj_raw); break; case "comment": _obj_attrib["json"] ~= _comment(obj_raw); break; default: _obj_attrib["json"] ~= _para(obj_raw); break; } _obj_attrib["json"] ~=" }"; _obj_attrib["json"]=_set_additional_values_parse_as_json(_obj_attrib["json"], obj_is_, _comp_obj_heading); debug(structattrib) { if (oa_j["is"].str() == "heading") { writeln(_obj_attrib["json"]); writeln( "is: ", oa_j["is"].str(), "; obj_cite_number: ", oa_j["obj_cite_number"].integer() ); } } return _obj_attrib["json"]; } invariant() { } #+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(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { 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(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"para\"," ~ " \"is\": \"para\""; return _obj_attributes; } invariant() { } #+END_SRC ******** heading #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _heading(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"para\"," ~ " \"is\": \"heading\""; return _obj_attributes; } invariant() { } #+END_SRC ******** code #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _code(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"code\""; return _obj_attributes; } invariant() { } #+END_SRC ******** group #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _group(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"group\""; return _obj_attributes; } invariant() { } #+END_SRC ******** block #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _block(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"block\""; return _obj_attributes; } invariant() { } #+END_SRC ******** verse #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _verse(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"verse\""; return _obj_attributes; } invariant() { } #+END_SRC ******** quote #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _quote(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"quote\""; return _obj_attributes; } invariant() { } #+END_SRC ******** table #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _table(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"table\""; return _obj_attributes; } invariant() { } #+END_SRC ******** comment #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _comment(Ot)(Ot obj_txt_in) in { debug(asserts){ static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"comment\"," ~ " \"of\": \"comment\"," ~ " \"is\": \"comment\""; return _obj_attributes; } invariant() { } #+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(OA,Oi,OH)( OA _obj_attrib, Oi obj_is_, OH _comp_obj_heading, ) { debug(asserts){ static assert(is(typeof(_obj_attrib) == string)); static assert(is(typeof(obj_is_) == string)); static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite)); } JSONValue oa_j = parseJSON(_obj_attrib); assert( (oa_j.type == JSON_TYPE.OBJECT) ); if (obj_is_ == "heading") { oa_j.object["obj_cite_number"] = _comp_obj_heading.ocn; oa_j.object["lev_markup_number"] = _comp_obj_heading.heading_lev_markup; oa_j.object["lev_collapsed_number"] = _comp_obj_heading.heading_lev_collapsed; oa_j.object["heading_ptr"] = _comp_obj_heading.ptr_heading; oa_j.object["doc_object_ptr"] = _comp_obj_heading.ptr_doc_object; } oa_j.object["parent_obj_cite_number"] = _comp_obj_heading.parent_ocn; oa_j.object["parent_lev_markup_number"] = _comp_obj_heading.parent_lev_markup; _obj_attrib = oa_j.toString(); return _obj_attrib; } #+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(BI,N)( BI bookindex_section, N obj_cite_number ) in { debug(asserts){ static assert(is(typeof(bookindex_section) == string)); static assert(is(typeof(obj_cite_number) == int)); } debug(bookindexraw) { if (!bookindex_section.empty) { writeln( "* [bookindex] ", "[", 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(BI)( BI bookindex_unordered_hashes ) { debug(asserts){ static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string])); } auto mainkeys= bookindex_unordered_hashes.byKey.array.sort().release; foreach (mainkey; mainkeys) { debug(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(BI)( BI bookindex_unordered_hashes ) { debug(asserts){ static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string])); } auto mainkeys=bookindex_unordered_hashes.byKey.array.sort().release; foreach (mainkey; mainkeys) { write("_0_1 !{", mainkey, "}! "); foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { auto go = 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(BI,N,Ta,B)( BI bookindex_unordered_hashes, N obj_cite_number, Ta segment_anchor_tag_that_object_belongs_to, B opt_action_bool, ) { debug(asserts){ static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string])); static assert(is(typeof(obj_cite_number) == int)); static assert(is(typeof(segment_anchor_tag_that_object_belongs_to) == string)); static assert(is(typeof(opt_action_bool) == bool[string])); } mixin SiSUnode; mixin InternalMarkup; auto mkup = InlineMarkup(); string type_is; string lev; int heading_lev_markup, heading_lev_collapsed; string attrib; int[string] indent; auto mainkeys = bookindex_unordered_hashes.byKey.array.sort().release; ObjGenericComposite[][string] bookindex_section; ObjGenericComposite comp_obj_heading_, comp_obj_para; auto node_para_int_ = node_metadata_para_int; auto node_para_str_ = node_metadata_para_str; if ((mainkeys.length > 0) && (opt_action_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] ]; 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_(Bi,BJ)( ref Bi biblio_unsorted_incomplete, ref BJ bib_arr_json ) in { debug(asserts){ static assert(is(typeof(biblio_unsorted_incomplete) == string[])); static assert(is(typeof(bib_arr_json) == JSONValue[])); } } body { JSONValue[] biblio_unsorted = _biblio_unsorted_complete_(biblio_unsorted_incomplete, bib_arr_json); 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_(Bi,BJ)( Bi biblio_unordered, ref BJ bib_arr_json ) { debug(asserts){ static assert(is(typeof(biblio_unordered) == string[])); static assert(is(typeof(bib_arr_json) == JSONValue[])); } foreach (bibent; biblio_unordered) { // update bib to include deemed_author, needed for: // sort_bibliography_array_by_deemed_author_year_title // either: sort on multiple fields, or; create such sort field JSONValue j = parseJSON(bibent); if (!empty(j["fulltitle"].str)) { if (!empty(j["author_raw"].str)) { j["deemed_author"]=j["author_arr"][0]; } else if (!empty(j["editor_raw"].str)) { j["deemed_author"]=j["editor_arr"][0]; } j["sortby_deemed_author_year_title"] = ( j["deemed_author"].str ~ "; " ~ j["year"].str ~ "; " ~ j["fulltitle"].str ); } bib_arr_json ~= j; } JSONValue[] biblio_unsorted_array_of_json_objects = bib_arr_json.dup; return biblio_unsorted_array_of_json_objects; } #+END_SRC ***** biblio sort #+name: ao_emitters_bibliography #+BEGIN_SRC d final private JSONValue[] biblio_sort(BJ)(BJ biblio_unordered) { debug(asserts){ static assert(is(typeof(biblio_unordered) == JSONValue[])); } JSONValue[] biblio_sorted_; biblio_sorted_ = sort!((a, b){ return ((a["sortby_deemed_author_year_title"].str) < (b["sortby_deemed_author_year_title"].str)); })(biblio_unordered).array; debug(bibliosorted) { foreach (j; biblio_sorted_) { if (!empty(j["fulltitle"].str)) { writeln(j["sortby_deemed_author_year_title"]); } } } return biblio_sorted_; } #+END_SRC ***** biblio debug #+name: ao_emitters_bibliography #+BEGIN_SRC d void biblio_debug(BJ)(BJ biblio_sorted) { debug(asserts){ static assert(is(typeof(biblio_sorted) == JSONValue[])); } debug(biblio0) { foreach (j; biblio_sorted) { if (!empty(j["fulltitle"].str)) { writeln(j["sortby_deemed_author_year_title"]); } } } } #+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_ auto rgx = Rgx(); #+END_SRC ***** TODO node metadata emitter #+name: ao_emitters_metadata #+BEGIN_SRC d ObjGenericComposite node_location_emitter(Lv,Ta,N,C,P,I)( Lv lev_markup_number, Ta segment_anchor_tag, N obj_cite_number_, C cntr_, P ptr_, I is_ ) in { debug(asserts){ static assert(is(typeof(lev_markup_number) == string)); static assert(is(typeof(segment_anchor_tag) == string)); static assert(is(typeof(obj_cite_number_) == int)); static assert(is(typeof(cntr_) == int)); static assert(is(typeof(ptr_) == int)); static assert(is(typeof(is_) == string)); } assert(is_ != "heading"); assert(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(T,L,Lm,Lc,Ta,N,C,P,LA,I,PSn)( T _text, L lev, Lm lev_markup_number, Lc lev_collapsed_number, Ta segment_anchor_tag, N obj_cite_number_, C cntr_, P ptr_, LA lv_ancestors, I is_, PSn html_segnames_ptr, ) in { debug(asserts){ static assert(is(typeof(_text) == string)); static assert(is(typeof(lev) == string)); static assert(is(typeof(lev_markup_number) == string)); static assert(is(typeof(lev_collapsed_number) == string)); static assert(is(typeof(segment_anchor_tag) == string)); static assert(is(typeof(obj_cite_number_) == int)); static assert(is(typeof(cntr_) == int)); static assert(is(typeof(ptr_) == int)); static assert(is(typeof(lv_ancestors) == string[])); static assert(is(typeof(is_) == string)); static assert(is(typeof(html_segnames_ptr) == int)); } assert(is_ == "heading"); assert(to!int(obj_cite_number_) >= 0); assert( 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 { int obj_cite_number = to!int(obj_cite_number_); switch (to!int(lev_markup_number)) { 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"; // = 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(O,Lv)( O an_object, Lv lv ) { debug(asserts){ static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(lv) == int[string])); } if (lv["h3"] > State.off) { assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); assert(lv["h2"] > State.off); } else if (lv["h2"] > State.off) { assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); assert(lv["h3"] == State.off); } else if (lv["h1"] > State.off) { assert(lv["h0"] > State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } else if (lv["h0"] > State.off) { assert(lv["h1"] == State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } else { assert(lv["h0"] == State.off); assert(lv["h1"] == State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } if (lv["h7"] > State.off) { assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); assert(lv["h6"] > State.off); } else if (lv["h6"] > State.off) { assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); assert(lv["h7"] == State.off); } else if (lv["h5"] > State.off) { assert(lv["h4"] > State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } else if (lv["h4"] > State.off) { assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } else { assert(lv["h4"] == State.off); assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h0"] == State.off) { assert(lv["h1"] == State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); assert(lv["h4"] == State.off); assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h1"] == State.off) { assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } if (lv["h2"] == State.off) { assert(lv["h3"] == State.off); } if (lv["h3"] == State.off) { } if (lv["h4"] == State.off) { assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h5"] == State.off) { assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h6"] == State.off) { assert(lv["h7"] == State.off); } if (lv["h7"] == State.off) { } switch (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(T)(T type) { debug(asserts){ static assert(is(typeof(type) == int[string])); } assert( (type["code"] == TriState.off) || (type["code"] == TriState.closing), "code block status: off or closing"); assert( (type["poem"] == TriState.off) || (type["poem"] == TriState.closing), "poem status: off or closing"); assert( (type["table"] == TriState.off) || (type["table"] == TriState.closing), "table status: off or closing"); assert( (type["group"] == TriState.off) || (type["group"] == TriState.closing), "group block status: off or closing"); assert( (type["block"] == TriState.off) || (type["block"] == TriState.closing), "block status: off or closing"); } #+END_SRC * 2. Object Setter :abstract:object: set abstracted objects for downstream processing ** 0. 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. 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