/* emitters ao_emitters.d */ mixin template Emitters() { mixin InternalMarkup; class CLI { string[string] extract_actions(string cmdlnins, string[string] actions) in { } body { switch (cmdlnins) { case "--no-assert": actions["assert"] = "no"; break; default: break; } return actions; } } class OCNemitter : AssertOCN { int ocn, ocn_; int ocn_emitter(int ocn_status_flag) in { assert(ocn_status_flag <= 2); } body { if (ocn_status_flag == 0) { ocn=++ocn_; } else { ocn=0; } return ocn; } invariant() { } } class ObjAttributes { string[string] obj_txt; string para_and_blocks(string obj_txt_in) in { } body { auto rgx = new Rgx(); obj_txt["munge"]=obj_txt_in; if (match(obj_txt_in, rgx.para_bullet)) { obj_txt["attrib"] =" \"bullet\": \"true\"," ~ " \"indent_first\": 0," ~ " \"indent_rest\": 0,"; } else if (auto m = match(obj_txt_in, rgx.para_bullet_indent)) { obj_txt["attrib"] =" \"bullet\": \"true\"," ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ "," ~ " \"indent_rest\": " ~ to!string(m.captures[1]) ~ ","; } else if (auto m = match(obj_txt_in, rgx.para_indent_hang)) { obj_txt["attrib"] =" \"bullet\": \"false\"," ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ "," ~ " \"indent_rest\": " ~ to!string(m.captures[2]) ~ ","; } else if (auto m = match(obj_txt_in, rgx.para_indent)) { obj_txt["attrib"] =" \"bullet\": \"false\"," ~ " \"indent_first\": " ~ to!string(m.captures[1]) ~ "," ~ " \"indent_rest\": " ~ to!string(m.captures[1]) ~ ","; } else { obj_txt["attrib"] =" \"bullet\": \"false\"," ~ " \"indent_first\": 0," ~ " \"indent_rest\": 0,"; } return obj_txt["attrib"]; } string para(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"content\"," ~ " \"of\": \"para\"," ~ " \"is\": \"para\""; return obj_txt["attrib"]; } invariant() { } string heading(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"content\"," ~ " \"of\": \"para\"," ~ " \"is\": \"heading\""; return obj_txt["attrib"]; } invariant() { } string header_make(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"head\"," ~ " \"of\": \"header\"," ~ " \"is\": \"header_make\""; return obj_txt["attrib"]; } invariant() { } string header_metadata(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"head\"," ~ " \"of\": \"header\"," ~ " \"is\": \"header_metadata\""; return obj_txt["attrib"]; } invariant() { } string code(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"code\""; return obj_txt["attrib"]; } invariant() { } string group(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"group\""; return obj_txt["attrib"]; } invariant() { } string block(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"block\""; return obj_txt["attrib"]; } invariant() { } string verse(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"verse\""; return obj_txt["attrib"]; } invariant() { } string quote(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"quote\""; return obj_txt["attrib"]; } invariant() { } string table(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"content\"," ~ " \"of\": \"block\"," ~ " \"is\": \"table\""; return obj_txt["attrib"]; } invariant() { } string comment(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["attrib"] = " \"use\": \"comment\"," ~ " \"of\": \"comment\"," ~ " \"is\": \"comment\""; return obj_txt["attrib"]; } invariant() { } } class ObjInlineMarkupMunge { string[string] obj_txt; int n_foot, n_foot_reg, n_foot_sp_asterisk, n_foot_sp_plus; string obj_txt_out, tail, note; private auto initialize_note_numbers() { n_foot = 0; n_foot_reg = 0; n_foot_sp_asterisk = 0; n_foot_sp_plus = 0; } private auto object_notes_(string obj_txt_in) in { } body { auto rgx = new Rgx(); auto mkup = new InternalMarkup(); obj_txt_out = ""; tail = ""; obj_txt_in = replaceAll( obj_txt_in, rgx.inline_notes_curly_sp_asterisk, (mkup.en_a_o ~ "*" ~ " $1" ~ mkup.en_a_c) ); obj_txt_in = replaceAll( obj_txt_in, rgx.inline_notes_curly_sp_plus, (mkup.en_a_o ~ "+" ~ " $1" ~ mkup.en_a_c) ); obj_txt_in = replaceAll( obj_txt_in, rgx.inline_notes_curly, (mkup.en_a_o ~ " $1" ~ mkup.en_a_c) ); if (match(obj_txt_in, rgx.inline_notes_al_gen)) { foreach(m; matchAll(obj_txt_in, rgx.inline_text_and_note_al)) { if (match(obj_txt_in, rgx.inline_al_delimiter_open_asterisk)) { n_foot_sp_asterisk++; n_foot=n_foot_sp_asterisk; } else if (match(obj_txt_in, rgx.inline_al_delimiter_open_plus)) { n_foot_sp_plus++; n_foot=n_foot_sp_plus; } else { n_foot_reg++; n_foot=n_foot_reg; } obj_txt_out ~= replaceFirst( m.hit, rgx.inline_al_delimiter_open_regular, (mkup.en_a_o ~ to!string(n_foot)) ); tail = m.post; } } else { obj_txt_out = obj_txt_in; } debug(footnotes) { writeln(obj_txt_out, tail); } obj_txt_out = obj_txt_out ~ tail; debug(footnotesdone) { foreach(m; matchAll(obj_txt_out, (mkup.en_a_o ~ `\s*(.+?)` ~ mkup.en_a_c))) { writeln(m.captures[1]); writeln(m.hit); } } return obj_txt_out; } string para(string obj_txt_in) in { } body { auto rgx = new Rgx(); obj_txt["munge"]=obj_txt_in; obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.para_attribs, ""); obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.ocn_off_all, ""); obj_txt["munge"]=object_notes_(obj_txt["munge"]); debug(munge) { writeln(__LINE__); writeln(obj_txt_in); writeln(__LINE__); writeln(to!string(obj_txt["munge"])); } return obj_txt["munge"]; } string heading(string obj_txt_in) in { } body { auto rgx = new Rgx(); obj_txt["munge"]=obj_txt_in; obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.heading, ""); obj_txt["munge"]=replaceFirst(obj_txt["munge"], rgx.ocn_off_all, ""); obj_txt["munge"]=object_notes_(obj_txt["munge"]); debug(munge) { writeln(__LINE__); writeln(obj_txt_in); writeln(__LINE__); writeln(to!string(obj_txt["munge"])); } return obj_txt["munge"]; } invariant() { } string header_make(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } string header_metadata(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } string code(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } string group(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["munge"]=object_notes_(obj_txt["munge"]); return obj_txt["munge"]; } invariant() { } string block(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["munge"]=object_notes_(obj_txt["munge"]); return obj_txt["munge"]; } invariant() { } string verse(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; obj_txt["munge"]=object_notes_(obj_txt["munge"]); return obj_txt["munge"]; } invariant() { } string quote(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } string table(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } string comment(string obj_txt_in) in { } body { obj_txt["munge"]=obj_txt_in; return obj_txt["munge"]; } invariant() { } } class ObjInlineMarkup : AssertObjInlineMarkup { auto munge = new ObjInlineMarkupMunge(); string[string] obj_txt; string obj_inline_markup(string obj_is_, string obj_raw) in { } body { obj_txt["munge"]=obj_raw.dup; obj_txt["munge"]=(match(obj_is_, ctRegex!(`verse|code`))) ? obj_txt["munge"] : strip(obj_txt["munge"]); switch (obj_is_) { case "header_make": obj_txt["munge"]=munge.header_make(obj_txt["munge"]); break; case "header_metadata": obj_txt["munge"]=munge.header_metadata(obj_txt["munge"]); break; case "heading": obj_txt["munge"]=munge.heading(obj_txt["munge"]); break; case "para": obj_txt["munge"]=munge.para(obj_txt["munge"]); break; case "code": obj_txt["munge"]=munge.code(obj_txt["munge"]); break; case "group": obj_txt["munge"]=munge.group(obj_txt["munge"]); break; case "block": obj_txt["munge"]=munge.block(obj_txt["munge"]); break; case "verse": obj_txt["munge"]=munge.verse(obj_txt["munge"]); break; case "quote": obj_txt["munge"]=munge.quote(obj_txt["munge"]); break; case "table": obj_txt["munge"]=munge.table(obj_txt["munge"]); break; case "comment": obj_txt["munge"]=munge.comment(obj_txt["munge"]); break; case "doc_end_reset": munge.initialize_note_numbers(); break; default: break; } return obj_txt["munge"]; } invariant() { } } class ObjAttrib : AssertObjAttrib { auto attrib = new ObjAttributes(); string[string] obj_attrib; string obj_attributes(string obj_is_, string obj_raw, string node) in { } body { scope(exit) { destroy(obj_raw); destroy(node); } JSONValue node_j = parseJSON(node); obj_attrib.remove("json"); obj_attrib["json"] ="{"; switch (obj_is_) { case "header_make": obj_attrib["json"] ~= attrib.header_make(obj_raw); break; case "header_metadata": obj_attrib["json"] ~= attrib.header_metadata(obj_raw); break; case "heading": obj_attrib["json"] ~= attrib.heading(obj_raw); // break; case "para": obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw) ~ attrib.para(obj_raw); break; case "code": obj_attrib["json"] ~= attrib.code(obj_raw); break; case "group": obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw) ~ attrib.group(obj_raw); break; case "block": obj_attrib["json"] ~= attrib.para_and_blocks(obj_raw) ~ attrib.block(obj_raw); break; case "verse": obj_attrib["json"] ~= attrib.verse(obj_raw); break; case "quote": obj_attrib["json"] ~= attrib.quote(obj_raw); break; case "table": obj_attrib["json"] ~= attrib.table(obj_raw); break; case "comment": obj_attrib["json"] ~= attrib.comment(obj_raw); break; default: obj_attrib["json"] ~= attrib.para(obj_raw); break; } obj_attrib["json"] ~=" }"; JSONValue oa_j = parseJSON(obj_attrib["json"]); assert( (oa_j.type == JSON_TYPE.OBJECT) && (node_j.type == JSON_TYPE.OBJECT) ); if (obj_is_ == "heading") { oa_j.object["ocn"] = node_j["ocn"]; oa_j.object["lvn"] = node_j["lvn"]; oa_j.object["lcn"] = node_j["lcn"]; oa_j.object["heading_pointer"] = node_j["heading_pointer"]; // check oa_j.object["doc_object_pointer"] = node_j["doc_object_pointer"]; // check } oa_j.object["parent_ocn"] = node_j["parent_ocn"]; oa_j.object["parent_lvn"] = node_j["parent_lvn"]; obj_attrib["json"] = oa_j.toString(); debug(structattrib) { if (oa_j["is"].str() == "heading") { writeln(obj_attrib["json"]); writeln( "is: ", oa_j["is"].str(), "; ocn: ", oa_j["ocn"].integer() ); } } return obj_attrib["json"]; } invariant() { } } class HeaderDocMetadataMakeJson { auto rgx = new Rgx(); string hm, hs; auto header_metadata_and_make_jsonstr( string header, JSONValue[string] dochead_metadata, JSONValue[string] dochead_make ) in { } body { scope(exit) { destroy(header); destroy(dochead_metadata); destroy(dochead_make); } if (auto t = match(header, rgx.head_main)) { char[][] obj_spl = split( cast(char[]) header, rgx.line_delimiter_ws_strip ); auto hm = to!string(t.captures[1]); if (match(hm, rgx.main_headers)) { foreach (line; obj_spl) { if (auto m = match(line, rgx.head_main)) { if (!empty(m.captures[2])) { if (hm == "creator") { dochead_metadata[hm]["author"].str = to!string(m.captures[2]); } else if (hm == "title") { dochead_metadata[hm]["main"].str = to!string(m.captures[2]); } else if (hm == "publisher") { dochead_metadata[hm]["name"].str = to!string(m.captures[2]); } } } else if (auto s = match(line, rgx.head_sub)) { if (!empty(s.captures[2])) { auto hs = to!string(s.captures[1]); if ((hm == "make" ) && (dochead_make[hm].type() == JSON_TYPE.OBJECT)) { switch (hm) { case "make": if (match(hs, rgx.subhead_make)) { if (dochead_make[hm][hs].type() == JSON_TYPE.STRING) { dochead_make[hm][hs].str = to!string(s.captures[2]); } } else { writeln("not a valid header type:", hm, ":", hs); destroy(hm); destroy(hs); } break; default: break; } } else if (dochead_metadata[hm].type() == JSON_TYPE.OBJECT) { switch (hm) { case "creator": if (match(hs, rgx.subhead_creator)) { if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { dochead_metadata[hm][hs].str = to!string(s.captures[2]); } } else { writeln("not a valid header type:", hm, ":", hs); destroy(hm); destroy(hs); } break; case "title": if (match(hs, rgx.subhead_title)) { if ((hs == "subtitle") && (dochead_metadata[hm]["sub"].type() == JSON_TYPE.STRING)) { dochead_metadata[hm]["sub"].str = to!string(s.captures[2]); } else if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { dochead_metadata[hm][hs].str = to!string(s.captures[2]); } } else { writeln("not a valid header type:", hm, ":", hs); destroy(hm); destroy(hs); } break; case "rights": if (match(hs, rgx.subhead_rights)) { if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { dochead_metadata[hm][hs].str = to!string(s.captures[2]); } } else { writeln("not a valid header type:", hm, ":", hs); destroy(hm); destroy(hs); } break; case "date": if (match(hs, rgx.subhead_date)) { if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { dochead_metadata[hm][hs].str = to!string(s.captures[2]); } } else { writeln("not a valid header type:", hm, ":", hs); destroy(hm); destroy(hs); } break; case "original": if (match(hs, rgx.subhead_original)) { if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { dochead_metadata[hm][hs].str = to!string(s.captures[2]); } } else { writeln("not a valid header type:", hm, ":", hs); destroy(hm); destroy(hs); } break; case "classify": if (match(hs, rgx.subhead_classify)) { if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { dochead_metadata[hm][hs].str = to!string(s.captures[2]); } } else { writeln("not a valid header type:", hm, ":", hs); destroy(hm); destroy(hs); } break; case "identifier": if (match(hs, rgx.subhead_identifier)) { if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { dochead_metadata[hm][hs].str = to!string(s.captures[2]); } } else { writeln("not a valid header type:", hm, ":", hs); destroy(hm); destroy(hs); } break; case "notes": if (match(hs, rgx.subhead_notes)) { if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { dochead_metadata[hm][hs].str = to!string(s.captures[2]); } } else { writeln("not a valid header type:", hm, ":", hs); destroy(hm); destroy(hs); } break; case "publisher": if (match(hs, rgx.subhead_publisher)) { if (dochead_metadata[hm][hs].type() == JSON_TYPE.STRING) { dochead_metadata[hm][hs].str = to!string(s.captures[2]); } } else { writeln("not a valid header type:", hm, ":", hs); destroy(hm); destroy(hs); } break; case "links": destroy(hm); destroy(hs); break; default: break; } } } } } } else { writeln("not a valid header type:", hm); } } auto t = tuple(dochead_metadata, dochead_make); static assert(!isTypeTuple!(t)); return t; } } class HeaderMetadataMakeHash { auto rgx = new Rgx(); string header_main; string[string] head; string[string] header_topic_hash(string header) in { } body { if (auto t = match(header, rgx.head_main)) { char[][] obj_spl = split( cast(char[]) header, rgx.line_delimiter_ws_strip ); auto header_main = to!string(t.captures[1]); head[header_main] = "{"; foreach (line; obj_spl) { if (auto m = match(line, rgx.head_main)) { if (!empty(m.captures[2])) { head[header_main] ~= "\"" ~ header_main ~ "\": \"" ~ to!string(m.captures[2]) ~ "\","; } } else if (auto s = match(line, rgx.head_sub)) { head[header_main] ~= "\"" ~ s.captures[1] ~ "\":"; if (!empty(s.captures[2])) { head[header_main] ~= "\"" ~ s.captures[2] ~ "\","; } } } head[header_main] = replaceFirst( head[header_main], rgx.tailing_comma, "" ); head[header_main] ~= "}"; debug(headerjson) { JSONValue j = parseJSON(head[header_main]); assert( (j.type == JSON_TYPE.OBJECT) ); } } return head; } invariant() { } } class BookIndexNuggetHash : AssertBookIndexNuggetHash { string main_term, sub_term, sub_term_bits; uint ocn_offset, ocn_endpoint; string[] ocns; string[][string][string] bi; string[][string][string] hash_nugget; string[] bi_main_terms_split_arr; string[][string][string] bookindex_nugget_hash(string bookindex, int ocn) in { } body { auto rgx = new Rgx(); if (!bookindex.empty) { auto bi_main_terms_split_arr = split(bookindex, rgx.bi_main_terms_split); foreach (bi_main_terms_content; bi_main_terms_split_arr) { auto bi_main_term_and_rest = split(bi_main_terms_content, rgx.bi_main_term_plus_rest_split); if (auto m = match( bi_main_term_and_rest[0], rgx.bi_term_and_ocns_match) ) { main_term = strip(m.captures[1]); ocn_offset = to!uint(m.captures[2]); ocn_endpoint=(ocn + ocn_offset); ocns ~= (to!string(ocn) ~ "-" ~ to!string(ocn_endpoint)); } else { main_term = strip(bi_main_term_and_rest[0]); ocns ~= to!string(ocn); } bi[main_term]["_a"] ~= ocns; ocns=null; if (bi_main_term_and_rest.length > 1) { auto bi_sub_terms_split_arr = split( bi_main_term_and_rest[1], rgx.bi_sub_terms_plus_ocn_offset_split ); foreach (sub_terms_bits; bi_sub_terms_split_arr) { if (auto m = match(sub_terms_bits, rgx.bi_term_and_ocns_match)) { sub_term = strip(m.captures[1]); ocn_offset = to!uint(m.captures[2]); ocn_endpoint=(ocn + ocn_offset); ocns ~= (to!string(ocn) ~ " - " ~ to!string(ocn_endpoint)); } else { sub_term = strip(sub_terms_bits); ocns ~= to!string(ocn); } if (!empty(sub_term)) { bi[main_term][sub_term] ~= ocns; } ocns=null; } } } } hash_nugget = bi; return hash_nugget; } invariant() { } } class BookIndexReport { int mkn, skn; auto bookindex_report_sorted( string[][string][string] bookindex_unordered_hashes ) { auto mainkeys=bookindex_unordered_hashes.byKey.array. sort!("toLower(a) < toLower(b)", SwapStrategy.stable).release; foreach (mainkey; mainkeys) { auto subkeys=bookindex_unordered_hashes[mainkey].byKey.array. sort!("toLower(a) < toLower(b)", SwapStrategy.stable).release; foreach (subkey; subkeys) { debug(bookindex) { writeln( mainkey, ": ", subkey, ": ", to!string(bookindex_unordered_hashes[mainkey][subkey]) ); } skn++; } mkn++; } } } class BookIndexReportIndent { int mkn, skn; auto bookindex_report_indented( string[][string][string] bookindex_unordered_hashes ) { auto mainkeys= bookindex_unordered_hashes.byKey.array.sort().release; foreach (mainkey; mainkeys) { debug(bookindex) { writeln(mainkey); } auto subkeys= bookindex_unordered_hashes[mainkey].byKey.array.sort().release; foreach (subkey; subkeys) { debug(bookindex) { writeln(" ", subkey); writeln(" ", to!string( bookindex_unordered_hashes[mainkey][subkey] )); } skn++; } mkn++; } } } class BookIndexReportSection { mixin ObjectSetters; int mkn, skn; auto rgx = new Rgx(); auto bookindex_write_section( string[][string][string] bookindex_unordered_hashes ) { auto mainkeys=bookindex_unordered_hashes.byKey.array.sort().release; foreach (mainkey; mainkeys) { write("_0_1 !{", mainkey, "}! "); foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { auto go = replaceAll(ref_, rgx.book_index_go, "$1"); write(" {", ref_, "}#", go, ", "); } writeln(" \\\\"); bookindex_unordered_hashes[mainkey].remove("_a"); auto subkeys= bookindex_unordered_hashes[mainkey].byKey.array.sort().release; foreach (subkey; subkeys) { write(" ", subkey, ", "); foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { auto go = replaceAll(ref_, rgx.book_index_go, "$1"); write(" {", ref_, "}#", go, ", "); } writeln(" \\\\"); skn++; } mkn++; } } auto bookindex_build_section( string[][string][string] bookindex_unordered_hashes, int ocn ) { string type; int type_heading; string lev, lvn, lcn; string attrib; string indent_first; string indent_second; auto set_oa = new ObjectAbstractSet(); auto mainkeys = bookindex_unordered_hashes.byKey.array.sort().release; string bi_tmp; string[string][1024] bookindex_arbitrary_max_length_set; writeln(mainkeys.length); type_heading=1; bi_tmp = "Book Index"; attrib=""; lev="B"; lvn="1"; lcn="1"; bookindex_arbitrary_max_length_set[mkn] = set_oa.contents_heading( type_heading, bi_tmp, attrib, ocn, lev, lvn, lcn ); ocn++; mkn++; type_heading=1; bi_tmp = "Index"; attrib=""; lev="1"; lvn="4"; lcn="2"; bookindex_arbitrary_max_length_set[mkn] = set_oa.contents_heading( type_heading, bi_tmp, attrib, ocn, lev, lvn, lcn ); ocn++; mkn++; foreach (mainkey; mainkeys) { bi_tmp = "!{" ~ mainkey ~ "}! "; foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { auto go = replaceAll(ref_, rgx.book_index_go, "$1"); bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", "; } bi_tmp ~= " \\\\\n "; bookindex_unordered_hashes[mainkey].remove("_a"); auto subkeys = bookindex_unordered_hashes[mainkey].byKey.array.sort().release; foreach (subkey; subkeys) { bi_tmp ~= subkey ~ ", "; foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { auto go = replaceAll(ref_, rgx.book_index_go, "$1"); bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", "; } bi_tmp ~= " \\\\\n "; skn++; } bi_tmp = replaceFirst(bi_tmp, rgx.trailing_linebreak, ""); type="para"; attrib=""; indent_first = "0"; indent_second = "1"; attrib=""; bookindex_arbitrary_max_length_set[mkn] = set_oa.contents_para( type, bi_tmp, attrib, ocn, indent_first, indent_second, false ); ocn++; mkn++; } auto bookindex = bookindex_arbitrary_max_length_set[0..mkn].dup; auto t = tuple(bookindex, ocn); return t; } auto bookindex_build_section_( string[][string][string] bookindex_unordered_hashes ) { auto mainkeys = bookindex_unordered_hashes.byKey.array.sort().release; string bi_tmp; string[1024] bookindex_arbitrary_max_length_set; writeln(mainkeys.length); foreach (mainkey; mainkeys) { bi_tmp = "_0_1 !{" ~ mainkey ~ "}! "; foreach (ref_; bookindex_unordered_hashes[mainkey]["_a"]) { auto go = replaceAll(ref_, rgx.book_index_go, "$1"); bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", "; } bi_tmp ~= " \\\\\n "; bookindex_unordered_hashes[mainkey].remove("_a"); auto subkeys = bookindex_unordered_hashes[mainkey].byKey.array.sort().release; foreach (subkey; subkeys) { bi_tmp ~= subkey ~ ", "; foreach (ref_; bookindex_unordered_hashes[mainkey][subkey]) { auto go = replaceAll(ref_, rgx.book_index_go, "$1"); bi_tmp ~= " {" ~ ref_ ~ "}#" ~ go ~ ", "; } bi_tmp ~= " \\\\\n "; skn++; } bi_tmp = replaceFirst(bi_tmp, rgx.trailing_linebreak, ""); bookindex_arbitrary_max_length_set[mkn] = bi_tmp; mkn++; } auto bookindex = bookindex_arbitrary_max_length_set[0..mkn].dup; return bookindex; } } class NotesSection { mixin ObjectSetters; string object_notes; int previous_count; int mkn; auto rgx = new Rgx(); private auto gather_notes_for_endnote_section( string[string][131072] contents_arbitrary_max_length_set, int counter ) in { // endnotes/ footnotes for // doc objects other than paragraphs & headings // various forms of grouped text assert((contents_arbitrary_max_length_set[counter]["is"] == "para") || (contents_arbitrary_max_length_set[counter]["is"] == "heading")); assert(counter > previous_count); previous_count=counter; assert( match(contents_arbitrary_max_length_set[counter]["obj"], rgx.inline_notes_delimiter_al_regular_number_note) ); } body { foreach(m; matchAll(contents_arbitrary_max_length_set[counter]["obj"], rgx.inline_notes_delimiter_al_regular_number_note)) { debug(endnotes_build) { writeln( "{^{", m.captures[1], ".}^}#noteref_", m.captures[1], " ", m.captures[2]); // sometimes need segment name (segmented html & epub) } object_notes ~= "{^{" ~ m.captures[1] ~ ".}^}#noteref_" ~ m.captures[1] ~ " " ~ m.captures[2] ~ "』"; } return object_notes; } private auto gathered_notes() in { } body { string[] endnotes_; if (object_notes.length > 1) { endnotes_ = (split(object_notes, rgx.break_string))[0..$-1]; } return endnotes_; } private auto endnote_objects(int ocn) in { } body { auto set_oa = new ObjectAbstractSet(); string[string][1024] endnotes_arbitrary_max_length_set; auto endnotes_ = gathered_notes(); string type; int type_heading; string lev, lvn, lcn; string attrib; string indent_first; string indent_second; type_heading=1; attrib=""; lev="B"; lvn="1"; lcn="1"; endnotes_arbitrary_max_length_set[mkn] = set_oa.contents_heading( type_heading, "Endnotes", attrib, ocn, lev, lvn, lcn ); ocn++; mkn++; type_heading=1; attrib=""; lev="1"; lvn="4"; lcn="2"; endnotes_arbitrary_max_length_set[mkn] = set_oa.contents_heading( type_heading, "Endnotes", attrib, ocn, lev, lvn, lcn ); ocn++; mkn++; foreach (endnote; endnotes_) { type="para"; attrib=""; indent_first = "0"; indent_second = "0"; attrib=""; endnotes_arbitrary_max_length_set[mkn] = set_oa.contents_para( type, endnote, attrib, ocn, indent_first, indent_second, false ); ocn++; mkn++; } auto endnotes = endnotes_arbitrary_max_length_set[0..mkn].dup; auto t = tuple(endnotes, ocn); return t; } } class Bibliography { public JSONValue[] bibliography(string[] biblio_unsorted_incomplete) in { } body { JSONValue[] biblio_unsorted = biblio_unsorted_complete(biblio_unsorted_incomplete); JSONValue[] biblio_sorted = biblio_sort(biblio_unsorted); biblio_debug(biblio_sorted); return biblio_sorted; } final private JSONValue[] biblio_unsorted_complete( string[] biblio_unordered ) { JSONValue[1024] bib_arr_json; int count_biblio_entry; count_biblio_entry=0; 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[count_biblio_entry] = j; count_biblio_entry++; } JSONValue[] biblio_unsorted_array_of_json_objects = bib_arr_json[0..(count_biblio_entry)].dup; return biblio_unsorted_array_of_json_objects; } 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; } auto biblio_debug(JSONValue[] biblio_sorted) { debug(biblio) { foreach (j; biblio_sorted) { if (!empty(j["fulltitle"].str)) { writeln(j["sortby_deemed_author_year_title"]); } } } } } class NodeStructureMetadata : AssertNodeJSON { int lv, lv0, lv1, lv2, lv3, lv4, lv5, lv6, lv7; uint ocn; uint[string] p_; // p_ parent_ string node; string node_emitter( string lvn, int ocn_, int counter_, int pointer_, string is_ ) in { auto rgx = new Rgx(); } body { assert(is_ != "heading"); // should not be necessary assert(to!int(ocn_) >= 0); // should not be necessary uint ocn=to!uint(ocn_); if (lv7 > 0) { p_["lvn"] = 7; p_["ocn"] = lv7; } else if (lv6 > 0) { p_["lvn"] = 6; p_["ocn"] = lv6; } else if (lv5 > 0) { p_["lvn"] = 5; p_["ocn"] = lv5; } else { p_["lvn"] = 4; p_["ocn"] = lv4; } node=("{ " ~ "\"is\": \"" ~ is_ ~ "\"" ~ ", \"heading_pointer\": " ~ to!string(pointer_) ~ ", \"doc_object_pointer\": " ~ to!string(counter_) ~ ", \"ocn\": " ~ to!string(ocn_) ~ ", \"parent_ocn\": " ~ to!string(p_["ocn"]) ~ ", \"parent_lvn\": " ~ to!string(p_["lvn"]) ~ " }" ); return node; } invariant() { } string node_emitter_heading( string lvn, string lcn, int ocn_, int counter_, int pointer_, string is_ ) in { auto rgx = new Rgx(); } body { uint ocn=to!uint(ocn_); switch (lvn) { // switch (to!string(lv)) { case "0": lv=0; lv0=ocn; lv1=0; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; p_["lvn"] = 0; p_["ocn"] = 0; break; case "1": lv=1; lv1=ocn; lv2=0; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; p_["lvn"] = 0; p_["ocn"] = lv0; break; case "2": lv=2; lv2=ocn; lv3=0; lv4=0; lv5=0; lv6=0; lv7=0; p_["lvn"] = 1; p_["ocn"] = lv1; break; case "3": lv=3; lv3=ocn; lv4=0; lv5=0; lv6=0; lv7=0; p_["lvn"] = 2; p_["ocn"] = lv2; break; case "4": lv=4; lv4=ocn; lv5=0; lv6=0; lv7=0; if (lv3 > 0) { p_["lvn"] = 3; p_["ocn"] = lv3; } else if (lv2 > 0) { p_["lvn"] = 2; p_["ocn"] = lv2; } else if (lv1 > 0) { p_["lvn"] = 1; p_["ocn"] = lv1; } else { p_["lvn"] = 0; p_["ocn"] = lv0; } break; case "5": lv=5; lv5=ocn; lv6=0; lv7=0; p_["lvn"] = 4; p_["ocn"] = lv4; break; case "6": lv=6; lv6=ocn; lv7=0; p_["lvn"] = 5; p_["ocn"] = lv5; break; case "7": lv=7; lv7=ocn; p_["lvn"] = 6; p_["ocn"] = lv6; break; default: break; } node=("{ " ~ "\"is\": \"" ~ is_ ~ "\"" ~ ", \"heading_pointer\": " ~ to!string(pointer_) ~ ", \"doc_object_pointer\": " ~ to!string(counter_) ~ ", \"ocn\": " ~ to!string(ocn_) ~ ", \"lvn\": " ~ to!string(lvn) ~ ", \"lcn\": " ~ to!string(lcn) ~ ", \"parent_ocn\": " ~ to!string(p_["ocn"]) ~ ", \"parent_lvn\": " ~ to!string(p_["lvn"]) ~ " }" ); return node; } invariant() { } } }