hemplate

Simple XML template engine
git clone git://git.dimitrijedobrota.com/hemplate.git
Log | Files | Refs | README | LICENSE

commit f63c8fed3fdfe6d1db925c9a4682fc6dc5c7d49b
parent 597755cfc6f067e3eee598175b6d88763c9993c1
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Sat, 22 Jun 2024 17:01:50 +0200

Proof of concept HTML tags

Diffstat:
M.clang-format | 4++--
M.clang-tidy | 10+++++-----
MCMakeLists.txt | 4++--
Ainclude/hemplate/classes.hpp | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/hemplate/element.hpp | 45+++++++++++++++++++++++++++++++++++++++++++++
Ainclude/hemplate/elementAtomic.hpp | 29+++++++++++++++++++++++++++++
Ainclude/hemplate/elementBoolean.hpp | 29+++++++++++++++++++++++++++++
Dinclude/hemplate/hemplate.hpp | 17-----------------
Ainclude/hemplate/streamable.hpp | 29+++++++++++++++++++++++++++++
Asource/element.cpp | 17+++++++++++++++++
Dsource/hemplate.cpp | 13-------------
Mtest/source/hemplate_test.cpp | 7+++++--
12 files changed, 304 insertions(+), 41 deletions(-)

diff --git a/.clang-format b/.clang-format @@ -4,10 +4,10 @@ Language: Cpp AccessModifierOffset: -2 AlignAfterOpenBracket: Align AlignConsecutiveMacros: false -AlignConsecutiveAssignments: false +AlignConsecutiveAssignments: true AlignConsecutiveBitFields: false AlignConsecutiveDeclarations: false -AlignEscapedNewlines: DontAlign +AlignEscapedNewlines: Right AlignOperands: DontAlign AlignTrailingComments: false AllowAllArgumentsOnNextLine: true diff --git a/.clang-tidy b/.clang-tidy @@ -57,7 +57,7 @@ CheckOptions: - key: 'readability-identifier-naming.AbstractClassCase' value: 'lower_case' - key: 'readability-identifier-naming.ClassCase' - value: 'lower_case' + value: 'camelBack' - key: 'readability-identifier-naming.ClassConstantCase' value: 'lower_case' - key: 'readability-identifier-naming.ClassMemberCase' @@ -79,9 +79,9 @@ CheckOptions: - key: 'readability-identifier-naming.ConstexprVariableCase' value: 'lower_case' - key: 'readability-identifier-naming.EnumCase' - value: 'lower_case' + value: 'CamelCase' - key: 'readability-identifier-naming.EnumConstantCase' - value: 'lower_case' + value: 'CamelCase' - key: 'readability-identifier-naming.FunctionCase' value: 'lower_case' - key: 'readability-identifier-naming.GlobalConstantCase' @@ -135,7 +135,7 @@ CheckOptions: - key: 'readability-identifier-naming.PublicMethodCase' value: 'lower_case' - key: 'readability-identifier-naming.ScopedEnumConstantCase' - value: 'lower_case' + value: 'CamelCase' - key: 'readability-identifier-naming.StaticConstantCase' value: 'lower_case' - key: 'readability-identifier-naming.StaticVariableCase' @@ -152,7 +152,7 @@ CheckOptions: value: 'lower_case' - key: 'readability-identifier-naming.TypeTemplateParameterCase' value: 'CamelCase' - - key: 'readability-identifier-naming.TypeTemplateParameterIgnoredRegexp', + - key: 'readability-identifier-naming.TypeTemplateParameterIgnoredRegexp' value: 'expr-type' - key: 'readability-identifier-naming.UnionCase' value: 'lower_case' diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -4,7 +4,7 @@ include(cmake/prelude.cmake) project( hemplate - VERSION 0.1.0 + VERSION 0.1.1 DESCRIPTION "Simple HTML template engine" HOMEPAGE_URL "https://git.dimitrijedobrota.com/hemplate.git" LANGUAGES CXX @@ -17,7 +17,7 @@ include(cmake/variables.cmake) add_library( hemplate_hemplate - source/hemplate.cpp + source/element.cpp ) add_library(hemplate::hemplate ALIAS hemplate_hemplate) diff --git a/include/hemplate/classes.hpp b/include/hemplate/classes.hpp @@ -0,0 +1,141 @@ +#pragma once + +#include <array> + +#include "hemplate/elementAtomic.hpp" +#include "hemplate/elementBoolean.hpp" +#include "hemplate/hemplate_export.hpp" + +template<std::size_t N> +struct string_literal +{ + // NOLINTNEXTLINE + constexpr string_literal(const char (&str)[N]) + : m_value(std::to_array(str)) + { + } + + constexpr std::size_t size() const { return N; } + constexpr const char* data() const { return m_value.data(); } + + std::array<char, N> m_value; +}; + +template<string_literal Name> +struct tag +{ + static char const* get_name() { return Name.data(); } +}; + +namespace hemplate +{ + +using a = elementBoolean<tag<"a">>; +using abbr = elementBoolean<tag<"abbr">>; +using address = elementBoolean<tag<"address">>; +using area = elementAtomic<tag<"area">>; +using article = elementBoolean<tag<"article">>; +using aside = elementBoolean<tag<"aside">>; +using audio = elementBoolean<tag<"audio">>; +using b = elementBoolean<tag<"b">>; +using base = elementAtomic<tag<"base">>; +using bdi = elementBoolean<tag<"bdi">>; +using bdo = elementBoolean<tag<"bdo">>; +using blockquote = elementBoolean<tag<"blockquote">>; +using body = elementBoolean<tag<"body">>; +using br = elementAtomic<tag<"br">>; +using button = elementBoolean<tag<"button">>; +using canvas = elementBoolean<tag<"canvas">>; +using caption = elementBoolean<tag<"caption">>; +using cite = elementBoolean<tag<"cite">>; +using code = elementBoolean<tag<"code">>; +using col = elementAtomic<tag<"col">>; +using colgroup = elementBoolean<tag<"colgroup">>; +using data = elementBoolean<tag<"data">>; +using datalist = elementBoolean<tag<"datalist">>; +using dd = elementBoolean<tag<"dd">>; +using del = elementBoolean<tag<"del">>; +using details = elementBoolean<tag<"details">>; +using dfn = elementBoolean<tag<"dfn">>; +using dialog = elementBoolean<tag<"dialog">>; +using div = elementBoolean<tag<"div">>; +using dl = elementBoolean<tag<"dl">>; +using dt = elementBoolean<tag<"dt">>; +using em = elementBoolean<tag<"em">>; +using embed = elementAtomic<tag<"embed">>; +using fieldset = elementBoolean<tag<"fieldset">>; +using figcaption = elementBoolean<tag<"figcaption">>; +using figure = elementBoolean<tag<"figure">>; +using footer = elementBoolean<tag<"footer">>; +using form = elementBoolean<tag<"form">>; +using h1 = elementBoolean<tag<"h1">>; +using head = elementBoolean<tag<"head">>; +using header = elementBoolean<tag<"header">>; +using hgroup = elementBoolean<tag<"hgroup">>; +using hr = elementAtomic<tag<"hr">>; +using html = elementBoolean<tag<"html">>; +using i = elementBoolean<tag<"i">>; +using iframe = elementBoolean<tag<"iframe">>; +using img = elementAtomic<tag<"img">>; +using input = elementAtomic<tag<"input">>; +using ins = elementBoolean<tag<"ins">>; +using kbd = elementBoolean<tag<"kbd">>; +using label = elementBoolean<tag<"label">>; +using legend = elementBoolean<tag<"legend">>; +using li = elementBoolean<tag<"li">>; +using link = elementAtomic<tag<"link">>; +using main = elementBoolean<tag<"main">>; +using map = elementBoolean<tag<"map">>; +using mark = elementBoolean<tag<"mark">>; +using menu = elementBoolean<tag<"menu">>; +using meta = elementAtomic<tag<"meta">>; +using meter = elementBoolean<tag<"meter">>; +using nav = elementBoolean<tag<"nav">>; +using noscript = elementBoolean<tag<"noscript">>; +using object = elementBoolean<tag<"object">>; +using ol = elementBoolean<tag<"ol">>; +using optgroup = elementBoolean<tag<"optgroup">>; +using option = elementBoolean<tag<"option">>; +using output = elementBoolean<tag<"output">>; +using p = elementBoolean<tag<"p">>; +using param = elementAtomic<tag<"param">>; +using picture = elementBoolean<tag<"picture">>; +using pre = elementBoolean<tag<"pre">>; +using progress = elementBoolean<tag<"progress">>; +using q = elementBoolean<tag<"q">>; +using rp = elementBoolean<tag<"rp">>; +using rt = elementBoolean<tag<"rt">>; +using ruby = elementBoolean<tag<"ruby">>; +using s = elementBoolean<tag<"s">>; +using samp = elementBoolean<tag<"samp">>; +using script = elementBoolean<tag<"script">>; +using search = elementBoolean<tag<"search">>; +using section = elementBoolean<tag<"section">>; +using select = elementBoolean<tag<"select">>; +using small = elementBoolean<tag<"small">>; +using source = elementAtomic<tag<"source">>; +using span = elementBoolean<tag<"span">>; +using strong = elementBoolean<tag<"strong">>; +using style = elementBoolean<tag<"style">>; +using sub = elementBoolean<tag<"sub">>; +using summary = elementBoolean<tag<"summary">>; +using sup = elementBoolean<tag<"sup">>; +using svg = elementBoolean<tag<"svg">>; +using table = elementBoolean<tag<"table">>; +using tbody = elementBoolean<tag<"tbody">>; +using td = elementBoolean<tag<"td">>; +using textarea = elementBoolean<tag<"textarea">>; +using tfoot = elementBoolean<tag<"tfoot">>; +using th = elementBoolean<tag<"th">>; +using thead = elementBoolean<tag<"thead">>; +using time = elementBoolean<tag<"time">>; +using title = elementBoolean<tag<"title">>; +using tr = elementBoolean<tag<"tr">>; +using track = elementAtomic<tag<"track">>; +using u = elementBoolean<tag<"u">>; +using ul = elementBoolean<tag<"ul">>; +using var = elementBoolean<tag<"var">>; +using video = elementBoolean<tag<"video">>; +using wbr = elementAtomic<tag<"wbr">>; + +} // namespace hemplate diff --git a/include/hemplate/element.hpp b/include/hemplate/element.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include <string> + +#include "hemplate/hemplate_export.hpp" +#include "hemplate/streamable.hpp" + +namespace hemplate +{ + +class HEMPLATE_EXPORT element : public streamable +{ +public: + enum class Type + { + Atomic, + Boolean, + }; + + explicit element(Type type) + : m_type(type) + { + } + + element(const element&) = default; + element(element&&) noexcept = default; + element& operator=(const element&) = default; + element& operator=(element&&) noexcept = default; + ~element() override = default; + + Type get_type() const { return m_type; } + std::string get_data() const { return m_data; } + + void set_data(const std::string& data) { m_data = data; } + + virtual const char* get_name() const = 0; + void render(std::ostream& out) const override; + +private: + Type m_type; + + std::string m_data; +}; + +} // namespace hemplate diff --git a/include/hemplate/elementAtomic.hpp b/include/hemplate/elementAtomic.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "hemplate/element.hpp" +#include "hemplate/hemplate_export.hpp" + +namespace hemplate +{ + +template<typename Tag> +class HEMPLATE_EXPORT elementAtomic : public element +{ +public: + elementAtomic() + : element(Type::Atomic) + { + } + + elementAtomic(const elementAtomic&) = default; + elementAtomic(elementAtomic&&) noexcept = default; + elementAtomic& operator=(const elementAtomic&) = default; + elementAtomic& operator=(elementAtomic&&) noexcept = default; + ~elementAtomic() override = default; + + const char* get_name() const override { return Tag::get_name(); } + +private: +}; + +} // namespace hemplate diff --git a/include/hemplate/elementBoolean.hpp b/include/hemplate/elementBoolean.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "hemplate/element.hpp" +#include "hemplate/hemplate_export.hpp" + +namespace hemplate +{ + +template<typename Tag> +class HEMPLATE_EXPORT elementBoolean : public element +{ +public: + elementBoolean() + : element(Type::Boolean) + { + } + + elementBoolean(const elementBoolean&) = default; + elementBoolean(elementBoolean&&) noexcept = default; + elementBoolean& operator=(const elementBoolean&) = default; + elementBoolean& operator=(elementBoolean&&) noexcept = default; + ~elementBoolean() override = default; + + const char* get_name() const override { return Tag::get_name(); } + +private: +}; + +} // namespace hemplate diff --git a/include/hemplate/hemplate.hpp b/include/hemplate/hemplate.hpp @@ -1,17 +0,0 @@ -#pragma once - -#include <string> - -#include "hemplate/hemplate_export.hpp" - -class HEMPLATE_EXPORT exported_class -{ -public: - exported_class(); - - char const* name() const; - -private: - HEMPLATE_SUPPRESS_C4251 - std::string m_name; -}; diff --git a/include/hemplate/streamable.hpp b/include/hemplate/streamable.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include <ostream> + +#include "hemplate/hemplate_export.hpp" + +namespace hemplate +{ + +class HEMPLATE_EXPORT streamable +{ +public: + streamable() = default; + streamable(const streamable&) = default; + streamable(streamable&&) noexcept = default; + streamable& operator=(const streamable&) = default; + streamable& operator=(streamable&&) noexcept = default; + virtual ~streamable() = default; + + virtual void render(std::ostream& out) const = 0; + + friend std::ostream& operator<<(std::ostream& out, const streamable& obj) + { + obj.render(out); + return out; + } +}; + +} // namespace hemplate diff --git a/source/element.cpp b/source/element.cpp @@ -0,0 +1,17 @@ +#include "hemplate/element.hpp" + +namespace hemplate +{ + +void element::render(std::ostream& out) const +{ + if (get_type() == Type::Boolean) { + out << "<" << get_name() << ">"; + out << get_data(); + out << "</" << get_name() << ">"; + } else { + out << "<" << get_name() << " />"; + } +} + +} // namespace hemplate diff --git a/source/hemplate.cpp b/source/hemplate.cpp @@ -1,13 +0,0 @@ -#include <string> - -#include "hemplate/hemplate.hpp" - -exported_class::exported_class() - : m_name {"hemplate"} -{ -} - -char const* exported_class::name() const -{ - return m_name.c_str(); -} diff --git a/test/source/hemplate_test.cpp b/test/source/hemplate_test.cpp @@ -1,8 +1,11 @@ -#include <string> +#include <iostream> -#include "hemplate/hemplate.hpp" +#include "hemplate/classes.hpp" int main() { + std::cout << hemplate::a() << std::endl; + std::cout << hemplate::meta() << std::endl; + return 0; }