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 7b79f6bda1d93c11b4e581d375b585cb9bbe9c63
parent cb6446371e20af7b6f6b6637da005fa73ebbe589
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Sat, 3 May 2025 09:41:56 +0200

Add shorthands for commonly used tags, with tests

Diffstat:
M include/hemplate/atom.hpp | ++++++++++++++++++++++++++++++++++++++++ --
M include/hemplate/html.hpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ---
M test/source/atom_test.cpp | ++++++++++++++++++++++++
M test/source/html_test.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

4 files changed, 227 insertions(+), 4 deletions(-)


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

@@ -51,7 +51,6 @@ using generator = element_boolean<"generator">;

using icon = element_boolean<"icon">;
using id = element_boolean<"id">;
using intervalBlock = element_boolean<"intervalBlock">;
using link = element_boolean<"link">;
using logo = element_boolean<"logo">;
using meterReading = element_boolean<"meterReading">;
using name = element_boolean<"name">;

@@ -65,7 +64,46 @@ using title = element_boolean<"title">;

using updated = element_boolean<"updated">;
using uri = element_boolean<"uri">;
using usagePoint = element_boolean<"usagePoint">;
// NOLINTEND(*naming*)

using link = element_atomic<"link">;
// clang-format on

class HEMPLATE_EXPORT linkHref : public link
{
public:
explicit linkHref(std::string_view href)
: link(attribute_list {
{"href", href},
})
{
}
};

class HEMPLATE_EXPORT linkSelf : public link
{
public:
explicit linkSelf(std::string_view href)
: link(attribute_list {
{"rel", "self"},
{"href", href},
})
{
}
};

class HEMPLATE_EXPORT linkAlternate : public link
{
public:
explicit linkAlternate(std::string_view href)
: link(attribute_list {
{"rel", "alternate"},
{"type", "text/html"},
{"href", href},
})
{
}
};

// NOLINTEND(*naming*)

} // namespace hemplate::atom

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

@@ -10,7 +10,7 @@ using hemplate::element;

using hemplate::transform;
using hemplate::xml;

class doctype : public element
class HEMPLATE_EXPORT doctype : public element
{
public:
explicit doctype()

@@ -134,7 +134,97 @@ using param = element_atomic<"param">;

using source = element_atomic<"source">;
using track = element_atomic<"track">;
using wbr = element_atomic<"wbr">;
// NOLINTEND(*naming*)
// clang-format on

class HEMPLATE_EXPORT aHref : public a
{
public:
template<typename... Args>
requires(!std::same_as<attribute_list, std::remove_cvref_t<Args>> && ...)
explicit aHref(std::string_view href, Args&&... args)
: a(attribute_list {{"href", href}}, std::forward<Args>(args)...)
{
}
};

class HEMPLATE_EXPORT metaUTF8 : public meta
{
public:
metaUTF8()
: meta(attribute_list {
{"charset", "UTF8"},
})
{
}
};

class HEMPLATE_EXPORT metaName : public meta
{
public:
metaName(std::string_view name, std::string_view content)
: meta(attribute_list {
{"name", name},
{"content", content},
})
{
}
};

class HEMPLATE_EXPORT linkStylesheet : public link
{
public:
explicit linkStylesheet(std::string_view href)
: link(attribute_list {
{"rel", "stylesheet"},
{"type", "text/css"},
{"href", href},
})
{
}
};

class HEMPLATE_EXPORT linkRss : public link
{
public:
linkRss(std::string_view ttl, std::string_view href)
: link(attribute_list {
{"rel", "alternate"},
{"type", "application/atom+xml"},
{"title", ttl},
{"href", href},
})
{
}
};

class HEMPLATE_EXPORT linkAtom : public link
{
public:
linkAtom(std::string_view ttl, std::string_view href)
: link(attribute_list {
{"rel", "alternate"},
{"type", "application/atom+xml"},
{"title", ttl},
{"href", href},
})
{
}
};

class HEMPLATE_EXPORT linkIcon : public link
{
public:
linkIcon(std::string_view sizes, std::string_view href)
: link(attribute_list {
{"rel", "icon"},
{"type", "image/png"},
{"sizes", sizes},
{"href", href},
})
{
}
};

// NOLINTEND(*naming*)

} // namespace hemplate::html

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

@@ -23,3 +23,27 @@ TEST_CASE("feed", "[atom/feed]")

REQUIRE(std::string(feed) == "<feed hello=\"world\">\n</feed>\n");
}
}

TEST_CASE("linkHref", "[atom/linkHref]")
{
const atom::linkHref link {"url"};

REQUIRE(std::string(link) == "<link href=\"url\" />\n");
}

TEST_CASE("linkSelf", "[atom/linkSelf]")
{
const atom::linkSelf link {"url"};

REQUIRE(std::string(link) == "<link rel=\"self\" href=\"url\" />\n");
}

TEST_CASE("linkAlternate", "[atom/linkAlternate]")
{
const atom::linkAlternate link {"url"};

REQUIRE(
std::string(link)
== "<link rel=\"alternate\" type=\"text/html\" href=\"url\" />\n"
);
}

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

@@ -10,3 +10,74 @@ TEST_CASE("doctype", "[html/doctype]")


REQUIRE(std::string(doctype) == "<!DOCTYPE html>\n");
}

TEST_CASE("aHref", "[html/aHref]")
{
SECTION("empty")
{
const html::aHref a {"url"};

REQUIRE(std::string(a) == "<a href=\"url\">\n</a>\n");
}

SECTION("child")
{
const html::aHref a {"url", html::br{}};

REQUIRE(std::string(a) == "<a href=\"url\"><br /></a>\n");
}
}

TEST_CASE("metaUTF8", "[html/metaUTF8]")
{
const html::metaUTF8 meta;

REQUIRE(std::string(meta) == "<meta charset=\"UTF8\" />\n");
}

TEST_CASE("metaName", "[html/metaName]")
{
const html::metaName meta {"author", "Kenobi"};

REQUIRE(std::string(meta) == "<meta name=\"author\" content=\"Kenobi\" />\n");
}

TEST_CASE("linkStylesheet", "[html/linkStylesheet]")
{
const html::linkStylesheet link {"url"};

REQUIRE(
std::string(link)
== "<link rel=\"stylesheet\" type=\"text/css\" href=\"url\" />\n"
);
}

TEST_CASE("linkRss", "[html/linkRss]")
{
const html::linkRss link {"hi", "url"};

REQUIRE(
std::string(link)
== "<link rel=\"alternate\" type=\"application/atom+xml\" title=\"hi\" href=\"url\" />\n"
);
}

TEST_CASE("linkAtom", "[html/linkAtom]")
{
const html::linkAtom link {"hi", "url"};

REQUIRE(
std::string(link)
== "<link rel=\"alternate\" type=\"application/atom+xml\" title=\"hi\" href=\"url\" />\n"
);
}

TEST_CASE("linkIcon", "[html/linkIcon]")
{
const html::linkIcon link {"16x16", "url"};

REQUIRE(
std::string(link)
== "<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"url\" />\n"
);
}