hemplateSimple XML template engine |
git clone git://git.dimitrijedobrota.com/hemplate.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | d25af86820fd01efb12416de44c93554d8a15321 |
parent | 3236ff76f60e6d1df780edbbbe1a9904f70d6045 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Sat, 22 Jun 2024 20:28:41 +0200 |
Add attributes and various constructors * Working render for all different cases
Diffstat:M | CMakeLists.txt | | | ++- |
A | include/hemplate/attribute.hpp | | | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | include/hemplate/element.hpp | | | ++++++++++++++++++++----- |
M | include/hemplate/elementAtomic.hpp | | | ++++++++++----- |
M | include/hemplate/elementBoolean.hpp | | | +++++++++++++++++++++++++++++++++++-------- |
A | source/attribute.cpp | | | +++++++++++++++++++++++++++++++++++++++++ |
M | source/element.cpp | | | ++++++++++++++++++++++++++++++++++++++------- |
M | test/source/hemplate_test.cpp | | | +++++++++++-- |
8 files changed, 227 insertions(+), 28 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
hemplate
VERSION 0.1.2
VERSION 0.1.3
DESCRIPTION "Simple HTML template engine"
HOMEPAGE_URL "https://git.dimitrijedobrota.com/hemplate.git"
LANGUAGES CXX
@@ -18,6 +18,7 @@ include(cmake/variables.cmake)
add_library(
hemplate_hemplate
source/element.cpp
source/attribute.cpp
)
add_library(hemplate::hemplate ALIAS hemplate_hemplate)
diff --git a/include/hemplate/attribute.hpp b/include/hemplate/attribute.hpp
@@ -0,0 +1,70 @@
#pragma once
#include <string>
#include <vector>
#include "hemplate/hemplate_export.hpp"
#include "hemplate/streamable.hpp"
namespace hemplate
{
class HEMPLATE_EXPORT attribute : public streamable
{
public:
attribute() = default;
attribute(const attribute&) = default;
attribute(attribute&&) = default;
attribute& operator=(const attribute&) = default;
attribute& operator=(attribute&&) = default;
~attribute() override = default;
attribute(std::string name) // NOLINT
: m_name(std::move(name))
{
}
attribute(std::string name, std::string value) // NOLINT
: m_name(std::move(name))
, m_value(std::move(value))
{
}
bool operator!=(const attribute& rhs) const;
bool operator==(const attribute& rhs) const;
const std::string& get_name() const { return m_name; }
const std::string& get_value() const { return m_value; }
void set_name(const std::string& name) { m_name = name; }
void set_value(const std::string& value) { m_value = value; }
void render(std::ostream& out) const override;
private:
std::string m_name;
std::string m_value;
};
class HEMPLATE_EXPORT attributeList : public streamable
{
public:
attributeList() = default;
attributeList(const attributeList&) = default;
attributeList(attributeList&&) = default;
attributeList& operator=(const attributeList&) = default;
attributeList& operator=(attributeList&&) = default;
~attributeList() override = default;
attributeList& set(const std::string& name);
attributeList& set(const std::string& name, const std::string& value);
bool empty() const { return m_attributes.empty(); }
void render(std::ostream& out) const override;
private:
std::vector<attribute> m_attributes;
};
} // namespace hemplate
diff --git a/include/hemplate/element.hpp b/include/hemplate/element.hpp
@@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include "hemplate/attribute.hpp"
#include "hemplate/hemplate_export.hpp"
#include "hemplate/streamable.hpp"
@@ -44,8 +45,13 @@ public:
Boolean,
};
explicit element(std::string data, Type type)
: m_data(std::move(data))
explicit element(attributeList attributes,
elementList embedded,
std::string data,
Type type)
: m_attributes(std::move(attributes))
, m_embeded(std::move(embedded))
, m_data(std::move(data))
, m_type(type)
{
}
@@ -59,23 +65,32 @@ public:
Type get_type() const { return m_type; }
std::string get_data() const { return m_data; }
const elementList& get_embeded() const { return m_embeded; }
const attributeList& get_attributes() const { return m_attributes; }
virtual bool get_state() const { return false; }
virtual const char* get_name() const = 0;
void set_data(const std::string& data) { m_data = data; }
void set_embedded(const elementList& embed) { m_embeded = embed; }
void set_attributes(const attributeList& attrs) { m_attributes = attrs; }
virtual void tgl_state() const {}
element& add(const element& elem);
element& add(std::unique_ptr<element> elem);
virtual const char* get_name() const = 0;
element& set(const std::string& name);
element& set(const std::string& name, const std::string& value);
virtual std::unique_ptr<element> clone() const = 0;
void render(std::ostream& out) const override;
private:
attributeList m_attributes;
elementList m_embeded;
std::string m_data;
Type m_type;
elementList m_embeded;
};
} // namespace hemplate
diff --git a/include/hemplate/elementAtomic.hpp b/include/hemplate/elementAtomic.hpp
@@ -10,17 +10,22 @@ template<typename Tag>
class HEMPLATE_EXPORT elementAtomic : public element
{
public:
elementAtomic()
: element("", Type::Atomic)
{
}
elementAtomic(const elementAtomic&) = default;
elementAtomic(elementAtomic&&) noexcept = default;
elementAtomic& operator=(const elementAtomic&) = default;
elementAtomic& operator=(elementAtomic&&) noexcept = default;
~elementAtomic() override = default;
elementAtomic()
: element({}, {}, "", Type::Atomic)
{
}
elementAtomic(attributeList attributes) // NOLINT
: element(std::move(attributes), {}, "", Type::Atomic)
{
}
const char* get_name() const override { return Tag::get_name(); }
std::unique_ptr<element> clone() const override
diff --git a/include/hemplate/elementBoolean.hpp b/include/hemplate/elementBoolean.hpp
@@ -10,23 +10,46 @@ template<typename Tag>
class HEMPLATE_EXPORT elementBoolean : public element
{
public:
elementBoolean(const elementBoolean&) = default;
elementBoolean(elementBoolean&&) noexcept = default;
elementBoolean& operator=(const elementBoolean&) = default;
elementBoolean& operator=(elementBoolean&&) noexcept = default;
~elementBoolean() override = default;
elementBoolean()
: element("", Type::Boolean)
: element({}, {}, "", Type::Boolean)
{
}
elementBoolean(const std::string& text) // NOLINT
: element(text, Type::Boolean)
elementBoolean(std::string text) // NOLINT
: element({}, {}, std::move(text), Type::Boolean)
{
}
elementBoolean(const elementBoolean&) = default;
elementBoolean(elementBoolean&&) noexcept = default;
elementBoolean& operator=(const elementBoolean&) = default;
elementBoolean& operator=(elementBoolean&&) noexcept = default;
~elementBoolean() override = default;
elementBoolean(attributeList attributes) // NOLINT
: element(std::move(attributes), {}, "", Type::Boolean)
{
}
elementBoolean(elementList embedded) // NOLINT
: element({}, std::move(embedded), "", Type::Boolean)
{
}
elementBoolean(std::string text, attributeList attributes)
: element(std::move(attributes), {}, std::move(text), Type::Boolean)
{
}
elementBoolean(attributeList attributes, elementList embedded)
: element(std::move(attributes), std::move(embedded), "", Type::Boolean)
{
}
const char* get_name() const override { return Tag::get_name(); }
bool get_state() const override { return m_state; }
void tgl_state() const override { m_state = !m_state; }
std::unique_ptr<element> clone() const override
{
@@ -34,6 +57,10 @@ public:
}
private:
static bool m_state; // NOLINT
};
template<typename Tag>
bool elementBoolean<Tag>::m_state = false; // NOLINT
} // namespace hemplate
diff --git a/source/attribute.cpp b/source/attribute.cpp
@@ -0,0 +1,41 @@
#include "hemplate/attribute.hpp"
namespace hemplate
{
bool attribute::operator!=(const attribute& rhs) const
{
return !(*this == rhs);
}
bool attribute::operator==(const attribute& rhs) const
{
return m_name == rhs.m_name && m_value == rhs.m_value;
}
void attribute::render(std::ostream& out) const
{
out << get_name() << "=\"" << get_value() << "\"";
}
attributeList& attributeList::set(const std::string& name)
{
m_attributes.emplace_back(name);
return *this;
}
attributeList& attributeList::set(const std::string& name,
const std::string& value)
{
m_attributes.emplace_back(name, value);
return *this;
}
void attributeList::render(std::ostream& out) const
{
for (const auto& attr : m_attributes) {
out << attr << ' ';
}
}
} // namespace hemplate
diff --git a/source/element.cpp b/source/element.cpp
@@ -15,24 +15,55 @@ element& element::add(std::unique_ptr<element> elem)
return *this;
}
element& element::set(const std::string& name)
{
m_attributes.set(name);
return *this;
}
element& element::set(const std::string& name, const std::string& value)
{
m_attributes.set(name, value);
return *this;
}
void element::render(std::ostream& out) const
{
if (get_type() == Type::Boolean && m_data.empty()) {
out << '<' << get_name() << '>';
const auto open_tag = [this, &out](bool atomic)
{
out << '<' << get_name();
if (!m_attributes.empty()) {
out << ' ';
m_attributes.render(out);
}
out << (atomic ? " />" : ">");
};
m_embeded.render(out);
const auto close_tag = [this, &out]() { out << "</" << get_name() << '>'; };
out << "</" << get_name() << '>';
} else {
out << '<' << get_name() << '>';
if (m_type == Type::Atomic) {
open_tag(true);
return;
}
if (!m_data.empty()) {
open_tag(false);
if (!m_embeded.empty()) {
m_embeded.render(out);
} else {
out << m_data;
}
close_tag();
return;
}
out << "</" << get_name() << '>';
if (m_embeded.empty()) {
tgl_state();
get_state() ? open_tag(false) : close_tag();
} else {
open_tag(false);
m_embeded.render(out);
close_tag();
}
}
diff --git a/test/source/hemplate_test.cpp b/test/source/hemplate_test.cpp
@@ -4,10 +4,19 @@
int main()
{
using namespace hemplate; // NOLINT
using namespace hemplate; // NOLINT
std::cout << ul("Won't see").add(li("Item 1")).add(li("Item 2")) << std::endl;
attributeList li_attrs;
li_attrs.set("class", "main_li");
std::cout << html() << std::endl;
std::cout << ul("Won't see")
.set("id", "main_ul")
.add(li("Item 1", li_attrs))
.add(li("Item 2", li_attrs))
<< std::endl;
std::cout << meta() << std::endl;
std::cout << html() << std::endl;
return 0;
}