Skip to content

Commit

Permalink
html writer + formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
andiwand committed Dec 24, 2023
1 parent 3cfdf8f commit 85e81d2
Show file tree
Hide file tree
Showing 13 changed files with 634 additions and 348 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ add_library(odr
"src/odr/internal/html/document.cpp"
"src/odr/internal/html/document_style.cpp"
"src/odr/internal/html/document_element.cpp"
"src/odr/internal/html/html_writer.cpp"
"src/odr/internal/html/image_file.cpp"
"src/odr/internal/html/text_file.cpp"

Expand Down
4 changes: 4 additions & 0 deletions src/odr/html.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ struct HtmlConfig {
bool spreadsheet_limit_by_content{true};
// spreadsheet gridlines
HtmlTableGridlines spreadsheet_gridlines{HtmlTableGridlines::soft};

// formatting
bool format_html{false};
std::uint8_t html_indent{2};
};

class Html final {
Expand Down
37 changes: 0 additions & 37 deletions src/odr/internal/html/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,6 @@

namespace odr::internal {

const char *html::doctype() noexcept {
// clang-format off
return R"V0G0N(<!DOCTYPE html>
)V0G0N";
// clang-format on
}

const char *html::default_headers() noexcept {
// clang-format off
return R"V0G0N(<meta charset="UTF-8"/>
<base target="_blank"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=yes"/>
<title>odr</title>)V0G0N";
// clang-format on
}

std::string html::body_attributes(const HtmlConfig &config) noexcept {
std::string result;

result += "class=\"";
switch (config.spreadsheet_gridlines) {
case HtmlTableGridlines::soft:
result += "odr-gridlines-soft";
break;
case HtmlTableGridlines::hard:
result += "odr-gridlines-hard";
break;
case HtmlTableGridlines::none:
default:
result += "odr-gridlines-none";
break;
}
result += "\"";

return result;
}

std::string html::escape_text(std::string text) noexcept {
if (text.empty()) {
return text;
Expand Down
6 changes: 0 additions & 6 deletions src/odr/internal/html/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@ struct HtmlConfig;

namespace odr::internal::html {

const char *doctype() noexcept;

const char *default_headers() noexcept;

std::string body_attributes(const HtmlConfig &config) noexcept;

std::string escape_text(std::string text) noexcept;

std::string color(const Color &color) noexcept;
Expand Down
119 changes: 68 additions & 51 deletions src/odr/internal/html/document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,56 +8,54 @@

#include <odr/internal/abstract/file.hpp>
#include <odr/internal/common/path.hpp>
#include <odr/internal/html/common.hpp>
#include <odr/internal/html/document_element.hpp>
#include <odr/internal/html/document_style.hpp>
#include <odr/internal/html/html_writer.hpp>
#include <odr/internal/resource.hpp>
#include <odr/internal/util/stream_util.hpp>
#include <odr/internal/util/string_util.hpp>

#include <fstream>
#include <iostream>

namespace odr::internal {

namespace {

void front(const Document &document, const std::string &path, std::ostream &out,
const HtmlConfig &config) {
out << internal::html::doctype();
out << "<html>\n";
out << "<head>\n";
void front(const Document &document, const std::string &path,
internal::html::HtmlWriter &out, const HtmlConfig &config) {
out.write_begin();
out.write_header_begin();
out.write_header_charset("UTF-8");
out.write_header_target("_blank");
out.write_header_title("odr");
if (document.document_type() == DocumentType::text &&
config.text_document_margin) {
out << R"V0G0N(<meta charset="UTF-8"/>
<base target="_blank"/>
<meta name="viewport" content="width=device-width,user-scalable=yes"/>
<title>odr</title>)V0G0N";
out.write_header_viewport("width=device-width,user-scalable=yes");
} else {
out << internal::html::default_headers();
out.write_header_viewport(
"width=device-width,initial-scale=1.0,user-scalable=yes");
}
out << "\n";

if (config.embed_resources) {
out << "<style>\n";
out.write_header_style_begin();
util::stream::pipe(
*Resources::instance().filesystem()->open("odr.css")->stream(), out);
*Resources::instance().filesystem()->open("odr.css")->stream(),
out.out());
if (document.document_type() == DocumentType::spreadsheet) {
util::stream::pipe(*Resources::instance()
.filesystem()
->open("odr_spreadsheet.css")
->stream(),
out);
out.out());
}
out << "\n";
out << "</style>\n";
out.write_header_style_end();
} else {
auto odr_css_path =
common::Path(config.external_resource_path).join("odr.css");
if (config.relative_resource_paths) {
odr_css_path = common::Path(odr_css_path).rebase(path);
}
out << "<link rel=\"stylesheet\" href=\"" << odr_css_path << "\">\n";
out.write_header_style(odr_css_path.string().c_str());
if (document.document_type() == DocumentType::spreadsheet) {
auto odr_spreadsheet_css_path =
common::Path(config.external_resource_path)
Expand All @@ -66,37 +64,48 @@ void front(const Document &document, const std::string &path, std::ostream &out,
odr_spreadsheet_css_path =
common::Path(odr_spreadsheet_css_path).rebase(path);
}
out << "<link rel=\"stylesheet\" href=\"" << odr_spreadsheet_css_path
<< "\">\n";
out.write_header_style(odr_spreadsheet_css_path.string().c_str());
}
}

out << "</head>\n";
out << "<body " << internal::html::body_attributes(config) << ">\n";
}
out.write_header_end();

std::string body_clazz;
switch (config.spreadsheet_gridlines) {
case HtmlTableGridlines::soft:
body_clazz = "odr-gridlines-soft";
break;
case HtmlTableGridlines::hard:
body_clazz = "odr-gridlines-hard";
break;
case HtmlTableGridlines::none:
default:
body_clazz = "odr-gridlines-none";
break;
}

void back(const Document &, const std::string &path, std::ostream &out,
const HtmlConfig &config) {
out << "\n";
out.write_body_begin({.clazz = body_clazz});
}

void back(const Document &, const std::string &path,
internal::html::HtmlWriter &out, const HtmlConfig &config) {
if (config.embed_resources) {
out << "<script type=\"text/javascript\">\n";
out.write_script_begin();
util::stream::pipe(
*Resources::instance().filesystem()->open("odr.js")->stream(), out);
out << "\n";
out << "</script>\n";
*Resources::instance().filesystem()->open("odr.js")->stream(),
out.out());
out.write_script_end();
} else {
auto odr_js_path =
common::Path(config.external_resource_path).join("odr.js");
if (config.relative_resource_paths) {
odr_js_path = common::Path(odr_js_path).rebase(path);
}
out << "<script type=\"text/javascript\" src=\"" << odr_js_path
<< "\"></script>";
out.write_script(odr_js_path.string().c_str());
}

out << "</body>\n";
out << "</html>";
out.write_body_end();
out.write_end();
}

std::string fill_path_variables(const std::string &path,
Expand All @@ -107,10 +116,8 @@ std::string fill_path_variables(const std::string &path,
return result;
}

std::ofstream output(const std::string &path,
std::optional<std::uint32_t> index = {}) {
auto filled_path = fill_path_variables(path, index);
std::ofstream out(filled_path);
std::ofstream output(const std::string &path) {
std::ofstream out(path);
if (!out.is_open()) {
throw FileWriteError();
}
Expand Down Expand Up @@ -139,24 +146,28 @@ Html html::translate_text_document(const Document &document,
const HtmlConfig &config) {
auto filled_path =
fill_path_variables(path + "/" + config.text_document_output_file_name);
auto out = output(filled_path);
auto ostream = output(filled_path);
internal::html::HtmlWriter out(ostream, config.format_html,
config.html_indent);

auto root = document.root_element();
auto element = root.text_root();

front(document, path, out, config);
if (config.text_document_margin) {
out << "<div";
out.write_element_begin("div");
auto page_layout = element.page_layout();
page_layout.height = {};
out << optional_style_attribute(translate_outer_page_style(page_layout));
out << ">";
out << "<div";
out << optional_style_attribute(translate_inner_page_style(page_layout));
out << ">";

out.write_element_begin("div",
{.style = translate_outer_page_style(page_layout)});
out.write_element_begin("div",
{.style = translate_inner_page_style(page_layout)});

translate_children(element.children(), out, config);
out << "</div>";
out << "</div>";

out.write_element_end("div");
out.write_element_end("div");
} else {
translate_children(element.children(), out, config);
}
Expand All @@ -174,7 +185,9 @@ Html html::translate_presentation(const Document &document,
for (auto child : document.root_element().children()) {
auto filled_path =
fill_path_variables(path + "/" + config.slide_output_file_name, i);
auto out = output(filled_path);
auto ostream = output(filled_path);
internal::html::HtmlWriter out(ostream, config.format_html,
config.html_indent);

front(document, path, out, config);
internal::html::translate_slide(child, out, config);
Expand All @@ -197,7 +210,9 @@ Html html::translate_spreadsheet(const Document &document,
for (auto child : document.root_element().children()) {
auto filled_path =
fill_path_variables(path + "/" + config.sheet_output_file_name, i);
auto out = output(filled_path);
auto ostream = output(filled_path);
internal::html::HtmlWriter out(ostream, config.format_html,
config.html_indent);

front(document, path, out, config);
translate_sheet(child, out, config);
Expand All @@ -219,7 +234,9 @@ Html html::translate_drawing(const Document &document, const std::string &path,
for (auto child : document.root_element().children()) {
auto filled_path =
fill_path_variables(path + "/" + config.page_output_file_name, i);
auto out = output(filled_path);
auto ostream = output(filled_path);
internal::html::HtmlWriter out(ostream, config.format_html,
config.html_indent);

front(document, path, out, config);
internal::html::translate_page(child, out, config);
Expand Down
Loading

0 comments on commit 85e81d2

Please sign in to comment.