diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index c5d81238..2efdd3b4 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -215,7 +215,7 @@ jobs: with: python-version: 3.12 - name: install python dependencies - run: pip install htmlcmp==1.0.12 + run: pip install htmlcmp==1.2.1 - name: download binaries uses: actions/download-artifact@v4 diff --git a/cli/src/translate.cpp b/cli/src/translate.cpp index d294d274..90c49494 100644 --- a/cli/src/translate.cpp +++ b/cli/src/translate.cpp @@ -36,6 +36,7 @@ int main(const int argc, char **argv) { HtmlConfig config; config.editable = true; + config.format_html = true; const std::string output_tmp = output + "/tmp"; std::filesystem::create_directories(output_tmp); diff --git a/src/odr/internal/html/common.cpp b/src/odr/internal/html/common.cpp index bc7e2103..2092e60c 100644 --- a/src/odr/internal/html/common.cpp +++ b/src/odr/internal/html/common.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include #include diff --git a/src/odr/internal/html/document.cpp b/src/odr/internal/html/document.cpp index a169a530..6ee895e5 100644 --- a/src/odr/internal/html/document.cpp +++ b/src/odr/internal/html/document.cpp @@ -440,9 +440,10 @@ class PageHtmlFragment final : public HtmlFragmentBase { namespace odr::internal { -odr::HtmlService html::create_document_service( - const Document &document, const std::string & /*cache_path*/, - HtmlConfig config, std::shared_ptr logger) { +HtmlService html::create_document_service(const Document &document, + const std::string & /*cache_path*/, + HtmlConfig config, + std::shared_ptr logger) { std::vector> fragments; if (document.document_type() == DocumentType::text) { diff --git a/src/odr/internal/html/document.hpp b/src/odr/internal/html/document.hpp index c337a4e7..39db1193 100644 --- a/src/odr/internal/html/document.hpp +++ b/src/odr/internal/html/document.hpp @@ -12,9 +12,9 @@ class Logger; namespace odr::internal::html { -odr::HtmlService create_document_service(const Document &document, - const std::string &cache_path, - HtmlConfig config, - std::shared_ptr logger); +HtmlService create_document_service(const Document &document, + const std::string &cache_path, + HtmlConfig config, + std::shared_ptr logger); } // namespace odr::internal::html diff --git a/src/odr/internal/html/filesystem.cpp b/src/odr/internal/html/filesystem.cpp index ef1f0820..189b29dd 100644 --- a/src/odr/internal/html/filesystem.cpp +++ b/src/odr/internal/html/filesystem.cpp @@ -148,9 +148,10 @@ class HtmlServiceImpl final : public HtmlService { namespace odr::internal { -odr::HtmlService html::create_filesystem_service( - const Filesystem &filesystem, const std::string & /*cache_path*/, - HtmlConfig config, std::shared_ptr logger) { +HtmlService html::create_filesystem_service(const Filesystem &filesystem, + const std::string & /*cache_path*/, + HtmlConfig config, + std::shared_ptr logger) { return odr::HtmlService(std::make_unique( filesystem, std::move(config), std::move(logger))); } diff --git a/src/odr/internal/html/filesystem.hpp b/src/odr/internal/html/filesystem.hpp index 7bc925bd..9241370c 100644 --- a/src/odr/internal/html/filesystem.hpp +++ b/src/odr/internal/html/filesystem.hpp @@ -4,7 +4,6 @@ #include namespace odr { -enum class FileType; struct HtmlConfig; class HtmlService; class Filesystem; @@ -13,9 +12,9 @@ class Logger; namespace odr::internal::html { -odr::HtmlService create_filesystem_service(const Filesystem &filesystem, - const std::string &cache_path, - HtmlConfig config, - std::shared_ptr logger); +HtmlService create_filesystem_service(const Filesystem &filesystem, + const std::string &cache_path, + HtmlConfig config, + std::shared_ptr logger); } diff --git a/src/odr/internal/html/html_writer.cpp b/src/odr/internal/html/html_writer.cpp index 5616ac54..0b487f12 100644 --- a/src/odr/internal/html/html_writer.cpp +++ b/src/odr/internal/html/html_writer.cpp @@ -83,8 +83,8 @@ void write_element_options(std::ostream &out, } // namespace -HtmlElementOptions &HtmlElementOptions::set_inline(const bool _inline_element) { - inline_element = _inline_element; +HtmlElementOptions &HtmlElementOptions::set_inline(const bool is_inline) { + inline_element = is_inline; return *this; } diff --git a/src/odr/internal/html/html_writer.hpp b/src/odr/internal/html/html_writer.hpp index 4228dfd8..056e5eb0 100644 --- a/src/odr/internal/html/html_writer.hpp +++ b/src/odr/internal/html/html_writer.hpp @@ -37,12 +37,12 @@ struct HtmlElementOptions { std::optional extra{}; - HtmlElementOptions &set_inline(bool); - HtmlElementOptions &set_close_type(HtmlCloseType); - HtmlElementOptions &set_attributes(std::optional); - HtmlElementOptions &set_style(std::optional); - HtmlElementOptions &set_class(std::optional); - HtmlElementOptions &set_extra(std::optional); + HtmlElementOptions &set_inline(bool is_inline); + HtmlElementOptions &set_close_type(HtmlCloseType _close_type); + HtmlElementOptions &set_attributes(std::optional _attributes); + HtmlElementOptions &set_style(std::optional _style); + HtmlElementOptions &set_class(std::optional _class); + HtmlElementOptions &set_extra(std::optional _extra); }; class HtmlWriter { diff --git a/src/odr/internal/html/image_file.cpp b/src/odr/internal/html/image_file.cpp index 314222a9..ab56b7fa 100644 --- a/src/odr/internal/html/image_file.cpp +++ b/src/odr/internal/html/image_file.cpp @@ -141,10 +141,10 @@ void html::translate_image_src(const ImageFile &image_file, std::ostream &out, } } -odr::HtmlService html::create_image_service(const ImageFile &image_file, - const std::string & /*cache_path*/, - HtmlConfig config, - std::shared_ptr logger) { +HtmlService html::create_image_service(const ImageFile &image_file, + const std::string & /*cache_path*/, + HtmlConfig config, + std::shared_ptr logger) { return odr::HtmlService(std::make_unique( image_file, std::move(config), std::move(logger))); } diff --git a/src/odr/internal/html/image_file.hpp b/src/odr/internal/html/image_file.hpp index 34b9b5ee..21afcaca 100644 --- a/src/odr/internal/html/image_file.hpp +++ b/src/odr/internal/html/image_file.hpp @@ -18,9 +18,9 @@ void translate_image_src(const File &file, std::ostream &out, void translate_image_src(const ImageFile &image_file, std::ostream &out, const HtmlConfig &config); -odr::HtmlService create_image_service(const ImageFile &image_file, - const std::string &cache_path, - HtmlConfig config, - std::shared_ptr logger); +HtmlService create_image_service(const ImageFile &image_file, + const std::string &cache_path, + HtmlConfig config, + std::shared_ptr logger); } // namespace odr::internal::html diff --git a/src/odr/internal/html/pdf_file.cpp b/src/odr/internal/html/pdf_file.cpp index be978ca6..ae24be14 100644 --- a/src/odr/internal/html/pdf_file.cpp +++ b/src/odr/internal/html/pdf_file.cpp @@ -210,10 +210,10 @@ class HtmlServiceImpl final : public HtmlService { namespace odr::internal { -odr::HtmlService html::create_pdf_service(const PdfFile &pdf_file, - const std::string & /*cache_path*/, - HtmlConfig config, - std::shared_ptr logger) { +HtmlService html::create_pdf_service(const PdfFile &pdf_file, + const std::string & /*cache_path*/, + HtmlConfig config, + std::shared_ptr logger) { return odr::HtmlService(std::make_unique( pdf_file, std::move(config), std::move(logger))); } diff --git a/src/odr/internal/html/pdf_file.hpp b/src/odr/internal/html/pdf_file.hpp index 9cf831b7..6e9cbbff 100644 --- a/src/odr/internal/html/pdf_file.hpp +++ b/src/odr/internal/html/pdf_file.hpp @@ -12,9 +12,8 @@ class Logger; namespace odr::internal::html { -odr::HtmlService create_pdf_service(const PdfFile &pdf_file, - const std::string &cache_path, - HtmlConfig config, - std::shared_ptr logger); +HtmlService create_pdf_service(const PdfFile &pdf_file, + const std::string &cache_path, HtmlConfig config, + std::shared_ptr logger); } diff --git a/src/odr/internal/html/text_file.cpp b/src/odr/internal/html/text_file.cpp index d1a4f460..c1021c31 100644 --- a/src/odr/internal/html/text_file.cpp +++ b/src/odr/internal/html/text_file.cpp @@ -4,6 +4,8 @@ #include #include +#include +#include #include #include #include @@ -66,52 +68,97 @@ class HtmlServiceImpl final : public HtmlService { HtmlResources write_text(HtmlWriter &out) const { HtmlResources resources; - const std::unique_ptr in = m_text_file.stream(); - out.write_begin(); out.write_header_begin(); + + // TODO charset out.write_header_charset("UTF-8"); out.write_header_target("_blank"); out.write_header_title("odr"); out.write_header_viewport( "width=device-width,initial-scale=1.0,user-scalable=yes"); - out.write_header_style_begin(); - out.write_raw("*{font-family:monospace;}"); - out.write_raw("td{padding-left:10px;padding-right:10px;}"); - out.write_header_style_end(); + + auto css_file = File( + AbsPath(config().resource_path).join(RelPath("text.css")).string()); + odr::HtmlResource document_css_resource = + HtmlResource::create(HtmlResourceType::css, "text/css", "text.css", + "text.css", css_file, true, false, true); + HtmlResourceLocation document_css_location = + config().resource_locator(document_css_resource, config()); + resources.emplace_back(std::move(document_css_resource), + document_css_location); + if (document_css_location.has_value()) { + out.write_header_style(document_css_location.value()); + } else { + out.write_header_style_begin(); + util::stream::pipe(*css_file.stream(), out.out()); + out.write_header_style_end(); + } + out.write_header_end(); out.write_body_begin(); - out.write_element_begin( - "table", - HtmlElementOptions().set_attributes(HtmlAttributesVector{ - {"cellpadding", "0"}, {"border", "0"}, {"cellspacing", "0"}})); - for (std::uint32_t line = 1;; ++line) { - out.write_element_begin("tr"); + out.write_element_begin("div", HtmlElementOptions().set_class("odr-text")); - out.write_element_begin("td", - HtmlElementOptions().set_inline(true).set_style( - "text-align:right;user-select:none;")); + out.write_element_begin("div", + HtmlElementOptions().set_class("odr-text-nr")); + std::unique_ptr in = m_text_file.stream(); + for (std::uint32_t line = 1; !in->eof(); ++line) { + out.write_element_begin("div", HtmlElementOptions().set_inline(true)); out.out() << line; - out.write_element_end("td"); + out.write_element_end("div"); - out.write_element_begin("td"); + NullStream ss_out; + util::stream::pipe_line(*in, ss_out, false); + } + out.write_element_end("div"); + + out.write_element_begin("div", + HtmlElementOptions().set_attributes( + [&](const HtmlAttributeWriterCallback &clb) { + clb("class", "odr-text-body odr-text-wrap"); + if (config().editable) { + clb("contenteditable", "true"); + } + })); + in = m_text_file.stream(); + while (!in->eof()) { + out.write_element_begin("div", HtmlElementOptions().set_inline(true)); std::ostringstream ss_out; util::stream::pipe_line(*in, ss_out, false); - out.out() << escape_text(ss_out.str()); - - out.write_element_end("td"); - out.write_element_end("tr"); - - if (in->eof()) { - break; + if (const std::string &line = ss_out.str(); line.empty()) { + out.write_element_begin( + "br", HtmlElementOptions().set_close_type(HtmlCloseType::trailing)); + } else { + out.out() << escape_text(ss_out.str()); } + + out.write_element_end("div"); + } + out.write_element_end("div"); + + out.write_element_end("div"); + + auto js_file = + File(AbsPath(config().resource_path).join(RelPath("text.js")).string()); + odr::HtmlResource document_js_resource = + HtmlResource::create(HtmlResourceType::js, "text/javascript", "text.js", + "text.js", js_file, true, false, true); + HtmlResourceLocation document_js_location = + config().resource_locator(document_js_resource, config()); + resources.emplace_back(std::move(document_js_resource), + document_js_location); + if (document_js_location.has_value()) { + out.write_script(document_js_location.value()); + } else { + out.write_script_begin(); + util::stream::pipe(*js_file.stream(), out.out()); + out.write_script_end(); } - out.write_element_end("table"); out.write_body_end(); out.write_end(); @@ -130,7 +177,7 @@ class HtmlServiceImpl final : public HtmlService { namespace odr::internal { -odr::HtmlService +HtmlService html::create_text_service(const TextFile &text_file, [[maybe_unused]] const std::string &cache_path, HtmlConfig config, std::shared_ptr logger) { diff --git a/src/odr/internal/html/text_file.hpp b/src/odr/internal/html/text_file.hpp index 7c6bd6bd..0c51eb23 100644 --- a/src/odr/internal/html/text_file.hpp +++ b/src/odr/internal/html/text_file.hpp @@ -12,9 +12,9 @@ class Logger; namespace odr::internal::html { -odr::HtmlService create_text_service(const TextFile &text_file, - const std::string &cache_path, - HtmlConfig config, - std::shared_ptr logger); +HtmlService create_text_service(const TextFile &text_file, + const std::string &cache_path, + HtmlConfig config, + std::shared_ptr logger); } diff --git a/src/odr/internal/html/wvware_wrapper.cpp b/src/odr/internal/html/wvware_wrapper.cpp index fecccd85..619685d9 100644 --- a/src/odr/internal/html/wvware_wrapper.cpp +++ b/src/odr/internal/html/wvware_wrapper.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -973,7 +972,7 @@ class HtmlServiceImpl final : public HtmlService { namespace odr::internal { -odr::HtmlService html::create_wvware_oldms_service( +HtmlService html::create_wvware_oldms_service( const WvWareLegacyMicrosoftFile &oldms_file, const std::string &cache_path, HtmlConfig config, std::shared_ptr logger) { return odr::HtmlService(std::make_unique( diff --git a/src/odr/internal/html/wvware_wrapper.hpp b/src/odr/internal/html/wvware_wrapper.hpp index d96eae59..35fe00b6 100644 --- a/src/odr/internal/html/wvware_wrapper.hpp +++ b/src/odr/internal/html/wvware_wrapper.hpp @@ -15,7 +15,7 @@ class WvWareLegacyMicrosoftFile; namespace odr::internal::html { -odr::HtmlService +HtmlService create_wvware_oldms_service(const WvWareLegacyMicrosoftFile &oldms_file, const std::string &cache_path, HtmlConfig config, std::shared_ptr logger); diff --git a/test/data/reference-output/odr-public b/test/data/reference-output/odr-public index ed13801a..089609c1 160000 --- a/test/data/reference-output/odr-public +++ b/test/data/reference-output/odr-public @@ -1 +1 @@ -Subproject commit ed13801a4d4d5c83ffecbb1b3430523d6ee4fcbe +Subproject commit 089609c1cd04d752bdd842630238a86ae97a6a7f diff --git a/test/scripts/compare_output_server.sh b/test/scripts/compare_output_server.sh index 4524e5ff..dfe7df96 100755 --- a/test/scripts/compare_output_server.sh +++ b/test/scripts/compare_output_server.sh @@ -17,5 +17,5 @@ docker run -ti \ -v $(pwd):/repo \ -p 8000:8000 \ --platform linux/amd64 \ - ghcr.io/opendocument-app/odr_core_test:1.0.18 \ + ghcr.io/opendocument-app/odr_core_test:1.2.1 \ compare-html-server /repo/$REF /repo/$OBS --compare --driver $DRIVER --port 8000 -vv