hemplate

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

commit bf0389ba151e90bf9837fb2c442a73b14e5ef91b
parent 51fafc0d0c594527807ffbeae0075095fedc502a
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Fri, 25 Apr 2025 09:34:22 +0200

Even more simplicity and flexibility

Diffstat:
M example/html.cpp | ++
M include/hemplate/atom.hpp | -
M include/hemplate/classes.hpp | ++++ ------
M include/hemplate/element.hpp | +++++++++++++++++++++++++++ -----------------------------------------------------
M include/hemplate/html.hpp | + --
M include/hemplate/rss.hpp | -
M include/hemplate/sitemap.hpp | -
M source/element.cpp | + -----------

8 files changed, 35 insertions(+), 75 deletions(-)


diff --git a/ example/html.cpp b/ example/html.cpp

@@ -22,10 +22,12 @@ int main()

html::li {
{li_attrs, {{"class", "item1"}}},
"Item 1",
"some text",
},
html::li {
{li_attrs, {{"class", "item2"}}},
"Item 2",
"some text",
},
},
html::hr {},

diff --git a/ include/hemplate/atom.hpp b/ include/hemplate/atom.hpp

@@ -33,7 +33,6 @@ public:

}
};

using hemplate::blank;
using hemplate::comment;
using hemplate::element;
using hemplate::transform;

diff --git a/ include/hemplate/classes.hpp b/ include/hemplate/classes.hpp

@@ -15,7 +15,7 @@ class HEMPLATE_EXPORT comment : public element

{
public:
explicit comment(std::string_view data)
: element(std::format("<-- {} -->", data), "", "")
: element(std::format("<-- {} -->", data))
{
}
};

@@ -36,15 +36,13 @@ public:

std::string_view version = default_version,
std::string_view encoding = default_encoding
)
: element(
std::format("<? {}?>", attribute_list {version, encoding}), "", ""
)
: element(std::format("<? {}?>", attribute_list {version, encoding}))
{
}
};

template<std::ranges::forward_range R>
blank transform(
element transform(
const R& range, based::Procedure<std::ranges::range_value_t<R>> auto proc
)
{

@@ -55,7 +53,7 @@ blank transform(

res.emplace_back(proc(elem));
}

return blank {res};
return element {res};
}

} // namespace hemplate

diff --git a/ include/hemplate/element.hpp b/ include/hemplate/element.hpp

@@ -27,6 +27,9 @@ public:

Boolean,
};

template<based::string_literal Tag, Type MyType>
friend class element_builder;

private:
std::string m_otag;
std::string m_ctag;

@@ -37,23 +40,6 @@ private:

void render_children(std::ostream& out, std::size_t indent_value) const;
void render(std::ostream& out, std::size_t indent_value) const;

public:
explicit element(std::string_view open_tag)
: m_otag(open_tag)
{
}

explicit element(
std::string_view open_tag,
std::string_view close_tag,
std::string_view data
)
: m_otag(open_tag)
, m_ctag(close_tag)
, m_data(data)
{
}

explicit element(
std::string_view open_tag,
std::string_view close_tag,

@@ -76,6 +62,24 @@ public:

{
}

public:
// NOLINTBEGIN *-explicit-constructor
element(std::string_view data)
: m_data(data)
{
}

element(const is_element auto&... children)
: m_children(std::initializer_list<element> {children...})
{
}

element(std::span<const element> children)
: m_children(std::begin(children), std::end(children))
{
}
// NOLINTEND *-explicit-constructor

explicit operator std::string() const
{
std::stringstream ss;

@@ -105,13 +109,9 @@ class HEMPLATE_EXPORT element_builder<Tag, element::Type::Boolean>

}

public:
explicit element_builder(std::string_view data)
: element(open(), close(), data)
{
}

explicit element_builder(const is_element auto&... children)
: element(open(), close(), children...)
template<typename... Args>
explicit element_builder(Args&&... args)
: element(open(), close(), element(std::forward<Args>(args))...)
{
}

@@ -119,16 +119,9 @@ public:

: element(open(), close(), children)
{
}

explicit element_builder(const attribute_list& attrs, std::string_view data)
: element(open(attrs), close(), data)
{
}

explicit element_builder(
const attribute_list& attrs, const is_element auto&... children
)
: element(open(attrs), close(), children...)
template<typename... Args>
explicit element_builder(const attribute_list& attrs, Args&&... args)
: element(open(attrs), close(), element(std::forward<Args>(args))...)
{
}

@@ -157,23 +150,4 @@ public:

}
};

class HEMPLATE_EXPORT blank : public element
{
public:
explicit blank(std::string_view data)
: element("", "", data)
{
}

explicit blank(const is_element auto&... children)
: element("", "", children...)
{
}

explicit blank(std::span<const element> children)
: element("", "", children)
{
}
};

} // namespace hemplate

diff --git a/ include/hemplate/html.hpp b/ include/hemplate/html.hpp

@@ -5,7 +5,6 @@

namespace hemplate::html
{

using hemplate::blank;
using hemplate::comment;
using hemplate::element;
using hemplate::transform;

@@ -15,7 +14,7 @@ class doctype : public element

{
public:
explicit doctype()
: element("<!DOCTYPE html>", "", "")
: element("<!DOCTYPE html>")
{
}
};

diff --git a/ include/hemplate/rss.hpp b/ include/hemplate/rss.hpp

@@ -87,7 +87,6 @@ public:

}
};

using hemplate::blank;
using hemplate::comment;
using hemplate::element;
using hemplate::transform;

diff --git a/ include/hemplate/sitemap.hpp b/ include/hemplate/sitemap.hpp

@@ -31,7 +31,6 @@ public:

}
};

using hemplate::blank;
using hemplate::comment;
using hemplate::element;
using hemplate::transform;

diff --git a/ source/element.cpp b/ source/element.cpp

@@ -26,20 +26,10 @@ void element::render(std::ostream& out, std::size_t indent_value) const

return;
}

if (m_ctag.empty()) {
out << indent << m_otag << '\n';
return;
}

if (!m_data.empty()) {
out << indent << m_otag << m_data << m_ctag << '\n';
return;
}

if (!m_children.empty()) {
out << indent << m_otag << '\n';
render_children(out, indent_value + 2);
out << m_ctag << '\n';
out << indent << m_ctag << '\n';
return;
}