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 d287efed0625b53751c1eb47d9a91d46a42c7218
parent 5dbbc906fba4ffb4aac3d9d2ca4b28529573ec48
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Wed, 23 Apr 2025 12:17:28 +0200

Improve element by inheriting from attribute_list

Diffstat:
M include/hemplate/element.hpp | ++++++++++++++++++++++++++++++++ -------------------------------
M source/attribute.cpp | + -
M source/element.cpp | +++++++++ -------------------------------------

3 files changed, 42 insertions(+), 69 deletions(-)


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

@@ -16,7 +16,7 @@ class element; template<typename T> concept is_element = std::derived_from<T, element>;
class HEMPLATE_EXPORT element
class HEMPLATE_EXPORT element : public attribute_list
{ public: enum class Type : uint8_t

@@ -28,90 +28,93 @@ public: Transparent, };
const attribute_list& attributes() const { return *this; }
private:
using attribute_list::empty;
template<based::string_literal Tag, element::Type MyType>
friend class element_builder;
bool* m_state; Type m_type;
std::string m_name;
std::string m_tag;
attribute_list m_attributes;
std::vector<element> m_children; std::string m_data; explicit element(bool& state, Type type,
std::string_view name,
std::string_view tag,
const is_element auto&... children) : m_state(&state) , m_type(type)
, m_name(name)
, m_tag(tag)
, m_children(std::initializer_list<element> {children...}) { } explicit element(bool& state, Type type,
std::string_view name,
std::string_view tag,
std::string_view data) : m_state(&state) , m_type(type)
, m_name(name)
, m_tag(tag)
, m_data(data) { } explicit element(bool& state, Type type,
std::string_view name,
std::string_view tag,
std::span<const element> children) : m_state(&state) , m_type(type)
, m_name(name)
, m_tag(tag)
, m_children(children.begin(), children.end()) { } explicit element(bool& state, Type type,
std::string_view name,
std::string_view tag,
attribute_list attributes, const is_element auto&... children)
: m_state(&state)
: attribute_list(std::move(attributes))
, m_state(&state)
, m_type(type)
, m_name(name)
, m_attributes(std::move(attributes))
, m_tag(tag)
, m_children(std::initializer_list<element> {children...}) { } explicit element(bool& state, Type type,
std::string_view name,
std::string_view tag,
attribute_list attributes, std::string_view data)
: m_state(&state)
: attribute_list(std::move(attributes))
, m_state(&state)
, m_type(type)
, m_name(name)
, m_attributes(std::move(attributes))
, m_tag(tag)
, m_data(data) { } explicit element(bool& state, Type type,
std::string_view name,
std::string_view tag,
attribute_list attributes, std::span<const element> children)
: m_state(&state)
: attribute_list(std::move(attributes))
, m_state(&state)
, m_type(type)
, m_name(name)
, m_attributes(std::move(attributes))
, m_tag(tag)
, m_children(children.begin(), children.end()) { }
template<based::string_literal Tag, element::Type MyType>
friend class element_builder;
void render_atomic(std::ostream& out, std::size_t indent_value) const; void render_boolean(std::ostream& out, std::size_t indent_value) const; void render_comment(std::ostream& out, std::size_t indent_value) const;

@@ -126,13 +129,11 @@ public: return out; }
element& add(const element& elem);
element& set(const attribute_list& list);
element& set(attribute attr);
element add(const attribute_list& list) const;
element add(attribute attr) const;
element& add(const element& elem)
{
m_children.emplace_back(elem);
return *this;
}
bool get_state() const { return *m_state; } bool tgl_state() const { return *m_state = !*m_state; }

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

@@ -48,7 +48,7 @@ attribute_list& attribute_list::set(attribute attr) if (attr.name == "class") { m_class.append(" ", attr.value); } else if (attr.name == "style") {
m_class.append("; ", attr.value);
m_style.append("; ", attr.value);
} else { m_attributes.emplace_back(std::move(attr)); }

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

@@ -7,12 +7,6 @@ namespace hemplate {
element& element::add(const element& elem)
{
m_children.emplace_back(elem);
return *this;
}
void element::render_comment(std::ostream& out, std::size_t indent_value) const { const std::string indent(indent_value, ' ');

@@ -24,13 +18,13 @@ void element::render_atomic(std::ostream& out, std::size_t indent_value) const { const std::string indent(indent_value, ' ');
out << indent << std::format("<{} {}/>\n", m_name, m_attributes);
out << indent << std::format("<{} {}/>\n", m_tag, attributes());
} void element::render_xml(std::ostream& out, std::size_t indent_value) const { const std::string indent(indent_value, ' ');
out << indent << std::format("<?xml {}?>\n", m_attributes);
out << indent << std::format("<?xml {}?>\n", attributes());
} void element::render_children(std::ostream& out, std::size_t indent_value) const

@@ -61,13 +55,13 @@ void element::render(std::ostream& out, std::size_t indent_value) const break; }
if (m_name.empty()) {
if (m_tag.empty()) {
out << indent << m_data << '\n'; return; } if (!m_data.empty()) {
out << indent << std::format("<{} {}>\n", m_name, m_attributes);
out << indent << std::format("<{} {}>\n", m_tag, attributes());
if (!m_children.empty()) { render_children(out, indent_value + 2);

@@ -75,43 +69,21 @@ void element::render(std::ostream& out, std::size_t indent_value) const out << indent << " " << m_data << '\n'; }
out << indent << std::format("</{}>\n", m_name);
out << indent << std::format("</{}>\n", m_tag);
return; } if (m_children.empty()) { if (tgl_state()) {
out << indent << std::format("<{} {}>\n", m_name, m_attributes);
out << indent << std::format("<{} {}>\n", m_tag, attributes());
} else {
out << indent << std::format("</{}>\n", m_name);
out << indent << std::format("</{}>\n", m_tag);
} } else {
out << indent << std::format("<{} {}>\n", m_name, m_attributes);
out << indent << std::format("<{} {}>\n", m_tag, attributes());
render_children(out, indent_value + 2);
out << indent << std::format("</{}>\n", m_name);
out << indent << std::format("</{}>\n", m_tag);
} }
element& element::set(const attribute_list& list)
{
m_attributes.set(list);
return *this;
}
element& element::set(attribute attr)
{
m_attributes.set(std::move(attr));
return *this;
}
element element::add(const attribute_list& list) const
{
return element(*this).set(list);
}
element element::add(attribute attr) const
{
return element(*this).set(std::move(attr));
}
} // namespace hemplate