commit 3236ff76f60e6d1df780edbbbe1a9904f70d6045
parent f63c8fed3fdfe6d1db925c9a4682fc6dc5c7d49b
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Sat, 22 Jun 2024 21:09:32 +0200
Add elementList
Diffstat:
6 files changed, 125 insertions(+), 14 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
hemplate
- VERSION 0.1.1
+ VERSION 0.1.2
DESCRIPTION "Simple HTML template engine"
HOMEPAGE_URL "https://git.dimitrijedobrota.com/hemplate.git"
LANGUAGES CXX
diff --git a/include/hemplate/element.hpp b/include/hemplate/element.hpp
@@ -1,6 +1,8 @@
#pragma once
+#include <memory>
#include <string>
+#include <vector>
#include "hemplate/hemplate_export.hpp"
#include "hemplate/streamable.hpp"
@@ -8,6 +10,31 @@
namespace hemplate
{
+class element;
+
+class HEMPLATE_EXPORT elementList : public streamable
+{
+public:
+ elementList() = default;
+ ~elementList() override = default;
+ elementList(elementList&&) = default;
+ elementList& operator=(elementList&&) = default;
+
+ // explicitly clone all the elements
+ elementList(const elementList& rhs);
+ elementList& operator=(const elementList& rhs);
+
+ elementList& add(const element& elem);
+ elementList& add(std::unique_ptr<element> elem);
+
+ bool empty() const { return m_elems.empty(); }
+
+ void render(std::ostream& out) const override;
+
+private:
+ std::vector<std::unique_ptr<element>> m_elems;
+};
+
class HEMPLATE_EXPORT element : public streamable
{
public:
@@ -17,8 +44,9 @@ public:
Boolean,
};
- explicit element(Type type)
- : m_type(type)
+ explicit element(std::string data, Type type)
+ : m_data(std::move(data))
+ , m_type(type)
{
}
@@ -30,16 +58,24 @@ public:
Type get_type() const { return m_type; }
std::string get_data() const { return m_data; }
+ const elementList& get_embeded() const { return m_embeded; }
void set_data(const std::string& data) { m_data = data; }
+ void set_embedded(const elementList& embed) { m_embeded = embed; }
+
+ element& add(const element& elem);
+ element& add(std::unique_ptr<element> elem);
+
+ virtual const char* get_name() const = 0;
+ virtual std::unique_ptr<element> clone() const = 0;
- virtual const char* get_name() const = 0;
void render(std::ostream& out) const override;
private:
+ std::string m_data;
Type m_type;
- std::string m_data;
+ elementList m_embeded;
};
} // namespace hemplate
diff --git a/include/hemplate/elementAtomic.hpp b/include/hemplate/elementAtomic.hpp
@@ -11,7 +11,7 @@ class HEMPLATE_EXPORT elementAtomic : public element
{
public:
elementAtomic()
- : element(Type::Atomic)
+ : element("", Type::Atomic)
{
}
@@ -23,6 +23,11 @@ public:
const char* get_name() const override { return Tag::get_name(); }
+ std::unique_ptr<element> clone() const override
+ {
+ return std::make_unique<elementAtomic<Tag>>(*this);
+ }
+
private:
};
diff --git a/include/hemplate/elementBoolean.hpp b/include/hemplate/elementBoolean.hpp
@@ -11,7 +11,12 @@ class HEMPLATE_EXPORT elementBoolean : public element
{
public:
elementBoolean()
- : element(Type::Boolean)
+ : element("", Type::Boolean)
+ {
+ }
+
+ elementBoolean(const std::string& text) // NOLINT
+ : element(text, Type::Boolean)
{
}
@@ -23,6 +28,11 @@ public:
const char* get_name() const override { return Tag::get_name(); }
+ std::unique_ptr<element> clone() const override
+ {
+ return std::make_unique<elementBoolean<Tag>>(*this);
+ }
+
private:
};
diff --git a/source/element.cpp b/source/element.cpp
@@ -3,14 +3,72 @@
namespace hemplate
{
+element& element::add(const element& elem)
+{
+ m_embeded.add(elem);
+ return *this;
+}
+
+element& element::add(std::unique_ptr<element> elem)
+{
+ m_embeded.add(std::move(elem));
+ return *this;
+}
+
void element::render(std::ostream& out) const
{
- if (get_type() == Type::Boolean) {
- out << "<" << get_name() << ">";
- out << get_data();
- out << "</" << get_name() << ">";
+ if (get_type() == Type::Boolean && m_data.empty()) {
+ out << '<' << get_name() << '>';
+
+ m_embeded.render(out);
+
+ out << "</" << get_name() << '>';
} else {
- out << "<" << get_name() << " />";
+ out << '<' << get_name() << '>';
+
+ if (!m_embeded.empty()) {
+ m_embeded.render(out);
+ } else {
+ out << m_data;
+ }
+
+ out << "</" << get_name() << '>';
+ }
+}
+
+elementList::elementList(const elementList& rhs)
+{
+ this->operator=(rhs);
+}
+
+elementList& elementList::operator=(const elementList& rhs)
+{
+ if (this == &rhs) return *this;
+
+ m_elems.clear();
+ for (const auto& elem : rhs.m_elems) {
+ add(*elem);
+ }
+
+ return *this;
+}
+
+elementList& elementList::add(const element& elem)
+{
+ m_elems.push_back(elem.clone());
+ return *this;
+}
+
+elementList& elementList::add(std::unique_ptr<element> elem)
+{
+ m_elems.push_back(std::move(elem));
+ return *this;
+}
+
+void elementList::render(std::ostream& out) const
+{
+ for (const auto& elem : m_elems) {
+ elem->render(out);
}
}
diff --git a/test/source/hemplate_test.cpp b/test/source/hemplate_test.cpp
@@ -4,8 +4,10 @@
int main()
{
- std::cout << hemplate::a() << std::endl;
- std::cout << hemplate::meta() << std::endl;
+ using namespace hemplate; // NOLINT
+
+ std::cout << ul("Won't see").add(li("Item 1")).add(li("Item 2")) << std::endl;
+ std::cout << meta() << std::endl;
return 0;
}