hemplate

Simple XML template engine
git clone git://git.dimitrijedobrota.com/hemplate.git
Log | Files | Refs | README | LICENSE

commit 3236ff76f60e6d1df780edbbbe1a9904f70d6045
parent f63c8fed3fdfe6d1db925c9a4682fc6dc5c7d49b
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Sat, 22 Jun 2024 21:09:32 +0200

Add elementList

Diffstat:
MCMakeLists.txt | 2+-
Minclude/hemplate/element.hpp | 44++++++++++++++++++++++++++++++++++++++++----
Minclude/hemplate/elementAtomic.hpp | 7++++++-
Minclude/hemplate/elementBoolean.hpp | 12+++++++++++-
Msource/element.cpp | 68+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mtest/source/hemplate_test.cpp | 6++++--
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; }