hemplateSimple 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
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