/+
- Name: Spine, Doc Reform [a part of]
- Description: documents, structuring, processing, publishing, search
- static content generator
- Author: Ralph Amissah
[ralph.amissah@gmail.com]
- Copyright: (C) 2015 - 2023 Ralph Amissah, All Rights Reserved.
- License: AGPL 3 or later:
Spine (SiSU), a framework for document structuring, publishing and
search
Copyright (C) Ralph Amissah
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU AFERO General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see [https://www.gnu.org/licenses/].
If you have Internet connection, the latest version of the AGPL should be
available at these locations:
[https://www.fsf.org/licensing/licenses/agpl.html]
[https://www.gnu.org/licenses/agpl.html]
- Spine (by Doc Reform, related to SiSU) uses standard:
- docReform markup syntax
- standard SiSU markup syntax with modified headers and minor modifications
- docReform object numbering
- standard SiSU object citation numbering & system
- Homepages:
[https://www.doc_reform.org]
[https://www.sisudoc.org]
- Git
[https://git.sisudoc.org/projects/?p=software/spine.git;a=summary]
+/
module doc_reform.io_out.odt;
template formatODT() {
import
doc_reform.io_out,
doc_reform.io_out.rgx,
doc_reform.io_out.rgx_xhtml;
import
std.digest.sha,
std.file,
std.outbuffer,
std.uri,
std.zip,
std.conv : to;
import
doc_reform.io_out.create_zip_file,
doc_reform.io_out.xmls,
doc_reform.io_out.xmls_css;
mixin spineRgxOut;
mixin spineRgxXHTML;
struct formatODT {
static auto rgx = RgxO();
static auto rgx_xhtml = RgxXHTML();
@safe string _tags(O)(const O obj) {
string _tags = "";
if (obj.tags.anchor_tags.length > 0) {
foreach (tag_; obj.tags.anchor_tags) {
if (tag_.length > 0) {
_tags ~= format(q"┃
┃",
_special_characters(tag_, obj),
_special_characters(tag_, obj),
);
}
}
}
return _tags;
}
@safe string _xhtml_anchor_tags(O)(O obj) {
const(string[]) anchor_tags = obj.tags.anchor_tags;
string tags="";
if (anchor_tags.length > 0) {
foreach (tag; anchor_tags) {
if (!(tag.empty)) {
tags ~= "";
}
}
}
return tags;
}
@safe string obj_num(O)(const O obj) { // TODO
string _on;
_on = (obj.metainfo.object_number.empty)
? ""
: (format(q"┃
「%s」┃",
obj.metainfo.object_number,
));
return _on;
}
@safe string _footnotes()(string _txt) {
static auto rgx = RgxO();
static auto rgx_xhtml = RgxXHTML();
_txt = _txt.replaceAll(
rgx.inline_notes_al_regular_number_note,
format(q"┃
%s
%s
┃",
"$1", "$1", "$2",
)
);
return _txt;
}
@safe string _bullet(O)(const O obj) {
string _b = "";
if (obj.attrib.bullet) {
_b = format(q"┃● ┃",);
}
return _b;
}
@safe string _indent(O)(string _txt, const O obj) { // TODO
// if (obj.attrib.indent_base > 0 ||
// obj.attrib.indent_hang > 0
// ) {
if (obj.metainfo.is_a == "toc") {
_txt = format(q"┃
%s
%s%s%s
┃",
(obj.attrib.indent_base < 4)
? "\n " : "",
obj.attrib.indent_base,
obj.attrib.indent_base,
_tags(obj),
_txt,
obj_num(obj),
);
} else if (!empty(obj.metainfo.object_number)) {
if (obj.attrib.indent_base == 0 && obj.attrib.indent_hang == 0) {
_txt = format(q"┃
%s
%s%s%s
┃",
_bullet(obj),
obj.metainfo.object_number,
obj.metainfo.object_number,
_tags(obj),
_txt,
obj_num(obj),
);
} else if (obj.attrib.indent_base == obj.attrib.indent_hang) {
_txt = format(q"┃
%s
%s%s%s
┃",
obj.attrib.indent_base,
_bullet(obj),
obj.metainfo.object_number,
obj.metainfo.object_number,
_tags(obj),
_txt,
obj_num(obj),
);
} else {
_txt = format(q"┃
%s
%s%s%s
┃",
obj.attrib.indent_base,
obj.attrib.indent_hang,
_bullet(obj),
obj.metainfo.object_number,
obj.metainfo.object_number,
_tags(obj),
_txt,
obj_num(obj),
);
}
} else {
if (obj.attrib.indent_base == 0 && obj.attrib.indent_hang == 0) { /+ can omit and would explicitly set indent base and hang as 0 each below +/
_txt = format(q"┃
%s
%s%s%s
┃",
_bullet(obj),
_tags(obj),
_txt,
obj_num(obj),
);
} else if (obj.attrib.indent_base == obj.attrib.indent_hang) {
_txt = format(q"┃
%s
%s%s%s
┃",
obj.attrib.indent_base,
_bullet(obj),
_tags(obj),
_txt,
obj_num(obj),
);
} else {
_txt = format(q"┃
%s
%s%s%s
┃",
_bullet(obj),
obj.attrib.indent_base,
obj.attrib.indent_hang,
_tags(obj),
_txt,
obj_num(obj),
);
}
}
return _txt;
}
@safe string _block_type_delimiters(O)(string[] _block_lines, const O obj) { // TODO
string _block = "";
foreach (i, _line; _block_lines) {
_line = _footnotes(_line);
if (i == 0) {
_block ~= format(q"┃
%s
%s
┃",
_bullet(obj),
obj.metainfo.object_number,
obj.metainfo.object_number,
// _tags(obj),
_line,
);
} else {
_block ~= format(q"┃
%s┃",
_line);
}
}
_block ~= format(q"┃
「%s」
┃",
obj_num(obj));
return _block;
}
@safe string _special_characters(O)(string _txt, const O obj) {
_txt = _txt
.replaceAll(rgx_xhtml.ampersand, "&")
.replaceAll(rgx_xhtml.quotation, """)
.replaceAll(rgx_xhtml.less_than, "<")
.replaceAll(rgx_xhtml.greater_than, ">")
.replaceAll(rgx.nbsp_char, " ");
return _txt;
}
@safe string _preserve_white_spaces(O)(string _txt, const O obj) {
if (obj.metainfo.is_a == "code" || obj.metainfo.is_a == "verse" || obj.metainfo.is_a == "block") {
_txt = _txt
.replaceAll(rgx.space, " ");
}
return _txt;
}
string _font_face(string _txt){
_txt = _txt
.replaceAll(rgx.inline_strike, "$1")
.replaceAll(rgx.inline_insert, "$1")
.replaceAll(rgx.inline_cite, "$1")
.replaceAll(rgx.inline_emphasis, format(q"┃%s┃", "$1"))
.replaceAll(rgx.inline_bold, format(q"┃%s┃", "$1"))
.replaceAll(rgx.inline_italics, format(q"┃%s┃", "$1"))
.replaceAll(rgx.inline_underscore, format(q"┃%s┃", "$1"))
.replaceAll(rgx.inline_superscript, format(q"┃%s┃","$1"))
.replaceAll(rgx.inline_subscript, format(q"┃%s┃", "$1"))
.replaceAll(rgx.inline_mono, format(q"┃%s┃", "$1"));
return _txt;
}
@safe auto _obj_num(O)(O obj) { // NOT USED YET
struct objNum {
@safe string reference() {
return format(q"┃
┃",
obj.object_number,
obj.object_number,
);
}
@safe string display() {
return format(q"┃
%s%s%s
┃",
on_o,
obj.object_number,
on_c,
);
}
}
return objNum();
}
@safe string _break_page()() {
return format(q"┃
┃",
);
}
@safe string _empty_line_break(O)(string _txt, const O obj) {
if (obj.metainfo.is_a == "code" || obj.metainfo.is_a == "verse" || obj.metainfo.is_a == "block") {
_txt = _txt
.replaceAll(rgx.br_empty_line, "
");
}
return _txt;
}
@safe string _links(O)(string _txt, const O obj) {
if (obj.metainfo.is_a != "code") {
if (obj.metainfo.is_a == "toc") {
_txt = replaceAll!(m =>
m[1] ~ "┤"
~ (replaceAll!(n =>
n["type"] ~ n["path"] ~ (n["file"].encodeComponent)
)((obj.stow.link[m["num"].to!ulong]).to!string, rgx.uri_identify_components))
~ "├"
)(_txt, rgx.inline_link_number_only)
.replaceAll(rgx.inline_link,
format(q"┃%s┃",
_special_characters("$3", obj),
_special_characters("$1", obj)
));
} else {
_txt = replaceAll!(m =>
m[1] ~ "┤"
~ (replaceAll!(n =>
n["type"] ~ n["path"] ~ (n["file"].encodeComponent)
)((obj.stow.link[m["num"].to!ulong]).to!string, rgx.uri_identify_components))
~ "├"
)(_txt, rgx.inline_link_number_only)
.replaceAll(rgx.inline_link,
format(q"┃%s┃",
_special_characters("$2", obj),
_special_characters("$1", obj)
));
}
}
debug(links) {
if (obj.text.match(rgx.inline_link_number)
&& _txt.match(rgx.inline_link_number_only)
) {
writeln(">> ", _txt);
writeln("is_a: ", obj.metainfo.is_a);
}
}
return _txt;
}
@safe string _images(O)(string _txt, const O obj) {
if (_txt.match(rgx.inline_image)) {
_txt = _txt
.replaceAll(rgx.inline_image,
("$1 $6"))
.replaceAll(
rgx.inline_link_empty,
("$1"));
}
return _txt;
}
@safe string markup(O)(const O obj) {
/+ markup TODO +/
string _txt = obj.text;
_txt = _special_characters(_txt, obj); // TODO & why both obj & obj.text, consider also in output_xmls.org
if (obj.metainfo.is_a == "code" || obj.metainfo.is_a == "verse" || obj.metainfo.is_a == "block") {
_txt = replaceAll!(m => _preserve_white_spaces(m[1], obj))(_txt, rgx.spaces_keep);
} // check that this does what you want, keep: leading spaces (indent) & more than single spaces within text
// _txt = _preserve_white_spaces(_txt, obj); // (obj.metainfo.is_a == "code" || obj.metainfo.is_a == "verse" || obj.metainfo.is_a == "block")
_txt = _font_face(_txt);
_txt = _images(_txt, obj); // (obj.metainfo.is_a != "code")
_txt = _links(_txt, obj); // (obj.metainfo.is_a != "code")
_txt = _empty_line_break(_txt, obj); // (obj.metainfo.is_a == "code" || obj.metainfo.is_a == "verse" || obj.metainfo.is_a == "block")
return _txt;
}
@safe string heading(O,M)(
const O obj,
const M doc_matters,
) {
assert(obj.metainfo.is_of_part == "body" || "frontmatter" || "backmatter");
assert(obj.metainfo.is_of_section == "body" || "toc" || "endnotes" || "glossary" || "bibliography" || "bookindex" || "blurb");
assert(obj.metainfo.is_of_type == "para");
assert(obj.metainfo.is_a == "heading");
string _o_txt_odt = markup(obj);
if (obj.metainfo.dummy_heading
&& (obj.metainfo.is_a == "toc" || obj.metainfo.is_a == "heading")) {
_o_txt_odt = "";
} else if (obj.metainfo.is_a == "toc") {
_o_txt_odt = format(q"┃%s
%s%s%s
┃",
_break_page,
obj.metainfo.heading_lev_markup,
obj.metainfo.heading_lev_markup,
_tags(obj),
_o_txt_odt,
obj_num(obj),
);
} else {
_o_txt_odt = _footnotes(_o_txt_odt);
_o_txt_odt = format(q"┃%s
%s%s%s
┃",
_break_page,
obj.metainfo.heading_lev_markup,
obj.metainfo.heading_lev_markup,
obj.metainfo.object_number,
obj.metainfo.object_number,
_tags(obj),
_o_txt_odt,
obj_num(obj),
);
}
return _o_txt_odt;
}
@safe string para(O,M)(
const O obj,
const M doc_matters,
) {
assert(obj.metainfo.is_of_part == "body" || "frontmatter" || "backmatter");
assert(obj.metainfo.is_of_section == "body" || "toc" || "endnotes" || "glossary" || "bibliography" || "bookindex" || "blurb");
assert(obj.metainfo.is_of_type == "para");
assert(obj.metainfo.is_a == "para" || "toc" || "endnote" || "glossary" || "bibliography" || "bookindex" || "blurb");
string _o_txt_odt;
if (obj.metainfo.dummy_heading
&& (obj.metainfo.is_a == "toc" || obj.metainfo.is_a == "heading")) {
_o_txt_odt = "";
} else {
_o_txt_odt = markup(obj);
_o_txt_odt = _footnotes(_o_txt_odt);
_o_txt_odt = _indent(_o_txt_odt, obj); // final setting?
}
return _o_txt_odt;
}
@safe string quote(O,M)(
const O obj,
const M doc_matters,
) {
assert(obj.metainfo.is_of_part == "body");
assert(obj.metainfo.is_of_section == "body" || "glossary" || "bibliography" || "bookindex" || "blurb");
assert(obj.metainfo.is_of_type == "block");
assert(obj.metainfo.is_a == "quote");
string _o_txt_odt = markup(obj);
_o_txt_odt = _footnotes(_o_txt_odt); // decide
return _o_txt_odt;
}
@safe string group(O,M)(
const O obj,
const M doc_matters,
) {
assert(obj.metainfo.is_of_part == "body");
assert(obj.metainfo.is_of_section == "body" || "glossary" || "bibliography" || "bookindex" || "blurb");
assert(obj.metainfo.is_of_type == "block");
assert(obj.metainfo.is_a == "group");
string _o_txt_odt = markup(obj);
/+ TODO
- split lines
- only double newlines (paragraph delimiter), (not line breaks, single new lines)
- no hard space indentation
+/
string[] _block_lines = (_o_txt_odt).split(rgx.br_linebreaks_newlines);
_o_txt_odt = _block_type_delimiters(_block_lines, obj);
return _o_txt_odt;
}
@safe string block(O,M)(
const O obj,
const M doc_matters,
) {
assert(obj.metainfo.is_of_part == "body");
assert(obj.metainfo.is_of_section == "body" || "glossary" || "bibliography" || "bookindex" || "blurb");
assert(obj.metainfo.is_of_type == "block");
assert(obj.metainfo.is_a == "block");
string _o_txt_odt = markup(obj);
string[] _block_lines = (_o_txt_odt).split(rgx.br_linebreaks_newlines);
_o_txt_odt = _block_type_delimiters(_block_lines, obj);
return _o_txt_odt;
}
@safe string verse(O,M)(
const O obj,
const M doc_matters,
) {
assert(obj.metainfo.is_of_part == "body");
assert(obj.metainfo.is_of_section == "body" || "glossary" || "bibliography" || "bookindex" || "blurb");
assert(obj.metainfo.is_of_type == "block");
assert(obj.metainfo.is_a == "verse");
string _o_txt_odt = markup(obj);
string[] _block_lines = (_o_txt_odt).split(rgx.br_linebreaks_newlines);
_o_txt_odt = _block_type_delimiters(_block_lines, obj);
return _o_txt_odt;
}
@safe string code(O,M)(
const O obj,
const M doc_matters,
) {
assert(obj.metainfo.is_of_part == "body");
assert(obj.metainfo.is_of_section == "body");
assert(obj.metainfo.is_of_type == "block");
assert(obj.metainfo.is_a == "code");
string _o_txt_odt = markup(obj);
/+ TODO
- split lines
- each line including empty lines
- hard space indentation
- "^[ ]"
- count number only at beginning of line and replace each
+/
string[] _block_lines = (_o_txt_odt).split(rgx.br_linebreaks_newlines);
string _block = "";
foreach (i, _line; _block_lines) {
if (i == 1) {
_block ~= format(q"┃
%s
┃",
obj.metainfo.object_number,
obj.metainfo.object_number,
_line,
);
} else {
_block ~= format(q"┃
%s┃",
_line);
}
}
_block ~= format(q"┃
「%s」
┃",
obj_num(obj));
_o_txt_odt = _block;
return _o_txt_odt;
}
@safe Tuple!(string, string) tablarize(O)(
const O obj,
string _txt,
) {
string[] _table_rows = (_txt).split(rgx.table_delimiter_row);
string[] _table_cols;
string _table;
string _tablenote;
foreach(row_idx, row; _table_rows) {
_table_cols = row.split(rgx.table_delimiter_col);
_table ~= "";
foreach(col_idx, cell; _table_cols) {
if ((_table_cols.length == 1)
&& (_table_rows.length <= row_idx+2)) { // check row_idx+2 (rather than == ++row_idx)
_tablenote ~= cell;
} else {
_table ~= format(q"┃
%s
┃",
(row_idx == 0 && obj.table.heading) ? "Table_Heading" : "P_table_cell",
cell,
);
}
}
_table ~= "";
}
Tuple!(string, string) t = tuple(
_table,
_tablenote,
);
return t;
}
int _table_number = 0;
@safe string table(O,M)(
const O obj,
const M doc_matters,
) {
assert(obj.metainfo.is_of_part == "body");
assert(obj.metainfo.is_of_section == "body");
assert(obj.metainfo.is_of_type == "block");
assert(obj.metainfo.is_a == "table");
string _o_txt_odt = markup(obj);
Tuple!(string, string) t = tablarize(obj, _o_txt_odt);
string _note = t[1];
_o_txt_odt = format(q"┃
%s
「%s」
┃",
_table_number++,
obj.metainfo.object_number,
obj.metainfo.object_number,
obj.table.number_of_columns,
t[0],
obj.metainfo.object_number,
// _note,
);
return _o_txt_odt;
}
}
}
template outputODT() {
import
doc_reform.io_out,
doc_reform.io_out.rgx,
doc_reform.io_out.rgx_xhtml;
import
std.digest.sha,
std.file,
std.outbuffer,
std.uri,
std.zip,
std.conv : to;
import
doc_reform.io_out.create_zip_file,
doc_reform.io_out.xmls,
doc_reform.io_out.xmls_css;
mixin InternalMarkup;
mixin spineRgxOut;
mixin spineRgxXHTML;
static auto rgx = RgxO();
static auto rgx_xhtml = RgxXHTML();
// mixin outputXmlODT;
@safe string odt_head(I)(I doc_matters) {
string _has_tables = format(q"┃
┃",);
string _odt_head = format(q"┃
%s
┃",
(doc_matters.has.tables > 0) ? _has_tables : "",
);
return _odt_head;
}
@safe string odt_body(D,I)(
const D doc_abstraction,
I doc_matters,
) {
mixin formatODT;
auto odt_format = formatODT();
string delimit = "";
string doc_odt = "";
string _txt = "";
foreach (part; doc_matters.has.keys_seq.scroll) {
foreach (obj; doc_abstraction[part]) {
switch (obj.metainfo.is_of_part) {
case "frontmatter": assert(part == "head" || "toc");
switch (obj.metainfo.is_of_type) {
case "para":
switch (obj.metainfo.is_a) {
case "heading":
_txt = delimit ~ odt_format.heading(obj, doc_matters);
goto default;
case "toc":
_txt = odt_format.para(obj, doc_matters);
goto default;
default:
doc_odt ~= _txt;
_txt = "";
break;
}
break;
default: break;
}
break;
case "body": assert(part == "body" || "head"); // surprise
switch (obj.metainfo.is_of_type) {
case "para":
switch (obj.metainfo.is_a) {
case "heading":
_txt = delimit ~ odt_format.heading(obj, doc_matters);
goto default;
case "para":
_txt = odt_format.para(obj, doc_matters);
goto default;
default:
doc_odt ~= _txt;
_txt = "";
break;
}
break;
case "block":
switch (obj.metainfo.is_a) {
case "quote":
_txt = odt_format.quote(obj, doc_matters);
goto default;
case "group":
_txt = odt_format.group(obj, doc_matters);
goto default;
case "block":
_txt = odt_format.block(obj, doc_matters);
goto default;
case "verse":
_txt = odt_format.verse(obj, doc_matters);
goto default;
case "code":
_txt = odt_format.code(obj, doc_matters);
goto default;
case "table":
_txt = odt_format.table(obj, doc_matters);
goto default;
default:
doc_odt ~= _txt;
_txt = "";
break;
}
break;
default: break;
}
break;
case "backmatter":
assert(part == "endnotes" || "glossary" || "bibliography" || "bookindex" || "blurb" || "tail");
switch (obj.metainfo.is_of_type) {
case "para":
switch (obj.metainfo.is_a) {
case "heading":
_txt = delimit ~ odt_format.heading(obj, doc_matters);
goto default;
case "endnote": assert(part == "endnotes");
_txt = odt_format.para(obj, doc_matters);
goto default;
case "glossary": assert(part == "glossary");
_txt = odt_format.para(obj, doc_matters);
goto default;
case "bibliography": assert(part == "bibliography");
_txt = odt_format.para(obj, doc_matters);
goto default;
case "bookindex": assert(part == "bookindex");
_txt = odt_format.para(obj, doc_matters);
goto default;
case "blurb": assert(part == "blurb");
_txt = odt_format.para(obj, doc_matters);
goto default;
default:
doc_odt ~= _txt;
_txt = "";
break;
}
break;
default: break;
}
break;
case "comment":
break;
default:
{ /+ debug +/
if (doc_matters.opt.action.debug_do
&& doc_matters.opt.action.vox_gt1) {
writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_part);
writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a);
writeln(__FILE__, ":", __LINE__, ": ", obj.text);
}
}
break;
}
}
}
return doc_odt;
}
@safe string odt_tail() {
string _odt_tail = format(q"┃spine: <www.doc_reform.org> and <www.sisudoc.org>
┃",);
return _odt_tail;
}
@safe string content_xml(D,I)(
const D doc_abstraction,
I doc_matters,
) {
string _content_xml;
string break_line = (doc_matters.opt.action.debug_do) ? "\n" : "";
string odt_break_page = format(q"┃┃",);
string br_pg = format(q"┃┃",);
_content_xml ~= odt_head(doc_matters);
_content_xml ~= odt_body(doc_abstraction, doc_matters);
_content_xml ~= odt_tail;
return _content_xml;
}
@safe string manifest_xml(M)(
auto ref M doc_matters,
) {
string _bullet = format(q"┃┃");
string[] _images = [ _bullet ];
foreach (image; doc_matters.srcs.image_list) {
_images ~= format(q"┃ ┃", image);
}
string _manifest_xml = format(q"┃
%s
┃",
_images.join("\n"),
);
return _manifest_xml;
}
@safe void images_cp(M)(
auto ref M doc_matters,
) {
{ /+ (copy odt images) +/
import doc_reform.io_out.paths_output;
auto pth_odt = spinePathsODT!()(doc_matters);
foreach (image; doc_matters.srcs.image_list) {
auto fn_src_in = doc_matters.src.image_dir_path ~ "/" ~ image;
auto fn_src_out_file = pth_odt.image_dir("fs") ~ "/" ~ image;
auto fn_src_out_zip = pth_odt.image_dir("zip") ~ "/" ~ image;
if (exists(fn_src_in)) {
if (doc_matters.opt.action.debug_do) {
if (doc_matters.opt.action.debug_do) {
fn_src_in.copy(fn_src_out_file);
}
}
}
}
}
// return 0;
}
@safe string meta_xml(M)(
auto ref M doc_matters,
) {
/+ (meta_xml includes output time-stamp) +/
string _meta_xml = format(q"┃
%s
%s
%s
en-US
┃",
doc_matters.generator_program.name_and_version,
doc_matters.generated_time,
doc_matters.generated_time,
);
return _meta_xml;
}
void dirtree(I)(
I doc_matters,
) {
import doc_reform.io_out.paths_output;
auto pth_odt = spinePathsODT!()(doc_matters);
if (doc_matters.opt.action.debug_do) { /+ (dir tree) +/
if (!exists(pth_odt.meta_inf_dir("fs"))) {
pth_odt.meta_inf_dir("fs").mkdirRecurse;
}
if (!exists(pth_odt.image_dir("fs"))) {
pth_odt.image_dir("fs").mkdirRecurse;
}
}
if (!exists(pth_odt.base_pth)) {
pth_odt.base_pth.mkdirRecurse;
}
// return 0;
}
@safe string mimetype() {
string mimetype_ = format(q"┃application/vnd.oasis.opendocument.text┃");
return mimetype_;
}
@safe string manifest_rdf() {
string _manifest_rdf = format(q"┃
┃");
return _manifest_rdf;
}
@safe string settings_xml() {
string _settings_xml = format(q"┃
0
0
0
0
true
false
view2
0
0
0
0
0
0
0
2
true
100
false
true
false
false
true
true
false
true
false
false
false
false
false
true
true
0
false
false
false
false
true
false
false
false
false
true
true
false
false
true
false
true
false
high-resolution
1
0
true
false
true
false
true
false
true
false
true
false
true
true
false
true
true
true
false
false
false
0
false
false
true
true
┃");
return _settings_xml;
}
@safe string styles_xml() {
string _styles_xml = format(q"┃
┃");
return _styles_xml;
}
void writeOutputODT(W,I)(
const W odt_content,
I doc_matters,
) {
auto pth_odt = spinePathsODT!()(doc_matters);
auto fn_odt = pth_odt.odt_file;
auto zip = new ZipArchive(); // ZipArchive zip = new ZipArchive();
void ODTzip()(string contents, string fn) {
auto zip_arc_member_file = new ArchiveMember();
zip_arc_member_file.name = fn;
auto zip_data = new OutBuffer();
(doc_matters.opt.action.debug_do)
? zip_data.write(contents.dup)
: zip_data.write(contents.dup
.replaceAll(rgx.spaces_line_start, "")
.replaceAll(rgx.newline, "")
.strip
);
zip_arc_member_file.expandedData = zip_data.toBytes();
zip.addMember(zip_arc_member_file);
createZipFile!()(fn_odt, zip.build());
}
try {
if (!exists(pth_odt.base_pth)) { // check
pth_odt.base_pth.mkdirRecurse;
}
string fn;
File f;
{ fn = pth_odt.mimetype("zip");
ODTzip(odt_content.mimetype, fn);
}
{ fn = pth_odt.manifest_rdf("zip");
ODTzip(odt_content.manifest_rdf, fn);
}
{ fn = pth_odt.settings_xml("zip");
ODTzip(odt_content.settings_xml, fn);
}
{ fn = pth_odt.styles_xml("zip");
ODTzip(odt_content.styles_xml, fn);
}
{ fn = pth_odt.content_xml("zip");
ODTzip(odt_content.content_xml, fn);
}
{ fn = pth_odt.manifest_xml("zip");
ODTzip(odt_content.manifest_xml, fn);
}
{ fn = pth_odt.meta_xml("zip");
ODTzip(odt_content.meta_xml, fn);
}
{ /+ (images) +/
foreach (image; doc_matters.srcs.image_list) {
auto fn_src = doc_matters.src.image_dir_path ~ "/" ~ image;
auto fn_out = pth_odt.image_dir("zip") ~ "/" ~ image;
if (exists(fn_src)) {
{
auto zip_arc_member_file = new ArchiveMember();
zip_arc_member_file.name = fn_out;
auto zip_data = new OutBuffer();
zip_data.write(cast(char[]) ((fn_src).read));
zip_arc_member_file.expandedData = zip_data.toBytes();
zip.addMember(zip_arc_member_file);
createZipFile!()(fn_odt, zip.build());
}
}
}
}
if (doc_matters.opt.action.vox_gt0) {
writeln(" ", pth_odt.odt_file);
}
} catch (ErrnoException ex) {
// Handle error
}
if (doc_matters.opt.action.debug_do) {
pth_odt.mimetype("fs"); /+ (mimetype) +/
pth_odt.manifest_rdf("fs"); /+ (manifest.rdf) +/
pth_odt.settings_xml("fs"); /+ (settings.xml) +/
pth_odt.styles_xml("fs"); /+ (styles_xml) +/
pth_odt.content_xml("fs");
pth_odt.manifest_xml("fs");
pth_odt.meta_xml("fs");
}
}
void outputODT(D,I)(
const D doc_abstraction,
I doc_matters,
) {
struct ODT {
/+ fixed output +/
string mimetype;
string manifest_rdf;
string settings_xml;
string styles_xml;
/+ variable output +/
string content_xml; // substantive content
string manifest_xml; // image list changes
string meta_xml; // time stamp
}
// auto pth_odt = spinePathsODT!()(doc_matters);
auto odt = ODT();
odt.mimetype = mimetype;
odt.manifest_rdf = manifest_rdf;
odt.settings_xml = settings_xml;
odt.styles_xml = styles_xml;
odt.content_xml = content_xml(doc_abstraction, doc_matters);
odt.manifest_xml = manifest_xml(doc_matters);
odt.meta_xml = meta_xml(doc_matters);
odt.writeOutputODT(doc_matters);
dirtree(doc_matters);
images_cp(doc_matters); // copy images
}
}