summaryrefslogtreecommitdiff
path: root/src/document.cc
blob: 7304c8ad8b959dd58e563de693dd905fd6aee353 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "common.hh"

#include "document.hh"
#include "hash_method.hh"
#include "htmlutil.hh"
#include "tag.hh"

#include <vector>

namespace {

class DocumentImpl : public Document {
public:
  explicit DocumentImpl(std::string title)
    : html_(Tag::create("html")), head_(html_->add_tag("head")),
      title_(head_->add_tag("title", std::move(title))),
      body_(html_->add_tag("body")) {
  }

  void add_style(std::string rel_path) override {
    head_->add_tag("link")
      ->attr("rel", "stylesheet")
      ->attr("href", std::move(rel_path));
  }

  void add_script(std::string src_path) override {
    head_->add_tag("script")
      ->attr("type", "text/javascript")
      ->attr("src", std::move(src_path));
  }

  void add_script(std::unique_ptr<Tag> script) override {
    if (!script->has_attr("type"))
      script->attr("type", "text/javascript");
    head_->add(std::move(script));
  }

  Tag* body() override {
    return body_;
  }

  std::unique_ptr<Transport::Response> build(Transport* transport) override {
    std::string data = "<!DOCTYPE html>";
    html_->render(&data);
    auto sha256 = HashMethod::sha256();
    sha256->update(data.data(), data.size());
    auto etag = "\"" + sha256->finish() + "\"";
    auto resp = transport->create_ok_data(std::move(data));
    resp->add_header("Content-Type", "text/html; charset=utf-8");
    resp->add_header("ETag", etag);
    return resp;
  }

private:
  std::unique_ptr<Tag> html_;
  Tag* head_;
  Tag* title_;
  Tag* body_;
};

}  // namespace

std::unique_ptr<Document> Document::create(std::string title) {
  return std::make_unique<DocumentImpl>(std::move(title));
}