-*- mode: org -*- #+TITLE: spine (doc_reform) object-centric document abstraction #+DESCRIPTION: documents - structuring, publishing in multiple formats & search #+FILETAGS: :spine:abstraction: #+AUTHOR: Ralph Amissah #+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]] #+COPYRIGHT: Copyright (C) 2015 - 2024 Ralph Amissah #+LANGUAGE: en #+STARTUP: content hideblocks hidestars noindent entitiespretty #+PROPERTY: header-args :noweb yes #+PROPERTY: header-args+ :exports code #+PROPERTY: header-args+ :results no #+PROPERTY: header-args+ :cache no #+PROPERTY: header-args+ :padline no #+PROPERTY: header-args+ :mkdirp yes #+OPTIONS: H:3 num:nil toc:t \n:t ::t |:t ^:nil -:t f:t *:t - [[./doc-reform.org][doc-reform.org]] [[./][org/]] * (Object-Centric) Document Abstraction Process markup document, create document abstraction. ** _module template_ :module:metadoc_from_src: #+HEADER: :tangle "../src/doc_reform/meta/metadoc_from_src.d" #+HEADER: :noweb yes #+BEGIN_SRC d <<doc_header_including_copyright_and_license>> // document abstraction: // abstraction of sisu markup for downstream processing // metadoc_from_src.d module doc_reform.meta.metadoc_from_src; template docAbstraction() { <<docInitialize>> @system auto docAbstraction(CMM,Opt,Mf) ( char[][] markup_sourcefile_content, CMM conf_make_meta, Opt opt_action, Mf manifested, bool _new_doc ) { <<docAbstraction>> } // ← closed: abstract doc source <<docAbstractionRelatedFunctions>> } template docSectKeysSeq() { <<docSectKeysSeq>> } #+END_SRC ** docInitialize #+NAME: docInitialize #+HEADER: :noweb yes #+BEGIN_SRC d // ↓ abstraction imports import std.algorithm, std.container, std.file, std.json, std.path; import doc_reform.meta, doc_reform.meta.defaults, doc_reform.meta.rgx, doc_reform.meta.metadoc_object_setter, doc_reform.meta.rgx; // ↓ abstraction mixins mixin ObjectSetter; mixin InternalMarkup; mixin spineRgxIn; // initialize ObjGenericComposite[] the_document_toc_section, the_document_head_section, the_document_body_section, the_document_endnotes_section, the_document_bibliography_section, the_document_bookindex_section, the_document_glossary_section, the_document_blurb_section, the_document_xml_dom_tail_section; struct _theDoc { ObjGenericComposite[] toc; ObjGenericComposite[] head; ObjGenericComposite[] body; ObjGenericComposite[] bibliography; ObjGenericComposite[] glossary; ObjGenericComposite[] bookindex; ObjGenericComposite[] blurb; ObjGenericComposite[] endnotes; } string[string] an_object, processing, object_notes; string an_object_key; string[] anchor_tags; string anchor_tag; string anchor_tag_; string[string] tag_in_seg; string lev_anchor_tag; string[string][string] tag_assoc; string[] lv0to3_tags; // enum enum DocStructMarkupHeading { h_sect_A, h_sect_B, h_sect_C, h_sect_D, h_text_1, h_text_2, h_text_3, h_text_4, h_text_5, // extra level, drop content_non_header } // header section A-D; header text 1-4 enum Status { off, on, } enum OCNtype { ocn, non, bkidx, } // biblio variables string biblio_tag_name, biblio_tag_entry, st; string[] biblio_arr_json; string biblio_entry_str_json; JSONValue[] bib_arr_json; int bib_entry; // counters int cntr, previous_count, previous_length; bool reset_note_numbers = true; int[string] line_occur; int html_segnames_ptr = 0; int html_segnames_ptr_cntr = 0; int verse_line, heading_ptr; // paragraph attributes int[string] indent; bool bullet = true; string content_non_header = "8"; static auto obj_im = ObjInlineMarkup(); static auto obj_att = ObjAttributes(); // ocn struct OCNset { int digit; int object_number; bool off; string identifier; int bkidx; int type; } OCNset obj_cite_digits; int obj_cite_digit_, obj_cite_digit_off, obj_cite_digit_bkidx, obj_cite_digit_type; auto object_citation_number = OCNemitter(); struct ST_endnotes { ObjGenericComposite[] endnotes; OCNset ocn; } struct ST_bookindex { ObjGenericComposite[] bookindex; OCNset ocn; } struct ST_biblio_section { ObjGenericComposite[] bibliography_section; string[string][string] tag_assoc; } int[] dom_structure_markedup_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_structure_markedup_tags_status_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_structure_collapsed_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; int[] dom_structure_collapsed_tags_status_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0, 0,]; struct ST_ancestors { ObjGenericComposite[] the_document_body_section; ObjGenericComposite[] the_document_endnotes_section; ObjGenericComposite[] the_document_glossary_section; ObjGenericComposite[] the_document_bibliography_section; ObjGenericComposite[] the_document_bookindex_section; ObjGenericComposite[] the_document_blurb_section; } struct ST_segnames { string[][string] segnames; int html_segnames_ptr_cntr; int html_segnames_ptr; } struct ST_txtPlusHasFootnotes { string obj_txt; bool has_notes_reg; bool has_notes_star; bool has_notes_plus; } struct ST_txtPlusHasFootnotesUrlsImages { string obj_txt; bool has_notes_reg; bool has_notes_star; bool has_notes_plus; bool has_urls; bool has_images_without_dimensions; } struct ST_txtAndAnchorTagPlusHasFootnotesUrlsImages { string obj_txt; string anchor_tag; bool has_notes_reg; bool has_notes_star; bool has_notes_plus; bool has_links; // use same name bool has_images_without_dimensions; } struct ST_the_section { ObjGenericComposite[] comp_section_obj; // array: the heading has 2 members inserted, paras just 1 uint[string] pith; string[string][string] tag_assoc; // only for headings: html & epub } enum DomTags { none, open, close, close_and_open, open_still, } // book index variables string book_idx_tmp; string[][string][string] bookindex_unordered_hashes; // node ObjGenericComposite comp_obj_, comp_obj_location, comp_obj_poem_ocn, comp_obj_comment; auto node_construct = NodeStructureMetadata(); struct ST_txt_by_line_common_reset { int[string] line_occur; string[string] this_object; uint[string] pith; } struct ST_txt_by_line_block_start { uint[string] pith; uint[string] dochas; string[string] object_number_poem; } struct ST_txt_by_line_block_generic { uint[string] pith; string[string] this_object; } struct ST_txt_by_line_block_poem { int cntr; uint[string] pith; string[string] this_object; } struct ST_txt_by_line_block_biblio { uint[string] pith; int bib_entry; string biblio_entry_str_json; string[] biblio_arr_json; } struct ST_flow_book_index { string[string] this_object; uint[string] pith; string book_idx_tmp; } struct ST_flow_heading_found { string[string] heading_match_str; Regex!(char)[string] heading_match_rgx; uint[string] pith; } struct ST_flow_heading_make_set { char[] line; uint[string] pith; string[string] this_object; } struct ST_flow_para_match { uint[string] pith; string[string] this_object; string this_object_key; int[string] indent; bool bullet; int[string] line_occur; } struct ST_flow_table_array_munge { ObjGenericComposite table_object; string[][] table_array; } struct ST_flow_table_of_contents_gather_headings { ObjGenericComposite[] the_document_toc_section; string[][string] lev4_subtoc; } struct ST_flow_bibliography { JSONValue[] biblio_sorted; JSONValue[] bib_arr_json; string[] biblio_unsorted_incomplete; } struct ST_flow_table_closed_make_special_notation_table { string[string] this_object; ObjGenericComposite[] the_document_body_section; OCNset obj_cite_digits; ObjGenericComposite comp_obj_; int cntr; uint[string] pith; } struct ST_flow_block_flag_line_empty { string[string] this_object; ObjGenericComposite[] the_document_body_section; string[][string][string] bookindex_unordered_hashes; OCNset obj_cite_digits; ObjGenericComposite comp_obj_; int cntr; uint[string] pith; } struct ST_flow_table_substantive_munge { ObjGenericComposite table_object; string table_substantive; } #+END_SRC ** docAbstraction *** toc #+NAME: docAbstraction #+HEADER: :noweb yes #+BEGIN_SRC d <<docAbstractionInit>> <<docAbstractionInitSubstitutions>> <<docAbstractionMainLoopSrcByLine>> <<docAbstractionPostMainLoop>> <<docAbstractionReturnsStruct>> #+END_SRC *** abstraction init #+NAME: docAbstractionInit #+HEADER: :noweb yes #+BEGIN_SRC d static auto rgx = RgxI(); // ↓ abstraction init scope(success) { } scope(failure) { } scope(exit) { destroy(the_document_toc_section); destroy(the_document_head_section); destroy(the_document_body_section); destroy(the_document_bibliography_section); destroy(the_document_glossary_section); destroy(the_document_blurb_section); destroy(the_document_xml_dom_tail_section); destroy(an_object); destroy(processing); destroy(biblio_arr_json); previous_length = 0; reset_note_numbers = true; lev_anchor_tag = ""; anchor_tag = ""; } mixin spineNode; auto node_para_int_ = node_metadata_para_int; auto node_para_str_ = node_metadata_para_str; ObjGenericComposite comp_obj_; line_occur = [ "heading" : 0, "para" : 0, "glossary" : 0, "blurb" : 0, ]; uint[string] dochas = [ "inline_links" : 0, "inline_notes" : 0, "inline_notes_star" : 0, "codeblock" : 0, "table" : 0, "block" : 0, "group" : 0, "poem" : 0, "quote" : 0, "images" : 0, ]; uint[string] pith = [ "ocn" : 1, "section" : 0, "txt_is" : 0, "block_is" : 0, "block_state" : 0, "block_delim" : 0, "make_headings" : 0, "dummy_heading_status" : 0, "dummy_heading_multiple_objects" : 0, "no_ocn_multiple_objects" : 0, "verse_new" : 0, ]; string[string] object_number_poem = [ "start" : "", "end" : "" ]; string[] lv_ancestors_txt = [ "", "", "", "", "", "", "", "", ]; int[string] lv = [ "lv" : eN.bi.off, "h0" : eN.bi.off, "h1" : eN.bi.off, "h2" : eN.bi.off, "h3" : eN.bi.off, "h4" : eN.bi.off, "h5" : eN.bi.off, "h6" : eN.bi.off, "h7" : eN.bi.off, "lev_int_collapsed" : 0, ]; int[string] collapsed_lev = [ "h0" : eN.bi.off, "h1" : eN.bi.off, "h2" : eN.bi.off, "h3" : eN.bi.off, "h4" : eN.bi.off, "h5" : eN.bi.off, "h6" : eN.bi.off, "h7" : eN.bi.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)" ]; Regex!char[string] 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_ = set_object_heading("lev4", "frontmatter", "toc", "Table of Contents"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = false; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "toc"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = comp_obj_.tags.anchor_tag_html; comp_obj_.ptr.html_segnames = html_segnames_ptr; comp_obj_.tags.anchor_tags = ["toc"]; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; auto toc_head = comp_obj_; html_segnames_ptr_cntr++; the_document_toc_section = [toc_head]; static auto mkup = InlineMarkup(); static auto munge = ObjInlineMarkupMunge(); auto note_section = NotesSection(); auto bookindex_extract_hash = BookIndexNuggetHash(); string[][string] lev4_subtoc; string[][string] segnames = ["html": ["toc"], "epub": ["toc"]]; int cnt1 = 1; int cnt2 = 1; int cnt3 = 1; // abstraction init ↑ #+END_SRC *** abstraction init substitutions #+NAME: docAbstractionInitSubstitutions #+HEADER: :noweb yes #+BEGIN_SRC d enum Substitute { match, markup, } debug (substitutions) { writeln(__LINE__, ":", __FILE__, ": DEBUG substitutions:"); if (!(conf_make_meta.make.headings.empty)) { writeln(conf_make_meta.make.headings); } if (conf_make_meta.make.substitute) { foreach(substitution_pair; conf_make_meta.make.substitute) { writeln("regex to match: ", substitution_pair[Substitute.match]); writeln("substitution to make: ", substitution_pair[Substitute.markup]); } } if (conf_make_meta.make.bold) { writeln("regex to match: ", conf_make_meta.make.bold[Substitute.match]); writeln("substitution to make: ", conf_make_meta.make.bold[Substitute.markup]); } if (conf_make_meta.make.emphasis) { writeln("regex to match: ", conf_make_meta.make.emphasis[Substitute.match]); writeln("substitution to make: ", conf_make_meta.make.emphasis[Substitute.markup]); } if (conf_make_meta.make.italics) { writeln("regex to match: ", conf_make_meta.make.italics[Substitute.match]); writeln("substitution to make: ", conf_make_meta.make.italics[Substitute.markup]); } } #+END_SRC *** loop source by line (large block) #+NAME: docAbstractionMainLoopSrcByLine #+HEADER: :noweb yes #+BEGIN_SRC d auto loopMarkupSrcByLine( char[][] markup_sourcefile_content, string[string] an_object, uint[string] pith, ) { struct _loopMarkupSrcByLineStruct { ObjGenericComposite[] toc; ObjGenericComposite[] body; ObjGenericComposite[] glossary; ObjGenericComposite[] blurb; string[string] object_notes; string[][string] segnames; } _loopMarkupSrcByLineStruct ret; srcDocLoopLineByLine_: foreach (line; markup_sourcefile_content) { // ↓ markup document/text line by line // "line" variable can be empty but should never be null // scope scope(exit) { } scope(failure) { stderr.writefln( "\n%s\n%s\n\n%s:%s\nFAILED while processing the file: ❮❮ %s ❯❯ on line with text:\n%s\n", __MODULE__, __FUNCTION__, __FILE__, __LINE__, manifested.src.filename, line, ); } debug(source) { writeln(line); } debug(srclines) { if (!line.empty) { writefln("* %s", line); } } if (!line.empty) { pith = line._check_ocn_status_(pith); } if ( pith["block_is"] == eN.blk_is.code && pith["block_state"] == eN.blk_state.on ) { // block object: code { ST_txt_by_line_block_generic _get = line.txt_by_line_block_code(an_object, pith); { an_object = _get.this_object; pith = _get.pith; } } continue; } 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 line = line.inline_markup_faces; // by text line (rather than by text object), linebreaks in para problematic if (line.matchFirst(rgx.heading_biblio) || (pith["section"] == eN.sect.bibliography && ((!(line.matchFirst(rgx.heading_glossary))) && (!(line.matchFirst(rgx.heading_blurb))) && (!(line.matchFirst(rgx.heading))) && (!(line.matchFirst(rgx.comment))))) ) { pith["section"] = eN.sect.bibliography; if (opt_action.backmatter && opt_action.section_biblio) { { ST_txt_by_line_block_biblio _get = line.txt_by_line_block_biblio(pith, bib_entry, biblio_entry_str_json, biblio_arr_json); { pith = _get.pith; bib_entry = _get.bib_entry; biblio_entry_str_json = _get.biblio_entry_str_json; biblio_arr_json = _get.biblio_arr_json; } } debug(bibliobuild) { writeln("- ", biblio_entry_str_json); writeln("-> ", biblio_arr_json.length); } } continue; } else if (line.matchFirst(rgx.heading_glossary) || (pith["section"] == eN.sect.glossary && ((!(line.matchFirst(rgx.heading_biblio))) && (!(line.matchFirst(rgx.heading_blurb))) && (!(line.matchFirst(rgx.heading))) && (!(line.matchFirst(rgx.comment))))) ) { // within section (block object): glossary debug(glossary) { writeln(__LINE__); writeln(line); } pith["section"] = eN.sect.glossary; if (opt_action.backmatter && opt_action.section_glossary) { ST_the_section add_to_glossary_sect = line.build_the_glossary_section(pith, tag_assoc); the_document_glossary_section ~= add_to_glossary_sect.comp_section_obj[0]; if (add_to_glossary_sect.comp_section_obj.length > 1) { // heading the_document_glossary_section ~= add_to_glossary_sect.comp_section_obj[1]; } pith = add_to_glossary_sect.pith; tag_assoc = add_to_glossary_sect.tag_assoc; } continue; } else if (line.matchFirst(rgx.heading_blurb) || (pith["section"] == eN.sect.blurb && ((!(line.matchFirst(rgx.heading_glossary))) && (!(line.matchFirst(rgx.heading_biblio))) && (!(line.matchFirst(rgx.heading))) && (!(line.matchFirst(rgx.comment))))) ) { pith["section"] = eN.sect.blurb; debug(blurb) { writeln(__LINE__); writeln(line); } if ((opt_action.backmatter && opt_action.section_blurb) && !(line.empty)) { ST_the_section add_to_blurb_sect = line.build_the_blurb_section(pith, tag_assoc, opt_action); the_document_blurb_section ~= add_to_blurb_sect.comp_section_obj[0]; if (add_to_blurb_sect.comp_section_obj.length > 1) { // heading the_document_blurb_section ~= add_to_blurb_sect.comp_section_obj[1]; } pith = add_to_blurb_sect.pith; tag_assoc = add_to_blurb_sect.tag_assoc; } continue; } else if (pith["block_state"] == eN.blk_state.on) { if (pith["block_is"] == eN.blk_is.quote) { line = line ._doc_header_and_make_substitutions_(conf_make_meta) ._doc_header_and_make_substitutions_fontface_(conf_make_meta); { auto _get = line.txt_by_line_block_quote(an_object, pith); { an_object = _get.this_object; pith = _get.pith; } } continue; } else if (pith["block_is"] == eN.blk_is.group) { line = line ._doc_header_and_make_substitutions_(conf_make_meta) ._doc_header_and_make_substitutions_fontface_(conf_make_meta) .replaceAll(rgx.para_delimiter, mkup.br_line_spaced ~ "$1"); { auto _get = line.txt_by_line_block_group(an_object, pith); { an_object = _get.this_object; pith = _get.pith; } } continue; } else if (pith["block_is"] == eN.blk_is.block) { line = line ._doc_header_and_make_substitutions_(conf_make_meta) ._doc_header_and_make_substitutions_fontface_(conf_make_meta); if (auto m = line.match(rgx.spaces_keep)) { line = line .replaceAll(rgx.spaces_keep, (m.captures[1]).translate([ ' ' : mkup.nbsp ])); } { auto _get = line.txt_by_line_block_block(an_object, pith); { an_object = _get.this_object; pith = _get.pith; } } continue; } else if (pith["block_is"] == eN.blk_is.poem) { { auto _get = line.txt_by_line_block_poem(an_object, pith, cntr, object_number_poem, conf_make_meta, tag_in_seg); { an_object = _get.this_object; pith = _get.pith; cntr = _get.cntr; } } continue; } else if (pith["block_is"] == eN.blk_is.table) { { auto _get = line.txt_by_line_block_table(an_object, pith, conf_make_meta); { an_object = _get.this_object; pith = _get.pith; conf_make_meta = _get.conf_make_meta; } } continue; } } else { // not within a block group assert( (pith["block_state"] == eN.blk_state.off) || (pith["block_state"] == eN.blk_state.closing), "block status: none or closed" ); if (line.matchFirst(rgx.block_open)) { if (line.matchFirst(rgx.block_poem_open)) { // poem to verse exceptions! object_reset(an_object); processing.remove("verse"); object_number_poem["start"] = obj_cite_digits.object_number.to!string; } { auto _get = line.txt_by_line_block_start(pith, dochas, object_number_poem); { pith = _get.pith; dochas = _get.dochas; object_number_poem = _get.object_number_poem; } } continue; } else if (!line.empty) { // line not empty - non blocks (headings, paragraphs) & closed blocks assert(!line.empty, "line tested, line not empty surely:\n \"" ~ line ~ "\""); assert( (pith["block_state"] == eN.blk_state.off) || (pith["block_state"] == eN.blk_state.closing), "code block status: none or closed" ); if (pith["block_state"] == eN.blk_state.closing) { debug(check) { writeln(__LINE__); writeln(line); } assert( line.matchFirst(rgx.book_index_item) || line.matchFirst(rgx.book_index_item_open) || pith["section"] == eN.sect.book_index, "\nblocks closed, unless followed by book index, non-matching line:\n \"" ~ line ~ "\"" ); } if (line.matchFirst(rgx.book_index_item) || line.matchFirst(rgx.book_index_item_open) || pith["section"] == eN.sect.book_index) { { // book_index auto _get = line.flow_book_index_(an_object, book_idx_tmp, pith, opt_action); { an_object = _get.this_object; pith = _get.pith; book_idx_tmp = _get.book_idx_tmp; } } } else { // not book_index an_object_key = "body_nugget"; if (auto m = line.matchFirst(rgx.comment)) { // matched comment debug(comment) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; comp_obj_comment = comp_obj_comment.init; comp_obj_comment.metainfo.is_of_part = "comment"; // breaks flow comp_obj_comment.metainfo.is_of_section = "comment"; // breaks flow comp_obj_comment.metainfo.is_of_type = "comment"; comp_obj_comment.metainfo.is_a = "comment"; comp_obj_comment.text = an_object[an_object_key].strip; the_document_body_section ~= comp_obj_comment; { auto _get = txt_by_line_common_reset_(line_occur, an_object, pith); { line_occur = _get.line_occur; an_object = _get.this_object; pith = _get.pith; } } processing.remove("verse"); ++cntr; } else if ((line_occur["para"] == eN.bi.off && line_occur["heading"] == eN.bi.off) && pith["txt_is"] == eN.txt_is.off ) { // heading or para but neither flag nor line exists if ((conf_make_meta.make.headings.length > 2) && (pith["make_headings"] == eN.bi.off)) { // heading found { auto _get = line.flow_heading_found_(heading_match_str, conf_make_meta.make.headings, heading_match_rgx, pith); { heading_match_str = _get.heading_match_str; heading_match_rgx = _get.heading_match_rgx; pith = _get.pith; } } } if (pith["make_headings"] == eN.bi.on && (line_occur["para"] == eN.bi.off && line_occur["heading"] == eN.bi.off) && pith["txt_is"] == eN.txt_is.off ) { // heading make set { auto _get = line.flow_heading_make_set_(line_occur, heading_match_rgx, pith); { line = _get.line; an_object = _get.this_object; pith = _get.pith; } } } // 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.headings)) { // heading match line = line._doc_header_and_make_substitutions_(conf_make_meta); { auto _get = line.flow_heading_matched_( an_object, line_occur, an_object_key, lv, collapsed_lev, pith, conf_make_meta, ); { an_object = _get.this_object; pith = _get.pith; } } } else if (line_occur["para"] == eN.bi.off) { // para match an_object_key = "body_nugget"; line = line ._doc_header_and_make_substitutions_(conf_make_meta) ._doc_header_and_make_substitutions_fontface_(conf_make_meta); { auto _get = line.flow_para_match_(an_object, an_object_key, indent, bullet, pith, line_occur); { an_object = _get.this_object; an_object_key = _get.this_object_key; pith = _get.pith; indent = _get.indent; bullet = _get.bullet; line_occur = _get.line_occur; } } } } else if (line_occur["heading"] > eN.bi.off) { // heading debug(heading) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; ++line_occur["heading"]; } else if (line_occur["para"] > eN.bi.off) { // paragraph debug(para) { writeln(an_object_key, "-> ", line); } line = line ._doc_header_and_make_substitutions_(conf_make_meta) ._doc_header_and_make_substitutions_fontface_(conf_make_meta); an_object[an_object_key] ~= " " ~ line; ++line_occur["para"]; } } } else if (pith["block_state"] == eN.blk_state.closing) { // line empty, with blocks flag { auto _get = line.flow_block_flag_line_empty_( an_object, bookindex_extract_hash, the_document_body_section, bookindex_unordered_hashes, obj_cite_digits, comp_obj_, cntr, pith, object_number_poem, conf_make_meta, tag_in_seg, ); { an_object = _get.this_object; the_document_body_section = _get.the_document_body_section; bookindex_unordered_hashes = _get.bookindex_unordered_hashes; obj_cite_digits = _get.obj_cite_digits; comp_obj_ = _get.comp_obj_; cntr = _get.cntr; pith = _get.pith; } } } else { // line.empty, post contents, empty variables: assert( line.empty, "\nline should be empty:\n \"" ~ line ~ "\"" ); assert( (pith["block_state"] == eN.blk_state.off), "code block status: none" ); if (_new_doc) { tag_assoc = tag_assoc.init; lv0to3_tags = lv0to3_tags.init; tag_in_seg = tag_in_seg.init; } if (pith["txt_is"] == eN.txt_is.heading && line_occur["heading"] > eN.bi.off ) { // heading object (current line empty) obj_cite_digits = (an_object["lev_markup_number"].to!int == 0) ? ocn_emit(eN.ocn.reset) : ocn_emit(pith["ocn"]); an_object["is"] = "heading"; an_object_key = "body_nugget"; ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_object_and_anchor_tags_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, ((_new_doc) ? Yes._new_doc : No._new_doc)); an_object["substantive"] = substantive_object_and_anchor_tags_struct.obj_txt; anchor_tag = substantive_object_and_anchor_tags_struct.anchor_tag; if (_new_doc) { cnt1 = 1; cnt2 = 1; cnt3 = 1; _new_doc = false; } if ( an_object["lev_markup_number"].to!int == 4 && (!(anchor_tag.empty) || (lv0to3_tags.length > 0)) ) { tag_in_seg["seg_lv4"] = anchor_tag; tag_in_seg["seg_lv1to4"] = anchor_tag; lev_anchor_tag = anchor_tag; tag_assoc[anchor_tag]["seg_lv4"] = tag_in_seg["seg_lv4"]; tag_assoc[anchor_tag]["seg_lv1to4"] = tag_in_seg["seg_lv1to4"]; if (lv0to3_tags.length > 0) { // names used for html markup segments 1 to 4 (rather than epub which has separate segments for A to D) foreach (lv0_to_lv3_html_tag; lv0to3_tags) { tag_assoc[lv0_to_lv3_html_tag]["seg_lv4"] = anchor_tag; } } anchor_tag_ = anchor_tag; lv0to3_tags = lv0to3_tags.init; } else if (an_object["lev_markup_number"].to!int > 4) { tag_in_seg["seg_lv4"] = anchor_tag_; tag_in_seg["seg_lv1to4"] = anchor_tag_; lev_anchor_tag = anchor_tag; tag_assoc[anchor_tag]["seg_lv4"] = tag_in_seg["seg_lv4"]; tag_assoc[anchor_tag]["seg_lv1to4"] = tag_in_seg["seg_lv1to4"]; } else if (an_object["lev_markup_number"].to!int < 4) { string segn; switch (an_object["lev_markup_number"].to!int) { // names used for epub markup segments A to D 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: lv0to3_tags ~= obj_cite_digits.object_number.to!string; lv0to3_tags ~= segn; tag_in_seg["seg_lv4"] = segn; // for html segname need following lv4 not yet known tag_in_seg["seg_lv1to4"] = segn; break; } } an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_digits, tag_in_seg); _anchor_tag = obj_cite_digits.identifier; // (incrementally build toc) table of contents here! { auto _get = obj_im.flow_table_of_contents_gather_headings( an_object, conf_make_meta, tag_in_seg, _anchor_tag, lev4_subtoc, the_document_toc_section, ); { the_document_toc_section = _get.the_document_toc_section; lev4_subtoc = _get.lev4_subtoc; } } if (an_object["lev_markup_number"] == "4") { segnames["html"] ~= tag_in_seg["seg_lv4"]; html_segnames_ptr = html_segnames_ptr_cntr; html_segnames_ptr_cntr++; } if (an_object["lev_markup_number"].to!int <= 4) { segnames["epub"] ~= tag_in_seg["seg_lv1to4"]; } auto comp_obj_ = node_construct.node_emitter_heading( an_object, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, // OCNset cntr, // int heading_ptr, // int lv_ancestors_txt, // string[] html_segnames_ptr, // int substantive_object_and_anchor_tags_struct, ); ++heading_ptr; debug(segments) { writeln(an_object["lev_markup_number"]); writeln(tag_in_seg["seg_lv4"]); writeln(tag_in_seg["seg_lv1to4"]); } the_document_body_section ~= comp_obj_; debug(objectrelated1) { writeln(line); } // check { auto _get = txt_by_line_common_reset_(line_occur, an_object, pith); { line_occur = _get.line_occur; an_object = _get.this_object; pith = _get.pith; } } an_object.remove("lev"); an_object.remove("lev_markup_number"); processing.remove("verse"); ++cntr; } else if (pith["txt_is"] == eN.txt_is.para && line_occur["para"] > eN.bi.off ) { // paragraph object (current line empty) - repeated character paragraph separator if ((an_object[an_object_key].to!string).matchFirst(rgx.repeated_character_line_separator)) { pith["ocn"] = eN.ocn.off; } obj_cite_digits = ocn_emit(pith["ocn"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash(an_object["bookindex_nugget"], obj_cite_digits, tag_in_seg); an_object["is"] = "para"; auto comp_obj_ = node_construct.node_location_emitter( content_non_header, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, cntr, heading_ptr-1, an_object["is"], ); ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; anchor_tag = substantive_obj_misc_struct.anchor_tag; comp_obj_ = set_object_generic("body", "body", "para", "para", an_object["substantive"].to!string.strip, obj_cite_digits.object_number); comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = (obj_cite_digits.off == 0) ? true : false; // TODO comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digits.type; comp_obj_.attrib.indent_hang = indent["hang_position"]; comp_obj_.attrib.indent_base = indent["base_position"]; comp_obj_.attrib.bullet = bullet; comp_obj_.tags.anchor_tags = [anchor_tag]; anchor_tag=""; comp_obj_.has.inline_notes_reg = substantive_obj_misc_struct.has_notes_reg; comp_obj_.has.inline_notes_star = substantive_obj_misc_struct.has_notes_star; comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links; comp_obj_.has.image_without_dimensions = substantive_obj_misc_struct.has_images_without_dimensions; the_document_body_section ~= comp_obj_; tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc); { auto _get = txt_by_line_common_reset_(line_occur, an_object, pith); { line_occur = _get.line_occur; an_object = _get.this_object; pith = _get.pith; } } indent = [ "hang_position" : 0, "base_position" : 0, ]; bullet = false; processing.remove("verse"); ++cntr; // } else { // could be useful to test line variable should be empty and never null } } // close else for line empty } // close else for not the above } // close after non code, other blocks or regular text // unless (the_document_body_section.length == 0) ? if (the_document_body_section.length > 0) { if (((the_document_body_section[$-1].metainfo.is_a == "para") || (the_document_body_section[$-1].metainfo.is_a == "heading") || (the_document_body_section[$-1].metainfo.is_a == "quote") || (the_document_body_section[$-1].metainfo.is_a == "group") || (the_document_body_section[$-1].metainfo.is_a == "block") || (the_document_body_section[$-1].metainfo.is_a == "verse")) && (the_document_body_section.length > previous_length)) { if ((the_document_body_section[$-1].metainfo.is_a == "heading") && (the_document_body_section[$-1].metainfo.heading_lev_markup < 5)) { pith["section"] = eN.sect.unset; } if (the_document_body_section[$-1].metainfo.is_a == "verse") { // scan for endnotes for whole poem (each verse in poem) foreach (i; previous_length .. the_document_body_section.length) { if (the_document_body_section[i].metainfo.is_a == "verse") { if ((the_document_body_section[i].text).match( rgx.inline_notes_al_all_note )) { object_notes = note_section.gather_notes_for_endnote_section( the_document_body_section, tag_in_seg, (i).to!int, ); } } } } else { // scan object for endnotes previous_length = the_document_body_section.length.to!int; if ((the_document_body_section[$-1].text).match( rgx.inline_notes_al_all_note )) { previous_count = (the_document_body_section.length -1).to!int; object_notes = note_section.gather_notes_for_endnote_section( the_document_body_section, tag_in_seg, (the_document_body_section.length-1).to!int, ); } } previous_length = the_document_body_section.length.to!int; } } } ret.toc = the_document_toc_section; ret.body = the_document_body_section; ret.glossary = the_document_glossary_section; ret.blurb = the_document_blurb_section; ret.object_notes = object_notes; ret.segnames = segnames; return ret; } { // loopMarkupSrcByLine auto _doc_by_line = loopMarkupSrcByLine(markup_sourcefile_content, an_object, pith); the_document_toc_section = _doc_by_line.toc; the_document_body_section = _doc_by_line.body; the_document_glossary_section = _doc_by_line.glossary; the_document_blurb_section = _doc_by_line.blurb; segnames = _doc_by_line.segnames; object_notes = _doc_by_line.object_notes; // endnotes, compare, not sure is used destroy(_doc_by_line); } #+END_SRC *** post loop (consider and segment/break up further in code & org) #+NAME: docAbstractionPostMainLoop #+HEADER: :noweb yes #+BEGIN_SRC d <<docAbstractionRelatedFunctionsBackMatter>> <<docAbstractionRelatedFunctionsEndnotes>> <<docAbstractionRelatedFunctionsGlossary>> <<docAbstractionRelatedFunctionsBibliography>> <<docAbstractionRelatedFunctionsBookIndex>> <<docAbstractionRelatedFunctionsBlurb>> <<docAbstractionRelatedFunctionsTOCgather>> <<docAbstractionDocHeadAndBody>> <<docAbstractionAncestors>> <<docAbstractionSegNames>> <<docAbstractionSegNamesLinkedAndImages>> <<docAbstractionEndnotes>> <<docAbstractionGlossary>> <<docAbstractionBibliography>> <<docAbstractionBookIndex>> <<docAbstractionBlurb>> <<docAbstractionGetDecendants>> <<docAbstractionHeadingCloseOpenTags>> // the_dom_tail_section ~= comp_obj_; // remove tail for now, decide on later <<docAbstractionTheDoc>> <<docAbstractionDocReInit>> <<docAbstractionDocHasParts>> #+END_SRC *** return structure #+NAME: docAbstractionReturnsStruct #+HEADER: :noweb yes #+BEGIN_SRC d // the doc to be returned struct ST_docAbstraction { ObjGenericComposite[][string] document_the; DocHas_ doc_has; } ST_docAbstraction ret; { ret.document_the = document_the; ret.doc_has = doc_has; } return ret; #+END_SRC ** docAbstraction Functions (post loop) *** Back Matter (added after end of document loop) **** Back Matter #+NAME: docAbstractionRelatedFunctionsBackMatter #+HEADER: :noweb yes #+BEGIN_SRC d { // EOF backMatter comp_obj_ = set_object_heading("lev1", "backmatter", "tail", ""); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = false; comp_obj_.metainfo.object_number_off = false; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "_part_eof"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = "tail"; comp_obj_.tags.anchor_tags = ["section_eof"]; comp_obj_.metainfo.dom_structure_markedup_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0]; comp_obj_.metainfo.dom_structure_collapsed_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0]; the_document_xml_dom_tail_section ~= comp_obj_; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; } #+END_SRC **** Endnotes function (add gathered endnotes) #+NAME: docAbstractionRelatedFunctionsEndnotes #+HEADER: :noweb yes #+BEGIN_SRC d // endNotes ST_endnotes en_st = note_section.backmatter_endnote_objects(obj_cite_digits, opt_action); { // endnotes the_document_endnotes_section = en_st.endnotes; obj_cite_digits = en_st.ocn; debug(endnotes) { writefln("%s %s", __LINE__, the_document_endnotes_section.length); foreach (o; the_document_endnotes_section) { writeln(o); } } } #+END_SRC **** Glossary function #+NAME: docAbstractionRelatedFunctionsGlossary #+HEADER: :noweb yes #+BEGIN_SRC d { // glossary if (an_object["glossary_nugget"].length == 0) { comp_obj_ = set_object_heading("lev1", "empty", "empty", "(skip) there is no Glossary section"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = true; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; the_document_glossary_section ~= comp_obj_; } debug(glossary) { foreach (gloss; the_document_glossary_section) { writeln(gloss.text); } } } #+END_SRC **** Bibliography function #+NAME: docAbstractionRelatedFunctionsBibliography #+HEADER: :noweb yes #+BEGIN_SRC d { // bibliography string[] biblio_unsorted_incomplete = biblio_arr_json.dup; ST_biblio_section biblio_section = backmatter_make_the_bibliography_section(biblio_unsorted_incomplete, bib_arr_json); the_document_bibliography_section = biblio_section.bibliography_section; tag_assoc = biblio_section.tag_assoc; } #+END_SRC **** Book Index function #+NAME: docAbstractionRelatedFunctionsBookIndex #+HEADER: :noweb yes #+BEGIN_SRC d { // bookindex BookIndexReportSection bi = BookIndexReportSection(); ST_bookindex bi_st = bi.backmatter_bookindex_build_abstraction_section(bookindex_unordered_hashes, obj_cite_digits, opt_action); destroy(bookindex_unordered_hashes); the_document_bookindex_section = bi_st.bookindex; obj_cite_digits = bi_st.ocn; debug(bookindex) { foreach (bi_entry; the_document_bookindex_section) { writeln(bi_entry); } } } #+END_SRC **** Blurb function #+NAME: docAbstractionRelatedFunctionsBlurb #+HEADER: :noweb yes #+BEGIN_SRC d { // blurb if (an_object["blurb_nugget"].length == 0) { comp_obj_ = set_object_heading("lev1", "empty", "empty", "(skip) there is no Blurb section"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = ""; comp_obj_.tags.anchor_tag_html = ""; comp_obj_.tags.in_segment_html = ""; the_document_blurb_section ~= comp_obj_; } debug(blurb) { foreach (blurb; the_document_blurb_section) { writeln(blurb.text); } } } #+END_SRC **** TOC gather function #+NAME: docAbstractionRelatedFunctionsTOCgather #+HEADER: :noweb yes #+BEGIN_SRC d { // toc gather backmatter the_document_toc_section ~= backmatter_gather_table_of_contents(the_document_endnotes_section, the_document_glossary_section, the_document_bibliography_section, the_document_bookindex_section, the_document_blurb_section); // } #+END_SRC *** Doc Head and Body #+NAME: docAbstractionDocHeadAndBody #+HEADER: :noweb yes #+BEGIN_SRC d { // document head and body the_document_head_section ~= the_document_body_section[0]; the_document_body_section = the_document_body_section[1..$]; } #+END_SRC *** Extract **** Ancestors #+NAME: docAbstractionAncestors #+HEADER: :noweb yes #+BEGIN_SRC d { // document ancestors ST_ancestors get_ancestors; get_ancestors = the_document_body_section.after_doc_determine_ancestors(the_document_endnotes_section, the_document_glossary_section, the_document_bibliography_section, the_document_bookindex_section, the_document_blurb_section); the_document_body_section = get_ancestors.the_document_body_section; the_document_endnotes_section = get_ancestors.the_document_endnotes_section; the_document_glossary_section = get_ancestors.the_document_glossary_section; the_document_bibliography_section = get_ancestors.the_document_bibliography_section; the_document_bookindex_section = get_ancestors.the_document_bookindex_section; the_document_blurb_section = get_ancestors.the_document_blurb_section; } #+END_SRC **** SegNames #+NAME: docAbstractionSegNames #+HEADER: :noweb yes #+BEGIN_SRC d { // document segnames ST_segnames get_segnames; get_segnames = the_document_body_section.after_doc_determine_segnames(the_document_endnotes_section, the_document_glossary_section, the_document_bibliography_section, the_document_bookindex_section, the_document_blurb_section, segnames, html_segnames_ptr_cntr, html_segnames_ptr); // segnames = get_segnames.segnames; html_segnames_ptr_cntr = get_segnames.html_segnames_ptr_cntr; html_segnames_ptr = get_segnames.html_segnames_ptr; } #+END_SRC **** SegNames with links & images #+NAME: docAbstractionSegNamesLinkedAndImages #+HEADER: :noweb yes #+BEGIN_SRC d // document head string[] segnames_0_to_4; foreach (ref obj; the_document_head_section) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup <= 4) { segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub; } if (obj.metainfo.heading_lev_markup == 0) { // TODO second hit (of two) with same assertion failure, check, fix and reinstate // assert( obj.metainfo.ocn == 1, // "Title OCN should be 1 not: " ~ obj.metainfo.ocn.to!string); // bug introduced 0.18.1 obj.metainfo.ocn = 1; obj.metainfo.identifier = "1"; obj.metainfo.object_number_type = OCNtype.ocn; } // dom structure (marked up & collapsed) if (opt_action.meta_processing_xml_dom) { obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj.obj_heading_ancestors(lv_ancestors_txt); } obj = _links(obj); } if (the_document_toc_section.length > 1) { // scroll dom_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup; dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup; foreach (ref obj; the_document_toc_section) { if (obj.metainfo.is_a == "heading") { if (obj.metainfo.heading_lev_markup <= 4) { segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1]; assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames], obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]); } } // dom structure (marked up & collapsed) if (opt_action.meta_processing_xml_dom) { obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj.obj_heading_ancestors(lv_ancestors_txt); } obj = _links(obj); } } // images string[] _images; // multiple 1~ levels, loop through document body if (the_document_body_section.length > 1) { foreach (ref obj; the_document_body_section) { if (!(obj.metainfo.identifier.empty)) { if (!(((obj.metainfo.identifier) in tag_assoc) && ("seg_lv4" in tag_assoc[(obj.metainfo.identifier)])) ) { tag_assoc[(obj.metainfo.identifier)]["seg_lv4"] = obj.tags.html_segment_anchor_tag_is; } tag_assoc[(obj.metainfo.identifier)]["seg_lv1to4"] = obj.tags.epub_segment_anchor_tag_is; } if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup <= 4) { segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.lev4_subtoc = lev4_subtoc[obj.tags.anchor_tag_html]; obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1]; if (segnames["html"].length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1]; } assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames], obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]); } } // dom structure (marked up & collapsed) if (opt_action.meta_processing_xml_dom) { obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj.obj_heading_ancestors(lv_ancestors_txt); } else if (obj.metainfo.is_a == "para") { _images ~= extract_images(obj.text); obj = _image_dimensions(obj, manifested); } obj = _links(obj); } } auto image_list = (_images.sort()).uniq; #+END_SRC *** Level 1~ **** Endnotes #+NAME: docAbstractionEndnotes #+HEADER: :noweb yes #+BEGIN_SRC d // endnotes optional only one 1~ level if (the_document_endnotes_section.length > 1) { dom_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup; dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup; dom_structure_markedup_tags_status = dom_structure_markedup_tags_status_buffer.dup; dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status_buffer.dup; foreach (ref obj; the_document_endnotes_section) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup == 1) { obj_cite_digits = ocn_emit(eN.ocn.on); obj.metainfo.ocn = obj_cite_digits.object_number; obj.metainfo.identifier = obj_cite_digits.identifier; } if (obj.metainfo.heading_lev_markup <= 4) { segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1]; if (segnames["html"].length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1]; } assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames], obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]); } } // dom structure (marked up & collapsed) if (opt_action.meta_processing_xml_dom) { obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj.obj_heading_ancestors(lv_ancestors_txt); } obj = _links(obj); } } #+END_SRC **** Glossary #+NAME: docAbstractionGlossary #+HEADER: :noweb yes #+BEGIN_SRC d // glossary optional only one 1~ level if (the_document_glossary_section.length > 1) { foreach (ref obj; the_document_glossary_section) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup == 1) { obj_cite_digits = ocn_emit(eN.ocn.on); obj.metainfo.ocn = obj_cite_digits.object_number; obj.metainfo.identifier = obj_cite_digits.identifier; } if (obj.metainfo.heading_lev_markup <= 4) { segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1]; if (segnames["html"].length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1]; } assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames], obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]); } } // dom structure (marked up & collapsed) if (opt_action.meta_processing_xml_dom) { obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj.obj_heading_ancestors(lv_ancestors_txt); } else if (obj.metainfo.is_a == "glossary" && !(obj.text.empty)) { obj_cite_digits = ocn_emit(eN.ocn.on); obj.metainfo.ocn = obj_cite_digits.object_number; obj.metainfo.identifier = obj_cite_digits.identifier; } obj = _links(obj); } } #+END_SRC **** Bibliography #+NAME: docAbstractionBibliography #+HEADER: :noweb yes #+BEGIN_SRC d // bibliography optional only one 1~ level if (the_document_bibliography_section.length > 1) { foreach (ref obj; the_document_bibliography_section) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup == 1) { obj_cite_digits = ocn_emit(eN.ocn.on); obj.metainfo.ocn = obj_cite_digits.object_number; obj.metainfo.identifier = obj_cite_digits.identifier; } if (obj.metainfo.heading_lev_markup <= 4) { segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1]; if (segnames["html"].length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1]; } assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames], obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]); } } // dom structure (marked up & collapsed) if (opt_action.meta_processing_xml_dom) { obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj.obj_heading_ancestors(lv_ancestors_txt); } else if (obj.metainfo.is_a == "bibliography") { obj_cite_digits = ocn_emit(eN.ocn.on); obj.metainfo.ocn = obj_cite_digits.object_number; obj.metainfo.identifier = obj_cite_digits.identifier; } obj = _links(obj); } } #+END_SRC **** Book Index #+NAME: docAbstractionBookIndex #+HEADER: :noweb yes #+BEGIN_SRC d // book index, optional only one 1~ level int ocn_ = obj_cite_digits.object_number; int ocn_bkidx_ = 0; int ocn_bidx_; if (the_document_bookindex_section.length > 1) { // scroll dom_structure_markedup_tags_status_buffer = dom_structure_markedup_tags_status.dup; dom_structure_collapsed_tags_status_buffer = dom_structure_collapsed_tags_status.dup; foreach (ref obj; the_document_bookindex_section) { if (obj.metainfo.is_a == "heading") { // debug(dom) { } if (obj.metainfo.heading_lev_markup <= 4) { segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub; } if (obj.metainfo.heading_lev_markup == 1) { obj_cite_digits = ocn_emit(eN.ocn.on); obj.metainfo.ocn = obj_cite_digits.object_number; obj.metainfo.identifier = obj_cite_digits.identifier; } if (obj.metainfo.heading_lev_markup <= 4) { if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1]; if (segnames["html"].length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1]; } assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames], obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]); } } // dom structure (marked up & collapsed) if (opt_action.meta_processing_xml_dom) { obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj.obj_heading_ancestors(lv_ancestors_txt); } else if (obj.metainfo.is_a == "bookindex") { obj_cite_digits = ocn_emit(eN.ocn.bkidx); obj.metainfo.ocn = obj_cite_digits.object_number; obj.metainfo.identifier = obj_cite_digits.identifier; obj.metainfo.o_n_book_index = obj_cite_digits.bkidx; obj.metainfo.object_number_type = OCNtype.bkidx; } obj = _links(obj); } // TODO assert failure, reinstate // assert(obj_cite_digit_bkidx == ocn_bidx_ obj_cite_digit_bkidx ~ " == ocn_" ~ ocn_ ~ "?"); } #+END_SRC **** Blurb #+NAME: docAbstractionBlurb #+HEADER: :noweb yes #+BEGIN_SRC d // blurb optional only one 1~ level if (the_document_blurb_section.length > 1) { foreach (ref obj; the_document_blurb_section) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup == 1) { obj_cite_digits = ocn_emit(eN.ocn.on); obj.metainfo.ocn = obj_cite_digits.object_number; obj.metainfo.identifier = obj_cite_digits.identifier; } if (obj.metainfo.heading_lev_markup <= 4) { segnames_0_to_4 ~= obj.tags.segment_anchor_tag_epub; if (obj.metainfo.heading_lev_markup == 4) { obj.tags.segname_prev = segnames["html"][obj.ptr.html_segnames - 1]; if (segnames["html"].length > obj.ptr.html_segnames + 1) { obj.tags.segname_next = segnames["html"][obj.ptr.html_segnames + 1]; } assert(obj.tags.anchor_tag_html == segnames["html"][obj.ptr.html_segnames], obj.tags.anchor_tag_html ~ "!=" ~ segnames["html"][obj.ptr.html_segnames]); } } // dom structure (marked up & collapsed) if (opt_action.meta_processing_xml_dom) { obj = obj.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, obj.metainfo.heading_lev_markup); obj = obj.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, obj.metainfo.heading_lev_collapsed); } obj = obj.obj_heading_ancestors(lv_ancestors_txt); } else if (obj.metainfo.is_a == "blurb") { obj_cite_digits = ocn_emit(eN.ocn.off); obj.metainfo.object_number_off = obj_cite_digits.off; obj.metainfo.object_number_type = OCNtype.non; } obj = _links(obj); } } #+END_SRC *** Get Decendants #+NAME: docAbstractionGetDecendants #+HEADER: :noweb yes #+BEGIN_SRC d // get decendants if (the_document_body_section.length > 1) { auto pairs = after_doc_get_decendants( the_document_head_section ~ the_document_body_section ~ the_document_endnotes_section ~ the_document_glossary_section ~ the_document_bibliography_section ~ the_document_bookindex_section ~ the_document_blurb_section ~ the_document_xml_dom_tail_section ); debug(decendants_tuple) { pairs = pairs.sort(); foreach (pair; pairs) { // (pair; pairs.sort()) writeln(pair[0], "..", pair[1]); } } foreach (ref obj; the_document_head_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } if (the_document_body_section.length > 1) { foreach (ref obj; the_document_body_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_document_endnotes_section.length > 1) { foreach (ref obj; the_document_endnotes_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_document_glossary_section.length > 1) { foreach (ref obj; the_document_glossary_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_document_bibliography_section.length > 1) { foreach (ref obj; the_document_bibliography_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_document_bookindex_section.length > 1) { foreach (ref obj; the_document_bookindex_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_document_blurb_section.length > 1) { foreach (ref obj; the_document_blurb_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } if (the_document_xml_dom_tail_section.length > 1) { foreach (ref obj; the_document_xml_dom_tail_section) { if (obj.metainfo.is_a == "heading") { foreach (pair; pairs) { if (obj.metainfo.ocn == pair[0]) { obj.metainfo.last_decendant_ocn = pair[1]; } } } } } } #+END_SRC *** Heading Closes All Open Tags #+NAME: docAbstractionHeadingCloseOpenTags #+HEADER: :noweb yes #+BEGIN_SRC d // TODO // - note create/insert heading object sole purpose eof close all open tags // sort out: // - obj.metainfo.dom_structure_markedup_tags_status = dom_structure_markedup_tags_status; // - obj.metainfo.dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status; comp_obj_ = set_object_heading("lev1", "empty", "empty", ""); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = true; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = ""; comp_obj_.tags.anchor_tag_html = ""; comp_obj_.tags.in_segment_html = ""; comp_obj_.tags.html_segment_anchor_tag_is = ""; comp_obj_.tags.epub_segment_anchor_tag_is = ""; comp_obj_.metainfo.heading_lev_markup = 9; comp_obj_.metainfo.heading_lev_collapsed = 9; comp_obj_.metainfo.parent_ocn = 0; comp_obj_.metainfo.parent_lev_markup = 0; comp_obj_.metainfo.dom_structure_markedup_tags_status = dom_structure_markedup_tags_status.dup; comp_obj_.metainfo.dom_structure_collapsed_tags_status = dom_structure_collapsed_tags_status.dup; comp_obj_ = comp_obj_.obj_dom_structure_set_markup_tags(dom_structure_markedup_tags_status, 0); comp_obj_ = comp_obj_.obj_dom_set_collapsed_tags(dom_structure_collapsed_tags_status, 0); comp_obj_ = comp_obj_.obj_heading_ancestors(lv_ancestors_txt); #+END_SRC *** The Doc #+NAME: docAbstractionTheDoc #+HEADER: :noweb yes #+BEGIN_SRC d // the doc ObjGenericComposite[][string] document_the = [ "head": the_document_head_section, "toc": the_document_toc_section, // substantive/body: "body": the_document_body_section, // backmatter: "endnotes": the_document_endnotes_section, "glossary": the_document_glossary_section, "bibliography": the_document_bibliography_section, "bookindex": the_document_bookindex_section, "blurb": the_document_blurb_section, // dom tail only "tail": the_document_xml_dom_tail_section, ]; // document parts keys as needed string[][string] document_section_keys_sequenced = [ "scroll": ["head", "toc", "body",], "seg": ["head", "toc", "body",], "sql": ["head", "body",], "latex": ["head", "toc", "body",] ]; if (document_the["endnotes"].length > 1) { document_section_keys_sequenced["scroll"] ~= "endnotes"; document_section_keys_sequenced["seg"] ~= "endnotes"; document_section_keys_sequenced["latex"] ~= "endnotes"; } if (document_the["glossary"].length > 1) { document_section_keys_sequenced["scroll"] ~= "glossary"; document_section_keys_sequenced["seg"] ~= "glossary"; document_section_keys_sequenced["sql"] ~= "glossary"; document_section_keys_sequenced["latex"] ~= "glossary"; } if (document_the["bibliography"].length > 1) { document_section_keys_sequenced["scroll"] ~= "bibliography"; document_section_keys_sequenced["seg"] ~= "bibliography"; document_section_keys_sequenced["sql"] ~= "bibliography"; document_section_keys_sequenced["latex"] ~= "bibliography"; } if (document_the["bookindex"].length > 1) { document_section_keys_sequenced["scroll"] ~= "bookindex"; document_section_keys_sequenced["seg"] ~= "bookindex"; document_section_keys_sequenced["sql"] ~= "bookindex"; document_section_keys_sequenced["latex"] ~= "bookindex"; } if (document_the["blurb"].length > 1) { document_section_keys_sequenced["scroll"] ~= "blurb"; document_section_keys_sequenced["seg"] ~= "blurb"; document_section_keys_sequenced["sql"] ~= "blurb"; document_section_keys_sequenced["latex"] ~= "blurb"; } if ((opt_action.html) || (opt_action.html_scroll) || (opt_action.html_seg) || (opt_action.epub)) { document_section_keys_sequenced["scroll"] ~= "tail"; document_section_keys_sequenced["seg"] ~= "tail"; } // segnames string[] segnames_4 = segnames["html"].dup; string[] segnames_lv1to4 = segnames["epub"].dup; debug(segnames) { writeln("segnames_lv4: ", segnames_4); writeln("segnames_lv1to4: ", segnames_lv1to4); } #+END_SRC *** Doc Re Init #+NAME: docAbstractionDocReInit #+HEADER: :noweb yes #+BEGIN_SRC d // restart destroy(the_document_head_section); destroy(the_document_toc_section); destroy(the_document_body_section); destroy(the_document_endnotes_section); destroy(the_document_glossary_section); destroy(the_document_bibliography_section); destroy(the_document_bookindex_section); destroy(the_document_blurb_section); destroy(the_document_xml_dom_tail_section); destroy(segnames); destroy(bookindex_unordered_hashes); destroy(an_object); obj_cite_digits = ocn_emit(eN.ocn.reset); biblio_arr_json = []; obj_cite_digit_ = 0; html_segnames_ptr = 0; html_segnames_ptr_cntr = 0; content_non_header = "8"; dom_structure_markedup_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0,]; dom_structure_markedup_tags_status_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0,]; dom_structure_collapsed_tags_status = [ 0, 0, 0, 0, 0, 0, 0, 0,]; dom_structure_collapsed_tags_status_buffer = [ 0, 0, 0, 0, 0, 0, 0, 0,]; lev_anchor_tag = ""; anchor_tag = ""; #+END_SRC *** Doc Has (identify parts) #+NAME: docAbstractionDocHasParts #+HEADER: :noweb yes #+BEGIN_SRC d // identify parts struct DocHas_ { uint inline_links() { return dochas["inline_links"]; } uint inline_notes_reg() { return dochas["inline_notes"]; } uint inline_notes_star() { return dochas["inline_notes_star"]; } uint codeblocks() { return dochas["codeblock"]; } uint tables() { return dochas["table"]; } uint blocks() { return dochas["block"]; } uint groups() { return dochas["group"]; } uint poems() { return dochas["poem"]; } uint quotes() { return dochas["quote"]; } ulong images() { // TODO not ideal rethink return (image_list.to!string.strip("[","]").split(",").length); } auto imagelist() { return image_list; } auto keys_seq() { return docSectKeysSeq!()(document_section_keys_sequenced); } string[] segnames_lv4() { return segnames_4; } string[] segnames_lv_0_to_4() { return segnames_0_to_4; } string[string][string] tag_associations() { return tag_assoc; } } @safe auto doc_has() { return DocHas_(); } #+END_SRC ** docAbstraction related Functions *** docAbstraction related Functions #+NAME: docAbstractionRelatedFunctions #+HEADER: :noweb yes #+BEGIN_SRC d @safe pure ObjGenericComposite obj_heading_ancestors()( ObjGenericComposite obj, string[] lv_ancestors_txt, ) { switch (obj.metainfo.heading_lev_markup) { case 0: lv_ancestors_txt[0] = obj.text.to!string; foreach(k; 1..8) { lv_ancestors_txt[k] = ""; } goto default; case 1: lv_ancestors_txt[1] = obj.text.to!string; foreach(k; 2..8) { lv_ancestors_txt[k] = ""; } goto default; case 2: lv_ancestors_txt[2] = obj.text.to!string; foreach(k; 3..8) { lv_ancestors_txt[k] = ""; } goto default; case 3: lv_ancestors_txt[3] = obj.text.to!string; foreach(k; 4..8) { lv_ancestors_txt[k] = ""; } goto default; case 4: lv_ancestors_txt[4] = obj.text.to!string; foreach(k; 5..8) { lv_ancestors_txt[k] = ""; } goto default; case 5: lv_ancestors_txt[5] = obj.text.to!string; foreach(k; 6..8) { lv_ancestors_txt[k] = ""; } goto default; case 6: lv_ancestors_txt[6] = obj.text.to!string; lv_ancestors_txt[7] = ""; goto default; case 7: lv_ancestors_txt[7] = obj.text.to!string; goto default; default: obj.tags.heading_ancestors_text = lv_ancestors_txt.dup; } return obj; } @safe pure ObjGenericComposite obj_dom_structure_set_markup_tags()( ObjGenericComposite obj, int[] dom, int lev ) { foreach (i; 0 .. 8) { if (i < lev) { if (dom[i] == DomTags.open || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.open_still; } else if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } } else if (i == lev) { if (lev == 0 && dom[i] == DomTags.open_still ) { dom[i] = DomTags.close; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close_and_open; } else { dom[i] = DomTags.open; } } else if (i > lev) { if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close; } } } debug(dom_magic_numbers) { writeln("marked up: ", lev, ": ", dom); } obj.metainfo.dom_structure_markedup_tags_status = dom.dup; return obj; } @safe pure ObjGenericComposite obj_dom_set_collapsed_tags()( ObjGenericComposite obj, int[] dom, int lev ) { foreach (i; 0 .. 8) { if (i < lev) { if (dom[i] == DomTags.open || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.open_still; } else if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } } else if (i == lev) { if (lev == 0 && dom[i] == DomTags.open_still ) { dom[i] = DomTags.close; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close_and_open; } else { dom[i] = DomTags.open; } } else if (i > lev) { if (dom[i] == DomTags.close) { dom[i] = DomTags.none; } else if (dom[i] == DomTags.open || dom[i] == DomTags.open_still || dom[i] == DomTags.close_and_open ) { dom[i] = DomTags.close; } } } debug(dom_magic_numbers) { writeln("collapsed: ", lev, ": ", dom); } obj.metainfo.dom_structure_collapsed_tags_status = dom.dup; return obj; } @safe static OCNset ocn_emit(int ocn_status_flag) { return object_citation_number.ocn_emitter(ocn_status_flag); } @safe auto inline_markup_faces(L)(L line) { static auto rgx = RgxI(); static auto mkup = InlineMarkup(); line = replaceAll!(m => mkup.quote_o ~ m[1] ~ mkup.quote_c)(line, rgx.within_quotes); line = replaceAll!(m => mkup.ff_i ~ mkup.mono ~ mkup.ff_o ~ m["text"] ~ mkup.ff_c ~ mkup.mono)(line, rgx.inline_mark_mono); line = replaceAll!(m => mkup.ff_i ~ mkup.cite ~ mkup.ff_o ~ m["text"] ~ mkup.ff_c ~ mkup.cite)(line, rgx.inline_mark_cite); foreach (regx; [rgx.inline_mark_emphasis, rgx.inline_mark_bold, rgx.inline_mark_underscore, rgx.inline_mark_italics, rgx.inline_mark_superscript, rgx.inline_mark_subscript, rgx.inline_mark_strike, rgx.inline_mark_insert]) { line = replaceAll!(m => mkup.ff_i ~ m["mark"] ~ mkup.ff_o ~ m["text"] ~ mkup.ff_c ~ m["mark"])(line, regx); } return line; } @safe static string links_and_images()(string obj_txt) { static auto rgx = RgxI(); static auto mkup = InlineMarkup(); if (obj_txt.match(rgx.smid_inline_url_generic)) { if ( obj_txt.match(rgx.smid_inline_link_endnote_url_helper) || obj_txt.match(rgx.smid_inline_link_endnote_url_helper_punctuated) ) { obj_txt = replaceAll!(m => format("%s%s%s%s%s%s%s %s%s%s%s%s%s %s%s", mkup.lnk_o, m["content"].strip, mkup.lnk_c, mkup.url_o, m["link"], mkup.url_c, mkup.en_a_o, mkup.lnk_o, m["link"].strip, mkup.lnk_c, mkup.url_o, m["link"], mkup.url_c, mkup.en_a_c, m[3] ))(obj_txt, rgx.smid_inline_link_endnote_url_helper_punctuated); obj_txt = replaceAll!(m => format("%s%s%s%s%s%s%s %s%s%s%s%s%s %s", mkup.lnk_o, m["content"].strip, mkup.lnk_c, mkup.url_o, m["link"], mkup.url_c, mkup.en_a_o, mkup.lnk_o, m["link"].strip, mkup.lnk_c, mkup.url_o, m["link"], mkup.url_c, mkup.en_a_c ))(obj_txt, rgx.smid_inline_link_endnote_url_helper); } else { obj_txt = replaceAll!(m => format("%s%s%s%s%s%s%s", m["pre"], mkup.lnk_o, m["content"].strip, mkup.lnk_c, mkup.url_o, m["link"], mkup.url_c ))(obj_txt, rgx.smid_inline_link_markup_regular); } obj_txt = replaceAll!(m => format("%s%s%s%s%s%s%s", m["pre"], mkup.lnk_o, m["link"].strip, mkup.lnk_c, mkup.url_o, m["link"], mkup.url_c ))(obj_txt, rgx.smid_inline_link_naked_url); // } return obj_txt; } // ↓ abstraction struct init @safe static auto eN() { struct _e { enum bi { off, on, } enum ocn { off, on, closing, bkidx, reset, } enum sect { unset, head, toc, substantive, bibliography, glossary, book_index, blurb, } enum txt_is { off, para, heading, } enum blk_is { off, code, poem, block, group, table, quote, } enum blk_state { off, on, closing, } enum blk_delim { off, curly, tic, curly_special, tic_special, } } return _e(); } @safe string[string][string] inline_para_link_anchor()( string[string] an_object, string[string] tag_in_seg, string[string][string] tag_assoc ) { static auto rgx = RgxI(); if (auto m = an_object["substantive"].match(rgx.inline_link_anchor)) { if (m.captures[1] !in tag_assoc) { tag_assoc[(m.captures[1])]["seg_lv4"] = tag_in_seg["seg_lv4"]; tag_assoc[(m.captures[1])]["seg_lv1to4"] = tag_in_seg["seg_lv1to4"]; } else { writeln("a tag named already exists, check text line\n ", an_object["substantive"]); } } return tag_assoc; } @system ST_txt_by_line_common_reset txt_by_line_common_reset_()( int[string] line_occur, string[string] an_object, uint[string] pith, ) { line_occur["heading"] = eN.bi.off; line_occur["para"] = eN.bi.off; pith["txt_is"] = eN.txt_is.off; an_object = an_object.object_reset; ST_txt_by_line_common_reset ret; { ret.line_occur = line_occur; ret.this_object = an_object; ret.pith = pith; } return ret; } ST_the_section build_the_glossary_section( char[] line, // line is immutable, not necessary to return unchanged uint[string] pith, string[string][string] tag_assoc, // only for headings: html & epub ) { static auto rgx = RgxI(); ObjGenericComposite comp_obj_; ObjGenericComposite[] add_to_current_document_section; indent = [ "hang_position" : 0, "base_position" : 0, ]; bullet = false; pith["txt_is"] = eN.txt_is.para; line_occur["para"] = eN.bi.off; an_object_key = "glossary_nugget"; ST_the_section ret; if (line.matchFirst(rgx.heading_glossary)) { { comp_obj_ = set_object_heading("lev1", "backmatter", "glossary", "Glossary"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = false; comp_obj_.metainfo.object_number_off = false; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "_part_glossary"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = "glossary"; comp_obj_.tags.anchor_tags = ["section_glossary"]; comp_obj_.metainfo.dom_structure_markedup_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; comp_obj_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; add_to_current_document_section ~= comp_obj_; // tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; } { comp_obj_ = set_object_heading("lev4", "backmatter", "glossary", "Glossary"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = true; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "glossary"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = comp_obj_.tags.anchor_tag_html; comp_obj_.metainfo.heading_lev_collapsed = 2; comp_obj_.tags.anchor_tags = ["glossary"]; add_to_current_document_section ~= comp_obj_; // tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; pith["ocn"] = eN.ocn.on; } { ret.comp_section_obj ~= add_to_current_document_section; ret.pith = pith; ret.tag_assoc = tag_assoc; // only for headings: html & epub } } else { // para { auto _get = line.flow_para_match_(an_object, an_object_key, indent, bullet, pith, line_occur); { an_object = _get.this_object; an_object_key = _get.this_object_key; pith = _get.pith; indent = _get.indent; bullet = _get.bullet; line_occur = _get.line_occur; } } comp_obj_ = set_object_generic("backmatter", "glossary", "para", "glossary", links_and_images(line.to!string.strip).replaceFirst(rgx.para_attribs, ""), 0); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.attrib.indent_hang = indent["hang_position"]; comp_obj_.attrib.indent_base = indent["base_position"]; comp_obj_.attrib.bullet = bullet; add_to_current_document_section ~= comp_obj_; // pith["ocn"] = eN.ocn.on; { ret.comp_section_obj = add_to_current_document_section; ret.pith = pith; ret.tag_assoc = tag_assoc; // NO CHANGE here, only for headings: html & epub } } return ret; } ST_the_section build_the_blurb_section(Opt) ( char[] line, // line is immutable, not necessary to return unchanged uint[string] pith, string[string][string] tag_assoc, // only for headings: html & epub Opt opt_action, ) { static auto rgx = RgxI(); ObjGenericComposite comp_obj_; ObjGenericComposite[] add_to_current_document_section; // assert (opt_action.backmatter && opt_action.section_blurb); indent = [ "hang_position" : 0, "base_position" : 0, ]; bullet = false; if (auto m = line.matchFirst(rgx.para_indent)) { debug(paraindent) { writeln(line); } indent["hang_position"] = (m["indent"]).to!int; indent["base_position"] = (m["indent"]).to!int; } else if (line.matchFirst(rgx.para_bullet)) { debug(parabullet) { writeln(line); } bullet = true; } else if (auto m = line.matchFirst(rgx.para_indent_hang)) { debug(paraindenthang) { writeln(line); } indent = [ "hang_position" : (m["hang"]).to!int, "base_position" : (m["indent"]).to!int, ]; } else if (auto m = line.matchFirst(rgx.para_bullet_indent)) { debug(parabulletindent) { writeln(line); } indent = [ "hang_position" : (m["indent"]).to!int, "base_position" : (m["indent"]).to!int, ]; bullet = true; } pith["txt_is"] = eN.txt_is.para; line_occur["para"] = eN.bi.off; an_object_key = "blurb_nugget"; ST_the_section ret; if (line.matchFirst(rgx.heading_blurb) && (opt_action.backmatter && opt_action.section_blurb)) { { comp_obj_ = set_object_heading("lev1", "backmatter", "blurb", "Blurb"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = false; comp_obj_.metainfo.object_number_off = false; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "_part_blurb"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = "blurb"; comp_obj_.tags.anchor_tags = ["section_blurb"]; comp_obj_.metainfo.dom_structure_markedup_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; comp_obj_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; add_to_current_document_section ~= comp_obj_; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; } { comp_obj_ = set_object_heading("lev4", "backmatter", "blurb", "Blurb"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = true; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "blurb"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = comp_obj_.tags.anchor_tag_html; comp_obj_.metainfo.heading_lev_collapsed = 2; comp_obj_.tags.anchor_tags = ["blurb"]; add_to_current_document_section ~= comp_obj_; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; } } else if (line.matchFirst(rgx.headings) && (opt_action.backmatter && opt_action.section_blurb)) { comp_obj_ = comp_obj_.init; comp_obj_.metainfo.is_of_part = "backmatter"; comp_obj_.metainfo.is_of_section = "blurb"; comp_obj_.metainfo.is_of_type = "para"; comp_obj_.metainfo.is_a = "heading"; comp_obj_.text = line.to!string; comp_obj_.metainfo.ocn = 0; comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = false; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "blurb"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = comp_obj_.tags.anchor_tag_html; comp_obj_.metainfo.heading_lev_markup = an_object["lev_markup_number"].to!int; // make int, remove need to conv comp_obj_.metainfo.heading_lev_collapsed = an_object["lev_collapsed_number"].to!int; // make int, remove need to conv comp_obj_.metainfo.parent_ocn = 1; comp_obj_.metainfo.parent_lev_markup = 0; add_to_current_document_section ~= comp_obj_; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; } else if (!(line.empty)) { { auto _get = line.flow_para_match_(an_object, an_object_key, indent, bullet, pith, line_occur); { an_object = _get.this_object; an_object_key = _get.this_object_key; pith = _get.pith; indent = _get.indent; bullet = _get.bullet; line_occur = _get.line_occur; } } comp_obj_ = set_object_generic("backmatter", "blurb", "para", "blurb", links_and_images(line.to!string.strip).replaceFirst(rgx.para_attribs, ""), 0); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.attrib.indent_hang = indent["hang_position"]; comp_obj_.attrib.indent_base = indent["base_position"]; comp_obj_.has.inline_links = true; comp_obj_.attrib.bullet = bullet; add_to_current_document_section ~= comp_obj_; } pith["ocn"] = eN.ocn.on; { ret.comp_section_obj = add_to_current_document_section; ret.pith = pith; ret.tag_assoc = tag_assoc; // NO CHANGE here, only for headings: html & epub } return ret; } @safe ST_txt_by_line_block_start txt_by_line_block_start()( char[] line, uint[string] pith, uint[string] dochas, string[string] object_number_poem ) { static auto rgx = RgxI(); if (auto m = line.matchFirst(rgx.block_curly_code_open)) { dochas["codeblock"]++; an_object["lang"] = ""; an_object["attrib"] = (m["attrib"]) ? m["attrib"].to!string : ""; an_object["syntax"] = (m["syntax"]) ? m["syntax"].to!string : ""; debug(codecurly) { writefln( "* [code curly] %s", line); } // code (curly) open pith["block_is"] = eN.blk_is.code; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.curly; } else if (auto m = line.matchFirst(rgx.block_curly_poem_open)) { dochas["poem"]++; an_object["syntax"] = ""; an_object["attrib"] = (m["attrib"]) ? m["attrib"].to!string : ""; an_object["lang"] = (m["lang"]) ? m["lang"].to!string : ""; debug(poem) { writefln( "* [poem curly] %s", line); } // poem (curly) open object_number_poem["start"] = obj_cite_digits.object_number.to!string; pith["block_is"] = eN.blk_is.poem; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.curly; pith["verse_new"] = eN.bi.on; } else if (auto m = line.matchFirst(rgx.block_curly_group_open)) { dochas["group"]++; an_object["syntax"] = ""; an_object["attrib"] = (m["attrib"]) ? m["attrib"].to!string : ""; an_object["lang"] = (m["lang"]) ? m["lang"].to!string : ""; debug(group) { writefln( "* [group curly] %s", line); } // group (curly) open pith["block_is"] = eN.blk_is.group; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.curly; } else if (auto m = line.matchFirst(rgx.block_curly_block_open)) { dochas["block"]++; an_object["syntax"] = ""; an_object["attrib"] = (m["attrib"]) ? m["attrib"].to!string : ""; an_object["lang"] = (m["lang"]) ? m["lang"].to!string : ""; debug(block) { writefln( "* [block curly] %s", line); } pith["block_is"] = eN.blk_is.block; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.curly; } else if (auto m = line.matchFirst(rgx.block_curly_quote_open)) { dochas["quote"]++; an_object["syntax"] = ""; an_object["attrib"] = m["attrib"].to!string; an_object["lang"] = m["lang"].to!string; debug(quote) { writefln( "* [quote curly] %s", line); } pith["block_is"] = eN.blk_is.quote; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.curly; } else if (auto m = line.matchFirst(rgx.block_curly_table_open)) { // curly table open debug(table) { writefln( "* [table curly] %s", line); } dochas["table"] ++; an_object["table_head"] = m["attrib"].to!string; an_object["block_type"] = "curly"; pith["block_is"] = eN.blk_is.table; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.curly; } else if (auto m = line.matchFirst(rgx.block_curly_table_special_markup)) { // table: special table block markup syntax! dochas["table"]++; an_object["table_head"] = m["attrib"].to!string; an_object["block_type"] = "special"; pith["block_is"] = eN.blk_is.table; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.curly_special; } else if (auto m = line.matchFirst(rgx.block_tic_code_open)) { dochas["codeblock"]++; an_object["lang"] = ""; an_object["attrib"] = (m["attrib"]) ? m["attrib"].to!string : ""; an_object["syntax"] = (m["syntax"]) ? m["syntax"].to!string : ""; debug(codetic) { writefln( "* [code tic] %s", line); } pith["block_is"] = eN.blk_is.code; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.tic; } else if (auto m = line.matchFirst(rgx.block_tic_poem_open)) { dochas["poem"]++; an_object["syntax"] = ""; an_object["attrib"] = (m["attrib"]) ? m["attrib"].to!string : ""; an_object["lang"] = (m["lang"]) ? m["lang"].to!string : ""; debug(poem) { writefln( "* [poem tic] %s", line); } object_number_poem["start"] = obj_cite_digits.object_number.to!string; pith["block_is"] = eN.blk_is.poem; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.tic; pith["verse_new"] = eN.bi.on; } else if (auto m = line.matchFirst(rgx.block_tic_group_open)) { dochas["group"]++; an_object["syntax"] = ""; an_object["attrib"] = (m["attrib"]) ? m["attrib"].to!string : ""; an_object["lang"] = (m["lang"]) ? m["lang"].to!string : ""; debug(group) { writefln( "* [group tic] %s", line); } pith["block_is"] = eN.blk_is.group; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.tic; } else if (auto m = line.matchFirst(rgx.block_tic_block_open)) { dochas["block"]++; an_object["syntax"] = ""; an_object["attrib"] = (m["attrib"]) ? m["attrib"].to!string : ""; an_object["lang"] = (m["lang"]) ? m["lang"].to!string : ""; debug(block) { writefln( "* [block tic] %s", line); } pith["block_is"] = eN.blk_is.block; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.tic; } else if (auto m = line.matchFirst(rgx.block_tic_quote_open)) { dochas["quote"]++; an_object["syntax"] = ""; an_object["attrib"] = m["attrib"].to!string; an_object["lang"] = m["lang"].to!string; debug(quote) { writefln( "* [quote tic] %s", line); // quote (tic) open } pith["block_is"] = eN.blk_is.quote; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.tic; } else if (auto m = line.matchFirst(rgx.block_tic_table_open)) { // tic table open debug(table) { writefln( "* [table tic] %s", line); } dochas["table"] ++; an_object["table_head"] = m["attrib"].to!string; an_object["block_type"] = "tic"; pith["block_is"] = eN.blk_is.table; pith["block_state"] = eN.blk_state.on; pith["block_delim"] = eN.blk_delim.tic; } ST_txt_by_line_block_start ret; { ret.pith = pith; ret.dochas = dochas; ret.object_number_poem = object_number_poem; } return ret; } @safe ST_txt_by_line_block_generic txt_by_line_block_quote()( char[] line, string[string] an_object, uint[string] pith, ) { static auto rgx = RgxI(); if (pith["block_is"] == eN.blk_is.quote){ if (pith["block_delim"] == eN.blk_delim.curly) { if (line.matchFirst(rgx.block_curly_quote_close)) { debug(quote) { writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; pith["block_is"] = eN.blk_is.quote; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { debug(quote) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } else if (pith["block_delim"] == eN.blk_delim.tic) { if (line.matchFirst(rgx.block_tic_close)) { debug(quote) { writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; pith["block_is"] = eN.blk_is.quote; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { debug(quote) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } } ST_txt_by_line_block_generic ret; { ret.pith = pith; ret.this_object = an_object; } return ret; } @safe ST_txt_by_line_block_generic txt_by_line_block_group()( char[] line, string[string] an_object, uint[string] pith, ) { static auto rgx = RgxI(); if (pith["block_is"] == eN.blk_is.group) { if (pith["block_delim"] == eN.blk_delim.curly) { if (line.matchFirst(rgx.block_curly_group_close)) { debug(group) { writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; pith["block_is"] = eN.blk_is.group; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { debug(group) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } else if (pith["block_delim"] == eN.blk_delim.tic) { if (line.matchFirst(rgx.block_tic_close)) { debug(group) { writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; pith["block_is"] = eN.blk_is.group; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { debug(group) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } } ST_txt_by_line_block_generic ret; { ret.pith = pith; ret.this_object = an_object; } return ret; } @safe ST_txt_by_line_block_generic txt_by_line_block_block()( char[] line, string[string] an_object, uint[string] pith, ) { static auto rgx = RgxI(); if (pith["block_is"] == eN.blk_is.block) { if (pith["block_delim"] == eN.blk_delim.curly) { if (line.matchFirst(rgx.block_curly_block_close)) { debug(block) { writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; pith["block_is"] = eN.blk_is.block; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { debug(block) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } else if (pith["block_delim"] == eN.blk_delim.tic) { if (line.matchFirst(rgx.block_tic_close)) { debug(block) { writeln(line); } an_object[an_object_key] = an_object[an_object_key].stripRight; pith["block_is"] = eN.blk_is.block; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { debug(block) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } } ST_txt_by_line_block_generic ret; { ret.pith = pith; ret.this_object = an_object; } return ret; } @safe ST_txt_by_line_block_poem txt_by_line_block_poem(CMM)( char[] line, string[string] an_object, uint[string] pith, int cntr, string[string] object_number_poem, CMM conf_make_meta, string[string] tag_in_seg, ) { static auto rgx = RgxI(); if (pith["block_is"] == eN.blk_is.poem) { if (pith["block_delim"] == eN.blk_delim.curly) { if (line.matchFirst(rgx.block_curly_poem_close)) { if (an_object_key in an_object || processing.length > 0) { an_object[an_object_key] = ""; debug(poem) { writefln( "* [poem curly] %s", line); } if (processing.length > 0) { an_object[an_object_key] = processing["verse"]; } debug(poem) { writeln(__LINE__); writefln( "* %s %s", obj_cite_digits.object_number, line); } if (an_object.length > 0) { debug(poem) { writeln( obj_cite_digits.object_number, an_object[an_object_key]); } an_object["is"] = "verse"; ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; anchor_tag = substantive_obj_misc_struct.anchor_tag; comp_obj_ = set_object_generic("body", "body", "block", "verse", an_object["substantive"], obj_cite_digits.object_number); comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digits.type; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.has.inline_notes_reg = substantive_obj_misc_struct.has_notes_reg; comp_obj_.has.inline_notes_star = substantive_obj_misc_struct.has_notes_star; comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links; the_document_body_section ~= comp_obj_; tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc); } object_reset(an_object); processing.remove("verse"); ++cntr; } object_number_poem["end"] = obj_cite_digits.object_number.to!string; pith["block_is"] = eN.blk_is.poem; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { processing["verse"] ~= line ~= "\n"; if (pith["verse_new"] == eN.bi.on) { obj_cite_digits = ocn_emit(pith["ocn"]); pith["verse_new"] = eN.bi.off; } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) { processing["verse"] = processing["verse"].stripRight; verse_line = eN.bi.off; pith["verse_new"] = eN.bi.on; } if (pith["verse_new"] == eN.bi.on) { verse_line = 1; an_object[an_object_key] = processing["verse"]; debug(poem) { writefln( "* %s curly\n%s", obj_cite_digits.object_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, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; anchor_tag = substantive_obj_misc_struct.anchor_tag; comp_obj_ = set_object_generic("body", "body", "block", "verse", an_object["substantive"], obj_cite_digits.object_number); comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digits.type; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.has.inline_notes_reg = substantive_obj_misc_struct.has_notes_reg; comp_obj_.has.inline_notes_star = substantive_obj_misc_struct.has_notes_star; comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links; the_document_body_section ~= comp_obj_; tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc); object_reset(an_object); processing.remove("verse"); ++cntr; } } } else if (pith["block_delim"] == eN.blk_delim.tic) { if (auto m = line.matchFirst(rgx.block_tic_close)) { an_object[an_object_key] = "verse"; debug(poem) { writefln( "* [poem tic] %s", line); } if (processing.length > 0) { an_object[an_object_key] = processing["verse"]; } if (an_object.length > 0) { debug(poem) { writeln(__LINE__); writeln(obj_cite_digits.object_number, line); } processing.remove("verse"); an_object["is"] = "verse"; ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; anchor_tag = substantive_obj_misc_struct.anchor_tag; comp_obj_ = set_object_generic("body", "body", "block", "verse", an_object["substantive"], obj_cite_digits.object_number); comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digits.type; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.has.inline_notes_reg = substantive_obj_misc_struct.has_notes_reg; comp_obj_.has.inline_notes_star = substantive_obj_misc_struct.has_notes_star; comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links; the_document_body_section ~= comp_obj_; tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc); object_number_poem["end"] = obj_cite_digits.object_number.to!string; object_reset(an_object); processing.remove("verse"); ++cntr; } pith["block_is"] = eN.blk_is.poem; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { processing["verse"] ~= line ~= "\n"; if (pith["verse_new"] == eN.bi.on) { obj_cite_digits = ocn_emit(pith["ocn"]); pith["verse_new"] = eN.bi.off; } else if (line.matchFirst(rgx.newline_eol_delimiter_only)) { processing["verse"] = processing["verse"].stripRight; pith["verse_new"] = eN.bi.on; verse_line = eN.bi.off; } if (pith["verse_new"] == eN.bi.on) { verse_line = 1; an_object[an_object_key] = processing["verse"]; debug(poem) { writefln( "* %s tic\n%s", obj_cite_digits.object_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, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; anchor_tag = substantive_obj_misc_struct.anchor_tag; comp_obj_ = set_object_generic("body", "body", "block", "verse", an_object["substantive"], obj_cite_digits.object_number); comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digits.type; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.has.inline_notes_reg = substantive_obj_misc_struct.has_notes_reg; comp_obj_.has.inline_notes_star = substantive_obj_misc_struct.has_notes_star; comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links; the_document_body_section ~= comp_obj_; tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc); object_reset(an_object); processing.remove("verse"); ++cntr; } } } } ST_txt_by_line_block_poem ret; { ret.cntr = cntr; ret.pith = pith; ret.this_object = an_object; } return ret; } @safe ST_txt_by_line_block_generic txt_by_line_block_code()( char[] line, string[string] an_object, uint[string] pith, ) { static auto rgx = RgxI(); if ( pith["block_is"] == eN.blk_is.code) { if (pith["block_delim"] == eN.blk_delim.curly) { if (line.matchFirst(rgx.block_curly_code_close)) { debug(codecurly) { writeln(line); } an_object[an_object_key] = an_object[an_object_key] .replaceFirst(rgx.newline_eol_delimiter_only, "") .stripRight; pith["block_is"] = eN.blk_is.code; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { debug(codecurly) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } else if (pith["block_delim"] == eN.blk_delim.tic) { if (line.matchFirst(rgx.block_tic_close)) { debug(codetic) { writeln(line); } an_object[an_object_key] = an_object[an_object_key] .replaceFirst(rgx.newline_eol_delimiter_only, "") .stripRight; pith["block_is"] = eN.blk_is.code; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { debug(codetic) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } } ST_txt_by_line_block_generic ret; { ret.pith = pith; ret.this_object = an_object; } return ret; } @system auto txt_by_line_block_table(CMM)( char[] line, string[string] an_object, uint[string] pith, CMM conf_make_meta, ) { static auto rgx = RgxI(); if (pith["block_is"] == eN.blk_is.table) { if (pith["block_delim"] == eN.blk_delim.curly) { if (line.matchFirst(rgx.block_curly_table_close)) { debug(table) { writeln(line); } pith["block_is"] = eN.blk_is.table; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { debug(table) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } else if (pith["block_delim"] == eN.blk_delim.curly_special) { if (line.empty) { pith["block_is"] = eN.blk_is.table; pith["block_state"] = eN.blk_state.off; pith["block_delim"] = eN.blk_delim.off; { auto _get = line.flow_table_closed_make_special_notation_table_( an_object, the_document_body_section, obj_cite_digits, comp_obj_, cntr, pith, conf_make_meta, ); { an_object = _get.this_object; the_document_body_section = _get.the_document_body_section; obj_cite_digits = _get.obj_cite_digits; comp_obj_ = _get.comp_obj_; cntr = _get.cntr; pith = _get.pith; } } } else { debug(table) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } else if (pith["block_delim"] == eN.blk_delim.tic) { if (line.matchFirst(rgx.block_tic_close)) { debug(table) { writeln(line); } pith["block_is"] = eN.blk_is.table; pith["block_state"] = eN.blk_state.closing; pith["block_delim"] = eN.blk_delim.off; } else { debug(table) { writeln(line); } an_object[an_object_key] ~= line ~= "\n"; } } } struct ST_txt_by_line_block_table { CMM conf_make_meta; uint[string] pith; string[string] this_object; } ST_txt_by_line_block_table ret; { ret.conf_make_meta = conf_make_meta, ret.pith = pith; ret.this_object = an_object; } return ret; } @system ST_txt_by_line_block_biblio txt_by_line_block_biblio( char[] line, uint[string] pith, int bib_entry, string biblio_entry_str_json, string[] biblio_arr_json, ) { mixin spineBiblio; auto jsn = BibJsnStr(); static auto rgx = RgxI(); string biblio_tag_map()(string abr) { auto btm = [ "au" : "author_raw", "ed" : "editor_raw", "ti" : "fulltitle", "lng" : "language", "jo" : "journal", "vol" : "volume", "edn" : "edition", "yr" : "year", "pl" : "place", "pb" : "publisher", "pub" : "publisher", "pg" : "pages", "pgs" : "pages", "sn" : "short_name" ]; return btm[abr]; } if (line.matchFirst(rgx.heading_biblio)) { pith["section"] = eN.sect.bibliography; } if (line.empty) { debug { debug(biblioblock) { writeln("---"); } debug(biblioblockinclude) { writeln(biblio_entry_str_json.length); } } if ((bib_entry == eN.bi.off) && (biblio_entry_str_json.empty)) { bib_entry = eN.bi.on; biblio_entry_str_json = jsn.biblio_entry_tags_jsonstr; } else if (!(biblio_entry_str_json.empty)) { bib_entry = eN.bi.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 { 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 = eN.bi.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 = ""; } ST_txt_by_line_block_biblio ret; { ret.pith = pith; ret.bib_entry = bib_entry; ret.biblio_entry_str_json = biblio_entry_str_json; ret.biblio_arr_json = biblio_arr_json; } return ret; } // ↓ abstraction functions @safe static string[string] object_reset()(string[string] an_object) { an_object.remove("body_nugget"); an_object.remove("substantive"); an_object.remove("is"); an_object.remove("attrib"); an_object.remove("bookindex_nugget"); return an_object; } @safe static uint[string] _check_ocn_status_()( char[] line, uint[string] pith, ) { static auto rgx = RgxI(); if (!(line.empty)) { if (pith["no_ocn_multiple_objects"] == eN.bi.off) { // not multi-line object, check whether object_number is on or turned off if (line.matchFirst(rgx.object_number_block_marks)) { // switch off object_number if (line.matchFirst(rgx.object_number_off_block)) { pith["no_ocn_multiple_objects"] = eN.bi.on; pith["ocn"] = eN.ocn.off; debug(ocnoff) { writeln(line); } } if (line.matchFirst(rgx.object_number_off_block_dummy_heading)) { pith["no_ocn_multiple_objects"] = eN.bi.on; pith["dummy_heading_multiple_objects"] = eN.bi.on; pith["ocn"] = eN.ocn.off; debug(ocnoff) { writeln(line); } } } else if (pith["no_ocn_multiple_objects"] == eN.bi.off) { pith["dummy_heading_status"] = eN.bi.off; if (pith["dummy_heading_multiple_objects"]) { pith["dummy_heading_status"] = eN.bi.on; } if (line.matchFirst(rgx.object_number_off)) { pith["ocn"] = eN.ocn.off; } else if (line.matchFirst(rgx.object_number_off_dummy_heading)) { pith["ocn"] = eN.ocn.off; pith["dummy_heading_status"] = eN.bi.on; } else { pith["ocn"] = eN.ocn.on; pith["dummy_heading_status"] = eN.bi.off; } } else { pith["ocn"] = pith["no_ocn_multiple_objects"]; } } else if (pith["no_ocn_multiple_objects"] == eN.bi.on) { if (line.matchFirst(rgx.object_number_off_block_close)) { pith["no_ocn_multiple_objects"] = eN.bi.off; pith["ocn"] = eN.ocn.on; pith["dummy_heading_status"] = eN.bi.off; debug(ocnoff) { writeln(line); } } } } return pith; } @safe char[] _doc_header_and_make_substitutions_(CMM)( char[] line, CMM conf_make_meta, ) { enum Substitute { match, markup, } if (conf_make_meta.make.substitute) { foreach(substitution_pair; conf_make_meta.make.substitute) { line = line.replaceAll( regex("\b" ~ substitution_pair[Substitute.match]), substitution_pair[Substitute.markup] ); } } return line; } @safe char[] _doc_header_and_make_substitutions_fontface_(CMM)( char[] line, CMM conf_make_meta, ) { enum Substitute { match, markup, } if ( conf_make_meta.make.bold) { line = line.replaceAll( regex("\b" ~ conf_make_meta.make.bold[Substitute.match]), conf_make_meta.make.bold[Substitute.markup] ); } if (conf_make_meta.make.emphasis) { line = line.replaceAll( regex("\b" ~ conf_make_meta.make.emphasis[Substitute.match]), conf_make_meta.make.emphasis[Substitute.markup] ); } if (conf_make_meta.make.italics) { line = line.replaceAll( regex("\b" ~ conf_make_meta.make.italics[Substitute.match]), conf_make_meta.make.italics[Substitute.markup] ); } return line; } @system ST_flow_table_closed_make_special_notation_table flow_table_closed_make_special_notation_table_(CMM)( char[] line, string[string] an_object, ObjGenericComposite[] the_document_body_section, OCNset obj_cite_digits, ObjGenericComposite comp_obj_, int cntr, uint[string] pith, CMM conf_make_meta ) { comp_obj_ = comp_obj_.init; obj_cite_digits = ocn_emit(pith["ocn"]); auto comp_obj_location = node_construct.node_location_emitter( content_non_header, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, cntr, heading_ptr-1, "table" ); an_object["is"] = "table"; ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, "body_nugget", conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; comp_obj_.metainfo.ocn = obj_cite_digits.object_number; comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digits.type; comp_obj_ = comp_obj_.flow_table_instructions(an_object["table_head"]); { auto _get = comp_obj_.flow_table_substantive_munge_special(an_object["substantive"]); { comp_obj_ = _get.table_object; an_object["substantive"] = _get.table_substantive; } } the_document_body_section ~= comp_obj_; object_reset(an_object); processing.remove("verse"); ++cntr; ST_flow_table_closed_make_special_notation_table ret; { ret.this_object = an_object; ret.the_document_body_section = the_document_body_section; ret.obj_cite_digits = obj_cite_digits; ret.comp_obj_ = comp_obj_; ret.cntr = cntr; ret.pith = pith; } return ret; } @system ST_flow_block_flag_line_empty flow_block_flag_line_empty_(B,CMM,Ts)( char[] line, string[string] an_object, B bookindex_extract_hash, ObjGenericComposite[] the_document_body_section, string[][string][string] bookindex_unordered_hashes, OCNset obj_cite_digits, ObjGenericComposite comp_obj_, int cntr, uint[string] pith, string[string] object_number_poem, CMM conf_make_meta, Ts tag_in_seg, ) { assert( line.empty, "\nline should be empty:\n \"" ~ line ~ "\"" ); assert( (pith["block_state"] == eN.blk_state.closing), "code block status: closed" ); static auto rgx = RgxI(); if (pith["block_state"] == eN.blk_state.closing) { if (pith["block_is"] == eN.blk_is.quote) { obj_cite_digits = ocn_emit(pith["ocn"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, tag_in_seg ); an_object["is"] = "quote"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; anchor_tag = substantive_obj_misc_struct.anchor_tag; comp_obj_ = set_object_generic("body", "body", "block", "quote", an_object["substantive"], obj_cite_digits.object_number); comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digit_type; comp_obj_.metainfo.lang = an_object["lang"]; comp_obj_.metainfo.attrib = an_object["attrib"]; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.has.inline_notes_reg = substantive_obj_misc_struct.has_notes_reg; comp_obj_.has.inline_notes_star = substantive_obj_misc_struct.has_notes_star; comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links; the_document_body_section ~= comp_obj_; tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc); pith["block_is"] = eN.blk_is.quote; pith["block_state"] = eN.blk_state.off; pith["block_delim"] = eN.blk_delim.off; object_reset(an_object); processing.remove("verse"); ++cntr; } else if (pith["block_is"] == eN.blk_is.group) { obj_cite_digits = ocn_emit(pith["ocn"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, tag_in_seg ); an_object["is"] = "group"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; anchor_tag = substantive_obj_misc_struct.anchor_tag; comp_obj_ = set_object_generic("body", "body", "block", "group", an_object["substantive"], obj_cite_digits.object_number); comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digits.type; comp_obj_.metainfo.lang = an_object["lang"]; comp_obj_.metainfo.attrib = an_object["attrib"]; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.has.inline_notes_reg = substantive_obj_misc_struct.has_notes_reg; comp_obj_.has.inline_notes_star = substantive_obj_misc_struct.has_notes_star; comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links; the_document_body_section ~= comp_obj_; tag_assoc = an_object.inline_para_link_anchor(tag_in_seg, tag_assoc); pith["block_is"] = eN.blk_is.poem; pith["block_state"] = eN.blk_state.off; pith["block_delim"] = eN.blk_delim.off; object_reset(an_object); processing.remove("verse"); ++cntr; } else if (pith["block_is"] == eN.blk_is.block) { obj_cite_digits = ocn_emit(pith["ocn"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, tag_in_seg ); an_object["is"] = "block"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; // anchor_tag = substantive_obj_misc_struct.anchor_tag; // check comp_obj_ = set_object_generic("body", "body", "block", "block", an_object["substantive"], obj_cite_digits.object_number); comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digit_type; comp_obj_.metainfo.lang = an_object["lang"]; comp_obj_.metainfo.attrib = an_object["attrib"]; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.has.inline_notes_reg = substantive_obj_misc_struct.has_notes_reg; comp_obj_.has.inline_notes_star = substantive_obj_misc_struct.has_notes_star; comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links; the_document_body_section ~= comp_obj_; pith["block_is"] = eN.blk_is.block; pith["block_state"] = eN.blk_state.off; pith["block_delim"] = eN.blk_delim.off; object_reset(an_object); processing.remove("verse"); ++cntr; } else if (pith["block_is"] == eN.blk_is.poem) { an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, tag_in_seg ); an_object["is"] = "verse"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); comp_obj_poem_ocn = set_object_generic("body", "body", "block", "poem", "", obj_cite_digits.object_number); comp_obj_poem_ocn.metainfo.identifier = obj_cite_digits.identifier; comp_obj_poem_ocn.metainfo.object_number_off = obj_cite_digits.off; comp_obj_poem_ocn.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_poem_ocn.metainfo.object_number_type = obj_cite_digits.type; the_document_body_section ~= comp_obj_poem_ocn; pith["block_is"] = eN.blk_is.poem; pith["block_state"] = eN.blk_state.off; pith["block_delim"] = eN.blk_delim.off; object_reset(an_object); processing.remove("verse"); } else if (pith["block_is"] == eN.blk_is.code) { obj_cite_digits = ocn_emit(pith["ocn"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, tag_in_seg ); an_object["is"] = "code"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; anchor_tag = substantive_obj_misc_struct.anchor_tag; comp_obj_ = set_object_generic("body", "body", "block", "code", an_object["substantive"], obj_cite_digits.object_number); comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digits.type; comp_obj_.metainfo.syntax = an_object["syntax"]; comp_obj_.metainfo.attrib = an_object["attrib"]; comp_obj_.code_block.linenumbers = (an_object["attrib"].match(rgx.code_numbering)) ? true : false; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.has.inline_notes_reg = substantive_obj_misc_struct.has_notes_reg; comp_obj_.has.inline_notes_star = substantive_obj_misc_struct.has_notes_star; comp_obj_.has.inline_links = substantive_obj_misc_struct.has_links; the_document_body_section ~= comp_obj_; pith["block_is"] = eN.blk_is.code; pith["block_state"] = eN.blk_state.off; pith["block_delim"] = eN.blk_delim.off; object_reset(an_object); processing.remove("verse"); ++cntr; } else if (pith["block_is"] == eN.blk_is.table) { comp_obj_ = comp_obj_.init; obj_cite_digits = ocn_emit(pith["ocn"]); an_object["bookindex_nugget"] = ("bookindex_nugget" in an_object) ? an_object["bookindex_nugget"] : ""; bookindex_unordered_hashes = bookindex_extract_hash.bookindex_nugget_hash( an_object["bookindex_nugget"], obj_cite_digits, tag_in_seg ); an_object["is"] = "table"; auto comp_obj_location = node_construct.node_location_emitter( content_non_header, tag_in_seg, lev_anchor_tag, tag_assoc, obj_cite_digits, cntr, heading_ptr-1, an_object["is"] ); ST_txtAndAnchorTagPlusHasFootnotesUrlsImages substantive_obj_misc_struct = obj_im.obj_inline_markup_and_anchor_tags_and_misc(an_object, an_object_key, conf_make_meta, No._new_doc); an_object["substantive"] = substantive_obj_misc_struct.obj_txt; comp_obj_ = comp_obj_.init; comp_obj_.metainfo.ocn = obj_cite_digits.object_number; comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digits.type; comp_obj_ = comp_obj_.flow_table_instructions(an_object["table_head"]); { auto _get = comp_obj_.flow_table_substantive_munge(an_object["substantive"]); { comp_obj_ = _get.table_object; an_object["substantive"] = _get.table_substantive; } } the_document_body_section ~= comp_obj_; pith["block_is"] = eN.blk_is.table; pith["block_state"] = eN.blk_state.off; pith["block_delim"] = eN.blk_delim.off; object_reset(an_object); processing.remove("verse"); ++cntr; } } ST_flow_block_flag_line_empty ret; { ret.this_object = an_object; ret.the_document_body_section = the_document_body_section; ret.bookindex_unordered_hashes = bookindex_unordered_hashes; ret.obj_cite_digits = obj_cite_digits; ret.comp_obj_ = comp_obj_; // ret.cntr = cntr; ret.pith = pith; } return ret; } @system ST_flow_book_index flow_book_index_(B)( char[] line, string[string] an_object, string book_idx_tmp, uint[string] pith, B opt_action, ) { static auto rgx = RgxI(); if (auto m = line.match(rgx.book_index_item)) { // match book_index debug(bookindexmatch) { writefln( "* [bookindex] %s\n", m["bookindex"].to!string, ); } an_object["bookindex_nugget"] = m.captures[1].to!string; } else if (auto m = line.match(rgx.book_index_item_open)) { // match open book_index pith["section"] = eN.sect.book_index; if (opt_action.backmatter && opt_action.section_bookindex) { book_idx_tmp = m.captures[1].to!string; debug(bookindexmatch) { writefln( "* [bookindex] %s\n", book_idx_tmp,); } } } else if (pith["section"] == eN.sect.book_index) { // book_index flag set if (auto m = line.match(rgx.book_index_item_close)) { pith["section"] = eN.sect.unset; if (opt_action.backmatter && opt_action.section_bookindex) { an_object["bookindex_nugget"] = book_idx_tmp ~ m.captures[1].to!string; debug(bookindexmatch) { writefln( "* [bookindex] %s\n", book_idx_tmp,); } } book_idx_tmp = ""; } else { if (opt_action.backmatter && opt_action.section_bookindex) { book_idx_tmp ~= line; } } } ST_flow_book_index ret; { ret.this_object = an_object; ret.pith = pith; ret.book_idx_tmp = book_idx_tmp; } return ret; } @safe ST_flow_heading_found flow_heading_found_()( char[] line, string[string] heading_match_str, string[] _make_unmarked_headings, Regex!(char)[string] heading_match_rgx, uint[string] pith, ) { static auto rgx = RgxI(); if ((_make_unmarked_headings.length > 2) && (pith["make_headings"] == eN.bi.off)) { // headings found debug(headingsfound) { writeln(_make_unmarked_headings); } debug(headingsfound) { writeln(_make_unmarked_headings.length); writeln(_make_unmarked_headings); } switch (_make_unmarked_headings.length) { case 7 : if (!empty(_make_unmarked_headings[6])) { heading_match_str["h_4"] = "^(" ~ _make_unmarked_headings[6].to!string ~ ")"; heading_match_rgx["h_4"] = regex(heading_match_str["h_4"]); } goto case; case 6 : if (!empty(_make_unmarked_headings[5])) { heading_match_str["h_3"] = "^(" ~ _make_unmarked_headings[5].to!string ~ ")"; heading_match_rgx["h_3"] = regex(heading_match_str["h_3"]); } goto case; case 5 : if (!empty(_make_unmarked_headings[4])) { heading_match_str["h_2"] = "^(" ~ _make_unmarked_headings[4].to!string ~ ")"; heading_match_rgx["h_2"] = regex(heading_match_str["h_2"]); } goto case; case 4 : if (!empty(_make_unmarked_headings[3])) { heading_match_str["h_1"] = "^(" ~ _make_unmarked_headings[3].to!string ~ ")"; heading_match_rgx["h_1"] = regex(heading_match_str["h_1"]); } goto case; case 3 : if (!empty(_make_unmarked_headings[2])) { heading_match_str["h_D"] = "^(" ~ _make_unmarked_headings[2].to!string ~ ")"; heading_match_rgx["h_D"] = regex(heading_match_str["h_D"]); } goto case; case 2 : if (!empty(_make_unmarked_headings[1])) { heading_match_str["h_C"] = "^(" ~ _make_unmarked_headings[1].to!string ~ ")"; heading_match_rgx["h_C"] = regex(heading_match_str["h_C"]); } goto case; case 1 : if (!empty(_make_unmarked_headings[0])) { heading_match_str["h_B"] = "^(" ~ _make_unmarked_headings[0].to!string ~ ")"; heading_match_rgx["h_B"] = regex(heading_match_str["h_B"]); } break; default: break; } pith["make_headings"] = eN.bi.on; } ST_flow_heading_found ret; { ret.heading_match_str = heading_match_str; ret.heading_match_rgx = heading_match_rgx; ret.pith = pith; } return ret; } @safe ST_flow_heading_make_set flow_heading_make_set_()( char[] line, int[string] line_occur, return ref Regex!(char)[string] heading_match_rgx, return ref uint[string] pith, ) { if (pith["make_headings"] == eN.bi.on && (line_occur["para"] == eN.bi.off && line_occur["heading"] == eN.bi.off) && pith["txt_is"] == eN.txt_is.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); } } } ST_flow_heading_make_set ret; { ret.line = line; ret.pith = pith; ret.this_object = an_object; } return ret; } @safe auto flow_heading_matched_(CMM)( char[] line, string[string] an_object, int[string] line_occur, string an_object_key, int[string] lv, int[string] collapsed_lev, uint[string] pith, CMM conf_make_meta, ) { static auto rgx = RgxI(); static auto mkup = InlineMarkup(); if (auto m = line.match(rgx.headings)) { // heading match ++line_occur["heading"]; pith["txt_is"] = eN.txt_is.heading; if (line.match(rgx.heading_seg_and_above)) { pith["section"] = eN.sect.unset; } an_object[an_object_key] ~= line ~= "\n"; an_object["lev"] ~= m.captures[1]; assertions_doc_structure(an_object, an_object_key, lv); // includes most of the logic for collapsed levels switch (an_object["lev"]) { case "A": // Title set if ((an_object[an_object_key].match(rgx.variable_doc_title_author_date)) || (an_object[an_object_key].match(rgx.variable_doc_title) && an_object[an_object_key].match(rgx.variable_doc_author) && an_object[an_object_key].match(rgx.variable_doc_date))) { an_object[an_object_key] = an_object[an_object_key] .replaceFirst(rgx.variable_doc_title_author_date, (conf_make_meta.meta.title_full ~ mkup.br_line_inline ~ conf_make_meta.meta.creator_author ~ " (" ~ (conf_make_meta.meta.date_published.replaceFirst(regex(r"(?:-00)+"),"")) ~ ")")) .replaceFirst(rgx.variable_doc_title, (conf_make_meta.meta.title_full ~ mkup.br_line_inline)) .replaceFirst(rgx.variable_doc_author, conf_make_meta.meta.creator_author) .replaceFirst(rgx.variable_doc_date, " (" ~ (conf_make_meta.meta.date_published.replaceFirst(regex(r"(?:-00)+"),"")) ~ ")"); } else if ((an_object[an_object_key].match(rgx.variable_doc_title_author)) || (an_object[an_object_key].match(rgx.variable_doc_title) && an_object[an_object_key].match(rgx.variable_doc_author))) { an_object[an_object_key] = an_object[an_object_key] .replaceFirst(rgx.variable_doc_title_author_date, (conf_make_meta.meta.title_full ~ mkup.br_line_inline ~ conf_make_meta.meta.creator_author)) .replaceFirst(rgx.variable_doc_title, (conf_make_meta.meta.title_full ~ mkup.br_line_inline)) .replaceFirst(rgx.variable_doc_author, conf_make_meta.meta.creator_author); } else if (an_object[an_object_key].match(rgx.variable_doc_title)) { an_object[an_object_key] = an_object[an_object_key] .replaceFirst(rgx.variable_doc_title, conf_make_meta.meta.title_full); } collapsed_lev["h0"] = 0; an_object["lev_collapsed_number"] = collapsed_lev["h0"].to!string; lv["lv"] = DocStructMarkupHeading.h_sect_A; ++lv["h0"]; lv["h1"] = eN.bi.off; lv["h2"] = eN.bi.off; lv["h3"] = eN.bi.off; lv["h4"] = eN.bi.off; lv["h5"] = eN.bi.off; lv["h6"] = eN.bi.off; lv["h7"] = eN.bi.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"] = eN.bi.off; lv["h3"] = eN.bi.off; lv["h4"] = eN.bi.off; lv["h5"] = eN.bi.off; lv["h6"] = eN.bi.off; lv["h7"] = eN.bi.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"] = eN.bi.off; lv["h4"] = eN.bi.off; lv["h5"] = eN.bi.off; lv["h6"] = eN.bi.off; lv["h7"] = eN.bi.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"] = eN.bi.off; lv["h5"] = eN.bi.off; lv["h6"] = eN.bi.off; lv["h7"] = eN.bi.off; goto default; case "1": if (lv["h3"] > eN.bi.off) { collapsed_lev["h4"] = collapsed_lev["h3"] + 1; } else if (lv["h2"] > eN.bi.off) { collapsed_lev["h4"] = collapsed_lev["h2"] + 1; } else if (lv["h1"] > eN.bi.off) { collapsed_lev["h4"] = collapsed_lev["h1"] + 1; } else if (lv["h0"] > eN.bi.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"] = eN.bi.off; lv["h6"] = eN.bi.off; lv["h7"] = eN.bi.off; goto default; case "2": if (lv["h5"] > eN.bi.off) { an_object["lev_collapsed_number"] = collapsed_lev["h5"].to!string; } else if (lv["h4"] > eN.bi.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"] = eN.bi.off; lv["h7"] = eN.bi.off; goto default; case "3": if (lv["h6"] > eN.bi.off) { an_object["lev_collapsed_number"] = collapsed_lev["h6"].to!string; } else if (lv["h5"] > eN.bi.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"] = eN.bi.off; goto default; case "4": if (lv["h7"] > eN.bi.off) { an_object["lev_collapsed_number"] = collapsed_lev["h7"].to!string; } else if (lv["h6"] > eN.bi.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; } an_object["dummy_heading_status"] = (pith["dummy_heading_status"] == eN.bi.off) ? "f" : "t"; debug(heading) { writeln(line.strip); } } struct ST_flow_heading_matched { string[string] this_object; int[string] line_occur; string an_object_key; int[string] lv; int[string] collapsed_lev; uint[string] pith; CMM conf_make_meta; } ST_flow_heading_matched ret; { ret.this_object = an_object; ret.line_occur = line_occur; ret.an_object_key = an_object_key; ret.lv = lv; ret.collapsed_lev = collapsed_lev; ret.pith = pith; ret.conf_make_meta = conf_make_meta; } return ret; } @safe ST_flow_para_match flow_para_match_()( char[] line, string[string] an_object, string an_object_key, int[string] indent, bool bullet, uint[string] pith, int[string] line_occur, ) { static auto rgx = RgxI(); if (line_occur["para"] == eN.bi.off) { line = font_faces_line(line); // para matches pith["txt_is"] = eN.txt_is.para; an_object[an_object_key] ~= line; indent = [ "hang_position" : 0, "base_position" : 0, ]; bullet = false; if (auto m = line.matchFirst(rgx.para_indent)) { debug(paraindent) { writeln(line); } indent["hang_position"] = (m["indent"]).to!int; indent["base_position"] = (m["indent"]).to!int; } else if (line.matchFirst(rgx.para_bullet)) { debug(parabullet) { writeln(line); } bullet = true; } else if (auto m = line.matchFirst(rgx.para_indent_hang)) { debug(paraindenthang) { writeln(line); } indent = [ "hang_position" : (m["hang"]).to!int, "base_position" : (m["indent"]).to!int, ]; } else if (auto m = line.matchFirst(rgx.para_bullet_indent)) { debug(parabulletindent) { writeln(line); } indent = [ "hang_position" : (m["indent"]).to!int, "base_position" : (m["indent"]).to!int, ]; bullet = true; } ++line_occur["para"]; } ST_flow_para_match ret; { ret.pith = pith; ret.this_object = an_object; ret.this_object_key = an_object_key; ret.indent = indent; ret.bullet = bullet; ret.line_occur = line_occur; } return ret; } @safe char[] font_faces_line()( char[] textline, ) { static auto rgx = RgxI(); static auto mkup = InlineMarkup(); if (textline.match(rgx.inline_faces_line)) { textline = textline .replaceFirst(rgx.inline_emphasis_line, format(q"┃%s%s%s%s%s%s%s┃", mkup.ff_i, mkup.emph, mkup.ff_o, "$1", mkup.ff_c, mkup.emph, "$2")) .replaceFirst(rgx.inline_bold_line, format(q"┃%s%s%s%s%s%s%s┃", mkup.ff_i, mkup.bold, mkup.ff_o, "$1", mkup.ff_c, mkup.bold, "$2")) .replaceFirst(rgx.inline_underscore_line, format(q"┃%s%s%s%s%s%s%s┃", mkup.ff_i, mkup.underscore, mkup.ff_o, "$1", mkup.ff_c, mkup.underscore, "$2")) .replaceFirst(rgx.inline_italics_line, format(q"┃%s%s%s%s%s%s%s┃", mkup.ff_i, mkup.italic, mkup.ff_o, "$1", mkup.ff_c, mkup.italic, "$2")); } return textline; } @safe ObjGenericComposite flow_table_instructions(H)( ObjGenericComposite table_object, H table_head, ) { static auto rgx = RgxI(); table_object.metainfo.is_of_part = "body"; table_object.metainfo.is_of_section = "body"; table_object.metainfo.is_of_type = "block"; table_object.metainfo.is_a = "table"; table_object.has.inline_notes_reg = false; table_object.has.inline_notes_star = false; table_object.has.inline_links = false; if (auto m = table_head.matchFirst(rgx.table_head_instructions)) { table_object.table.heading = ((m["c_heading"].length > 0) && (m["c_heading"] == "h")) ? true : false; table_object.table.number_of_columns = ((m["c_num"].length > 0) && (m["c_num"].to!int > 0)) ? m["c_num"].to!int : 0; 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; } @safe ST_flow_table_array_munge flow_table_array_munge()( ObjGenericComposite table_object, string[][] table_array, ) { static auto rgx = RgxI(); static auto mng = InlineMarkup(); string _table_substantive; ulong col_num; ulong col_num_; ulong col_num_chk = 0; foreach(idx_r, row; table_array) { debug(table_dev) { writeln("row ", idx_r); } col_num_ = 0; if (col_num == 0 || col_num < row.length) { col_num = row.length; } if (col_num_chk == 0) { col_num_chk = col_num; } else if (col_num == 1) { debug(table_dev) { writeln("table note: "); } } else if (col_num_chk != col_num) { debug(table_dev) { writeln("warning irregular number of columns: ", col_num_chk, " != ", col_num); } } else { } foreach(idx_c, col; row) { debug(table_dev) { write(idx_c, ", "); } col_num_ = idx_c; _table_substantive ~= col ~ mng.tc_s; if (idx_r == 0 && table_object.table.heading) { } else if (col.match(rgx.numeric_col) && idx_r == 1) { // conditions reversed to avoid: gdc compiled program run segfault if ((table_object.table.column_aligns.length > idx_c) && (table_object.table.column_aligns[idx_c].matchFirst(rgx.table_col_align_match))) { table_object.table.column_aligns[idx_c] = table_object.table.column_aligns[idx_c]; } else if (table_object.table.column_aligns.length > idx_c) { table_object.table.column_aligns[idx_c] = "r"; } else { table_object.table.column_aligns ~= "r"; } } else if (idx_r == 1) { if ((table_object.table.column_aligns.length > idx_c) && (table_object.table.column_aligns[idx_c].matchFirst(rgx.table_col_align_match))) { table_object.table.column_aligns[idx_c] = table_object.table.column_aligns[idx_c]; } else if (table_object.table.column_aligns.length > idx_c) { table_object.table.column_aligns[idx_c] = "l"; } else { table_object.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 (table_object.table.number_of_columns != col_num) { if (table_object.table.number_of_columns == 0) { table_object.table.number_of_columns = (col_num).to!int; } else { debug(table_dev) { writeln(table_object.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: ", table_object.table.column_aligns, "\n", "no. of columns: ", table_object.table.number_of_columns, "\n", "col widths: ", table_object.table.column_widths, " sum: ", table_object.table.column_widths.sum, "\n", _table_substantive); } table_object.text = _table_substantive; ST_flow_table_array_munge ret; { ret.table_object = table_object; ret.table_array = table_array; } return ret; } @system ST_flow_table_substantive_munge flow_table_substantive_munge()( ObjGenericComposite table_object, string table_substantive, ) { static auto rgx = RgxI(); static auto munge = ObjInlineMarkupMunge(); string[] _table_rows = (table_substantive).split(rgx.table_row_delimiter); string[] _table_cols; string[][] _table_array; foreach(col; _table_rows) { _table_cols = col.split(rgx.table_col_delimiter); _table_array ~= _table_cols; } { auto _get = table_object.flow_table_array_munge(_table_array); { table_object = _get.table_object; _table_array = _get.table_array; // what do you do with this? how is this passed down? } } ST_flow_table_substantive_munge ret; { ret.table_object = table_object; ret.table_substantive = table_substantive; // has anything been changed here? } return ret; } @system ST_flow_table_substantive_munge flow_table_substantive_munge_special()( ObjGenericComposite table_object, string table_substantive, ) { static auto rgx = RgxI(); static auto munge = ObjInlineMarkupMunge(); string[] _table_rows = (table_substantive).split(rgx.table_row_delimiter_special); string[] _table_cols; string[][] _table_array; foreach(col; _table_rows) { _table_cols = col.split(rgx.table_col_delimiter_special); _table_array ~= _table_cols; } { auto _get = table_object.flow_table_array_munge(_table_array); { table_object = _get.table_object; _table_array = _get.table_array; } } ST_flow_table_substantive_munge ret; { ret.table_object = table_object; ret.table_substantive = table_substantive; } return ret; } // abstraction functions ↑ // ↓ abstraction function emitters @safe pure struct OCNemitter { int ocn_digit, ocn_object_number, ocn_on_, ocn_off_, ocn_bkidx, ocn_bkidx_; string object_identifier; bool ocn_is_off; @safe auto ocn_emitter(int ocn_status_flag) { OCNset ocn; assert(ocn_status_flag <= eN.ocn.reset); ocn_object_number = ocn_bkidx = 0; object_identifier = ""; ocn_is_off = false; switch(ocn_status_flag) with (eN.ocn) { case reset: ocn_digit = ocn_on_ = 1; object_identifier = "1"; ocn_is_off = false; ocn_off_ = ocn_bkidx_ = 0; break; case on: ocn_digit = ocn_object_number = ++ocn_on_; object_identifier = ocn_digit.to!string; ocn_is_off = false; break; case off: ocn_digit = 0; ocn_off_ = ++ocn_off_; object_identifier = "a" ~ ocn_off_.to!string; ocn_is_off = true; break; case bkidx: ocn_bkidx = ++ocn_bkidx_; break; case closing: // unused? break; default: ocn_digit = 0; } assert(ocn_digit >= 0); ocn.digit = ocn_digit; ocn.object_number = ocn_object_number; // difference between .object_number and .digit? ocn.identifier = object_identifier; ocn.off = ocn_is_off; ocn.bkidx = ocn_bkidx; ocn.type = ocn_status_flag; return ocn; } invariant() { } } @safe ObjGenericComposite set_object_heading()( string level, string part, string section, string text, ) { ObjGenericComposite comp_obj; comp_obj = comp_obj.init; comp_obj.metainfo.is_of_part = part; comp_obj.metainfo.is_of_section = section; comp_obj.metainfo.is_of_type = "para"; comp_obj.metainfo.is_a = "heading"; comp_obj.text = text; comp_obj.metainfo.ocn = 0; if (level == "lev1") { comp_obj.metainfo.heading_lev_markup = 1; comp_obj.metainfo.heading_lev_collapsed = 1; comp_obj.metainfo.parent_ocn = 1; comp_obj.metainfo.parent_lev_markup = 0; } else if (level == "lev4") { comp_obj.metainfo.heading_lev_markup = 4; comp_obj.metainfo.heading_lev_collapsed = 1; comp_obj.metainfo.parent_ocn = 1; comp_obj.metainfo.parent_lev_markup = 0; comp_obj.metainfo.dom_structure_markedup_tags_status = [ 1, 1, 0, 0, 1, 0, 0, 0]; // KEEP comp_obj.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 1, 0, 0, 0, 0, 0]; // KEEP } return comp_obj; } @safe ObjGenericComposite set_object_generic()( string part, string section, string type, string is_a, string text, int ocn, ) { ObjGenericComposite comp_obj; comp_obj = comp_obj.init; comp_obj.metainfo.is_of_part = part; comp_obj.metainfo.is_of_section = section; comp_obj.metainfo.is_of_type = type; comp_obj.metainfo.is_a = is_a; comp_obj.text = text; comp_obj.metainfo.ocn = ocn; return comp_obj; } @safe static struct ObjInlineMarkupMunge { string[string] obj_txt; int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus; string asterisks_, plus_; string obj_txt_out, tail, note; static auto rgx = RgxI(); static auto mkup = InlineMarkup(); int stage_reset_note_numbers = true; private auto initialize_note_numbers() { n_foot = 0; n_foot_reg = 0; n_foot_sp_asterisk = 0; n_foot_sp_plus = 0; } @safe static auto images()(string obj_txt_in) { static auto mng = InlineMarkup(); // url matched obj_txt_in = obj_txt_in.replaceAll(rgx.inline_notes_al_special, ""); // TODO reinstate when special footnotes are implemented if (obj_txt_in.match(rgx.smid_image_generic)) { // images with and without links debug(images) { writeln("Image: ", obj_txt_in); } if (obj_txt_in.match(rgx.smid_image_with_dimensions)) { obj_txt_in = obj_txt_in .replaceAll(rgx.smid_image_with_dimensions, ("$1" ~ mkup.img ~ "$2,w$3h$4 " ~ "$5")) .replaceAll(rgx.smid_image_delimit, ("$1" ~ mkup.lnk_o ~ "$2".strip ~ mkup.lnk_c ~ mkup.url_o ~ mkup.url_c)); debug(images) { writeln("IMAGE with size: ", obj_txt_in); } } else if (obj_txt_in.match(rgx.smid_image)) { obj_txt_in = obj_txt_in .replaceAll(rgx.smid_image, ("$1" ~ mkup.img ~ "$2,w0h0" ~ "$3")) .replaceAll(rgx.smid_image_delimit, ("$1" ~ mkup.lnk_o ~ "$2".strip ~ mkup.lnk_c ~ mkup.url_o ~ mkup.url_c)); debug(images) { writeln("IMAGE: ", obj_txt_in); } // decide on representation } } return obj_txt_in; } @safe ST_txtPlusHasFootnotes footnotes_endnotes_markup_and_number_or_stars()(string obj_txt_in, bool reset_note_numbers) { // endnotes (regular) bool flg_notes_reg = false; bool flg_notes_star = false; bool flg_notes_plus = false; obj_txt_in = obj_txt_in.replaceAll( rgx.inline_notes_curly, (mkup.en_a_o ~ " $1" ~ mkup.en_a_c) ); if (!(stage_reset_note_numbers) && reset_note_numbers) { stage_reset_note_numbers = true; } obj_txt_out = ""; if (obj_txt_in.match(rgx.inline_notes_al_gen)) { string[] _tmp_txt; foreach (x; obj_txt_in.split("\n")) { if (auto m = x.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; _tmp_txt ~= n.hit.to!string.replaceFirst( rgx.inline_al_delimiter_open_symbol_star, (mkup.en_a_o ~ replicate(asterisks_, n_foot_sp_asterisk) ~ " ") ); } else if (n.hit.to!string.match(rgx.inline_al_delimiter_open_symbol_plus)) { flg_notes_plus = true; ++n_foot_sp_plus; plus_ = "*"; n_foot = n_foot_sp_plus; _tmp_txt ~= n.hit.to!string.replaceFirst( rgx.inline_al_delimiter_open_symbol_plus, (mkup.en_a_o ~ replicate(plus_, n_foot_sp_plus) ~ " ") ); } else if (n.hit.to!string.matchFirst(rgx.inline_al_delimiter_open_regular)) { string _tmp_str = n.hit.to!string; flg_notes_reg = true; foreach (q; n.hit.to!string.matchAll(rgx.inline_al_delimiter_open_regular)) { ++n_foot_reg; n_foot = n_foot_reg; _tmp_str = replaceFirst!(m => mkup.en_a_o ~ n_foot.to!string ~ " ") (_tmp_str, rgx.inline_al_delimiter_open_regular); } _tmp_txt ~= _tmp_str; } else { _tmp_txt ~= n.hit.to!string; } } obj_txt_out = _tmp_txt.join("\n"); } } } else { obj_txt_out = obj_txt_in; } ST_txtPlusHasFootnotes ret; { ret.obj_txt = obj_txt_out; ret.has_notes_reg = flg_notes_reg; ret.has_notes_star = flg_notes_star; ret.has_notes_plus = flg_notes_plus; } return ret; } @safe private ST_txtPlusHasFootnotesUrlsImages object_notes_and_links_()( string obj_txt_in, bool reset_note_numbers = false ) { obj_txt_out = ""; bool urls = false; bool images_without_dimensions = false; tail = ""; // special endnotes obj_txt_in = obj_txt_in.replaceAll( rgx.inline_notes_curly_sp_asterisk, (mkup.en_a_o ~ "*" ~ " $1" ~ mkup.en_a_c) ); obj_txt_in = obj_txt_in.replaceAll( rgx.inline_notes_curly_sp_plus, (mkup.en_a_o ~ "+" ~ " $1" ~ mkup.en_a_c) ); // image matched if (obj_txt_in.match(rgx.smid_image_generic)) { obj_txt_in = images(obj_txt_in); if (obj_txt_in.match(rgx.smid_mod_image_without_dimensions)) { images_without_dimensions = true; } } // url matched if (obj_txt_in.match(rgx.smid_inline_url)) { urls = true; obj_txt_in = obj_txt_in.links_and_images; } if (auto m = obj_txt_in.match(rgx.para_inline_link_anchor)) { obj_txt_in = obj_txt_in .replaceAll(rgx.para_inline_link_anchor, "┃$1┃"); } ST_txtPlusHasFootnotes ftn = footnotes_endnotes_markup_and_number_or_stars(obj_txt_in, reset_note_numbers); obj_txt_out = ftn.obj_txt; 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[1]); writeln(m.hit); } } ST_txtPlusHasFootnotesUrlsImages ret; { ret.obj_txt = obj_txt_out; ret.has_notes_reg = ftn.has_notes_reg; ret.has_notes_star = ftn.has_notes_star; ret.has_notes_plus = ftn.has_notes_plus; ret.has_urls = urls; ret.has_images_without_dimensions = images_without_dimensions; } return ret; } @safe private ST_txtPlusHasFootnotesUrlsImages object_only_()( string obj_txt_in, bool reset_note_numbers = false ) { ST_txtPlusHasFootnotesUrlsImages ret; { ret.obj_txt = obj_txt_in; ret.has_notes_reg = false; ret.has_notes_star = false; ret.has_notes_plus = false; ret.has_urls = false; ret.has_images_without_dimensions = false; } return ret; } ST_txtPlusHasFootnotesUrlsImages init() { ST_txtPlusHasFootnotesUrlsImages ret = object_notes_and_links_(""); return ret; } invariant() { } @safe ST_txtPlusHasFootnotesUrlsImages munge_heading()( string obj_txt_in, bool reset_note_numbers = false ) { obj_txt["munge"] = obj_txt_in .replaceFirst(rgx.headings, "") .replaceFirst(rgx.object_number_off_all, "") .replaceFirst(rgx.markup_inline_linebreak, mkup.br_line_inline) .strip; ST_txtPlusHasFootnotesUrlsImages ret = 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 ret; } invariant() { } @safe ST_txtPlusHasFootnotesUrlsImages munge_para()(string obj_txt_in) { obj_txt["munge"] = (obj_txt_in) .replaceFirst(rgx.para_attribs, "") .replaceFirst(rgx.object_number_off_all, "") .replaceFirst(rgx.markup_inline_linebreak, mkup.br_line_inline); ST_txtPlusHasFootnotesUrlsImages ret = object_notes_and_links_(obj_txt["munge"]); debug(munge) { writeln(__LINE__); writeln(obj_txt_in); writeln(__LINE__); writeln(obj_txt["munge"].to!string); } return ret; } @safe ST_txtPlusHasFootnotesUrlsImages munge_quote()(string obj_txt_in) { ST_txtPlusHasFootnotesUrlsImages ret = object_notes_and_links_(obj_txt_in.split("\n\n").join(" \\\\\n \\\\\n")); return ret; } invariant() { } @safe ST_txtPlusHasFootnotesUrlsImages munge_group(string obj_txt_in) { ST_txtPlusHasFootnotesUrlsImages ret = object_notes_and_links_(obj_txt_in.split("\n\n").join("\n" ~ mkup.br_line_spaced ~ "\n")); return ret; } invariant() { } @safe ST_txtPlusHasFootnotesUrlsImages munge_block()(string obj_txt_in) { ST_txtPlusHasFootnotesUrlsImages ret = object_notes_and_links_(obj_txt_in); return ret; } invariant() { } @safe auto munge_verse()(string obj_txt_in) { ST_txtPlusHasFootnotesUrlsImages ret = object_notes_and_links_(obj_txt_in); return ret; } invariant() { } @safe ST_txtPlusHasFootnotesUrlsImages munge_code()(string obj_txt_in) { obj_txt_in = obj_txt_in.replaceAll(rgx.space, mkup.nbsp); ST_txtPlusHasFootnotesUrlsImages ret = object_only_(obj_txt_in); return ret; } invariant() { } @safe ST_txtPlusHasFootnotesUrlsImages munge_table()(string obj_txt_in) { ST_txtPlusHasFootnotesUrlsImages ret = object_notes_and_links_(obj_txt_in); return ret; } invariant() { } @safe ST_txtPlusHasFootnotesUrlsImages munge_comment()(string obj_txt_in) { ST_txtPlusHasFootnotesUrlsImages ret = object_only_(obj_txt_in); return ret; } invariant() { } } static struct ObjInlineMarkup { static auto rgx = RgxI(); static auto munge = ObjInlineMarkupMunge(); string[string] obj_txt; string anchor_tag = ""; @safe ST_txtAndAnchorTagPlusHasFootnotesUrlsImages obj_inline_markup_and_anchor_tags_and_misc(CMM)( string[string] obj_, string obj_key_, CMM conf_make_meta, Flag!"_new_doc" _new_doc ) { obj_txt["munge"] = obj_[obj_key_].dup; obj_txt["munge"] = (obj_["is"].match(ctRegex!(`verse|code`))) ? obj_txt["munge"] : obj_txt["munge"].strip; if (_new_doc) { anchor_tag = ""; } auto x = munge.init; ST_txtAndAnchorTagPlusHasFootnotesUrlsImages ret; ret.obj_txt = ""; ret.anchor_tag = ""; ret.has_notes_reg = false; ret.has_notes_star = false; ret.has_notes_plus = false; ret.has_links = false; ret.has_images_without_dimensions = false; if ((obj_["is"] == "para") || (obj_["is"] == "heading") || (obj_["is"] == "quote") || (obj_["is"] == "group") || (obj_["is"] == "block") || (obj_["is"] == "verse")) { obj_txt["munge"] = (obj_txt["munge"]).inline_markup_faces; obj_txt["munge"] = (obj_txt["munge"]).links_and_images; } switch (obj_["is"]) { case "heading": if (_new_doc) { anchor_tag = ""; } obj_txt["munge"] = _configured_auto_heading_numbering_and_segment_anchor_tags(obj_txt["munge"], obj_, conf_make_meta, _new_doc); obj_txt["munge"] = _make_segment_anchor_tags_if_none_provided(obj_txt["munge"], obj_["lev"], _new_doc); if (auto m = obj_txt["munge"].match(rgx.heading_anchor_tag)) { anchor_tag = m.captures[1]; } else if (obj_["lev"] == "1") { writeln("heading anchor tag missing: ", obj_txt["munge"]); } x = munge.munge_heading(obj_txt["munge"], reset_note_numbers); reset_note_numbers = false; goto default; case "para": x = munge.munge_para(obj_txt["munge"]); goto default; case "group": x = munge.munge_group(obj_txt["munge"]); goto default; case "block": x = munge.munge_block(obj_txt["munge"]); goto default; case "quote": x = munge.munge_quote(obj_txt["munge"]); goto default; case "verse": x = munge.munge_verse(obj_txt["munge"]); goto default; case "code": x = munge.munge_code(obj_txt["munge"]); goto default; case "table": x = munge.munge_table(obj_txt["munge"]); goto default; case "comment": x = munge.munge_comment(obj_txt["munge"]); goto default; case "doc_end_reset": munge.initialize_note_numbers(); break; default: // para, heading, group, block, verse ret.obj_txt = x.obj_txt; ret.anchor_tag = anchor_tag; ret.has_notes_reg = x.has_notes_reg; ret.has_notes_star = x.has_notes_star; ret.has_notes_plus = x.has_notes_plus; ret.has_links = x.has_urls; ret.has_images_without_dimensions = x.has_images_without_dimensions; break; } anchor_tag = ""; return ret; } invariant() { } @safe auto _clean_heading_toc_()( char[] heading_toc_, ) { auto m = (cast(char[]) heading_toc_).matchFirst(rgx.heading); heading_toc_ = (m.post).replaceAll(rgx.inline_notes_curly_gen, ""); return heading_toc_; }; @safe ST_flow_table_of_contents_gather_headings flow_table_of_contents_gather_headings(CMM)( // string[string] obj_, CMM conf_make_meta, string[string] tag_in_seg, string _anchor_tag, string[][string] lev4_subtoc, ObjGenericComposite[] the_document_toc_section, ) { ObjGenericComposite comp_obj_; mixin InternalMarkup; static auto mkup = InlineMarkup(); char[] heading_toc_ = (obj_["substantive"].dup.strip.to!(char[])) .replaceAll(rgx.inline_notes_al, ""); heading_toc_ = _clean_heading_toc_(heading_toc_); auto attrib = ""; string toc_txt_, subtoc_txt_; int[string] indent; if (obj_["lev_markup_number"].to!int > 0) { indent = [ "hang_position" : obj_["lev_markup_number"].to!int, "base_position" : obj_["lev_markup_number"].to!int, ]; toc_txt_ = format("%s%s%s%s#%s%s", mkup.lnk_o, heading_toc_.strip, mkup.lnk_c, mkup.url_o, _anchor_tag, mkup.url_c, ); toc_txt_= toc_txt_.links_and_images; comp_obj_ = set_object_generic("frontmatter", "toc", "para", "toc", toc_txt_.to!string.strip, 0); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.metainfo.dummy_heading = (an_object["dummy_heading_status"] == "t") ? true: false; comp_obj_.attrib.indent_hang = indent["hang_position"]; comp_obj_.attrib.indent_base = indent["base_position"]; comp_obj_.attrib.bullet = false; comp_obj_.has.inline_links = true; the_document_toc_section ~= comp_obj_; } comp_obj_ = comp_obj_.init; comp_obj_.metainfo.is_of_part = "frontmatter"; comp_obj_.metainfo.is_of_section = "toc"; comp_obj_.metainfo.is_of_type = "para"; comp_obj_.metainfo.is_a = "toc"; comp_obj_.metainfo.ocn = 0; comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.metainfo.dummy_heading = (an_object["dummy_heading_status"] == "t") ? true: false; comp_obj_.attrib.bullet = false; comp_obj_.has.inline_links = true; switch (obj_["lev_markup_number"].to!int) { case 0: .. case 3: break; case 4: lev4_subtoc[tag_in_seg["seg_lv4"]] = []; break; case 5: .. case 7: subtoc_txt_ = format("%s%s%s%s#%s%s", mkup.lnk_o, heading_toc_.strip, mkup.lnk_c, mkup.url_o, _anchor_tag, mkup.url_c, ); lev4_subtoc[tag_in_seg["seg_lv4"]] ~= links_and_images(obj_["lev_markup_number"] ~ "~ " ~ subtoc_txt_.to!string.strip ); break; default: break; } ST_flow_table_of_contents_gather_headings ret; { ret.the_document_toc_section = the_document_toc_section; ret.lev4_subtoc = lev4_subtoc; } return ret; } invariant() { } private: static int[] heading_num = [ 0, 0, 0, 0 ]; static string heading_number_auto_composite = ""; static string heading_number_auto_composite_segname = ""; static bool[] auto_heading_numbering = [ true, true, true, true]; @safe static string _configured_auto_heading_numbering_and_segment_anchor_tags(CMM)( string munge_, string[string] obj_, CMM conf_make_meta, bool _new_doc, ) { if (_new_doc) { heading_num = [ 0, 0, 0, 0 ]; heading_number_auto_composite = ""; auto_heading_numbering = [ true, true, true, true]; } if (conf_make_meta.make.auto_num_top_lv) { if (obj_["lev_markup_number"].to!int == 0) { heading_num[0] = 0; heading_num[1] = 0; heading_num[2] = 0; heading_num[3] = 0; heading_number_auto_composite = ""; } // auto_num_depth minimum 0 // (1.) default 2 (1.1.1) max 3 (1.1.1.1) implement if ( conf_make_meta.make.auto_num_top_lv > obj_["lev_markup_number"].to!uint ) { heading_num[1] = 0; heading_num[2] = 0; heading_num[3] = 0; } else if ( conf_make_meta.make.auto_num_top_lv == obj_["lev_markup_number"].to!uint ) { auto_heading_numbering[0] = (munge_.match(rgx.auto_heading_numbering_off_lv1)) ? false : true; if (auto_heading_numbering[0]) { heading_num[0] ++; } heading_num[1] = 0; heading_num[2] = 0; heading_num[3] = 0; } else if ( conf_make_meta.make.auto_num_top_lv == (obj_["lev_markup_number"].to!uint - 1) ) { auto_heading_numbering[1] = (munge_.match(rgx.auto_heading_numbering_off_lv2)) ? false : true; if (auto_heading_numbering[0] && auto_heading_numbering[1]) { heading_num[1] ++; } heading_num[2] = 0; heading_num[3] = 0; } else if ( conf_make_meta.make.auto_num_top_lv == (obj_["lev_markup_number"].to!uint - 2) ) { auto_heading_numbering[2] = (munge_.match(rgx.auto_heading_numbering_off_lv3)) ? false : true; if (auto_heading_numbering[0] && auto_heading_numbering[1] && auto_heading_numbering[2]) { heading_num[2] ++; } heading_num[3] = 0; } else if ( conf_make_meta.make.auto_num_top_lv == (obj_["lev_markup_number"].to!uint - 3) ) { auto_heading_numbering[3] = (munge_.match(rgx.auto_heading_numbering_off_lv4)) ? false : true; if (auto_heading_numbering[0] && auto_heading_numbering[1] && auto_heading_numbering[2] && auto_heading_numbering[3]) { heading_num[3] ++; } } if (auto_heading_numbering[0]) { if (heading_num[3] > 0) { heading_number_auto_composite = (conf_make_meta.make.auto_num_depth.to!uint == 3 && auto_heading_numbering[3]) ? (format(q"┃%s.%s.%s.%s┃", heading_num[0].to!string, heading_num[1].to!string, heading_num[2].to!string, heading_num[3].to!string )) : ""; } else if (heading_num[2] > 0) { heading_number_auto_composite = ((conf_make_meta.make.auto_num_depth.to!uint >= 2) && (conf_make_meta.make.auto_num_depth.to!uint <= 3) && auto_heading_numbering[2]) ? (format(q"┃%s.%s.%s┃", heading_num[0].to!string, heading_num[1].to!string, heading_num[2].to!string )) : ""; } else if (heading_num[1] > 0) { heading_number_auto_composite = ((conf_make_meta.make.auto_num_depth.to!uint >= 1) && (conf_make_meta.make.auto_num_depth.to!uint <= 3) && auto_heading_numbering[1]) ? (format(q"┃%s.%s┃", heading_num[0].to!string, heading_num[1].to!string )) : ""; } else if (heading_num[0] > 0 && munge_.match(rgx.auto_heading_numbering_lv1) ) { heading_number_auto_composite = ((conf_make_meta.make.auto_num_depth.to!uint >= 0) && (conf_make_meta.make.auto_num_depth.to!uint <= 3) && auto_heading_numbering[0]) ? (format(q"┃%s┃", heading_num[0].to!string )) : ""; } else { heading_number_auto_composite = ""; } } heading_number_auto_composite_segname = (heading_number_auto_composite.empty) ? "" : "seg_" ~ heading_number_auto_composite; debug(heading_number_auto) { writeln(heading_number_auto_composite); } if ((!empty(heading_number_auto_composite)) && (obj_["lev_markup_number"].to!uint >= conf_make_meta.make.auto_num_top_lv)) { munge_ = munge_ .replaceFirst(rgx.heading, "$1~$2 " ~ heading_number_auto_composite ~ ". ") .replaceFirst(rgx.heading_marker_missing_tag, "$1~" ~ heading_number_auto_composite_segname ~ " "); } } return munge_; } static int heading_num_lev1 = 0; @safe static string _make_segment_anchor_tags_if_none_provided()( string munge_, string lev_, bool _new_doc ) { if (!(munge_.match(rgx.heading_anchor_tag))) { if (lev_ == "A") { // (_new_doc) heading_num_lev1 = 0; } if (munge_.match(rgx.heading_identify_anchor_tag)) { if (auto m = munge_.match(rgx.heading_extract_named_anchor_tag)) { munge_ = munge_.replaceFirst( rgx.heading_marker_missing_tag, "$1~" ~ m.captures[1].toLower ~ "_" ~ m.captures[2] ~ " "); if (auto n = munge_.match(rgx.heading_anchor_tag_plus_colon)) { auto tag_remunge_ = n.captures[2] .replaceAll(rgx.heading_marker_tag_has_colon, ".."); munge_ = munge_.replaceFirst(rgx.heading_anchor_tag_plus_colon, n.captures[1] ~ tag_remunge_ ~ " "); } } else if (auto m = munge_.match(rgx.heading_extract_unnamed_anchor_tag)) { munge_ = munge_.replaceFirst( rgx.heading_marker_missing_tag, "$1~" ~ "s" ~ m.captures[1] ~ " "); } } else if (lev_ == "1") { // (if not successful) manufacture a unique anchor tag for lev == "1" heading_num_lev1 ++; munge_ = munge_.replaceFirst( rgx.heading_marker_missing_tag, "$1~" ~ "x" ~ heading_num_lev1.to!string ~ " "); } } return munge_; } } struct ObjAttributes { string[string] _obj_attrib; @safe string obj_attributes()( string obj_is_, string obj_raw, ObjGenericComposite comp_obj_, ) { scope(exit) { destroy(obj_is_); destroy(obj_raw); destroy(comp_obj_); } _obj_attrib["json"] ="{"; switch (obj_is_) { case "heading": _obj_attrib["json"] ~= txt_heading(obj_raw); break; case "para": _obj_attrib["json"] ~= txt_para_and_blocks(obj_raw) ~ txt_para(obj_raw); break; case "code": _obj_attrib["json"] ~= txt_code(obj_raw); break; case "group": _obj_attrib["json"] ~= txt_para_and_blocks(obj_raw) ~ txt_group(obj_raw); break; case "block": _obj_attrib["json"] ~= txt_para_and_blocks(obj_raw) ~ txt_block(obj_raw); break; case "verse": _obj_attrib["json"] ~= txt_verse(obj_raw); break; case "quote": _obj_attrib["json"] ~= txt_quote(obj_raw); break; case "table": _obj_attrib["json"] ~= txt_table(obj_raw); break; case "comment": _obj_attrib["json"] ~= txt_comment(obj_raw); break; default: _obj_attrib["json"] ~= txt_para(obj_raw); break; } _obj_attrib["json"] ~= " }"; _obj_attrib["json"] = _set_additional_values_parse_as_json(_obj_attrib["json"], obj_is_, comp_obj_); debug(structattrib) { if (oa_j["is"].str() == "heading") { writeln(_obj_attrib["json"]); writeln( "is: ", oa_j["is"].str(), "; object_number: ", oa_j["object_number"].integer() ); } } return _obj_attrib["json"]; } invariant() { } private: string _obj_attributes; @safe string txt_para_and_blocks()(string obj_txt_in) { 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["indent"].to!string ~ "," ~ " \"indent_base\": " ~ m["indent"].to!string ~ ","; } else if (auto m = obj_txt_in.matchFirst(rgx.para_indent_hang)) { _obj_attributes =" \"bullet\": \"false\"," ~ " \"indent_hang\": " ~ m["hang"].to!string ~ "," ~ " \"indent_base\": " ~ m["indent"].to!string ~ ","; } else if (auto m = obj_txt_in.matchFirst(rgx.para_indent)) { _obj_attributes =" \"bullet\": \"false\"," ~ " \"indent_hang\": " ~ m["indent"].to!string ~ "," ~ " \"indent_base\": " ~ m["indent"].to!string ~ ","; } else { _obj_attributes =" \"bullet\": \"false\"," ~ " \"indent_hang\": 0," ~ " \"indent_base\": 0,"; } return _obj_attributes; } @safe string txt_heading()(string obj_txt_in) { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"para\"," ~ " \"is\": \"heading\""; return _obj_attributes; } invariant() { } @safe string txt_para()(string obj_txt_in) { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"para\"," ~ " \"is\": \"para\""; return _obj_attributes; } invariant() { } @safe string txt_quote()(string obj_txt_in) { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"quote\""; return _obj_attributes; } invariant() { } @safe string txt_group()(string obj_txt_in) { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"group\""; return _obj_attributes; } invariant() { } @safe string txt_block()(string obj_txt_in) { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"block\""; return _obj_attributes; } invariant() { } @safe string txt_verse()(string obj_txt_in) { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"verse\""; return _obj_attributes; } invariant() { } @safe string txt_code()(string obj_txt_in) { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"code\""; return _obj_attributes; } invariant() { } @safe string txt_table()(string obj_txt_in) { _obj_attributes = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"table\""; return _obj_attributes; } invariant() { } @safe string txt_comment()(string obj_txt_in) { _obj_attributes = " \"use\": \"comment\"," ~ " \"of\": \"comment\"," ~ " \"is\": \"comment\""; return _obj_attributes; } invariant() { } @safe string _set_additional_values_parse_as_json()( string _obj_attrib, string obj_is_, ObjGenericComposite comp_obj_, ) { JSONValue oa_j = parseJSON(_obj_attrib); assert( (oa_j.type == JSON_TYPE.OBJECT) ); if (obj_is_ == "heading") { oa_j.object["object_number"] = comp_obj_.metainfo.ocn; oa_j.object["lev_markup_number"] = comp_obj_.metainfo.heading_lev_markup; oa_j.object["lev_collapsed_number"] = comp_obj_.metainfo.heading_lev_collapsed; oa_j.object["heading_ptr"] = comp_obj_.ptr.heading; oa_j.object["doc_object_ptr"] = comp_obj_.ptr.doc_object; } oa_j.object["parent_object_number"] = comp_obj_.metainfo.parent_ocn; oa_j.object["parent_lev_markup_number"] = comp_obj_.metainfo.parent_lev_markup; _obj_attrib = oa_j.toString(); return _obj_attrib; } } struct BookIndexNuggetHash { string main_term, sub_term, sub_term_bits; int object_number_offset, object_number_endpoint; string[] object_numbers; string[][string][string] bi_hash_nugget; string[] bi_main_terms_split_arr; @safe string[][string][string] bookindex_nugget_hash(S)( string bookindex_section, OCNset obj_cite_digits, S tag_in_seg, ) { debug(asserts) { static assert(is(typeof(obj_cite_digits.object_number) == int)); } debug(bookindexraw) { if (!bookindex_section.empty) { writeln( "* [bookindex] ", "[", obj_cite_digits.object_number.to!string, ": ", tag_in_seg["seg_lv4"], "] ", bookindex_section, " - - - ", "[", obj_cite_digits.object_number.to!string, "] ", bookindex_section ); } } static auto rgx = RgxI(); if (!bookindex_section.empty) { auto bi_main_terms_split_arr = bookindex_section.split(rgx.bi_main_terms_split); foreach (bi_main_terms_content; bi_main_terms_split_arr) { auto bi_main_term_and_rest = bi_main_terms_content.split(rgx.bi_main_term_plus_rest_split); if (auto m = bi_main_term_and_rest[0].match( rgx.bi_term_and_object_numbers_match) ) { main_term = m.captures[1].strip; object_number_offset = m.captures[2].to!int; object_number_endpoint = (obj_cite_digits.object_number + object_number_offset); object_numbers ~= (obj_cite_digits.object_number.to!string ~ "-" ~ object_number_endpoint.to!string); } else { main_term = bi_main_term_and_rest[0].strip; object_numbers ~= obj_cite_digits.object_number.to!string; } bi_hash_nugget[main_term]["_a"] ~= object_numbers; object_numbers = null; if (bi_main_term_and_rest.length > 1) { auto bi_sub_terms_split_arr = bi_main_term_and_rest[1].split( rgx.bi_sub_terms_plus_object_number_offset_split ); foreach (sub_terms_bits; bi_sub_terms_split_arr) { if (auto m = sub_terms_bits.match(rgx.bi_term_and_object_numbers_match)) { sub_term = m.captures[1].strip; object_number_offset = m.captures[2].to!int; object_number_endpoint = (obj_cite_digits.object_number + object_number_offset); object_numbers ~= (obj_cite_digits.object_number.to!string ~ " - " ~ object_number_endpoint.to!string); } else { sub_term = sub_terms_bits.strip; object_numbers ~= obj_cite_digits.object_number.to!string; } if (!empty(sub_term)) { bi_hash_nugget[main_term][sub_term] ~= object_numbers; } object_numbers = null; } } } } return bi_hash_nugget; } invariant() { } } struct BookIndexReportIndent { int mkn, skn; @safe void bookindex_report_indented()( string[][string][string] bookindex_unordered_hashes ) { 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; } } } struct BookIndexReportSection { int mkn, skn; static auto rgx = RgxI(); static auto munge = ObjInlineMarkupMunge(); @safe void bookindex_write_section()( string[][string][string] bookindex_unordered_hashes ) { auto mainkeys = bookindex_unordered_hashes.byKey.array .sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable).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!("toUpper(a) < toUpper(b)", SwapStrategy.stable).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; } } @system ST_bookindex backmatter_bookindex_build_abstraction_section(B)( string[][string][string] bookindex_unordered_hashes, OCNset obj_cite_digits, B opt_action, ) { debug(asserts) { static assert(is(typeof(obj_cite_digits.object_number) == int)); } mixin spineNode; mixin InternalMarkup; static auto mkup = InlineMarkup(); string type_is; string lev; int heading_lev_markup, heading_lev_collapsed; string attrib; int[string] indent; auto mainkeys = bookindex_unordered_hashes.byKey.array .sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable).release; ObjGenericComposite[] bookindex_section; ObjGenericComposite comp_obj_; auto node_para_int_ = node_metadata_para_int; auto node_para_str_ = node_metadata_para_str; if ((mainkeys.length > 0) && (opt_action.backmatter && opt_action.section_bookindex)) { string bi_tmp; string[] bi_tmp_tags; { comp_obj_ = set_object_heading("lev1", "backmatter", "bookindex", "Book Index"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = false; comp_obj_.metainfo.object_number_off = false; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "_part_book_index"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = "bookindex"; comp_obj_.tags.anchor_tags = ["section_bookindex"]; comp_obj_.has.inline_links = true; bookindex_section ~= comp_obj_; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; ++mkn; } { comp_obj_ = set_object_heading("lev4", "backmatter", "bookindex", "Index"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = true; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "bookindex"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = comp_obj_.tags.anchor_tag_html; comp_obj_.metainfo.heading_lev_collapsed = 2; comp_obj_.has.inline_links = false; comp_obj_.tags.anchor_tags = ["bookindex"]; bookindex_section ~= comp_obj_; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; ++mkn; } import std.array : appender; auto buffer = appender!(char[])(); string[dchar] transTable = [' ' : "_"]; foreach (mainkey; mainkeys) { bi_tmp_tags = [""]; bi_tmp = mkup.ff_i ~ mkup.bold ~ mkup.ff_o ~ mainkey ~ mkup.ff_c ~ mkup.bold ~ " "; buffer.clear(); bi_tmp_tags ~= translate(mainkey, transTable); auto bkidx_lnk(string locs) { string markup = ""; if (auto m = locs.matchFirst(rgx.book_index_go)) { markup = links_and_images("{ " ~ m["link"] ~ " }" ~ "#" ~ m["ocn"] ~ ", "); } else { writeln(__LINE__, ": ", locs); } return markup; } foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { bi_tmp ~= bkidx_lnk(ref_); } bi_tmp ~= " \\\\\n "; bookindex_unordered_hashes[mainkey].remove("_a"); auto subkeys = bookindex_unordered_hashes[mainkey].byKey.array .sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable).release; foreach (subkey; subkeys) { bi_tmp ~= subkey ~ ", "; buffer.clear(); bi_tmp_tags ~= translate(subkey, transTable); foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { bi_tmp ~= bkidx_lnk(ref_); } bi_tmp ~= " \\\\\n "; ++skn; } bi_tmp = bi_tmp.replaceFirst(rgx.trailing_linebreak, ""); comp_obj_ = set_object_generic("backmatter", "bookindex", "para", "bookindex", bi_tmp.to!string.strip, 0); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.anchor_tags = bi_tmp_tags; comp_obj_.attrib.indent_hang = 0; comp_obj_.attrib.indent_base = 1; comp_obj_.attrib.bullet = false; comp_obj_.has.inline_links = true; comp_obj_.text = bi_tmp.to!string.strip; bookindex_section ~= comp_obj_; ++mkn; } } else { // no book index, (figure out what to do here) comp_obj_ = set_object_heading("lev1", "backmatter", "bookindex", "(skip) there is no Book Index"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = true; comp_obj_.metainfo.object_number_off = true; bookindex_section ~= comp_obj_; } ST_bookindex ret; { ret.bookindex = bookindex_section; ret.ocn = obj_cite_digits; } return ret; } } struct NotesSection { string[string] object_notes; int previous_count; int mkn; static auto rgx = RgxI(); @safe private auto gather_notes_for_endnote_section( ObjGenericComposite[] contents_am, string[string] tag_in_seg, int cntr, ) { assert((contents_am[cntr].metainfo.is_a == "para") || (contents_am[cntr].metainfo.is_a == "heading") || (contents_am[cntr].metainfo.is_a == "quote") || (contents_am[cntr].metainfo.is_a == "group") || (contents_am[cntr].metainfo.is_a == "block") || (contents_am[cntr].metainfo.is_a == "verse")); assert(cntr >= previous_count); assert( (contents_am[cntr].text).match( rgx.inline_notes_al_all_note) ); mixin InternalMarkup; previous_count = cntr; static auto mkup = InlineMarkup(); static auto munge = ObjInlineMarkupMunge(); foreach(m; (contents_am[cntr].text).matchAll( rgx.inline_notes_al_special_char_note) ) { debug(endnotes_build) { writeln( "{", mkup.ff_i, mkup.superscript, mkup.ff_o, m["char"], ".", mkup.ff_c, mkup.superscript, "}" ~ mkup.mark_internal_site_lnk, tag_in_seg["seg_lv4"], ".fnSuffix#noteref_\n ", m["char"], " ", m["note"]); // sometimes need segment name (segmented html & epub) } // you need anchor for segments at this point -> object_notes["anchor"] ~= "note_" ~ m["char"] ~ "』"; object_notes["notes"] ~= (tag_in_seg["seg_lv4"].empty) ? (links_and_images( "{" ~ mkup.ff_i ~ mkup.superscript ~ mkup.ff_o ~ m["char"] ~ "." ~ mkup.ff_c ~ mkup.superscript ~ "}#noteref_" ~ m["char"]) ~ " " ~ m["note"] ~ "』" ) : (links_and_images( "{" ~ mkup.ff_i ~ mkup.superscript ~ mkup.ff_o ~ m["char"] ~ "." ~ mkup.ff_c ~ mkup.superscript ~ "}" ~ mkup.mark_internal_site_lnk ~ tag_in_seg["seg_lv4"] ~ ".fnSuffix#noteref_" ~ m["char"]) ~ " " ~ m["note"] ~ "』" ); } foreach(m; (contents_am[cntr].text).matchAll( rgx.inline_notes_al_regular_number_note) ) { debug(endnotes_build) { writeln( "{", mkup.ff_i, mkup.superscipt, mkup.ff_o, m["num"], ".", mkup.ff_c, mkup.superscipt, "}" ~ mkup.mark_internal_site_lnk, tag_in_seg["seg_lv4"], ".fnSuffix#noteref_\n ", m["num"], " ", m["note"]); // sometimes need segment name (segmented html & epub) } // you need anchor for segments at this point -> object_notes["anchor"] ~= "note_" ~ m["num"] ~ "』"; object_notes["notes"] ~= (tag_in_seg["seg_lv4"].empty) ? (links_and_images( "{" ~ mkup.ff_i ~ mkup.superscript ~ mkup.ff_o ~ m["num"] ~ "." ~ mkup.ff_c ~ mkup.superscript ~ "}#noteref_" ~ m["num"]) ~ " " ~ m["note"] ~ "』" ) : (links_and_images( "{" ~ mkup.ff_i ~ mkup.superscript ~ mkup.ff_o ~ m["num"] ~ "." ~ mkup.ff_c ~ mkup.superscript ~ "}" ~ mkup.mark_internal_site_lnk ~ tag_in_seg["seg_lv4"] ~ ".fnSuffix#noteref_" ~ m["num"]) ~ " " ~ m["note"] ~ "』" ); } return object_notes; } @safe private auto gathered_notes() { 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_; } @safe private ST_endnotes backmatter_endnote_objects(O)( OCNset obj_cite_digits, O opt_action, ) { mixin spineNode; ObjGenericComposite[] the_document_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_; if ((endnotes_["notes"].length > 0) && (opt_action.backmatter && opt_action.section_endnotes)) { { comp_obj_ = set_object_heading("lev1", "backmatter", "endnotes", "Endnotes"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = false; comp_obj_.metainfo.object_number_off = false; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "_part_endnotes"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = "endnotes"; comp_obj_.tags.anchor_tags = ["section_endnotes"]; the_document_endnotes_section ~= comp_obj_; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; ++mkn; } { comp_obj_ = set_object_heading("lev4", "backmatter", "endnotes", "Endnotes"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = true; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "endnotes"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = comp_obj_.tags.anchor_tag_html; comp_obj_.tags.anchor_tags = ["endnotes"]; the_document_endnotes_section ~= comp_obj_; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; ++mkn; } } else { comp_obj_ = set_object_heading("lev1", "empty", "empty", "(skip) there are no Endnotes"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = true; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; the_document_endnotes_section ~= comp_obj_; } if (opt_action.backmatter && opt_action.section_endnotes) { ObjGenericComposite comp_obj_endnote_; comp_obj_endnote_ = set_object_generic("backmatter", "endnotes", "para", "endnote", "", 0); comp_obj_endnote_.metainfo.identifier = ""; // comp_obj_.metainfo.dummy_heading = false; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_endnote_.attrib.indent_hang = 0; comp_obj_endnote_.attrib.indent_base = 0; comp_obj_endnote_.attrib.bullet = false; foreach (i, endnote; endnotes_["notes"]) { auto m = endnote.matchFirst(rgx.note_ref); string notenumber = m["ref"].to!string; string anchor_tag = "note_" ~ notenumber; comp_obj_endnote_.tags.anchor_tags = [ endnotes_["anchor"][i] ]; comp_obj_endnote_.has.inline_links = true; comp_obj_endnote_.text = endnote.inline_markup_faces.strip; the_document_endnotes_section ~= comp_obj_endnote_; } } ST_endnotes ret; { ret.endnotes = the_document_endnotes_section; ret.ocn = obj_cite_digits; } return ret; } } @system public ST_biblio_section backmatter_make_the_bibliography_section()( string[] biblio_unsorted_incomplete, JSONValue[] bib_arr_json, ) { Bibliography biblio = Bibliography(); ObjGenericComposite comp_obj_; static auto mkup = InlineMarkup(); ST_flow_bibliography _get = biblio.flow_bibliography_(biblio_unsorted_incomplete, bib_arr_json); JSONValue[] biblio_ordered; biblio_ordered = _get.biblio_sorted; if (biblio_ordered.length > 0) { { comp_obj_ = set_object_heading("lev1", "backmatter", "bibliography", "Bibliography"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = false; comp_obj_.metainfo.object_number_off = false; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "_part_bibliography"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = "bibliography"; comp_obj_.tags.anchor_tags = ["section_bibliography"]; comp_obj_.metainfo.dom_structure_markedup_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; comp_obj_.metainfo.dom_structure_collapsed_tags_status = [ 1, 1, 0, 0, 0, 0, 0, 0]; the_document_bibliography_section ~= comp_obj_; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; } { comp_obj_ = set_object_heading("lev4", "backmatter", "bibliography", "Bibliography"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = true; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.tags.segment_anchor_tag_epub = "bibliography"; comp_obj_.tags.anchor_tag_html = comp_obj_.tags.segment_anchor_tag_epub; comp_obj_.tags.in_segment_html = comp_obj_.tags.anchor_tag_html; comp_obj_.tags.anchor_tags = ["bibliography"]; the_document_bibliography_section ~= comp_obj_; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; } { 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) ? "" : ", " ~ mkup.ff_i ~ mkup.italic ~ mkup.ff_o ~ entry["journal"].str ~ mkup.ff_c ~ mkup.italic), ((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_ = set_object_generic("backmatter", "bibliography", "para", "bibliography", out_.to!string.strip, 0); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.attrib.indent_hang = 0; comp_obj_.attrib.indent_base = 1; comp_obj_.attrib.bullet = bullet; comp_obj_.tags.anchor_tags = [anchor_tag]; the_document_bibliography_section ~= comp_obj_; } } } else { comp_obj_ = set_object_heading("lev1", "empty", "empty", "(skip) there is no Bibliography"); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.dummy_heading = true; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; the_document_bibliography_section ~= comp_obj_; } debug(bibliosection) { foreach (o; the_document_bibliography_section) { writeln(o.text); } } ST_biblio_section ret; { ret.bibliography_section = the_document_bibliography_section; ret.tag_assoc = tag_assoc; // } return ret; } struct Bibliography { @system public ST_flow_bibliography flow_bibliography_()( string[] biblio_unsorted_incomplete, JSONValue[] bib_arr_json ) { JSONValue[] biblio_unsorted = biblio_make_unsorted_array_of_json_objects(biblio_unsorted_incomplete, bib_arr_json); // TODO lookat returns biblio_arr_json = []; biblio_unsorted_incomplete = []; JSONValue[] biblio_sorted__ = biblio_sort(biblio_unsorted); debug(biblio0) { biblio_debug(biblio_sorted__); 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++; } } ST_flow_bibliography ret; { ret.biblio_sorted = biblio_sorted__; ret.bib_arr_json = bib_arr_json; ret.biblio_unsorted_incomplete = biblio_unsorted_incomplete; } return ret; } @system final private JSONValue[] biblio_make_unsorted_array_of_json_objects()( string[] biblio_unordered, JSONValue[] bib_arr_json ) { foreach (bibent; biblio_unordered) { // update bib to include deemed_author, needed for: // sort_bibliography_array_by_deemed_author_year_title // either: sort on multiple fields, or; create such sort field JSONValue j = parseJSON(bibent); if (!empty(j["fulltitle"].str)) { if (!empty(j["author_raw"].str)) { j["deemed_author"] = j["author_arr"][0]; } else if (!empty(j["editor_raw"].str)) { j["deemed_author"] = j["editor_arr"][0]; } j["sortby_deemed_author_year_title"] = ( j["deemed_author"].str ~ "; " ~ j["year"].str ~ "; " ~ j["fulltitle"].str ); } bib_arr_json ~= j; } return bib_arr_json.dup; } @system final private JSONValue[] biblio_sort()(JSONValue[] biblio_unordered) { JSONValue[] biblio_sorted_; biblio_sorted_ = sort!((a, b){ return ((a["sortby_deemed_author_year_title"].str) < (b["sortby_deemed_author_year_title"].str)); })(biblio_unordered).array; debug(bibliosorted) { foreach (j; biblio_sorted_) { if (!empty(j["fulltitle"].str)) { writeln(j["sortby_deemed_author_year_title"]); } } } return biblio_sorted_; } @system void biblio_debug()(JSONValue[] biblio_sorted) { debug(biblio0) { foreach (j; biblio_sorted) { if (!empty(j["fulltitle"].str)) { writeln(j["sortby_deemed_author_year_title"]); } } } } } @system public ObjGenericComposite[] backmatter_gather_table_of_contents( ObjGenericComposite[] the_document_endnotes_section, ObjGenericComposite[] the_document_glossary_section, ObjGenericComposite[] the_document_bibliography_section, ObjGenericComposite[] the_document_bookindex_section, ObjGenericComposite[] the_document_blurb_section, ) { ObjGenericComposite[] toc_section_backmatter; string toc_txt_; static auto mkup = InlineMarkup(); ObjGenericComposite comp_obj_; int[string] indent = [ "hang_position" : 1, "base_position" : 1, ]; comp_obj_ = set_object_generic("frontmatter", "toc", "para", "toc", "", 0); comp_obj_.metainfo.identifier = ""; comp_obj_.metainfo.object_number_off = true; comp_obj_.metainfo.object_number_type = 0; comp_obj_.attrib.indent_hang = indent["hang_position"]; comp_obj_.attrib.indent_base = indent["base_position"]; comp_obj_.attrib.bullet = false; if (the_document_endnotes_section.length > 1) { toc_txt_ = format("%s%s%s%s#%s%s", mkup.lnk_o, "Endnotes", mkup.lnk_c, mkup.url_o, "endnotes", mkup.url_c, ); toc_txt_= toc_txt_.links_and_images; comp_obj_.text = toc_txt_.to!string.strip; comp_obj_.has.inline_links = true; toc_section_backmatter ~= comp_obj_; } if (the_document_glossary_section.length > 1) { toc_txt_ = format("%s%s%s%s#%s%s", mkup.lnk_o, "Glossary", mkup.lnk_c, mkup.url_o, "glossary", mkup.url_c, ); toc_txt_= toc_txt_.links_and_images; comp_obj_.text = toc_txt_.to!string.strip; comp_obj_.has.inline_links = true; toc_section_backmatter ~= comp_obj_; } if (the_document_bibliography_section.length > 1){ toc_txt_ = format("%s%s%s%s#%s%s", mkup.lnk_o, "Bibliography", mkup.lnk_c, mkup.url_o, "bibliography", mkup.url_c, ); toc_txt_= toc_txt_.links_and_images; comp_obj_.text = toc_txt_.to!string.strip; comp_obj_.has.inline_links = true; toc_section_backmatter ~= comp_obj_; } if (the_document_bookindex_section.length > 1) { toc_txt_ = format("%s%s%s%s#%s%s", mkup.lnk_o, "Book Index", mkup.lnk_c, mkup.url_o, "bookindex", mkup.url_c, ); toc_txt_= toc_txt_.links_and_images; comp_obj_.text = toc_txt_.to!string.strip; comp_obj_.has.inline_links = true; toc_section_backmatter ~= comp_obj_; } if (the_document_blurb_section.length > 1) { toc_txt_ = format("%s%s%s%s#%s%s", mkup.lnk_o, "Blurb", mkup.lnk_c, mkup.url_o, "blurb", mkup.url_c, ); toc_txt_= toc_txt_.links_and_images; comp_obj_.has.inline_links = true; comp_obj_.text = toc_txt_.to!string.strip; toc_section_backmatter ~= comp_obj_; } debug(toc) { writefln( "%s %s", __LINE__,); foreach (toc_linked_heading; toc_section_backmatter) { writeln(mkup.indent_by_spaces_provided(toc_linked_heading.attrib.indent_hang), toc_linked_heading.text); } } return toc_section_backmatter; } @system public ST_ancestors after_doc_determine_ancestors( ObjGenericComposite[] the_document_body_section, ObjGenericComposite[] the_document_endnotes_section, ObjGenericComposite[] the_document_glossary_section, ObjGenericComposite[] the_document_bibliography_section, ObjGenericComposite[] the_document_bookindex_section, ObjGenericComposite[] the_document_blurb_section, ) { @safe int[] _get_ancestors_markup(ObjGenericComposite obj, int[] _ancestors_markup) { if (obj.metainfo.is_a == "heading") { debug(dom) { writeln(obj.text); } if (obj.metainfo.heading_lev_markup == 1) { _ancestors_markup = [ _ancestors_markup[0], 0,0,0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_markup == 2) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], 0,0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_markup == 3) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], 0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_markup == 4) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], _ancestors_markup[3], 0,0,0,0 ]; } if (obj.metainfo.heading_lev_markup == 5) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], _ancestors_markup[3], _ancestors_markup[4], 0,0,0 ]; } if (obj.metainfo.heading_lev_markup == 6) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], _ancestors_markup[3], _ancestors_markup[4], _ancestors_markup[5], 0,0 ]; } if (obj.metainfo.heading_lev_markup == 7) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], _ancestors_markup[3], _ancestors_markup[4], _ancestors_markup[5], _ancestors_markup[6], 0 ]; } if (obj.metainfo.heading_lev_markup == 8) { _ancestors_markup = [ _ancestors_markup[0], _ancestors_markup[1], _ancestors_markup[2], _ancestors_markup[3], _ancestors_markup[4], _ancestors_markup[5], _ancestors_markup[6], _ancestors_markup[7] ]; } _ancestors_markup[obj.metainfo.heading_lev_markup] = obj.metainfo.ocn; } debug(ancestor_markup) { writeln("marked up: ", _ancestors_markup); } return _ancestors_markup; } @safe int[] _get_ancestors_collapsed(ObjGenericComposite obj, int[] _ancestors_collapsed) { if (obj.metainfo.is_a == "heading") { if (obj.metainfo.heading_lev_collapsed == 1) { _ancestors_collapsed = [ _ancestors_collapsed[0], 0,0,0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 2) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], 0,0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 3) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], 0,0,0,0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 4) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], _ancestors_collapsed[3], 0,0,0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 5) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], _ancestors_collapsed[3], _ancestors_collapsed[4], 0,0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 6) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], _ancestors_collapsed[3], _ancestors_collapsed[4], _ancestors_collapsed[5], 0,0 ]; } if (obj.metainfo.heading_lev_collapsed == 7) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], _ancestors_collapsed[3], _ancestors_collapsed[4], _ancestors_collapsed[5], _ancestors_collapsed[6], 0 ]; } if (obj.metainfo.heading_lev_collapsed == 8) { _ancestors_collapsed = [ _ancestors_collapsed[0], _ancestors_collapsed[1], _ancestors_collapsed[2], _ancestors_collapsed[3], _ancestors_collapsed[4], _ancestors_collapsed[5], _ancestors_collapsed[6], _ancestors_collapsed[7] ]; } _ancestors_collapsed[obj.metainfo.heading_lev_collapsed] = obj.metainfo.ocn; } debug(ancestor_collapsed) { writeln("collapsed: ", _ancestors_collapsed); } return _ancestors_collapsed; } // multiple 1~ levels, loop through document body if (the_document_body_section.length > 1) { int[] _ancestors_markup = [0,0,0,0,0,0,0,0]; int[][] _ancestors_markup_; _ancestors_markup = [1,0,0,0,0,0,0,0]; _ancestors_markup_ ~= _ancestors_markup; int[] _ancestors_collapsed = [0,0,0,0,0,0,0,0]; int[][] _ancestors_collapsed_; _ancestors_collapsed = [1,0,0,0,0,0,0,0]; _ancestors_collapsed_ ~= _ancestors_collapsed; foreach (ref obj; the_document_body_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.markedup_ancestors = _get_ancestors_markup(obj, _ancestors_markup); obj.metainfo.collapsed_ancestors = _get_ancestors_collapsed(obj, _ancestors_collapsed); obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } } debug(ancestors) { writeln("ancestors markup o_n: ", obj.metainfo.markedup_ancestors); writeln("ancestors collapsed o_n: ", obj.metainfo.markedup_ancestors); } } ST_ancestors ret; ret.the_document_body_section = the_document_body_section; ret.the_document_endnotes_section = the_document_endnotes_section; ret.the_document_glossary_section = the_document_glossary_section; ret.the_document_bibliography_section = the_document_bibliography_section; ret.the_document_bookindex_section = the_document_bookindex_section; ret.the_document_blurb_section = the_document_blurb_section; return ret; } @system public ST_segnames after_doc_determine_segnames( ObjGenericComposite[] the_document_body_section, ObjGenericComposite[] the_document_endnotes_section, ObjGenericComposite[] the_document_glossary_section, ObjGenericComposite[] the_document_bibliography_section, ObjGenericComposite[] the_document_bookindex_section, ObjGenericComposite[] the_document_blurb_section, string[][string] segnames, int html_segnames_ptr_cntr, int html_segnames_ptr, ) { if (the_document_endnotes_section.length > 1) { segnames["html"] ~= "endnotes"; segnames["epub"] ~= "endnotes"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref obj; the_document_endnotes_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } if (obj.metainfo.heading_lev_markup == 4) { obj.ptr.html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_document_glossary_section.length > 1) { segnames["html"] ~= "glossary"; segnames["epub"] ~= "glossary"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref obj; the_document_glossary_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } if (obj.metainfo.heading_lev_markup == 4) { obj.ptr.html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_document_bibliography_section.length > 1) { segnames["html"] ~= "bibliography"; segnames["epub"] ~= "bibliography"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref obj; the_document_bibliography_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } if (obj.metainfo.heading_lev_markup == 4) { obj.ptr.html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_document_bookindex_section.length > 1) { segnames["html"] ~= "bookindex"; segnames["epub"] ~= "bookindex"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref obj; the_document_bookindex_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } if (obj.metainfo.heading_lev_markup == 4) { obj.ptr.html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } if (the_document_blurb_section.length > 1) { segnames["html"] ~= "blurb"; segnames["epub"] ~= "blurb"; html_segnames_ptr = html_segnames_ptr_cntr; foreach (ref obj; the_document_blurb_section) { if (obj.metainfo.is_a == "heading") { obj.metainfo.parent_ocn = obj.metainfo.markedup_ancestors[obj.metainfo.parent_lev_markup]; } if (obj.metainfo.heading_lev_markup == 4) { obj.ptr.html_segnames = html_segnames_ptr; break; } } html_segnames_ptr_cntr++; } ST_segnames ret; ret.segnames = segnames; ret.html_segnames_ptr_cntr = html_segnames_ptr_cntr; ret.html_segnames_ptr = html_segnames_ptr; return ret; } // decendants @safe auto after_doc_get_decendants()(ObjGenericComposite[] document_sections) { int[string] _heading_ocn_decendants; string[] _ocn_open_key = ["","","","","","","",""]; auto _doc_sect_length = document_sections.length - 1; int _last_ocn; foreach (_lg, ref obj; document_sections) { if (obj.metainfo.is_a == "heading") { foreach (_dts_lv, dom_tag_status; obj.metainfo.dom_structure_markedup_tags_status) { switch (dom_tag_status) with (DomTags) { case none: break; case open: _ocn_open_key[_dts_lv] = (obj.metainfo.ocn).to!string; _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn; break; case close: if (_ocn_open_key[_dts_lv].empty) { _ocn_open_key[_dts_lv] = "0"; } _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn - 1; _ocn_open_key[_dts_lv] = (0).to!string; break; case close_and_open: if (_ocn_open_key[_dts_lv].empty) { _ocn_open_key[_dts_lv] = "0"; } _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn - 1; _ocn_open_key[_dts_lv] = (obj.metainfo.ocn).to!string; _heading_ocn_decendants[_ocn_open_key[_dts_lv]] = obj.metainfo.ocn; break; case open_still: break; default: break; } } } if (obj.metainfo.ocn > 0) { _last_ocn = obj.metainfo.ocn; } if (_lg == _doc_sect_length) { _heading_ocn_decendants["1"] = _last_ocn; // close existing o_n key } } Tuple!(int, int)[] pairs; foreach (pair; _heading_ocn_decendants.byPair) { pairs ~= tuple(pair[0].to!int, pair[1]); } return pairs.sort; } @safe string[] extract_images()(string content_block) { static auto rgx = RgxI(); string[] images_; if (auto m = content_block.matchAll(rgx.image)) { images_ ~= m.captures[1]; } return images_; } @system auto _image_dimensions(O,M)(O obj, M manifested) { static auto rgx = RgxI(); if (obj.has.image_without_dimensions) { import std.math; import imageformats; int w, h, chans; real _w, _h; int max_width = 640; foreach (img; obj.text.matchAll(rgx.inline_image_without_dimensions)) { try { read_image_info(manifested.src.image_dir_path ~ "/" ~ img["img"], w, h, chans); } catch (Exception ex) { writeln("WARNING, image not found: ", img["img"], "\n ", manifested.src.image_dir_path ~ "/" ~ img["img"]); } // calculate, decide max width and proportionally reduce to keep w & h within it debug(images) { writeln("width: ", w, ", height: ", h); } if (w > max_width) { _w = max_width; _h = round((max_width / w.to!real) * h.to!real); } else { _w = w; _h = h; } obj.text = obj.text.replaceFirst( rgx.inline_image_without_dimensions, format(q"┃%s☼%s,w%sh%s %s┃", "$1", "$3", _w.to!string, _h.to!string, "$6", ) ); } debug(images) { writeln("image without dimensions: ", obj.text); } } return obj; } // links @safe auto _links(O)(O obj) { static auto rgx = RgxI(); if (auto m = obj.text.match(rgx.inline_link_stow_uri)) { debug(links) { writeln("number of link matches to stow: ", (obj.text.match(rgx.inline_link_stow_uri)).count); writeln("links to stow: ", (obj.text.match(rgx.inline_link_stow_uri))); } int _n_matches = (obj.text.match(rgx.inline_link_stow_uri)).count.to!int; for(int i = 0; i < _n_matches; ++i) { if (obj.text.match(rgx.inline_link_stow_uri)) { obj.stow.link ~= obj.text.matchFirst(rgx.inline_link_stow_uri)[2]; obj.text = obj.text.replaceFirst( rgx.inline_link_stow_uri, format(q"┃┥%s┝┤%s├┃", "$1", i) ); } } } return obj; } struct NodeStructureMetadata { int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7; int obj_cite_digit; int[string] p_; // p_ parent_ static auto rgx = RgxI(); @safe ObjGenericComposite node_location_emitter(La,Ta)( string lev_markup_number, string[string] tag_in_seg, La lev_anchor_tag, Ta tag_assoc, OCNset obj_cite_digits, int cntr_, int ptr_, string is_ ) { debug(asserts) { static assert(is(typeof(obj_cite_digits.object_number) == int)); } assert(is_ != "heading"); assert(obj_cite_digits.object_number.to!int >= 0); assert(is_ != "heading"); // should not be necessary assert(obj_cite_digits.object_number.to!int >= 0); // should not be necessary if (lv7 > eN.bi.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_4; p_["object_number"] = lv7; } else if (lv6 > eN.bi.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3; p_["object_number"] = lv6; } else if (lv5 > eN.bi.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2; p_["object_number"] = lv5; } else { p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1; p_["object_number"] = lv4; } ObjGenericComposite comp_obj_location; comp_obj_location = comp_obj_location.init; comp_obj_location.metainfo.is_a = is_; comp_obj_location.metainfo.ocn = obj_cite_digits.object_number; comp_obj_location.metainfo.identifier = obj_cite_digits.identifier; comp_obj_location.tags.anchor_tag_html = tag_in_seg["seg_lv4"]; comp_obj_location.tags.segment_anchor_tag_epub = tag_in_seg["seg_lv1to4"]; comp_obj_location.tags.heading_lev_anchor_tag = lev_anchor_tag; comp_obj_location.metainfo.parent_ocn = p_["object_number"]; comp_obj_location.metainfo.parent_lev_markup = p_["lev_markup_number"]; debug(_node) { if (lev_markup_number.match(rgx.levels_numbered_headings)) { writeln("x ", _node.to!string); } else { writeln("- ", _node.to!string); } } assert(comp_obj_location.metainfo.parent_lev_markup >= 4); assert(comp_obj_location.metainfo.parent_lev_markup <= 7); assert(comp_obj_location.metainfo.parent_ocn >= 0); return comp_obj_location; } invariant() { } @safe ObjGenericComposite node_emitter_heading(O,TaL,TA,SOAT)( O an_object, string[string] tag_in_seg, TaL lev_anchor_tag, TA tag_assoc, OCNset obj_cite_digits, int cntr_, int ptr_, string[] lv_ancestors_txt, int html_segnames_ptr, SOAT substantive_object_and_anchor_tags_struct, ) { string _text = an_object["substantive"]; string lev_markup_number = an_object["lev_markup_number"]; string lev_collapsed_number = an_object["lev_collapsed_number"]; string dummy_heading_status = an_object["dummy_heading_status"]; string is_ = an_object["is"]; debug(asserts) { static assert(is(typeof(lev) == string)); static assert(is(typeof(obj_cite_digits.object_number) == int)); } assert(is_ == "heading"); assert((obj_cite_digits.object_number).to!int >= 0); assert( lev_markup_number.match(rgx.levels_numbered), ("not a valid heading level: " ~ lev_markup_number ~ " at " ~ obj_cite_digits.object_number.to!string) ); if (lev_markup_number.match(rgx.levels_numbered)) { if (lev_markup_number.to!int == 0) { // TODO first hit (of two) with this assertion failure, check, fix & reinstate // assert(obj_cite_digits.object_number.to!int == 1, // "ERROR header lev markup number is: " ~ // lev_markup_number.to!string ~ // " obj_cite_digits.object_number.to!int should == 1 but is: " ~ // obj_cite_digits.object_number.to!string ~ // "\n" ~ _text); } } switch (lev_markup_number.to!int) { case 0: lv = DocStructMarkupHeading.h_sect_A; lv0 = obj_cite_digit; lv1 = 0; lv2 = 0; lv3 = 0; lv4 = 0; lv5 = 0; lv6 = 0; lv7 = 0; p_["lev_markup_number"] = 0; p_["object_number"] = 0; break; case 1: lv = DocStructMarkupHeading.h_sect_B; lv1 = obj_cite_digit; lv2 = 0; lv3 = 0; lv4 = 0; lv5 = 0; lv6 = 0; lv7 = 0; p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_A; p_["object_number"] = lv0; break; case 2: lv = DocStructMarkupHeading.h_sect_C; lv2 = obj_cite_digit; lv3 = 0; lv4 = 0; lv5 = 0; lv6 = 0; lv7 = 0; p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_B; p_["object_number"] = lv1; break; case 3: lv = DocStructMarkupHeading.h_sect_D; lv3 = obj_cite_digit; lv4 = 0; lv5 = 0; lv6 = 0; lv7 = 0; p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_C; p_["object_number"] = lv2; break; case 4: lv = DocStructMarkupHeading.h_text_1; lv4 = obj_cite_digit; lv5 = 0; lv6 = 0; lv7 = 0; if (lv3 > eN.bi.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_D; p_["object_number"] = lv3; } else if (lv2 > eN.bi.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_C; p_["object_number"] = lv2; } else if (lv1 > eN.bi.off) { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_B; p_["object_number"] = lv1; } else { p_["lev_markup_number"] = DocStructMarkupHeading.h_sect_A; p_["object_number"] = lv0; } break; case 5: lv = DocStructMarkupHeading.h_text_2; lv5 = obj_cite_digit; lv6 = 0; lv7 = 0; p_["lev_markup_number"] = DocStructMarkupHeading.h_text_1; p_["object_number"] = lv4; break; case 6: lv = DocStructMarkupHeading.h_text_3; lv6 = obj_cite_digit; lv7 = 0; p_["lev_markup_number"] = DocStructMarkupHeading.h_text_2; p_["object_number"] = lv5; break; case 7: lv = DocStructMarkupHeading.h_text_4; lv7 = obj_cite_digit; p_["lev_markup_number"] = DocStructMarkupHeading.h_text_3; p_["object_number"] = lv6; break; default: break; } ObjGenericComposite comp_obj_; comp_obj_ = comp_obj_.init; comp_obj_.metainfo.is_of_part = "body"; comp_obj_.metainfo.is_of_section = "body"; comp_obj_.metainfo.is_of_type = "para"; comp_obj_.metainfo.is_a = "heading"; comp_obj_.text = _text.to!string.strip; comp_obj_.metainfo.ocn = obj_cite_digits.object_number; comp_obj_.metainfo.identifier = obj_cite_digits.identifier; comp_obj_.metainfo.dummy_heading = (dummy_heading_status == "t") ? true: false; comp_obj_.metainfo.object_number_off = obj_cite_digits.off; // comp_obj_.metainfo.o_n_book_index = obj_cite_digits.bkidx; comp_obj_.metainfo.object_number_type = obj_cite_digits.type; comp_obj_.tags.segment_anchor_tag_epub = tag_in_seg["seg_lv1to4"]; comp_obj_.tags.anchor_tag_html = tag_in_seg["seg_lv4"]; comp_obj_.tags.in_segment_html = comp_obj_.tags.anchor_tag_html; comp_obj_.tags.heading_lev_anchor_tag = lev_anchor_tag; comp_obj_.tags.html_segment_anchor_tag_is = tag_in_seg["seg_lv4"]; comp_obj_.tags.epub_segment_anchor_tag_is = tag_in_seg["seg_lv1to4"]; comp_obj_.metainfo.heading_lev_markup = (!(lev_markup_number.empty) ? lev_markup_number.to!int : 0); comp_obj_.metainfo.heading_lev_collapsed = (!(lev_collapsed_number.empty) ? lev_collapsed_number.to!int : 0); comp_obj_.metainfo.parent_ocn = p_["object_number"]; comp_obj_.metainfo.parent_lev_markup = p_["lev_markup_number"]; comp_obj_.tags.heading_ancestors_text = lv_ancestors_txt; comp_obj_.ptr.doc_object = cntr_; comp_obj_.ptr.html_segnames = ((lev_markup_number == "4") ? html_segnames_ptr : 0); comp_obj_.ptr.heading = ptr_; comp_obj_.has.inline_notes_reg = substantive_object_and_anchor_tags_struct.has_notes_reg; comp_obj_.has.inline_notes_star = substantive_object_and_anchor_tags_struct.has_notes_star; comp_obj_.has.inline_links = substantive_object_and_anchor_tags_struct.has_links; tag_assoc[comp_obj_.tags.anchor_tag_html]["seg_lv4"] = comp_obj_.tags.in_segment_html; tag_assoc[comp_obj_.tags.segment_anchor_tag_epub]["seg_lv1to4"] = comp_obj_.tags.segment_anchor_tag_epub; 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_.metainfo.parent_lev_markup <= 7); assert(comp_obj_.metainfo.parent_ocn >= 0); if (lev_markup_number.match(rgx.levels_numbered_headings)) { assert(comp_obj_.metainfo.heading_lev_markup <= 7); assert(comp_obj_.metainfo.ocn >= 0); if (comp_obj_.metainfo.parent_lev_markup > 0) { assert(comp_obj_.metainfo.parent_lev_markup < comp_obj_.metainfo.heading_lev_markup); if (comp_obj_.metainfo.ocn != 0) { assert(comp_obj_.metainfo.parent_ocn < comp_obj_.metainfo.ocn); } } if (comp_obj_.metainfo.heading_lev_markup == 0) { assert(comp_obj_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_A); } else if (comp_obj_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_B) { assert(comp_obj_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_A); } else if (comp_obj_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_C) { assert(comp_obj_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_B); } else if (comp_obj_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_sect_D) { assert(comp_obj_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_sect_C); } else if (comp_obj_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_1) { assert(comp_obj_.metainfo.parent_lev_markup <= DocStructMarkupHeading.h_sect_D); } else if (comp_obj_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_2) { assert(comp_obj_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_1); } else if (comp_obj_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_3) { assert(comp_obj_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_2); } else if (comp_obj_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_4) { assert(comp_obj_.metainfo.parent_lev_markup == DocStructMarkupHeading.h_text_3); } else if (comp_obj_.metainfo.heading_lev_markup == DocStructMarkupHeading.h_text_5) { } } return comp_obj_; } invariant() { } } // abstraction functions emitters ↑ // ↓ abstraction functions assertions @safe pure void assertions_doc_structure()( string[string] an_object, string an_object_key, int[string] lv ) { string msg_error_doc_struct = "\nERROR in document structure, check markup (heading level relationships):\n"; if (lv["h3"] > eN.bi.off) { assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h1"] > eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h2"] > eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } else if (lv["h2"] > eN.bi.off) { assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h1"] > eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h3"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } else if (lv["h1"] > eN.bi.off) { assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h2"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h3"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } else if (lv["h0"] > eN.bi.off) { assert(lv["h1"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h2"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h3"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } else { assert(lv["h0"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h1"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h2"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h3"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } if (lv["h7"] > eN.bi.off) { assert(lv["h4"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~\n" ~ an_object[an_object_key] ); assert(lv["h5"] > eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h6"] > eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } else if (lv["h6"] > eN.bi.off) { assert(lv["h4"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~\n" ~ an_object[an_object_key] ); assert(lv["h5"] > eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } else if (lv["h5"] > eN.bi.off) { assert(lv["h4"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~\n" ~ an_object[an_object_key] ); assert(lv["h6"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } else if (lv["h4"] > eN.bi.off) { assert(lv["h5"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h6"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } else { assert(lv["h4"] == eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~\n" ~ an_object[an_object_key] ); assert(lv["h5"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h6"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } if (lv["h0"] == eN.bi.off) { assert(lv["h1"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h2"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h3"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h4"] == eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~\n" ~ an_object[an_object_key] ); assert(lv["h5"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h6"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } if (lv["h1"] == eN.bi.off) { assert(lv["h2"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h3"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } if (lv["h2"] == eN.bi.off) { assert(lv["h3"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } if (lv["h3"] == eN.bi.off) { } if (lv["h4"] == eN.bi.off) { assert(lv["h5"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h6"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } if (lv["h5"] == eN.bi.off) { assert(lv["h6"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } if (lv["h6"] == eN.bi.off) { assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ an_object[an_object_key] ); } if (lv["h7"] == eN.bi.off) { } switch ((an_object["lev"]).to!string) { case "A": if (lv["h0"] == eN.bi.off) { assert(lv["h1"] == eN.bi.off, msg_error_doc_struct ~ "at level A~\n" ~ an_object[an_object_key] ); assert(lv["h2"] == eN.bi.off, msg_error_doc_struct ~ "at level A~\n" ~ an_object[an_object_key] ); assert(lv["h3"] == eN.bi.off, msg_error_doc_struct ~ "at level A~\n" ~ an_object[an_object_key] ); assert(lv["h4"] == eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~\n" ~ "at level A~\n" ~ an_object[an_object_key] ); assert(lv["h5"] == eN.bi.off, msg_error_doc_struct ~ "at level A~\n" ~ an_object[an_object_key] ); assert(lv["h6"] == eN.bi.off, msg_error_doc_struct ~ "at level A~\n" ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ "at level A~\n" ~ an_object[an_object_key] ); } else { // (lv["h0"] > eN.bi.off) assert(lv["h0"] == eN.bi.off, msg_error_doc_struct ~ "should not enter level A a second time\n" ~ "at level A~\n" ~ an_object[an_object_key] ); } break; case "B": if (lv["h1"] == eN.bi.off) { assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level B~\n" ~ an_object[an_object_key] ); assert(lv["h2"] == eN.bi.off, msg_error_doc_struct ~ "at level B~\n" ~ an_object[an_object_key] ); assert(lv["h3"] == eN.bi.off, msg_error_doc_struct ~ "at level B~\n" ~ an_object[an_object_key] ); } else { // (lv["h1"] > eN.bi.off) assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level B~\n" ~ an_object[an_object_key] ); assert(lv["h1"] > eN.bi.off, msg_error_doc_struct ~ "at level B~\n" ~ an_object[an_object_key] ); } break; case "C": if (lv["h2"] == eN.bi.off) { assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level C~\n" ~ an_object[an_object_key] ); assert(lv["h1"] > eN.bi.off, msg_error_doc_struct ~ "level C should not follow level A\n" ~ "at level C~\n" ~ an_object[an_object_key] ); assert(lv["h3"] == eN.bi.off, msg_error_doc_struct ~ "at level C~\n" ~ an_object[an_object_key] ); } else { // (lv["h2"] > eN.bi.off) assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level C~\n" ~ an_object[an_object_key] ); assert(lv["h1"] > eN.bi.off, msg_error_doc_struct ~ "at level C~\n" ~ an_object[an_object_key] ); assert(lv["h2"] > eN.bi.off, msg_error_doc_struct ~ "at level C~\n" ~ an_object[an_object_key] ); } break; case "D": if (lv["h3"] == eN.bi.off) { assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level D~\n" ~ an_object[an_object_key] ); assert(lv["h1"] > eN.bi.off, msg_error_doc_struct ~ "level D should not follow level A\n" ~ "at level D~\n" ~ an_object[an_object_key] ); assert(lv["h2"] > eN.bi.off, msg_error_doc_struct ~ "at level D~\n" ~ an_object[an_object_key] ); } else { // (lv["h3"] > eN.bi.off) assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level D~\n" ~ an_object[an_object_key] ); assert(lv["h1"] > eN.bi.off, msg_error_doc_struct ~ "at level D~\n" ~ an_object[an_object_key] ); assert(lv["h2"] > eN.bi.off, msg_error_doc_struct ~ "at level D~\n" ~ an_object[an_object_key] ); assert(lv["h3"] > eN.bi.off, msg_error_doc_struct ~ "at level D~\n" ~ an_object[an_object_key] ); } break; case "1": if (lv["h4"] == eN.bi.off) { assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level 1~\n" ~ an_object[an_object_key] ); assert(lv["h5"] == eN.bi.off, msg_error_doc_struct ~ "at level 1~\n" ~ an_object[an_object_key] ); assert(lv["h6"] == eN.bi.off, msg_error_doc_struct ~ "at level 1~\n" ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ "at level 1~\n" ~ an_object[an_object_key] ); } else { // (lv["h4"] > eN.bi.off) assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level 1~\n" ~ an_object[an_object_key] ); assert(lv["h4"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~ ?\n" ~ "at level 1~\n" ~ an_object[an_object_key] ); } break; case "2": if (lv["h5"] == eN.bi.off) { assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level 2~\n" ~ an_object[an_object_key] ); assert(lv["h4"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~ ?\n" ~ "at level 2~\n" ~ an_object[an_object_key] ); assert(lv["h6"] == eN.bi.off, msg_error_doc_struct ~ "at level 2~\n" ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ "at level 2~\n" ~ an_object[an_object_key] ); } else { // (lv["h5"] > eN.bi.off) assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level 2~\n" ~ an_object[an_object_key] ); assert(lv["h4"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~ ?\n" ~ "at level 2~\n" ~ an_object[an_object_key] ); assert(lv["h5"] > eN.bi.off, msg_error_doc_struct ~ "at level 2~\n" ~ an_object[an_object_key] ); } break; case "3": if (lv["h6"] == eN.bi.off) { assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level 3~\n" ~ an_object[an_object_key] ); assert(lv["h4"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~ ?\n" ~ "at level 3~\n" ~ an_object[an_object_key] ); assert(lv["h5"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 2~ ?\n" ~ "at level 3~\n" ~ an_object[an_object_key] ); assert(lv["h7"] == eN.bi.off, msg_error_doc_struct ~ "at level 3~\n" ~ an_object[an_object_key] ); } else { // (lv["h6"] > eN.bi.off) assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level 3~\n" ~ an_object[an_object_key] ); assert(lv["h4"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~ ?\n" ~ "at level 3~\n" ~ an_object[an_object_key] ); assert(lv["h5"] > eN.bi.off, msg_error_doc_struct ~ "at level 3~\n" ~ an_object[an_object_key] ); assert(lv["h6"] > eN.bi.off, msg_error_doc_struct ~ "at level 3~\n" ~ an_object[an_object_key] ); } break; case "4": if (lv["h7"] == eN.bi.off) { assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level 4~\n" ~ an_object[an_object_key] ); assert(lv["h4"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~ ?\n" ~ "at level 4~\n" ~ an_object[an_object_key] ); assert(lv["h5"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 2~ ?\n" ~ "at level 4~\n" ~ an_object[an_object_key] ); assert(lv["h6"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 3~ ?\n" ~ "at level 4~\n" ~ an_object[an_object_key] ); } else { // (lv["h7"] > eN.bi.off) assert(lv["h0"] > eN.bi.off, msg_error_doc_struct ~ "at level 4~\n" ~ an_object[an_object_key] ); assert(lv["h4"] > eN.bi.off, msg_error_doc_struct ~ "missing segment level 1~ ?\n" ~ "at level 4~\n" ~ an_object[an_object_key] ); assert(lv["h5"] > eN.bi.off, msg_error_doc_struct ~ "at level 4~\n" ~ an_object[an_object_key] ); assert(lv["h6"] > eN.bi.off, msg_error_doc_struct ~ "at level 4~\n" ~ an_object[an_object_key] ); assert(lv["h7"] > eN.bi.off, msg_error_doc_struct ~ "at level 4~\n" ~ an_object[an_object_key] ); } break; default: break; } } // abstraction functions assertions ↑ #+END_SRC * template docSectKeysSeq #+NAME: docSectKeysSeq #+HEADER: :noweb yes #+BEGIN_SRC d @safe auto docSectKeysSeq(string[][string] document_section_keys_sequenced) { struct doc_sect_keys_seq { string[] scroll() { return document_section_keys_sequenced["scroll"]; } string[] seg() { return document_section_keys_sequenced["seg"]; } string[] sql() { return document_section_keys_sequenced["sql"]; } string[] latex() { return document_section_keys_sequenced["latex"]; } } return doc_sect_keys_seq(); } #+END_SRC * document header including copyright & license #+NAME: doc_header_including_copyright_and_license #+HEADER: :noweb yes #+BEGIN_SRC emacs-lisp <<./spine_version_info_and_doc_header_including_copyright_and_license.org:spine_doc_header_including_copyright_and_license()>> #+END_SRC * __END__