#+TITLE: sdp document abstraction #+AUTHOR: Ralph Amissah #+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]] #+DESCRIPTION: documents - structuring, publishing in multiple formats & search #+KEYWORDS #+LANGUAGE: en #+STARTUP: indent content #+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:meta: #+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 :module:sdp:metadoc_from_src: Process markup document, create document abstraction. ** 0. module template #+BEGIN_SRC d :tangle ../src/sdp/meta/metadoc_from_src.d /++ document abstraction: abstraction of sisu markup for downstream processing metadoc_from_src.d +/ module sdp.meta.metadoc_from_src; template SiSUdocAbstraction() { /+ ↓ abstraction imports +/ <<abs_top_imports>> /+ ↓ abstraction mixins +/ <<abs_top_mixins>> /+ ↓ abstraction struct init +/ <<abs_top_init_struct>> /+ ↓ abstract marked up document +/ auto SiSUdocAbstraction(Src,CMM,Opt)( Src markup_sourcefile_content, CMM conf_make_meta, Opt opt_action, ) { static auto rgx = Rgx(); debug(asserts) { static assert(is(typeof(markup_sourcefile_content) == char[][])); } /+ ↓ abstraction init +/ <<abs_init_rest>> /+ abstraction init ↑ +/ <<make_tests>> /+ ↓ loop markup document/text line by line +/ srcDocLoop: foreach (line; markup_sourcefile_content) { // "line" variable can be empty but should never be null /+ ↓ markup document/text line by line +/ <<abs_in_loop_body_00>> if (obj_type_status["code"] == TriState.on) { <<abs_in_loop_body_00_code_block>> } else if (!matchFirst(line, rgx.skip_from_regular_parse)) { /+ object other than "code block" object (includes regular text paragraph, headings & blocks other than code) +/ /+ heading, glossary, blurb, poem, group, block, quote, table +/ <<abs_in_loop_body_non_code_obj>> } else { /+ not within a block group +/ <<abs_in_loop_body_open_block_obj_assert>> if (line.matchFirst(rgx.block_open)) { <<abs_in_loop_body_open_block_obj>> } else if (!line.empty) { /+ line not empty +/ /+ non blocks (headings, paragraphs) & closed blocks +/ <<abs_in_loop_body_not_block_obj>> } else if (obj_type_status["blocks"] == TriState.closing) { /+ line empty, with blocks flag +/ <<abs_in_loop_body_not_block_obj_line_empty_blocks_flags>> } else { /+ line.empty, post contents, empty variables: +/ <<abs_in_loop_body_not_block_obj_line_empty>> } // close else for line empty } // close else for not the above } // close after non code, other blocks or regular text <<abs_in_loop_body_01>> } /+ ← closed: loop markup document/text line by line +/ /+ ↓ post loop markup document/text +/ <<abs_post>> /+ post loop markup document/text ↑ +/ } /+ ← closed: abstract doc source +/ /+ ↓ abstraction functions +/ <<abs_functions_object_reset>> <<abs_functions_header_set_common>> <<abs_functions_ocn_status>> <<abs_functions_substitutions>> <<abs_functions_block>> <<abs_functions_block_quote>> <<abs_functions_block_group>> <<abs_functions_block_block>> <<abs_functions_block_poem>> <<abs_functions_block_code>> <<abs_functions_block_table>> <<abs_functions_block_biblio>> <<abs_functions_block_line_status_empty>> <<abs_functions_book_index>> <<abs_functions_heading>> <<abs_functions_para>> <<abs_functions_table>> /+ abstraction functions ↑ +/ /+ ↓ abstraction function emitters +/ <<meta_emitters_ocn>> /+ +/ <<meta_emitters_obj_inline_markup_munge>> <<meta_emitters_obj_inline_markup>> <<meta_emitters_obj_inline_markup_and_anchor_tags_and_misc>> <<meta_emitters_obj_inline_markup_table_of_contents>> <<meta_emitters_obj_inline_markup_private>> <<meta_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags>> <<meta_emitters_obj_inline_markup_close>> /+ +/ <<meta_emitters_obj_attributes>> <<meta_emitters_obj_attributes_public>> <<meta_emitters_obj_attributes_private>> <<meta_emitters_obj_attributes_private_an_attribute>> <<meta_emitters_obj_attributes_private_json>> <<meta_emitters_obj_attributes_private_close>> /+ +/ <<meta_emitters_book_index_nugget>> <<meta_emitters_book_index_report_indented>> <<meta_emitters_book_index_report_section>> /+ +/ <<meta_emitters_endnotes>> /+ +/ <<meta_emitters_bibliography>> /+ +/ <<meta_emitters_metadata>> /+ abstraction functions emitters ↑ +/ /+ ↓ abstraction functions assertions +/ <<abs_functions_assertions>> /+ abstraction functions assertions ↑ +/ } /+ ← closed: template SiSUdocAbstraction +/ <<template_doc_sect_keys_seq>> #+END_SRC ** 1. _pre loop processing_ :pre: *** imports :imports: [[./meta_defaults.org][meta_defaults]] #+name: abs_top_imports #+BEGIN_SRC d import sdp.meta; import std.algorithm, std.container, std.file, std.json, std.path; import sdp.meta.defaults, sdp.meta.object_setter, sdp.meta.rgx; #+END_SRC *** mixins :mixins: #+name: abs_top_mixins #+BEGIN_SRC d mixin ObjectSetter; mixin InternalMarkup; mixin SiSUrgxInit; #+END_SRC *** initialize :initialize: **** initialize general #+name: abs_top_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; /+ 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 OCNstatus { on, off, bkidx, closing, reset, } enum OCNtype { ocn, non, bkidx, } /+ biblio variables +/ string biblio_tag_name, biblio_tag_entry, st; string[] biblio_arr_json; string biblio_entry_str_json; JSONValue[] bib_arr_json; int bib_entry; /+ counters +/ int cntr, previous_count, previous_length; bool reset_note_numbers=true; int[string] line_occur; int html_segnames_ptr=0; int html_segnames_ptr_cntr=0; int verse_line, heading_ptr; /+ paragraph attributes +/ int[string] indent; bool bullet = true; string content_non_header = "8"; static auto obj_im = ObjInlineMarkup(); static auto obj_att = ObjAttributes(); /+ ocn +/ struct OCNset { int digit; int on; int off; int bkidx; int type; } OCNset obj_cite_digits; int obj_cite_digit_, obj_cite_digit_off, obj_cite_digit_bkidx, obj_cite_digit_type; 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_top_init_struct #+BEGIN_SRC d pure auto obj_heading_ancestors(O)( O obj, string[] lv_ancestors_txt, ) { switch (obj.heading_lev_markup) { case 0: lv_ancestors_txt[0] = obj.text.to!string; foreach(k; 1..8) { lv_ancestors_txt[k] = ""; } goto default; case 1: lv_ancestors_txt[1] = obj.text.to!string; foreach(k; 2..8) { lv_ancestors_txt[k] = ""; } goto default; case 2: lv_ancestors_txt[2] = obj.text.to!string; foreach(k; 3..8) { lv_ancestors_txt[k] = ""; } goto default; case 3: lv_ancestors_txt[3] = obj.text.to!string; foreach(k; 4..8) { lv_ancestors_txt[k] = ""; } goto default; case 4: lv_ancestors_txt[4] = obj.text.to!string; foreach(k; 5..8) { lv_ancestors_txt[k] = ""; } goto default; case 5: lv_ancestors_txt[5] = obj.text.to!string; foreach(k; 6..8) { lv_ancestors_txt[k] = ""; } goto default; case 6: lv_ancestors_txt[6] = obj.text.to!string; lv_ancestors_txt[7] = ""; goto default; case 7: lv_ancestors_txt[7] = obj.text.to!string; goto default; default: obj.heading_ancestors_text = lv_ancestors_txt.dup; } return obj; } #+END_SRC **** initialize dom markup tags #+name: abs_top_init_struct #+BEGIN_SRC d pure auto obj_dom_structure_set_markup_tags(O)( O obj, int[] dom, int lev ) { foreach (i; 0 .. 8) { if (i < lev) { if (dom[i] == DomTags.open || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.open_still; } else if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } } else if (i == lev) { if (lev == 0 && dom[i] == DomTags.open_still ) { dom[i] = DomTags.close; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close_and_open; } else { dom[i] = DomTags.open; } } else if (i > lev) { if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close; } } } debug(dom_magic_numbers) { writeln("marked up: ", lev, ": ", dom); } obj.dom_markedup = dom.dup; return obj; } #+END_SRC **** initialize dom collapsed tags #+name: abs_top_init_struct #+BEGIN_SRC d pure auto obj_dom_set_collapsed_tags(O)( O obj, int[] dom, int lev ) { foreach (i; 0 .. 8) { if (i < lev) { if (dom[i] == DomTags.open || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.open_still; } else if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } } else if (i == lev) { if (lev == 0 && dom[i] == DomTags.open_still ) { dom[i] = DomTags.close; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close_and_open; } else { dom[i] = DomTags.open; } } else if (i > lev) { if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close; } } } debug(dom_magic_numbers) { writeln("collapsed: ", lev, ": ", dom); } obj.dom_collapsed = dom.dup; return obj; } #+END_SRC **** initialize ocn emit #+name: abs_top_init_struct #+BEGIN_SRC d static auto ocn_emit(int ocn_status_flag) { return object_citation_number.ocn_emitter(ocn_status_flag); } /+ book index variables +/ string book_idx_tmp; string[][string][string] bookindex_unordered_hashes; /+ node +/ ObjGenericComposite comp_obj_heading, comp_obj_location, comp_obj_block, comp_obj_code, comp_obj_poem_ocn, comp_obj_comment; auto node_construct = NodeStructureMetadata(); enum sObj { content, anchor_tags, notes_reg, notes_star, links } #+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); previous_length=0; reset_note_numbers=true; } #+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 obj_type_status = flags_type_init; string[string] obj_cite_number_poem = [ "start" : "", "end" : "" ]; string[] lv_ancestors_txt = [ "", "", "", "", "", "", "", "", ]; int[string] lv = [ "lv" : State.off, "h0" : State.off, "h1" : State.off, "h2" : State.off, "h3" : State.off, "h4" : State.off, "h5" : State.off, "h6" : State.off, "h7" : State.off, "lev_int_collapsed" : 0, ]; int[string] collapsed_lev = [ "h0" : State.off, "h1" : State.off, "h2" : State.off, "h3" : State.off, "h4" : State.off, "h5" : State.off, "h6" : State.off, "h7" : State.off ]; string[string] heading_match_str = [ "h_A": "^(none)", "h_B": "^(none)", "h_C": "^(none)", "h_D": "^(none)", "h_1": "^(none)", "h_2": "^(none)", "h_3": "^(none)", "h_4": "^(none)" ]; auto heading_match_rgx = [ "h_A": regex(r"^(none)"), "h_B": regex(r"^(none)"), "h_C": regex(r"^(none)"), "h_D": regex(r"^(none)"), "h_1": regex(r"^(none)"), "h_2": regex(r"^(none)"), "h_3": regex(r"^(none)"), "h_4": regex(r"^(none)") ]; string _anchor_tag; string toc_txt_; an_object["glossary_nugget"] = ""; an_object["blurb_nugget"] = ""; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "frontmatter"; comp_obj_heading_.of_section = "toc"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.segment_anchor_tag = "toc"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.ptr_html_segnames = html_segnames_ptr; comp_obj_heading_.anchor_tags = ["toc"]; comp_obj_heading_.dom_markedup = [ 1, 1, 0, 0, 1, 0, 0, 0]; comp_obj_heading_.dom_collapsed = [ 1, 1, 1, 0, 0, 0, 0, 0]; auto toc_head = comp_obj_heading_; html_segnames_ptr_cntr++; the_table_of_contents_section = [ "seg": [toc_head], "scroll": [toc_head], ]; static auto mkup = InlineMarkup(); static auto munge = ObjInlineMarkupMunge(); auto note_section = NotesSection(); auto bookindex_extract_hash = BookIndexNuggetHash(); string[][string] lev4_subtoc; string[] html_segnames=["toc"]; int cnt1 = 1; int cnt2 = 1; int cnt3 = 1; #+END_SRC *** make tests #+name: make_tests #+BEGIN_SRC d enum Substitute { match, markup, } debug (substitutions) { writeln(__LINE__, ":", __FILE__, ": DEBUG substitutions:"); if (!(conf_make_meta.make.headings.empty)) { writeln(conf_make_meta.make.headings); } if (conf_make_meta.make.substitute) { foreach(substitution_pair; conf_make_meta.make.substitute) { writeln("regex to match: ", substitution_pair[Substitute.match]); writeln("substitution to make: ", substitution_pair[Substitute.markup]); } } if (conf_make_meta.make.bold) { writeln("regex to match: ", conf_make_meta.make.bold[Substitute.match]); writeln("substitution to make: ", conf_make_meta.make.bold[Substitute.markup]); } if (conf_make_meta.make.emphasis) { writeln("regex to match: ", conf_make_meta.make.emphasis[Substitute.match]); writeln("substitution to make: ", conf_make_meta.make.emphasis[Substitute.markup]); } if (conf_make_meta.make.italics) { writeln("regex to match: ", conf_make_meta.make.italics[Substitute.match]); writeln("substitution to make: ", conf_make_meta.make.italics[Substitute.markup]); } } #+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 = (line).replaceAll(rgx.true_dollar, "$$$$"); /+ dollar represented as $$ needed to stop submatching on $ (substitutions using ${identifiers} must take into account (i.e. happen earlier)) +/ debug(source) { // source lines writeln(line); } debug(srclines) { if (!line.empty) { // source lines, not empty writefln( "* %s", line ); } } #+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) { obj_type_status = _check_ocn_status_(line, obj_type_status); } #+END_SRC *** [#A] separate _code blocks_ from _other markup text_ [+5] **** _code blocks_ :block:code: #+name: abs_in_loop_body_00_code_block #+BEGIN_SRC d /+ block object: code +/ _code_block_(line, an_object, obj_type_status); continue; #+END_SRC **** _non code objects_ (other blocks or regular text) [+4] :non_code: ***** in section (biblio, glossary, blurb) +(block group)+ [+1] :block:active: ****** in section: biblio :biblio: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d if (line.matchFirst(rgx.heading_biblio) || (obj_type_status["biblio_section"] == State.on && (!(line.matchFirst(rgx.heading_blurb_glossary))) && (!(line.matchFirst(rgx.heading))) && (!(line.matchFirst(rgx.comment))))) { /+ within section (block object): biblio +/ obj_type_status["glossary_section"] = State.off; obj_type_status["biblio_section"] = State.on; obj_type_status["blurb_section"] = State.off; if (opt_action.backmatter && opt_action.section_biblio) { _biblio_block_(line, obj_type_status, bib_entry, biblio_entry_str_json, biblio_arr_json); debug(bibliobuild) { writeln("- ", biblio_entry_str_json); writeln("-> ", biblio_arr_json.length); } } continue; #+END_SRC ****** in 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 (line.matchFirst(rgx.heading_glossary) || (obj_type_status["glossary_section"] == State.on && (!(line.matchFirst(rgx.heading_biblio_blurb))) && (!(line.matchFirst(rgx.heading))) && (!(line.matchFirst(rgx.comment))))) { /+ within section (block object): glossary +/ debug(glossary) { writeln(__LINE__); writeln(line); } obj_type_status["glossary_section"] = State.on; obj_type_status["biblio_section"] = State.off; obj_type_status["blurb_section"] = State.off; if (opt_action.backmatter && opt_action.section_glossary) { indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; obj_type_status["para"] = State.on; line_occur["para"] = State.off; an_object_key="glossary_nugget"; // if (line.matchFirst(rgx.heading_glossary)) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "backmatter"; comp_obj_heading_.of_section = "glossary"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.segment_anchor_tag = "_part_glossary"; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.dom_markedup = [ 1, 1, 0, 0, 0, 0, 0, 0]; comp_obj_heading_.dom_collapsed = [ 1, 1, 0, 0, 0, 0, 0, 0]; the_glossary_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "backmatter"; comp_obj_heading_.of_section = "glossary"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.segment_anchor_tag = "glossary"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.dom_markedup = [ 1, 1, 0, 0, 1, 0, 0, 0]; comp_obj_heading_.dom_collapsed = [ 1, 1, 1, 0, 0, 0, 0, 0]; comp_obj_heading_.anchor_tags = ["glossary"]; the_glossary_section ~= comp_obj_heading_; } else { _para_match_(line, an_object, an_object_key, indent, bullet, obj_type_status, line_occur); comp_obj_para = comp_obj_para.init; comp_obj_para.of_part = "backmatter"; comp_obj_para.of_section = "glossary"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "glossary"; comp_obj_para.text = line.to!string.strip; comp_obj_para.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.obj_cite_number_off = ""; comp_obj_para.obj_cite_number_type = 0; 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; } obj_type_status["ocn_status"] = OCNstatus.on; } continue; #+END_SRC ****** in 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 (line.matchFirst(rgx.heading_blurb) || (obj_type_status["blurb_section"] == State.on && (!(line.matchFirst(rgx.heading_biblio_glossary))) && (!(line.matchFirst(rgx.heading))) && (!(line.matchFirst(rgx.comment))))) { /+ within section (block object): blurb +/ debug(blurb) { writeln(__LINE__); writeln(line); } obj_type_status["glossary_section"] = State.off; obj_type_status["biblio_section"] = State.off; obj_type_status["blurb_section"] = State.on; if (opt_action.backmatter && opt_action.section_blurb) { indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; obj_type_status["para"] = State.on; line_occur["para"] = State.off; an_object_key="blurb_nugget"; if (line.matchFirst(rgx.heading_blurb)) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "backmatter"; comp_obj_heading_.of_section = "blurb"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.segment_anchor_tag = "_part_blurb"; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.dom_markedup = [ 1, 1, 0, 0, 0, 0, 0, 0]; comp_obj_heading_.dom_collapsed = [ 1, 1, 0, 0, 0, 0, 0, 0]; the_blurb_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "backmatter"; comp_obj_heading_.of_section = "blurb"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.segment_anchor_tag = "blurb"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.anchor_tags = ["blurb"]; comp_obj_heading_.dom_markedup = [ 1, 1, 0, 0, 1, 0, 0, 0]; comp_obj_heading_.dom_collapsed = [ 1, 1, 1, 0, 0, 0, 0, 0]; the_blurb_section ~= comp_obj_heading_; } else if (line.matchFirst(rgx.heading) && (opt_action.backmatter && opt_action.section_blurb)) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "backmatter"; comp_obj_heading_.of_section = "blurb"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = line.to!string; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.segment_anchor_tag = "blurb"; comp_obj_heading_.marked_up_level = an_object["lev"].to!string; comp_obj_heading_.heading_lev_markup = an_object["lev_markup_number"].to!int; // make int, remove need to conv comp_obj_heading_.heading_lev_collapsed = an_object["lev_collapsed_number"].to!int; // make int, remove need to conv comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_blurb_section ~= comp_obj_heading_; } else { _para_match_(line, an_object, an_object_key, indent, bullet, obj_type_status, line_occur); comp_obj_para = comp_obj_para.init; comp_obj_para.of_part = "backmatter"; comp_obj_para.of_section = "blurb"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "blurb"; comp_obj_para.text = line.to!string.strip; comp_obj_para.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.obj_cite_number_off = ""; comp_obj_para.obj_cite_number_type = 0; 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; } obj_type_status["ocn_status"] = OCNstatus.on; } continue; #+END_SRC ***** in blocks [+1] :block:active: ****** in block: quote :quote: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (obj_type_status["quote"] == TriState.on) { /+ within block object: quote +/ line = _doc_header_and_make_substitutions_(line, conf_make_meta); line = _doc_header_and_make_substitutions_fontface_(line, conf_make_meta); _quote_block_(line, an_object, obj_type_status); continue; #+END_SRC ****** in block: group :group: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d /+ within block object: group +/ } else if (obj_type_status["group"] == TriState.on) { /+ within block object: group +/ line = _doc_header_and_make_substitutions_(line, conf_make_meta); line = _doc_header_and_make_substitutions_fontface_(line, conf_make_meta); line = (line) .replaceAll(rgx.para_delimiter, mkup.br_paragraph ~ "$1"); _group_block_(line, an_object, obj_type_status); continue; #+END_SRC ****** in block: block :block: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (obj_type_status["block"] == TriState.on) { /+ within block object: block +/ line = _doc_header_and_make_substitutions_(line, conf_make_meta); line = _doc_header_and_make_substitutions_fontface_(line, conf_make_meta); if (auto m = line.match(rgx.spaces_line_start)) { line = (line) .replaceAll(rgx.spaces_line_start, (m.captures[1]).translate([ ' ' : mkup.nbsp ])); } if (auto m = line.match(rgx.spaces_multiple)) { line = (line) .replaceAll(rgx.spaces_multiple, (m.captures[1]).translate([ ' ' : mkup.nbsp ])); } _block_block_(line, an_object, obj_type_status); continue; #+END_SRC ****** in block: poem :poem: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (obj_type_status["poem"] == TriState.on) { /+ within block object: poem +/ _poem_block_(line, an_object, obj_type_status, cntr, obj_cite_number_poem, conf_make_meta); continue; #+END_SRC ****** in block: table :table: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (obj_type_status["table"] == TriState.on) { /+ within block object: table +/ _table_block_(line, an_object, obj_type_status, conf_make_meta); 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( (obj_type_status["blocks"] == TriState.off) || (obj_type_status["blocks"] == TriState.closing), "block status: none or closed" ); assertions_flag_types_block_status_none_or_closed(obj_type_status); #+END_SRC ****** catch misc +block open+ #+name: abs_in_loop_body_open_block_obj #+BEGIN_SRC d if (line.matchFirst(rgx.block_poem_open)) { /+ poem to verse exceptions! +/ object_reset(an_object); processing.remove("verse"); obj_cite_number_poem["start"] = obj_cite_digits.on.to!string; } _start_block_(line, obj_type_status, 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:\n \"" ~ line ~ "\"" ); assert( (obj_type_status["blocks"] == TriState.off) || (obj_type_status["blocks"] == TriState.closing), "code block status: none or closed" ); if (obj_type_status["blocks"] == TriState.closing) { debug(check) { // block writeln(__LINE__); writeln(line); } assert( line.matchFirst(rgx.book_index) || line.matchFirst(rgx.book_index_open) || obj_type_status["book_index"] == State.on, "\nblocks closed, unless followed by book index, non-matching line:\n \"" ~ line ~ "\"" ); } #+END_SRC ******* book index :bookindex: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d if (line.matchFirst(rgx.book_index) || line.matchFirst(rgx.book_index_open) || obj_type_status["book_index"] == State.on ) { /+ book_index +/ _book_index_(line, book_idx_tmp, an_object, obj_type_status, opt_action); #+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.of_part = "comment"; // breaks flow comp_obj_comment.of_section = "comment"; // breaks flow 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, obj_type_status); processing.remove("verse"); ++cntr; #+END_SRC ******** flag !set & line !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)) && ((obj_type_status["para"] == State.off) && (obj_type_status["heading"] == State.off))) { /+ heading or para but neither flag nor line exists +/ if ((conf_make_meta.make.headings.length > 2) && (obj_type_status["make_headings"] == State.off)) { /+ heading found +/ _heading_found_(line, conf_make_meta.make.headings, heading_match_str, heading_match_rgx, obj_type_status); } if ((obj_type_status["make_headings"] == State.on) && ((line_occur["para"] == State.off) && (line_occur["heading"] == State.off)) && ((obj_type_status["para"] == State.off) && (obj_type_status["heading"] == State.off))) { /+ heading make set +/ line = _heading_make_set_(line, line_occur, heading_match_rgx, obj_type_status); } /+ TODO node info: all headings identified at this point, - extract node info here?? - how long can it wait? - should be incorporated in composite objects - should happen before endnote links set (they need to be moved down?) +/ if (line.matchFirst(rgx.heading)) { /+ heading match +/ line = _doc_header_and_make_substitutions_(line, conf_make_meta); _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, obj_type_status, conf_make_meta); } else if (line_occur["para"] == State.off) { /+ para match +/ an_object_key="body_nugget"; line = _doc_header_and_make_substitutions_(line, conf_make_meta); line = _doc_header_and_make_substitutions_fontface_(line, conf_make_meta); _para_match_(line, an_object, an_object_key, indent, bullet, obj_type_status, 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(an_object_key, "-> ", line); } line = _doc_header_and_make_substitutions_(line, conf_make_meta); line = _doc_header_and_make_substitutions_fontface_(line, conf_make_meta); 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_( bookindex_extract_hash, line, an_object, the_document_body_section, bookindex_unordered_hashes, obj_cite_digits, comp_obj_heading, cntr, obj_type_status, obj_cite_number_poem, conf_make_meta, ); #+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, "\nline should be empty:\n \"" ~ line ~ "\"" ); assert( (obj_type_status["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 ((obj_type_status["heading"] == State.on) && (line_occur["heading"] > State.off)) { /+ heading object (current line empty) +/ obj_cite_digits = (an_object["lev_markup_number"].to!int == 0) ? ocn_emit(OCNstatus.reset) : ocn_emit(OCNstatus.on); // : ocn_emit(obj_type_status["ocn_status"]); an_object["is"] = "heading"; an_object_key="body_nugget"; auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[sObj.content]; anchor_tags = substantive_object_and_anchor_tags_tuple[sObj.anchor_tags]; if (an_object["lev_markup_number"].to!int == 4) { segment_anchor_tag_that_object_belongs_to = anchor_tags[0]; segment_anchor_tag_that_object_belongs_to_uri = anchor_tags[0] ~ ".fnSuffix"; anchor_tag_ = anchor_tags[0]; } else if (an_object["lev_markup_number"].to!int > 4) { segment_anchor_tag_that_object_belongs_to = anchor_tag_; segment_anchor_tag_that_object_belongs_to_uri = anchor_tag_ ~ ".fnSuffix#" ~ obj_cite_digits.on.to!string; } else if (an_object["lev_markup_number"].to!int < 4) { string segn; switch (an_object["lev_markup_number"].to!int) { case 0: segn = "_the_title"; goto default; case 1: segn = "_part_" ~ cnt1.to!string; ++cnt1; goto default; case 2: segn = "_part_" ~ cnt1.to!string ~ "_" ~ cnt2.to!string; ++cnt2; goto default; case 3: segn = "_part_" ~ cnt1.to!string ~ "_" ~ cnt2.to!string ~ "_" ~ cnt3.to!string; ++cnt3; goto default; default: segment_anchor_tag_that_object_belongs_to = segn; segment_anchor_tag_that_object_belongs_to_uri = segn ~ ".fnSuffix"; break; } } an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_digits, segment_anchor_tag_that_object_belongs_to); /+ (incrementally build toc) table of contents here! +/ _anchor_tag=to!string(obj_cite_digits.on); the_table_of_contents_section = obj_im.table_of_contents_gather_headings( an_object, conf_make_meta, 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_digits, // OCNset cntr, // int heading_ptr, // int lv_ancestors_txt, // string[] an_object["is"], // string html_segnames_ptr, // int substantive_object_and_anchor_tags_tuple[sObj.notes_reg], substantive_object_and_anchor_tags_tuple[sObj.notes_star], substantive_object_and_anchor_tags_tuple[sObj.links], ); ++heading_ptr; debug(segments) { writeln(an_object["lev_markup_number"]); writeln(segment_anchor_tag_that_object_belongs_to); } the_document_body_section ~= comp_obj_heading; debug(objectrelated1) { // check writeln(line); } _common_reset_(line_occur, an_object, obj_type_status); 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 ((obj_type_status["para"] == State.on) && (line_occur["para"] > State.off)) { /+ paragraph object (current line empty) +/ obj_cite_digits = ocn_emit(obj_type_status["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_digits, segment_anchor_tag_that_object_belongs_to); an_object["is"] = "para"; auto comp_obj_heading = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_digits, cntr, heading_ptr-1, an_object["is"], ); auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_para = comp_obj_para.init; comp_obj_para.of_part = "body"; comp_obj_para.of_section = "body"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "para"; comp_obj_para.text = an_object["substantive"].to!string.strip; comp_obj_para.ocn = obj_cite_digits.digit; comp_obj_para.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_para.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_para.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_para.obj_cite_number_type = obj_cite_digits.type; comp_obj_para.indent_hang = indent["hang_position"]; comp_obj_para.indent_base = indent["base_position"]; comp_obj_para.bullet = bullet; comp_obj_para.anchor_tags = anchor_tags; comp_obj_para.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_para.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_para.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_para; _common_reset_(line_occur, an_object, obj_type_status); indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; processing.remove("verse"); ++cntr; } else { // could be useful to test line variable should be empty and never null } #+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 == "quote") || (the_document_body_section[$-1].is_a == "group") || (the_document_body_section[$-1].is_a == "block") || (the_document_body_section[$-1].is_a == "verse")) && (the_document_body_section.length > previous_length)) { if ((the_document_body_section[$-1].is_a == "heading") && (the_document_body_section[$-1].heading_lev_markup < 5)) { obj_type_status["biblio_section"] = State.off; obj_type_status["glossary_section"] = State.off; obj_type_status["blurb_section"] = State.off; } if (the_document_body_section[$-1].is_a == "verse") { /+ scan for endnotes for whole poem (each verse in poem) +/ foreach (i; previous_length .. the_document_body_section.length) { if (the_document_body_section[i].is_a == "verse") { if ((the_document_body_section[i].text).match( rgx.inline_notes_delimiter_al_regular_number_note )) { note_section.gather_notes_for_endnote_section( the_document_body_section, segment_anchor_tag_that_object_belongs_to, (i).to!int, ); } } } } else { /+ scan object for endnotes +/ previous_length = the_document_body_section.length.to!int; if ((the_document_body_section[$-1].text).match( rgx.inline_notes_delimiter_al_regular_number_note )) { previous_count=(the_document_body_section.length -1).to!int; note_section.gather_notes_for_endnote_section( the_document_body_section, segment_anchor_tag_that_object_belongs_to, (the_document_body_section.length-1).to!int, ); } } previous_length = the_document_body_section.length.to!int; } } #+END_SRC ** 3. _post main-loop processing_ :post: *** misc /+ 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_digits, opt_action); static assert(!isTypeTuple!(en_tuple)); auto the_endnotes_section = en_tuple[0]; obj_cite_digits = 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_.of_part = "empty"; comp_obj_heading_.of_section = "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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; 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_.of_part = "backmatter"; comp_obj_heading_.of_section = "bibliography"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.segment_anchor_tag = "_part_bibliography"; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_bibliography_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "backmatter"; comp_obj_heading_.of_section = "bibliography"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; 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_.of_part = "empty"; comp_obj_heading_.of_section = "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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; 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.of_part = "backmatter"; comp_obj_para.of_section = "bibliography"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "bibliography"; comp_obj_para.text = out_.to!string.strip; comp_obj_para.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.obj_cite_number_off = ""; comp_obj_para.obj_cite_number_type = 0; 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_digits, opt_action, ); destroy(bookindex_unordered_hashes); static assert(!isTypeTuple!(bi_tuple)); auto the_bookindex_section = bi_tuple[0]; obj_cite_digits = 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_.of_part = "empty"; comp_obj_heading_.of_section = "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_para.obj_cite_number_off = ""; comp_obj_para.obj_cite_number_type = 0; 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.of_part = "frontmatter"; comp_obj_toc.of_section = "toc"; 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.obj_cite_number_off = ""; comp_obj_toc.obj_cite_number_type = 0; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.bullet = false; if (the_endnotes_section.length > 1) { toc_txt_ = format( "{ %s }%s%s%s", "Endnotes", mkup.mark_internal_site_lnk, "endnotes", // segment_anchor_tag_that_object_belongs_to ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; } if (the_glossary_section.length > 1) { toc_txt_ = format( "{ %s }%s%s%s", "Glossary", mkup.mark_internal_site_lnk, "glossary", // segment_anchor_tag_that_object_belongs_to ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Glossary", "glossary", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } if (the_bibliography_section.length > 1){ toc_txt_ = format( "{ %s }%s%s%s", "Bibliography", mkup.mark_internal_site_lnk, "bibliography", // segment_anchor_tag_that_object_belongs_to ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Bibliography", "bibliography", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } if (the_bookindex_section["seg"].length > 1) { toc_txt_ = format( "{ %s }%s%s%s", "Book Index", mkup.mark_internal_site_lnk, "bookindex", // segment_anchor_tag_that_object_belongs_to ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; } if (the_bookindex_section["scroll"].length > 1) { toc_txt_ = format( "{ %s }#%s", "Book Index", "bookindex", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } if (the_blurb_section.length > 1) { toc_txt_ = format( "{ %s }%s%s%s", "Blurb", mkup.mark_internal_site_lnk, "blurb", // segment_anchor_tag_that_object_belongs_to ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Blurb", "blurb", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.inline_links = true; comp_obj_toc.text = toc_txt_.to!string.strip; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } debug(toc) { writefln( "%s %s", __LINE__, the_table_of_contents_section["seg"].length ); foreach (toc_linked_heading; the_table_of_contents_section["seg"]) { writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text); } } debug(tocscroll) { writefln( "%s %s", __LINE__, the_table_of_contents_section["seg"].length ); foreach (toc_linked_heading; the_table_of_contents_section["scroll"]) { writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text); } } #+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 *** _post main-loop loops_ :post: **** 1. _loop backmatter:_ loop up to lev4, extract html_segnames, set pointers this extra loop is needed to determine pre and (in particular) next segment for html, that is then used in a subsequent loop 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 - could optimise a bit by - skipping second (and third) loop unless the html seg or epub output is selected ***** section: endnotes #+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++; } #+END_SRC ***** section: glossary #+name: abs_post #+BEGIN_SRC d 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++; } #+END_SRC ***** section: bibliography #+name: abs_post #+BEGIN_SRC d 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++; } #+END_SRC ***** section: book index #+name: abs_post #+BEGIN_SRC d 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++; } #+END_SRC ***** section: blurb #+name: abs_post #+BEGIN_SRC d 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:_ encode _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 - ancestors could be determined earlier, but convenient to have here - descendants could be in the form of: headings contained under current heading, and/or; the range of objects under the current heading - you could decide on a sequential object list, containing all objects (both substantive and non-substantive objects), in addition to ocn, which are for substantive/ citable objects within the document (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 ***** images #+name: abs_post #+BEGIN_SRC d string[] _images; auto extract_images(S)(S content_block) { string[] images_; if (auto m = content_block.matchAll(rgx.image)) { images_ ~= m.captures[1]; } return images_; } string[] segnames_0_4; #+END_SRC ***** section: head #+name: abs_post #+BEGIN_SRC d foreach (ref obj; the_document_head_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; } if (obj.heading_lev_markup == 0) { /+ TODO second hit (of two) with same assertion failure, check, fix and reinstate assert( obj.ocn == 1, "Title OCN should be 1 not: " ~ obj.ocn.to!string); // bug introduced 0.18.1 +/ obj.ocn = 1; obj.obj_cite_number = "1"; obj.obj_cite_number_type = OCNtype.ocn; } /+ dom structure (marked up & collapsed) +/ if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub) || (opt_action.sqlite_discrete) || (opt_action.sqlite_update) || (opt_action.postgresql)) { obj = obj_dom_structure_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } } #+END_SRC ***** section: toc #+name: abs_post #+BEGIN_SRC d if (the_table_of_contents_section["scroll"].length > 1) { /+ scroll +/ dom_markedup_buffer = dom_markedup.dup; dom_collapsed_buffer = dom_collapsed.dup; foreach (ref obj; the_table_of_contents_section["scroll"]) { if (obj.is_a == "heading") { if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames], obj.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr_html_segnames]); } } /+ dom structure (marked up & collapsed) +/ if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub) || (opt_action.sqlite_discrete) || (opt_action.sqlite_update) || (opt_action.postgresql)) { obj = obj_dom_structure_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } } /+ seg +/ dom_markedup = dom_markedup_buffer.dup; dom_collapsed = dom_collapsed_buffer.dup; foreach (ref obj; the_table_of_contents_section["seg"]) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames], obj.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr_html_segnames]); } } if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub)) { obj = obj_dom_structure_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } } } #+END_SRC ***** section: document body #+name: abs_post #+BEGIN_SRC d /+ multiple 1~ levels, loop through document body +/ if (the_document_body_section.length > 1) { foreach (ref obj; the_document_body_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.lev4_subtoc = lev4_subtoc[obj.segment_anchor_tag]; obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames], obj.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr_html_segnames]); } } /+ dom structure (marked up & collapsed) +/ if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub) || (opt_action.sqlite_discrete) || (opt_action.sqlite_update) || (opt_action.postgresql)) { obj = obj_dom_structure_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.is_a == "para") { _images ~= extract_images(obj.text); } } } auto images=uniq(_images.sort()); #+END_SRC ***** section: endnotes #+name: abs_post #+BEGIN_SRC d /+ 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); } obj_cite_digits = ocn_emit(OCNstatus.on); obj.ocn = obj_cite_digits.digit; obj.obj_cite_number = obj_cite_digits.on.to!string; if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames], obj.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr_html_segnames]); } } /+ dom structure (marked up & collapsed) +/ if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub) || (opt_action.sqlite_discrete) || (opt_action.sqlite_update) || (opt_action.postgresql)) { obj = obj_dom_structure_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } } } #+END_SRC ***** section: glossary #+name: abs_post #+BEGIN_SRC d /+ 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); } obj_cite_digits = ocn_emit(OCNstatus.on); obj.ocn = obj_cite_digits.digit; obj.obj_cite_number = obj_cite_digits.on.to!string; if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames], obj.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr_html_segnames]); } } /+ dom structure (marked up & collapsed) +/ if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub) || (opt_action.sqlite_discrete) || (opt_action.sqlite_update) || (opt_action.postgresql)) { obj = obj_dom_structure_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.is_a == "glossary") { obj_cite_digits = ocn_emit(OCNstatus.on); obj.ocn = obj_cite_digits.digit; obj.obj_cite_number = obj_cite_digits.on.to!string; } } } #+END_SRC ***** section: bibliography #+name: abs_post #+BEGIN_SRC d /+ 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); } obj_cite_digits = ocn_emit(OCNstatus.on); obj.ocn = obj_cite_digits.digit; obj.obj_cite_number = obj_cite_digits.on.to!string; // check if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames], obj.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr_html_segnames]); } } /+ dom structure (marked up & collapsed) +/ if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub) || (opt_action.sqlite_discrete) || (opt_action.sqlite_update) || (opt_action.postgresql)) { obj = obj_dom_structure_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.is_a == "bibliography") { obj_cite_digits = ocn_emit(OCNstatus.on); obj.ocn = obj_cite_digits.on; obj.obj_cite_number = obj_cite_digits.on.to!string; } } } #+END_SRC ***** section: book index (scroll, seg) #+name: abs_post #+BEGIN_SRC d /+ optional only one 1~ level +/ int ocn_ = obj_cite_digits.on; int ocn_bkidx_ = 0; int ocn_bidx_; if (the_bookindex_section["scroll"].length > 1) { /+ scroll +/ dom_markedup_buffer = dom_markedup.dup; dom_collapsed_buffer = dom_collapsed.dup; foreach (ref obj; the_bookindex_section["scroll"]) { if (obj.is_a == "heading") { debug(dom) { } obj_cite_digits = ocn_emit(OCNstatus.on); obj.ocn = obj_cite_digits.on; obj.obj_cite_number = obj_cite_digits.on.to!string; if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames], obj.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr_html_segnames]); } } /+ dom structure (marked up & collapsed) +/ if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub) || (opt_action.sqlite_discrete) || (opt_action.sqlite_update) || (opt_action.postgresql)) { obj = obj_dom_structure_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.is_a == "bookindex") { obj_cite_digits = ocn_emit(OCNstatus.bkidx); obj.ocn = obj_cite_digits.digit; obj.obj_cite_number_bkidx = obj_cite_digits.bkidx.to!string; obj.obj_cite_number_type = OCNtype.bkidx; } } /+ seg +/ dom_markedup = dom_markedup_buffer.dup; dom_collapsed = dom_collapsed_buffer.dup; foreach (ref obj; the_bookindex_section["seg"]) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } obj.ocn = ++ocn_; obj.obj_cite_number = obj.ocn.to!string; if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames], obj.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr_html_segnames]); } } /+ dom structure (marked up & collapsed) +/ if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub) || (opt_action.sqlite_discrete) || (opt_action.sqlite_update) || (opt_action.postgresql)) { obj = obj_dom_structure_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.is_a == "bookindex") { ocn_bidx_ = ++ocn_bkidx_; obj.obj_cite_number_bkidx = ocn_bidx_.to!string; // FIX need to distinguish from regular ocn obj.obj_cite_number_type = OCNtype.bkidx; } } /+ TODO assert failure, reinstate assert(obj_cite_digit_bkidx == ocn_bidx_ obj_cite_digit_bkidx ~ " == ocn_" ~ ocn_ ~ "?"); +/ } #+END_SRC ***** section: blurb #+name: abs_post #+BEGIN_SRC d /+ 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); } obj_cite_digits = ocn_emit(OCNstatus.on); obj.ocn = obj_cite_digits.on; obj.obj_cite_number = obj_cite_digits.on.to!string; if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames], obj.segment_anchor_tag ~ "!=" ~ html_segnames[obj.ptr_html_segnames]); } } /+ dom structure (marked up & collapsed) +/ if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub) || (opt_action.sqlite_discrete) || (opt_action.sqlite_update) || (opt_action.postgresql)) { obj = obj_dom_structure_set_markup_tags(obj, dom_markedup, obj.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_collapsed, obj.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.is_a == "blurb") { obj_cite_digits = ocn_emit(OCNstatus.off); obj.obj_cite_number_off = obj_cite_digits.off.to!string; obj.obj_cite_number_type = OCNtype.non; } } } #+END_SRC **** TODO update BUG? #+name: abs_post #+BEGIN_SRC d /+ TODO - note create/insert heading object sole purpose eof close all open tags sort out: - obj.dom_markedup = dom_markedup; - obj.dom_collapsed = dom_collapsed; +/ comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "empty"; comp_obj_heading_.of_section = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.obj_cite_number_off = ""; comp_obj_para.obj_cite_number_type = 0; 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; comp_obj_heading_ = obj_dom_structure_set_markup_tags(comp_obj_heading_, dom_markedup, 0); comp_obj_heading_ = obj_dom_set_collapsed_tags(comp_obj_heading_, dom_collapsed, 0); comp_obj_heading_ = obj_heading_ancestors(comp_obj_heading_, lv_ancestors_txt); // the_dom_tail_section ~= comp_obj_heading_; // remove tail for now, decide on later #+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",], "sql": ["head", "body",] ]; if (document_the["endnotes"].length > 1) { document_section_keys_sequenced["seg"] ~= "endnotes"; document_section_keys_sequenced["scroll"] ~= "endnotes"; } if (document_the["glossary"].length > 1) { document_section_keys_sequenced["seg"] ~= "glossary"; document_section_keys_sequenced["scroll"] ~= "glossary"; document_section_keys_sequenced["sql"] ~= "glossary"; } if (document_the["bibliography"].length > 1) { document_section_keys_sequenced["seg"] ~= "bibliography"; document_section_keys_sequenced["scroll"] ~= "bibliography"; document_section_keys_sequenced["sql"] ~= "bibliography"; } if (document_the["bookindex_seg"].length > 1) { document_section_keys_sequenced["seg"] ~= "bookindex_seg"; document_section_keys_sequenced["sql"] ~= "bookindex_seg"; } if (document_the["bookindex_scroll"].length > 1) { document_section_keys_sequenced["scroll"] ~= "bookindex_scroll"; } if (document_the["blurb"].length > 1) { document_section_keys_sequenced["seg"] ~= "blurb"; document_section_keys_sequenced["scroll"] ~= "blurb"; document_section_keys_sequenced["sql"] ~= "blurb"; } if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub)) { document_section_keys_sequenced["seg"] ~= "tail"; document_section_keys_sequenced["scroll"] ~= "tail"; } #+END_SRC *** dup #+name: abs_post #+BEGIN_SRC d auto segnames = html_segnames.dup; #+END_SRC *** clean out structure #+name: abs_post #+BEGIN_SRC d destroy(the_document_head_section); destroy(the_table_of_contents_section); destroy(the_document_body_section); destroy(the_endnotes_section); destroy(the_glossary_section); destroy(the_bibliography_section); destroy(the_bookindex_section); destroy(the_blurb_section); destroy(html_segnames); destroy(bookindex_unordered_hashes); destroy(an_object); biblio_arr_json = []; obj_cite_digits=ocn_emit(OCNstatus.reset); obj_cite_digit_=0; html_segnames_ptr=0; html_segnames_ptr_cntr=0; content_non_header = "8"; dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; #+END_SRC *** [#A] _return document tuple_ :return:tuple: #+name: abs_post #+BEGIN_SRC d auto t = tuple( document_the, docSectKeysSeq!()(document_section_keys_sequenced), segnames, segnames_0_4, 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 static auto object_reset(O)(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"); return an_object; } #+END_SRC **** set, initialize or re-initialize :set: #+name: abs_functions_header_set_common #+BEGIN_SRC d auto _common_reset_(L,O,T)( return ref L line_occur, return ref O an_object, return ref T obj_type_status ) { debug(asserts) { static assert(is(typeof(line_occur) == int[string])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(obj_type_status) == int[string])); } line_occur["heading"] = State.off; line_occur["para"] = State.off; obj_type_status["heading"] = State.off; obj_type_status["para"] = State.off; an_object = object_reset(an_object); } #+END_SRC *** check obj_cite_number status in document :ocn: #+name: abs_functions_ocn_status #+BEGIN_SRC d static auto _check_ocn_status_(L,T)( L line, T obj_type_status ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(obj_type_status) == int[string])); } static auto rgx = Rgx(); if ((!line.empty) && (obj_type_status["ocn_status_off_for_multiple_objects"] == TriState.off)) { /+ not multi-line object, check whether obj_cite_number is on or turned off +/ if (line.matchFirst(rgx.obj_cite_number_block_marks)) { /+ switch off obj_cite_number +/ if (line.matchFirst(rgx.obj_cite_number_off_block)) { obj_type_status["ocn_status_off_for_multiple_objects"] = TriState.on; debug(ocnoff) { writeln(line); } } if (line.matchFirst(rgx.obj_cite_number_off_block_dh)) { obj_type_status["ocn_status_off_for_multiple_objects"] = TriState.closing; debug(ocnoff) { writeln(line); } } } else { if (obj_type_status["ocn_status_off_for_multiple_objects"] == TriState.off) { if (line.matchFirst(rgx.obj_cite_number_off)) { obj_type_status["ocn_status"] = OCNstatus.off; } else if (line.matchFirst(rgx.obj_cite_number_off_dh)) { obj_type_status["ocn_status"] = OCNstatus.closing; } else { obj_type_status["ocn_status"] = OCNstatus.on; } } else { obj_type_status["ocn_status"] = obj_type_status["ocn_status_off_for_multiple_objects"]; } } } else if ((!line.empty) && (obj_type_status["ocn_status_off_for_multiple_objects"] > TriState.off)) { if (line.matchFirst(rgx.obj_cite_number_off_block_close)) { obj_type_status["ocn_status_off_for_multiple_objects"] = TriState.off; obj_type_status["ocn_status"] = OCNstatus.on; debug(ocnoff) { writeln(line); } } } return obj_type_status; } #+END_SRC *** make substitutions **** project #+name: abs_functions_substitutions #+BEGIN_SRC d auto _doc_header_and_make_substitutions_(L,CMM)( L line, CMM conf_make_meta, ) { debug(asserts) { static assert(is(typeof(line) == char[])); } enum Substitute { match, markup, } if (conf_make_meta.make.substitute) { foreach(substitution_pair; conf_make_meta.make.substitute) { line = line.replaceAll( regex(substitution_pair[Substitute.match]), substitution_pair[Substitute.markup] ); } } return line; } #+END_SRC **** fontface #+name: abs_functions_substitutions #+BEGIN_SRC d auto _doc_header_and_make_substitutions_fontface_(L,CMM)( L line, CMM conf_make_meta, ) { debug(asserts) { static assert(is(typeof(line) == char[])); } enum Substitute { match, markup, } if ( conf_make_meta.make.bold) { line = line.replaceAll( regex(conf_make_meta.make.bold[Substitute.match]), conf_make_meta.make.bold[Substitute.markup] ); } if (conf_make_meta.make.emphasis) { line = line.replaceAll( regex(conf_make_meta.make.emphasis[Substitute.match]), conf_make_meta.make.emphasis[Substitute.markup] ); } if (conf_make_meta.make.italics) { line = line.replaceAll( regex(conf_make_meta.make.italics[Substitute.match]), conf_make_meta.make.italics[Substitute.markup] ); } return line; } #+END_SRC *** block :block: **** block start (open) block :start: ***** { block starts function #+name: abs_functions_block #+BEGIN_SRC d void _start_block_(L,T,N)( L line, return ref T obj_type_status, return ref N obj_cite_number_poem ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(obj_type_status) == 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 static auto rgx = Rgx(); string code_block_syntax = ""; bool code_block_numbered = false; if (auto m = line.matchFirst(rgx.block_curly_code_open)) { /+ curly code open +/ code_block_syntax = (m.captures[1]) ? m.captures[1].to!string : ""; code_block_numbered = (m.captures[2] == "#") ? true : false; debug(code) { // code (curly) open writefln( "* [code curly] %s", line ); } obj_type_status["blocks"] = TriState.on; obj_type_status["code"] = TriState.on; obj_type_status["curly_code"] = TriState.on; } else if (line.matchFirst(rgx.block_curly_poem_open)) { /+ curly poem open +/ debug(poem) { // poem (curly) open writefln( "* [poem curly] %s", line ); } obj_cite_number_poem["start"] = obj_cite_digits.on.to!string; obj_type_status["blocks"] = TriState.on; obj_type_status["verse_new"] = State.on; obj_type_status["poem"] = TriState.on; obj_type_status["curly_poem"] = TriState.on; } else if (line.matchFirst(rgx.block_curly_group_open)) { /+ curly group open +/ debug(group) { // group (curly) open writefln( "* [group curly] %s", line ); } obj_type_status["blocks"] = TriState.on; obj_type_status["group"] = TriState.on; obj_type_status["curly_group"] = TriState.on; } else if (line.matchFirst(rgx.block_curly_block_open)) { /+ curly block open +/ debug(block) { // block (curly) open writefln( "* [block curly] %s", line ); } obj_type_status["blocks"] = TriState.on; obj_type_status["block"] = TriState.on; obj_type_status["curly_block"] = TriState.on; } else if (line.matchFirst(rgx.block_curly_quote_open)) { /+ curly quote open +/ debug(quote) { // quote (curly) open writefln( "* [quote curly] %s", line ); } obj_type_status["blocks"] = TriState.on; obj_type_status["quote"] = TriState.on; obj_type_status["curly_quote"] = TriState.on; } else if (auto m = line.matchFirst(rgx.block_curly_table_open)) { /+ curly table open +/ debug(table) { // table (curly) open writefln( "* [table curly] %s", line ); } an_object["table_head"] = m.captures[1].to!string; an_object["block_type"] = "curly"; obj_type_status["blocks"] = TriState.on; obj_type_status["table"] = TriState.on; obj_type_status["curly_table"] = TriState.on; } else if (auto m = line.matchFirst(rgx.block_curly_table_special_markup)) { /+ table: special table block markup syntax! +/ an_object["table_head"] = m.captures[1].to!string; an_object["block_type"] = "special"; obj_type_status["blocks"] = TriState.on; obj_type_status["table"] = TriState.on; obj_type_status["curly_table_special_markup"] = TriState.on; #+END_SRC ****** block (various) tic open :tic: #+name: abs_functions_block #+BEGIN_SRC d } else if (auto m = line.matchFirst(rgx.block_tic_code_open)) { /+ tic code open +/ code_block_syntax = (m.captures[1]) ? m.captures[1].to!string : ""; code_block_numbered = (m.captures[2] == "#") ? true : false; debug(code) { // code (tic) open writefln( "* [code tic] %s", line ); } obj_type_status["blocks"] = TriState.on; obj_type_status["code"] = TriState.on; obj_type_status["tic_code"] = TriState.on; } else if (line.matchFirst(rgx.block_tic_poem_open)) { /+ tic poem open +/ debug(poem) { // poem (tic) open writefln( "* [poem tic] %s", line ); } obj_cite_number_poem["start"] = obj_cite_digits.on.to!string; obj_type_status["blocks"] = TriState.on; obj_type_status["verse_new"] = State.on; obj_type_status["poem"] = TriState.on; obj_type_status["tic_poem"] = TriState.on; } else if (line.matchFirst(rgx.block_tic_group_open)) { /+ tic group open +/ debug(group) { // group (tic) open writefln( "* [group tic] %s", line ); } obj_type_status["blocks"] = TriState.on; obj_type_status["group"] = TriState.on; obj_type_status["tic_group"] = TriState.on; } else if (line.matchFirst(rgx.block_tic_block_open)) { /+ tic block open +/ debug(block) { // block (tic) open writefln( "* [block tic] %s", line ); } obj_type_status["blocks"] = TriState.on; obj_type_status["block"] = TriState.on; obj_type_status["tic_block"] = TriState.on; } else if (line.matchFirst(rgx.block_tic_quote_open)) { /+ tic quote open +/ debug(quote) { // quote (tic) open writefln( "* [quote tic] %s", line ); } obj_type_status["blocks"] = TriState.on; obj_type_status["quote"] = TriState.on; obj_type_status["tic_quote"] = TriState.on; } else if (auto m = line.matchFirst(rgx.block_tic_table_open)) { /+ tic table open +/ debug(table) { // table (tic) open writefln( "* [table tic] %s", line ); } an_object["table_head"] = m.captures[1].to!string; an_object["block_type"] = "tic"; obj_type_status["blocks"] = TriState.on; obj_type_status["table"] = TriState.on; obj_type_status["tic_table"] = TriState.on; } #+END_SRC ***** } #+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)( L line, return ref O an_object, return ref T obj_type_status ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(obj_type_status) == int[string])); } static auto rgx = Rgx(); if (obj_type_status["curly_code"] == TriState.on) { if (line.matchFirst(rgx.block_curly_code_close)) { debug(code) { // code (curly) close writeln(line); } an_object[an_object_key] = an_object[an_object_key] .replaceFirst(rgx.newline_eol_delimiter_only, "") .stripRight; obj_type_status["blocks"] = TriState.closing; obj_type_status["code"] = TriState.closing; obj_type_status["curly_code"] = TriState.off; } else { debug(code) { // code (curly) line writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // code (curly) line } } else if (obj_type_status["tic_code"] == TriState.on) { if (line.matchFirst(rgx.block_tic_close)) { debug(code) { // code (tic) close writeln(line); } an_object[an_object_key] = an_object[an_object_key] .replaceFirst(rgx.newline_eol_delimiter_only, "") .stripRight; obj_type_status["blocks"] = TriState.closing; obj_type_status["code"] = TriState.closing; obj_type_status["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, return ref int[string] obj_type_status, return ref int bib_entry, return ref string biblio_entry_str_json, return ref string[] biblio_arr_json ) { mixin SiSUbiblio; auto jsn = BibJsnStr(); static auto rgx = Rgx(); if (line.matchFirst(rgx.heading_biblio)) { obj_type_status["biblio_section"] = TriState.on; obj_type_status["blurb_section"] = State.off; obj_type_status["glossary_section"] = State.off; } if (line.empty) { debug { debug(biblioblock) { writeln("---"); } debug(biblioblockinclude) { writeln(biblio_entry_str_json.length); } } if ((bib_entry == State.off) && (biblio_entry_str_json.empty)) { bib_entry = State.on; biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr; } else if (!(biblio_entry_str_json.empty)) { bib_entry = State.off; if (!(biblio_entry_str_json == jsn.biblio_entry_tags_jsonstr)) { auto biblio_entry = parseJSON(biblio_entry_str_json); if (biblio_entry["fulltitle"].str.empty) { writeln("check problem entry (Title missing): ", biblio_entry_str_json); } else if ((biblio_entry["author_raw"].str.empty) && (biblio_entry["editor_raw"].str.empty)) { writeln("check problem entry (No author and no editor): ", biblio_entry_str_json); } else { biblio_arr_json ~= biblio_entry_str_json; } biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr; } } else { // CHECK ERROR writeln("?? 2. ERROR ", biblio_entry_str_json, "??"); biblio_entry_str_json = ""; } } else if (line.matchFirst(rgx.biblio_tags)) { debug(biblioblock) { writeln(line); } auto bt = line.match(rgx.biblio_tags); bib_entry = State.off; st = bt.captures[1].to!string; auto header_tag_value=(bt.captures[2]).to!string; JSONValue j = parseJSON(biblio_entry_str_json); biblio_tag_name = (st.match(rgx.biblio_abbreviations)) ? (biblio_tag_map(st)) : st; j.object[biblio_tag_name] = header_tag_value; debug(bibliounsortedcheckduplicates) { writeln(biblio_tag_name, ": ", header_tag_value); writeln("--"); } switch (biblio_tag_name) { case "author_raw": // author_arr author (fn sn) j["author_arr"] = header_tag_value.split(rgx.arr_delimiter); string tmp; biblioAuthorLoop: foreach (au; j["author_arr"].array) { if (auto x = au.str.match(rgx.name_delimiter)) { tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", "; } else { tmp ~= au.str; } } tmp = (tmp).replace(rgx.trailing_comma, ""); j["author"].str = tmp; goto default; case "editor_raw": // editor_arr editor (fn sn) j["editor_arr"] = header_tag_value.split(rgx.arr_delimiter); string tmp; biblioEditorLoop: foreach (ed; j["editor_arr"].array) { if (auto x = ed.str.match(rgx.name_delimiter)) { tmp ~= x.captures[2] ~ " " ~ x.captures[1] ~ ", "; } else { tmp ~= ed.str; } } tmp = (tmp).replace(rgx.trailing_comma, ""); j["editor"].str = tmp; goto default; case "fulltitle": // title & subtitle goto default; default: break; } auto s = j.toString(); debug(biblio1) { writefln( "* %s: %s\n%s", biblio_tag_name, biblio_tag_entry, j[biblio_tag_name] ); } if (line.match(rgx.comment)) { writeln("ERROR", line, "COMMENT"); writeln("ERROR", s, "%%"); } if (!(match(line, rgx.comment))) { debug(biblioblockinclude) { writeln(line); } biblio_entry_str_json = s; } else { biblio_entry_str_json = ""; } header_tag_value=""; } } #+END_SRC ***** quote block :quote: #+name: abs_functions_block_quote #+BEGIN_SRC d void _quote_block_(L,O,T)( L line, return ref O an_object, return ref T obj_type_status ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(obj_type_status) == int[string])); } static auto rgx = Rgx(); if (obj_type_status["curly_quote"] == TriState.on) { if (line.matchFirst(rgx.block_curly_quote_close)) { debug(quote) { // quote (curly) close writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; obj_type_status["blocks"] = TriState.closing; obj_type_status["quote"] = TriState.closing; obj_type_status["curly_quote"] = TriState.off; } else { debug(quote) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build quote array (or string) } } else if (obj_type_status["tic_quote"] == TriState.on) { if (line.matchFirst(rgx.block_tic_close)) { debug(quote) { // quote (tic) close writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; obj_type_status["blocks"] = TriState.closing; obj_type_status["quote"] = TriState.closing; obj_type_status["tic_quote"] = TriState.off; } else { debug(quote) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build quote array (or string) } } } #+END_SRC ***** group block :group: - apply inline markup - discard leading and newline whitespace #+name: abs_functions_block_group #+BEGIN_SRC d void _group_block_(L,O,T)( L line, return ref O an_object, return ref T obj_type_status ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(obj_type_status) == int[string])); } static auto rgx = Rgx(); if (obj_type_status["curly_group"] == State.on) { if (line.matchFirst(rgx.block_curly_group_close)) { debug(group) { writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; obj_type_status["blocks"] = TriState.closing; obj_type_status["group"] = TriState.closing; obj_type_status["curly_group"] = TriState.off; } else { debug(group) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build group array (or string) } } else if (obj_type_status["tic_group"] == TriState.on) { if (line.matchFirst(rgx.block_tic_close)) { debug(group) { writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; obj_type_status["blocks"] = TriState.closing; obj_type_status["group"] = TriState.closing; obj_type_status["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: - apply inline markup - keep whitespace indentation - keep newlines #+name: abs_functions_block_block #+BEGIN_SRC d void _block_block_(L,O,T)( L line, return ref O an_object, return ref T obj_type_status ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(obj_type_status) == int[string])); } static auto rgx = Rgx(); if (obj_type_status["curly_block"] == TriState.on) { if (line.matchFirst(rgx.block_curly_block_close)) { debug(block) { // block (curly) close writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; obj_type_status["blocks"] = TriState.closing; obj_type_status["block"] = TriState.closing; obj_type_status["curly_block"] = TriState.off; } else { debug(block) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build block array (or string) } } else if (obj_type_status["tic_block"] == TriState.on) { if (line.matchFirst(rgx.block_tic_close)) { debug(block) { writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; obj_type_status["blocks"] = TriState.closing; obj_type_status["block"] = TriState.closing; obj_type_status["tic_block"] = TriState.off; } else { debug(block) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build block array (or string) } } } #+END_SRC ***** 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,CMM)( L line, return ref O an_object, return ref T obj_type_status, return ref C cntr, N obj_cite_number_poem, CMM conf_make_meta, ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(obj_type_status) == int[string])); static assert(is(typeof(cntr) == int)); static assert(is(typeof(obj_cite_number_poem) == string[string])); } static auto rgx = Rgx(); if (obj_type_status["curly_poem"] == TriState.on) { if (line.matchFirst(rgx.block_curly_poem_close)) { if (an_object_key in an_object || processing.length > 0) { an_object[an_object_key] = ""; debug(poem) { // poem (curly) close writefln( "* [poem curly] %s", line ); } if (processing.length > 0) { an_object[an_object_key] = processing["verse"]; } debug(poem) { // poem (curly) close writeln(__LINE__); writefln( "* %s %s", obj_cite_digits.on, line ); } if (an_object.length > 0) { debug(poem) { // poem (curly) close writeln( obj_cite_digits.on, an_object[an_object_key] ); } an_object["is"] = "verse"; auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.of_part = "body"; comp_obj_block.of_section = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_digits.on; comp_obj_block.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_block.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_block.obj_cite_number_type = obj_cite_digits.type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; } object_reset(an_object); processing.remove("verse"); ++cntr; } obj_cite_number_poem["end"] = obj_cite_digits.on.to!string; obj_type_status["blocks"] = TriState.closing; obj_type_status["poem"] = TriState.closing; obj_type_status["curly_poem"] = TriState.off; } else { processing["verse"] ~= line ~= "\n"; if (obj_type_status["verse_new"] == State.on) { obj_cite_digits = ocn_emit(OCNstatus.on); obj_type_status["verse_new"] = State.off; } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) { processing["verse"] = processing["verse"].stripRight; verse_line = TriState.off; obj_type_status["verse_new"] = State.on; } if (obj_type_status["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_digits.on, 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_digits, cntr, heading_ptr-1, an_object["is"] ); auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.of_part = "body"; comp_obj_block.of_section = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_digits.on; comp_obj_block.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_block.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_block.obj_cite_number_type = obj_cite_digits.type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; } } } else if (obj_type_status["tic_poem"] == TriState.on) { if (auto m = line.matchFirst(rgx.block_tic_close)) { // tic_poem_close an_object[an_object_key]="verse"; debug(poem) { // poem (curly) close writefln( "* [poem tic] %s", line ); } if (processing.length > 0) { an_object[an_object_key] = processing["verse"]; } if (an_object.length > 0) { debug(poem) { // poem (tic) close writeln(__LINE__); writeln(obj_cite_digits.on, line); } processing.remove("verse"); an_object["is"] = "verse"; auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.of_part = "body"; comp_obj_block.of_section = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_digits.on; comp_obj_block.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_block.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_block.obj_cite_number_type = obj_cite_digits.type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; obj_cite_number_poem["end"] = obj_cite_digits.on.to!string; object_reset(an_object); processing.remove("verse"); ++cntr; } obj_type_status["blocks"] = TriState.closing; obj_type_status["poem"] = TriState.closing; obj_type_status["tic_poem"] = TriState.off; } else { processing["verse"] ~= line ~= "\n"; if (obj_type_status["verse_new"] == State.on) { obj_cite_digits = ocn_emit(OCNstatus.on); obj_type_status["verse_new"] = State.off; } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) { processing["verse"] = processing["verse"].stripRight; obj_type_status["verse_new"] = State.on; verse_line = TriState.off; } if (obj_type_status["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_digits.on, 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_digits, cntr, heading_ptr-1, an_object["is"] ); auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.of_part = "body"; comp_obj_block.of_section = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_digits.on; comp_obj_block.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_block.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_block.obj_cite_number_type = obj_cite_digits.type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; } } } } #+END_SRC ***** table block :table: there are 3 types of table markup that need to be nomalized (given a single representation) here - curly brace block - tic block - special notation block you need: - identify the type for the munging to create uniform presentation - curly, tick, special - table heading row, bool - present table header info in uniform way - table_number_of_columns, int (count) - table_column_widths, int[] column widths (as given or calculate average) - show table walls, bool - table content marked up in uniform way #+name: abs_functions_block_table #+BEGIN_SRC d void _table_block_(L,O,T,CMM)( L line, return ref O an_object, return ref T obj_type_status, return ref CMM conf_make_meta, ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(obj_type_status) == int[string])); } static auto rgx = Rgx(); if (obj_type_status["curly_table"] == TriState.on) { if (line.matchFirst(rgx.block_curly_table_close)) { debug(table) { // table (curly) close writeln(line); } obj_type_status["blocks"] = TriState.closing; obj_type_status["table"] = TriState.closing; obj_type_status["curly_table"] = TriState.off; } else { debug(table) { // table writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build table array (or string) } } else if (obj_type_status["curly_table_special_markup"] == TriState.on) { if (line.empty) { obj_type_status["blocks"] = TriState.off; obj_type_status["table"] = TriState.off; obj_type_status["curly_table_special_markup"] = TriState.off; _table_closed_make_special_notation_table_( line, an_object, the_document_body_section, obj_cite_digits, comp_obj_heading, cntr, obj_type_status, conf_make_meta, ); } else { debug(table) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } else if (obj_type_status["tic_table"] == TriState.on) { if (line.matchFirst(rgx.block_tic_close)) { debug(table) { // table (tic) close writeln(line); } obj_type_status["blocks"] = TriState.closing; obj_type_status["table"] = TriState.closing; obj_type_status["tic_table"] = TriState.off; } else { debug(table) { // table writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build table array (or string) } } } #+END_SRC **** special table notation, make: table process and use an_object["table_head"] (then empty it) - present table header info in uniform way - table_number_of_columns, int (count) - table_column_widths, int[] column widths (as given or calculate average) - show table walls, bool #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d void _table_closed_make_special_notation_table_(N,CMM)( char[] line, return ref string[string] an_object, return ref ObjGenericComposite[] the_document_body_section, return ref N obj_cite_digits, return ref ObjGenericComposite _comp_obj_heading, return ref int cntr, return ref int[string] obj_type_status, CMM conf_make_meta ) { comp_obj_block = comp_obj_block.init; obj_cite_digits = ocn_emit(OCNstatus.on); auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_digits, cntr, heading_ptr-1, "table" ); an_object["is"] = "table"; auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, "body_nugget", conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; comp_obj_block.ocn = obj_cite_digits.on; comp_obj_block.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_block.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_block.obj_cite_number_type = obj_cite_digits.type; comp_obj_block = table_instructions(comp_obj_block, an_object["table_head"]); comp_obj_block = table_substantive_munge_special(comp_obj_block, an_object["substantive"]); the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; } #+END_SRC **** block end (close an open block): line empty, block flag _makes_ :close: ***** { line empty, _make block_ #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d void _block_flag_line_empty_(B,N,CMM)( B bookindex_extract_hash, char[] line, return ref string[string] an_object, return ref ObjGenericComposite[] the_document_body_section, return ref string[][string][string] bookindex_unordered_hashes, return ref N obj_cite_digits, return ref ObjGenericComposite _comp_obj_heading, return ref int cntr, return ref int[string] obj_type_status, string[string] obj_cite_number_poem, CMM conf_make_meta, ) { assert( line.empty, "\nline should be empty:\n \"" ~ line ~ "\"" ); assert( (obj_type_status["blocks"] == TriState.closing), "code block status: closed" ); assertions_flag_types_block_status_none_or_closed(obj_type_status); #+END_SRC ****** make: quote block #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d if (obj_type_status["quote"] == TriState.closing) { obj_cite_digits = ocn_emit(OCNstatus.on); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "quote"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.of_part = "body"; comp_obj_block.of_section = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "quote"; comp_obj_block.ocn = obj_cite_digits.on; comp_obj_block.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_block.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_block.obj_cite_number_type = obj_cite_digit_type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; obj_type_status["blocks"] = TriState.off; obj_type_status["quote"] = TriState.off; object_reset(an_object); processing.remove("verse"); ++cntr; #+END_SRC ****** make: group block #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d } else if (obj_type_status["group"] == TriState.closing) { obj_cite_digits = ocn_emit(OCNstatus.on); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "group"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.of_part = "body"; comp_obj_block.of_section = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "group"; comp_obj_block.ocn = obj_cite_digits.on; comp_obj_block.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_block.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_block.obj_cite_number_type = obj_cite_digits.type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; obj_type_status["blocks"] = TriState.off; obj_type_status["group"] = TriState.off; object_reset(an_object); processing.remove("verse"); ++cntr; #+END_SRC ****** make: block #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d } else if (obj_type_status["block"] == TriState.closing) { obj_cite_digits = ocn_emit(OCNstatus.on); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "block"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; comp_obj_block = comp_obj_block.init; comp_obj_block.of_part = "body"; comp_obj_block.of_section = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "block"; comp_obj_block.ocn = obj_cite_digits.on; comp_obj_block.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_block.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_block.obj_cite_number_type = obj_cite_digit_type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; obj_type_status["blocks"] = TriState.off; obj_type_status["block"] = TriState.off; object_reset(an_object); processing.remove("verse"); ++cntr; #+END_SRC ****** make: poem #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d } else if (obj_type_status["poem"] == TriState.closing) { an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "verse"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); comp_obj_poem_ocn = comp_obj_poem_ocn.init; comp_obj_poem_ocn.of_part = "body"; comp_obj_poem_ocn.of_section = "body"; comp_obj_poem_ocn.is_of = "block"; comp_obj_poem_ocn.is_a = "poem"; comp_obj_poem_ocn.ocn = obj_cite_digits.on; comp_obj_poem_ocn.obj_cite_number = (obj_cite_number_poem["start"] ~ "..." ~ obj_cite_number_poem["end"]); comp_obj_poem_ocn.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; // comp_obj_poem_ocn.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; // comp_obj_poem_ocn.obj_cite_number_type = obj_cite_digits.type; comp_obj_poem_ocn.text = ""; the_document_body_section ~= comp_obj_poem_ocn; obj_type_status["blocks"] = TriState.off; obj_type_status["poem"] = TriState.off; object_reset(an_object); processing.remove("verse"); #+END_SRC ****** make: code block #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d } else if (obj_type_status["code"] == TriState.closing) { obj_cite_digits = ocn_emit(OCNstatus.on); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "code"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_code = comp_obj_code.init; comp_obj_code.of_part = "body"; comp_obj_code.of_section = "body"; comp_obj_code.is_of = "block"; comp_obj_code.is_a = "code"; comp_obj_code.ocn = obj_cite_digits.on; comp_obj_code.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_block.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_block.obj_cite_number_type = obj_cite_digits.type; comp_obj_code.text = an_object["substantive"]; comp_obj_code.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_code.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_code.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_code; obj_type_status["blocks"] = TriState.off; obj_type_status["code"] = TriState.off; object_reset(an_object); processing.remove("verse"); ++cntr; #+END_SRC ****** make: table #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d } else if (obj_type_status["table"] == TriState.closing) { comp_obj_block = comp_obj_block.init; obj_cite_digits = ocn_emit(OCNstatus.on); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "table"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; comp_obj_block = comp_obj_block.init; comp_obj_block.ocn = obj_cite_digits.on; comp_obj_block.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; comp_obj_block.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.obj_cite_number_bkidx = (obj_cite_digits.bkidx==0) ? "" : obj_cite_digits.bkidx.to!string; comp_obj_block.obj_cite_number_type = obj_cite_digits.type; comp_obj_block = table_instructions(comp_obj_block, an_object["table_head"]); comp_obj_block = table_substantive_munge(comp_obj_block, an_object["substantive"]); the_document_body_section ~= comp_obj_block; obj_type_status["blocks"] = TriState.off; obj_type_status["table"] = TriState.off; object_reset(an_object); processing.remove("verse"); ++cntr; } #+END_SRC ***** } #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d } #+END_SRC *** book index :bookindex: #+name: abs_functions_book_index #+BEGIN_SRC d auto _book_index_(L,I,O,T,B)( L line, return ref I book_idx_tmp, return ref O an_object, return ref T obj_type_status, B opt_action, ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(book_idx_tmp) == string)); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(obj_type_status) == int[string])); } static auto rgx = Rgx(); if (auto m = line.match(rgx.book_index)) { /+ match book_index +/ debug(bookindexmatch) { // book index writefln( "* [bookindex] %s\n", m.captures[1].to!string, ); } an_object["bookindex_nugget"] = m.captures[1].to!string; } else if (auto m = line.match(rgx.book_index_open)) { /+ match open book_index +/ obj_type_status["book_index"] = State.on; if (opt_action.backmatter && opt_action.section_bookindex) { book_idx_tmp = m.captures[1].to!string; debug(bookindexmatch) { // book index writefln( "* [bookindex] %s\n", book_idx_tmp, ); } } } else if (obj_type_status["book_index"] == State.on ) { /+ book_index flag set +/ if (auto m = line.match(rgx.book_index_close)) { obj_type_status["book_index"] = State.off; if (opt_action.backmatter && opt_action.section_bookindex) { an_object["bookindex_nugget"] = book_idx_tmp ~ m.captures[1].to!string; debug(bookindexmatch) { // book index writefln( "* [bookindex] %s\n", book_idx_tmp, ); } } book_idx_tmp = ""; } else { if (opt_action.backmatter && opt_action.section_bookindex) { book_idx_tmp ~= line; } } } } #+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 _make_unmarked_headings, return ref H heading_match_str, return ref R heading_match_rgx, return ref T obj_type_status ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(_make_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(obj_type_status) == int[string])); } static auto rgx = Rgx(); if ((_make_unmarked_headings.length > 2) && (obj_type_status["make_headings"] == State.off)) { /+ headings found +/ debug(headingsfound) { writeln(_make_unmarked_headings); } debug(headingsfound) { writeln(_make_unmarked_headings.length); writeln(_make_unmarked_headings); } switch (_make_unmarked_headings.length) { case 7 : if (!empty(_make_unmarked_headings[6])) { heading_match_str["h_4"] = "^(" ~ _make_unmarked_headings[6].to!string ~ ")"; heading_match_rgx["h_4"] = regex(heading_match_str["h_4"]); } goto case; case 6 : if (!empty(_make_unmarked_headings[5])) { heading_match_str["h_3"] = "^(" ~ _make_unmarked_headings[5].to!string ~ ")"; heading_match_rgx["h_3"] = regex(heading_match_str["h_3"]); } goto case; case 5 : if (!empty(_make_unmarked_headings[4])) { heading_match_str["h_2"] = "^(" ~ _make_unmarked_headings[4].to!string ~ ")"; heading_match_rgx["h_2"] = regex(heading_match_str["h_2"]); } goto case; case 4 : if (!empty(_make_unmarked_headings[3])) { heading_match_str["h_1"] = "^(" ~ _make_unmarked_headings[3].to!string ~ ")"; heading_match_rgx["h_1"] = regex(heading_match_str["h_1"]); } goto case; case 3 : if (!empty(_make_unmarked_headings[2])) { heading_match_str["h_D"] = "^(" ~ _make_unmarked_headings[2].to!string ~ ")"; heading_match_rgx["h_D"] = regex(heading_match_str["h_D"]); } goto case; case 2 : if (!empty(_make_unmarked_headings[1])) { heading_match_str["h_C"] = "^(" ~ _make_unmarked_headings[1].to!string ~ ")"; heading_match_rgx["h_C"] = regex(heading_match_str["h_C"]); } goto case; case 1 : if (!empty(_make_unmarked_headings[0])) { heading_match_str["h_B"] = "^(" ~ _make_unmarked_headings[0].to!string ~ ")"; heading_match_rgx["h_B"] = regex(heading_match_str["h_B"]); } break; default: break; } obj_type_status["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, return ref R heading_match_rgx, return ref T obj_type_status ) { 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(obj_type_status) == int[string])); } if ((obj_type_status["make_headings"] == State.on) && ((line_occur["para"] == State.off) && (line_occur["heading"] == State.off)) && ((obj_type_status["para"] == State.off) && (obj_type_status["heading"] == State.off))) { /+ heading make set +/ if (line.matchFirst(heading_match_rgx["h_B"])) { line = "B~ " ~ line; debug(headingsfound) { writeln(line); } } if (line.matchFirst(heading_match_rgx["h_C"])) { line = "C~ " ~ line; debug(headingsfound) { writeln(line); } } if (line.matchFirst(heading_match_rgx["h_D"])) { line = "D~ " ~ line; debug(headingsfound) { writeln(line); } } if (line.matchFirst(heading_match_rgx["h_1"])) { line = "1~ " ~ line; debug(headingsfound) { writeln(line); } } if (line.matchFirst(heading_match_rgx["h_2"])) { line = "2~ " ~ line; debug(headingsfound) { writeln(line); } } if (line.matchFirst(heading_match_rgx["h_3"])) { line = "3~ " ~ line; debug(headingsfound) { writeln(line); } } if (line.matchFirst(heading_match_rgx["h_4"])) { line = "4~ " ~ line; debug(headingsfound) { writeln(line); } } } return line; } #+END_SRC **** heading match :heading: #+name: abs_functions_heading #+BEGIN_SRC d auto _heading_matched_(L,C,O,K,Lv,Lc,T,CMM)( L line, return ref C line_occur, return ref O an_object, return ref K an_object_key, return ref Lv lv, return ref Lc collapsed_lev, return ref T obj_type_status, return ref CMM conf_make_meta, ) { 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(obj_type_status) == int[string])); } static auto rgx = Rgx(); if (auto m = line.match(rgx.heading)) { /+ heading match +/ ++line_occur["heading"]; obj_type_status["heading"] = State.on; obj_type_status["para"] = State.off; if (line.match(rgx.heading_seg_and_above)) { obj_type_status["biblio_section"] = State.off; obj_type_status["glossary_section"] = State.off; obj_type_status["blurb_section"] = State.off; } 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": // Title set an_object[an_object_key]=(an_object[an_object_key]) .replaceFirst(rgx.variable_doc_title, (conf_make_meta.meta.title_full ~ ",")) .replaceFirst(rgx.variable_doc_author, conf_make_meta.meta.creator_author); collapsed_lev["h0"] = 0; an_object["lev_collapsed_number"] = collapsed_lev["h0"].to!string; lv["lv"] = DocStructMarkupHeading.h_sect_A; ++lv["h0"]; lv["h1"] = State.off; lv["h2"] = State.off; lv["h3"] = State.off; lv["h4"] = State.off; lv["h5"] = State.off; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "B": collapsed_lev["h1"] = collapsed_lev["h0"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h1"].to!string; lv["lv"] = DocStructMarkupHeading.h_sect_B; ++lv["h1"]; lv["h2"] = State.off; lv["h3"] = State.off; lv["h4"] = State.off; lv["h5"] = State.off; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "C": collapsed_lev["h2"] = collapsed_lev["h1"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h2"].to!string; lv["lv"] = DocStructMarkupHeading.h_sect_C; ++lv["h2"]; lv["h3"] = State.off; lv["h4"] = State.off; lv["h5"] = State.off; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "D": collapsed_lev["h3"] = collapsed_lev["h2"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h3"].to!string; lv["lv"] = DocStructMarkupHeading.h_sect_D; ++lv["h3"]; lv["h4"] = State.off; lv["h5"] = State.off; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "1": if (lv["h3"] > State.off) { collapsed_lev["h4"] = collapsed_lev["h3"] + 1; } else if (lv["h2"] > State.off) { collapsed_lev["h4"] = collapsed_lev["h2"] + 1; } else if (lv["h1"] > State.off) { collapsed_lev["h4"] = collapsed_lev["h1"] + 1; } else if (lv["h0"] > State.off) { collapsed_lev["h4"] = collapsed_lev["h0"] + 1; } an_object["lev_collapsed_number"] = collapsed_lev["h4"].to!string; lv["lv"] = DocStructMarkupHeading.h_text_1; ++lv["h4"]; lv["h5"] = State.off; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "2": if (lv["h5"] > State.off) { an_object["lev_collapsed_number"] = collapsed_lev["h5"].to!string; } else if (lv["h4"] > State.off) { collapsed_lev["h5"] = collapsed_lev["h4"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h5"].to!string; } lv["lv"] = DocStructMarkupHeading.h_text_2; ++lv["h5"]; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "3": if (lv["h6"] > State.off) { an_object["lev_collapsed_number"] = collapsed_lev["h6"].to!string; } else if (lv["h5"] > State.off) { collapsed_lev["h6"] = collapsed_lev["h5"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h6"].to!string; } lv["lv"] = DocStructMarkupHeading.h_text_3; ++lv["h6"]; lv["h7"] = State.off; goto default; case "4": if (lv["h7"] > State.off) { an_object["lev_collapsed_number"] = collapsed_lev["h7"].to!string; } else if (lv["h6"] > State.off) { collapsed_lev["h7"] = collapsed_lev["h6"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h7"].to!string; } lv["lv"] = DocStructMarkupHeading.h_text_4; ++lv["h7"]; goto default; default: an_object["lev_markup_number"] = lv["lv"].to!string; } debug(heading) { // heading writeln(line.strip); } } } #+END_SRC **** para match :para: #+name: abs_functions_para #+BEGIN_SRC d void _para_match_(L,O,K,I,B,T,C)( L line, return ref O an_object, return ref K an_object_key, return ref I indent, return ref B bullet, return ref T obj_type_status, return ref C line_occur, ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(an_object_key) == string)); static assert(is(typeof(indent) == int[string])); static assert(is(typeof(bullet) == bool)); static assert(is(typeof(obj_type_status) == int[string])); static assert(is(typeof(line_occur) == int[string])); } static auto rgx = Rgx(); if (line_occur["para"] == State.off) { line = font_faces_line(line); /+ para matches +/ obj_type_status["para"] = State.on; an_object[an_object_key] ~= line; // body_nugget indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; if (auto m = line.matchFirst(rgx.para_indent)) { debug(paraindent) { // para indent writeln(line); } indent["hang_position"] = (m.captures[1]).to!int; indent["base_position"] = 0; } else if (line.matchFirst(rgx.para_bullet)) { debug(parabullet) { // para bullet writeln(line); } bullet = true; } else if (auto m = line.matchFirst(rgx.para_indent_hang)) { debug(paraindenthang) { // para indent hang writeln(line); } indent=[ "hang_position" : (m.captures[1]).to!int, "base_position" : (m.captures[2]).to!int, ]; } else if (auto m = line.matchFirst(rgx.para_bullet_indent)) { debug(parabulletindent) { // para bullet indent writeln(line); } indent=[ "hang_position" : (m.captures[1]).to!int, "base_position" : 0, ]; bullet = true; } ++line_occur["para"]; } } #+END_SRC **** text font face #+name: abs_functions_para #+BEGIN_SRC d auto font_faces_line(T)( T textline, ) { static auto rgx = Rgx(); if (textline.match(rgx.inline_faces_line)) { textline = (textline) .replaceFirst(rgx.inline_emphasis_line, ("*{$1}*$2")) .replaceFirst(rgx.inline_bold_line, ("!{$1}!$2")) .replaceFirst(rgx.inline_underscore_line, ("_{$1}_$2")) .replaceFirst(rgx.inline_italics_line, ("/{$1}/$2")); } return textline; } #+END_SRC **** tables - number of columns - column widths (either as given or uniform, first often different from rest) - column aligns (as given else default left for text, check whether can default right for digits) - table heading (auto align left) - table walls - TODO need to be able to align columns left or right (digits) ***** table instructions #+name: abs_functions_table #+BEGIN_SRC d auto table_instructions(O,H)( return ref O table_object, return ref H table_head, ) { static auto rgx = Rgx(); table_object.of_part = "body"; table_object.of_section = "body"; table_object.is_of = "block"; table_object.is_a = "table"; table_object.inline_notes_reg = false; table_object.inline_notes_star = false; table_object.inline_links = false; if (auto m = table_head.matchFirst(rgx.table_head_instructions)) { table_object.table_heading = ((m["c_heading"].length > 0) && (m["c_heading"] == "h")) ? true : false; table_object.table_number_of_columns = ((m["c_num"].length > 0) && (m["c_num"].to!int > 0)) ? m["c_num"].to!int : 0; // double check, may be obsolete foreach (cw; m["c_widths"].matchAll(rgx.table_col_widths)) { auto x = cw.hit.matchFirst(rgx.table_col_widths_and_alignment); table_object.table_column_widths ~= x["width"].to!int; table_object.table_column_aligns ~= (x["align"].empty) ? "" : x["align"]; } } return table_object; } #+END_SRC ***** table array munge #+name: abs_functions_table #+BEGIN_SRC d auto table_array_munge(O,T)( return ref O table_object, return ref T table_array, ) { static auto rgx = Rgx(); static auto mng = InlineMarkup(); string _table_substantive; ulong col_num; ulong col_num_; ulong col_num_chk = 0; foreach(idx_r, row; table_array) { debug(table_dev) { writeln("row ", idx_r); } col_num_ = 0; if (col_num == 0 || col_num < row.length) { col_num = row.length; } if (col_num_chk == 0) { col_num_chk = col_num; } else if (col_num == 1) { debug(table_dev) { writeln("table note: "); } } else if (col_num_chk != col_num) { debug(table_dev) { writeln("warning irregular number of columns: ", col_num_chk, " != ", col_num); } } else { } foreach(idx_c, col; row) { debug(table_dev) { write(idx_c, ", "); } col_num_ = idx_c; _table_substantive ~= col ~ mng.tc_s; if (idx_r == 0 && comp_obj_block.table_heading) { } else if (col.match(rgx.numeric_col) && idx_r == 1) { // conditions reversed to avoid: gdc compiled program run segfault if ((comp_obj_block.table_column_aligns.length > idx_c) && (comp_obj_block.table_column_aligns[idx_c].matchFirst(rgx.table_col_align_match))) { comp_obj_block.table_column_aligns[idx_c] = comp_obj_block.table_column_aligns[idx_c]; } else if (comp_obj_block.table_column_aligns.length > idx_c) { comp_obj_block.table_column_aligns[idx_c] = "r"; } else { comp_obj_block.table_column_aligns ~= "r"; } } else if (idx_r == 1) { if ((comp_obj_block.table_column_aligns.length > idx_c) && (comp_obj_block.table_column_aligns[idx_c].matchFirst(rgx.table_col_align_match))) { comp_obj_block.table_column_aligns[idx_c] = comp_obj_block.table_column_aligns[idx_c]; } else if (comp_obj_block.table_column_aligns.length > idx_c) { comp_obj_block.table_column_aligns[idx_c] = "l"; } else { comp_obj_block.table_column_aligns ~= "l"; } } } debug(table_dev) { writeln(""); } if (col_num_chk > 0 && (col_num != col_num_chk)) { } else if (col_num == col_num_chk){ } else { col_num_chk = col_num; } _table_substantive = _table_substantive.replaceFirst(rgx.table_col_separator_nl, "\n"); } if (comp_obj_block.table_number_of_columns != col_num) { if (comp_obj_block.table_number_of_columns == 0) { comp_obj_block.table_number_of_columns = (col_num).to!int; } else { debug(table_dev) { writeln(comp_obj_block.table_number_of_columns, " != ", col_num); } } } if (table_object.table_number_of_columns == 0 && table_object.table_column_widths.length > 0) { writeln(__LINE__, " ERROR"); } if (table_object.table_number_of_columns > 0 && table_object.table_column_widths.length == 0) { double col_w = (100.00 / table_object.table_number_of_columns); foreach (i; 0..table_object.table_number_of_columns) { table_object.table_column_widths ~= col_w; } } else if (table_object.table_number_of_columns != table_object.table_column_widths.length) { debug(table_dev) { writeln(m.hit); // further logic required } if (table_object.table_number_of_columns > table_object.table_column_widths.length) { double col_w = (100.00 - (table_object.table_column_widths).sum) / (table_object.table_number_of_columns - table_object.table_column_widths.length); foreach (i; 0..table_object.table_column_widths.length) { table_object.table_column_widths ~= col_w; } foreach (i; 0..(table_object.table_number_of_columns - table_object.table_column_widths.length)) { table_object.table_column_widths ~= col_w; } } else if (table_object.table_number_of_columns < table_object.table_column_widths.length) { writeln(__LINE__, " warning, ERROR"); } } if (table_object.table_column_widths.sum > 101 || table_object.table_column_widths.sum < 95 ) { writeln("sum: ", table_object.table_column_widths.sum, ", array: ", table_object.table_column_widths, ", cols: ", table_object.table_number_of_columns); writeln(_table_substantive); } debug(table_res) { writeln("aligns: ", comp_obj_block.table_column_aligns, "\n", "no. of columns: ", comp_obj_block.table_number_of_columns, "\n", "col widths: ", comp_obj_block.table_column_widths, " sum: ", comp_obj_block.table_column_widths.sum, "\n", _table_substantive); } comp_obj_block.text = _table_substantive; return table_object; } #+END_SRC ****** table array munge simple open & close #+name: abs_functions_table #+BEGIN_SRC d auto table_array_munge_open_close(O,T)( return ref O table_object, return ref T table_array, ) { static auto rgx = Rgx(); static auto mng = InlineMarkup(); string _table_substantive; foreach(row; table_array) { foreach(col; row) { _table_substantive ~= mng.tc_o ~ col ~ mng.tc_c; } _table_substantive ~= "\n"; } debug(table_dev) { writeln(_table_substantive); } comp_obj_block.text = _table_substantive; return table_object; } #+END_SRC ***** table substantive munge #+name: abs_functions_table #+BEGIN_SRC d auto table_substantive_munge(O,T)( return ref O table_object, return ref T table_substantive, ) { static auto rgx = Rgx(); static auto munge = ObjInlineMarkupMunge(); string[] _table_rows = (table_substantive).split(rgx.table_row_delimiter); string[] _table_cols; string[][] _table; foreach(col; _table_rows) { _table_cols = col.split(rgx.table_col_delimiter); _table ~= _table_cols; } table_object = table_array_munge(table_object, _table); return table_object; } #+END_SRC ***** table substantive munge special #+name: abs_functions_table #+BEGIN_SRC d auto table_substantive_munge_special(O,T)( return ref O table_object, return ref T table_substantive, ) { static auto rgx = Rgx(); static auto munge = ObjInlineMarkupMunge(); string[] _table_rows = (table_substantive).split(rgx.table_row_delimiter_special); string[] _table_cols; string[][] _table; foreach(col; _table_rows) { _table_cols = col.split(rgx.table_col_delimiter_special); _table ~= _table_cols; } table_object = table_array_munge(table_object, _table); return table_object; } #+END_SRC *** function emitters :emitters: **** object :object: ***** ocn :ocn: #+name: meta_emitters_ocn #+BEGIN_SRC d pure struct OCNemitter { int ocn_, ocn_on, ocn_on_, ocn_off, ocn_off_, ocn_bkidx, ocn_bkidx_; auto ocn_emitter(int ocn_status_flag) { OCNset ocn; assert(ocn_status_flag <= OCNstatus.reset); ocn_on = ocn_off = ocn_bkidx = 0; switch(ocn_status_flag) { case OCNstatus.reset: ocn_ = ocn_on_ = ocn_off_ = 1; ocn_bkidx_ = 0; break; case OCNstatus.on: ocn_ = ocn_on = ++ocn_on_; break; case OCNstatus.off: ocn_ = ocn_off = ++ocn_off_; break; case OCNstatus.bkidx: ocn_ = ocn_bkidx = ++ocn_bkidx_; break; case OCNstatus.closing: break; default: ocn_ = 0; } assert(ocn_ >= 0); ocn.digit = ocn_; ocn.on = ocn_on; ocn.off = ocn_off; ocn.bkidx = ocn_bkidx; ocn.type = ocn_status_flag; return ocn; } invariant() { } } #+END_SRC ***** object inline markup munge :markup:inline: ****** { struct, inline markup munge #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d static struct ObjInlineMarkupMunge { string[string] obj_txt; int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus; string asterisks_, plus_; string obj_txt_out, tail, note; static auto rgx = Rgx(); static auto mkup = InlineMarkup(); int stage_reset_note_numbers = true; private auto initialize_note_numbers() { n_foot = 0; n_foot_reg = 0; n_foot_sp_asterisk = 0; n_foot_sp_plus = 0; } #+END_SRC ******* url links #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d static auto url_links(Ot)(Ot obj_txt_in) { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } static auto mng = InlineMarkup(); obj_txt_in = obj_txt_in.replaceAll(rgx.inline_mono, (mng.mono ~ "{$1}" ~ mng.mono)); /+ url matched +/ obj_txt_in = obj_txt_in.replaceAll(rgx.inline_notes_al_special, ""); // TODO reinstate when special footnotes are implemented if (obj_txt_in.match(rgx.inline_url_generic)) { /+ link: naked url: http://url +/ if (obj_txt_in.match(rgx.inline_link_naked_url)) { obj_txt_in = (obj_txt_in).replaceAll( rgx.inline_link_naked_url, ("$1" ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "$3") // ("$1{ $2 }$2$3") ); } /+ link with helper for endnote including the url: {~^ link which includes url as footnote }http://url maps to: { link which includes url as footnote }http://url~{ { http://url }http://url }~ +/ if (obj_txt_in.match(rgx.inline_link_endnote_url_helper)) { obj_txt_in = (obj_txt_in) .replaceAll( rgx.inline_link_endnote_url_helper_punctuated, (mkup.lnk_o ~ "$1" ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3") ) .replaceAll( rgx.inline_link_endnote_url_helper, (mkup.lnk_o ~ "$1" ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ " }~") // ("{ $1 }$2~{ { $2 }$2 }~") ); } /+ link with regular markup: { linked text or image }http://url +/ if (obj_txt_in.match(rgx.inline_link_markup_regular)) { obj_txt_in = (obj_txt_in).replaceAll( rgx.inline_link_markup_regular, ("$1" ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c ~ mkup.url_o ~ "$3" ~ mkup.url_c ~ "$4") // ("$1{ $2 }$3$4") ); } } obj_txt_in = obj_txt_in.replaceAll(rgx.inline_mono_box, ("#{$1}#")); return obj_txt_in; } #+END_SRC ******* footnotes endnotes markup #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d auto footnotes_endnotes_markup_and_number_or_stars(Ot)(Ot obj_txt_in, bool reset_note_numbers) { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } /+ endnotes (regular) +/ bool flg_notes_reg = false; bool flg_notes_star = false; bool flg_notes_plus = false; obj_txt_in = (obj_txt_in).replaceAll( rgx.inline_notes_curly, (mkup.en_a_o ~ " $1" ~ mkup.en_a_c) ); if (!(stage_reset_note_numbers) && reset_note_numbers) { stage_reset_note_numbers = true; } if (obj_txt_in.match(rgx.inline_notes_al_gen)) { if (auto m = obj_txt_in.matchAll(rgx.inline_text_and_note_al_)) { if (stage_reset_note_numbers) { n_foot = 0; n_foot_reg = 0; n_foot_sp_asterisk = 0; n_foot_sp_plus = 0; } stage_reset_note_numbers = false; foreach(n; m) { if (n.hit.to!string.match(rgx.inline_al_delimiter_open_symbol_star)) { flg_notes_star = true; ++n_foot_sp_asterisk; asterisks_ = "*"; n_foot=n_foot_sp_asterisk; obj_txt_out ~= n.hit.to!string.replaceFirst( rgx.inline_al_delimiter_open_symbol_star, (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ") ) ~ "\n"; } else if (n.hit.to!string.match(rgx.inline_al_delimiter_open_symbol_plus)) { flg_notes_plus = true; ++n_foot_sp_plus; plus_ = "*"; n_foot=n_foot_sp_plus; obj_txt_out ~= n.hit.to!string.replaceFirst( rgx.inline_al_delimiter_open_symbol_plus, (mkup.en_a_o ~ replicate(plus_, n_foot_sp_plus) ~ " ") ) ~ "\n"; } else if (n.hit.to!string.match(rgx.inline_al_delimiter_open_regular)) { flg_notes_reg = true; ++n_foot_reg; n_foot=n_foot_reg; obj_txt_out ~= n.hit.to!string.replaceFirst( rgx.inline_al_delimiter_open_regular, (mkup.en_a_o ~ to!string(n_foot) ~ " ") ) ~ "\n"; } else { obj_txt_out ~= n.hit.to!string ~ "\n"; } } } } else { obj_txt_out = obj_txt_in; } auto t = tuple( obj_txt_out, flg_notes_reg, flg_notes_star, flg_notes_plus, ); return t; } #+END_SRC ******* object notes and links #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d private auto object_notes_and_links_(Ot)(Ot obj_txt_in, bool reset_note_numbers=false) in { debug(asserts) { assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt_out = ""; bool urls = false; tail = ""; /+ special endnotes +/ obj_txt_in = obj_txt_in.replaceAll( rgx.inline_notes_curly_sp_asterisk, (mkup.en_a_o ~ "*" ~ " $1" ~ mkup.en_a_c) ); obj_txt_in = obj_txt_in.replaceAll( rgx.inline_notes_curly_sp_plus, (mkup.en_a_o ~ "+" ~ " $1" ~ mkup.en_a_c) ); /+ url matched +/ if (obj_txt_in.match(rgx.inline_url)) { urls = true; obj_txt_in = url_links(obj_txt_in); } auto ftn = footnotes_endnotes_markup_and_number_or_stars(obj_txt_in, reset_note_numbers); obj_txt_out = ftn[0]; debug(footnotes) { writeln(obj_txt_out, tail); } obj_txt_out = obj_txt_out ~ tail; debug(footnotesdone) { foreach(m; matchAll(obj_txt_out, (mkup.en_a_o ~ `\s*(.+?)` ~ mkup.en_a_c))) { writeln(m.captures[1]); writeln(m.hit); } } auto t = tuple( obj_txt_out, ftn[1], ftn[2], ftn[3], urls, ); return t; } auto init() in { } body { auto t = object_notes_and_links_(""); return t; } invariant() { } #+END_SRC ******* heading - identified text by heading level marker followed by text until two new lines - general markup #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d auto munge_heading(Ot)(Ot obj_txt_in, bool reset_note_numbers=false) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=(obj_txt_in) .replaceFirst(rgx.heading, "") .replaceFirst(rgx.obj_cite_number_off_all, "") .strip; auto t = object_notes_and_links_(obj_txt["munge"], reset_note_numbers); debug(munge) { writeln(__LINE__); writeln(obj_txt_in); writeln(__LINE__); writeln(obj_txt["munge"].to!string); } return t; } invariant() { } #+END_SRC ******* para - paragraph text without other identification until two new lines - general markup - paragraph attributes - font faces (bold, italics, underscore etc.) - footnotes/endnotes - links #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d auto munge_para(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=(obj_txt_in) .replaceFirst(rgx.para_attribs, "") .replaceFirst(rgx.obj_cite_number_off_all, ""); auto t = object_notes_and_links_(obj_txt["munge"]); debug(munge) { writeln(__LINE__); writeln(obj_txt_in); writeln(__LINE__); writeln(obj_txt["munge"].to!string); } return t; } #+END_SRC ******* quote #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d string munge_quote(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } #+END_SRC ******* group - group block identified by open an close tags - general markup - paragraph attributes - font faces (bold, italics, underscore etc.) - footnotes/endnotes - links - newlines detected and kept? #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d auto munge_group(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; auto t = object_notes_and_links_(obj_txt["munge"]); return t; } invariant() { } #+END_SRC ******* block - group block identified by open an close tags - general markup - paragraph attributes - font faces (bold, italics, underscore etc.) - footnotes/endnotes - links - newlines detected and kept? #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d auto munge_block(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=obj_txt_in; auto t = object_notes_and_links_(obj_txt["munge"]); return t; } invariant() { } #+END_SRC ******* verse (poem) - sub part of poem block which is identified by open an close tags, separated from other verse by double newline - newlines - indentation - what part of general markup? - font faces (bold, italics, underscore etc.) - footnotes/endnotes - links? #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d auto munge_verse(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=obj_txt_in; auto t = object_notes_and_links_(obj_txt["munge"]); return t; } invariant() { } #+END_SRC ******* code - newlines - indentation - possibly identify syntax for coloring (obj attribute) - numbered code blocks (markup/obj attribute?) - no general markup - one special character represented by mkup.nbsp ░ #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d string munge_code(Ot)(Ot obj_txt_in) in { debug(asserts) { assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt_in = (obj_txt_in).replaceAll(rgx.space, mkup.nbsp); obj_txt["munge"] = obj_txt_in; return obj_txt["munge"]; } invariant() { } #+END_SRC ******* table - table block identified by open an close tags - table markup #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d string munge_table(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } #+END_SRC ******* comment #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d string munge_comment(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } #+END_SRC ****** } #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d } #+END_SRC ***** toc, tags, object inline markup :markup:inline: ****** { #+name: meta_emitters_obj_inline_markup #+BEGIN_SRC d static struct ObjInlineMarkup { static auto rgx = Rgx(); static auto munge = ObjInlineMarkupMunge(); string[string] obj_txt; #+END_SRC ******* object inline markup and anchor tags :markup:inline: #+name: meta_emitters_obj_inline_markup_and_anchor_tags_and_misc #+BEGIN_SRC d auto obj_inline_markup_and_anchor_tags_and_misc(O,K,CMM)( O obj_, K obj_key_, CMM conf_make_meta, ) in { debug(asserts) { static assert(is(typeof(obj_) == string[string])); static assert(is(typeof(obj_key_) == string)); } } body { obj_txt["munge"] = obj_[obj_key_].dup; obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`))) ? obj_txt["munge"] : strip(obj_txt["munge"]); static __gshared string[] anchor_tags_ = []; auto x = munge.init; bool[string] obj_notes_and_links; obj_notes_and_links["notes_reg"] = false; obj_notes_and_links["notes_star"] = false; obj_notes_and_links["links"] = false; switch (obj_["is"]) { case "heading": static __gshared string anchor_tag = ""; obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, conf_make_meta); obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"]); if (auto m = obj_txt["munge"].match(rgx.heading_anchor_tag)) { anchor_tag = m.captures[1]; anchor_tags_ ~= anchor_tag; } else if (obj_["lev"] == "1") { writeln("heading anchor tag missing: ", obj_txt["munge"]); } x =munge.munge_heading(obj_txt["munge"], reset_note_numbers); reset_note_numbers=false; goto default; case "para": x = munge.munge_para(obj_txt["munge"]); goto default; case "group": x = munge.munge_group(obj_txt["munge"]); goto default; case "block": x = munge.munge_block(obj_txt["munge"]); goto default; case "verse": x = munge.munge_verse(obj_txt["munge"]); goto default; case "code": obj_txt["munge"] = munge.munge_code(obj_txt["munge"]); break; case "table": obj_txt["munge"] = munge.munge_table(obj_txt["munge"]); break; case "quote": obj_txt["munge"] = munge.munge_quote(obj_txt["munge"]); break; case "comment": obj_txt["munge"] = munge.munge_comment(obj_txt["munge"]); break; case "doc_end_reset": munge.initialize_note_numbers(); break; default: /+ para, heading, group, block, verse +/ obj_txt["munge"] = x[0]; obj_notes_and_links["notes_reg"] = x[1]; obj_notes_and_links["notes_star"] = x[2]; obj_notes_and_links["notes_plus"] = x[3]; obj_notes_and_links["links"] = x[4]; break; } auto t = tuple( obj_txt["munge"], anchor_tags_, obj_notes_and_links["notes_reg"], obj_notes_and_links["notes_star"], obj_notes_and_links["links"], ); anchor_tags_=[]; return t; } invariant() { } #+END_SRC ******* toc (table of contents), build, gather headings :markup:inline: #+name: meta_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 = (cast(char[]) heading_toc_).matchFirst(rgx.heading); heading_toc_ = (m.post).replaceAll( rgx.inline_notes_curly_gen, ""); return heading_toc_; }; auto table_of_contents_gather_headings(O,CMM,Ts,Ta,X,Toc)( O obj_, CMM conf_make_meta, Ts segment_anchor_tag_that_object_belongs_to, Ta _anchor_tag, return ref X lev4_subtoc, Toc the_table_of_contents_section, ) in { debug(asserts) { static assert(is(typeof(obj_) == string[string])); static assert(is(typeof(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; static auto mkup = InlineMarkup(); char[] heading_toc_ = (obj_["substantive"].dup.strip.to!(char[])).replaceAll(rgx.inline_notes_al, ""); heading_toc_ = _clean_heading_toc_(heading_toc_); auto attrib=""; string toc_txt_, subtoc_txt_; int[string] indent; if (obj_["lev_markup_number"].to!int > 0) { indent=[ "hang_position" : obj_["lev_markup_number"].to!int, "base_position" : obj_["lev_markup_number"].to!int, ]; toc_txt_ = format( "{ %s }#%s", heading_toc_, _anchor_tag, ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc = comp_obj_toc.init; comp_obj_toc.of_part = "frontmatter"; comp_obj_toc.of_section = "toc"; 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.obj_cite_number_off = ""; comp_obj_toc.obj_cite_number_type = 0; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.bullet = false; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } else { indent=[ "hang_position" : 0, "base_position" : 0, ]; comp_obj_toc = comp_obj_toc.init; comp_obj_toc.of_part = "frontmatter"; comp_obj_toc.of_section = "toc"; 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.obj_cite_number_off = ""; comp_obj_toc.obj_cite_number_type = 0; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.bullet = false; comp_obj_toc.text = "Table of Contents"; comp_obj_toc.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } comp_obj_toc = comp_obj_toc.init; comp_obj_toc.of_part = "frontmatter"; comp_obj_toc.of_section = "toc"; 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.obj_cite_number_off = ""; comp_obj_toc.obj_cite_number_type = 0; comp_obj_toc.bullet = false; comp_obj_toc.inline_links = true; switch (obj_["lev_markup_number"].to!int) { case 0: indent=[ "hang_position" : 0, "base_position" : 0, ]; toc_txt_ = "{ Table of Contents }" ~ mkup.mark_internal_site_lnk ~ "toc.fnSuffix"; toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; case 1: .. case 3: indent=[ "hang_position" : obj_["lev_markup_number"].to!int, "base_position" : obj_["lev_markup_number"].to!int, ]; toc_txt_ = format( "%s", heading_toc_, ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; case 4: toc_txt_ = format( "{ %s }%s%s%s", heading_toc_, mkup.mark_internal_site_lnk, segment_anchor_tag_that_object_belongs_to, ".fnSuffix", ); lev4_subtoc[segment_anchor_tag_that_object_belongs_to] = []; toc_txt_= munge.url_links(toc_txt_); indent=[ "hang_position" : obj_["lev_markup_number"].to!int, "base_position" : obj_["lev_markup_number"].to!int, ]; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; case 5: .. case 7: toc_txt_ = format( "{ %s }%s%s%s#%s", heading_toc_, mkup.mark_internal_site_lnk, segment_anchor_tag_that_object_belongs_to, ".fnSuffix", _anchor_tag, ); subtoc_txt_ = format( "{ %s }#%s", heading_toc_, _anchor_tag, ); lev4_subtoc[segment_anchor_tag_that_object_belongs_to] ~= munge.url_links(obj_["lev_markup_number"] ~ "~ " ~ subtoc_txt_.to!string.strip ); toc_txt_= munge.url_links(toc_txt_); indent=[ "hang_position" : obj_["lev_markup_number"].to!int, "base_position" : obj_["lev_markup_number"].to!int, ]; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; default: break; } return the_table_of_contents_section; } invariant() { } #+END_SRC ******* private: #+name: meta_emitters_obj_inline_markup_private #+BEGIN_SRC d private: #+END_SRC ******** make heading number & segment anchor tags if instructed :markup:inline:segment:anchor:tags: #+name: meta_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags #+BEGIN_SRC d static string _configured_auto_heading_numbering_and_segment_anchor_tags(M,O,CMM)( M munge_, O obj_, CMM conf_make_meta, ) { debug(asserts) { static assert(is(typeof(munge_) == string)); static assert(is(typeof(obj_) == string[string])); } static __gshared int[] heading_num = [ 0, 0, 0, 0 ]; static __gshared string heading_number_auto_composite = ""; if (conf_make_meta.make.auto_num_top_lv) { if (obj_["lev_markup_number"].to!int == 0) { heading_num[0] = 0; heading_num[1] = 0; heading_num[2] = 0; heading_num[3] = 0; heading_number_auto_composite = ""; } /+ auto_num_depth minimum 0 (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement +/ if ( conf_make_meta.make.auto_num_top_lv > obj_["lev_markup_number"].to!uint ) { heading_num[1] = 0; heading_num[2] = 0; heading_num[3] = 0; } else if ( conf_make_meta.make.auto_num_top_lv == obj_["lev_markup_number"].to!uint ) { heading_num[0] ++; heading_num[1] = 0; heading_num[2] = 0; heading_num[3] = 0; } else if ( conf_make_meta.make.auto_num_top_lv == (obj_["lev_markup_number"].to!uint - 1) ) { heading_num[1] ++; heading_num[2] = 0; heading_num[3] = 0; } else if ( conf_make_meta.make.auto_num_top_lv == (obj_["lev_markup_number"].to!uint - 2) ) { heading_num[2] ++; heading_num[3] = 0; } else if ( conf_make_meta.make.auto_num_top_lv == (obj_["lev_markup_number"].to!uint - 3) ) { heading_num[3] ++; } if (heading_num[3] > 0) { heading_number_auto_composite = (conf_make_meta.make.auto_num_depth.to!uint == 3) ? ( heading_num[0].to!string ~ "." ~ heading_num[1].to!string ~ "." ~ heading_num[2].to!string ~ "." ~ heading_num[3].to!string ) : ""; } else if (heading_num[2] > 0) { heading_number_auto_composite = ((conf_make_meta.make.auto_num_depth.to!uint >= 2) && (conf_make_meta.make.auto_num_depth.to!uint <= 3)) ? ( heading_num[0].to!string ~ "." ~ heading_num[1].to!string ~ "." ~ heading_num[2].to!string ) : ""; } else if (heading_num[1] > 0) { heading_number_auto_composite = ((conf_make_meta.make.auto_num_depth.to!uint >= 1) && (conf_make_meta.make.auto_num_depth.to!uint <= 3)) ? ( heading_num[0].to!string ~ "." ~ heading_num[1].to!string ) : ""; } else if (heading_num[0] > 0) { heading_number_auto_composite = ((conf_make_meta.make.auto_num_depth.to!uint >= 0) && (conf_make_meta.make.auto_num_depth.to!uint <= 3)) ? (heading_num[0].to!string) : ""; } else { heading_number_auto_composite = ""; } debug(heading_number_auto) { writeln(heading_number_auto_composite); } if ((!empty(heading_number_auto_composite)) && (obj_["lev_markup_number"].to!uint >= conf_make_meta.make.auto_num_top_lv)) { munge_=(munge_) .replaceFirst(rgx.heading, "$1~$2 " ~ heading_number_auto_composite ~ ". ") .replaceFirst(rgx.heading_marker_missing_tag, "$1~" ~ heading_number_auto_composite ~ " "); } } return munge_; } #+END_SRC ******** make segment anchor tags if not provided :markup:inline:segment:anchor:tags: #+name: meta_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 (!(munge_.match(rgx.heading_anchor_tag))) { if (munge_.match(rgx.heading_identify_anchor_tag)) { if (auto m = munge_.match(rgx.heading_extract_named_anchor_tag)) { munge_=(munge_).replaceFirst( rgx.heading_marker_missing_tag, "$1~" ~ m.captures[1].toLower ~ "_" ~ m.captures[2] ~ " "); } else if (auto m = munge_.match(rgx.heading_extract_unnamed_anchor_tag)) { munge_=(munge_).replaceFirst( rgx.heading_marker_missing_tag, "$1~" ~ "s" ~ m.captures[1] ~ " "); } } else if (lev_ == "1") { // (if not successful) manufacture a unique anchor tag for lev=="1" static __gshared int heading_num_lev1 = 0; heading_num_lev1 ++; munge_=(munge_).replaceFirst( rgx.heading_marker_missing_tag, "$1~" ~ "x" ~ heading_num_lev1.to!string ~ " "); } } return munge_; } #+END_SRC ******** unittests #+name: meta_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 ****** } #+name: meta_emitters_obj_inline_markup_close #+BEGIN_SRC d } #+END_SRC ***** object attrib :attributes: ****** { attributes structure open, public #+name: meta_emitters_obj_attributes #+BEGIN_SRC d struct ObjAttributes { string[string] _obj_attrib; #+END_SRC ******* emitter obj attributes, public #+name: meta_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: meta_emitters_obj_attributes_private #+BEGIN_SRC d private: string _obj_attributes; #+END_SRC ******** para & blocks #+name: meta_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 (obj_txt_in.matchFirst(rgx.para_bullet)) { _obj_attributes =" \"bullet\": \"true\"," ~ " \"indent_hang\": 0," ~ " \"indent_base\": 0,"; } else if (auto m = obj_txt_in.matchFirst(rgx.para_bullet_indent)) { _obj_attributes =" \"bullet\": \"true\"," ~ " \"indent_hang\": " ~ m.captures[1].to!string ~ "," ~ " \"indent_base\": " ~ m.captures[1].to!string ~ ","; } else if (auto m = obj_txt_in.matchFirst(rgx.para_indent_hang)) { _obj_attributes =" \"bullet\": \"false\"," ~ " \"indent_hang\": " ~ m.captures[1].to!string ~ "," ~ " \"indent_base\": " ~ m.captures[2].to!string ~ ","; } else if (auto m = obj_txt_in.matchFirst(rgx.para_indent)) { _obj_attributes =" \"bullet\": \"false\"," ~ " \"indent_hang\": " ~ m.captures[1].to!string ~ "," ~ " \"indent_base\": " ~ m.captures[1].to!string ~ ","; } else { _obj_attributes =" \"bullet\": \"false\"," ~ " \"indent_hang\": 0," ~ " \"indent_base\": 0,"; } return _obj_attributes; } #+END_SRC ******** heading #+name: meta_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 ******** para #+name: meta_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 ******** quote #+name: meta_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 ******** group #+name: meta_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: meta_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: meta_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 ******** code #+name: meta_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 ******** table #+name: meta_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: meta_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: meta_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 ****** } #+name: meta_emitters_obj_attributes_private_close #+BEGIN_SRC d } #+END_SRC **** book index :book:index: ***** book index nugget hash :hash:nugget: #+name: meta_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,S)( BI bookindex_section, N obj_cite_digits, S segment_anchor_tag, ) in { debug(asserts) { static assert(is(typeof(bookindex_section) == string)); static assert(is(typeof(obj_cite_digits.on) == int)); } debug(bookindexraw) { if (!bookindex_section.empty) { writeln( "* [bookindex] ", "[", obj_cite_digits.on.to!string, ": ", segment_anchor_tag, "] ", bookindex_section ); } } } body { static auto rgx = Rgx(); if (!bookindex_section.empty) { auto bi_main_terms_split_arr = bookindex_section.split(rgx.bi_main_terms_split); foreach (bi_main_terms_content; bi_main_terms_split_arr) { auto bi_main_term_and_rest = bi_main_terms_content.split(rgx.bi_main_term_plus_rest_split); if (auto m = bi_main_term_and_rest[0].match( rgx.bi_term_and_obj_cite_numbers_match) ) { main_term = m.captures[1].strip; obj_cite_number_offset = m.captures[2].to!int; obj_cite_number_endpoint=(obj_cite_digits.on + obj_cite_number_offset); obj_cite_numbers ~= (obj_cite_digits.on.to!string ~ "-" ~ to!string(obj_cite_number_endpoint) ~ ":" ~ segment_anchor_tag); } else { main_term = bi_main_term_and_rest[0].strip; obj_cite_numbers ~= obj_cite_digits.on.to!string ~ ":" ~ segment_anchor_tag; } bi[main_term]["_a"] ~= obj_cite_numbers; obj_cite_numbers=null; if (bi_main_term_and_rest.length > 1) { auto bi_sub_terms_split_arr = bi_main_term_and_rest[1].split( rgx.bi_sub_terms_plus_obj_cite_number_offset_split ); foreach (sub_terms_bits; bi_sub_terms_split_arr) { if (auto m = sub_terms_bits.match(rgx.bi_term_and_obj_cite_numbers_match)) { sub_term = m.captures[1].strip; obj_cite_number_offset = m.captures[2].to!int; obj_cite_number_endpoint=(obj_cite_digits.on + obj_cite_number_offset); obj_cite_numbers ~= (obj_cite_digits.on.to!string ~ " - " ~ to!string(obj_cite_number_endpoint) ~ ":" ~ segment_anchor_tag); } else { sub_term = sub_terms_bits.strip; obj_cite_numbers ~= to!string(obj_cite_digits.on) ~ ":" ~ segment_anchor_tag; } if (!empty(sub_term)) { bi[main_term][sub_term] ~= obj_cite_numbers; } obj_cite_numbers=null; } } } } hash_nugget = bi; return hash_nugget; } invariant() { } } #+END_SRC ***** book index (sort &) report indented :report:indented: #+name: meta_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(bookindex1) { writeln(mainkey); } auto subkeys = bookindex_unordered_hashes[mainkey].byKey.array.sort().release; foreach (subkey; subkeys) { debug(bookindex1) { writeln(" ", subkey); writeln(" ", to!string( bookindex_unordered_hashes[mainkey][subkey] )); } ++skn; } ++mkn; } } } #+END_SRC ***** book index (sort &) report section :report:section: ****** { book index struct open #+name: meta_emitters_book_index_report_section #+BEGIN_SRC d struct BookIndexReportSection { int mkn, skn; static auto rgx = Rgx(); static auto munge = ObjInlineMarkupMunge(); #+END_SRC ******* bookindex write section #+name: meta_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 = (ref_).replaceAll(rgx.book_index_go, "$1"); write(" {", ref_, "}#", go, ", "); } writeln(" \\\\"); bookindex_unordered_hashes[mainkey].remove("_a"); auto subkeys = bookindex_unordered_hashes[mainkey].byKey.array.sort().release; foreach (subkey; subkeys) { write(" ", subkey, ", "); foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { auto go = (ref_).replaceAll(rgx.book_index_go, "$1"); write(" {", ref_, "}#", go, ", "); } writeln(" \\\\"); ++skn; } ++mkn; } } #+END_SRC ******* book index (sort &) build section :report:section: #+name: meta_emitters_book_index_report_section #+BEGIN_SRC d auto bookindex_build_abstraction_section(BI,N,B)( BI bookindex_unordered_hashes, N obj_cite_digits, B opt_action, ) { debug(asserts) { static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string])); static assert(is(typeof(obj_cite_digits.on) == int)); } mixin SiSUnode; mixin InternalMarkup; static auto mkup = InlineMarkup(); string type_is; string lev; int heading_lev_markup, heading_lev_collapsed; string attrib; int[string] indent; auto mainkeys = bookindex_unordered_hashes.byKey.array.sort().release; ObjGenericComposite[][string] bookindex_section; ObjGenericComposite comp_obj_heading_, comp_obj_para; auto node_para_int_ = node_metadata_para_int; auto node_para_str_ = node_metadata_para_str; if ((mainkeys.length > 0) && (opt_action.backmatter && opt_action.section_bookindex)) { string bi_tmp_seg, bi_tmp_scroll; string[] bi_tmp_tags; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "backmatter"; comp_obj_heading_.of_section = "bookindex"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.segment_anchor_tag = "_part_book_index"; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading.inline_links = true; bookindex_section["scroll"] ~= comp_obj_heading_; bookindex_section["seg"] ~= comp_obj_heading_; ++mkn; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "backmatter"; comp_obj_heading_.of_section = "bookindex"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.segment_anchor_tag = "bookindex"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading.inline_links = false; comp_obj_heading_.anchor_tags = ["bookindex"]; bookindex_section["scroll"] ~= comp_obj_heading_; bookindex_section["seg"] ~= comp_obj_heading_; ++mkn; import std.array : appender; auto buffer = appender!(char[])(); string[dchar] transTable = [' ' : "_"]; foreach (mainkey; mainkeys) { bi_tmp_tags = [""]; bi_tmp_scroll = "!{" ~ mainkey ~ "}! "; buffer.clear(); bi_tmp_tags ~= translate(mainkey, transTable); bi_tmp_seg = "!{" ~ mainkey ~ "}! "; auto bkidx_lnk_seg(string locs) { string markup = ""; if (auto m = locs.matchFirst(rgx.book_index_go_seg)) { markup = munge.url_links("{ " ~ m["link"] ~ " }" ~ mkup.mark_internal_site_lnk ~ m["seg"] ~ ".fnSuffix" ~ "#" ~ m["ocn"] ~ ", "); } else { writeln(__LINE__, ": ", locs); } return markup; } auto bkidx_lnk_scroll(string locs) { string markup = ""; if (auto m = locs.matchFirst(rgx.book_index_go)) { markup = munge.url_links("{ " ~ m["link"] ~ " }" ~ mkup.mark_internal_site_lnk ~ "#" ~ m["ocn"] ~ ", "); } else { writeln(__LINE__, ": ", locs); } return markup; } foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { bi_tmp_scroll ~= bkidx_lnk_scroll(ref_); bi_tmp_seg ~= bkidx_lnk_seg(ref_); } bi_tmp_scroll ~= " \\\\\n "; bi_tmp_seg ~= " \\\\\n "; bookindex_unordered_hashes[mainkey].remove("_a"); auto subkeys = bookindex_unordered_hashes[mainkey].byKey.array.sort().release; foreach (subkey; subkeys) { bi_tmp_scroll ~= subkey ~ ", "; buffer.clear(); bi_tmp_tags ~= translate(subkey, transTable); bi_tmp_seg ~= subkey ~ ", "; foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { bi_tmp_scroll ~= bkidx_lnk_scroll(ref_); bi_tmp_seg ~= bkidx_lnk_seg(ref_); } bi_tmp_scroll ~= " \\\\\n "; bi_tmp_seg ~= " \\\\\n "; ++skn; } bi_tmp_scroll = (bi_tmp_scroll).replaceFirst(rgx.trailing_linebreak, ""); bi_tmp_seg = (bi_tmp_seg).replaceFirst(rgx.trailing_linebreak, ""); comp_obj_para = comp_obj_para.init; comp_obj_para.of_part = "backmatter"; comp_obj_para.of_section = "bookindex"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "bookindex"; comp_obj_para.text = bi_tmp_scroll.to!string.strip; comp_obj_para.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.obj_cite_number_off = ""; comp_obj_para.obj_cite_number_type = 0; comp_obj_para.anchor_tags = bi_tmp_tags; comp_obj_para.indent_hang = 0; comp_obj_para.indent_base = 1; comp_obj_para.bullet = false; comp_obj_para.inline_links = true; bookindex_section["scroll"] ~= comp_obj_para; comp_obj_para.text = bi_tmp_seg.to!string.strip; bookindex_section["seg"] ~= comp_obj_para; ++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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; 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_digits); return t; } #+END_SRC ****** } #+name: meta_emitters_book_index_report_section #+BEGIN_SRC d } #+END_SRC **** (end)notes section :endnotes:section: #+name: meta_emitters_endnotes #+BEGIN_SRC d struct NotesSection { string[string] object_notes; int previous_count; int mkn; static auto rgx = Rgx(); #+END_SRC ***** { gather notes for endnote section struct open #+name: meta_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 { assert((contents_am[cntr].is_a == "para") || (contents_am[cntr].is_a == "heading") || (contents_am[cntr].is_a == "quote") || (contents_am[cntr].is_a == "group") || (contents_am[cntr].is_a == "block") || (contents_am[cntr].is_a == "verse")); assert(cntr >= previous_count); previous_count=cntr; assert( (contents_am[cntr].text).match( rgx.inline_notes_delimiter_al_regular_number_note) ); } body { mixin InternalMarkup; static auto mkup = InlineMarkup(); static auto munge = ObjInlineMarkupMunge(); foreach( m; (contents_am[cntr].text).matchAll( rgx.inline_notes_delimiter_al_regular_number_note ) ) { debug(endnotes_build) { writeln( "{^{", m.captures[1], ".}^}" ~ mkup.mark_internal_site_lnk, segment_anchor_tag_that_object_belongs_to, ".fnSuffix#noteref_\n ", m.captures[1], " ", m.captures[2]); // sometimes need segment name (segmented html & epub) } // TODO NEXT you need anchor for segments at this point -> object_notes["anchor"] ~= "note_" ~ m.captures[1] ~ "』"; object_notes["notes"] ~= (segment_anchor_tag_that_object_belongs_to.empty) ? (munge.url_links( "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~ m.captures[1]) ~ " " ~ m.captures[2] ~ "』" ) : (munge.url_links( "{^{" ~ m.captures[1] ~ ".}^}" ~ mkup.mark_internal_site_lnk ~ segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#noteref_" ~ m.captures[1]) ~ " " ~ m.captures[2] ~ "』" ); } return object_notes; } #+END_SRC ****** gathered notes #+name: meta_emitters_endnotes #+BEGIN_SRC d private auto gathered_notes() in { } body { string[][string] endnotes_; if (object_notes.length > 1) { endnotes_["notes"] = (object_notes["notes"].split(rgx.break_string))[0..$-1]; endnotes_["anchor"] = (object_notes["anchor"].split(rgx.break_string))[0..$-1]; } else { endnotes_["notes"] = []; endnotes_["anchor"] = []; } return endnotes_; } #+END_SRC ****** endnote objects #+name: meta_emitters_endnotes #+BEGIN_SRC d private auto endnote_objects(N,O)( N obj_cite_digits, O opt_action, ) in { } body { mixin SiSUnode; ObjGenericComposite[] the_endnotes_section; auto endnotes_ = gathered_notes(); string type_is; string lev, lev_markup_number, lev_collapsed_number; string attrib; int[string] indent; ObjGenericComposite comp_obj_heading_; if ((endnotes_["notes"].length > 0) && (opt_action.backmatter && opt_action.section_endnotes)) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "backmatter"; comp_obj_heading_.of_section = "endnotes"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.segment_anchor_tag = "_part_endnotes"; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_endnotes_section ~= comp_obj_heading_; ++mkn; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "backmatter"; comp_obj_heading_.of_section = "endnotes"; 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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; 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_; ++mkn; } else { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.of_part = "empty"; comp_obj_heading_.of_section = "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_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_endnotes_section ~= comp_obj_heading_; } if (opt_action.backmatter && opt_action.section_endnotes) { ObjGenericComposite comp_obj_endnote_; comp_obj_endnote_ = comp_obj_endnote_.init; comp_obj_endnote_.of_part = "backmatter"; comp_obj_endnote_.of_section = "endnote"; 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_heading_.obj_cite_number_off = ""; comp_obj_heading_.obj_cite_number_type = 0; comp_obj_endnote_.indent_hang = 0; comp_obj_endnote_.indent_base = 0; comp_obj_endnote_.bullet = false; foreach (i, endnote; endnotes_["notes"]) { auto m = endnote.matchFirst(rgx.note_ref); string notenumber = m.captures[1].to!string; string anchor_tag = "note_" ~ notenumber; comp_obj_endnote_.anchor_tags = [ endnotes_["anchor"][i] ]; comp_obj_endnote_.inline_links = true; comp_obj_endnote_.text = endnote.strip; the_endnotes_section ~= comp_obj_endnote_; } } auto t = tuple(the_endnotes_section, obj_cite_digits); return t; } #+END_SRC ***** } #+name: meta_emitters_endnotes #+BEGIN_SRC d } #+END_SRC **** bibliography :bibliography: ***** { biblio struct #+name: meta_emitters_bibliography #+BEGIN_SRC d struct Bibliography { #+END_SRC ****** biblio #+name: meta_emitters_bibliography #+BEGIN_SRC d public JSONValue[] _bibliography_(Bi,BJ)( return ref Bi biblio_unsorted_incomplete, return ref BJ bib_arr_json ) in { debug(asserts) { static assert(is(typeof(biblio_unsorted_incomplete) == string[])); static assert(is(typeof(bib_arr_json) == JSONValue[])); } } body { JSONValue[] biblio_unsorted = _biblio_unsorted_complete_(biblio_unsorted_incomplete, bib_arr_json); biblio_arr_json = []; biblio_unsorted_incomplete = []; JSONValue[] biblio_sorted__ = biblio_sort(biblio_unsorted); biblio_debug(biblio_sorted__); debug(biblio0) { writeln("---"); writeln("unsorted incomplete: ", biblio_unsorted_incomplete.length); writeln("json: ", bib_arr_json.length); writeln("unsorted: ", biblio_unsorted.length); writeln("sorted: ", biblio_sorted__.length); int cntr; int[7] x; while (cntr < x.length) { writeln(cntr, ": ", biblio_sorted__[cntr]["fulltitle"]); cntr++; } } return biblio_sorted__; } #+END_SRC ****** biblio unsorted complete #+name: meta_emitters_bibliography #+BEGIN_SRC d final private JSONValue[] _biblio_unsorted_complete_(Bi,BJ)( Bi biblio_unordered, return ref BJ bib_arr_json ) { debug(asserts) { static assert(is(typeof(biblio_unordered) == string[])); static assert(is(typeof(bib_arr_json) == JSONValue[])); } foreach (bibent; biblio_unordered) { /+ update bib to include deemed_author, needed for: sort_bibliography_array_by_deemed_author_year_title either: sort on multiple fields, or; create such sort field +/ JSONValue j = parseJSON(bibent); if (!empty(j["fulltitle"].str)) { if (!empty(j["author_raw"].str)) { j["deemed_author"]=j["author_arr"][0]; } else if (!empty(j["editor_raw"].str)) { j["deemed_author"]=j["editor_arr"][0]; } j["sortby_deemed_author_year_title"] = ( j["deemed_author"].str ~ "; " ~ j["year"].str ~ "; " ~ j["fulltitle"].str ); } bib_arr_json ~= j; } JSONValue[] biblio_unsorted_array_of_json_objects = bib_arr_json.dup; destroy(bib_arr_json); return biblio_unsorted_array_of_json_objects; } #+END_SRC ****** biblio sort #+name: meta_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: meta_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 ***** } #+name: meta_emitters_bibliography #+BEGIN_SRC d } #+END_SRC **** node structure metadata :structure:metadata:node: ***** { metadata node struct #+name: meta_emitters_metadata #+BEGIN_SRC d struct NodeStructureMetadata { int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7; int obj_cite_digit; int[string] p_; // p_ parent_ static auto rgx = Rgx(); #+END_SRC ****** node metadata emitter #+name: meta_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_digits, 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_digits.on) == int)); static assert(is(typeof(cntr_) == int)); static assert(is(typeof(ptr_) == int)); static assert(is(typeof(is_) == string)); } assert(is_ != "heading"); assert(obj_cite_digits.on.to!int >= 0); } body { assert(is_ != "heading"); // should not be necessary assert(obj_cite_digits.on.to!int >= 0); // should not be necessary 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_digits.on; comp_obj_location.segment_anchor_tag = segment_anchor_tag.to!string; comp_obj_location.parent_ocn = p_["obj_cite_number"]; comp_obj_location.parent_lev_markup = p_["lev_markup_number"]; debug(node) { if (lev_markup_number.match(rgx.levels_numbered_headings)) { writeln("x ", _node.to!string); } else { writeln("- ", _node.to!string); } } assert(comp_obj_location.parent_lev_markup >= 4); assert(comp_obj_location.parent_lev_markup <= 7); assert(comp_obj_location.parent_ocn >= 0); return comp_obj_location; } invariant() { } #+END_SRC ****** node metadata emitter heading, (including most segnames & their pointers) #+name: meta_emitters_metadata #+BEGIN_SRC d ObjGenericComposite node_emitter_heading(T,L,Lm,Lc,Ta,N,C,P,LA,I,PSn,fNr,fNs,fL)( T _text, L lev, Lm lev_markup_number, Lc lev_collapsed_number, Ta segment_anchor_tag, N obj_cite_digits, C cntr_, P ptr_, LA lv_ancestors_txt, I is_, PSn html_segnames_ptr, fNr flag_notes_reg, fNs flag_notes_star, fL flag_links, ) in { debug(asserts) { static assert(is(typeof(_text) == string)); static assert(is(typeof(lev) == string)); static assert(is(typeof(lev_markup_number) == string)); static assert(is(typeof(lev_collapsed_number) == string)); static assert(is(typeof(segment_anchor_tag) == string)); static assert(is(typeof(obj_cite_digits.on) == int)); static assert(is(typeof(cntr_) == int)); static assert(is(typeof(ptr_) == int)); static assert(is(typeof(lv_ancestors_txt) == string[])); static assert(is(typeof(is_) == string)); static assert(is(typeof(html_segnames_ptr) == int)); } assert(is_ == "heading"); assert((obj_cite_digits.on).to!int >= 0); assert( lev_markup_number.match(rgx.levels_numbered), ("not a valid heading level: " ~ lev_markup_number ~ " at " ~ obj_cite_digits.on.to!string) ); if (lev_markup_number.match(rgx.levels_numbered)) { if (lev_markup_number.to!int == 0) { /+ TODO first hit (of two) with this assertion failure, check, fix & reinstate assert(obj_cite_digits.on.to!int == 1, "ERROR header lev markup number is: " ~ lev_markup_number.to!string ~ " obj_cite_digits.on.to!int should == 1 but is: " ~ obj_cite_digits.on.to!string ~ "\n" ~ _text); +/ } } } body { switch (lev_markup_number.to!int) { case 0: lv = DocStructMarkupHeading.h_sect_A; lv0 = obj_cite_digit; 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_digit; 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_digit; 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_digit; 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_digit; 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_digit; 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_digit; 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_digit; 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_.of_part = "body"; _comp_obj_heading_.of_section = "body"; _comp_obj_heading_.is_of = "para"; _comp_obj_heading_.is_a = "heading"; _comp_obj_heading_.text = _text.to!string.strip; _comp_obj_heading_.ocn = obj_cite_digits.on; _comp_obj_heading_.obj_cite_number = (obj_cite_digits.on==0) ? "" : obj_cite_digits.on.to!string; _comp_obj_heading_.obj_cite_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; _comp_obj_heading_.obj_cite_number_type = obj_cite_digits.type; _comp_obj_heading_.segment_anchor_tag = segment_anchor_tag.to!string; _comp_obj_heading_.marked_up_level = lev; _comp_obj_heading_.heading_lev_markup = (!(lev_markup_number.empty) ? lev_markup_number.to!int : 0); _comp_obj_heading_.heading_lev_collapsed = (!(lev_collapsed_number.empty) ? lev_collapsed_number.to!int : 0); _comp_obj_heading_.parent_ocn = p_["obj_cite_number"]; _comp_obj_heading_.parent_lev_markup = p_["lev_markup_number"]; _comp_obj_heading_.heading_ancestors_text = lv_ancestors_txt; _comp_obj_heading_.ptr_doc_object = cntr_; _comp_obj_heading_.ptr_html_segnames = ((lev_markup_number == "4") ? html_segnames_ptr : 0); _comp_obj_heading_.ptr_heading = ptr_; _comp_obj_heading_.inline_notes_reg = flag_notes_reg; _comp_obj_heading_.inline_notes_star = flag_notes_star; _comp_obj_heading_.inline_links = flag_links; debug(node) { if (lev_markup_number.match(rgx.levels_numbered_headings)) { writeln("* ", _node.to!string); } } debug(nodeheading) { if (lev_markup_number.match(rgx.levels_numbered_headings)) { writeln("* ", _node.to!string); } } assert(_comp_obj_heading_.parent_lev_markup <= 7); assert(_comp_obj_heading_.parent_ocn >= 0); if (lev_markup_number.match(rgx.levels_numbered_headings)) { assert(_comp_obj_heading_.heading_lev_markup <= 7); assert(_comp_obj_heading_.ocn >= 0); if (_comp_obj_heading_.parent_lev_markup > 0) { assert(_comp_obj_heading_.parent_lev_markup < _comp_obj_heading_.heading_lev_markup); if (_comp_obj_heading_.ocn != 0) { assert(_comp_obj_heading_.parent_ocn < _comp_obj_heading_.ocn); } } if (_comp_obj_heading_.heading_lev_markup == 0) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_B) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_C) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_B); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_D) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_C); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_1) { assert(_comp_obj_heading_.parent_lev_markup <= DocStructMarkupHeading.h_sect_D); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_2) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_1); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_3) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_2); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_4) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_3); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_5) { } } return _comp_obj_heading_; } invariant() { } #+END_SRC ***** } #+name: meta_emitters_metadata #+BEGIN_SRC d } #+END_SRC *** function assertions :assertions: **** assertions on markup document structure :doc_structure: #+name: abs_functions_assertions #+BEGIN_SRC d pure void assertions_doc_structure(O,Lv)( O an_object, Lv lv ) { debug(asserts) { static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(lv) == int[string])); } if (lv["h3"] > State.off) { assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); assert(lv["h2"] > State.off); } else if (lv["h2"] > State.off) { assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); assert(lv["h3"] == State.off); } else if (lv["h1"] > State.off) { assert(lv["h0"] > State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } else if (lv["h0"] > State.off) { assert(lv["h1"] == State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } else { assert(lv["h0"] == State.off); assert(lv["h1"] == State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } if (lv["h7"] > State.off) { assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); assert(lv["h6"] > State.off); } else if (lv["h6"] > State.off) { assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); assert(lv["h7"] == State.off); } else if (lv["h5"] > State.off) { assert(lv["h4"] > State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } else if (lv["h4"] > State.off) { assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } else { assert(lv["h4"] == State.off); assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h0"] == State.off) { assert(lv["h1"] == State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); assert(lv["h4"] == State.off); assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h1"] == State.off) { assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } if (lv["h2"] == State.off) { assert(lv["h3"] == State.off); } if (lv["h3"] == State.off) { } if (lv["h4"] == State.off) { assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h5"] == State.off) { assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h6"] == State.off) { assert(lv["h7"] == State.off); } if (lv["h7"] == State.off) { } switch ((an_object["lev"]).to!string) { case "A": if (lv["h0"] == State.off) { assert(lv["h1"] == State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); assert(lv["h4"] == State.off); assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } else { // (lv["h0"] > State.off) assert(lv["h0"] == State.off,"error should not enter level A a second time"); } break; case "B": if (lv["h1"] == State.off) { assert(lv["h0"] > State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } else { // (lv["h1"] > State.off) assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); } break; case "C": if (lv["h2"] == State.off) { assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); assert(lv["h3"] == State.off); } else { // (lv["h2"] > State.off) assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); assert(lv["h2"] > State.off); } break; case "D": if (lv["h3"] == State.off) { assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); assert(lv["h2"] > State.off); } else { // (lv["h3"] > State.off) assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); assert(lv["h2"] > State.off); assert(lv["h3"] > State.off); } break; case "1": if (lv["h4"] == State.off) { assert(lv["h0"] > State.off); } else { // (lv["h4"] > State.off) assert(lv["h0"] > State.off); assert(lv["h4"] > State.off); } break; case "2": if (lv["h5"] == State.off) { assert(lv["h0"] > State.off); assert(lv["h4"] > State.off); } else { // (lv["h5"] > State.off) assert(lv["h0"] > State.off); assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); } break; case "3": if (lv["h6"] == State.off) { assert(lv["h0"] > State.off); assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); } else { // (lv["h6"] > State.off) assert(lv["h0"] > State.off); assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); assert(lv["h6"] > State.off); } break; case "4": if (lv["h7"] == State.off) { assert(lv["h0"] > State.off); assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); assert(lv["h6"] > State.off); } else { // (lv["h7"] > State.off) assert(lv["h0"] > State.off); assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); assert(lv["h6"] > State.off); assert(lv["h7"] > State.off); } break; default: break; } } #+END_SRC **** assertions on blocks :blocks: #+name: abs_functions_assertions #+BEGIN_SRC d pure void assertions_flag_types_block_status_none_or_closed(T)(T obj_type_status) { debug(asserts) { static assert(is(typeof(obj_type_status) == int[string])); } assert( (obj_type_status["code"] == TriState.off) || (obj_type_status["code"] == TriState.closing), "code block status: off or closing"); assert( (obj_type_status["poem"] == TriState.off) || (obj_type_status["poem"] == TriState.closing), "poem status: off or closing"); assert( (obj_type_status["table"] == TriState.off) || (obj_type_status["table"] == TriState.closing), "table status: off or closing"); assert( (obj_type_status["group"] == TriState.off) || (obj_type_status["group"] == TriState.closing), "group block status: off or closing"); assert( (obj_type_status["block"] == TriState.off) || (obj_type_status["block"] == TriState.closing), "block status: off or closing"); } #+END_SRC *** doc sect keys seq #+name: template_doc_sect_keys_seq #+BEGIN_SRC d template docSectKeysSeq() { auto docSectKeysSeq(string[][string] document_section_keys_sequenced) { struct doc_sect_keys_seq { auto seg() { return document_section_keys_sequenced["seg"]; } auto scroll() { return document_section_keys_sequenced["scroll"]; } auto sql() { return document_section_keys_sequenced["sql"]; } } return doc_sect_keys_seq(); } } #+END_SRC * 2. Object Setter (Set Abstract Object) :module:sdp:meta_object_setter: set abstracted objects for downstream processing ** 0. module template #+BEGIN_SRC d :tangle ../src/sdp/meta/object_setter.d /++ object setter: setting of sisu objects for downstream processing meta_object_setter.d +/ module sdp.meta.object_setter; template ObjectSetter() { /+ structs +/ <<meta_structs_init>> } #+END_SRC ** 1. initialize structs :struct: *** heading attribute #+name: meta_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 *** [#A] _composite object_ #+name: meta_structs_init #+BEGIN_SRC d struct ObjGenericComposite { // size_t id; string of_part = ""; string of_section = ""; string is_of = ""; string is_a = ""; string text = ""; string obj_cite_number = ""; string obj_cite_number_off = ""; string obj_cite_number_bkidx = ""; int obj_cite_number_type = 0; string[] anchor_tags = []; int indent_base = 0; int indent_hang = 0; bool bullet = false; bool inline_links = false; bool inline_notes_reg = false; bool inline_notes_star = false; string language = ""; // not implemented, consider string code_block_syntax = ""; int table_number_of_columns = 0; double[] table_column_widths = []; string[] table_column_aligns = []; bool table_heading = false; bool table_walls = false; // not implemented int ocn = 0; string segment_anchor_tag = ""; string segname_prev = ""; string segname_next = ""; int parent_lev_markup = 0; int parent_ocn = 0; int[] ancestors = []; string marked_up_level = "9"; int heading_lev_markup = 9; int heading_lev_collapsed = 9; int[] dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0,]; int[] heading_ancestors = [ 0, 0, 0, 0, 0, 0, 0, 0,]; string[] heading_ancestors_text = [ "", "", "", "", "", "", "", "", ]; string[] lev4_subtoc = []; int heading_array_ptr = 0; int ptr_doc_object = 0; int ptr_html_segnames = 0; int ptr_heading = 0; int array_ptr = 0; int heading_array_ptr_segments = 0; string[string][string] node; } #+END_SRC *** The Objects: generic composite object array #+name: meta_structs_init #+BEGIN_SRC d struct TheObjects { ObjGenericComposite[] oca; } #+END_SRC * __END__