Skip to content

Commit bd83c73

Browse files
authored
Html views (#412)
1 parent 1297f10 commit bd83c73

10 files changed

Lines changed: 184 additions & 29 deletions

File tree

cli/src/server.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,16 @@ int main(int argc, char **argv) {
4040
HtmlConfig html_config;
4141
html_config.embed_images = false;
4242
html_config.embed_shipped_resources = false;
43+
html_config.relative_resource_paths = false;
4344

4445
{
4546
std::string prefix = "one_file";
46-
server.serve_file(decoded_file, prefix, html_config);
47+
HtmlViews views = server.serve_file(decoded_file, prefix, html_config);
4748
std::cout << "hosted decoded file with id: " << prefix << std::endl;
48-
std::cout << "http://localhost:8080/file/" << prefix << "/document.html"
49-
<< std::endl;
49+
for (const auto &view : views) {
50+
std::cout << "http://localhost:8080/file/" << prefix << "/" << view.path()
51+
<< std::endl;
52+
}
5053
}
5154

5255
server.listen("localhost", 8080);

src/odr/html_service.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ const HtmlResourceLocator &HtmlService::resource_locator() const {
1818
return m_impl->resource_locator();
1919
}
2020

21+
const HtmlViews &HtmlService::list_views() const {
22+
return m_impl->list_views();
23+
}
24+
2125
void HtmlService::warmup() const { m_impl->warmup(); }
2226

2327
bool HtmlService::exists(const std::string &path) const {
@@ -43,6 +47,26 @@ HtmlService::impl() const {
4347
return m_impl;
4448
}
4549

50+
HtmlView::HtmlView() = default;
51+
52+
HtmlView::HtmlView(std::shared_ptr<internal::abstract::HtmlView> impl)
53+
: m_impl{std::move(impl)} {}
54+
55+
const std::string &HtmlView::name() const { return m_impl->name(); }
56+
57+
const std::string &HtmlView::path() const { return m_impl->path(); }
58+
59+
const HtmlConfig &HtmlView::config() const { return m_impl->config(); }
60+
61+
HtmlResources HtmlView::write_html(std::ostream &out) const {
62+
internal::html::HtmlWriter writer(out, config());
63+
return m_impl->write_html(writer);
64+
}
65+
66+
const std::shared_ptr<internal::abstract::HtmlView> &HtmlView::impl() const {
67+
return m_impl;
68+
}
69+
4670
HtmlResource::HtmlResource() = default;
4771

4872
HtmlResource::HtmlResource(

src/odr/html_service.hpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
namespace odr::internal::abstract {
1111
class HtmlService;
12+
class HtmlView;
1213
class HtmlResource;
1314
} // namespace odr::internal::abstract
1415

@@ -17,6 +18,7 @@ enum class FileType;
1718
class File;
1819
struct HtmlConfig;
1920

21+
class HtmlView;
2022
class HtmlResource;
2123

2224
enum class HtmlResourceType {
@@ -27,6 +29,7 @@ enum class HtmlResourceType {
2729
font,
2830
};
2931

32+
using HtmlViews = std::vector<HtmlView>;
3033
using HtmlResourceLocation = std::optional<std::string>;
3134
using HtmlResourceLocator =
3235
std::function<HtmlResourceLocation(const HtmlResource &resource)>;
@@ -40,11 +43,11 @@ class HtmlService final {
4043

4144
[[nodiscard]] const HtmlConfig &config() const;
4245
[[nodiscard]] const HtmlResourceLocator &resource_locator() const;
46+
[[nodiscard]] const HtmlViews &list_views() const;
4347

4448
void warmup() const;
4549

4650
[[nodiscard]] bool exists(const std::string &path) const;
47-
4851
[[nodiscard]] std::string mimetype(const std::string &path) const;
4952

5053
void write(const std::string &path, std::ostream &out) const;
@@ -57,6 +60,24 @@ class HtmlService final {
5760
std::shared_ptr<internal::abstract::HtmlService> m_impl;
5861
};
5962

63+
class HtmlView final {
64+
public:
65+
HtmlView();
66+
explicit HtmlView(std::shared_ptr<internal::abstract::HtmlView> impl);
67+
68+
[[nodiscard]] const std::string &name() const;
69+
[[nodiscard]] const std::string &path() const;
70+
[[nodiscard]] const HtmlConfig &config() const;
71+
72+
HtmlResources write_html(std::ostream &out) const;
73+
74+
[[nodiscard]] const std::shared_ptr<internal::abstract::HtmlView> &
75+
impl() const;
76+
77+
private:
78+
std::shared_ptr<internal::abstract::HtmlView> m_impl;
79+
};
80+
6081
class HtmlResource final {
6182
public:
6283
HtmlResource();

src/odr/http_server.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include <odr/file.hpp>
55
#include <odr/filesystem.hpp>
66
#include <odr/html.hpp>
7-
#include <odr/html_service.hpp>
87
#include <odr/internal/html/document.hpp>
98
#include <odr/internal/html/pdf2htmlex_wrapper.hpp>
109
#include <odr/internal/pdf_poppler/poppler_pdf_file.hpp>
@@ -99,8 +98,8 @@ void HttpServer::connect_service(HtmlService service,
9998
m_impl->connect_service(std::move(service), prefix);
10099
}
101100

102-
void HttpServer::serve_file(DecodedFile file, const std::string &prefix,
103-
const HtmlConfig &config) {
101+
HtmlViews HttpServer::serve_file(DecodedFile file, const std::string &prefix,
102+
const HtmlConfig &config) {
104103
static std::regex prefix_regex(prefix_pattern);
105104
if (!std::regex_match(prefix, prefix_regex)) {
106105
throw InvalidPrefix(prefix);
@@ -128,7 +127,9 @@ void HttpServer::serve_file(DecodedFile file, const std::string &prefix,
128127
throw std::runtime_error("Unsupported file type.");
129128
}
130129

131-
m_impl->connect_service(std::move(service), prefix);
130+
m_impl->connect_service(service, prefix);
131+
132+
return service.list_views();
132133
}
133134

134135
void HttpServer::listen(const std::string &host, std::uint32_t port) {

src/odr/http_server.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22

3+
#include <odr/html_service.hpp>
4+
35
#include <cstdint>
46
#include <memory>
57
#include <string>
@@ -23,8 +25,8 @@ class HttpServer {
2325

2426
void connect_service(HtmlService service, const std::string &prefix);
2527

26-
void serve_file(DecodedFile file, const std::string &prefix,
27-
const HtmlConfig &config);
28+
HtmlViews serve_file(DecodedFile file, const std::string &prefix,
29+
const HtmlConfig &config);
2830

2931
void listen(const std::string &host, std::uint32_t port);
3032

src/odr/internal/abstract/html_service.hpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,29 @@ class HtmlService {
2121

2222
[[nodiscard]] virtual const HtmlConfig &config() const = 0;
2323
[[nodiscard]] virtual const HtmlResourceLocator &resource_locator() const = 0;
24+
[[nodiscard]] virtual const HtmlViews &list_views() const = 0;
2425

2526
virtual void warmup() const = 0;
2627

2728
[[nodiscard]] virtual bool exists(const std::string &path) const = 0;
28-
2929
[[nodiscard]] virtual std::string mimetype(const std::string &path) const = 0;
3030

3131
virtual void write(const std::string &path, std::ostream &out) const = 0;
3232
virtual HtmlResources write_html(const std::string &path,
3333
html::HtmlWriter &out) const = 0;
3434
};
3535

36+
class HtmlView {
37+
public:
38+
virtual ~HtmlView() = default;
39+
40+
[[nodiscard]] virtual const std::string &name() const = 0;
41+
[[nodiscard]] virtual const std::string &path() const = 0;
42+
[[nodiscard]] virtual const HtmlConfig &config() const = 0;
43+
44+
virtual HtmlResources write_html(html::HtmlWriter &out) const = 0;
45+
};
46+
3647
class HtmlResource {
3748
public:
3849
virtual ~HtmlResource() = default;

src/odr/internal/html/document.cpp

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,41 @@ class HtmlFragmentBase {
163163
Document m_document;
164164
};
165165

166+
class HtmlFragmentView final : public HtmlView {
167+
public:
168+
HtmlFragmentView(const abstract::HtmlService &service, std::string name,
169+
std::string path, std::shared_ptr<HtmlFragmentBase> fragment)
170+
: HtmlView(service, std::move(name), std::move(path)),
171+
m_fragment{std::move(fragment)} {}
172+
173+
HtmlResources write_html(html::HtmlWriter &out) const final {
174+
HtmlResources resources;
175+
WritingState state(out, service().config(), service().resource_locator(),
176+
resources);
177+
m_fragment->write_document(out, state);
178+
return resources;
179+
}
180+
181+
private:
182+
std::shared_ptr<HtmlFragmentBase> m_fragment;
183+
};
184+
166185
class HtmlServiceImpl : public HtmlService {
167186
public:
168187
HtmlServiceImpl(Document document,
169188
std::vector<std::shared_ptr<HtmlFragmentBase>> fragments,
170189
HtmlConfig config, HtmlResourceLocator resource_locator)
171190
: HtmlService(std::move(config), std::move(resource_locator)),
172-
m_document{std::move(document)}, m_fragments{std::move(fragments)} {}
191+
m_document{std::move(document)}, m_fragments{std::move(fragments)} {
192+
m_views.emplace_back(
193+
std::make_shared<HtmlView>(*this, "document", "document.html"));
194+
for (const auto &fragment : m_fragments) {
195+
m_views.emplace_back(std::make_shared<HtmlFragmentView>(
196+
*this, fragment->name(), fragment->name() + ".html", fragment));
197+
}
198+
}
199+
200+
const HtmlViews &list_views() const final { return m_views; }
173201

174202
[[nodiscard]] Document document() const { return m_document; }
175203

@@ -191,7 +219,9 @@ class HtmlServiceImpl : public HtmlService {
191219
}
192220

193221
bool exists(const std::string &path) const final {
194-
if (path == "document.html") {
222+
if (std::ranges::any_of(m_views, [&path](const auto &view) {
223+
return view.path() == path;
224+
})) {
195225
return true;
196226
}
197227

@@ -206,7 +236,9 @@ class HtmlServiceImpl : public HtmlService {
206236
}
207237

208238
std::string mimetype(const std::string &path) const final {
209-
if (path == "document.html") {
239+
if (std::ranges::any_of(m_views, [&path](const auto &view) {
240+
return view.path() == path;
241+
})) {
210242
return "text/html";
211243
}
212244

@@ -220,10 +252,12 @@ class HtmlServiceImpl : public HtmlService {
220252
}
221253

222254
void write(const std::string &path, std::ostream &out) const final {
223-
if (path == "document.html") {
224-
HtmlWriter writer(out, config());
225-
write_document(writer);
226-
return;
255+
for (const auto &view : m_views) {
256+
if (view.path() == path) {
257+
HtmlWriter writer(out, config());
258+
write_html(path, writer);
259+
return;
260+
}
227261
}
228262

229263
warmup();
@@ -244,6 +278,12 @@ class HtmlServiceImpl : public HtmlService {
244278
return write_document(out);
245279
}
246280

281+
for (const auto &view : m_views) {
282+
if (view.path() == path) {
283+
return view.impl()->write_html(out);
284+
}
285+
}
286+
247287
throw FileNotFound("Unknown path: " + path);
248288
}
249289

@@ -264,6 +304,9 @@ class HtmlServiceImpl : public HtmlService {
264304
protected:
265305
Document m_document;
266306
std::vector<std::shared_ptr<HtmlFragmentBase>> m_fragments;
307+
308+
HtmlViews m_views;
309+
267310
mutable bool m_warm = false;
268311
mutable HtmlResources m_resources;
269312
};

src/odr/internal/html/html_service.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ const HtmlResourceLocator &HtmlService::resource_locator() const {
1818
return m_resource_locator;
1919
}
2020

21+
HtmlView::HtmlView(const abstract::HtmlService &service, std::string name,
22+
std::string path)
23+
: m_service{&service}, m_name{std::move(name)}, m_path{std::move(path)} {}
24+
25+
const std::string &HtmlView::name() const { return m_name; }
26+
27+
const std::string &HtmlView::path() const { return m_path; }
28+
29+
const HtmlConfig &HtmlView::config() const { return m_service->config(); }
30+
31+
const abstract::HtmlService &HtmlView::service() const { return *m_service; }
32+
33+
HtmlResources HtmlView::write_html(html::HtmlWriter &out) const {
34+
return m_service->write_html(path(), out);
35+
}
36+
2137
odr::HtmlResource HtmlResource::create(HtmlResourceType type,
2238
std::string mime_type, std::string name,
2339
std::string path, odr::File file,

src/odr/internal/html/html_service.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,24 @@ class HtmlService : public abstract::HtmlService {
1919
HtmlResourceLocator m_resource_locator;
2020
};
2121

22+
class HtmlView : public abstract::HtmlView {
23+
public:
24+
HtmlView(const abstract::HtmlService &service, std::string name,
25+
std::string path);
26+
27+
[[nodiscard]] const std::string &name() const override;
28+
[[nodiscard]] const std::string &path() const override;
29+
[[nodiscard]] const HtmlConfig &config() const override;
30+
[[nodiscard]] const abstract::HtmlService &service() const;
31+
32+
HtmlResources write_html(html::HtmlWriter &out) const override;
33+
34+
private:
35+
const abstract::HtmlService *m_service;
36+
std::string m_name;
37+
std::string m_path;
38+
};
39+
2240
class HtmlResource : public abstract::HtmlResource {
2341
public:
2442
static odr::HtmlResource create(HtmlResourceType type, std::string mime_type,

0 commit comments

Comments
 (0)