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 71995b9619fec51a9e57635abd4d7ec9efadf91d
parent 67206b1ffe8c8b0f326ecd8c8e762e282594ba5e
author Dimitrije Dobrota <mail@dimitrijedobrota.com>
date Wed, 23 Apr 2025 08:16:24 +0200

Fix formating, naming and inconsistencies

Diffstat:
M include/hemplate/atom.hpp | +++++++++++++++++++++++++++++++++ ------------------------------
M include/hemplate/attribute.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 include/hemplate/streamable.hpp | ++++++++++++++ -------------
M source/attribute.cpp | +++++++++++++++++++++++++++++++++++++ -----------------------------
M source/classes.cpp | ++++++ ---
M source/element.cpp | +++++++++++++ --------------------------
M test/source/hemplate_test.cpp | ++ --

12 files changed, 339 insertions(+), 328 deletions(-)


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

@@ -2,24 +2,25 @@ #include "hemplate/classes.hpp"
namespace hemplate::atom {
namespace hemplate::atom
{
std::string format_time(std::int64_t sec); std::string format_time_now();
class feed : public elementBuilder<tag<"feed">, element::Type::Boolean>
class feed : public element_builder<tag<"feed">, element::Type::Boolean>
{ public: static constexpr const auto default_xmlns = "http://www.w3.org/2005/Atom"; explicit feed(std::string xmlns, const std::derived_from<element> auto&... children)
: elementBuilder({{"xmlns", std::move(xmlns)}}, children...)
: element_builder({{"xmlns", std::move(xmlns)}}, children...)
{ } explicit feed(std::string xmlns, std::span<const element> children)
: elementBuilder({{"xmlns", std::move(xmlns)}}, children)
: element_builder({{"xmlns", std::move(xmlns)}}, children)
{ }

@@ -41,32 +42,34 @@ using hemplate::transparent; using hemplate::xml; // clang-format off
using author = elementBuilder<tag<"author">, element::Type::Boolean>;
using category = elementBuilder<tag<"category">, element::Type::Boolean>;
using content = elementBuilder<tag<"content">, element::Type::Boolean>;
using contributor = elementBuilder<tag<"contributor">, element::Type::Boolean>;
using div = elementBuilder<tag<"div">, element::Type::Boolean>;
using email = elementBuilder<tag<"email">, element::Type::Boolean>;
using entry = elementBuilder<tag<"entry">, element::Type::Boolean>;
using generator = elementBuilder<tag<"generator">, element::Type::Boolean>;
using icon = elementBuilder<tag<"icon">, element::Type::Boolean>;
using id = elementBuilder<tag<"id">, element::Type::Boolean>;
using intervalBlock = elementBuilder<tag<"intervalBlock">, element::Type::Boolean>;
using link = elementBuilder<tag<"link">, element::Type::Boolean>;
using logo = elementBuilder<tag<"logo">, element::Type::Boolean>;
using meterReading = elementBuilder<tag<"meterReading">, element::Type::Boolean>;
using name = elementBuilder<tag<"name">, element::Type::Boolean>;
using published = elementBuilder<tag<"published">, element::Type::Boolean>;
using readingType = elementBuilder<tag<"readingType">, element::Type::Boolean>;
using rights = elementBuilder<tag<"rights">, element::Type::Boolean>;
using source = elementBuilder<tag<"source">, element::Type::Boolean>;
using subtitle = elementBuilder<tag<"subtitle">, element::Type::Boolean>;
using summary = elementBuilder<tag<"summary">, element::Type::Boolean>;
using text = elementBuilder<tag<"">, element::Type::Boolean>;
using title = elementBuilder<tag<"title">, element::Type::Boolean>;
using updated = elementBuilder<tag<"updated">, element::Type::Boolean>;
using uri = elementBuilder<tag<"uri">, element::Type::Boolean>;
using usagePoint = elementBuilder<tag<"usagePoint">, element::Type::Boolean>;
// NOLINTBEGIN *-identifier-naming
using author = element_builder<tag<"author">, element::Type::Boolean>;
using category = element_builder<tag<"category">, element::Type::Boolean>;
using content = element_builder<tag<"content">, element::Type::Boolean>;
using contributor = element_builder<tag<"contributor">, element::Type::Boolean>;
using div = element_builder<tag<"div">, element::Type::Boolean>;
using email = element_builder<tag<"email">, element::Type::Boolean>;
using entry = element_builder<tag<"entry">, element::Type::Boolean>;
using generator = element_builder<tag<"generator">, element::Type::Boolean>;
using icon = element_builder<tag<"icon">, element::Type::Boolean>;
using id = element_builder<tag<"id">, element::Type::Boolean>;
using intervalBlock = element_builder<tag<"intervalBlock">, element::Type::Boolean>;
using link = element_builder<tag<"link">, element::Type::Boolean>;
using logo = element_builder<tag<"logo">, element::Type::Boolean>;
using meterReading = element_builder<tag<"meterReading">, element::Type::Boolean>;
using name = element_builder<tag<"name">, element::Type::Boolean>;
using published = element_builder<tag<"published">, element::Type::Boolean>;
using readingType = element_builder<tag<"readingType">, element::Type::Boolean>;
using rights = element_builder<tag<"rights">, element::Type::Boolean>;
using source = element_builder<tag<"source">, element::Type::Boolean>;
using subtitle = element_builder<tag<"subtitle">, element::Type::Boolean>;
using summary = element_builder<tag<"summary">, element::Type::Boolean>;
using text = element_builder<tag<"">, element::Type::Boolean>;
using title = element_builder<tag<"title">, element::Type::Boolean>;
using updated = element_builder<tag<"updated">, element::Type::Boolean>;
using uri = element_builder<tag<"uri">, element::Type::Boolean>;
using usagePoint = element_builder<tag<"usagePoint">, element::Type::Boolean>;
// NOLINTEND *-identifier-naming
// clang-format on } // namespace hemplate::atom

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

@@ -7,7 +7,8 @@ #include "hemplate/hemplate_export.hpp" #include "hemplate/streamable.hpp"
namespace hemplate {
namespace hemplate
{
class HEMPLATE_EXPORT attribute : public streamable<attribute> {

@@ -44,21 +45,21 @@ private: std::string m_value; };
class HEMPLATE_EXPORT attributeList : public streamable<attributeList>
class HEMPLATE_EXPORT attribute_list : public streamable<attribute_list>
{ public:
attributeList() = default;
attribute_list() = default;
attributeList(std::initializer_list<attribute> list);
attributeList(attribute attr); // NOLINT
attribute_list(std::initializer_list<attribute> list);
attribute_list(attribute attr); // NOLINT
attributeList& set(const attributeList& list);
attributeList& set(const std::string& name);
attributeList& set(const std::string& name, const std::string& value);
attribute_list& set(const attribute_list& list);
attribute_list& set(const std::string& name);
attribute_list& set(const std::string& name, const std::string& value);
attributeList add(const attributeList& list) const;
attributeList add(const std::string& name) const;
attributeList add(const std::string& name, const std::string& value) const;
attribute_list add(const attribute_list& list) const;
attribute_list add(const std::string& name) const;
attribute_list add(const std::string& name, const std::string& value) const;
bool empty() const;

@@ -66,20 +67,17 @@ public: { std::string res;
if (!m_class.empty())
{
if (!m_class.empty()) {
res += m_class; res += ' '; }
if (!m_style.empty())
{
if (!m_style.empty()) {
res += m_style; res += ' '; }
for (const auto& attr : m_attributes)
{
for (const auto& attr : m_attributes) {
res += attr; res += ' '; }

@@ -96,4 +94,4 @@ private: } // namespace hemplate CUSTOM_FORMAT(hemplate::attribute)
CUSTOM_FORMAT(hemplate::attributeList)
CUSTOM_FORMAT(hemplate::attribute_list)

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

@@ -6,7 +6,8 @@ #include "hemplate/element.hpp" #include "hemplate/hemplate_export.hpp"
namespace hemplate {
namespace hemplate
{
template<std::size_t N> struct string_literal

@@ -29,24 +30,24 @@ struct tag static char const* get_name() { return Name.data(); } };
using comment = elementBuilder<tag<"comment">, element::Type::Comment>;
using comment = element_builder<tag<"comment">, element::Type::Comment>;
class xml : public elementBuilder<tag<"xml">, element::Type::Xml>
class xml : public element_builder<tag<"xml">, element::Type::Xml>
{ public:
static constexpr const auto default_version = "1.0";
static constexpr const auto default_version = "1.0";
static constexpr const auto default_encoding = "UTF-8";
explicit xml(std::string version = default_version,
explicit xml(std::string version = default_version,
std::string encoding = default_encoding)
: elementBuilder({{"version", std::move(version)},
{"encoding", std::move(encoding)}})
: element_builder({{"version", std::move(version)},
{"encoding", std::move(encoding)}})
{ } }; using transparent =
elementBuilder<tag<"transparent">, element::Type::Transparent>;
element_builder<tag<"transparent">, element::Type::Transparent>;
template<typename P, typename T> concept procedure = requires { requires(std::invocable<P, const T&>); };

@@ -58,8 +59,7 @@ transparent transform(const R& range, std::vector<element> res; res.reserve(std::size(range));
for (const auto& elem : range)
{
for (const auto& elem : range) {
res.emplace_back(proc(elem)); }

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

@@ -7,7 +7,8 @@ #include "hemplate/attribute.hpp" #include "hemplate/hemplate_export.hpp"
namespace hemplate {
namespace hemplate
{
class HEMPLATE_EXPORT element {

@@ -26,7 +27,7 @@ private: Type m_type; std::string m_name;
attributeList m_attributes;
attribute_list m_attributes;
std::vector<element> m_children; std::string m_data;

@@ -41,10 +42,11 @@ private: { }
explicit element(bool& state,
Type type,
std::string_view name,
std::string_view data)
explicit element(
bool& state,
Type type,
std::string_view name, // NOLINT *-easily-swappable-parameters
std::string_view data)
: m_state(&state) , m_type(type) , m_name(name)

@@ -66,7 +68,7 @@ private: explicit element(bool& state, Type type, std::string_view name,
attributeList attributes,
attribute_list attributes,
const std::derived_from<element> auto&... children) : m_state(&state) , m_type(type)

@@ -79,7 +81,7 @@ private: explicit element(bool& state, Type type, std::string_view name,
attributeList attributes,
attribute_list attributes,
std::string_view data) : m_state(&state) , m_type(type)

@@ -92,7 +94,7 @@ private: explicit element(bool& state, Type type, std::string_view name,
attributeList attributes,
attribute_list attributes,
std::span<const element> children) : m_state(&state) , m_type(type)

@@ -103,7 +105,7 @@ private: } template<typename Tag, element::Type MyType>
friend class elementBuilder;
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;

@@ -129,33 +131,33 @@ public: }; template<typename Tag, element::Type MyType>
class HEMPLATE_EXPORT elementBuilder : public element
class HEMPLATE_EXPORT element_builder : public element
{ static bool m_state; // NOLINT public:
explicit elementBuilder(std::string_view data)
explicit element_builder(std::string_view data)
: element(m_state, MyType, Tag::get_name(), data) { }
explicit elementBuilder(const std::derived_from<element> auto&... children)
explicit element_builder(const std::derived_from<element> auto&... children)
: element(m_state, MyType, Tag::get_name(), children...) { }
explicit elementBuilder(std::span<const element> children)
explicit element_builder(std::span<const element> children)
: element(m_state, MyType, Tag::get_name(), children) { }
explicit elementBuilder(attributeList attributes, std::string_view data)
explicit element_builder(attribute_list attributes, std::string_view data)
: element(m_state, MyType, Tag::get_name(), std::move(attributes), data) { }
explicit elementBuilder(attributeList attributes,
const std::derived_from<element> auto&... children)
explicit element_builder(attribute_list attributes,
const std::derived_from<element> auto&... children)
: element(m_state, MyType, Tag::get_name(),

@@ -164,8 +166,8 @@ public: { }
explicit elementBuilder(attributeList attributes,
std::span<const element> children)
explicit element_builder(attribute_list attributes,
std::span<const element> children)
: element( m_state, MyType, Tag::get_name(), std::move(attributes), children) {

@@ -173,6 +175,6 @@ public: }; template<typename Tag, element::Type Type>
bool elementBuilder<Tag, Type>::m_state = false; // NOLINT
bool element_builder<Tag, Type>::m_state = false; // NOLINT
} // namespace hemplate

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

@@ -2,7 +2,8 @@ #include "hemplate/classes.hpp"
namespace hemplate::html {
namespace hemplate::html
{
using hemplate::comment; using hemplate::element;

@@ -11,120 +12,122 @@ using hemplate::transparent; using hemplate::xml; // clang-format off
using abbr = elementBuilder<tag<"abbr">, element::Type::Boolean>;
using address = elementBuilder<tag<"address">, element::Type::Boolean>;
using a = elementBuilder<tag<"a">, element::Type::Boolean>;
using area = elementBuilder<tag<"area">, element::Type::Atomic>;
using article = elementBuilder<tag<"article">, element::Type::Boolean>;
using aside = elementBuilder<tag<"aside">, element::Type::Boolean>;
using audio = elementBuilder<tag<"audio">, element::Type::Boolean>;
using base = elementBuilder<tag<"base">, element::Type::Atomic>;
using bdi = elementBuilder<tag<"bdi">, element::Type::Boolean>;
using bdo = elementBuilder<tag<"bdo">, element::Type::Boolean>;
using b = elementBuilder<tag<"b">, element::Type::Boolean>;
using blockquote = elementBuilder<tag<"blockquote">, element::Type::Boolean>;
using body = elementBuilder<tag<"body">, element::Type::Boolean>;
using br = elementBuilder<tag<"br">, element::Type::Atomic>;
using button = elementBuilder<tag<"button">, element::Type::Boolean>;
using canvas = elementBuilder<tag<"canvas">, element::Type::Boolean>;
using caption = elementBuilder<tag<"caption">, element::Type::Boolean>;
using cite = elementBuilder<tag<"cite">, element::Type::Boolean>;
using code = elementBuilder<tag<"code">, element::Type::Boolean>;
using col = elementBuilder<tag<"col">, element::Type::Atomic>;
using colgroup = elementBuilder<tag<"colgroup">, element::Type::Boolean>;
using data = elementBuilder<tag<"data">, element::Type::Boolean>;
using datalist = elementBuilder<tag<"datalist">, element::Type::Boolean>;
using dd = elementBuilder<tag<"dd">, element::Type::Boolean>;
using del = elementBuilder<tag<"del">, element::Type::Boolean>;
using details = elementBuilder<tag<"details">, element::Type::Boolean>;
using dfn = elementBuilder<tag<"dfn">, element::Type::Boolean>;
using dialog = elementBuilder<tag<"dialog">, element::Type::Boolean>;
using div = elementBuilder<tag<"div">, element::Type::Boolean>;
using dl = elementBuilder<tag<"dl">, element::Type::Boolean>;
using doctype = elementBuilder<tag<"!DOCTYPE html">, element::Type::Atomic>;
using dt = elementBuilder<tag<"dt">, element::Type::Boolean>;
using embed = elementBuilder<tag<"embed">, element::Type::Atomic>;
using em = elementBuilder<tag<"em">, element::Type::Boolean>;
using fieldset = elementBuilder<tag<"fieldset">, element::Type::Boolean>;
using figcaption = elementBuilder<tag<"figcaption">, element::Type::Boolean>;
using figure = elementBuilder<tag<"figure">, element::Type::Boolean>;
using footer = elementBuilder<tag<"footer">, element::Type::Boolean>;
using form = elementBuilder<tag<"form">, element::Type::Boolean>;
using h1 = elementBuilder<tag<"h1">, element::Type::Boolean>;
using h2 = elementBuilder<tag<"h2">, element::Type::Boolean>;
using h3 = elementBuilder<tag<"h3">, element::Type::Boolean>;
using h4 = elementBuilder<tag<"h4">, element::Type::Boolean>;
using h5 = elementBuilder<tag<"h5">, element::Type::Boolean>;
using h6 = elementBuilder<tag<"h6">, element::Type::Boolean>;
using head = elementBuilder<tag<"head">, element::Type::Boolean>;
using header = elementBuilder<tag<"header">, element::Type::Boolean>;
using hgroup = elementBuilder<tag<"hgroup">, element::Type::Boolean>;
using hr = elementBuilder<tag<"hr">, element::Type::Atomic>;
using html = elementBuilder<tag<"html">, element::Type::Boolean>;
using i = elementBuilder<tag<"i">, element::Type::Boolean>;
using iframe = elementBuilder<tag<"iframe">, element::Type::Boolean>;
using img = elementBuilder<tag<"img">, element::Type::Atomic>;
using input = elementBuilder<tag<"input">, element::Type::Atomic>;
using ins = elementBuilder<tag<"ins">, element::Type::Boolean>;
using kbd = elementBuilder<tag<"kbd">, element::Type::Boolean>;
using label = elementBuilder<tag<"label">, element::Type::Boolean>;
using legend = elementBuilder<tag<"legend">, element::Type::Boolean>;
using li = elementBuilder<tag<"li">, element::Type::Boolean>;
using link = elementBuilder<tag<"link">, element::Type::Atomic>;
using main = elementBuilder<tag<"main">, element::Type::Boolean>;
using map = elementBuilder<tag<"map">, element::Type::Boolean>;
using mark = elementBuilder<tag<"mark">, element::Type::Boolean>;
using menu = elementBuilder<tag<"menu">, element::Type::Boolean>;
using meta = elementBuilder<tag<"meta">, element::Type::Atomic>;
using meter = elementBuilder<tag<"meter">, element::Type::Boolean>;
using nav = elementBuilder<tag<"nav">, element::Type::Boolean>;
using noscript = elementBuilder<tag<"noscript">, element::Type::Boolean>;
using object = elementBuilder<tag<"object">, element::Type::Boolean>;
using ol = elementBuilder<tag<"ol">, element::Type::Boolean>;
using optgroup = elementBuilder<tag<"optgroup">, element::Type::Boolean>;
using option = elementBuilder<tag<"option">, element::Type::Boolean>;
using output = elementBuilder<tag<"output">, element::Type::Boolean>;
using p = elementBuilder<tag<"p">, element::Type::Boolean>;
using param = elementBuilder<tag<"param">, element::Type::Atomic>;
using picture = elementBuilder<tag<"picture">, element::Type::Boolean>;
using pre = elementBuilder<tag<"pre">, element::Type::Boolean>;
using progress = elementBuilder<tag<"progress">, element::Type::Boolean>;
using q = elementBuilder<tag<"q">, element::Type::Boolean>;
using rp = elementBuilder<tag<"rp">, element::Type::Boolean>;
using rt = elementBuilder<tag<"rt">, element::Type::Boolean>;
using ruby = elementBuilder<tag<"ruby">, element::Type::Boolean>;
using s = elementBuilder<tag<"s">, element::Type::Boolean>;
using samp = elementBuilder<tag<"samp">, element::Type::Boolean>;
using script = elementBuilder<tag<"script">, element::Type::Boolean>;
using search = elementBuilder<tag<"search">, element::Type::Boolean>;
using section = elementBuilder<tag<"section">, element::Type::Boolean>;
using select = elementBuilder<tag<"select">, element::Type::Boolean>;
using small = elementBuilder<tag<"small">, element::Type::Boolean>;
using source = elementBuilder<tag<"source">, element::Type::Atomic>;
using span = elementBuilder<tag<"span">, element::Type::Boolean>;
using strong = elementBuilder<tag<"strong">, element::Type::Boolean>;
using style = elementBuilder<tag<"style">, element::Type::Boolean>;
using sub = elementBuilder<tag<"sub">, element::Type::Boolean>;
using summary = elementBuilder<tag<"summary">, element::Type::Boolean>;
using sup = elementBuilder<tag<"sup">, element::Type::Boolean>;
using svg = elementBuilder<tag<"svg">, element::Type::Boolean>;
using table = elementBuilder<tag<"table">, element::Type::Boolean>;
using tbody = elementBuilder<tag<"tbody">, element::Type::Boolean>;
using td = elementBuilder<tag<"td">, element::Type::Boolean>;
using textarea = elementBuilder<tag<"textarea">, element::Type::Boolean>;
using text = elementBuilder<tag<"">, element::Type::Boolean>;
using tfoot = elementBuilder<tag<"tfoot">, element::Type::Boolean>;
using th = elementBuilder<tag<"th">, element::Type::Boolean>;
using thead = elementBuilder<tag<"thead">, element::Type::Boolean>;
using time = elementBuilder<tag<"time">, element::Type::Boolean>;
using title = elementBuilder<tag<"title">, element::Type::Boolean>;
using tr = elementBuilder<tag<"tr">, element::Type::Boolean>;
using track = elementBuilder<tag<"track">, element::Type::Atomic>;
using u = elementBuilder<tag<"u">, element::Type::Boolean>;
using ul = elementBuilder<tag<"ul">, element::Type::Boolean>;
using var = elementBuilder<tag<"var">, element::Type::Boolean>;
using video = elementBuilder<tag<"video">, element::Type::Boolean>;
using wbr = elementBuilder<tag<"wbr">, element::Type::Atomic>;
// NOLINTBEGIN *-identifier-naming
using abbr = element_builder<tag<"abbr">, element::Type::Boolean>;
using address = element_builder<tag<"address">, element::Type::Boolean>;
using a = element_builder<tag<"a">, element::Type::Boolean>;
using area = element_builder<tag<"area">, element::Type::Atomic>;
using article = element_builder<tag<"article">, element::Type::Boolean>;
using aside = element_builder<tag<"aside">, element::Type::Boolean>;
using audio = element_builder<tag<"audio">, element::Type::Boolean>;
using base = element_builder<tag<"base">, element::Type::Atomic>;
using bdi = element_builder<tag<"bdi">, element::Type::Boolean>;
using bdo = element_builder<tag<"bdo">, element::Type::Boolean>;
using b = element_builder<tag<"b">, element::Type::Boolean>;
using blockquote = element_builder<tag<"blockquote">, element::Type::Boolean>;
using body = element_builder<tag<"body">, element::Type::Boolean>;
using br = element_builder<tag<"br">, element::Type::Atomic>;
using button = element_builder<tag<"button">, element::Type::Boolean>;
using canvas = element_builder<tag<"canvas">, element::Type::Boolean>;
using caption = element_builder<tag<"caption">, element::Type::Boolean>;
using cite = element_builder<tag<"cite">, element::Type::Boolean>;
using code = element_builder<tag<"code">, element::Type::Boolean>;
using col = element_builder<tag<"col">, element::Type::Atomic>;
using colgroup = element_builder<tag<"colgroup">, element::Type::Boolean>;
using data = element_builder<tag<"data">, element::Type::Boolean>;
using datalist = element_builder<tag<"datalist">, element::Type::Boolean>;
using dd = element_builder<tag<"dd">, element::Type::Boolean>;
using del = element_builder<tag<"del">, element::Type::Boolean>;
using details = element_builder<tag<"details">, element::Type::Boolean>;
using dfn = element_builder<tag<"dfn">, element::Type::Boolean>;
using dialog = element_builder<tag<"dialog">, element::Type::Boolean>;
using div = element_builder<tag<"div">, element::Type::Boolean>;
using dl = element_builder<tag<"dl">, element::Type::Boolean>;
using doctype = element_builder<tag<"!DOCTYPE html">, element::Type::Atomic>;
using dt = element_builder<tag<"dt">, element::Type::Boolean>;
using embed = element_builder<tag<"embed">, element::Type::Atomic>;
using em = element_builder<tag<"em">, element::Type::Boolean>;
using fieldset = element_builder<tag<"fieldset">, element::Type::Boolean>;
using figcaption = element_builder<tag<"figcaption">, element::Type::Boolean>;
using figure = element_builder<tag<"figure">, element::Type::Boolean>;
using footer = element_builder<tag<"footer">, element::Type::Boolean>;
using form = element_builder<tag<"form">, element::Type::Boolean>;
using h1 = element_builder<tag<"h1">, element::Type::Boolean>;
using h2 = element_builder<tag<"h2">, element::Type::Boolean>;
using h3 = element_builder<tag<"h3">, element::Type::Boolean>;
using h4 = element_builder<tag<"h4">, element::Type::Boolean>;
using h5 = element_builder<tag<"h5">, element::Type::Boolean>;
using h6 = element_builder<tag<"h6">, element::Type::Boolean>;
using head = element_builder<tag<"head">, element::Type::Boolean>;
using header = element_builder<tag<"header">, element::Type::Boolean>;
using hgroup = element_builder<tag<"hgroup">, element::Type::Boolean>;
using hr = element_builder<tag<"hr">, element::Type::Atomic>;
using html = element_builder<tag<"html">, element::Type::Boolean>;
using i = element_builder<tag<"i">, element::Type::Boolean>;
using iframe = element_builder<tag<"iframe">, element::Type::Boolean>;
using img = element_builder<tag<"img">, element::Type::Atomic>;
using input = element_builder<tag<"input">, element::Type::Atomic>;
using ins = element_builder<tag<"ins">, element::Type::Boolean>;
using kbd = element_builder<tag<"kbd">, element::Type::Boolean>;
using label = element_builder<tag<"label">, element::Type::Boolean>;
using legend = element_builder<tag<"legend">, element::Type::Boolean>;
using li = element_builder<tag<"li">, element::Type::Boolean>;
using link = element_builder<tag<"link">, element::Type::Atomic>;
using main = element_builder<tag<"main">, element::Type::Boolean>;
using map = element_builder<tag<"map">, element::Type::Boolean>;
using mark = element_builder<tag<"mark">, element::Type::Boolean>;
using menu = element_builder<tag<"menu">, element::Type::Boolean>;
using meta = element_builder<tag<"meta">, element::Type::Atomic>;
using meter = element_builder<tag<"meter">, element::Type::Boolean>;
using nav = element_builder<tag<"nav">, element::Type::Boolean>;
using noscript = element_builder<tag<"noscript">, element::Type::Boolean>;
using object = element_builder<tag<"object">, element::Type::Boolean>;
using ol = element_builder<tag<"ol">, element::Type::Boolean>;
using optgroup = element_builder<tag<"optgroup">, element::Type::Boolean>;
using option = element_builder<tag<"option">, element::Type::Boolean>;
using output = element_builder<tag<"output">, element::Type::Boolean>;
using p = element_builder<tag<"p">, element::Type::Boolean>;
using param = element_builder<tag<"param">, element::Type::Atomic>;
using picture = element_builder<tag<"picture">, element::Type::Boolean>;
using pre = element_builder<tag<"pre">, element::Type::Boolean>;
using progress = element_builder<tag<"progress">, element::Type::Boolean>;
using q = element_builder<tag<"q">, element::Type::Boolean>;
using rp = element_builder<tag<"rp">, element::Type::Boolean>;
using rt = element_builder<tag<"rt">, element::Type::Boolean>;
using ruby = element_builder<tag<"ruby">, element::Type::Boolean>;
using s = element_builder<tag<"s">, element::Type::Boolean>;
using samp = element_builder<tag<"samp">, element::Type::Boolean>;
using script = element_builder<tag<"script">, element::Type::Boolean>;
using search = element_builder<tag<"search">, element::Type::Boolean>;
using section = element_builder<tag<"section">, element::Type::Boolean>;
using select = element_builder<tag<"select">, element::Type::Boolean>;
using small = element_builder<tag<"small">, element::Type::Boolean>;
using source = element_builder<tag<"source">, element::Type::Atomic>;
using span = element_builder<tag<"span">, element::Type::Boolean>;
using strong = element_builder<tag<"strong">, element::Type::Boolean>;
using style = element_builder<tag<"style">, element::Type::Boolean>;
using sub = element_builder<tag<"sub">, element::Type::Boolean>;
using summary = element_builder<tag<"summary">, element::Type::Boolean>;
using sup = element_builder<tag<"sup">, element::Type::Boolean>;
using svg = element_builder<tag<"svg">, element::Type::Boolean>;
using table = element_builder<tag<"table">, element::Type::Boolean>;
using tbody = element_builder<tag<"tbody">, element::Type::Boolean>;
using td = element_builder<tag<"td">, element::Type::Boolean>;
using textarea = element_builder<tag<"textarea">, element::Type::Boolean>;
using text = element_builder<tag<"">, element::Type::Boolean>;
using tfoot = element_builder<tag<"tfoot">, element::Type::Boolean>;
using th = element_builder<tag<"th">, element::Type::Boolean>;
using thead = element_builder<tag<"thead">, element::Type::Boolean>;
using time = element_builder<tag<"time">, element::Type::Boolean>;
using title = element_builder<tag<"title">, element::Type::Boolean>;
using tr = element_builder<tag<"tr">, element::Type::Boolean>;
using track = element_builder<tag<"track">, element::Type::Atomic>;
using u = element_builder<tag<"u">, element::Type::Boolean>;
using ul = element_builder<tag<"ul">, element::Type::Boolean>;
using var = element_builder<tag<"var">, element::Type::Boolean>;
using video = element_builder<tag<"video">, element::Type::Boolean>;
using wbr = element_builder<tag<"wbr">, element::Type::Atomic>;
// NOLINTEND *-identifier-naming
// clang-format on } // namespace hemplate::html

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

@@ -2,32 +2,33 @@ #include "hemplate/classes.hpp"
namespace hemplate::rss {
namespace hemplate::rss
{
std::string format_time(std::int64_t sec); std::string format_time_now();
class rss : public elementBuilder<tag<"rss">, element::Type::Boolean>
class rss : public element_builder<tag<"rss">, element::Type::Boolean>
{ public: static constexpr const auto default_version = "2.0";
static constexpr const auto default_xmlns = "http://www.w3.org/2005/Atom";
static constexpr const auto default_xmlns = "http://www.w3.org/2005/Atom";
explicit rss(std::string version, std::string xmlns, const std::derived_from<element> auto&... children)
: elementBuilder({{"version", std::move(version)},
{"xmlns:atom", std::move(xmlns)}},
children...)
: element_builder(
{{"version", std::move(version)}, {"xmlns:atom", std::move(xmlns)}},
children...)
{ } explicit rss(std::string version, std::string xmlns, std::span<const element> children)
: elementBuilder({{"version", std::move(version)},
{"xmlns:atom", std::move(xmlns)}},
children)
: element_builder(
{{"version", std::move(version)}, {"xmlns:atom", std::move(xmlns)}},
children)
{ }

@@ -42,30 +43,30 @@ public: } };
class atomLink
: public elementBuilder<tag<"atom:link">, element::Type::Boolean>
class atomLink // NOLINT *-identifier-naming
: public element_builder<tag<"atom:link">, element::Type::Boolean>
{ public:
static constexpr const auto default_rel = "self";
static constexpr const auto default_rel = "self";
static constexpr const auto default_type = "application/rss+xml"; explicit atomLink(std::string rel, std::string type,
const attributeList& attributes,
const attribute_list& attributes,
const std::derived_from<element> auto&... children)
: elementBuilder(attributes.add({{"rel", std::move(rel)},
{"type", std::move(type)}}),
children...)
: element_builder(attributes.add({{"rel", std::move(rel)},
{"type", std::move(type)}}),
children...)
{ } explicit atomLink(std::string rel, std::string type,
const attributeList& attributes,
const attribute_list& attributes,
std::span<const element> children)
: elementBuilder(attributes.add({{"rel", std::move(rel)},
{"type", std::move(type)}}),
children)
: element_builder(attributes.add({{"rel", std::move(rel)},
{"type", std::move(type)}}),
children)
{ }

@@ -79,13 +80,13 @@ public: { }
explicit atomLink(const attributeList& attributes,
explicit atomLink(const attribute_list& attributes,
const std::derived_from<element> auto&... children) : atomLink(default_rel, default_type, attributes, children...) { }
explicit atomLink(const attributeList& attributes,
explicit atomLink(const attribute_list& attributes,
std::span<const element> children) : atomLink(default_rel, default_type, attributes, children) {

@@ -99,37 +100,39 @@ using hemplate::transparent; using hemplate::xml; // clang-format off
using author = elementBuilder<tag<"author">, element::Type::Boolean>;
using category = elementBuilder<tag<"category">, element::Type::Boolean>;
using channel = elementBuilder<tag<"channel">, element::Type::Boolean>;
using cloud = elementBuilder<tag<"cloud">, element::Type::Atomic>;
using comments = elementBuilder<tag<"comments">, element::Type::Boolean>;
using copyright = elementBuilder<tag<"copyright">, element::Type::Boolean>;
using description = elementBuilder<tag<"description">, element::Type::Boolean>;
using docs = elementBuilder<tag<"docs">, element::Type::Boolean>;
using enclosure = elementBuilder<tag<"enclosure">, element::Type::Atomic>;
using generator = elementBuilder<tag<"generator">, element::Type::Boolean>;
using guid = elementBuilder<tag<"guid">, element::Type::Boolean>;
using height = elementBuilder<tag<"height">, element::Type::Boolean>;
using image = elementBuilder<tag<"image">, element::Type::Boolean>;
using item = elementBuilder<tag<"item">, element::Type::Boolean>;
using language = elementBuilder<tag<"language">, element::Type::Boolean>;
using lastBuildDate = elementBuilder<tag<"lastBuildDate">, element::Type::Boolean>;
using link = elementBuilder<tag<"link">, element::Type::Boolean>;
using managingEditor = elementBuilder<tag<"managingEditor">, element::Type::Boolean>;
using name = elementBuilder<tag<"name">, element::Type::Boolean>;
using pubDate = elementBuilder<tag<"pubDate">, element::Type::Boolean>;
using rating = elementBuilder<tag<"rating">, element::Type::Boolean>;
using skipDays = elementBuilder<tag<"skipDays">, element::Type::Boolean>;
using skipHours = elementBuilder<tag<"skipHours">, element::Type::Boolean>;
using source = elementBuilder<tag<"source">, element::Type::Boolean>;
using text = elementBuilder<tag<"">, element::Type::Boolean>;
using textinput = elementBuilder<tag<"textinput">, element::Type::Boolean>;
using title = elementBuilder<tag<"title">, element::Type::Boolean>;
using ttl = elementBuilder<tag<"ttl">, element::Type::Boolean>;
using url = elementBuilder<tag<"url">, element::Type::Boolean>;
using webMaster = elementBuilder<tag<"webMaster">, element::Type::Boolean>;
using width = elementBuilder<tag<"width">, element::Type::Boolean>;
// NOLINTBEGIN *-identifier-naming
using author = element_builder<tag<"author">, element::Type::Boolean>;
using category = element_builder<tag<"category">, element::Type::Boolean>;
using channel = element_builder<tag<"channel">, element::Type::Boolean>;
using cloud = element_builder<tag<"cloud">, element::Type::Atomic>;
using comments = element_builder<tag<"comments">, element::Type::Boolean>;
using copyright = element_builder<tag<"copyright">, element::Type::Boolean>;
using description = element_builder<tag<"description">, element::Type::Boolean>;
using docs = element_builder<tag<"docs">, element::Type::Boolean>;
using enclosure = element_builder<tag<"enclosure">, element::Type::Atomic>;
using generator = element_builder<tag<"generator">, element::Type::Boolean>;
using guid = element_builder<tag<"guid">, element::Type::Boolean>;
using height = element_builder<tag<"height">, element::Type::Boolean>;
using image = element_builder<tag<"image">, element::Type::Boolean>;
using item = element_builder<tag<"item">, element::Type::Boolean>;
using language = element_builder<tag<"language">, element::Type::Boolean>;
using lastBuildDate = element_builder<tag<"lastBuildDate">, element::Type::Boolean>;
using link = element_builder<tag<"link">, element::Type::Boolean>;
using managingEditor = element_builder<tag<"managingEditor">, element::Type::Boolean>;
using name = element_builder<tag<"name">, element::Type::Boolean>;
using pubDate = element_builder<tag<"pubDate">, element::Type::Boolean>;
using rating = element_builder<tag<"rating">, element::Type::Boolean>;
using skipDays = element_builder<tag<"skipDays">, element::Type::Boolean>;
using skipHours = element_builder<tag<"skipHours">, element::Type::Boolean>;
using source = element_builder<tag<"source">, element::Type::Boolean>;
using text = element_builder<tag<"">, element::Type::Boolean>;
using textinput = element_builder<tag<"textinput">, element::Type::Boolean>;
using title = element_builder<tag<"title">, element::Type::Boolean>;
using ttl = element_builder<tag<"ttl">, element::Type::Boolean>;
using url = element_builder<tag<"url">, element::Type::Boolean>;
using webMaster = element_builder<tag<"webMaster">, element::Type::Boolean>;
using width = element_builder<tag<"width">, element::Type::Boolean>;
// NOLINTEND *-identifier-naming
// clang-format on } // namespace hemplate::rss

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

@@ -2,9 +2,10 @@ #include "hemplate/classes.hpp"
namespace hemplate::sitemap {
namespace hemplate::sitemap
{
class urlset : public elementBuilder<tag<"urlset">, element::Type::Boolean>
class urlset : public element_builder<tag<"urlset">, element::Type::Boolean>
{ public: static constexpr const auto default_xmlns =

@@ -12,12 +13,12 @@ public: explicit urlset(std::string xmlns, const std::derived_from<element> auto&... children)
: elementBuilder({{"xmlns", std::move(xmlns)}}, children...)
: element_builder({{"xmlns", std::move(xmlns)}}, children...)
{ } explicit urlset(std::string xmlns, std::span<const element> children)
: elementBuilder({{"xmlns", std::move(xmlns)}}, children)
: element_builder({{"xmlns", std::move(xmlns)}}, children)
{ }

@@ -33,11 +34,13 @@ public: }; // clang-format off
using changefreq = elementBuilder<tag<"changefreq">, element::Type::Boolean>;
using lastmod = elementBuilder<tag<"lastmod">, element::Type::Boolean>;
using loc = elementBuilder<tag<"loc">, element::Type::Boolean>;
using url = elementBuilder<tag<"url">, element::Type::Boolean>;
using priority = elementBuilder<tag<"priority">, element::Type::Boolean>;
// NOLINTBEGIN *-identifier-naming
using changefreq = element_builder<tag<"changefreq">, element::Type::Boolean>;
using lastmod = element_builder<tag<"lastmod">, element::Type::Boolean>;
using loc = element_builder<tag<"loc">, element::Type::Boolean>;
using url = element_builder<tag<"url">, element::Type::Boolean>;
using priority = element_builder<tag<"priority">, element::Type::Boolean>;
// NOLINTEND *-identifier-naming
// clang-format on } // namespace hemplate::sitemap

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

@@ -5,7 +5,8 @@ #include "hemplate/hemplate_export.hpp"
namespace hemplate {
namespace hemplate
{
template<typename D> class HEMPLATE_EXPORT streamable

@@ -24,19 +25,19 @@ public: }; // NOLINTNEXTLINE cppcoreguidelines-macro-usage
#define CUSTOM_FORMAT(Type) \
template<> \
struct std::formatter<Type> \
{ \
constexpr auto parse(std::format_parse_context& ctx) \
{ \
return ctx.begin(); \
} \
\
auto format(const Type& type, std::format_context& ctx) const \
{ \
#define CUSTOM_FORMAT(Type) \
template<> \
struct std::formatter<Type> \
{ \
constexpr auto parse(std::format_parse_context& ctx) \
{ \
return ctx.begin(); \
} \
\
auto format(const Type& type, std::format_context& ctx) const \
{ \
return std::format_to(ctx.out(), "{}", static_cast<std::string>(type)); \
} \
} \
}; } // namespace hemplate

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

@@ -1,27 +1,29 @@ #include "hemplate/attribute.hpp"
namespace hemplate {
namespace hemplate
{
attributeList::attributeList(std::initializer_list<attribute> list)
attribute_list::attribute_list(std::initializer_list<attribute> list)
{
for (const auto& attr : list) set(attr.get_name(), attr.get_value());
for (const auto& attr : list) {
set(attr.get_name(), attr.get_value());
}
}
attributeList::attributeList(attribute attr) // NOLINT
attribute_list::attribute_list(attribute attr) // NOLINT
{ set(attr.get_name(), attr.get_value()); }
bool attributeList::empty() const
bool attribute_list::empty() const
{ return m_attributes.empty() && m_class.get_value().empty() && m_style.get_value().empty(); }
attributeList& attributeList::set(const attributeList& list)
attribute_list& attribute_list::set(const attribute_list& list)
{
for (const auto& attr : list.m_attributes)
{
for (const auto& attr : list.m_attributes) {
set(attr.get_name(), attr.get_value()); } set("class", list.m_class);

@@ -30,48 +32,54 @@ attributeList& attributeList::set(const attributeList& list) return (*this); }
attributeList& attributeList::set(const std::string& name)
attribute_list& attribute_list::set(const std::string& name)
{
if (name != "class" && name != "style") m_attributes.emplace_back(name);
if (name != "class" && name != "style") {
m_attributes.emplace_back(name);
}
return *this; }
attributeList& attributeList::set(const std::string& name,
const std::string& value)
attribute_list& attribute_list::set(const std::string& name,
const std::string& value)
{
if (name == "class")
{
if (m_class.get_value().empty()) m_class.set_value(value);
else m_class.set_value(m_class.get_value() + " " + value);
}
else if (name == "style")
{
if (m_style.get_value().empty()) m_style.set_value(value);
else m_style.set_value(m_style.get_value() + "; " + value);
if (name == "class") {
if (m_class.get_value().empty()) {
m_class.set_value(value);
} else {
m_class.set_value(m_class.get_value() + " " + value);
}
} else if (name == "style") {
if (m_style.get_value().empty()) {
m_style.set_value(value);
} else {
m_style.set_value(m_style.get_value() + "; " + value);
}
} else {
m_attributes.emplace_back(name, value);
}
else m_attributes.emplace_back(name, value);
return *this; }
attributeList attributeList::add(const attributeList& list) const
attribute_list attribute_list::add(const attribute_list& list) const
{
attributeList res = *this;
attribute_list res = *this;
res.set(list); return res; }
attributeList attributeList::add(const std::string& name) const
attribute_list attribute_list::add(const std::string& name) const
{
attributeList res = *this;
attribute_list res = *this;
res.set(name); return res; }
attributeList attributeList::add(const std::string& name,
const std::string& value) const
attribute_list attribute_list::add(const std::string& name,
const std::string& value) const
{
attributeList res = *this;
attribute_list res = *this;
res.set(name, value); return res; }

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

@@ -6,7 +6,8 @@ #include "hemplate/atom.hpp" #include "hemplate/rss.hpp"
namespace {
namespace
{
auto sec_since_epoch(int64_t sec) {

@@ -25,7 +26,8 @@ auto get_time_now() } // namespace
namespace hemplate::atom {
namespace hemplate::atom
{
std::string format_time(int64_t sec) {

@@ -40,7 +42,8 @@ std::string format_time_now() } // namespace hemplate::atom
namespace hemplate::rss {
namespace hemplate::rss
{
std::string format_time(int64_t sec) {

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

@@ -4,7 +4,8 @@ #include "hemplate/element.hpp"
namespace hemplate {
namespace hemplate
{
element& element::add(const element& elem) {

@@ -44,11 +45,9 @@ void element::render_xml(std::ostream& out, std::size_t indent_value) const out << indent << std::format("<?xml {}?>\n", m_attributes); }
void element::render_children(std::ostream& out,
std::size_t indent_value) const
void element::render_children(std::ostream& out, std::size_t indent_value) const
{
for (const auto& child : m_children)
{
for (const auto& child : m_children) {
child.render(out, indent_value); } }

@@ -57,8 +56,7 @@ void element::render(std::ostream& out, std::size_t indent_value) const { const std::string indent(indent_value, ' ');
switch (m_type)
{
switch (m_type) {
case Type::Atomic: render_atomic(out, indent_value); return;

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

@@ -98,19 +91,13 @@ void element::render(std::ostream& out, std::size_t indent_value) const return; }
if (m_children.empty())
{
if (tgl_state())
{
if (m_children.empty()) {
if (tgl_state()) {
out << indent << std::format("<{} {}>\n", m_name, m_attributes);
}
else
{
} else {
out << indent << std::format("</{}>\n", m_name); }
}
else
{
} else {
out << indent << std::format("<{} {}>\n", m_name, m_attributes); render_children(out, indent_value + 2); out << indent << std::format("</{}>\n", m_name);

diff --git a/ test/source/hemplate_test.cpp b/ test/source/hemplate_test.cpp

@@ -7,8 +7,8 @@ int main() { using namespace hemplate; // NOLINT
const attributeList li_attrs {{"class", "home_li"}};
const attributeList ul_attrs {
const attribute_list li_attrs {{"class", "home_li"}};
const attribute_list ul_attrs {
{"id", "main_ul"}, {"class", "home_ul"}, {"style", "margin-bottom: 1em"},