diff --git a/CHANGELOG.md b/CHANGELOG.md index 56aa8ec5a..d7e905737 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ The release run heads these entries with the version and opens a fresh ## Unreleased +- CLI `meta` accepts every decoded file type, `server` detects the input instead + of forcing ZIP, and `back_translate` supports editable text and CSV files. + The CLI container preserves executable permissions and forwards arguments. + - WebAssembly CSV editing, saving and rendering share one document. CSV and Markdown capability and locale queries now use their document interfaces. diff --git a/cli/Dockerfile b/cli/Dockerfile index 3657ec2ed..b48058745 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,6 +1,6 @@ FROM ubuntu:26.04@sha256:f3d28607ddd78734bb7f71f117f3c6706c666b8b76cbff7c9ff6e5718d46ff64 -RUN mkdir -p /install/bin -ADD install/bin /install/bin +COPY install/bin /install/bin +RUN chmod +x /install/bin/* -ENTRYPOINT /install/bin/translate +ENTRYPOINT ["/install/bin/translate"] diff --git a/cli/src/back_translate.cpp b/cli/src/back_translate.cpp index 7adde03a4..1ec6537c3 100644 --- a/cli/src/back_translate.cpp +++ b/cli/src/back_translate.cpp @@ -24,19 +24,25 @@ int main(const int argc, char **argv) { const std::string diff_path{argv[2]}; const std::string output{argv[3]}; - const DocumentFile document_file = open(input).as_document_file(); + const DecodedFile file = open(input); - if (document_file.password_encrypted()) { + if (file.password_encrypted()) { ODR_FATAL(logger, "encrypted documents are not supported"); return 1; } - const Document document = document_file.document(); - const std::string diff = internal::util::file::read(diff_path); - document.edit(diff); - - document.save(output); + if (file.is_text_file()) { + const TextFile text = file.as_text_file(); + text.edit(diff, logger); + text.save(output); + } else { + const Document document = file.is_csv_file() + ? file.as_csv_file().document() + : file.as_document_file().document(); + document.edit(diff, logger); + document.save(output); + } return 0; } catch (const std::exception &e) { diff --git a/cli/src/meta.cpp b/cli/src/meta.cpp index 14d7d29b6..27978d690 100644 --- a/cli/src/meta.cpp +++ b/cli/src/meta.cpp @@ -26,23 +26,22 @@ int main(const int argc, char **argv) { password = argv[2]; } - DocumentFile document_file = open(input).as_document_file(); + DecodedFile file = open(input); - if (document_file.password_encrypted()) { + if (file.password_encrypted()) { if (!password) { ODR_FATAL(logger, "document encrypted but no password given"); return 2; } try { - document_file = document_file.decrypt(*password); + file = file.decrypt(*password); } catch (const WrongPasswordError &) { ODR_FATAL(logger, "wrong password"); return 1; } } - const auto json = - internal::util::meta::meta_to_json(document_file.file_meta()); + const auto json = internal::util::meta::meta_to_json(file.file_meta()); std::cout << json.dump(4) << '\n'; return 0; diff --git a/cli/src/server.cpp b/cli/src/server.cpp index 537aee183..5cd329f96 100644 --- a/cli/src/server.cpp +++ b/cli/src/server.cpp @@ -21,17 +21,14 @@ int main(const int argc, char **argv) { try { const Logger logger = Logger::create_stdio("odr-server", LogLevel::verbose); - std::string input{argv[1]}; + const std::string input{argv[1]}; std::optional password; if (argc >= 3) { password = argv[2]; } - // the server offers the container's own entries beside the render, so a - // package is opened as the zip it is - DecodedFile decoded_file = - open(input, DecodeOptions::as(FileType::zip), logger); + DecodedFile decoded_file = open(input, {}, logger); if (decoded_file.password_encrypted()) { if (!password) { @@ -64,7 +61,7 @@ int main(const int argc, char **argv) { const HtmlService service = html::translate(decoded_file, html_config, logger); server.connect_service(service, prefix); - const HtmlViews views = service.list_views(); + const HtmlViews &views = service.list_views(); ODR_INFO(logger, "hosted decoded file with id: " << prefix); for (const auto &view : views) { ODR_INFO(logger, base_url << "/file/" << prefix << "/" << view.path());