Skip to content

Commit 7690b8b

Browse files
authored
PDF to HTML (#349)
1 parent 60daf83 commit 7690b8b

25 files changed

Lines changed: 476 additions & 99 deletions

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ add_library(odr
114114
"src/odr/internal/html/filesystem.cpp"
115115
"src/odr/internal/html/html_writer.cpp"
116116
"src/odr/internal/html/image_file.cpp"
117+
"src/odr/internal/html/pdf_file.cpp"
117118
"src/odr/internal/html/text_file.cpp"
118119

119120
"src/odr/internal/json/json_file.cpp"
@@ -152,7 +153,7 @@ add_library(odr
152153
"src/odr/internal/pdf/pdf_document.cpp"
153154
"src/odr/internal/pdf/pdf_document_element.cpp"
154155
"src/odr/internal/pdf/pdf_document_parser.cpp"
155-
"src/odr/internal/pdf/pdf_object.cpp"
156+
"src/odr/internal/pdf/pdf_file.cpp"
156157
"src/odr/internal/pdf/pdf_file_parser.cpp"
157158
"src/odr/internal/pdf/pdf_graphics_operator.cpp"
158159
"src/odr/internal/pdf/pdf_graphics_operator_parser.cpp"

src/odr/exceptions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ NoOpenDocumentFile::NoOpenDocumentFile()
4444
NoOfficeOpenXmlFile::NoOfficeOpenXmlFile()
4545
: std::runtime_error("not an office open xml file") {}
4646

47+
NoPdfFile::NoPdfFile() : std::runtime_error("not a pdf file") {}
48+
4749
NoXml::NoXml() : std::runtime_error("not xml") {}
4850

4951
UnsupportedCryptoAlgorithm::UnsupportedCryptoAlgorithm()

src/odr/exceptions.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ struct NoOfficeOpenXmlFile final : public std::runtime_error {
8080
NoOfficeOpenXmlFile();
8181
};
8282

83+
struct NoPdfFile final : public std::runtime_error {
84+
NoPdfFile();
85+
};
86+
8387
struct NoXml final : public std::runtime_error {
8488
NoXml();
8589
};

src/odr/file.cpp

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <odr/internal/abstract/file.hpp>
88
#include <odr/internal/common/file.hpp>
99
#include <odr/internal/open_strategy.hpp>
10+
#include <odr/internal/pdf/pdf_file.hpp>
1011

1112
#include <optional>
1213
#include <utility>
@@ -89,9 +90,7 @@ DecodedFile::DecodedFile(const std::string &path, FileType as)
8990

9091
DecodedFile::operator bool() const { return m_impl.operator bool(); }
9192

92-
FileType DecodedFile::file_type() const noexcept {
93-
return m_impl->file_meta().type;
94-
}
93+
FileType DecodedFile::file_type() const noexcept { return m_impl->file_type(); }
9594

9695
FileCategory DecodedFile::file_category() const noexcept {
9796
return m_impl->file_category();
@@ -101,6 +100,30 @@ FileMeta DecodedFile::file_meta() const noexcept { return m_impl->file_meta(); }
101100

102101
File DecodedFile::file() const { return File(m_impl->file()); }
103102

103+
bool DecodedFile::is_text_file() const {
104+
return std::dynamic_pointer_cast<internal::abstract::TextFile>(m_impl) !=
105+
nullptr;
106+
}
107+
108+
bool DecodedFile::is_image_file() const {
109+
return std::dynamic_pointer_cast<internal::abstract::ImageFile>(m_impl) !=
110+
nullptr;
111+
}
112+
113+
bool DecodedFile::is_archive_file() const {
114+
return std::dynamic_pointer_cast<internal::abstract::ArchiveFile>(m_impl) !=
115+
nullptr;
116+
}
117+
118+
bool DecodedFile::is_document_file() const {
119+
return std::dynamic_pointer_cast<internal::abstract::DocumentFile>(m_impl) !=
120+
nullptr;
121+
}
122+
123+
bool DecodedFile::is_pdf_file() const {
124+
return std::dynamic_pointer_cast<internal::pdf::PdfFile>(m_impl) != nullptr;
125+
}
126+
104127
TextFile DecodedFile::text_file() const {
105128
if (auto text_file =
106129
std::dynamic_pointer_cast<internal::abstract::TextFile>(m_impl)) {
@@ -133,6 +156,14 @@ DocumentFile DecodedFile::document_file() const {
133156
throw NoDocumentFile();
134157
}
135158

159+
PdfFile DecodedFile::pdf_file() const {
160+
if (auto pdf_file =
161+
std::dynamic_pointer_cast<internal::pdf::PdfFile>(m_impl)) {
162+
return PdfFile(pdf_file);
163+
}
164+
throw NoPdfFile();
165+
}
166+
136167
TextFile::TextFile(std::shared_ptr<internal::abstract::TextFile> impl)
137168
: DecodedFile(impl), m_impl{std::move(impl)} {}
138169

@@ -198,4 +229,7 @@ DocumentMeta DocumentFile::document_meta() const {
198229

199230
Document DocumentFile::document() const { return Document(m_impl->document()); }
200231

232+
PdfFile::PdfFile(std::shared_ptr<internal::pdf::PdfFile> impl)
233+
: DecodedFile(impl), m_impl{std::move(impl)} {}
234+
201235
} // namespace odr

src/odr/file.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@ class ArchiveFile;
1616
class DocumentFile;
1717
} // namespace odr::internal::abstract
1818

19+
namespace odr::internal::pdf {
20+
class PdfFile;
21+
}
22+
1923
namespace odr {
2024
class TextFile;
2125
class ImageFile;
2226
class ArchiveFile;
2327
class DocumentFile;
28+
class PdfFile;
2429

2530
class Archive;
2631
class Document;
@@ -166,10 +171,17 @@ class DecodedFile {
166171

167172
[[nodiscard]] File file() const;
168173

174+
[[nodiscard]] bool is_text_file() const;
175+
[[nodiscard]] bool is_image_file() const;
176+
[[nodiscard]] bool is_archive_file() const;
177+
[[nodiscard]] bool is_document_file() const;
178+
[[nodiscard]] bool is_pdf_file() const;
179+
169180
[[nodiscard]] TextFile text_file() const;
170181
[[nodiscard]] ImageFile image_file() const;
171182
[[nodiscard]] ArchiveFile archive_file() const;
172183
[[nodiscard]] DocumentFile document_file() const;
184+
[[nodiscard]] PdfFile pdf_file() const;
173185

174186
protected:
175187
std::shared_ptr<internal::abstract::DecodedFile> m_impl;
@@ -229,6 +241,14 @@ class DocumentFile final : public DecodedFile {
229241
std::shared_ptr<internal::abstract::DocumentFile> m_impl;
230242
};
231243

244+
class PdfFile final : public DecodedFile {
245+
public:
246+
explicit PdfFile(std::shared_ptr<internal::pdf::PdfFile>);
247+
248+
private:
249+
std::shared_ptr<internal::pdf::PdfFile> m_impl;
250+
};
251+
232252
} // namespace odr
233253

234254
#endif // ODR_FILE_HPP

src/odr/html.cpp

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
#include <odr/internal/html/document.hpp>
1010
#include <odr/internal/html/filesystem.hpp>
1111
#include <odr/internal/html/image_file.hpp>
12+
#include <odr/internal/html/pdf_file.hpp>
1213
#include <odr/internal/html/text_file.hpp>
1314

14-
#include <nlohmann/json.hpp>
15-
1615
#include <filesystem>
1716

17+
#include <nlohmann/json.hpp>
18+
1819
using namespace odr::internal;
1920
namespace fs = std::filesystem;
2021

@@ -53,21 +54,32 @@ Html html::translate(const File &file, const std::string &output_path,
5354
const PasswordCallback &password_callback) {
5455
auto decoded_file = DecodedFile(file);
5556

56-
if (decoded_file.file_category() == FileCategory::text) {
57-
return translate(decoded_file.text_file(), output_path, config);
58-
} else if (decoded_file.file_category() == FileCategory::image) {
59-
return translate(decoded_file.image_file(), output_path, config);
60-
} else if (decoded_file.file_category() == FileCategory::archive) {
61-
return translate(decoded_file.archive_file().archive(), output_path,
62-
config);
63-
} else if (decoded_file.file_category() == FileCategory::document) {
57+
if (decoded_file.is_document_file()) {
6458
DocumentFile document_file = decoded_file.document_file();
6559
if (document_file.password_encrypted()) {
6660
if (!document_file.decrypt(password_callback())) {
6761
throw WrongPassword();
6862
}
6963
}
70-
return translate(document_file.document(), output_path, config);
64+
}
65+
66+
return translate(decoded_file, output_path, config);
67+
}
68+
69+
Html html::translate(const DecodedFile &decoded_file,
70+
const std::string &output_path, const HtmlConfig &config) {
71+
if (decoded_file.is_text_file()) {
72+
return translate(decoded_file.text_file(), output_path, config);
73+
} else if (decoded_file.is_image_file()) {
74+
return translate(decoded_file.image_file(), output_path, config);
75+
} else if (decoded_file.is_archive_file()) {
76+
return translate(decoded_file.archive_file().archive(), output_path,
77+
config);
78+
} else if (decoded_file.is_document_file()) {
79+
return translate(decoded_file.document_file().document(), output_path,
80+
config);
81+
} else if (decoded_file.is_pdf_file()) {
82+
return translate(decoded_file.pdf_file(), output_path, config);
7183
}
7284

7385
throw UnsupportedFileType(decoded_file.file_type());
@@ -98,6 +110,12 @@ Html html::translate(const Document &document, const std::string &output_path,
98110
return internal::html::translate_document(document, output_path, config);
99111
}
100112

113+
Html html::translate(const PdfFile &pdf_file, const std::string &output_path,
114+
const HtmlConfig &config) {
115+
fs::create_directories(output_path);
116+
return internal::html::translate_pdf_file(pdf_file, output_path, config);
117+
}
118+
101119
void html::edit(const Document &document, const char *diff) {
102120
auto json = nlohmann::json::parse(diff);
103121
for (const auto &[key, value] : json["modifiedText"].items()) {

src/odr/html.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,13 @@ struct HtmlPage final {
9090
using PasswordCallback = std::function<std::string()>;
9191

9292
namespace html {
93+
9394
Html translate(const File &file, const std::string &output_path,
9495
const HtmlConfig &config,
9596
const PasswordCallback &password_callback);
97+
Html translate(const DecodedFile &file, const std::string &output_path,
98+
const HtmlConfig &config);
99+
96100
Html translate(const TextFile &text_file, const std::string &output_path,
97101
const HtmlConfig &config);
98102
Html translate(const ImageFile &image_file, const std::string &output_path,
@@ -101,7 +105,11 @@ Html translate(const Archive &archive, const std::string &output_path,
101105
const HtmlConfig &config);
102106
Html translate(const Document &document, const std::string &output_path,
103107
const HtmlConfig &config);
108+
Html translate(const PdfFile &pdf_file, const std::string &output_path,
109+
const HtmlConfig &config);
110+
104111
void edit(const Document &document, const char *diff);
112+
105113
} // namespace html
106114

107115
} // namespace odr

0 commit comments

Comments
 (0)