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 cac6d73e0f4c4f674875a911c1f4946d7bc690cb
parent d287efed0625b53751c1eb47d9a91d46a42c7218
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Wed, 23 Apr 2025 13:19:30 +0200

Attribute test, bug fixing, improved consistency

Diffstat:
M include/hemplate/attribute.hpp | +++++++++++++++++ ----------
M source/attribute.cpp | +++++++++ --------
M test/CMakeLists.txt | ++
A test/source/attribute.cpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

4 files changed, 87 insertions(+), 18 deletions(-)


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

@@ -9,30 +9,37 @@

namespace hemplate
{

struct HEMPLATE_EXPORT attribute
class HEMPLATE_EXPORT attribute
{
std::string name;
std::string value;
std::string m_name;
std::string m_value;

explicit attribute(std::string_view namee)
: name(namee)
public:
attribute(std::string_view name) // NOLINT *-explicit-constructor
: m_name(name)
{
}

attribute(std::string_view namee, std::string_view val)
: name(namee)
, value(val)
attribute(std::string_view name, std::string_view val)
: m_name(name)
, m_value(val)
{
}

operator std::string() const // NOLINT *-explicit-constructor
{
return name + "=\"" + value + "\"";
if (empty()) {
return name();
}
return name() + "=\"" + value() + "\"";
}

const std::string& name() const { return m_name; }
const std::string& value() const { return m_value; }

bool operator==(const attribute& rhs) const = default;

bool empty() const { return value.empty(); }
bool empty() const { return value().empty(); }

attribute& append(std::string_view delim, const std::string& val);
};

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

@@ -5,11 +5,11 @@ namespace hemplate


attribute& attribute::append(std::string_view delim, const std::string& val)
{
if (!value.empty()) {
if (!val.empty()) {
if (!empty()) {
value += std::string(delim);
m_value += std::string(delim);
}
value += val;
m_value += val;
}
return *this;
}

@@ -28,7 +28,8 @@ attribute_list::attribute_list(attribute attr)


bool attribute_list::empty() const
{
return m_attributes.empty() && m_class.value.empty() && m_style.value.empty();
return m_attributes.empty() && m_class.value().empty()
&& m_style.value().empty();
}

attribute_list& attribute_list::set(const attribute_list& list)

@@ -45,10 +46,10 @@ attribute_list& attribute_list::set(const attribute_list& list)


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

diff --git a/ test/CMakeLists.txt b/ test/CMakeLists.txt

@@ -21,6 +21,8 @@ function(add_test NAME)

catch_discover_tests("${NAME}")
endfunction()

add_test(attribute)

# ---- End-of-file commands ----

add_folders(Test)

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

@@ -0,0 +1,59 @@

#include "hemplate/attribute.hpp"

#include <catch2/catch_test_macros.hpp>

TEST_CASE("constructor", "[attribute]")
{
SECTION("name")
{
const hemplate::attribute attr {"class"};

REQUIRE(attr.name() == "class");
REQUIRE(attr.empty());
REQUIRE(std::string(attr) == "class");
}

SECTION("name, value")
{
const hemplate::attribute attr {"class", "test"};

REQUIRE(attr.name() == "class");
REQUIRE(attr.value() == "test");
REQUIRE(!attr.empty());
REQUIRE(std::string(attr) == R"(class="test")");
}
}

TEST_CASE("append", "[attribute]")
{
hemplate::attribute attr {"class"};

SECTION("empty")
{
attr.append(" ", "");

REQUIRE(attr.name() == "class");
REQUIRE(attr.empty());
REQUIRE(std::string(attr) == R"(class)");
}

SECTION("first")
{
attr.append(" ", "first");

REQUIRE(attr.name() == "class");
REQUIRE(attr.value() == "first");
REQUIRE(!attr.empty());
REQUIRE(std::string(attr) == R"(class="first")");

SECTION("second")
{
attr.append(" ", "second");

REQUIRE(attr.name() == "class");
REQUIRE(attr.value() == "first second");
REQUIRE(!attr.empty());
REQUIRE(std::string(attr) == R"(class="first second")");
}
}
}