#+TITLE: sdp document abstraction #+AUTHOR: Ralph Amissah #+EMAIL: ralph.amissah@gmail.com #+STARTUP: indent #+LANGUAGE: en #+OPTIONS: H:3 num:nil toc:t \n:nil @:t ::t |:t ^:nil _:nil -:t f:t *:t <:t #+OPTIONS: TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc #+OPTIONS: author:nil email:nil creator:nil timestamp:nil #+PROPERTY: header-args :padline no :exports code :noweb yes #+EXPORT_SELECT_TAGS: export #+EXPORT_EXCLUDE_TAGS: noexport #+FILETAGS: :sdp:rel:ao: #+TAGS: assert(a) class(c) debug(d) mixin(m) sdp(s) tangle(T) template(t) WEB(W) noexport(n) [[./sdp.org][sdp]] [[./][org/]] * 0. the document notes ** abstraction - abstract for downstream processing - identify document structure and objects - identify document structure (headings/levels/sections) - identify objects - set document, generate common abstraction for downstream parsing - set different document sections, toc, body, endnotes, book index, etc. - object numbers, heading/ chapter numbering etc, endnote numbers - unify object representations - multiple markups for same object type given single representation - extract object attributes - unify inline markup on objects - inline markup made easier to identify - simplify downstream parsing ** document sections |--------------+--------------+---+---+--------------------------------------------------+---+---+---| | front matter | head | | | | | | | |--------------+--------------+---+---+--------------------------------------------------+---+---+---| | toc | toc | | | generated: headings | | | | |--------------+--------------+---+---+--------------------------------------------------+---+---+---| | body | body | | | default section | | | | | | | | | - heading | | | | | | | | | - para | | | | | | | | | - code | | | | | | | | | - poem | | | | | | | | | - group | | | | | | | | | - block | | | | | | | | | - quote | | | | | | | | | - table | | | | |--------------+--------------+---+---+--------------------------------------------------+---+---+---| | back matter | endnote | | | generated: inline note markup | | | | |--------------+--------------+---+---+--------------------------------------------------+---+---+---| | | glossary | | | identified section, limited markup | | | | | | | | | - the heading | | | | | | | | | - paragraph | | | | |--------------+--------------+---+---+--------------------------------------------------+---+---+---| | | bibliography | | | generated from inline special markup | | | | | | | | | appended to paragraphs contained in body section | | | | |--------------+--------------+---+---+--------------------------------------------------+---+---+---| | | blurb | | | identified section, limited markup | | | | | | | | | - the heading | | | | | | | | | - paragraphs | | | | |--------------+--------------+---+---+--------------------------------------------------+---+---+---| ** objects |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| | | | identified by | object notes | attributes | inline | embedded | special | | | | | | | | appended | characters | |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| | para | heading | level markers | | | - italics | - endnotes | | | | | at start of line | | | | - bibliography | | |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| | | paragraph | delimited by two new lines | default object | - indent | - bold | - endnotes | | | | | | [discard leading & | - bullet | - italics | - bibliography | | | | | | newline whitespace] | | - underscore | | | | | | | | | - strikethrough | | | | | | | | | - superscript | | | | | | | | | - subscript | | | |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| | block | | open and close tags | | | | | | |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| | TODO | quote | | | - language? | | | | |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| | TODO | group | | - inline markup applied | - language? | as paragraph | - endnotes | | | | | | - [discard leading & | | | - bibliography | | | | | | newline whitespace] | | | | | |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| | TODO | block | | - inline markup applied | | as paragraph | - endnotes | | | | | | - whitespace indentation | | | - bibliography | | | | | | & newlines | | | | | |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| | | poem / verse | open and close tags | verse is the object | | | - endnotes | | | | | | - inline markup applied | | | - bibliography | | | | | (for poem) | - whitespace indentation | | | | | | | | | & newlines | | | | | |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| | | code | | - contents untouched | - syntax | | | | | | | | - whitespace indentation | - numbered | | | | | | | | & newlines | | | | | |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| | | table | | | - column width | | | | | | | | | - heading row | | | | |-------+--------------+----------------------------+--------------------------+----------------+-----------------+----------------+------------| * 1. Document Abstraction :abstract:process: Process markup document, create document abstraction. ** 0. ao abstract doc source: :ao_abstract_doc_source: #+BEGIN_SRC d :tangle ../src/sdp/ao_abstract_doc_source.d /++ document abstraction: abstraction of sisu markup for downstream processing ao_abstract_doc_source.d +/ template SiSUdocAbstraction() { /+ ↓ abstraction imports +/ <> /+ ↓ abstraction mixins +/ <> /+ ↓ abstraction struct init +/ <> /+ ↓ abstract marked up document +/ auto SiSUdocAbstraction(Src,Make,Meta,Opt)( Src markup_sourcefile_content, Make dochead_make_aa, Meta dochead_meta_aa, Opt opt_action_bool, ) { auto rgx = Rgx(); debug(asserts) { static assert(is(typeof(markup_sourcefile_content) == char[][])); static assert(is(typeof(dochead_make_aa) == string[string][string])); static assert(is(typeof(dochead_meta_aa) == string[string][string])); static assert(is(typeof(opt_action_bool) == bool[string])); } /+ ↓ abstraction init +/ <> /+ abstraction init ↑ +/ /+ ↓ loop markup document/text line by line +/ srcDocLoop: foreach (line; markup_sourcefile_content) { /+ ↓ markup document/text line by line +/ <> if (type["code"] == TriState.on) { <> } else if (!matchFirst(line, rgx.skip_from_regular_parse)) { /+ object other than "code block" object (includes regular text paragraph, headings & blocks other than code) +/ /+ 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 (type["blocks"] == TriState.closing) { /+ line empty, with blocks flag +/ <> } else { /+ line.empty, post contents, empty variables: +/ <> } // close else for line empty } // close else for not the above } // close after non code, other blocks or regular text <> } /+ ← closed: loop markup document/text line by line +/ /+ ↓ post loop markup document/text +/ <> /+ post loop markup document/text ↑ +/ } /+ ← closed: abstract doc source +/ /+ ↓ abstraction functions +/ <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> /+ abstraction functions ↑ +/ /+ ↓ abstraction function emitters +/ <> /+ +/ <> <> <> <> <> <> <> /+ +/ <> <> <> <> <> <> /+ +/ <> <> <> /+ +/ <> /+ +/ <> /+ +/ <> /+ abstraction functions emitters ↑ +/ /+ ↓ abstraction functions assertions +/ <> /+ abstraction functions assertions ↑ +/ } /+ ← closed: template SiSUdocAbstraction +/ <> #+END_SRC ** 1. _pre loop processing_ :pre: *** imports :imports: [[./ao_defaults.org][ao_defaults]] #+name: abs_top_imports #+BEGIN_SRC d import ao_defaults, ao_object_setter, ao_rgx, output_hub; private import std.algorithm, std.array, std.container, std.exception, std.file, std.getopt, std.json, std.path, std.process, std.range, std.regex, std.stdio, std.string, std.traits, std.typecons, std.uni, std.utf, std.conv : to; #+END_SRC *** mixins :mixins: #+name: abs_top_mixins #+BEGIN_SRC d mixin ObjectSetter; mixin InternalMarkup; mixin SiSUrgxInit; #+END_SRC *** initialize :initialize: **** initialize general #+name: abs_top_init_struct #+BEGIN_SRC d /+ initialize +/ ObjGenericComposite[][string] the_table_of_contents_section; ObjGenericComposite[] the_document_head_section, the_document_body_section, the_bibliography_section, the_glossary_section, the_blurb_section; ObjGenericComposite[] the_dom_tail_section; string[string] an_object, processing; string an_object_key; string[] anchor_tags; string anchor_tag_; string segment_anchor_tag_that_object_belongs_to; string segment_anchor_tag_that_object_belongs_to_uri; /+ enum +/ enum State { off, on } enum TriState { off, on, closing } enum DocStructMarkupHeading { h_sect_A, h_sect_B, h_sect_C, h_sect_D, h_text_1, h_text_2, h_text_3, h_text_4, h_text_5, // extra level, drop content_non_header } // header section A-D; header text 1-4 /+ 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"; auto obj_im = ObjInlineMarkup(); auto obj_att = ObjAttributes(); /+ ocn +/ int obj_cite_number, obj_cite_number_; auto object_citation_number = OCNemitter(); int[] dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; enum DomTags { none, open, close, close_and_open, open_still, } #+END_SRC **** initialize heading ancestors #+name: abs_top_init_struct #+BEGIN_SRC d void heading_ancestors(O)( auto return ref O obj, return ref string[] lv_ancestors, ) { switch (obj.heading_lev_markup) { case 0: lv_ancestors[0] = obj.text.to!string; foreach(k; 1..8) { lv_ancestors[k] = ""; } goto default; case 1: lv_ancestors[1] = obj.text.to!string; foreach(k; 2..8) { lv_ancestors[k] = ""; } goto default; case 2: lv_ancestors[2] = obj.text.to!string; foreach(k; 3..8) { lv_ancestors[k] = ""; } goto default; case 3: lv_ancestors[3] = obj.text.to!string; foreach(k; 4..8) { lv_ancestors[k] = ""; } goto default; case 4: lv_ancestors[4] = obj.text.to!string; foreach(k; 5..8) { lv_ancestors[k] = ""; } goto default; case 5: lv_ancestors[5] = obj.text.to!string; foreach(k; 6..8) { lv_ancestors[k] = ""; } goto default; case 6: lv_ancestors[6] = obj.text.to!string; lv_ancestors[7] = ""; goto default; case 7: lv_ancestors[7] = obj.text.to!string; goto default; default: obj.heading_ancestors_text = lv_ancestors.dup; } } #+END_SRC **** initialize dom markup tags #+name: abs_top_init_struct #+BEGIN_SRC d auto dom_set_markup_tags(int[] dom, int lev) { foreach (i; 0 .. 8) { if (i < lev) { if (dom[i] == DomTags.open || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.open_still; } else if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } } else if (i == lev) { if (lev == 0 && dom[i] == DomTags.open_still ) { dom[i] = DomTags.close; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close_and_open; } else { dom[i] = DomTags.open; } } else if (i > lev) { if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close; } } } debug(dom_magic_numbers) { writeln("marked up: ", lev, ": ", dom); } return dom; } #+END_SRC **** initialize dom collapsed tags #+name: abs_top_init_struct #+BEGIN_SRC d auto dom_set_collapsed_tags(int[] dom, int lev) { foreach (i; 0 .. 8) { if (i < lev) { if (dom[i] == DomTags.open || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.open_still; } else if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } } else if (i == lev) { if (lev == 0 && dom[i] == DomTags.open_still ) { dom[i] = DomTags.close; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close_and_open; } else { dom[i] = DomTags.open; } } else if (i > lev) { if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close; } } } debug(dom_magic_numbers) { writeln("collapsed: ", lev, ": ", dom); } return dom; } #+END_SRC **** initialize ocn emit #+name: abs_top_init_struct #+BEGIN_SRC d int ocn_emit(int ocn_status_flag) { return object_citation_number.ocn_emitter(ocn_status_flag); } /+ book index variables +/ string book_idx_tmp; string[][string][string] bookindex_unordered_hashes; /+ node +/ ObjGenericComposite comp_obj_heading, comp_obj_location, comp_obj_block, comp_obj_code, comp_obj_poem_ocn, comp_obj_comment; auto node_construct = NodeStructureMetadata(); enum sObj { content, anchor_tags, notes_reg, notes_star, links } #+END_SRC *** scope #+name: abs_init_rest #+BEGIN_SRC d scope(success) { } scope(failure) { } scope(exit) { destroy(the_document_head_section); destroy(the_table_of_contents_section); destroy(the_document_body_section); destroy(the_bibliography_section); destroy(an_object); destroy(processing); destroy(biblio_arr_json); previous_length=0; reset_note_numbers=true; } #+END_SRC *** init rest #+name: abs_init_rest #+BEGIN_SRC d mixin SiSUrgxInitFlags; mixin SiSUnode; auto node_para_int_ = node_metadata_para_int; auto node_para_str_ = node_metadata_para_str; ObjGenericComposite comp_obj_heading_, comp_obj_para, comp_obj_toc; line_occur = [ "heading" : 0, "para" : 0, "glossary" : 0, "blurb" : 0, ]; auto type = flags_type_init; string[string] obj_cite_number_poem = [ "start" : "", "end" : "" ]; string[] lv_ancestors = [ "", "", "", "", "", "", "", "", ]; int[string] lv = [ "lv" : State.off, "h0" : State.off, "h1" : State.off, "h2" : State.off, "h3" : State.off, "h4" : State.off, "h5" : State.off, "h6" : State.off, "h7" : State.off, "lev_int_collapsed" : 0, ]; int[string] collapsed_lev = [ "h0" : State.off, "h1" : State.off, "h2" : State.off, "h3" : State.off, "h4" : State.off, "h5" : State.off, "h6" : State.off, "h7" : State.off ]; string[string] heading_match_str = [ "h_A": "^(none)", "h_B": "^(none)", "h_C": "^(none)", "h_D": "^(none)", "h_1": "^(none)", "h_2": "^(none)", "h_3": "^(none)", "h_4": "^(none)" ]; auto heading_match_rgx = [ "h_A": regex(r"^(none)"), "h_B": regex(r"^(none)"), "h_C": regex(r"^(none)"), "h_D": regex(r"^(none)"), "h_1": regex(r"^(none)"), "h_2": regex(r"^(none)"), "h_3": regex(r"^(none)"), "h_4": regex(r"^(none)") ]; string _anchor_tag; string toc_txt_; an_object["glossary_nugget"] = ""; an_object["blurb_nugget"] = ""; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "frontmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Table of Contents"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "toc"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.ptr_html_segnames = html_segnames_ptr; comp_obj_heading_.anchor_tags = ["toc"]; auto toc_head = comp_obj_heading_; html_segnames_ptr_cntr++; the_table_of_contents_section = [ "seg": [toc_head], "scroll": [toc_head], ]; auto mkup = InlineMarkup(); auto munge = ObjInlineMarkupMunge(); 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 ** 2. _loop: process document body_ [+6] :loop: *** loop scope :scope: #+name: abs_in_loop_body_00 #+BEGIN_SRC d /+ scope +/ scope(exit) { } scope(failure) { stderr.writefln( "%s\n%s\n%s:%s failed here:\n line: %s", __MODULE__, __FUNCTION__, __FILE__, __LINE__, line, ); } line = (line).replaceAll(rgx.true_dollar, "$$$$"); /+ dollar represented as $$ needed to stop submatching on $ (substitutions using ${identifiers} must take into account (i.e. happen earlier)) +/ debug(source) { // source lines writeln(line); } debug(srclines) { if (!line.empty) { // source lines, not empty writefln( "* %s", line ); } } #+END_SRC *** check whether obj_cite_number is on or turned off :ocn: #+name: abs_in_loop_body_00 #+BEGIN_SRC d if (!line.empty) { _check_ocn_status_(line, type); } #+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, type); continue; #+END_SRC **** _non code objects_ (other blocks or regular text) [+4] :non_code: ***** in section (biblio, glossary, blurb) +(block group)+ [+1] :block:active: ****** in section: biblio :biblio: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d if (line.matchFirst(rgx.heading_biblio) || (type["biblio_section"] == State.on && (!(line.matchFirst(rgx.heading_blurb_glossary))) && (!(line.matchFirst(rgx.heading))) && (!(line.matchFirst(rgx.comment))))) { /+ within section (block object): biblio +/ type["glossary_section"] = State.off; type["biblio_section"] = State.on; type["blurb_section"] = State.off; if (opt_action_bool["backmatter"] && opt_action_bool["section_biblio"]) { _biblio_block_(line, type, bib_entry, biblio_entry_str_json, biblio_arr_json); debug(bibliobuild) { writeln("- ", biblio_entry_str_json); writeln("-> ", biblio_arr_json.length); } } continue; #+END_SRC ****** 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) || (type["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); } type["glossary_section"] = State.on; type["biblio_section"] = State.off; type["blurb_section"] = State.off; if (opt_action_bool["backmatter"] && opt_action_bool["section_glossary"]) { indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; type["para"] = State.on; line_occur["para"] = State.off; an_object_key="glossary_nugget"; // if (line.matchFirst(rgx.heading_glossary)) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Glossary"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "_part_glossary"; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_glossary_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Glossary"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "glossary"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.anchor_tags = ["glossary"]; the_glossary_section ~= comp_obj_heading_; } else { _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur); comp_obj_para = comp_obj_para.init; comp_obj_para.use = "backmatter"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "glossary"; comp_obj_para.text = line.to!string.strip; comp_obj_para.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.indent_hang = indent["hang_position"]; comp_obj_para.indent_base = indent["base_position"]; comp_obj_para.bullet = bullet; the_glossary_section ~= comp_obj_para; } type["ocn_status"] = TriState.off; } continue; #+END_SRC ****** 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) || (type["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); } type["glossary_section"] = State.off; type["biblio_section"] = State.off; type["blurb_section"] = State.on; if (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"]) { indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; type["para"] = State.on; line_occur["para"] = State.off; an_object_key="blurb_nugget"; if (line.matchFirst(rgx.heading_blurb)) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Blurb"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "_part_blurb"; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_blurb_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Blurb"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "blurb"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.anchor_tags = ["blurb"]; the_blurb_section ~= comp_obj_heading_; } else if (line.matchFirst(rgx.heading) && (opt_action_bool["backmatter"] && opt_action_bool["section_blurb"])) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = line.to!string; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "blurb"; comp_obj_heading_.marked_up_level = an_object["lev"].to!string; comp_obj_heading_.heading_lev_markup = an_object["lev_markup_number"].to!int; // make int, remove need to conv comp_obj_heading_.heading_lev_collapsed = an_object["lev_collapsed_number"].to!int; // make int, remove need to conv comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_blurb_section ~= comp_obj_heading_; } else { _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur); comp_obj_para = comp_obj_para.init; comp_obj_para.use = "backmatter"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "blurb"; comp_obj_para.text = line.to!string.strip; comp_obj_para.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.indent_hang = indent["hang_position"]; comp_obj_para.indent_base = indent["base_position"]; comp_obj_para.bullet = bullet; the_blurb_section ~= comp_obj_para; } type["ocn_status"] = TriState.off; } continue; #+END_SRC ***** in blocks [+1] :block:active: ****** in block: quote :quote: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (type["quote"] == TriState.on) { /+ within block object: quote +/ _quote_block_(line, an_object, type); continue; #+END_SRC ****** in block: group :group: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d /+ within block object: group +/ } else if (type["group"] == TriState.on) { /+ within block object: group +/ line = (line) .replaceAll(rgx.para_delimiter, mkup.br_paragraph ~ "$1"); _group_block_(line, an_object, type); continue; #+END_SRC ****** in block: block :block: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (type["block"] == TriState.on) { /+ within block object: block +/ 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, type); continue; #+END_SRC ****** in block: poem :poem: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (type["poem"] == TriState.on) { /+ within block object: poem +/ _poem_block_(line, an_object, type, cntr, obj_cite_number_poem, dochead_make_aa); continue; #+END_SRC ****** in block: table :table: #+name: abs_in_loop_body_non_code_obj #+BEGIN_SRC d } else if (type["table"] == TriState.on) { /+ within block object: table +/ _table_block_(line, an_object, type, dochead_make_aa); continue; #+END_SRC ***** not identified as being within block group (could still be, or not) [+3] ****** assert #+name: abs_in_loop_body_open_block_obj_assert #+BEGIN_SRC d assert( (type["blocks"] == TriState.off) || (type["blocks"] == TriState.closing), "block status: none or closed" ); assertions_flag_types_block_status_none_or_closed(type); #+END_SRC ****** catch misc +block open+ #+name: abs_in_loop_body_open_block_obj #+BEGIN_SRC d if (line.matchFirst(rgx.block_poem_open)) { /+ poem to verse exceptions! +/ object_reset(an_object); processing.remove("verse"); obj_cite_number_poem["start"] = obj_cite_number.to!string; } _start_block_(line, type, obj_cite_number_poem); continue; #+END_SRC ****** line not empty [+2] ******* asserts :assert: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d assert( !line.empty, "line tested, line not empty surely" ); assert( (type["blocks"] == TriState.off) || (type["blocks"] == TriState.closing), "code block status: none or closed" ); if (type["blocks"] == TriState.closing) { debug(check) { // block writeln(__LINE__); writeln(line); } assert( line.matchFirst(rgx.book_index) || line.matchFirst(rgx.book_index_open) || type["book_index"] == State.on ); } #+END_SRC ******* book index :bookindex: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d if (line.matchFirst(rgx.book_index) || line.matchFirst(rgx.book_index_open) || type["book_index"] == State.on ) { /+ book_index +/ _book_index_(line, book_idx_tmp, an_object, type, opt_action_bool); #+END_SRC ******* not book index [+1] #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d } else { /+ not book_index +/ #+END_SRC ******** matched: comment :comment:match: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d an_object_key="body_nugget"; if (auto m = matchFirst(line, rgx.comment)) { /+ matched comment +/ debug(comment) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; comp_obj_comment = comp_obj_comment.init; comp_obj_comment.use = "comment"; comp_obj_comment.is_of = "comment"; comp_obj_comment.is_a = "comment"; comp_obj_comment.text = an_object[an_object_key].strip; the_document_body_section ~= comp_obj_comment; _common_reset_(line_occur, an_object, type); processing.remove("verse"); ++cntr; #+END_SRC ******** flag not set & line not exist: heading or para :heading:paragraph: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d } else if (((line_occur["para"] == State.off) && (line_occur["heading"] == State.off)) && ((type["para"] == State.off) && (type["heading"] == State.off))) { /+ heading or para but neither flag nor line exists +/ if ((dochead_make_aa["make"]["headings"].length > 2) && (type["make_headings"] == State.off)) { /+ heading found +/ _heading_found_(line, dochead_make_aa["make"]["headings"], heading_match_str, heading_match_rgx, type); } if ((type["make_headings"] == State.on) && ((line_occur["para"] == State.off) && (line_occur["heading"] == State.off)) && ((type["para"] == State.off) && (type["heading"] == State.off))) { /+ heading make set +/ line = _heading_make_set_(line, line_occur, heading_match_rgx, type); } /+ TODO node info: all headings identified at this point, - extract node info here?? - how long can it wait? - should be incorporated in composite objects - should happen before endnote links set (they need to be moved down?) +/ if (line.matchFirst(rgx.heading)) { /+ heading match +/ _heading_matched_(line, line_occur, an_object, an_object_key, lv, collapsed_lev, type, dochead_meta_aa); } else if (line_occur["para"] == State.off) { /+ para match +/ an_object_key="body_nugget"; _para_match_(line, an_object, an_object_key, indent, bullet, type, line_occur); } #+END_SRC ******** line exist: heading :heading: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d } else if (line_occur["heading"] > State.off) { /+ heading +/ debug(heading) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; ++line_occur["heading"]; #+END_SRC ******** line exist: para :para: #+name: abs_in_loop_body_not_block_obj #+BEGIN_SRC d } else if (line_occur["para"] > State.off) { /+ paragraph +/ debug(para) { writeln(line); } an_object[an_object_key] ~= " " ~ line; ++line_occur["para"]; } } #+END_SRC ****** line empty, with block flag #+name: abs_in_loop_body_not_block_obj_line_empty_blocks_flags #+BEGIN_SRC d _block_flag_line_empty_( bookindex_extract_hash, line, an_object, the_document_body_section, bookindex_unordered_hashes, obj_cite_number, comp_obj_heading, cntr, type, obj_cite_number_poem, dochead_make_aa ); #+END_SRC ****** line empty [+1] ******* assert line empty :assert: #+name: abs_in_loop_body_not_block_obj_line_empty #+BEGIN_SRC d assert( line.empty, "line should be empty" ); assert( (type["blocks"] == State.off), "code block status: none" ); #+END_SRC ******* heading object :heading:object: #+name: abs_in_loop_body_not_block_obj_line_empty #+BEGIN_SRC d if ((type["heading"] == State.on) && (line_occur["heading"] > State.off)) { /+ heading object (current line empty) +/ obj_cite_number = (an_object["lev_markup_number"].to!int == 0) ? (ocn_emit(3)) : (obj_cite_number = ocn_emit(type["ocn_status"])); an_object["is"] = "heading"; an_object_key="body_nugget"; auto substantive_object_and_anchor_tags_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_object_and_anchor_tags_tuple[sObj.content]; anchor_tags = substantive_object_and_anchor_tags_tuple[sObj.anchor_tags]; if (an_object["lev_markup_number"].to!int == 4) { segment_anchor_tag_that_object_belongs_to = anchor_tags[0]; segment_anchor_tag_that_object_belongs_to_uri = anchor_tags[0] ~ ".fnSuffix"; anchor_tag_ = anchor_tags[0]; } else if (an_object["lev_markup_number"].to!int > 4) { segment_anchor_tag_that_object_belongs_to = anchor_tag_; segment_anchor_tag_that_object_belongs_to_uri = anchor_tag_ ~ ".fnSuffix#" ~ obj_cite_number.to!string; } else if (an_object["lev_markup_number"].to!int < 4) { string segn; switch (an_object["lev_markup_number"].to!int) { case 0: segn = "_the_title"; goto default; case 1: segn = "_part_" ~ cnt1.to!string; ++cnt1; goto default; case 2: segn = "_part_" ~ cnt1.to!string ~ "_" ~ cnt2.to!string; ++cnt2; goto default; case 3: segn = "_part_" ~ cnt1.to!string ~ "_" ~ cnt2.to!string ~ "_" ~ cnt3.to!string; ++cnt3; goto default; default: segment_anchor_tag_that_object_belongs_to = segn; segment_anchor_tag_that_object_belongs_to_uri = segn ~ ".fnSuffix"; break; } } an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_number, segment_anchor_tag_that_object_belongs_to); /+ (incrementally build toc) table of contents here! +/ _anchor_tag=to!string(obj_cite_number); the_table_of_contents_section = obj_im.table_of_contents_gather_headings( an_object, dochead_make_aa, segment_anchor_tag_that_object_belongs_to, _anchor_tag, lev4_subtoc, the_table_of_contents_section, ); if (an_object["lev_markup_number"] == "4") { html_segnames ~= segment_anchor_tag_that_object_belongs_to; html_segnames_ptr = html_segnames_ptr_cntr; html_segnames_ptr_cntr++; } auto comp_obj_heading = node_construct.node_emitter_heading( an_object["substantive"], // string an_object["lev"], // string an_object["lev_markup_number"], // string an_object["lev_collapsed_number"], // string segment_anchor_tag_that_object_belongs_to, // string obj_cite_number, // int cntr, // int heading_ptr, // int lv_ancestors, // string[] an_object["is"], // string html_segnames_ptr, // int 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, type); an_object.remove("lev"); an_object.remove("lev_markup_number"); processing.remove("verse"); ++cntr; #+END_SRC ******* paragraph object :paragraph:object: #+name: abs_in_loop_body_not_block_obj_line_empty #+BEGIN_SRC d } else if ((type["para"] == State.on) && (line_occur["para"] > State.off)) { /+ paragraph object (current line empty) +/ obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_number, segment_anchor_tag_that_object_belongs_to); an_object["is"] = "para"; auto comp_obj_heading = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, 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, dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_para = comp_obj_para.init; comp_obj_para.use = "body"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "para"; comp_obj_para.text = an_object["substantive"].to!string.strip; comp_obj_para.ocn = obj_cite_number; comp_obj_para.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; comp_obj_para.indent_hang = indent["hang_position"]; comp_obj_para.indent_base = indent["base_position"]; comp_obj_para.bullet = bullet; comp_obj_para.anchor_tags = anchor_tags; comp_obj_para.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_para.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_para.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_para; _common_reset_(line_occur, an_object, type); indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; processing.remove("verse"); ++cntr; } else { assert( line == null, "line variable should be empty, should not occur" ); } #+END_SRC *** regular text objects :text:paragraph: #+name: abs_in_loop_body_01 #+BEGIN_SRC d /+ unless (the_document_body_section.length == 0) ? +/ if (the_document_body_section.length > 0) { if (((the_document_body_section[$-1].is_a == "para") || (the_document_body_section[$-1].is_a == "heading") || (the_document_body_section[$-1].is_a == "quote") || (the_document_body_section[$-1].is_a == "group") || (the_document_body_section[$-1].is_a == "block") || (the_document_body_section[$-1].is_a == "verse")) && (the_document_body_section.length > previous_length)) { if ((the_document_body_section[$-1].is_a == "heading") && (the_document_body_section[$-1].heading_lev_markup < 5)) { type["biblio_section"] = State.off; type["glossary_section"] = State.off; type["blurb_section"] = State.off; } if (the_document_body_section[$-1].is_a == "verse") { /+ scan for endnotes for whole poem (each verse in poem) +/ foreach (i; previous_length .. the_document_body_section.length) { if (the_document_body_section[i].is_a == "verse") { if ((the_document_body_section[i].text).match( rgx.inline_notes_delimiter_al_regular_number_note )) { note_section.gather_notes_for_endnote_section( the_document_body_section, segment_anchor_tag_that_object_belongs_to, to!int(i), ); } } } } 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, to!int(the_document_body_section.length-1), ); } } 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_number, opt_action_bool); static assert(!isTypeTuple!(en_tuple)); auto the_endnotes_section = en_tuple[0]; obj_cite_number = en_tuple[1]; debug(endnotes) { writefln( "%s %s", __LINE__, the_endnotes_section.length ); foreach (o; the_endnotes_section) { writeln(o); } } #+END_SRC **** no glossary section? :glossary: #+name: abs_post #+BEGIN_SRC d if (an_object["glossary_nugget"].length == 0) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "(skip) there is no Glossary section"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_glossary_section ~= comp_obj_heading_; } else { writeln("gloss"); } debug(glossary) { foreach (gloss; the_glossary_section) { writeln(gloss.text); } } #+END_SRC **** bibliography section (objects) :bibliography: #+name: abs_post #+BEGIN_SRC d auto biblio_unsorted_incomplete = biblio_arr_json.dup; auto biblio = Bibliography(); auto biblio_ordered = biblio._bibliography_(biblio_unsorted_incomplete, bib_arr_json); #+END_SRC #+name: abs_post #+BEGIN_SRC d if (biblio_ordered.length > 0) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Bibliography"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "_part_bibliography"; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_bibliography_section ~= comp_obj_heading_; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Bibliography"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "bibliography"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.anchor_tags = ["bibliography"]; the_bibliography_section ~= comp_obj_heading_; } else { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "(skip) there is no Bibliography"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_bibliography_section ~= comp_obj_heading_; } #+END_SRC ***** format biblio string #+name: abs_post #+BEGIN_SRC d string out_; foreach (entry; biblio_ordered) { out_ = format( "%s \"%s\"%s%s%s%s%s%s%s%s%s.", ((entry["author"].str.empty) ? entry["editor"].str : entry["author"].str), entry["fulltitle"].str, ((entry["journal"].str.empty) ? "" : ", /{" ~ entry["journal"].str ~ "}/"), ((entry["volume"].str.empty) ? "" : ", " ~ entry["volume"].str), ((entry["in"].str.empty) ? "" : ", " ~ entry["in"].str), ((!(entry["author"].str.empty) && (!(entry["editor"].str.empty))) ? entry["editor"].str : ""), ", " ~ entry["year"].str, ((entry["pages"].str.empty) ? "" : ", " ~ entry["pages"].str), ((entry["publisher"].str.empty) ? "" : ", " ~ entry["publisher"].str), ((entry["place"].str.empty) ? "" : ", " ~ entry["place"].str), ((entry["url"].str.empty) ? "" : ", [" ~ entry["url"].str ~ "]"), ); comp_obj_para = comp_obj_para.init; comp_obj_para.use = "backmatter"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "bibliography"; comp_obj_para.text = out_.to!string.strip; comp_obj_para.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_para.indent_hang = 0; comp_obj_para.indent_base = 1; comp_obj_para.bullet = bullet; comp_obj_para.anchor_tags = anchor_tags; the_bibliography_section ~= comp_obj_para; } #+END_SRC #+name: abs_post #+BEGIN_SRC d debug(bibliosection) { foreach (o; the_bibliography_section) { writeln(o.text); } } #+END_SRC ***** bibliography components auto biblio_entry_tags_jsonstr = `{ "is" : "", "sortby_deemed_author_year_title" : "", "deemed_author" : "", "author_raw" : "", "author" : "", "author_arr" : [ "" ], "editor_raw" : "", "editor" : "", "editor_arr" : [ "" ], "title" : "", "subtitle" : "", "fulltitle" : "", "language" : "", "trans" : "", "src" : "", "journal" : "", "in" : "", "volume" : "", "edition" : "", "year" : "", "place" : "", "publisher" : "", "url" : "", "pages" : "", "note" : "", "short_name" : "", "id" : "" }`; // is: book, article, magazine, newspaper, blog, other **** bookindex section (scroll & seg) :book:index: #+name: abs_post #+BEGIN_SRC d auto bi = BookIndexReportSection(); auto bi_tuple = bi.bookindex_build_abstraction_section( bookindex_unordered_hashes, obj_cite_number, opt_action_bool, ); destroy(bookindex_unordered_hashes); static assert(!isTypeTuple!(bi_tuple)); auto the_bookindex_section = bi_tuple[0]; obj_cite_number = bi_tuple[1]; debug(bookindex) { foreach (bi_entry; the_bookindex_section["seg"]) { writeln(bi_entry); } } #+END_SRC **** no blurb section? :blurb: #+name: abs_post #+BEGIN_SRC d if (an_object["blurb_nugget"].length == 0) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "(skip) there is no Blurb section"; comp_obj_heading_.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_blurb_section ~= comp_obj_heading_; } debug(blurb) { foreach (blurb; the_blurb_section) { writeln(blurb.text); } } #+END_SRC **** toc backmatter, table of contents backmatter (scroll & seg) :contents: #+name: abs_post #+BEGIN_SRC d indent=[ "hang_position" : 1, "base_position" : 1, ]; comp_obj_toc = comp_obj_toc.init; comp_obj_toc.use = "frontmatter"; comp_obj_toc.is_of = "para"; comp_obj_toc.is_a = "toc"; comp_obj_toc.ocn = 0; comp_obj_toc.obj_cite_number = ""; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.bullet = false; if (the_endnotes_section.length > 1) { toc_txt_ = format( "{ %s }%s%s%s", "Endnotes", mkup.mark_internal_site_lnk, "endnotes", // segment_anchor_tag_that_object_belongs_to ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; } if (the_glossary_section.length > 1) { toc_txt_ = format( "{ %s }%s%s%s", "Glossary", mkup.mark_internal_site_lnk, "glossary", // segment_anchor_tag_that_object_belongs_to ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Glossary", "glossary", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } if (the_bibliography_section.length > 1){ toc_txt_ = format( "{ %s }%s%s%s", "Bibliography", mkup.mark_internal_site_lnk, "bibliography", // segment_anchor_tag_that_object_belongs_to ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Bibliography", "bibliography", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } if (the_bookindex_section["seg"].length > 1) { toc_txt_ = format( "{ %s }%s%s%s", "Book Index", mkup.mark_internal_site_lnk, "bookindex", // segment_anchor_tag_that_object_belongs_to ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; } if (the_bookindex_section["scroll"].length > 1) { toc_txt_ = format( "{ %s }#%s", "Book Index", "bookindex", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } if (the_blurb_section.length > 1) { toc_txt_ = format( "{ %s }%s%s%s", "Blurb", mkup.mark_internal_site_lnk, "blurb", // segment_anchor_tag_that_object_belongs_to ".fnSuffix", ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; toc_txt_ = format( "{ %s }#%s", "Blurb", "blurb", // _anchor_tag ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.inline_links = true; comp_obj_toc.text = toc_txt_.to!string.strip; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } debug(toc) { writefln( "%s %s", __LINE__, the_table_of_contents_section["seg"].length ); foreach (toc_linked_heading; the_table_of_contents_section["seg"]) { writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text); } } debug(tocscroll) { writefln( "%s %s", __LINE__, the_table_of_contents_section["seg"].length ); foreach (toc_linked_heading; the_table_of_contents_section["scroll"]) { writeln(mkup.indent_by_spaces_provided(toc_linked_heading.indent_hang), toc_linked_heading.text); } } #+END_SRC **** doc head (separate document head from body, make space for toc) #+name: abs_post #+BEGIN_SRC d the_document_head_section ~= the_document_body_section[0]; the_document_body_section=the_document_body_section[1..$]; #+END_SRC *** _minor loops_ :post: **** 1. loop: backmatter loop up to lev4: html_segnames, set backmatter pointers could optimise by - skipping second and third pass unless the output html seg or epub is being made! NOTE there are issues attempting to do this on first pass - as - backmatter is created out of sequence and - it is not certain which are present it is quite neat to have all in one place as we have here: #+name: abs_post #+BEGIN_SRC d if (the_endnotes_section.length > 1) { html_segnames ~= "endnotes"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref section; the_endnotes_section) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_glossary_section.length > 1) { html_segnames ~= "glossary"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref section; the_glossary_section) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_bibliography_section.length > 1) { html_segnames ~= "bibliography"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref section; the_bibliography_section) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_bookindex_section["scroll"].length > 1) { html_segnames ~= "bookindex"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref section; the_bookindex_section["scroll"]) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } foreach (ref section; the_bookindex_section["seg"]) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_blurb_section.length > 1) { html_segnames ~= "blurb"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref section; the_blurb_section) { if (section.heading_lev_markup == 4) { section.ptr_html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } #+END_SRC **** 2. loop: all objects structural relationships (sections, segments, objects) needed for DOM structure, segnames & subtoc, backmatter pointers & unique image list if used minimally only for DOM structure, segnames, subtoc, could optimise by - skipping second and third pass unless the output html seg or epub is being made! or could conveniently be used more extensively for ancestors as well (though this can be extracted earlier) Build here: - DOM structure - ancestors and decendants - ancestors could be determined earlier, but convenient to have here - descendants could be in the form of: headings contained under current heading, and/or; the range of objects under the current heading - you could decide on a sequential object list, containing all objects (both substantive and non-substantive objects), in addition to ocn, which are for substantive/ citable objects within the document (as needed) up to document heading 1~, lev4 html: during the third pass all previous and next segment names are known next are not yet known for backmatter during the second pass #+name: abs_post #+BEGIN_SRC d string[] _images; auto extract_images(S)(S content_block) { string[] images_; if (auto m = content_block.matchAll(rgx.image)) { images_ ~= m.captures[1]; } return images_; } string[] segnames_0_4; foreach (ref obj; the_document_head_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } if (the_table_of_contents_section["scroll"].length > 1) { dom_markedup_buffer = dom_markedup.dup; dom_collapsed_buffer = dom_collapsed.dup; foreach (ref obj; the_table_of_contents_section["scroll"]) { if (obj.is_a == "heading") { if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } dom_markedup = dom_markedup_buffer.dup; dom_collapsed = dom_collapsed_buffer.dup; foreach (ref obj; the_table_of_contents_section["seg"]) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ multiple 1~ levels, loop through document body +/ if (the_document_body_section.length > 1) { foreach (ref obj; the_document_body_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.lev4_subtoc = lev4_subtoc[obj.segment_anchor_tag]; obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } else if (obj.is_a == "para") { _images ~= extract_images(obj.text); } } } auto images=uniq(_images.sort()); /+ optional only one 1~ level +/ if (the_endnotes_section.length > 1) { dom_markedup_buffer = dom_markedup.dup; dom_collapsed_buffer = dom_collapsed.dup; dom_markedup = dom_markedup_buffer.dup; dom_collapsed = dom_collapsed_buffer.dup; foreach (ref obj; the_endnotes_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ optional only one 1~ level +/ if (the_glossary_section.length > 1) { foreach (ref obj; the_glossary_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ optional only one 1~ level +/ if (the_bibliography_section.length > 1) { foreach (ref obj; the_bibliography_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ optional only one 1~ level +/ if (the_bookindex_section["scroll"].length > 1) { dom_markedup_buffer = dom_markedup.dup; dom_collapsed_buffer = dom_collapsed.dup; foreach (ref obj; the_bookindex_section["scroll"]) { if (obj.is_a == "heading") { debug(dom) { } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } dom_markedup = dom_markedup_buffer.dup; dom_collapsed = dom_collapsed_buffer.dup; foreach (ref obj; the_bookindex_section["seg"]) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } } /+ optional only one 1~ level +/ if (the_blurb_section.length > 1) { foreach (ref obj; the_blurb_section) { if (obj.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.heading_lev_markup <= 4) { segnames_0_4 ~= obj.segment_anchor_tag; if (obj.heading_lev_markup == 4) { obj.segname_prev = html_segnames[obj.ptr_html_segnames - 1]; if (html_segnames.length > obj.ptr_html_segnames + 1) { obj.segname_next = html_segnames[obj.ptr_html_segnames + 1]; } assert(obj.segment_anchor_tag == html_segnames[obj.ptr_html_segnames]); } } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { obj.dom_markedup = dom_set_markup_tags(dom_markedup, obj.heading_lev_markup).dup; obj.dom_collapsed = dom_set_collapsed_tags(dom_collapsed, obj.heading_lev_collapsed).dup; } heading_ancestors(obj, lv_ancestors); } } /+ TODO - note create/insert heading object sole purpose eof close all open tags sort out: - obj.dom_markedup = dom_markedup; - obj.dom_collapsed = dom_collapsed; +/ dom_markedup = dom_set_markup_tags(dom_markedup, 0); dom_collapsed = dom_set_collapsed_tags(dom_collapsed, 0); comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.ocn = 0; comp_obj_para.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = ""; comp_obj_heading_.marked_up_level = ""; comp_obj_heading_.heading_lev_markup = 9; comp_obj_heading_.heading_lev_collapsed = 9; comp_obj_heading_.parent_ocn = 0; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.dom_markedup = dom_markedup.dup; comp_obj_heading_.dom_collapsed = dom_collapsed.dup; the_dom_tail_section ~= comp_obj_heading_; } #+END_SRC ** 4. _return document tuple_ :post: *** _the document_ :document: #+name: abs_post #+BEGIN_SRC d auto document_the = [ "head": the_document_head_section, "toc_seg": the_table_of_contents_section["seg"], "toc_scroll": the_table_of_contents_section["scroll"], /+ substantive/body: +/ "body": the_document_body_section, /+ backmatter: +/ "endnotes": the_endnotes_section, "glossary": the_glossary_section, "bibliography": the_bibliography_section, "bookindex_scroll": the_bookindex_section["scroll"], "bookindex_seg": the_bookindex_section["seg"], "blurb": the_blurb_section, /+ dom tail only +/ "tail": the_dom_tail_section, ]; #+END_SRC *** document _section keys_ sequence #+name: abs_post #+BEGIN_SRC d string[][string] document_section_keys_sequenced = [ "seg": ["head", "toc_seg", "body",], "scroll": ["head", "toc_scroll", "body",] ]; if (document_the["endnotes"].length > 1) { document_section_keys_sequenced["seg"] ~= "endnotes"; document_section_keys_sequenced["scroll"] ~= "endnotes"; } if (document_the["glossary"].length > 1) { document_section_keys_sequenced["seg"] ~= "glossary"; document_section_keys_sequenced["scroll"] ~= "glossary"; } if (document_the["bibliography"].length > 1) { document_section_keys_sequenced["seg"] ~= "bibliography"; document_section_keys_sequenced["scroll"] ~= "bibliography"; } if (document_the["bookindex_seg"].length > 1) { document_section_keys_sequenced["seg"] ~= "bookindex_seg"; } if (document_the["bookindex_scroll"].length > 1) { document_section_keys_sequenced["scroll"] ~= "bookindex_scroll"; } if (document_the["blurb"].length > 1) { document_section_keys_sequenced["seg"] ~= "blurb"; document_section_keys_sequenced["scroll"] ~= "blurb"; } if ((opt_action_bool["html"]) || (opt_action_bool["html_scroll"]) || (opt_action_bool["html_seg"]) || (opt_action_bool["epub"])) { document_section_keys_sequenced["seg"] ~= "tail"; document_section_keys_sequenced["scroll"] ~= "tail"; } #+END_SRC *** dup #+name: abs_post #+BEGIN_SRC d auto segnames = html_segnames.dup; #+END_SRC *** clean out structure #+name: abs_post #+BEGIN_SRC d destroy(the_document_head_section); destroy(the_table_of_contents_section); destroy(the_document_body_section); destroy(the_endnotes_section); destroy(the_glossary_section); destroy(the_bibliography_section); destroy(the_bookindex_section); destroy(the_blurb_section); destroy(html_segnames); destroy(bookindex_unordered_hashes); destroy(an_object); biblio_arr_json = []; obj_cite_number=0; obj_cite_number_=0; html_segnames_ptr=0; html_segnames_ptr_cntr=0; content_non_header = "8"; dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; dom_markedup_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; dom_collapsed_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; #+END_SRC *** [#A] _return document tuple_ :return:tuple: #+name: abs_post #+BEGIN_SRC d auto t = tuple( document_the, docSectKeysSeq!()(document_section_keys_sequenced), segnames, segnames_0_4, images, ); return t; #+END_SRC ** 5. Functions :abstract:function: functions used in document abstraction *** set & resets :reset: **** object reset: remove (clean) :object:remove: #+name: abs_functions_object_reset #+BEGIN_SRC d auto object_reset(O)(ref O an_object) { debug(asserts) { static assert(is(typeof(an_object) == string[string])); } an_object.remove("body_nugget"); an_object.remove("substantive"); an_object.remove("is"); an_object.remove("attrib"); an_object.remove("bookindex_nugget"); } #+END_SRC **** set, initialize or re-initialize :set: #+name: abs_functions_header_set_common #+BEGIN_SRC d auto _common_reset_(L,O,T)( return ref L line_occur, return ref O an_object, return ref T type ) { debug(asserts) { static assert(is(typeof(line_occur) == int[string])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } line_occur["heading"] = State.off; line_occur["para"] = State.off; type["heading"] = State.off; type["para"] = State.off; object_reset(an_object); } #+END_SRC *** check obj_cite_number status in document :ocn: #+name: abs_functions_ocn_status #+BEGIN_SRC d void _check_ocn_status_(L,T)( L line, return ref T type ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if ((!line.empty) && (type["ocn_status_multi_obj"] == TriState.off)) { /+ not multi-line object, check whether obj_cite_number is on or turned off +/ if (line.matchFirst(rgx.obj_cite_number_block_marks)) { /+ switch off obj_cite_number +/ if (line.matchFirst(rgx.obj_cite_number_off_block)) { type["ocn_status_multi_obj"] = TriState.on; debug(ocnoff) { writeln(line); } } if (line.matchFirst(rgx.obj_cite_number_off_block_dh)) { type["ocn_status_multi_obj"] = TriState.closing; debug(ocnoff) { writeln(line); } } } else { if (type["ocn_status_multi_obj"] == TriState.off) { if (line.matchFirst(rgx.obj_cite_number_off)) { type["ocn_status"] = TriState.on; } else if (line.matchFirst(rgx.obj_cite_number_off_dh)) { type["ocn_status"] = TriState.closing; } else { type["ocn_status"] = TriState.off; } } else { type["ocn_status"] = type["ocn_status_multi_obj"]; } } } else if ((!line.empty) && (type["ocn_status_multi_obj"] > TriState.off)) { if (line.matchFirst(rgx.obj_cite_number_off_block_close)) { type["ocn_status_multi_obj"] = TriState.off; type["ocn_status"] = TriState.off; debug(ocnoff) { writeln(line); } } } } #+END_SRC *** block :block: **** block start (open) block :start: ***** { block starts function #+name: abs_functions_block #+BEGIN_SRC d void _start_block_(L,T,N)( L line, return ref T type, N obj_cite_number_poem ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(type) == int[string])); static assert(is(typeof(obj_cite_number_poem) == string[string])); } #+END_SRC ***** block (various) curly open :curly: #+name: abs_functions_block #+BEGIN_SRC d auto rgx = Rgx(); 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 ); } type["blocks"] = TriState.on; type["code"] = TriState.on; type["curly_code"] = TriState.on; } else if (line.matchFirst(rgx.block_curly_poem_open)) { /+ curly poem open +/ debug(poem) { // poem (curly) open writefln( "* [poem curly] %s", line ); } obj_cite_number_poem["start"] = obj_cite_number.to!string; type["blocks"] = TriState.on; type["verse_new"] = State.on; type["poem"] = TriState.on; type["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 ); } type["blocks"] = TriState.on; type["group"] = TriState.on; type["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 ); } type["blocks"] = TriState.on; type["block"] = TriState.on; type["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 ); } type["blocks"] = TriState.on; type["quote"] = TriState.on; type["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"; type["blocks"] = TriState.on; type["table"] = TriState.on; type["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"; type["blocks"] = TriState.on; type["table"] = TriState.on; type["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 ); } type["blocks"] = TriState.on; type["code"] = TriState.on; type["tic_code"] = TriState.on; } else if (line.matchFirst(rgx.block_tic_poem_open)) { /+ tic poem open +/ debug(poem) { // poem (tic) open writefln( "* [poem tic] %s", line ); } obj_cite_number_poem["start"] = obj_cite_number.to!string; type["blocks"] = TriState.on; type["verse_new"] = State.on; type["poem"] = TriState.on; type["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 ); } type["blocks"] = TriState.on; type["group"] = TriState.on; type["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 ); } type["blocks"] = TriState.on; type["block"] = TriState.on; type["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 ); } type["blocks"] = TriState.on; type["quote"] = TriState.on; type["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"; type["blocks"] = TriState.on; type["table"] = TriState.on; type["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)( return ref L line, return ref O an_object, return ref T type ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if (type["curly_code"] == TriState.on) { if (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; type["blocks"] = TriState.closing; type["code"] = TriState.closing; type["curly_code"] = TriState.off; } else { debug(code) { // code (curly) line writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // code (curly) line } } else if (type["tic_code"] == TriState.on) { if (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; type["blocks"] = TriState.closing; type["code"] = TriState.closing; type["tic_code"] = TriState.off; } else { debug(code) { // code (tic) line writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // code (tic) line } } } #+END_SRC ***** biblio block :biblio: ****** biblio tag map #+name: abs_functions_block_biblio #+BEGIN_SRC d final string biblio_tag_map(A)(A abr) { debug(asserts) { static assert(is(typeof(abr) == string)); } auto btm = [ "au" : "author_raw", "ed" : "editor_raw", "ti" : "fulltitle", "lng" : "language", "jo" : "journal", "vol" : "volume", "edn" : "edition", "yr" : "year", "pl" : "place", "pb" : "publisher", "pub" : "publisher", "pg" : "pages", "pgs" : "pages", "sn" : "short_name" ]; return btm[abr]; } #+END_SRC ******* +consider+ #+name: none #+BEGIN_SRC d final string biblio_tag_map_(A)(A abr) { debug(asserts) { static assert(is(typeof(abr) == string)); } string name; switch (abr) { case "au": name="author_raw"; break; case "ed": name="editor_raw"; break; case "ti": name="fulltitle"; break; case "lng": name="language"; break; case "jo": name="journal"; break; case "vol": name="volume"; break; case "edn": name="edition"; break; case "yr": name="year"; break; case "pl": name="place"; break; case "pb": name="publisher"; break; case "pub": name="publisher"; break; case "pg": name="pages"; break; case "pgs": name="pages"; break; case "sn": name="short_name"; break; default: name=abr; break; } return name; } #+END_SRC ****** biblio block #+name: abs_functions_block_biblio #+BEGIN_SRC d void _biblio_block_( char[] line, return ref int[string] type, return ref int bib_entry, return ref string biblio_entry_str_json, return ref string[] biblio_arr_json ) { mixin SiSUbiblio; auto jsn = BibJsnStr(); auto rgx = Rgx(); if (line.matchFirst(rgx.heading_biblio)) { type["biblio_section"] = TriState.on; type["blurb_section"] = State.off; type["glossary_section"] = State.off; } if (line.empty) { debug { debug(biblioblock) { writeln("---"); } debug(biblioblockinclude) { writeln(biblio_entry_str_json.length); } } if ((bib_entry == State.off) && (biblio_entry_str_json.empty)) { bib_entry = State.on; biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr; } else if (!(biblio_entry_str_json.empty)) { bib_entry = State.off; if (!(biblio_entry_str_json == jsn.biblio_entry_tags_jsonstr)) { auto biblio_entry = parseJSON(biblio_entry_str_json); if (biblio_entry["fulltitle"].str.empty) { writeln("check problem entry (Title missing): ", biblio_entry_str_json); } else if ((biblio_entry["author_raw"].str.empty) && (biblio_entry["editor_raw"].str.empty)) { writeln("check problem entry (No author and no editor): ", biblio_entry_str_json); } else { biblio_arr_json ~= biblio_entry_str_json; } biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr; } } else { // CHECK ERROR writeln("?? 2. ERROR ", biblio_entry_str_json, "??"); biblio_entry_str_json = ""; } } else if (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)( return ref L line, return ref O an_object, return ref T type ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if (type["curly_quote"] == TriState.on) { if (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; type["blocks"] = TriState.closing; type["quote"] = TriState.closing; type["curly_quote"] = TriState.off; } else { debug(quote) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build quote array (or string) } } else if (type["tic_quote"] == TriState.on) { if (line.matchFirst(rgx.block_tic_close)) { debug(quote) { // quote (tic) close writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; type["blocks"] = TriState.closing; type["quote"] = TriState.closing; type["tic_quote"] = TriState.off; } else { debug(quote) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build quote array (or string) } } } #+END_SRC ***** 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)( return ref L line, return ref O an_object, return ref T type ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if (type["curly_group"] == State.on) { if (line.matchFirst(rgx.block_curly_group_close)) { debug(group) { writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; type["blocks"] = TriState.closing; type["group"] = TriState.closing; type["curly_group"] = TriState.off; } else { debug(group) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build group array (or string) } } else if (type["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; type["blocks"] = TriState.closing; type["group"] = TriState.closing; type["tic_group"] = TriState.off; } else { debug(group) { // group writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build group array (or string) } } } #+END_SRC ***** block block :block: - apply inline markup - keep whitespace indentation - keep newlines #+name: abs_functions_block_block #+BEGIN_SRC d void _block_block_(L,O,T)( return ref L line, return ref O an_object, return ref T type ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if (type["curly_block"] == TriState.on) { if (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; type["blocks"] = TriState.closing; type["block"] = TriState.closing; type["curly_block"] = TriState.off; } else { debug(block) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build block array (or string) } } else if (type["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; type["blocks"] = TriState.closing; type["block"] = TriState.closing; type["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,Ma)( L line, return ref O an_object, return ref T type, return ref C cntr, N obj_cite_number_poem, Ma dochead_make_aa, ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); static assert(is(typeof(cntr) == int)); static assert(is(typeof(obj_cite_number_poem) == string[string])); static assert(is(typeof(dochead_make_aa) == string[string][string])); } auto rgx = Rgx(); if (type["curly_poem"] == TriState.on) { if (line.matchFirst(rgx.block_curly_poem_close)) { if (an_object_key in an_object || processing.length > 0) { an_object[an_object_key] = ""; debug(poem) { // poem (curly) close writefln( "* [poem curly] %s", line ); } if (processing.length > 0) { an_object[an_object_key] = processing["verse"]; } debug(poem) { // poem (curly) close writeln(__LINE__); writefln( "* %s %s", obj_cite_number, line ); } if (an_object.length > 0) { debug(poem) { // poem (curly) close writeln( obj_cite_number, an_object[an_object_key] ); } an_object["is"] = "verse"; auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; } object_reset(an_object); processing.remove("verse"); ++cntr; } obj_cite_number_poem["end"] = obj_cite_number.to!string; type["blocks"] = TriState.closing; type["poem"] = TriState.closing; type["curly_poem"] = TriState.off; } else { processing["verse"] ~= line ~= "\n"; if (type["verse_new"] == State.on) { obj_cite_number = ocn_emit(type["ocn_status"]); type["verse_new"] = State.off; } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) { processing["verse"] = processing["verse"].stripRight; verse_line = TriState.off; type["verse_new"] = State.on; } if (type["verse_new"] == State.on) { verse_line=1; an_object[an_object_key] = processing["verse"]; debug(poem) { // poem verse writefln( "* %s curly\n%s", obj_cite_number, an_object[an_object_key] ); } processing.remove("verse"); an_object["is"] = "verse"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; } } } else if (type["tic_poem"] == TriState.on) { if (auto m = line.matchFirst(rgx.block_tic_close)) { // tic_poem_close an_object[an_object_key]="verse"; debug(poem) { // poem (curly) close writefln( "* [poem tic] %s", line ); } if (processing.length > 0) { an_object[an_object_key] = processing["verse"]; } if (an_object.length > 0) { debug(poem) { // poem (tic) close writeln(__LINE__); writeln(obj_cite_number, 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, dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; obj_cite_number_poem["end"] = obj_cite_number.to!string; object_reset(an_object); processing.remove("verse"); ++cntr; } type["blocks"] = TriState.closing; type["poem"] = TriState.closing; type["tic_poem"] = TriState.off; } else { processing["verse"] ~= line ~= "\n"; if (type["verse_new"] == State.on) { obj_cite_number = ocn_emit(type["ocn_status"]); type["verse_new"] = State.off; } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) { processing["verse"] = processing["verse"].stripRight; type["verse_new"] = State.on; verse_line = TriState.off; } if (type["verse_new"] == State.on) { verse_line=1; an_object[an_object_key] = processing["verse"]; debug(poem) { // poem (tic) close writefln( "* %s tic\n%s", obj_cite_number, an_object[an_object_key] ); } processing.remove("verse"); an_object["is"] = "verse"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "verse"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; object_reset(an_object); processing.remove("verse"); ++cntr; } } } } #+END_SRC ***** table block :table: there are 3 types of table markup that need to be nomalized (given a single representation) here - curly brace block - tic block - special notation block you need: - identify the type for the munging to create uniform presentation - curly, tick, special - table heading row, bool - present table header info in uniform way - table_number_of_columns, int (count) - table_column_widths, int[] column widths (as given or calculate average) - show table walls, bool - table content marked up in uniform way #+name: abs_functions_block_table #+BEGIN_SRC d void _table_block_(L,O,T,Ma)( return ref L line, return ref O an_object, return ref T type, return ref Ma dochead_make_aa ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if (type["curly_table"] == TriState.on) { if (line.matchFirst(rgx.block_curly_table_close)) { debug(table) { // table (curly) close writeln(line); } type["blocks"] = TriState.closing; type["table"] = TriState.closing; type["curly_table"] = TriState.off; } else { debug(table) { // table writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build table array (or string) } } else if (type["curly_table_special_markup"] == TriState.on) { if (line.empty) { type["blocks"] = TriState.off; type["table"] = TriState.off; type["curly_table_special_markup"] = TriState.off; _table_closed_make_special_notation_table_( line, an_object, the_document_body_section, obj_cite_number, comp_obj_heading, cntr, type, dochead_make_aa ); } else { debug(table) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } else if (type["tic_table"] == TriState.on) { if (line.matchFirst(rgx.block_tic_close)) { debug(table) { // table (tic) close writeln(line); } type["blocks"] = TriState.closing; type["table"] = TriState.closing; type["tic_table"] = TriState.off; } else { debug(table) { // table writeln(line); } an_object[an_object_key] ~= line ~= "\n"; // build table array (or string) } } } #+END_SRC **** 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_( char[] line, return ref string[string] an_object, return ref ObjGenericComposite[] the_document_body_section, return ref int obj_cite_number, return ref ObjGenericComposite _comp_obj_heading, return ref int cntr, return ref int[string] type, string[string][string] dochead_make_aa, ) { comp_obj_block = comp_obj_block.init; obj_cite_number = ocn_emit(type["ocn_status"]); auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, "table" ); an_object["is"] = "table"; auto substantive_obj_misc_tuple = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, "body_nugget", dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; 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)( 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 int obj_cite_number, return ref ObjGenericComposite _comp_obj_heading, return ref int cntr, return ref int[string] type, string[string] obj_cite_number_poem, string[string][string] dochead_make_aa, ) { assert( line.empty, "line should be empty" ); assert( (type["blocks"] == TriState.closing), "code block status: closed" ); assertions_flag_types_block_status_none_or_closed(type); #+END_SRC ***** make: quote block #+name: abs_functions_block_line_status_empty #+BEGIN_SRC d if (type["quote"] == TriState.closing) { obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_number, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "quote"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, 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, dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "quote"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; type["blocks"] = TriState.off; type["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 (type["group"] == TriState.closing) { obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_number, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "group"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, 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, dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "group"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; type["blocks"] = TriState.off; type["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 (type["block"] == TriState.closing) { obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_number, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "block"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, 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, dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; comp_obj_block = comp_obj_block.init; comp_obj_block.use = "body"; comp_obj_block.is_of = "block"; comp_obj_block.is_a = "block"; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; comp_obj_block.text = an_object["substantive"]; comp_obj_block.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_block.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_block.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_block; type["blocks"] = TriState.off; type["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 (type["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_number, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "verse"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, cntr, heading_ptr-1, an_object["is"] ); comp_obj_poem_ocn = comp_obj_poem_ocn.init; comp_obj_poem_ocn.use = "body"; comp_obj_poem_ocn.is_of = "block"; comp_obj_poem_ocn.is_a = "poem"; comp_obj_poem_ocn.ocn = obj_cite_number; comp_obj_poem_ocn.obj_cite_number = (obj_cite_number_poem["start"], obj_cite_number_poem["end"]); comp_obj_poem_ocn.text = ""; the_document_body_section ~= comp_obj_poem_ocn; type["blocks"] = TriState.off; type["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 (type["code"] == TriState.closing) { obj_cite_number = ocn_emit(type["ocn_status"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_number, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "code"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, 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, dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; anchor_tags = substantive_obj_misc_tuple[sObj.anchor_tags]; comp_obj_code = comp_obj_code.init; comp_obj_code.use = "body"; comp_obj_code.is_of = "block"; comp_obj_code.is_a = "code"; comp_obj_code.ocn = obj_cite_number; comp_obj_code.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; comp_obj_code.text = an_object["substantive"]; comp_obj_code.inline_notes_reg = substantive_obj_misc_tuple[sObj.notes_reg]; comp_obj_code.inline_notes_star = substantive_obj_misc_tuple[sObj.notes_star]; comp_obj_code.inline_links = substantive_obj_misc_tuple[sObj.links]; the_document_body_section ~= comp_obj_code; type["blocks"] = TriState.off; type["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 (type["table"] == TriState.closing) { comp_obj_block = comp_obj_block.init; obj_cite_number = ocn_emit(type["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_number, segment_anchor_tag_that_object_belongs_to ); an_object["is"] = "table"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, segment_anchor_tag_that_object_belongs_to, obj_cite_number, 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, dochead_make_aa); an_object["substantive"] = substantive_obj_misc_tuple[sObj.content]; comp_obj_block = comp_obj_block.init; comp_obj_block.ocn = obj_cite_number; comp_obj_block.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; 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; type["blocks"] = TriState.off; type["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 type, B opt_action_bool, ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(book_idx_tmp) == string)); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(type) == int[string])); static assert(is(typeof(opt_action_bool) == bool[string])); } auto rgx = Rgx(); if (auto m = line.match(rgx.book_index)) { /+ match book_index +/ debug(bookindexmatch) { // book index writefln( "* [bookindex] %s\n", m.captures[1].to!string, ); } an_object["bookindex_nugget"] = m.captures[1].to!string; } else if (auto m = line.match(rgx.book_index_open)) { /+ match open book_index +/ type["book_index"] = State.on; if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) { book_idx_tmp = m.captures[1].to!string; debug(bookindexmatch) { // book index writefln( "* [bookindex] %s\n", book_idx_tmp, ); } } } else if (type["book_index"] == State.on ) { /+ book_index flag set +/ if (auto m = line.match(rgx.book_index_close)) { type["book_index"] = State.off; if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) { an_object["bookindex_nugget"] = book_idx_tmp ~ m.captures[1].to!string; debug(bookindexmatch) { // book index writefln( "* [bookindex] %s\n", book_idx_tmp, ); } } book_idx_tmp = ""; } else { if (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"]) { book_idx_tmp ~= line; } } } } #+END_SRC *** heading or paragraph :heading:paragraph: **** heading found :heading: #+name: abs_functions_heading #+BEGIN_SRC d auto _heading_found_(L,X,H,R,T)( L line, X dochead_make_identify_unmarked_headings, return ref H heading_match_str, return ref R heading_match_rgx, return ref T type ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(dochead_make_identify_unmarked_headings) == string)); static assert(is(typeof(heading_match_str) == string[string])); static assert(is(typeof(heading_match_rgx) == Regex!(char)[string])); static assert(is(typeof(type) == int[string])); } auto rgx = Rgx(); if ((dochead_make_identify_unmarked_headings.length > 2) && (type["make_headings"] == State.off)) { /+ headings found +/ debug(headingsfound) { writeln(dochead_make_identify_unmarked_headings); } char[][] make_headings_spl = (cast(char[]) dochead_make_identify_unmarked_headings) .split(rgx.make_heading_delimiter); debug(headingsfound) { writeln(make_headings_spl.length); writeln(make_headings_spl); } switch (make_headings_spl.length) { case 7 : if (!empty(make_headings_spl[6])) { heading_match_str["h_4"] = "^(" ~ make_headings_spl[6].to!string ~ ")"; heading_match_rgx["h_4"] = regex(heading_match_str["h_4"]); } goto case; case 6 : if (!empty(make_headings_spl[5])) { heading_match_str["h_3"] = "^(" ~ make_headings_spl[5].to!string ~ ")"; heading_match_rgx["h_3"] = regex(heading_match_str["h_3"]); } goto case; case 5 : if (!empty(make_headings_spl[4])) { heading_match_str["h_2"] = "^(" ~ make_headings_spl[4].to!string ~ ")"; heading_match_rgx["h_2"] = regex(heading_match_str["h_2"]); } goto case; case 4 : if (!empty(make_headings_spl[3])) { heading_match_str["h_1"] = "^(" ~ make_headings_spl[3].to!string ~ ")"; heading_match_rgx["h_1"] = regex(heading_match_str["h_1"]); } goto case; case 3 : if (!empty(make_headings_spl[2])) { heading_match_str["h_D"] = "^(" ~ make_headings_spl[2].to!string ~ ")"; heading_match_rgx["h_D"] = regex(heading_match_str["h_D"]); } goto case; case 2 : if (!empty(make_headings_spl[1])) { heading_match_str["h_C"] = "^(" ~ make_headings_spl[1].to!string ~ ")"; heading_match_rgx["h_C"] = regex(heading_match_str["h_C"]); } goto case; case 1 : if (!empty(make_headings_spl[0])) { heading_match_str["h_B"] = "^(" ~ make_headings_spl[0].to!string ~ ")"; heading_match_rgx["h_B"] = regex(heading_match_str["h_B"]); } break; default: break; } type["make_headings"] = State.on; } } #+END_SRC **** heading make set :heading: #+name: abs_functions_heading #+BEGIN_SRC d auto _heading_make_set_(L,C,R,T)( L line, C line_occur, return ref R heading_match_rgx, return ref T type ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(line_occur) == int[string])); static assert(is(typeof(heading_match_rgx) == Regex!(char)[string])); static assert(is(typeof(type) == int[string])); } if ((type["make_headings"] == State.on) && ((line_occur["para"] == State.off) && (line_occur["heading"] == State.off)) && ((type["para"] == State.off) && (type["heading"] == State.off))) { /+ heading make set +/ if (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,Me)( return ref 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 type, return ref Me dochead_meta_aa, ) { debug(asserts) { static assert(is(typeof(line) == char[])); static assert(is(typeof(line_occur) == int[string])); static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(an_object_key) == string)); static assert(is(typeof(lv) == int[string])); static assert(is(typeof(collapsed_lev) == int[string])); static assert(is(typeof(type) == int[string])); static assert(is(typeof(dochead_meta_aa) == string[string][string])); } auto rgx = Rgx(); if (auto m = line.match(rgx.heading)) { /+ heading match +/ type["heading"] = State.on; if (line.match(rgx.heading_seg_and_above)) { type["biblio_section"] = State.off; type["glossary_section"] = State.off; type["blurb_section"] = State.off; } type["para"] = State.off; ++line_occur["heading"]; an_object[an_object_key] ~= line ~= "\n"; an_object["lev"] ~= m.captures[1]; assertions_doc_structure(an_object, lv); // includes most of the logic for collapsed levels switch (an_object["lev"]) { case "A": an_object[an_object_key]=(an_object[an_object_key]) .replaceFirst(rgx.variable_doc_title, (dochead_meta_aa["title"]["full"] ~ ",")) .replaceFirst(rgx.variable_doc_author, dochead_meta_aa["creator"]["author"]); collapsed_lev["h0"] = 0; an_object["lev_collapsed_number"] = collapsed_lev["h0"].to!string; lv["lv"] = DocStructMarkupHeading.h_sect_A; ++lv["h0"]; lv["h1"] = State.off; lv["h2"] = State.off; lv["h3"] = State.off; lv["h4"] = State.off; lv["h5"] = State.off; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "B": collapsed_lev["h1"] = collapsed_lev["h0"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h1"].to!string; lv["lv"] = DocStructMarkupHeading.h_sect_B; ++lv["h1"]; lv["h2"] = State.off; lv["h3"] = State.off; lv["h4"] = State.off; lv["h5"] = State.off; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "C": collapsed_lev["h2"] = collapsed_lev["h1"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h2"].to!string; lv["lv"] = DocStructMarkupHeading.h_sect_C; ++lv["h2"]; lv["h3"] = State.off; lv["h4"] = State.off; lv["h5"] = State.off; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "D": collapsed_lev["h3"] = collapsed_lev["h2"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h3"].to!string; lv["lv"] = DocStructMarkupHeading.h_sect_D; ++lv["h3"]; lv["h4"] = State.off; lv["h5"] = State.off; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "1": if (lv["h3"] > State.off) { collapsed_lev["h4"] = collapsed_lev["h3"] + 1; } else if (lv["h2"] > State.off) { collapsed_lev["h4"] = collapsed_lev["h2"] + 1; } else if (lv["h1"] > State.off) { collapsed_lev["h4"] = collapsed_lev["h1"] + 1; } else if (lv["h0"] > State.off) { collapsed_lev["h4"] = collapsed_lev["h0"] + 1; } an_object["lev_collapsed_number"] = collapsed_lev["h4"].to!string; lv["lv"] = DocStructMarkupHeading.h_text_1; ++lv["h4"]; lv["h5"] = State.off; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "2": if (lv["h5"] > State.off) { an_object["lev_collapsed_number"] = collapsed_lev["h5"].to!string; } else if (lv["h4"] > State.off) { collapsed_lev["h5"] = collapsed_lev["h4"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h5"].to!string; } lv["lv"] = DocStructMarkupHeading.h_text_2; ++lv["h5"]; lv["h6"] = State.off; lv["h7"] = State.off; goto default; case "3": if (lv["h6"] > State.off) { an_object["lev_collapsed_number"] = collapsed_lev["h6"].to!string; } else if (lv["h5"] > State.off) { collapsed_lev["h6"] = collapsed_lev["h5"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h6"].to!string; } lv["lv"] = DocStructMarkupHeading.h_text_3; ++lv["h6"]; lv["h7"] = State.off; goto default; case "4": if (lv["h7"] > State.off) { an_object["lev_collapsed_number"] = collapsed_lev["h7"].to!string; } else if (lv["h6"] > State.off) { collapsed_lev["h7"] = collapsed_lev["h6"] + 1; an_object["lev_collapsed_number"] = collapsed_lev["h7"].to!string; } lv["lv"] = DocStructMarkupHeading.h_text_4; ++lv["h7"]; goto default; default: an_object["lev_markup_number"] = lv["lv"].to!string; } debug(heading) { // heading writeln(line.strip); } } } #+END_SRC **** para match :para: #+name: abs_functions_para #+BEGIN_SRC d void _para_match_(L,O,K,I,B,T,C)( return ref L line, return ref O an_object, return ref K an_object_key, return ref I indent, return ref B bullet, return ref T type, 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(type) == int[string])); static assert(is(typeof(line_occur) == int[string])); } auto rgx = Rgx(); if (line_occur["para"] == State.off) { line = font_faces_line(line); /+ para matches +/ type["para"] = State.on; an_object[an_object_key] ~= line; // body_nugget indent=[ "hang_position" : 0, "base_position" : 0, ]; bullet = false; if (auto m = line.matchFirst(rgx.para_indent)) { debug(paraindent) { // para indent writeln(line); } indent["hang_position"] = (m.captures[1]).to!int; indent["base_position"] = 0; } else if (line.matchFirst(rgx.para_bullet)) { debug(parabullet) { // para bullet writeln(line); } bullet = true; } else if (auto m = line.matchFirst(rgx.para_indent_hang)) { debug(paraindenthang) { // para indent hang writeln(line); } indent=[ "hang_position" : (m.captures[1]).to!int, "base_position" : (m.captures[2]).to!int, ]; } else if (auto m = line.matchFirst(rgx.para_bullet_indent)) { debug(parabulletindent) { // para bullet indent writeln(line); } indent=[ "hang_position" : (m.captures[1]).to!int, "base_position" : 0, ]; bullet = true; } ++line_occur["para"]; } } #+END_SRC **** text font face #+name: abs_functions_para #+BEGIN_SRC d auto font_faces_line(T)( return ref T textline, ) { 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, ) { auto rgx = Rgx(); table_object.use = "body"; table_object.is_of = "block"; table_object.is_a = "table"; table_object.inline_notes_reg = false; table_object.inline_notes_star = false; table_object.inline_links = false; if (auto m = table_head.matchFirst(rgx.table_head_instructions)) { table_object.table_heading = ((m["c_heading"].length > 0) && (m["c_heading"] == "h")) ? true : false; table_object.table_number_of_columns = ((m["c_num"].length > 0) && (m["c_num"].to!int > 0)) ? m["c_num"].to!int : 0; // double check, may be obsolete foreach (cw; m["c_widths"].matchAll(rgx.table_col_widths)) { auto x = cw.hit.matchFirst(rgx.table_col_widths_and_alignment); table_object.table_column_widths ~= x["width"].to!int; table_object.table_column_aligns ~= (x["align"].empty) ? "" : x["align"]; } } return table_object; } #+END_SRC ***** table array munge #+name: abs_functions_table #+BEGIN_SRC d auto table_array_munge(O,T)( return ref O table_object, return ref T table_array, ) { auto rgx = Rgx(); 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 (idx_r == 1 && col.match(rgx.numeric_col)) { 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, ) { auto rgx = Rgx(); 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, ) { auto rgx = Rgx(); 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, ) { auto rgx = Rgx(); 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: ao_emitters_ocn #+BEGIN_SRC d struct OCNemitter { int obj_cite_number, obj_cite_number_; int ocn_emitter(int ocn_status_flag) in { assert(ocn_status_flag <= 3); } body { if (ocn_status_flag == 3) { obj_cite_number = obj_cite_number_ = 1; } else { obj_cite_number=(ocn_status_flag == 0) ? ++obj_cite_number_ : 0; } assert(obj_cite_number >= 0); return obj_cite_number; } invariant() { } } #+END_SRC ***** object inline markup munge :markup:inline: ****** { struct, inline markup munge #+name: ao_emitters_obj_inline_markup_munge #+BEGIN_SRC d struct ObjInlineMarkupMunge { string[string] obj_txt; int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus; string asterisks_; string obj_txt_out, tail, note; auto rgx = Rgx(); auto mkup = InlineMarkup(); int stage_reset_note_numbers = true; private auto initialize_note_numbers() { n_foot = 0; n_foot_reg = 0; n_foot_sp_asterisk = 0; n_foot_sp_plus = 0; } #+END_SRC ****** url links #+name: ao_emitters_obj_inline_markup_munge #+BEGIN_SRC d string url_links(Ot)(Ot obj_txt_in) { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } /+ url matched +/ if (obj_txt_in.match(rgx.inline_url_generic)) { /+ link: naked url: http://url +/ if (obj_txt_in.match(rgx.inline_link_naked_url)) { obj_txt_in = (obj_txt_in).replaceAll( rgx.inline_link_naked_url, ("$1" ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "$3") // ("$1{ $2 }$2$3") ); } /+ link with helper for endnote including the url: {~^ link which includes url as footnote }http://url maps to: { link which includes url as footnote }http://url~{ { http://url }http://url }~ +/ if (obj_txt_in.match(rgx.inline_link_endnote_url_helper)) { obj_txt_in = (obj_txt_in).replaceAll( rgx.inline_link_endnote_url_helper_punctuated, (mkup.lnk_o ~ "$1" ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ " }~$3") // ("{ $1 }$2~{ { $2 }$2 }~$3") ); obj_txt_in = (obj_txt_in).replaceAll( rgx.inline_link_endnote_url_helper, (mkup.lnk_o ~ "$1" ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ "~{ " ~ mkup.lnk_o ~ " $2 " ~ mkup.lnk_c ~ mkup.url_o ~ "$2" ~ mkup.url_c ~ " }~") // ("{ $1 }$2~{ { $2 }$2 }~") ); } /+ link with regular markup: { linked text or image }http://url +/ if (obj_txt_in.match(rgx.inline_link_markup_regular)) { obj_txt_in = (obj_txt_in).replaceAll( rgx.inline_link_markup_regular, ("$1" ~ mkup.lnk_o ~ "$2" ~ mkup.lnk_c ~ mkup.url_o ~ "$3" ~ mkup.url_c ~ "$4") // ("$1{ $2 }$3$4") ); } } return obj_txt_in; } #+END_SRC ****** footnotes endnotes markup #+name: ao_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; 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_regular)) { flg_notes_reg = true; ++n_foot_reg; n_foot=n_foot_reg; obj_txt_out ~= n.hit.to!string.replaceFirst( rgx.inline_al_delimiter_open_regular, (mkup.en_a_o ~ to!string(n_foot) ~ " ") ) ~ "\n"; } else { obj_txt_out ~= n.hit.to!string ~ "\n"; } } } } else { obj_txt_out = obj_txt_in; } auto t = tuple( obj_txt_out, flg_notes_reg, flg_notes_star, ); return t; } #+END_SRC ****** object notes and links #+name: ao_emitters_obj_inline_markup_munge #+BEGIN_SRC d private auto object_notes_and_links_(Ot)(Ot obj_txt_in, bool reset_note_numbers=false) in { debug(asserts) { assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt_out = ""; bool urls = false; tail = ""; /+ special endnotes +/ obj_txt_in = obj_txt_in.replaceAll( rgx.inline_notes_curly_sp_asterisk, (mkup.en_a_o ~ "*" ~ " $1" ~ mkup.en_a_c) ); obj_txt_in = obj_txt_in.replaceAll( rgx.inline_notes_curly_sp_plus, (mkup.en_a_o ~ "+" ~ " $1" ~ mkup.en_a_c) ); /+ url matched +/ if (obj_txt_in.match(rgx.inline_url)) { urls = true; obj_txt_in = url_links(obj_txt_in); } auto ftn = footnotes_endnotes_markup_and_number_or_stars(obj_txt_in, reset_note_numbers); obj_txt_out = ftn[0]; debug(footnotes) { writeln(obj_txt_out, tail); } obj_txt_out = obj_txt_out ~ tail; debug(footnotesdone) { foreach(m; matchAll(obj_txt_out, (mkup.en_a_o ~ `\s*(.+?)` ~ mkup.en_a_c))) { writeln(m.captures[1]); writeln(m.hit); } } auto t = tuple( obj_txt_out, ftn[1], ftn[2], urls, ); return t; } auto init() in { } body { auto t = object_notes_and_links_(""); return t; } invariant() { } #+END_SRC ****** heading - identified text by heading level marker followed by text until two new lines - general markup #+name: ao_emitters_obj_inline_markup_munge #+BEGIN_SRC d auto munge_heading(Ot)(Ot obj_txt_in, bool reset_note_numbers=false) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=(obj_txt_in) .replaceFirst(rgx.heading, "") .replaceFirst(rgx.obj_cite_number_off_all, "") .strip; auto t = object_notes_and_links_(obj_txt["munge"], reset_note_numbers); debug(munge) { writeln(__LINE__); writeln(obj_txt_in); writeln(__LINE__); writeln(obj_txt["munge"].to!string); } return t; } invariant() { } #+END_SRC ****** para - paragraph text without other identification until two new lines - general markup - paragraph attributes - font faces (bold, italics, underscore etc.) - footnotes/endnotes - links #+name: ao_emitters_obj_inline_markup_munge #+BEGIN_SRC d auto munge_para(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { obj_txt["munge"]=(obj_txt_in) .replaceFirst(rgx.para_attribs, "") .replaceFirst(rgx.obj_cite_number_off_all, ""); auto t = object_notes_and_links_(obj_txt["munge"]); debug(munge) { writeln(__LINE__); writeln(obj_txt_in); writeln(__LINE__); writeln(obj_txt["munge"].to!string); } return t; } #+END_SRC ****** quote #+name: ao_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: ao_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: ao_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: ao_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: ao_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: ao_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: ao_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: ao_emitters_obj_inline_markup_munge #+BEGIN_SRC d } #+END_SRC ***** toc, tags, object inline markup :markup:inline: ****** { #+name: ao_emitters_obj_inline_markup #+BEGIN_SRC d struct ObjInlineMarkup { auto rgx = Rgx(); auto munge = ObjInlineMarkupMunge(); string[string] obj_txt; #+END_SRC ****** object inline markup and anchor tags :markup:inline: #+name: ao_emitters_obj_inline_markup_and_anchor_tags_and_misc #+BEGIN_SRC d auto obj_inline_markup_and_anchor_tags_and_misc(O,K,Ma)( O obj_, K obj_key_, Ma dochead_make_aa ) in { debug(asserts) { static assert(is(typeof(obj_) == string[string])); static assert(is(typeof(obj_key_) == string)); static assert(is(typeof(dochead_make_aa) == string[string][string])); } } body { obj_txt["munge"] = obj_[obj_key_].dup; obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`))) ? obj_txt["munge"] : strip(obj_txt["munge"]); static __gshared string[] anchor_tags_ = []; auto x = munge.init; bool[string] obj_notes_and_links; obj_notes_and_links["notes_reg"] = false; obj_notes_and_links["notes_star"] = false; obj_notes_and_links["links"] = false; switch (obj_["is"]) { case "heading": static __gshared string anchor_tag = ""; obj_txt["munge"]=_configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, dochead_make_aa); obj_txt["munge"]=_make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"]); if (auto m = obj_txt["munge"].match(rgx.heading_anchor_tag)) { anchor_tag = m.captures[1]; anchor_tags_ ~= anchor_tag; } else if (obj_["lev"] == "1") { writeln("heading anchor tag missing: ", obj_txt["munge"]); } x =munge.munge_heading(obj_txt["munge"], reset_note_numbers); reset_note_numbers=false; goto default; case "para": x = munge.munge_para(obj_txt["munge"]); goto default; case "group": x = munge.munge_group(obj_txt["munge"]); goto default; case "block": x = munge.munge_block(obj_txt["munge"]); goto default; case "verse": x = munge.munge_verse(obj_txt["munge"]); goto default; case "code": obj_txt["munge"] = munge.munge_code(obj_txt["munge"]); break; case "table": obj_txt["munge"] = munge.munge_table(obj_txt["munge"]); break; case "quote": obj_txt["munge"] = munge.munge_quote(obj_txt["munge"]); break; case "comment": obj_txt["munge"] = munge.munge_comment(obj_txt["munge"]); break; case "doc_end_reset": munge.initialize_note_numbers(); break; default: /+ para, heading, group, block, verse +/ obj_txt["munge"] = x[0]; obj_notes_and_links["notes_reg"] = x[1]; obj_notes_and_links["notes_star"] = x[2]; obj_notes_and_links["links"] = x[3]; break; } auto t = tuple( obj_txt["munge"], anchor_tags_, obj_notes_and_links["notes_reg"], obj_notes_and_links["notes_star"], obj_notes_and_links["links"], ); anchor_tags_=[]; return t; } invariant() { } #+END_SRC ****** toc (table of contents), build, gather headings :markup:inline: #+name: ao_emitters_obj_inline_markup_table_of_contents #+BEGIN_SRC d auto _clean_heading_toc_(Toc)( Toc heading_toc_, ) { debug(asserts) { static assert(is(typeof(heading_toc_) == char[])); } auto m = (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,Ma,Ts,Ta,X,Toc)( O obj_, Ma dochead_make_aa, 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(dochead_make_aa) == string[string][string])); static assert(is(typeof(segment_anchor_tag_that_object_belongs_to) == string)); static assert(is(typeof(_anchor_tag) == string)); static assert(is(typeof(lev4_subtoc) == string[][string])); static assert(is(typeof(the_table_of_contents_section) == ObjGenericComposite[][string])); } } body { ObjGenericComposite comp_obj_toc; mixin InternalMarkup; auto mkup = InlineMarkup(); char[] heading_toc_ = (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.use = "frontmatter"; comp_obj_toc.is_of = "para"; comp_obj_toc.is_a = "toc"; comp_obj_toc.ocn = 0; comp_obj_toc.obj_cite_number = ""; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.bullet = false; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } else { indent=[ "hang_position" : 0, "base_position" : 0, ]; comp_obj_toc = comp_obj_toc.init; comp_obj_toc.use = "frontmatter"; comp_obj_toc.is_of = "para"; comp_obj_toc.is_a = "toc"; comp_obj_toc.ocn = 0; comp_obj_toc.obj_cite_number = ""; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.bullet = false; comp_obj_toc.text = "Table of Contents"; comp_obj_toc.inline_links = true; the_table_of_contents_section["scroll"] ~= comp_obj_toc; } comp_obj_toc = comp_obj_toc.init; comp_obj_toc.use = "frontmatter"; comp_obj_toc.is_of = "para"; comp_obj_toc.is_a = "toc"; comp_obj_toc.ocn = 0; comp_obj_toc.obj_cite_number = ""; comp_obj_toc.bullet = false; comp_obj_toc.inline_links = true; switch (obj_["lev_markup_number"].to!int) { case 0: indent=[ "hang_position" : 0, "base_position" : 0, ]; toc_txt_ = "{ Table of Contents }" ~ mkup.mark_internal_site_lnk ~ "toc.fnSuffix"; toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; case 1: .. case 3: indent=[ "hang_position" : obj_["lev_markup_number"].to!int, "base_position" : obj_["lev_markup_number"].to!int, ]; toc_txt_ = format( "%s", heading_toc_, ); toc_txt_= munge.url_links(toc_txt_); comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; case 4: toc_txt_ = format( "{ %s }%s%s%s", heading_toc_, mkup.mark_internal_site_lnk, segment_anchor_tag_that_object_belongs_to, ".fnSuffix", ); lev4_subtoc[segment_anchor_tag_that_object_belongs_to] = []; toc_txt_= munge.url_links(toc_txt_); indent=[ "hang_position" : obj_["lev_markup_number"].to!int, "base_position" : obj_["lev_markup_number"].to!int, ]; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; case 5: .. case 7: toc_txt_ = format( "{ %s }%s%s%s#%s", heading_toc_, mkup.mark_internal_site_lnk, segment_anchor_tag_that_object_belongs_to, ".fnSuffix", _anchor_tag, ); subtoc_txt_ = format( "{ %s }#%s", heading_toc_, _anchor_tag, ); lev4_subtoc[segment_anchor_tag_that_object_belongs_to] ~= obj_["lev_markup_number"] ~ "~ " ~ subtoc_txt_.to!string.strip; toc_txt_= munge.url_links(toc_txt_); indent=[ "hang_position" : obj_["lev_markup_number"].to!int, "base_position" : obj_["lev_markup_number"].to!int, ]; comp_obj_toc.indent_hang = indent["hang_position"]; comp_obj_toc.indent_base = indent["base_position"]; comp_obj_toc.text = toc_txt_.to!string.strip; comp_obj_toc.inline_links = true; the_table_of_contents_section["seg"] ~= comp_obj_toc; break; default: break; } return the_table_of_contents_section; } invariant() { } #+END_SRC ****** private: #+name: ao_emitters_obj_inline_markup_private #+BEGIN_SRC d private: #+END_SRC ******* make heading number and segment anchor tags if instructed :markup:inline:segment:anchor:tags: #+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags #+BEGIN_SRC d static string _configured_auto_heading_numbering_and_segment_anchor_tags(M,O,Ma)( M munge_, O obj_, Ma dochead_make_aa ) { debug(asserts) { static assert(is(typeof(munge_) == string)); static assert(is(typeof(obj_) == string[string])); static assert(is(typeof(dochead_make_aa) == string[string][string])); } if (dochead_make_aa["make"]["num_top"].length > 0) { static __gshared int heading_num_top_level=9; static __gshared int heading_num_depth=2; static __gshared int heading_num_0 = 0; static __gshared int heading_num_1 = 0; static __gshared int heading_num_2 = 0; static __gshared int heading_num_3 = 0; static __gshared string heading_number_auto_composite = ""; if (heading_num_top_level==9) { if (dochead_make_aa["make"]["num_depth"].length > 0) { heading_num_depth = dochead_make_aa["make"]["num_depth"].to!uint; } switch (dochead_make_aa["make"]["num_top"]) { case "A": break; case "B": heading_num_top_level=1; break; case "C": heading_num_top_level=2; break; case "D": heading_num_top_level=3; break; case "1": heading_num_top_level=4; break; case "2": heading_num_top_level=5; break; case "3": heading_num_top_level=6; break; case "4": heading_num_top_level=7; break; default: break; } } /+ num_depth minimum 0 (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement +/ if ( heading_num_top_level > obj_["lev_markup_number"].to!uint ) { heading_num_0 = 0; heading_num_1 = 0; heading_num_2 = 0; heading_num_3 = 0; } else if ( heading_num_top_level == obj_["lev_markup_number"].to!uint ) { heading_num_0 ++; heading_num_1 = 0; heading_num_2 = 0; heading_num_3 = 0; } else if ( heading_num_top_level == (obj_["lev_markup_number"].to!uint - 1) ) { heading_num_1 ++; heading_num_2 = 0; heading_num_3 = 0; } else if ( heading_num_top_level == (obj_["lev_markup_number"].to!uint - 2) ) { heading_num_2 ++; heading_num_3 = 0; } else if ( heading_num_top_level == (obj_["lev_markup_number"].to!uint - 3) ) { heading_num_3 ++; } if (heading_num_3 > 0) { heading_number_auto_composite = (heading_num_depth == 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 = ((heading_num_depth >= 2) && (heading_num_depth <= 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 = ((heading_num_depth >= 1) && (heading_num_depth <= 3)) ? ( heading_num_0.to!string ~ "." ~ heading_num_1.to!string ) : ""; } else if (heading_num_0 > 0) { heading_number_auto_composite = ((heading_num_depth >= 0) && (heading_num_depth <= 3)) ? (heading_num_0.to!string) : ""; } else { heading_number_auto_composite = ""; } debug(heading_number_auto) { writeln(heading_number_auto_composite); } if (!(munge_.match(rgx.heading_anchor_tag)) && !empty(heading_number_auto_composite)) { 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 ******** unittests #+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags #+BEGIN_SRC d #+END_SRC ******* make segment anchor tags if not provided :markup:inline:segment:anchor:tags: #+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags #+BEGIN_SRC d static string _make_segment_anchor_tags_if_none_provided(M,Lv)(M munge_, Lv lev_) { debug(asserts) { static assert(is(typeof(munge_) == string)); static assert(is(typeof(lev_) == string)); } if (!(munge_.match(rgx.heading_anchor_tag))) { if (munge_.match(rgx.heading_identify_anchor_tag)) { if (auto m = munge_.match(rgx.heading_extract_named_anchor_tag)) { munge_=(munge_).replaceFirst( rgx.heading_marker_missing_tag, "$1~" ~ m.captures[1].toLower ~ "_" ~ m.captures[2] ~ " "); } else if (auto m = munge_.match(rgx.heading_extract_unnamed_anchor_tag)) { munge_=(munge_).replaceFirst( rgx.heading_marker_missing_tag, "$1~" ~ "s" ~ m.captures[1] ~ " "); } } else if (lev_ == "1") { // (if not successful) manufacture a unique anchor tag for lev=="1" static __gshared int heading_num_lev1 = 0; heading_num_lev1 ++; munge_=(munge_).replaceFirst( rgx.heading_marker_missing_tag, "$1~" ~ "x" ~ heading_num_lev1.to!string ~ " "); } } return munge_; } #+END_SRC ******** unittests #+name: ao_emitters_obj_inline_markup_heading_numbering_segment_anchor_tags #+BEGIN_SRC d unittest { string txt_lev="1"; string txt_in, txt_out; txt_in = "1~copyright Copyright"; txt_out ="1~copyright Copyright"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in = "1~ 6. Writing Copyright Licenses"; txt_out ="1~s6 6. Writing Copyright Licenses"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ 1. Reinforcing trends"; txt_out= "1~s1 1. Reinforcing trends"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ 11 SCIENCE AS A COMMONS"; txt_out= "1~s11 11 SCIENCE AS A COMMONS"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ Chapter 1"; txt_out="1~chapter_1 Chapter 1"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ Chapter 1."; txt_out="1~chapter_1 Chapter 1."; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ Chapter 1: Done"; txt_out="1~chapter_1 Chapter 1: Done"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment"; txt_out= "1~chapter_11 Chapter 11 - The Battle Over the Institutional Ecology of the Digital Environment"; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ CHAPTER I."; txt_out="1~x1 CHAPTER I."; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); txt_in= "1~ CHAPTER II."; txt_out="1~x2 CHAPTER II."; assert(_make_segment_anchor_tags_if_none_provided(txt_in, txt_lev) == txt_out); } #+END_SRC ****** } #+name: ao_emitters_obj_inline_markup_close #+BEGIN_SRC d } #+END_SRC ***** object attrib :attributes: ****** { attributes structure open, public #+name: ao_emitters_obj_attributes #+BEGIN_SRC d struct ObjAttributes { string[string] _obj_attrib; #+END_SRC ****** emitter obj attributes, public #+name: ao_emitters_obj_attributes_public #+BEGIN_SRC d string obj_attributes(Oi,OR,OH)( Oi obj_is_, OR obj_raw, OH _comp_obj_heading, ) in { debug(asserts) { static assert(is(typeof(obj_is_) == string)); static assert(is(typeof(obj_raw) == string)); static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite)); } } body { scope(exit) { destroy(obj_is_); destroy(obj_raw); destroy(_comp_obj_heading); } _obj_attrib["json"] ="{"; switch (obj_is_) { case "heading": _obj_attrib["json"] ~= _heading(obj_raw); break; case "para": _obj_attrib["json"] ~= _para_and_blocks(obj_raw) ~ _para(obj_raw); break; case "code": _obj_attrib["json"] ~= _code(obj_raw); break; case "group": _obj_attrib["json"] ~= _para_and_blocks(obj_raw) ~ _group(obj_raw); break; case "block": _obj_attrib["json"] ~= _para_and_blocks(obj_raw) ~ _block(obj_raw); break; case "verse": _obj_attrib["json"] ~= _verse(obj_raw); break; case "quote": _obj_attrib["json"] ~= _quote(obj_raw); break; case "table": _obj_attrib["json"] ~= _table(obj_raw); break; case "comment": _obj_attrib["json"] ~= _comment(obj_raw); break; default: _obj_attrib["json"] ~= _para(obj_raw); break; } _obj_attrib["json"] ~=" }"; _obj_attrib["json"]=_set_additional_values_parse_as_json(_obj_attrib["json"], obj_is_, _comp_obj_heading); debug(structattrib) { if (oa_j["is"].str() == "heading") { writeln(_obj_attrib["json"]); writeln( "is: ", oa_j["is"].str(), "; obj_cite_number: ", oa_j["obj_cite_number"].integer() ); } } return _obj_attrib["json"]; } invariant() { } #+END_SRC ****** private #+name: ao_emitters_obj_attributes_private #+BEGIN_SRC d private: string _obj_attributes; #+END_SRC ******* attrubutes ******** para & blocks #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _para_and_blocks(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { if (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: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _heading(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"para\"," ~ " \"is\": \"heading\""; return _obj_attributes; } invariant() { } #+END_SRC ******** para #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _para(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"para\"," ~ " \"is\": \"para\""; return _obj_attributes; } invariant() { } #+END_SRC ******** quote #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _quote(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"quote\""; return _obj_attributes; } invariant() { } #+END_SRC ******** group #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _group(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"group\""; return _obj_attributes; } invariant() { } #+END_SRC ******** block #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _block(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"block\""; return _obj_attributes; } invariant() { } #+END_SRC ******** verse #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _verse(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"verse\""; return _obj_attributes; } invariant() { } #+END_SRC ******** code #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _code(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"code\""; return _obj_attributes; } invariant() { } #+END_SRC ******** table #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _table(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"table\""; return _obj_attributes; } invariant() { } #+END_SRC ******** comment #+name: ao_emitters_obj_attributes_private_an_attribute #+BEGIN_SRC d string _comment(Ot)(Ot obj_txt_in) in { debug(asserts) { static assert(is(typeof(obj_txt_in) == string)); } } body { _obj_attributes = " \"use\": \"comment\"," ~ " \"of\": \"comment\"," ~ " \"is\": \"comment\""; return _obj_attributes; } invariant() { } #+END_SRC ******* set additional attribute values, parse as json #+name: ao_emitters_obj_attributes_private_json #+BEGIN_SRC d string _set_additional_values_parse_as_json(OA,Oi,OH)( OA _obj_attrib, Oi obj_is_, OH _comp_obj_heading, ) { debug(asserts) { static assert(is(typeof(_obj_attrib) == string)); static assert(is(typeof(obj_is_) == string)); static assert(is(typeof(_comp_obj_heading) == ObjGenericComposite)); } JSONValue oa_j = parseJSON(_obj_attrib); assert( (oa_j.type == JSON_TYPE.OBJECT) ); if (obj_is_ == "heading") { oa_j.object["obj_cite_number"] = _comp_obj_heading.ocn; oa_j.object["lev_markup_number"] = _comp_obj_heading.heading_lev_markup; oa_j.object["lev_collapsed_number"] = _comp_obj_heading.heading_lev_collapsed; oa_j.object["heading_ptr"] = _comp_obj_heading.ptr_heading; oa_j.object["doc_object_ptr"] = _comp_obj_heading.ptr_doc_object; } oa_j.object["parent_obj_cite_number"] = _comp_obj_heading.parent_ocn; oa_j.object["parent_lev_markup_number"] = _comp_obj_heading.parent_lev_markup; _obj_attrib = oa_j.toString(); return _obj_attrib; } #+END_SRC ****** } #+name: ao_emitters_obj_attributes_private_close #+BEGIN_SRC d } #+END_SRC **** book index :book:index: ***** book index nugget hash :hash:nugget: #+name: ao_emitters_book_index_nugget #+BEGIN_SRC d struct BookIndexNuggetHash { string main_term, sub_term, sub_term_bits; int obj_cite_number_offset, obj_cite_number_endpoint; string[] obj_cite_numbers; string[][string][string] bi; string[][string][string] hash_nugget; string[] bi_main_terms_split_arr; string[][string][string] bookindex_nugget_hash(BI,N,S)( BI bookindex_section, N obj_cite_number, S segment_anchor_tag, ) in { debug(asserts) { static assert(is(typeof(bookindex_section) == string)); static assert(is(typeof(obj_cite_number) == int)); } debug(bookindexraw) { if (!bookindex_section.empty) { writeln( "* [bookindex] ", "[", obj_cite_number.to!string, ": ", segment_anchor_tag, "] ", bookindex_section ); } } } body { auto rgx = Rgx(); if (!bookindex_section.empty) { auto bi_main_terms_split_arr = bookindex_section.split(rgx.bi_main_terms_split); foreach (bi_main_terms_content; bi_main_terms_split_arr) { auto bi_main_term_and_rest = bi_main_terms_content.split(rgx.bi_main_term_plus_rest_split); if (auto m = bi_main_term_and_rest[0].match( rgx.bi_term_and_obj_cite_numbers_match) ) { main_term = m.captures[1].strip; obj_cite_number_offset = m.captures[2].to!int; obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset); obj_cite_numbers ~= (obj_cite_number.to!string ~ "-" ~ to!string(obj_cite_number_endpoint) ~ ":" ~ segment_anchor_tag); } else { main_term = bi_main_term_and_rest[0].strip; obj_cite_numbers ~= obj_cite_number.to!string ~ ":" ~ segment_anchor_tag; } bi[main_term]["_a"] ~= obj_cite_numbers; obj_cite_numbers=null; if (bi_main_term_and_rest.length > 1) { auto bi_sub_terms_split_arr = bi_main_term_and_rest[1].split( rgx.bi_sub_terms_plus_obj_cite_number_offset_split ); foreach (sub_terms_bits; bi_sub_terms_split_arr) { if (auto m = sub_terms_bits.match(rgx.bi_term_and_obj_cite_numbers_match)) { sub_term = m.captures[1].strip; obj_cite_number_offset = m.captures[2].to!int; obj_cite_number_endpoint=(obj_cite_number + obj_cite_number_offset); obj_cite_numbers ~= (obj_cite_number.to!string ~ " - " ~ to!string(obj_cite_number_endpoint) ~ ":" ~ segment_anchor_tag); } else { sub_term = sub_terms_bits.strip; obj_cite_numbers ~= to!string(obj_cite_number) ~ ":" ~ segment_anchor_tag; } if (!empty(sub_term)) { bi[main_term][sub_term] ~= obj_cite_numbers; } obj_cite_numbers=null; } } } } hash_nugget = bi; return hash_nugget; } invariant() { } } #+END_SRC ***** book index (sort &) report indented :report:indented: #+name: ao_emitters_book_index_report_indented #+BEGIN_SRC d struct BookIndexReportIndent { int mkn, skn; auto bookindex_report_indented(BI)( BI bookindex_unordered_hashes ) { debug(asserts) { static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string])); } auto mainkeys= bookindex_unordered_hashes.byKey.array.sort().release; foreach (mainkey; mainkeys) { debug(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: ao_emitters_book_index_report_section #+BEGIN_SRC d struct BookIndexReportSection { int mkn, skn; auto rgx = Rgx(); auto munge = ObjInlineMarkupMunge(); #+END_SRC ****** bookindex write section #+name: ao_emitters_book_index_report_section #+BEGIN_SRC d auto bookindex_write_section(BI)( BI bookindex_unordered_hashes ) { debug(asserts) { static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string])); } auto mainkeys=bookindex_unordered_hashes.byKey.array.sort().release; foreach (mainkey; mainkeys) { write("_0_1 !{", mainkey, "}! "); foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { auto go = (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: ao_emitters_book_index_report_section #+BEGIN_SRC d auto bookindex_build_abstraction_section(BI,N,B)( BI bookindex_unordered_hashes, N obj_cite_number, B opt_action_bool, ) { debug(asserts) { static assert(is(typeof(bookindex_unordered_hashes) == string[][string][string])); static assert(is(typeof(obj_cite_number) == int)); static assert(is(typeof(opt_action_bool) == bool[string])); } mixin SiSUnode; mixin InternalMarkup; auto mkup = InlineMarkup(); string type_is; string lev; int heading_lev_markup, heading_lev_collapsed; string attrib; int[string] indent; auto mainkeys = bookindex_unordered_hashes.byKey.array.sort().release; ObjGenericComposite[][string] bookindex_section; ObjGenericComposite comp_obj_heading_, comp_obj_para; auto node_para_int_ = node_metadata_para_int; auto node_para_str_ = node_metadata_para_str; if ((mainkeys.length > 0) && (opt_action_bool["backmatter"] && opt_action_bool["section_bookindex"])) { string bi_tmp_seg, bi_tmp_scroll; string[] bi_tmp_tags; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Book Index"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "_part_book_index"; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading.inline_links = true; bookindex_section["scroll"] ~= comp_obj_heading_; bookindex_section["seg"] ~= comp_obj_heading_; ++obj_cite_number; ++mkn; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Index"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "bookindex"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading.inline_links = false; comp_obj_heading_.anchor_tags = ["bookindex"]; bookindex_section["scroll"] ~= comp_obj_heading_; bookindex_section["seg"] ~= comp_obj_heading_; ++obj_cite_number; ++mkn; import std.array : appender; auto buffer = appender!(char[])(); string[dchar] transTable = [' ' : "_"]; foreach (mainkey; mainkeys) { bi_tmp_tags = [""]; bi_tmp_scroll = "!{" ~ mainkey ~ "}! "; buffer.clear(); bi_tmp_tags ~= translate(mainkey, transTable); bi_tmp_seg = "!{" ~ mainkey ~ "}! "; 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.use = "backmatter"; comp_obj_para.is_of = "para"; comp_obj_para.is_a = "bookindex"; comp_obj_para.text = bi_tmp_scroll.to!string.strip; comp_obj_para.ocn = obj_cite_number; comp_obj_para.obj_cite_number = (obj_cite_number==0) ? "" : to!string(obj_cite_number); comp_obj_para.anchor_tags = bi_tmp_tags; comp_obj_para.indent_hang = 0; comp_obj_para.indent_base = 1; comp_obj_para.bullet = false; comp_obj_para.inline_links = true; bookindex_section["scroll"] ~= comp_obj_para; comp_obj_para.text = bi_tmp_seg.to!string.strip; bookindex_section["seg"] ~= comp_obj_para; ++obj_cite_number; ++mkn; } } else { // no book index, (figure out what to do here) comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.text = "(skip) there is no Book Index"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; bookindex_section["scroll"] ~= comp_obj_heading_; bookindex_section["seg"] ~= comp_obj_heading_; } auto t = tuple(bookindex_section, obj_cite_number); return t; } #+END_SRC ****** } #+name: ao_emitters_book_index_report_section #+BEGIN_SRC d } #+END_SRC **** (end)notes section :endnotes:section: #+name: ao_emitters_endnotes #+BEGIN_SRC d struct NotesSection { string[string] object_notes; int previous_count; int mkn; auto rgx = Rgx(); #+END_SRC ***** { gather notes for endnote section struct open #+name: ao_emitters_endnotes #+BEGIN_SRC d private auto gather_notes_for_endnote_section( ObjGenericComposite[] contents_am, string segment_anchor_tag_that_object_belongs_to, int cntr, ) in { assert((contents_am[cntr].is_a == "para") || (contents_am[cntr].is_a == "heading") || (contents_am[cntr].is_a == "quote") || (contents_am[cntr].is_a == "group") || (contents_am[cntr].is_a == "block") || (contents_am[cntr].is_a == "verse")); assert(cntr >= previous_count); previous_count=cntr; assert( (contents_am[cntr].text).match( rgx.inline_notes_delimiter_al_regular_number_note) ); } body { mixin InternalMarkup; auto mkup = InlineMarkup(); auto munge = ObjInlineMarkupMunge(); foreach( m; (contents_am[cntr].text).matchAll( rgx.inline_notes_delimiter_al_regular_number_note ) ) { debug(endnotes_build) { writeln( "{^{", m.captures[1], ".}^}" ~ mkup.mark_internal_site_lnk, segment_anchor_tag_that_object_belongs_to, ".fnSuffix#noteref_\n ", m.captures[1], " ", m.captures[2]); // sometimes need segment name (segmented html & epub) } // TODO NEXT you need anchor for segments at this point -> object_notes["anchor"] ~= "note_" ~ m.captures[1] ~ "』"; object_notes["notes"] ~= (segment_anchor_tag_that_object_belongs_to.empty) ? (munge.url_links( "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~ m.captures[1]) ~ " " ~ m.captures[2] ~ "』" ) : (munge.url_links( "{^{" ~ m.captures[1] ~ ".}^}" ~ mkup.mark_internal_site_lnk ~ segment_anchor_tag_that_object_belongs_to ~ ".fnSuffix#noteref_" ~ m.captures[1]) ~ " " ~ m.captures[2] ~ "』" ); } return object_notes; } #+END_SRC ***** gathered notes #+name: ao_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: ao_emitters_endnotes #+BEGIN_SRC d private auto endnote_objects( int obj_cite_number, bool[string] opt_action_bool, ) in { } body { mixin SiSUnode; ObjGenericComposite[] the_endnotes_section; auto endnotes_ = gathered_notes(); string type_is; string lev, lev_markup_number, lev_collapsed_number; string attrib; int[string] indent; ObjGenericComposite comp_obj_heading_; if ((endnotes_["notes"].length > 0) && (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"])) { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Endnotes"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "_part_endnotes"; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_endnotes_section ~= comp_obj_heading_; ++obj_cite_number; ++mkn; comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "backmatter"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "Endnotes"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.segment_anchor_tag = "endnotes"; comp_obj_heading_.marked_up_level = "1"; comp_obj_heading_.heading_lev_markup = 4; comp_obj_heading_.heading_lev_collapsed = 2; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; comp_obj_heading_.anchor_tags = ["endnotes"]; the_endnotes_section ~= comp_obj_heading_; ++obj_cite_number; ++mkn; } else { comp_obj_heading_ = comp_obj_heading_.init; comp_obj_heading_.use = "empty"; comp_obj_heading_.is_of = "para"; comp_obj_heading_.is_a = "heading"; comp_obj_heading_.text = "(skip) there are no Endnotes"; comp_obj_heading_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_heading_.marked_up_level = "B"; comp_obj_heading_.heading_lev_markup = 1; comp_obj_heading_.heading_lev_collapsed = 1; comp_obj_heading_.parent_ocn = 1; comp_obj_heading_.parent_lev_markup = 0; the_endnotes_section ~= comp_obj_heading_; } if (opt_action_bool["backmatter"] && opt_action_bool["section_endnotes"]) { ObjGenericComposite comp_obj_endnote_; comp_obj_endnote_ = comp_obj_endnote_.init; comp_obj_endnote_.use = "backmatter"; comp_obj_endnote_.is_of = "para"; comp_obj_endnote_.is_a = "endnote"; comp_obj_endnote_.ocn = 0; comp_obj_heading_.obj_cite_number = ""; comp_obj_endnote_.indent_hang = 0; comp_obj_endnote_.indent_base = 0; comp_obj_endnote_.bullet = false; foreach (i, endnote; endnotes_["notes"]) { auto m = endnote.matchFirst(rgx.note_ref); string notenumber = m.captures[1].to!string; string anchor_tag = "note_" ~ notenumber; comp_obj_endnote_.anchor_tags = [ endnotes_["anchor"][i] ]; comp_obj_endnote_.inline_links = true; comp_obj_endnote_.text = endnote.strip; the_endnotes_section ~= comp_obj_endnote_; } } auto t = tuple(the_endnotes_section, obj_cite_number); return t; } #+END_SRC ***** } #+name: ao_emitters_endnotes #+BEGIN_SRC d } #+END_SRC **** bibliography :bibliography: ***** { biblio struct #+name: ao_emitters_bibliography #+BEGIN_SRC d struct Bibliography { #+END_SRC ***** biblio #+name: ao_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: ao_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: ao_emitters_bibliography #+BEGIN_SRC d final private JSONValue[] biblio_sort(BJ)(BJ biblio_unordered) { debug(asserts) { static assert(is(typeof(biblio_unordered) == JSONValue[])); } JSONValue[] biblio_sorted_; biblio_sorted_ = sort!((a, b){ return ((a["sortby_deemed_author_year_title"].str) < (b["sortby_deemed_author_year_title"].str)); })(biblio_unordered).array; debug(bibliosorted) { foreach (j; biblio_sorted_) { if (!empty(j["fulltitle"].str)) { writeln(j["sortby_deemed_author_year_title"]); } } } return biblio_sorted_; } #+END_SRC ***** biblio debug #+name: ao_emitters_bibliography #+BEGIN_SRC d void biblio_debug(BJ)(BJ biblio_sorted) { debug(asserts) { static assert(is(typeof(biblio_sorted) == JSONValue[])); } debug(biblio0) { foreach (j; biblio_sorted) { if (!empty(j["fulltitle"].str)) { writeln(j["sortby_deemed_author_year_title"]); } } } } #+END_SRC ***** } #+name: ao_emitters_bibliography #+BEGIN_SRC d } #+END_SRC **** node structure metadata :structure:metadata:node: ***** { metadata node struct #+name: ao_emitters_metadata #+BEGIN_SRC d struct NodeStructureMetadata { int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7; int obj_cite_number; int[string] p_; // p_ parent_ auto rgx = Rgx(); #+END_SRC ***** node metadata emitter #+name: ao_emitters_metadata #+BEGIN_SRC d ObjGenericComposite node_location_emitter(Lv,Ta,N,C,P,I)( Lv lev_markup_number, Ta segment_anchor_tag, N obj_cite_number_, C cntr_, P ptr_, I is_ ) in { debug(asserts) { static assert(is(typeof(lev_markup_number) == string)); static assert(is(typeof(segment_anchor_tag) == string)); static assert(is(typeof(obj_cite_number_) == int)); static assert(is(typeof(cntr_) == int)); static assert(is(typeof(ptr_) == int)); static assert(is(typeof(is_) == string)); } assert(is_ != "heading"); assert(obj_cite_number_.to!int >= 0); } body { assert(is_ != "heading"); // should not be necessary assert(obj_cite_number_.to!int >= 0); // should not be necessary int obj_cite_number = obj_cite_number_.to!int; if (lv7 > State.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_4; p_["obj_cite_number"] = lv7; } else if (lv6 > State.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3; p_["obj_cite_number"] = lv6; } else if (lv5 > State.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2; p_["obj_cite_number"] = lv5; } else { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1; p_["obj_cite_number"] = lv4; } ObjGenericComposite comp_obj_location; comp_obj_location = comp_obj_location.init; comp_obj_location.is_a = is_; comp_obj_location.ocn = obj_cite_number_; comp_obj_location.segment_anchor_tag = segment_anchor_tag.to!string; comp_obj_location.parent_ocn = p_["obj_cite_number"]; comp_obj_location.parent_lev_markup = p_["lev_markup_number"]; debug(node) { if (lev_markup_number.match(rgx.levels_numbered_headings)) { writeln("x ", _node.to!string); } else { writeln("- ", _node.to!string); } } assert(comp_obj_location.parent_lev_markup >= 4); assert(comp_obj_location.parent_lev_markup <= 7); assert(comp_obj_location.parent_ocn >= 0); return comp_obj_location; } invariant() { } #+END_SRC ***** node metadata emitter heading, (including most segnames & their pointers) #+name: ao_emitters_metadata #+BEGIN_SRC d ObjGenericComposite node_emitter_heading(T,L,Lm,Lc,Ta,N,C,P,LA,I,PSn,fNr,fNs,fL)( T _text, L lev, Lm lev_markup_number, Lc lev_collapsed_number, Ta segment_anchor_tag, N obj_cite_number_, C cntr_, P ptr_, LA lv_ancestors, I is_, PSn html_segnames_ptr, fNr flag_notes_reg, fNs flag_notes_star, fL flag_links, ) in { debug(asserts) { static assert(is(typeof(_text) == string)); static assert(is(typeof(lev) == string)); static assert(is(typeof(lev_markup_number) == string)); static assert(is(typeof(lev_collapsed_number) == string)); static assert(is(typeof(segment_anchor_tag) == string)); static assert(is(typeof(obj_cite_number_) == int)); static assert(is(typeof(cntr_) == int)); static assert(is(typeof(ptr_) == int)); static assert(is(typeof(lv_ancestors) == string[])); static assert(is(typeof(is_) == string)); static assert(is(typeof(html_segnames_ptr) == int)); } assert(is_ == "heading"); assert(to!int(obj_cite_number_) >= 0); assert( lev_markup_number.match(rgx.levels_numbered), ("not a valid heading level: " ~ lev_markup_number ~ " at " ~ obj_cite_number_.to!string) ); if (lev_markup_number.match(rgx.levels_numbered)) { if (lev_markup_number.to!int == 0) { assert(obj_cite_number_.to!int == 1); } } } body { int obj_cite_number = obj_cite_number_.to!int; switch (lev_markup_number.to!int) { case 0: lv = DocStructMarkupHeading.h_sect_A; lv0 = obj_cite_number; lv1=0; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; p_["lev_markup_number"] = 0; p_["obj_cite_number"] = 0; break; case 1: lv = DocStructMarkupHeading.h_sect_B; lv1 = obj_cite_number; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_A; p_["obj_cite_number"] = lv0; break; case 2: lv = DocStructMarkupHeading.h_sect_C; lv2 = obj_cite_number; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_B; p_["obj_cite_number"] = lv1; break; case 3: lv = DocStructMarkupHeading.h_sect_D; lv3=obj_cite_number; lv4=0; lv5=0; lv6=0; lv7=0; p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_C; p_["obj_cite_number"] = lv2; break; case 4: lv = DocStructMarkupHeading.h_text_1; lv4 = obj_cite_number; lv5=0; lv6=0; lv7=0; if (lv3 > State.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_D; p_["obj_cite_number"] = lv3; } else if (lv2 > State.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_C; p_["obj_cite_number"] = lv2; } else if (lv1 > State.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_B; p_["obj_cite_number"] = lv1; } else { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_A; p_["obj_cite_number"] = lv0; } break; case 5: lv = DocStructMarkupHeading.h_text_2; lv5 = obj_cite_number; lv6=0; lv7=0; p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1; p_["obj_cite_number"] = lv4; break; case 6: lv = DocStructMarkupHeading.h_text_3; lv6 = obj_cite_number; lv7=0; p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2; p_["obj_cite_number"] = lv5; break; case 7: lv = DocStructMarkupHeading.h_text_4; lv7 = obj_cite_number; p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3; p_["obj_cite_number"] = lv6; break; default: break; } ObjGenericComposite _comp_obj_heading_; _comp_obj_heading_ = _comp_obj_heading_.init; _comp_obj_heading_.use = "body"; _comp_obj_heading_.is_of = "para"; _comp_obj_heading_.is_a = "heading"; _comp_obj_heading_.text = _text.to!string.strip; _comp_obj_heading_.ocn = obj_cite_number_; _comp_obj_heading_.obj_cite_number = (obj_cite_number==0) ? "" : obj_cite_number.to!string; _comp_obj_heading_.segment_anchor_tag = segment_anchor_tag.to!string; _comp_obj_heading_.marked_up_level = lev; _comp_obj_heading_.heading_lev_markup = (!(lev_markup_number.empty) ? lev_markup_number.to!int : 0); _comp_obj_heading_.heading_lev_collapsed = (!(lev_collapsed_number.empty) ? lev_collapsed_number.to!int : 0); _comp_obj_heading_.parent_ocn = p_["obj_cite_number"]; _comp_obj_heading_.parent_lev_markup = p_["lev_markup_number"]; _comp_obj_heading_.heading_ancestors_text = lv_ancestors; _comp_obj_heading_.ptr_doc_object = cntr_; _comp_obj_heading_.ptr_html_segnames = ((lev_markup_number == "4") ? html_segnames_ptr : 0); _comp_obj_heading_.ptr_heading = ptr_; _comp_obj_heading_.inline_notes_reg = flag_notes_reg; _comp_obj_heading_.inline_notes_star = flag_notes_star; _comp_obj_heading_.inline_links = flag_links; debug(node) { if (lev_markup_number.match(rgx.levels_numbered_headings)) { writeln("* ", _node.to!string); } } debug(nodeheading) { if (lev_markup_number.match(rgx.levels_numbered_headings)) { writeln("* ", _node.to!string); } } assert(_comp_obj_heading_.parent_lev_markup <= 7); assert(_comp_obj_heading_.parent_ocn >= 0); if (lev_markup_number.match(rgx.levels_numbered_headings)) { assert(_comp_obj_heading_.heading_lev_markup <= 7); assert(_comp_obj_heading_.ocn >= 0); if (_comp_obj_heading_.parent_lev_markup > 0) { assert(_comp_obj_heading_.parent_lev_markup < _comp_obj_heading_.heading_lev_markup); if (_comp_obj_heading_.ocn != 0) { assert(_comp_obj_heading_.parent_ocn < _comp_obj_heading_.ocn); } } if (_comp_obj_heading_.heading_lev_markup == 0) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_B) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_A); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_C) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_B); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_sect_D) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_sect_C); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_1) { assert(_comp_obj_heading_.parent_lev_markup <= DocStructMarkupHeading.h_sect_D); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_2) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_1); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_3) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_2); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_4) { assert(_comp_obj_heading_.parent_lev_markup == DocStructMarkupHeading.h_text_3); } else if (_comp_obj_heading_.heading_lev_markup == DocStructMarkupHeading.h_text_5) { } } return _comp_obj_heading_; } invariant() { } #+END_SRC ***** } #+name: ao_emitters_metadata #+BEGIN_SRC d } #+END_SRC *** function assertions :assertions: **** mixin template: assertions on markup document structure :doc_structure: #+name: abs_functions_assertions #+BEGIN_SRC d auto assertions_doc_structure(O,Lv)( O an_object, Lv lv ) { debug(asserts) { static assert(is(typeof(an_object) == string[string])); static assert(is(typeof(lv) == int[string])); } if (lv["h3"] > State.off) { assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); assert(lv["h2"] > State.off); } else if (lv["h2"] > State.off) { assert(lv["h0"] > State.off); assert(lv["h1"] > State.off); assert(lv["h3"] == State.off); } else if (lv["h1"] > State.off) { assert(lv["h0"] > State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } else if (lv["h0"] > State.off) { assert(lv["h1"] == State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } else { assert(lv["h0"] == State.off); assert(lv["h1"] == State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } if (lv["h7"] > State.off) { assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); assert(lv["h6"] > State.off); } else if (lv["h6"] > State.off) { assert(lv["h4"] > State.off); assert(lv["h5"] > State.off); assert(lv["h7"] == State.off); } else if (lv["h5"] > State.off) { assert(lv["h4"] > State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } else if (lv["h4"] > State.off) { assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } else { assert(lv["h4"] == State.off); assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h0"] == State.off) { assert(lv["h1"] == State.off); assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); assert(lv["h4"] == State.off); assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h1"] == State.off) { assert(lv["h2"] == State.off); assert(lv["h3"] == State.off); } if (lv["h2"] == State.off) { assert(lv["h3"] == State.off); } if (lv["h3"] == State.off) { } if (lv["h4"] == State.off) { assert(lv["h5"] == State.off); assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h5"] == State.off) { assert(lv["h6"] == State.off); assert(lv["h7"] == State.off); } if (lv["h6"] == State.off) { assert(lv["h7"] == State.off); } if (lv["h7"] == State.off) { } switch ((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 **** mixin template: assertions on blocks :blocks: #+name: abs_functions_assertions #+BEGIN_SRC d auto assertions_flag_types_block_status_none_or_closed(T)(T type) { debug(asserts) { static assert(is(typeof(type) == int[string])); } assert( (type["code"] == TriState.off) || (type["code"] == TriState.closing), "code block status: off or closing"); assert( (type["poem"] == TriState.off) || (type["poem"] == TriState.closing), "poem status: off or closing"); assert( (type["table"] == TriState.off) || (type["table"] == TriState.closing), "table status: off or closing"); assert( (type["group"] == TriState.off) || (type["group"] == TriState.closing), "group block status: off or closing"); assert( (type["block"] == TriState.off) || (type["block"] == TriState.closing), "block status: off or closing"); } #+END_SRC *** 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"]; } } return doc_sect_keys_seq(); } } #+END_SRC * 2. Object Setter (Set Abstract Object) :abstract:object: set abstracted objects for downstream processing ** 0. ao object setter: :ao_object_setter: #+BEGIN_SRC d :tangle ../src/sdp/ao_object_setter.d /++ object setter: setting of sisu objects for downstream processing ao_object_setter.d +/ template ObjectSetter() { /+ structs +/ <> } #+END_SRC ** 1. initialize structs :struct: *** heading attribute #+name: ao_structs_init #+BEGIN_SRC d struct HeadingAttrib { string lev = "9"; int heading_lev_markup = 9; int heading_lev_collapsed = 9; int[] closes_lev_collapsed = []; int[] closes_lev_markup = []; int array_ptr = 0; int heading_array_ptr_segments = 0; } #+END_SRC *** [#A] composite object #+name: ao_structs_init #+BEGIN_SRC d struct ObjGenericComposite { // size_t id; string use = ""; string is_of = ""; string is_a = ""; string text = ""; string obj_cite_number = ""; string[] anchor_tags = []; int indent_base = 0; int indent_hang = 0; bool bullet = false; bool inline_links = false; bool inline_notes_reg = false; bool inline_notes_star = false; string language = ""; // not implemented, consider string code_block_syntax = ""; int table_number_of_columns = 0; double[] table_column_widths = []; string[] table_column_aligns = []; bool table_heading = false; bool table_walls = false; // not implemented int ocn = 0; string segment_anchor_tag = ""; string segname_prev = ""; string segname_next = ""; int parent_lev_markup = 0; int parent_ocn = 0; int[] ancestors = []; string marked_up_level = "9"; int heading_lev_markup = 9; int heading_lev_collapsed = 9; int[] dom_markedup = [ 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_collapsed = [ 0, 0, 0, 0, 0, 0, 0, 0,]; string[] heading_ancestors_text = [ "", "", "", "", "", "", "", "", ]; string[] lev4_subtoc = []; int heading_array_ptr = 0; int ptr_doc_object = 0; int ptr_html_segnames = 0; int ptr_heading = 0; int array_ptr = 0; int heading_array_ptr_segments = 0; string[string][string] node; } #+END_SRC *** The Objects: generic composite object array #+name: ao_structs_init #+BEGIN_SRC d struct TheObjects { ObjGenericComposite[] oca; } #+END_SRC