#+TITLE: doc_reform document abstraction #+DESCRIPTION: documents - structuring, publishing in multiple formats & search #+FILETAGS: :doc_reform:abstraction: #+AUTHOR: Ralph Amissah #+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]] #+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 #+TAGS: assert(a) class(c) debug(d) mixin(m) doc_reform(s) tangle(T) template(t) WEB(W) noexport(n) - [[./doc_reform.org][doc_reform]] [[./][org/]] * 1. Document Abstraction Process markup document, create document abstraction. ** 0. module template :module:metadoc_from_src: #+BEGIN_SRC d :tangle ../src/doc_reform/meta/metadoc_from_src.d /++ document abstraction: abstraction of sisu markup for downstream processing metadoc_from_src.d +/ module doc_reform.meta.metadoc_from_src; template DocReformDocAbstraction() { /+ ↓ abstraction imports +/ <> /+ ↓ abstraction mixins +/ <> /+ ↓ abstraction struct init +/ <> <> /+ ↓ abstract marked up document +/ auto DocReformDocAbstraction(Src,CMM,Opt,Mfst)( Src markup_sourcefile_content, CMM conf_make_meta, Opt opt_action, Mfst manifest_matter, bool _new_doc ) { static auto rgx = Rgx(); debug(asserts) { static assert(is(typeof(markup_sourcefile_content) == char[][])); } /+ ↓ abstraction init +/ <> /+ abstraction init ↑ +/ <> /+ ↓ ↻ 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 +/ <> if (obj_type_status["code"] == TriState.on) { <> } else if (!matchFirst(line, rgx.skip_from_regular_parse)) { /+ object other than "code block" object (includes regular text paragraph, headings & blocks other than code) +/ /+ heading, glossary, blurb, poem, group, block, quote, table +/ <> } else { /+ not within a block group +/ <> if (line.matchFirst(rgx.block_open)) { <> } else if (!line.empty) { /+ line not empty +/ /+ non blocks (headings, paragraphs) & closed blocks +/ <> } else if (obj_type_status["blocks"] == TriState.closing) { /+ line empty, with blocks flag +/ <> } else { /+ line.empty, post contents, empty variables: +/ <> } // close else for line empty } // close else for not the above } // close after non code, other blocks or regular text <> } /+ ← srcDocLoop closed: loop markup document/text line by line +/ /+ ↓ post loop markup document/text +/ <> <> <> /+ post loop markup document/text ↑ +/ } /+ ← closed: abstract doc source +/ /+ ↓ abstraction functions +/ <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> /+ abstraction functions ↑ +/ /+ ↓ abstraction function emitters +/ <> /+ +/ <> <> <> <> <> <> <> /+ +/ <> <> <> <> <> <> /+ +/ <> <> <> /+ +/ <> /+ +/ <> /+ +/ <> /+ abstraction functions emitters ↑ +/ /+ ↓ abstraction functions assertions +/ <> /+ abstraction functions assertions ↑ +/ } /+ ← closed: template DocReformDocAbstraction +/ <> #+END_SRC ** 1. _pre loop processing_ :pre: *** imports :imports: [[./meta_defaults.org][meta_defaults]] #+name: abs_top_imports #+BEGIN_SRC d import doc_reform.meta; import std.algorithm, std.container, std.file, std.json, std.path; import doc_reform.meta.defaults, doc_reform.meta.object_setter, doc_reform.meta.rgx; #+END_SRC *** mixins :mixins: #+name: abs_top_mixins #+BEGIN_SRC d mixin ObjectSetter; mixin InternalMarkup; mixin DocReformRgxInit; #+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 anchor_tag_; string segment_anchor_tag_that_object_belongs_to; string lev_anchor_tag; string[][string] tag_assoc_html; string[][string] tag_assoc_lv0_to_lv3_html; string[][string] tag_assoc_lv0_to_lv3_epub; 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_structure_markedup_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_structure_markedup_tags_status_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_structure_collapsed_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_structure_collapsed_tags_status_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; enum DomTags { none, open, close, close_and_open, open_still, } #+END_SRC **** method heading ancestors #+name: abs_top_init_struct #+BEGIN_SRC d pure auto obj_heading_ancestors(O)( O obj, string[] lv_ancestors_txt, ) { switch (obj.metainfo.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.tags.heading_ancestors_text = lv_ancestors_txt.dup; } return obj; } #+END_SRC **** method 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.metainfo.dom_structure_markedup_tags_status = dom.dup; return obj; } #+END_SRC **** method 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.metainfo.dom_structure_collapsed_tags_status = dom.dup; return obj; } #+END_SRC **** method 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_tag, notes_reg, notes_star, links, image_no_dimensions } #+END_SRC *** inline para tag associations #+name: abs_inline_para_tag_associations #+BEGIN_SRC d auto inline_para_link_anchor(O,St,TA)(O an_object, St segment_anchor_tag_that_object_belongs_to, TA tag_assoc_html) { static auto rgx = Rgx(); if (auto m = an_object["substantive"].match(rgx.inline_link_anchor)) { if (m.captures[1] !in tag_assoc_html) { tag_assoc_html[(m.captures[1])] = [segment_anchor_tag_that_object_belongs_to]; } else { writeln("a tag named already exists, check text line\n ", an_object["substantive"]); } } return tag_assoc_html; } #+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 DocReformRgxInitFlags; mixin DocReformNode; 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] object_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_.metainfo.is_of_part = "frontmatter"; comp_obj_heading_.metainfo.is_of_section = "toc"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Table of Contents"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "toc"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 4; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; comp_obj_heading_.ptr.html_segnames = html_segnames_ptr; comp_obj_heading_.tags.anchor_tags = ["toc"]; comp_obj_heading_.metainfo.dom_structure_markedup_tags_status = [ 1, 1, 0, 0, 1, 0, 0, 0]; comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 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* _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) { writeln(line); } debug(srclines) { if (!line.empty) { writefln( "* %s", line ); } } #+END_SRC *** check whether object_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_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "glossary"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Glossary"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "_part_glossary"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 1; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; comp_obj_heading_.metainfo.dom_structure_markedup_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; the_glossary_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "glossary"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Glossary"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "glossary"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 4; comp_obj_heading_.metainfo.heading_lev_collapsed = 2; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; comp_obj_heading_.metainfo.dom_structure_markedup_tags_status = [ 1, 1, 0, 0, 1, 0, 0, 0]; comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 1, 0, 0, 0, 0, 0]; comp_obj_heading_.tags.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.metainfo.is_of_part = "backmatter"; comp_obj_para.metainfo.is_of_section = "glossary"; comp_obj_para.metainfo.is_of_type = "para"; comp_obj_para.metainfo.is_a = "glossary"; comp_obj_para.text = line.to!string.strip; comp_obj_para.metainfo.ocn = 0; comp_obj_para.metainfo.object_number_off = ""; comp_obj_para.metainfo.object_number_type = 0; comp_obj_para.attrib.indent_hang = indent["hang_position"]; comp_obj_para.attrib.indent_base = indent["base_position"]; comp_obj_para.attrib.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; if (auto m = line.matchFirst(rgx.para_indent)) { debug(paraindent) { writeln(line); } indent["hang_position"] = (m.captures[1]).to!int; indent["base_position"] = 0; } else if (line.matchFirst(rgx.para_bullet)) { debug(parabullet) { writeln(line); } bullet = true; } else if (auto m = line.matchFirst(rgx.para_indent_hang)) { debug(paraindenthang) { 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) { writeln(line); } indent=[ "hang_position" : (m.captures[1]).to!int, "base_position" : 0, ]; bullet = true; } 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_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "blurb"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Blurb"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "_part_blurb"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 1; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; comp_obj_heading_.metainfo.dom_structure_markedup_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; the_blurb_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "blurb"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Blurb"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "blurb"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 4; comp_obj_heading_.metainfo.heading_lev_collapsed = 2; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; comp_obj_heading_.tags.anchor_tags = ["blurb"]; comp_obj_heading_.metainfo.dom_structure_markedup_tags_status = [ 1, 1, 0, 0, 1, 0, 0, 0]; comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = [ 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_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "blurb"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = line.to!string; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "blurb"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = an_object["lev_markup_number"].to!int; // make int, remove need to conv comp_obj_heading_.metainfo.heading_lev_collapsed = an_object["lev_collapsed_number"].to!int; // make int, remove need to conv comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.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.metainfo.is_of_part = "backmatter"; comp_obj_para.metainfo.is_of_section = "blurb"; comp_obj_para.metainfo.is_of_type = "para"; comp_obj_para.metainfo.is_a = "blurb"; comp_obj_para.text = munge.url_links(line.to!string.strip).replaceFirst(rgx.para_attribs, ""); comp_obj_para.metainfo.ocn = 0; comp_obj_para.metainfo.object_number_off = ""; comp_obj_para.metainfo.object_number_type = 0; comp_obj_para.attrib.indent_hang = indent["hang_position"]; comp_obj_para.attrib.indent_base = indent["base_position"]; comp_obj_para.has.inline_links = true; comp_obj_para.attrib.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, object_number_poem, conf_make_meta, segment_anchor_tag_that_object_belongs_to); 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"); object_number_poem["start"] = obj_cite_digits.on.to!string; } _start_block_(line, obj_type_status, object_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.metainfo.is_of_part = "comment"; // breaks flow comp_obj_comment.metainfo.is_of_section = "comment"; // breaks flow comp_obj_comment.metainfo.is_of_type = "comment"; comp_obj_comment.metainfo.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, object_number_poem, conf_make_meta, segment_anchor_tag_that_object_belongs_to, ); #+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); 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, _new_doc); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[sObj.content]; anchor_tag = substantive_object_and_anchor_tags_tuple[sObj.anchor_tag]; if (_new_doc) { cnt1 = 1; cnt2 = 1; cnt3 = 1; _new_doc = false; } if ( an_object["lev_markup_number"].to!int == 4 && (!(anchor_tag.empty) || (tag_assoc_lv0_to_lv3_html.length > 1)) ) { segment_anchor_tag_that_object_belongs_to = anchor_tag; lev_anchor_tag = anchor_tag; tag_assoc_html[anchor_tag] = [segment_anchor_tag_that_object_belongs_to]; if (tag_assoc_lv0_to_lv3_html.length > 1) { /+ names used for html markup segments 1 to 4 (rather than epub which has separate segments for A to D) +/ foreach (lv0_to_lv3_html_tag; tag_assoc_lv0_to_lv3_html) { tag_assoc_html[lv0_to_lv3_html_tag[0]] = [segment_anchor_tag_that_object_belongs_to]; } } segment_anchor_tag_that_object_belongs_to_uri = anchor_tag ~ ".fnSuffix"; anchor_tag_ = anchor_tag; tag_assoc_lv0_to_lv3_html = tag_assoc_lv0_to_lv3_html.init; } else if (an_object["lev_markup_number"].to!int > 4) { segment_anchor_tag_that_object_belongs_to = anchor_tag_; lev_anchor_tag = anchor_tag; tag_assoc_html[anchor_tag] = [segment_anchor_tag_that_object_belongs_to]; 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"; tag_assoc_lv0_to_lv3_html[segn] = [""]; tag_assoc_lv0_to_lv3_epub[segn] = ["segn"]; 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=obj_cite_digits.on.to!string; 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_markup_number"], // string an_object["lev_collapsed_number"], // string segment_anchor_tag_that_object_belongs_to, // string lev_anchor_tag, // string tag_assoc_html, 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, lev_anchor_tag, tag_assoc_html, 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag]; tag_assoc_html = inline_para_link_anchor(an_object, segment_anchor_tag_that_object_belongs_to, tag_assoc_html); comp_obj_para = comp_obj_para.init; comp_obj_para.metainfo.is_of_part = "body"; comp_obj_para.metainfo.is_of_section = "body"; comp_obj_para.metainfo.is_of_type = "para"; comp_obj_para.metainfo.is_a = "para"; comp_obj_para.text = an_object["substantive"].to!string.strip; comp_obj_para.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_para.metainfo.ocn = obj_cite_digits.digit; comp_obj_para.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_para.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_para.metainfo.object_number_type = obj_cite_digits.type; comp_obj_para.attrib.indent_hang = indent["hang_position"]; comp_obj_para.attrib.indent_base = indent["base_position"]; comp_obj_para.attrib.bullet = bullet; comp_obj_para.tags.anchor_tags = [anchor_tag]; comp_obj_para.has.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_para.has.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_para.has.inline_links = substantive_obj_misc_tuple[sObj.links]; comp_obj_para.has.contains_image_without_dimensions = substantive_obj_misc_tuple[sObj.image_no_dimensions]; 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].metainfo.is_a == "para") || (the_document_body_section[$-1].metainfo.is_a == "heading") || (the_document_body_section[$-1].metainfo.is_a == "quote") || (the_document_body_section[$-1].metainfo.is_a == "group") || (the_document_body_section[$-1].metainfo.is_a == "block") || (the_document_body_section[$-1].metainfo.is_a == "verse")) && (the_document_body_section.length > previous_length)) { if ((the_document_body_section[$-1].metainfo.is_a == "heading") && (the_document_body_section[$-1].metainfo.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].metainfo.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].metainfo.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_.metainfo.is_of_part = "empty"; comp_obj_heading_.metainfo.is_of_section = "empty"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "(skip) there is no Glossary section"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.metainfo.heading_lev_markup = 1; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; the_glossary_section ~= comp_obj_heading_; } 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_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "bibliography"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Bibliography"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "_part_bibliography"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 1; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; the_bibliography_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "bibliography"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Bibliography"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "bibliography"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 4; comp_obj_heading_.metainfo.heading_lev_collapsed = 2; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; comp_obj_heading_.tags.anchor_tags = ["bibliography"]; the_bibliography_section ~= comp_obj_heading_; } else { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.metainfo.is_of_part = "empty"; comp_obj_heading_.metainfo.is_of_section = "empty"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "(skip) there is no Bibliography"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.metainfo.heading_lev_markup = 1; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.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.metainfo.is_of_part = "backmatter"; comp_obj_para.metainfo.is_of_section = "bibliography"; comp_obj_para.metainfo.is_of_type = "para"; comp_obj_para.metainfo.is_a = "bibliography"; comp_obj_para.text = out_.to!string.strip; comp_obj_para.metainfo.ocn = 0; comp_obj_para.metainfo.object_number_off = ""; comp_obj_para.metainfo.object_number_type = 0; comp_obj_para.attrib.indent_hang = 0; comp_obj_para.attrib.indent_base = 1; comp_obj_para.attrib.bullet = bullet; comp_obj_para.tags.anchor_tags = [anchor_tag]; 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_.metainfo.is_of_part = "empty"; comp_obj_heading_.metainfo.is_of_section = "empty"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "(skip) there is no Blurb section"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_para.metainfo.object_number_off = ""; comp_obj_para.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = ""; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 1; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.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.metainfo.is_of_part = "frontmatter"; comp_obj_toc.metainfo.is_of_section = "toc"; comp_obj_toc.metainfo.is_of_type = "para"; comp_obj_toc.metainfo.is_a = "toc"; comp_obj_toc.metainfo.ocn = 0; comp_obj_toc.metainfo.object_number_off = ""; comp_obj_toc.metainfo.object_number_type = 0; comp_obj_toc.attrib.indent_hang = indent["hang_position"]; comp_obj_toc.attrib.indent_base = indent["base_position"]; comp_obj_toc.attrib.bullet = false; if (the_endnotes_section.length > 1) { toc_txt_ = format( "{ %s }%s%s%s", "Endnotes", mkup.mark_internal_site_lnk, "endnotes", ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.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", ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Glossary", "glossary", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.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", ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Bibliography", "bibliography", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.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", ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.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", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.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", ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Blurb", "blurb", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.has.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.attrib.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.attrib.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 *** ↻ *LOOPs* _post main-loop loops_ :loop:post: **** 1. ↻ _Loop as required_ (e.g. backmatter): loop up to lev4, extract html_segnames, set pointers this extra loop is used/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 this loop unless the html seg or epub output is selected ***** Methods ****** get ancestors markup #+name: abs_post #+BEGIN_SRC d int[] _get_ancestors_markup(O)(O obj, ref int[] _ancestors_markup) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup == 1) { _ancestors_markup = [ _ancestors_markup[0], 0,0,0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_markup == 2) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], 0,0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_markup == 3) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], 0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_markup == 4) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], _ancestors_markup[3], 0,0,0,0 ]; } if (obj.metainfo.heading_lev_markup == 5) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], _ancestors_markup[3], _ancestors_markup[4], 0,0,0 ]; } if (obj.metainfo.heading_lev_markup == 6) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], _ancestors_markup[3], _ancestors_markup[4], _ancestors_markup[5], 0,0 ]; } if (obj.metainfo.heading_lev_markup == 7) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], _ancestors_markup[3], _ancestors_markup[4], _ancestors_markup[5], _ancestors_markup[6], 0 ]; } if (obj.metainfo.heading_lev_markup == 8) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], _ancestors_markup[3], _ancestors_markup[4], _ancestors_markup[5], _ancestors_markup[6], _ancestors_markup[7] ]; } _ancestors_markup[obj.metainfo.heading_lev_markup] = obj.metainfo.ocn; } debug(ancestor_markup) { writeln("marked up: ", _ancestors_markup); } return _ancestors_markup; } #+END_SRC ****** get ancestors collapsed #+name: abs_post #+BEGIN_SRC d int[] _get_ancestors_collapsed(O)(O obj, ref int[] _ancestors_collapsed) { if (obj.metainfo.is_a == "heading") { if (obj.metainfo.heading_lev_collapsed == 1) { _ancestors_collapsed = [ _ancestors_collapsed[0], 0,0,0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 2) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], 0,0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 3) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], 0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 4) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], _ancestors_collapsed[3], 0,0,0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 5) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], _ancestors_collapsed[3], _ancestors_collapsed[4], 0,0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 6) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], _ancestors_collapsed[3], _ancestors_collapsed[4], _ancestors_collapsed[5], 0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 7) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], _ancestors_collapsed[3], _ancestors_collapsed[4], _ancestors_collapsed[5], _ancestors_collapsed[6], 0 ]; } if (obj.metainfo.heading_lev_collapsed == 8) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], _ancestors_collapsed[3], _ancestors_collapsed[4], _ancestors_collapsed[5], _ancestors_collapsed[6], _ancestors_collapsed[7] ]; } _ancestors_collapsed[obj.metainfo.heading_lev_collapsed] = obj.metainfo.ocn; } debug(ancestor_collapsed) { writeln("collapsed: ", _ancestors_collapsed); } return _ancestors_collapsed; } #+END_SRC ***** ↻ Loop section: document body [bd] - substantive object numbers already exist - number un-numbered non-substantive text #+name: abs_post #+BEGIN_SRC d /+ multiple 1~ levels, loop through document body +/ if (the_document_body_section.length > 1) { int[] _ancestors_markup = [0,0,0,0,0,0,0,0]; int[][] _ancestors_markup_; _ancestors_markup = [1,0,0,0,0,0,0,0]; _ancestors_markup_ ~= _ancestors_markup; int[] _ancestors_collapsed = [0,0,0,0,0,0,0,0]; int[][] _ancestors_collapsed_; _ancestors_collapsed = [1,0,0,0,0,0,0,0]; _ancestors_collapsed_ ~= _ancestors_collapsed; foreach (ref obj; the_document_body_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.markedup_ancestors = _get_ancestors_markup(obj, _ancestors_markup); obj.metainfo.collapsed_ancestors = _get_ancestors_collapsed(obj, _ancestors_collapsed); obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } } debug(ancestors) { writeln("ancestors markup o_n: ", obj.metainfo.markedup_ancestors); writeln("ancestors collapsed o_n: ", obj.metainfo.markedup_ancestors); } } #+END_SRC ***** ↻ Loop section: endnotes [en] #+name: abs_post #+BEGIN_SRC d if (the_endnotes_section.length > 1) { html_segnames ~= "endnotes"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref obj; the_endnotes_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } if (obj.metainfo.heading_lev_markup == 4) { obj.ptr.html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } #+END_SRC ***** ↻ Loop section: glossary [gl] #+name: abs_post #+BEGIN_SRC d if (the_glossary_section.length > 1) { html_segnames ~= "glossary"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref obj; the_glossary_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } if (obj.metainfo.heading_lev_markup == 4) { obj.ptr.html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } #+END_SRC ***** ↻ Loop section: bibliography [bb] #+name: abs_post #+BEGIN_SRC d if (the_bibliography_section.length > 1) { html_segnames ~= "bibliography"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref obj; the_bibliography_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } if (obj.metainfo.heading_lev_markup == 4) { obj.ptr.html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } #+END_SRC ***** ↻ Loop section: book index [bi] #+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 obj; the_bookindex_section["scroll"]) { if (obj.metainfo.is_a == "heading") { obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } if (obj.metainfo.heading_lev_markup == 4) { obj.ptr.html_segnames = html_segnames_ptr; break; } } foreach (ref obj; the_bookindex_section["seg"]) { if (obj.metainfo.heading_lev_markup == 4) { obj.ptr.html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } #+END_SRC ***** ↻ Loop section: blurb [bl] #+name: abs_post #+BEGIN_SRC d if (the_blurb_section.length > 1) { html_segnames ~= "blurb"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref obj; the_blurb_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } if (obj.metainfo.heading_lev_markup == 4) { obj.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! - this loop could conveniently be used more extensively for ancestors as well (though this information can be extracted earlier) Build here: - DOM structure - ancestors & 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 - numbering - already given - substantive object numbers - endnote - provide - glossary - bibliography - book index - blurb - other non-substantive objects (prefix & other stuff) - you could also 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 this (the third) pass all previous and next segment names are known - next are not yet known for backmatter during the second pas ***** Methods ****** decendants #+name: abs_post #+BEGIN_SRC d auto get_decendants(S)(S document_sections) { int[string] _heading_ocn_decendants; string[] _ocn_open_key = ["","","","","","","",""]; auto _doc_sect_length = document_sections.length - 1; int _last_ocn; foreach (_lg, ref obj; document_sections) { if (obj.metainfo.is_a == "heading") { foreach (_dts_lv, dom_tag_status; obj.metainfo.dom_structure_markedup_tags_status) { switch (dom_tag_status) { case DomTags.none: break; case DomTags.open: _ocn_open_key[_dts_lv] = (obj.metainfo.ocn).to!string; _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn; break; case DomTags.close: if (_ocn_open_key[_dts_lv].empty) { _ocn_open_key[_dts_lv] = "0"; } _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn - 1; _ocn_open_key[_dts_lv] = (0).to!string; break; case DomTags.close_and_open: if (_ocn_open_key[_dts_lv].empty) { _ocn_open_key[_dts_lv] = "0"; } _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn - 1; _ocn_open_key[_dts_lv] = (obj.metainfo.ocn).to!string; _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn; break; case DomTags.open_still: break; default: break; } } } if (obj.metainfo.ocn > 0) { _last_ocn = obj.metainfo.ocn; } if (_lg == _doc_sect_length) { _heading_ocn_decendants["1"] = _last_ocn; // close existing o_n key } } Tuple!(int, int)[] pairs; foreach (pair; _heading_ocn_decendants.byPair) { pairs ~= tuple(pair[0].to!int, pair[1]); } return pairs.sort; } #+END_SRC ****** images: extract #+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_lv0_to_4; #+END_SRC ****** images: dimensions #+name: abs_post #+BEGIN_SRC d auto _image_dimensions(M,O)(M manifest_matter, O obj) { if (obj.has.contains_image_without_dimensions) { import std.math; import imageformats; int w, h, chans; real _w, _h; int max_width = 640; foreach (m; obj.text.matchAll(rgx.inline_image_without_dimensions)) { debug(images) { writeln(manifest_matter.src.image_dir_path ~ "/" ~ m.captures["img"]); } read_image_info(manifest_matter.src.image_dir_path ~ "/" ~ m.captures["img"], w, h, chans); // calculate, decide max width and proportionally reduce to keep w & h within it debug(images) { writeln("width: ", w, ", height: ", h); } if (w > max_width) { _w = max_width; _h = round((max_width / w.to!real) * h.to!real); } else { _w = w; _h = h; } obj.text = obj.text.replaceFirst( rgx.inline_image_without_dimensions, ("$1☼$3,w" ~ _w.to!string ~ "h" ~ _h.to!string ~ " $6") ); } debug(images) { writeln("image without dimensions: ", obj.text); } } return obj; } #+END_SRC ***** ↻ Loop section: head #+name: abs_post #+BEGIN_SRC d foreach (ref obj; the_document_head_section) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup <= 4) { segnames_lv0_to_4 ~= obj.tags.segment_anchor_tag; } if (obj.metainfo.heading_lev_markup == 0) { /+ TODO second hit (of two) with same assertion failure, check, fix and reinstate assert( obj.metainfo.ocn == 1, "Title OCN should be 1 not: " ~ obj.metainfo.ocn.to!string); // bug introduced 0.18.1 +/ obj.metainfo.ocn = 1; obj.metainfo.object_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)) { obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } } #+END_SRC ***** ↻ Loop section: toc [to] #+name: abs_post #+BEGIN_SRC d if (the_table_of_contents_section["scroll"].length > 1) { /+ scroll +/ dom_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup; dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup; foreach (ref obj; the_table_of_contents_section["scroll"]) { if (obj.metainfo.is_a == "heading") { if (obj.metainfo.heading_lev_markup <= 4) { segnames_lv0_to_4 ~= obj.tags.segment_anchor_tag; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], obj.tags.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)) { obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } } /+ seg +/ dom_structure_markedup_tags_status = dom_structure_markedup_tags_status_buffer.dup; dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status_buffer.dup; foreach (ref obj; the_table_of_contents_section["seg"]) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup <= 4) { segnames_lv0_to_4 ~= obj.tags.segment_anchor_tag; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], obj.tags.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_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } } } #+END_SRC ***** ↻ Loop section: document body [bd] #+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.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup <= 4) { segnames_lv0_to_4 ~= obj.tags.segment_anchor_tag; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.lev4_subtoc = lev4_subtoc[obj.tags.segment_anchor_tag]; obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; if (html_segnames.length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; } assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], obj.tags.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)) { obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.metainfo.is_a == "para") { _images ~= extract_images(obj.text); obj = _image_dimensions(manifest_matter, obj); } } } auto images=uniq(_images.sort()); #+END_SRC ***** ↻ Loop section: endnotes [en] - endnotes have their own number, (also use in node) and they belong to calling object #+name: abs_post #+BEGIN_SRC d /+ optional only one 1~ level +/ if (the_endnotes_section.length > 1) { dom_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup; dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup; dom_structure_markedup_tags_status = dom_structure_markedup_tags_status_buffer.dup; dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status_buffer.dup; foreach (ref obj; the_endnotes_section) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } obj_cite_digits = ocn_emit(OCNstatus.on); obj.metainfo.ocn = obj_cite_digits.digit; if (obj.metainfo.heading_lev_markup <= 4) { segnames_lv0_to_4 ~= obj.tags.segment_anchor_tag; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; if (html_segnames.length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; } assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], obj.tags.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)) { obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } } } #+END_SRC ***** ↻ Loop section: glossary [gl] - add glossary numbering, (also use in node) no need to show in text #+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.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } obj_cite_digits = ocn_emit(OCNstatus.on); obj.metainfo.ocn = obj_cite_digits.digit; if (obj.metainfo.heading_lev_markup <= 4) { segnames_lv0_to_4 ~= obj.tags.segment_anchor_tag; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; if (html_segnames.length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; } assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], obj.tags.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)) { obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.metainfo.is_a == "glossary") { obj_cite_digits = ocn_emit(OCNstatus.on); obj.metainfo.ocn = obj_cite_digits.digit; } } } #+END_SRC ***** ↻ Loop section: bibliography [bb] - add bibliography numbering, (also use in node) no need to show in text #+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.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } obj_cite_digits = ocn_emit(OCNstatus.on); obj.metainfo.ocn = obj_cite_digits.digit; if (obj.metainfo.heading_lev_markup <= 4) { segnames_lv0_to_4 ~= obj.tags.segment_anchor_tag; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; if (html_segnames.length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; } assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], obj.tags.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)) { obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.metainfo.is_a == "bibliography") { obj_cite_digits = ocn_emit(OCNstatus.on); obj.metainfo.ocn = obj_cite_digits.on; } } } #+END_SRC ***** ↻ Loop section: book index (scroll, seg) [bi] - add book index numbering?, (also use in node) no need to show in text #+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_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup; dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup; foreach (ref obj; the_bookindex_section["scroll"]) { if (obj.metainfo.is_a == "heading") { debug(dom) { } obj_cite_digits = ocn_emit(OCNstatus.on); obj.metainfo.ocn = obj_cite_digits.on; if (obj.metainfo.heading_lev_markup <= 4) { segnames_lv0_to_4 ~= obj.tags.segment_anchor_tag; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; if (html_segnames.length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; } assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], obj.tags.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)) { obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.metainfo.is_a == "bookindex") { obj_cite_digits = ocn_emit(OCNstatus.bkidx); obj.metainfo.ocn = obj_cite_digits.digit; obj.metainfo.o_n_book_index = obj_cite_digits.bkidx; obj.metainfo.object_number_type = OCNtype.bkidx; } } /+ seg +/ dom_structure_markedup_tags_status = dom_structure_markedup_tags_status_buffer.dup; dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status_buffer.dup; foreach (ref obj; the_bookindex_section["seg"]) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } obj.metainfo.ocn = ++ocn_; if (obj.metainfo.heading_lev_markup <= 4) { segnames_lv0_to_4 ~= obj.tags.segment_anchor_tag; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; if (html_segnames.length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; } assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], obj.tags.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)) { obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.metainfo.is_a == "bookindex") { ocn_bidx_ = ++ocn_bkidx_; obj.metainfo.o_n_book_index = ocn_bidx_; // FIX need to distinguish from regular ocn obj.metainfo.object_number_type = OCNtype.bkidx; } } /+ TODO assert failure, reinstate assert(obj_cite_digit_bkidx == ocn_bidx_ obj_cite_digit_bkidx ~ " == ocn_" ~ ocn_ ~ "?"); +/ } #+END_SRC ***** ↻ Loop section: blurb [bl] #+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.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } obj_cite_digits = ocn_emit(OCNstatus.on); obj.metainfo.ocn = obj_cite_digits.on; if (obj.metainfo.heading_lev_markup <= 4) { segnames_lv0_to_4 ~= obj.tags.segment_anchor_tag; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = html_segnames[obj.ptr.html_segnames - 1]; if (html_segnames.length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = html_segnames[obj.ptr.html_segnames + 1]; } assert(obj.tags.segment_anchor_tag == html_segnames[obj.ptr.html_segnames], obj.tags.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)) { obj = obj_dom_structure_set_markup_tags(obj, dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj_dom_set_collapsed_tags(obj, dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj_heading_ancestors(obj, lv_ancestors_txt); } else if (obj.metainfo.is_a == "blurb") { obj_cite_digits = ocn_emit(OCNstatus.off); obj.metainfo.object_number_off = obj_cite_digits.off.to!string; obj.metainfo.object_number_type = OCNtype.non; } } } #+END_SRC ***** ↻ Loop sections: get decendants #+name: abs_post #+BEGIN_SRC d if (the_document_body_section.length > 1) { auto pairs = get_decendants( the_document_head_section ~ the_document_body_section ~ the_endnotes_section ~ the_glossary_section ~ the_bibliography_section ~ the_bookindex_section["scroll"] ~ the_blurb_section ); debug(decendants_tuple) { pairs = pairs.sort(); foreach (pair; pairs) { // (pair; pairs.sort()) writeln(pair[0], "..", pair[1]); } } foreach (ref obj; the_document_head_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } if (the_document_body_section.length > 1) { foreach (ref obj; the_document_body_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_endnotes_section.length > 1) { foreach (ref obj; the_endnotes_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_glossary_section.length > 1) { foreach (ref obj; the_glossary_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_bibliography_section.length > 1) { foreach (ref obj; the_bibliography_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_bookindex_section["scroll"].length > 1) { foreach (ref obj; the_bookindex_section["scroll"]) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_blurb_section.length > 1) { foreach (ref obj; the_blurb_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } } #+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.metainfo.dom_structure_markedup_tags_status = dom_structure_markedup_tags_status; - obj.metainfo.dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status; +/ comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.metainfo.is_of_part = "empty"; comp_obj_heading_.metainfo.is_of_section = "empty"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_para.metainfo.object_number_off = ""; comp_obj_para.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = ""; comp_obj_heading_.metainfo.heading_lev_markup = 9; comp_obj_heading_.metainfo.heading_lev_collapsed = 9; comp_obj_heading_.metainfo.parent_ocn = 0; comp_obj_heading_.metainfo.parent_lev_markup = 0; comp_obj_heading_.metainfo.dom_structure_markedup_tags_status = dom_structure_markedup_tags_status.dup; comp_obj_heading_.metainfo.dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status.dup; comp_obj_heading_ = obj_dom_structure_set_markup_tags(comp_obj_heading_, dom_structure_markedup_tags_status, 0); comp_obj_heading_ = obj_dom_set_collapsed_tags(comp_obj_heading_, dom_structure_collapsed_tags_status, 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"; } auto sequenced_document_keys = docSectKeysSeq!()(document_section_keys_sequenced); #+END_SRC *** dup #+name: abs_post #+BEGIN_SRC d auto segnames_lv4 = 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); obj_cite_digits = ocn_emit(OCNstatus.reset); biblio_arr_json = []; obj_cite_digit_ = 0; html_segnames_ptr = 0; html_segnames_ptr_cntr = 0; content_non_header = "8"; dom_structure_markedup_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; dom_structure_markedup_tags_status_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; dom_structure_collapsed_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; dom_structure_collapsed_tags_status_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; #+END_SRC *** [#A] ↻ _reloop_ :reloop: - this would work, but no need for extra loop, remove #+name: abs_post_doc_reloop_processing #+BEGIN_SRC d debug(abstraction) { foreach (part; sequenced_document_keys.scroll) { foreach (ref obj; document_the[part]) { debug(node_misc) { if (obj.metainfo.is_a == "heading") { writeln("heading ancestors text?: ", obj.tags.heading_ancestors_text); } } debug(node_headings) { if (obj.metainfo.is_a == "heading") { writeln("---"); writeln(obj.text); writeln(" node: ", obj.metainfo.node); writeln(" ocn: ", obj.metainfo.ocn); writeln(" markedup heading lev: ", obj.metainfo.heading_lev_markup); writeln(" collapsed heading lev ", obj.metainfo.heading_lev_collapsed); writeln(" parent ocn: ", obj.metainfo.parent_ocn); writeln(" parent lev: ", obj.metainfo.parent_lev_markup); writeln(" markedup ancestors o_n: ", obj.metainfo.markedup_ancestors); writeln(" dom markedup: ", obj.metainfo.dom_structure_markedup_tags_status); writeln(" collapsed ancestors o_n: ", obj.metainfo.collapsed_ancestors); writeln(" dom collapsed: ", obj.metainfo.dom_structure_collapsed_tags_status); } } debug(node_all) { writeln("---"); if (obj.metainfo.is_a == "heading") { writeln(obj.text); } writeln("node: ", obj.metainfo.node); writeln("ocn: ", obj.metainfo.ocn); writeln("markedup heading lev: ", obj.metainfo.heading_lev_markup); writeln("collapsed heading lev ", obj.metainfo.heading_lev_collapsed); writeln("markedup ancestors o_n: ", obj.metainfo.markedup_ancestors); writeln("collapsed ancestors o_n: ", obj.metainfo.collapsed_ancestors); writeln("dom markedup: ", obj.metainfo.dom_structure_markedup_tags_status); writeln("dom collapsed: ", obj.metainfo.dom_structure_collapsed_tags_status); writeln("parent ocn: ", obj.metainfo.parent_ocn); writeln("parent lev: ", obj.metainfo.parent_lev_markup); writeln("Node: ", obj.metainfo.ocn); } } } } #+END_SRC *** [#A] _return document tuple_ :return:tuple: #+name: abs_return_tuple #+BEGIN_SRC d auto t = tuple( document_the, sequenced_document_keys, segnames_lv4, segnames_lv0_to_4, tag_assoc_html, 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 object_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 object_number is on or turned off +/ if (line.matchFirst(rgx.object_number_block_marks)) { /+ switch off object_number +/ if (line.matchFirst(rgx.object_number_off_block)) { obj_type_status["ocn_status_off_for_multiple_objects"] = TriState.on; debug(ocnoff) { writeln(line); } } if (line.matchFirst(rgx.object_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.object_number_off)) { obj_type_status["ocn_status"] = OCNstatus.off; } else if (line.matchFirst(rgx.object_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.object_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("\b" ~ 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("\b" ~ conf_make_meta.make.bold[Substitute.match]), conf_make_meta.make.bold[Substitute.markup] ); } if (conf_make_meta.make.emphasis) { line = line.replaceAll( regex("\b" ~ conf_make_meta.make.emphasis[Substitute.match]), conf_make_meta.make.emphasis[Substitute.markup] ); } if (conf_make_meta.make.italics) { line = line.replaceAll( regex("\b" ~ 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 object_number_poem ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(obj_type_status) == int[string])); static assert(is(typeof(object_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 ); } object_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 ); } object_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 DocReformBiblio; 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) { 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,Ts)( L line, return ref O an_object, return ref T obj_type_status, return ref C cntr, N object_number_poem, CMM conf_make_meta, Ts segment_anchor_tag_that_object_belongs_to, ) { 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(object_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) { writefln( "* [poem curly] %s", line ); } if (processing.length > 0) { an_object[an_object_key] = processing["verse"]; } debug(poem) { 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag]; tag_assoc_html = inline_para_link_anchor(an_object, segment_anchor_tag_that_object_belongs_to, tag_assoc_html); comp_obj_block = comp_obj_block.init; comp_obj_block.metainfo.is_of_part = "body"; comp_obj_block.metainfo.is_of_section = "body"; comp_obj_block.metainfo.is_of_type = "block"; comp_obj_block.metainfo.is_a = "verse"; comp_obj_block.metainfo.ocn = obj_cite_digits.on; comp_obj_block.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_block.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_block.metainfo.object_number_type = obj_cite_digits.type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.has.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.has.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.has.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; } object_reset(an_object); processing.remove("verse"); ++cntr; } object_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, lev_anchor_tag, tag_assoc_html, 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag]; tag_assoc_html = inline_para_link_anchor(an_object, segment_anchor_tag_that_object_belongs_to, tag_assoc_html); comp_obj_block = comp_obj_block.init; comp_obj_block.metainfo.is_of_part = "body"; comp_obj_block.metainfo.is_of_section = "body"; comp_obj_block.metainfo.is_of_type = "block"; comp_obj_block.metainfo.is_a = "verse"; comp_obj_block.metainfo.ocn = obj_cite_digits.on; comp_obj_block.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_block.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_block.metainfo.object_number_type = obj_cite_digits.type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.has.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.has.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.has.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) { 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag]; tag_assoc_html = inline_para_link_anchor(an_object, segment_anchor_tag_that_object_belongs_to, tag_assoc_html); comp_obj_block = comp_obj_block.init; comp_obj_block.metainfo.is_of_part = "body"; comp_obj_block.metainfo.is_of_section = "body"; comp_obj_block.metainfo.is_of_type = "block"; comp_obj_block.metainfo.is_a = "verse"; comp_obj_block.metainfo.ocn = obj_cite_digits.on; comp_obj_block.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_block.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_block.metainfo.object_number_type = obj_cite_digits.type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.has.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.has.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.has.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; object_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, lev_anchor_tag, tag_assoc_html, 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag]; tag_assoc_html = inline_para_link_anchor(an_object, segment_anchor_tag_that_object_belongs_to, tag_assoc_html); comp_obj_block = comp_obj_block.init; comp_obj_block.metainfo.is_of_part = "body"; comp_obj_block.metainfo.is_of_section = "body"; comp_obj_block.metainfo.is_of_type = "block"; comp_obj_block.metainfo.is_a = "verse"; comp_obj_block.metainfo.ocn = obj_cite_digits.on; comp_obj_block.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_block.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_block.metainfo.object_number_type = obj_cite_digits.type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.has.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.has.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.has.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, lev_anchor_tag, tag_assoc_html, 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; comp_obj_block.metainfo.ocn = obj_cite_digits.on; comp_obj_block.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_block.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_block.metainfo.object_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,Ts)( 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] object_number_poem, CMM conf_make_meta, Ts segment_anchor_tag_that_object_belongs_to, ) { 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, lev_anchor_tag, tag_assoc_html, 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag]; tag_assoc_html = inline_para_link_anchor(an_object, segment_anchor_tag_that_object_belongs_to, tag_assoc_html); comp_obj_block = comp_obj_block.init; comp_obj_block.metainfo.is_of_part = "body"; comp_obj_block.metainfo.is_of_section = "body"; comp_obj_block.metainfo.is_of_type = "block"; comp_obj_block.metainfo.is_a = "quote"; comp_obj_block.metainfo.ocn = obj_cite_digits.on; comp_obj_block.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_block.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_block.metainfo.object_number_type = obj_cite_digit_type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.has.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.has.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.has.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, lev_anchor_tag, tag_assoc_html, 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag]; tag_assoc_html = inline_para_link_anchor(an_object, segment_anchor_tag_that_object_belongs_to, tag_assoc_html); comp_obj_block = comp_obj_block.init; comp_obj_block.metainfo.is_of_part = "body"; comp_obj_block.metainfo.is_of_section = "body"; comp_obj_block.metainfo.is_of_type = "block"; comp_obj_block.metainfo.is_a = "group"; comp_obj_block.metainfo.ocn = obj_cite_digits.on; comp_obj_block.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_block.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_block.metainfo.object_number_type = obj_cite_digits.type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.has.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.has.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.has.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, lev_anchor_tag, tag_assoc_html, 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; comp_obj_block = comp_obj_block.init; comp_obj_block.metainfo.is_of_part = "body"; comp_obj_block.metainfo.is_of_section = "body"; comp_obj_block.metainfo.is_of_type = "block"; comp_obj_block.metainfo.is_a = "block"; comp_obj_block.metainfo.ocn = obj_cite_digits.on; comp_obj_block.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_block.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_block.metainfo.object_number_type = obj_cite_digit_type; comp_obj_block.text = an_object["substantive"]; comp_obj_block.has.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.has.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.has.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, lev_anchor_tag, tag_assoc_html, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); comp_obj_poem_ocn = comp_obj_poem_ocn.init; comp_obj_poem_ocn.metainfo.is_of_part = "body"; comp_obj_poem_ocn.metainfo.is_of_section = "body"; comp_obj_poem_ocn.metainfo.is_of_type = "block"; comp_obj_poem_ocn.metainfo.is_a = "poem"; comp_obj_poem_ocn.metainfo.ocn = obj_cite_digits.on; comp_obj_poem_ocn.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; // comp_obj_poem_ocn.metainfo.o_n_book_index = obj_cite_digits.bkidx; // comp_obj_poem_ocn.metainfo.object_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, lev_anchor_tag, tag_assoc_html, 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tag = substantive_obj_misc_tuple[sObj.anchor_tag]; comp_obj_code = comp_obj_code.init; comp_obj_code.metainfo.is_of_part = "body"; comp_obj_code.metainfo.is_of_section = "body"; comp_obj_code.metainfo.is_of_type = "block"; comp_obj_code.metainfo.is_a = "code"; comp_obj_code.metainfo.ocn = obj_cite_digits.on; comp_obj_code.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_code.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_code.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_code.metainfo.object_number_type = obj_cite_digits.type; comp_obj_code.text = an_object["substantive"]; comp_obj_code.has.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_code.has.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_code.has.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, lev_anchor_tag, tag_assoc_html, 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, false); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; comp_obj_block = comp_obj_block.init; comp_obj_block.metainfo.ocn = obj_cite_digits.on; comp_obj_block.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; comp_obj_block.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; comp_obj_block.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_block.metainfo.object_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) { 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) { 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) { 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) { 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; indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; if (auto m = line.matchFirst(rgx.para_indent)) { debug(paraindent) { writeln(line); } indent["hang_position"] = (m.captures[1]).to!int; indent["base_position"] = 0; } else if (line.matchFirst(rgx.para_bullet)) { debug(parabullet) { writeln(line); } bullet = true; } else if (auto m = line.matchFirst(rgx.para_indent_hang)) { debug(paraindenthang) { 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) { 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.metainfo.is_of_part = "body"; table_object.metainfo.is_of_section = "body"; table_object.metainfo.is_of_type = "block"; table_object.metainfo.is_a = "table"; table_object.has.inline_notes_reg = false; table_object.has.inline_notes_star = false; table_object.has.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 including images #+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.smid_inline_url_generic)) { /+ link: naked url: http://url +/ if (obj_txt_in.match(rgx.smid_inline_link_naked_url)) { obj_txt_in = (obj_txt_in).replaceAll( rgx.smid_inline_link_naked_url, ("$1" ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ) // ("$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.smid_inline_link_endnote_url_helper)) { obj_txt_in = (obj_txt_in) .replaceAll( rgx.smid_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.smid_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.smid_inline_link_markup_regular)) { obj_txt_in = (obj_txt_in).replaceAll( rgx.smid_inline_link_markup_regular, ("$1" ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c ~ mkup.url_o ~ "$3" ~ mkup.url_c ) // ("$1{ $2 }$3$4") ); } } obj_txt_in = obj_txt_in.replaceAll(rgx.inline_mono_box, ("#{$1}#")); return obj_txt_in; } #+END_SRC #+name: meta_emitters_obj_inline_markup_munge #+BEGIN_SRC d static auto images(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)); // figure /+ 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.smid_image_generic)) { /+ images with and without links +/ debug(images) { writeln("Image: ", obj_txt_in); } if (obj_txt_in.match(rgx.smid_image_with_dimensions)) { obj_txt_in = (obj_txt_in).replaceAll( rgx.smid_image_with_dimensions, ("$1" ~ mkup.img ~ "$2,w$3h$4 " ~ "$5") // ("$1{ $2 }$2$3") ); debug(images) { writeln("IMAGE with size: ", obj_txt_in); // decide on representation } } else if (obj_txt_in.match(rgx.smid_image)) { obj_txt_in = (obj_txt_in).replaceAll( rgx.smid_image, ("$1" ~ mkup.img ~ "$2,w0h0 " ~ "$3") // ("$1{ $2 }$2$3") ); debug(images) { writeln("IMAGE: ", obj_txt_in); // decide on representation } } } obj_txt_in = obj_txt_in.replaceAll(rgx.inline_mono_box, ("#{$1}#")); // figure 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 ~ n_foot.to!string ~ " ") ) ~ "\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; bool images_without_dimensions = 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) ); /+ image matched +/ if (obj_txt_in.match(rgx.smid_image_generic)) { obj_txt_in = images(obj_txt_in); if (obj_txt_in.match(rgx.smid_mod_image_without_dimensions)) { images_without_dimensions = true; } } /+ url matched +/ if (obj_txt_in.match(rgx.smid_inline_url)) { urls = true; obj_txt_in = url_links(obj_txt_in); } if (auto m = obj_txt_in.match(rgx.para_inline_link_anchor)) { obj_txt_in = (obj_txt_in) .replaceAll(rgx.para_inline_link_anchor, "┋$1┋"); } 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, images_without_dimensions, ); 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.object_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.object_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; static string anchor_tag = ""; #+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, bool _new_doc ) 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"] : obj_txt["munge"].strip; if (_new_doc) { anchor_tag = ""; } 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; obj_notes_and_links["image_no_dimensions"] = false; switch (obj_["is"]) { case "heading": if (_new_doc) { anchor_tag = ""; } obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, conf_make_meta, _new_doc); obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"], _new_doc); if (auto m = obj_txt["munge"].match(rgx.heading_anchor_tag)) { anchor_tag = m.captures[1]; } 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]; obj_notes_and_links["image_no_dimensions"] = x[5]; break; } auto t = tuple( obj_txt["munge"], anchor_tag, obj_notes_and_links["notes_reg"], obj_notes_and_links["notes_star"], obj_notes_and_links["links"], obj_notes_and_links["image_no_dimensions"], ); anchor_tag = ""; 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.metainfo.is_of_part = "frontmatter"; comp_obj_toc.metainfo.is_of_section = "toc"; comp_obj_toc.metainfo.is_of_type = "para"; comp_obj_toc.metainfo.is_a = "toc"; comp_obj_toc.metainfo.ocn = 0; comp_obj_toc.metainfo.object_number_off = ""; comp_obj_toc.metainfo.object_number_type = 0; comp_obj_toc.attrib.indent_hang = indent["hang_position"]; comp_obj_toc.attrib.indent_base = indent["base_position"]; comp_obj_toc.attrib.bullet = false; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.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.metainfo.is_of_part = "frontmatter"; comp_obj_toc.metainfo.is_of_section = "toc"; comp_obj_toc.metainfo.is_of_type = "para"; comp_obj_toc.metainfo.is_a = "toc"; comp_obj_toc.metainfo.ocn = 0; comp_obj_toc.metainfo.object_number_off = ""; comp_obj_toc.metainfo.object_number_type = 0; comp_obj_toc.attrib.indent_hang = indent["hang_position"]; comp_obj_toc.attrib.indent_base = indent["base_position"]; comp_obj_toc.attrib.bullet = false; comp_obj_toc.text = "Table of Contents"; comp_obj_toc.has.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } comp_obj_toc = comp_obj_toc.init; comp_obj_toc.metainfo.is_of_part = "frontmatter"; comp_obj_toc.metainfo.is_of_section = "toc"; comp_obj_toc.metainfo.is_of_type = "para"; comp_obj_toc.metainfo.is_a = "toc"; comp_obj_toc.metainfo.ocn = 0; comp_obj_toc.metainfo.object_number_off = ""; comp_obj_toc.metainfo.object_number_type = 0; comp_obj_toc.attrib.bullet = false; comp_obj_toc.has.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.attrib.indent_hang = indent["hang_position"]; comp_obj_toc.attrib.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.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.attrib.indent_hang = indent["hang_position"]; comp_obj_toc.attrib.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.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.attrib.indent_hang = indent["hang_position"]; comp_obj_toc.attrib.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.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.attrib.indent_hang = indent["hang_position"]; comp_obj_toc.attrib.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.has.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 int[] heading_num = [ 0, 0, 0, 0 ]; static string heading_number_auto_composite = ""; static string _configured_auto_heading_numbering_and_segment_anchor_tags(M,O,CMM)( M munge_, O obj_, CMM conf_make_meta, bool _new_doc ) { debug(asserts) { static assert(is(typeof(munge_) == string)); static assert(is(typeof(obj_) == string[string])); } if (_new_doc) { heading_num = [ 0, 0, 0, 0 ]; 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 int heading_num_lev1 = 0; static string _make_segment_anchor_tags_if_none_provided(M,Lv)( M munge_, Lv lev_, bool _new_doc ) { 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] ~ " "); if (auto n = munge_.match(rgx.heading_anchor_tag_plus_colon)) { auto tag_remunge_ = n.captures[2] .replaceAll(rgx.heading_marker_tag_has_colon, ".."); munge_=(munge_).replaceFirst(rgx.heading_anchor_tag_plus_colon, n.captures[1] ~ tag_remunge_ ~ " "); } } 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" if (_new_doc) { 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(), "; object_number: ", oa_j["object_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["object_number"] = _comp_obj_heading.metainfo.ocn; oa_j.object["lev_markup_number"] = _comp_obj_heading.metainfo.heading_lev_markup; oa_j.object["lev_collapsed_number"] = _comp_obj_heading.metainfo.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_object_number"] = _comp_obj_heading.metainfo.parent_ocn; oa_j.object["parent_lev_markup_number"] = _comp_obj_heading.metainfo.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 object_number_offset, object_number_endpoint; string[] object_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_object_numbers_match) ) { main_term = m.captures[1].strip; object_number_offset = m.captures[2].to!int; object_number_endpoint=(obj_cite_digits.on + object_number_offset); object_numbers ~= (obj_cite_digits.on.to!string ~ "-" ~ object_number_endpoint.to!string ~ ":" ~ segment_anchor_tag); } else { main_term = bi_main_term_and_rest[0].strip; object_numbers ~= obj_cite_digits.on.to!string ~ ":" ~ segment_anchor_tag; } bi[main_term]["_a"] ~= object_numbers; object_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_object_number_offset_split ); foreach (sub_terms_bits; bi_sub_terms_split_arr) { if (auto m = sub_terms_bits.match(rgx.bi_term_and_object_numbers_match)) { sub_term = m.captures[1].strip; object_number_offset = m.captures[2].to!int; object_number_endpoint=(obj_cite_digits.on + object_number_offset); object_numbers ~= (obj_cite_digits.on.to!string ~ " - " ~ object_number_endpoint.to!string ~ ":" ~ segment_anchor_tag); } else { sub_term = sub_terms_bits.strip; object_numbers ~= obj_cite_digits.on.to!string ~ ":" ~ segment_anchor_tag; } if (!empty(sub_term)) { bi[main_term][sub_term] ~= object_numbers; } object_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 DocReformNode; 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_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "bookindex"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Book Index"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "_part_book_index"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 1; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; comp_obj_heading.has.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_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "bookindex"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Index"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "bookindex"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 4; comp_obj_heading_.metainfo.heading_lev_collapsed = 2; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; comp_obj_heading.has.inline_links = false; comp_obj_heading_.tags.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.metainfo.is_of_part = "backmatter"; comp_obj_para.metainfo.is_of_section = "bookindex"; comp_obj_para.metainfo.is_of_type = "para"; comp_obj_para.metainfo.is_a = "bookindex"; comp_obj_para.text = bi_tmp_scroll.to!string.strip; comp_obj_para.metainfo.ocn = 0; comp_obj_para.metainfo.object_number_off = ""; comp_obj_para.metainfo.object_number_type = 0; comp_obj_para.tags.anchor_tags = bi_tmp_tags; comp_obj_para.attrib.indent_hang = 0; comp_obj_para.attrib.indent_base = 1; comp_obj_para.attrib.bullet = false; comp_obj_para.has.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_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.metainfo.heading_lev_markup = 1; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.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].metainfo.is_a == "para") || (contents_am[cntr].metainfo.is_a == "heading") || (contents_am[cntr].metainfo.is_a == "quote") || (contents_am[cntr].metainfo.is_a == "group") || (contents_am[cntr].metainfo.is_a == "block") || (contents_am[cntr].metainfo.is_a == "verse")); assert(cntr >= previous_count); assert( (contents_am[cntr].text).match( rgx.inline_notes_delimiter_al_regular_number_note) ); } body { mixin InternalMarkup; previous_count=cntr; 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) } // 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 DocReformNode; 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_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "endnotes"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Endnotes"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "_part_endnotes"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 1; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; the_endnotes_section ~= comp_obj_heading_; ++mkn; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.metainfo.is_of_part = "backmatter"; comp_obj_heading_.metainfo.is_of_section = "endnotes"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "Endnotes"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.tags.segment_anchor_tag = "endnotes"; comp_obj_heading_.tags.segment_anchor_tag_is = comp_obj_heading_.tags.segment_anchor_tag; comp_obj_heading_.metainfo.heading_lev_markup = 4; comp_obj_heading_.metainfo.heading_lev_collapsed = 2; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.parent_lev_markup = 0; comp_obj_heading_.tags.anchor_tags = ["endnotes"]; the_endnotes_section ~= comp_obj_heading_; ++mkn; } else { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.metainfo.is_of_part = "empty"; comp_obj_heading_.metainfo.is_of_section = "empty"; comp_obj_heading_.metainfo.is_of_type = "para"; comp_obj_heading_.metainfo.is_a = "heading"; comp_obj_heading_.text = "(skip) there are no Endnotes"; comp_obj_heading_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_heading_.metainfo.heading_lev_markup = 1; comp_obj_heading_.metainfo.heading_lev_collapsed = 1; comp_obj_heading_.metainfo.parent_ocn = 1; comp_obj_heading_.metainfo.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_.metainfo.is_of_part = "backmatter"; comp_obj_endnote_.metainfo.is_of_section = "endnote"; comp_obj_endnote_.metainfo.is_of_type = "para"; comp_obj_endnote_.metainfo.is_a = "endnote"; comp_obj_endnote_.metainfo.ocn = 0; comp_obj_heading_.metainfo.object_number_off = ""; comp_obj_heading_.metainfo.object_number_type = 0; comp_obj_endnote_.attrib.indent_hang = 0; comp_obj_endnote_.attrib.indent_base = 0; comp_obj_endnote_.attrib.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_.tags.anchor_tags = [ endnotes_["anchor"][i] ]; comp_obj_endnote_.has.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,Tg,La,Ta,N,C,P,I)( Lv lev_markup_number, Tg segment_anchor_tag, La lev_anchor_tag, Ta tag_assoc_html, 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_["object_number"] = lv7; } else if (lv6 > State.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3; p_["object_number"] = lv6; } else if (lv5 > State.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2; p_["object_number"] = lv5; } else { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1; p_["object_number"] = lv4; } ObjGenericComposite comp_obj_location; comp_obj_location = comp_obj_location.init; comp_obj_location.metainfo.is_a = is_; comp_obj_location.metainfo.ocn = obj_cite_digits.on; comp_obj_location.tags.segment_anchor_tag = segment_anchor_tag.to!string; comp_obj_location.tags.segment_anchor_tag_is = comp_obj_location.tags.segment_anchor_tag; comp_obj_location.tags.heading_lev_anchor_tag = lev_anchor_tag; comp_obj_location.metainfo.parent_ocn = p_["object_number"]; comp_obj_location.metainfo.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.metainfo.parent_lev_markup >= 4); assert(comp_obj_location.metainfo.parent_lev_markup <= 7); assert(comp_obj_location.metainfo.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,Lm,Lc,TaB,TaL,TA,N,C,P,LA,I,PSn,fNr,fNs,fL)( T _text, Lm lev_markup_number, Lc lev_collapsed_number, TaB segment_anchor_tag_that_object_belongs_to, TaL lev_anchor_tag, TA tag_assoc_html, 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_that_object_belongs_to) == 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_["object_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_["object_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_["object_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_["object_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_["object_number"] = lv3; } else if (lv2 > State.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_C; p_["object_number"] = lv2; } else if (lv1 > State.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_B; p_["object_number"] = lv1; } else { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_A; p_["object_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_["object_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_["object_number"] = lv5; break; case 7: lv = DocStructMarkupHeading.h_text_4; lv7 = obj_cite_digit; p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3; p_["object_number"] = lv6; break; default: break; } ObjGenericComposite _comp_obj_heading_; _comp_obj_heading_ = _comp_obj_heading_.init; _comp_obj_heading_.metainfo.is_of_part = "body"; _comp_obj_heading_.metainfo.is_of_section = "body"; _comp_obj_heading_.metainfo.is_of_type = "para"; _comp_obj_heading_.metainfo.is_a = "heading"; _comp_obj_heading_.text = _text.to!string.strip; _comp_obj_heading_.metainfo.ocn = obj_cite_digits.on; _comp_obj_heading_.metainfo.object_number_off = (obj_cite_digits.off==0) ? "" : obj_cite_digits.off.to!string; _comp_obj_heading_.metainfo.object_number_type = obj_cite_digits.type; _comp_obj_heading_.tags.segment_anchor_tag = segment_anchor_tag_that_object_belongs_to; _comp_obj_heading_.tags.heading_lev_anchor_tag = lev_anchor_tag; _comp_obj_heading_.tags.segment_anchor_tag_is = segment_anchor_tag_that_object_belongs_to; _comp_obj_heading_.metainfo.heading_lev_markup = (!(lev_markup_number.empty) ? lev_markup_number.to!int : 0); _comp_obj_heading_.metainfo.heading_lev_collapsed = (!(lev_collapsed_number.empty) ? lev_collapsed_number.to!int : 0); _comp_obj_heading_.metainfo.parent_ocn = p_["object_number"]; _comp_obj_heading_.metainfo.parent_lev_markup = p_["lev_markup_number"]; _comp_obj_heading_.tags.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_.has.inline_notes_reg = flag_notes_reg; _comp_obj_heading_.has.inline_notes_star = flag_notes_star; _comp_obj_heading_.has.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_.metainfo.parent_lev_markup <= 7); assert(_comp_obj_heading_.metainfo.parent_ocn >= 0); if (lev_markup_number.match(rgx.levels_numbered_headings)) { assert(_comp_obj_heading_.metainfo.heading_lev_markup <= 7); assert(_comp_obj_heading_.metainfo.ocn >= 0); if (_comp_obj_heading_.metainfo.parent_lev_markup > 0) { assert(_comp_obj_heading_.metainfo.parent_lev_markup < _comp_obj_heading_.metainfo.heading_lev_markup); if (_comp_obj_heading_.metainfo.ocn != 0) { assert(_comp_obj_heading_.metainfo.parent_ocn < _comp_obj_heading_.metainfo.ocn); } } if (_comp_obj_heading_.metainfo.heading_lev_markup == 0) { assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_A); } else if (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_B) { assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_A); } else if (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_C) { assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_B); } else if (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_D) { assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_C); } else if (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_1) { assert(_comp_obj_heading_.metainfo.parent_lev_markup <= DocStructMarkupHeading.h_sect_D); } else if (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_2) { assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_1); } else if (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_3) { assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_2); } else if (_comp_obj_heading_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_4) { assert(_comp_obj_heading_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_3); } else if (_comp_obj_heading_.metainfo.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:doc_reform:meta_object_setter: set abstracted objects for downstream processing ** 0. module template #+BEGIN_SRC d :tangle ../src/doc_reform/meta/object_setter.d /++ object setter: setting of sisu objects for downstream processing meta_object_setter.d +/ module doc_reform.meta.object_setter; template ObjectSetter() { /+ structs +/ <> } #+END_SRC ** 1. initialize structs :struct: *** heading attribute #+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 DocObj_MetaInfo_ { string is_of_part = ""; // frontmatter, body, backmatter string is_of_section = ""; // toc, body, glossary, biography, book index, blurb string is_of_type = ""; // para, block ? string is_a = ""; // heading, para, table, code block, group, ... alias of_part = is_of_part; alias of_section = is_of_section; alias is_of = is_of_type; /+ o_n +/ int o_n_substantive = 0; int o_n_non_substantive = 0; int o_n_glossary = 0; int o_n_bibliography = 0; int o_n_book_index = 0; int o_n_blurb = 0; string object_number_substantive() const @property { return (o_n_substantive==0) ? "" : o_n_substantive.to!string; } string object_number_non_substantive() const @property { return (o_n_non_substantive==0) ? "" : o_n_non_substantive.to!string; } string object_number_glossary() const @property { return (o_n_glossary==0) ? "" : o_n_glossary.to!string; } string object_number_bibliography() const @property { return (o_n_bibliography==0) ? "" : o_n_bibliography.to!string; } string object_number_book_index() const @property { return (o_n_book_index==0) ? "" : o_n_book_index.to!string; } string object_number_blurb() const @property { return (o_n_blurb==0) ? "" : o_n_blurb.to!string; } string object_number_off = ""; bool visible_object_number = false; // enum ONtype { none, substantive, non_substantive, glossary, bibliography, book_index, blurb, comment } int object_number_type = 0; // { ocn, non, bkidx } /+ node +/ string[string][string] node; int ocn = 0; string object_number() const @property { return (ocn==0) ? "" : ocn.to!string; } int o_n_type = 0; int heading_lev_markup = 9; int heading_lev_collapsed = 9; string marked_up_level() const @property { string _out; switch (heading_lev_markup) { case 0: _out = "A"; break; case 1: _out = "B"; break; case 2: _out = "C"; break; case 3: _out = "D"; break; case 4: _out = "1"; break; case 5: _out = "2"; break; case 6: _out = "3"; break; case 7: _out = "4"; break; default: _out = ""; break; } return _out; } int[] markedup_ancestors = [ 0, 0, 0, 0, 0, 0, 0, 0,]; int[] collapsed_ancestors = [ 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_structure_markedup_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_structure_collapsed_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0,]; int parent_lev_markup = 0; int parent_ocn = 0; int last_decendant_ocn = 0; } struct DocObj_TxtAttrib_ { int indent_base = 0; int indent_hang = 0; bool bullet = false; string language = ""; // not implemented, consider } struct DocObj_Has_ { // has bool inline_links = false; bool inline_notes_reg = false; bool inline_notes_star = false; bool contains_image_without_dimensions = false; } struct DocObj_Table_ { int number_of_columns = 0; double[] column_widths = []; string[] column_aligns = []; bool heading = false; bool walls = false; // not implemented } struct DocObj_CodeBlock_ { string syntax = ""; } struct DocObj_Pointer_ { int doc_object = 0; int html_segnames = 0; int heading = 0; } struct DocObj_Tags_ { string[] heading_ancestors_text = [ "", "", "", "", "", "", "", "", ]; // TODO redundant? see markedup and collapsed ancestors DONE string segment_anchor_tag = ""; string segment_anchor_tag_is = ""; string heading_lev_anchor_tag = ""; string segname_prev = ""; string segname_next = ""; string[] lev4_subtoc = []; string[] anchor_tags = []; } struct ObjGenericComposite { string text = ""; DocObj_MetaInfo_ metainfo; DocObj_TxtAttrib_ attrib; DocObj_Tags_ tags; DocObj_Has_ has; DocObj_Table_ table; DocObj_CodeBlock_ code_block; DocObj_Pointer_ ptr; } #+END_SRC *** The Objects: generic composite object array #+name: meta_structs_init #+BEGIN_SRC d struct TheObjects { ObjGenericComposite[] oca; } #+END_SRC * __END__