diff --git a/examples/biteme.lol.cpp b/examples/biteme.lol.cpp index 9038dc0..7f1da40 100644 --- a/examples/biteme.lol.cpp +++ b/examples/biteme.lol.cpp @@ -51,8 +51,8 @@ int main() { docpp::HTML::HTMLSection div2{docpp::HTML::SECTION_DIV, {docpp::HTML::HTMLProperty("align", "center")}}; docpp::HTML::HTMLSection form{"form", {{docpp::HTML::HTMLProperty("action", "https://google.com/search"), docpp::HTML::HTMLProperty("method", "get")}}}; - form.push_back({"input", docpp::HTML::HTMLElementProperties({docpp::HTML::HTMLProperty("type", "text"), docpp::HTML::HTMLProperty("name", "q")}), "", docpp::HTML::TYPE_SELF_CLOSING}); - form.push_back({"input", docpp::HTML::HTMLElementProperties({docpp::HTML::HTMLProperty("type", "submit"), docpp::HTML::HTMLProperty("value", "Search!")}), "", docpp::HTML::TYPE_SELF_CLOSING}); + form.push_back({"input", docpp::HTML::HTMLProperties({docpp::HTML::HTMLProperty("type", "text"), docpp::HTML::HTMLProperty("name", "q")}), "", docpp::HTML::TYPE_SELF_CLOSING}); + form.push_back({"input", docpp::HTML::HTMLProperties({docpp::HTML::HTMLProperty("type", "submit"), docpp::HTML::HTMLProperty("value", "Search!")}), "", docpp::HTML::TYPE_SELF_CLOSING}); div2.push_back(form); html.push_back(div2); diff --git a/examples/hello-world.cpp b/examples/hello-world.cpp index 838438c..951fad0 100644 --- a/examples/hello-world.cpp +++ b/examples/hello-world.cpp @@ -22,7 +22,7 @@ int main() { * The first argument is the type of section, and this can either be a predefined value (e.g., docpp::HTML::SECTION_HTML) or a * custom value in the form of an std::string object. * - * The second argument is an HTMLElementProperties object, which is a collection of HTMLProperty objects. Each property is a std::pair of an + * The second argument is an HTMLProperties object, which is a collection of HTMLProperty objects. Each property is a std::pair of an * attribute name and an attribute value. If you don't want to specify any attributes, you can pass an empty HTMLElementAttributes object. * If you need to change the tag and/or attributes later, you can use the set() method. * @@ -40,7 +40,7 @@ int main() { /* This is an HTML element. Unlike a section, an element cannot hold any other elements or sections, rather it holds text and/or attributes. * The first argument is the type of element, and this should simply be the tag name (e.g., "p", "h1", "a", etc.). * - * The second argument is an HTMLElementProperties object, which is a collection of HTMLProperty objects. Each property is a std::pair of an + * The second argument is an HTMLProperties object, which is a collection of HTMLProperty objects. Each property is a std::pair of an * attribute name and an attribute value. If you don't want to specify any attributes, you can pass an empty HTMLElementAttributes object. * If you need to change the element's tag, attributes, type or text later, you can use the set() method. * diff --git a/include/docpp.hpp b/include/docpp.hpp index 9654190..5b8a54c 100644 --- a/include/docpp.hpp +++ b/include/docpp.hpp @@ -16,11 +16,43 @@ #include #include #include +#include /** * @brief A namespace to represent HTML elements and documents */ namespace docpp { + /** + * @brief A class to represent an exception when an index is out of range + */ + class out_of_range : public std::exception { + private: + const char* message{"Out of range"}; + public: + const char* what() const noexcept override { + return message; + } + out_of_range() = default; + out_of_range(const char* message) : message(message) {}; + }; + + /** + * @brief A class to represent an exception when an argument is invalid + */ + class invalid_argument : public std::exception { + private: + const char* message{"Invalid argument"}; + public: + const char* what() const noexcept override { + return message; + } + invalid_argument() = default; + invalid_argument(const char* message) : message(message) {}; + }; + + /** + * @brief A namespace to represent HTML elements and documents + */ namespace HTML { enum { SECTION_EMPTY, @@ -100,11 +132,57 @@ namespace docpp { /** * @brief A class to represent the properties of an HTML element */ - class HTMLElementProperties { + class HTMLProperties { private: std::vector properties{}; protected: public: + using iterator = std::vector::iterator; + using const_iterator = std::vector::const_iterator; + using reverse_iterator = std::vector::reverse_iterator; + using const_reverse_iterator = std::vector::const_reverse_iterator; + + /** + * @brief Return an iterator to the beginning. + * @return iterator The iterator to the beginning. + */ + iterator begin() { return properties.begin(); } + /** + * @brief Return an iterator to the end. + * @return iterator The iterator to the end. + */ + iterator end() { return properties.end(); } + /** + * @brief Return a const iterator to the beginning. + * @return const_iterator The const iterator to the beginning. + */ + const_iterator cbegin() const { return properties.cbegin(); } + /** + * @brief Return a const iterator to the end. + * @return const_iterator The const iterator to the end. + */ + const_iterator cend() const { return properties.cend(); } + /** + * @brief Return a reverse iterator to the beginning. + * @return reverse_iterator The reverse iterator to the beginning. + */ + reverse_iterator rbegin() { return properties.rbegin(); } + /** + * @brief Return a reverse iterator to the end. + * @return reverse_iterator The reverse iterator to the end. + */ + reverse_iterator rend() { return properties.rend(); } + /** + * @brief Return a const reverse iterator to the beginning. + * @return const_reverse_iterator The const reverse iterator to the beginning. + */ + const_reverse_iterator crbegin() { return properties.crbegin(); } + /** + * @brief Return a const reverse iterator to the end. + * @return const_reverse_iterator The const reverse iterator to the end. + */ + const_reverse_iterator crend() { return properties.crend(); } + /** * @brief The npos value */ @@ -187,25 +265,27 @@ namespace docpp { */ void push_back(const HTMLProperty& property); /** - * @brief Construct a new HTMLElementProperties object + * @brief Construct a new HTMLProperties object * @param properties The properties to set */ - HTMLElementProperties(const std::vector& properties); + HTMLProperties(const std::vector& properties); /** - * @brief Construct a new HTMLElementProperties object + * @brief Construct a new HTMLProperties object * @param property The property to add */ - HTMLElementProperties(const HTMLProperty& property); + HTMLProperties(const HTMLProperty& property); /** - * @brief Construct a new HTMLElementProperties object + * @brief Construct a new HTMLProperties object */ - HTMLElementProperties() = default; - HTMLElementProperties operator=(const HTMLElementProperties& properties); - HTMLElementProperties operator=(const std::vector& properties); - HTMLElementProperties operator=(const HTMLProperty& property); + HTMLProperties() = default; + HTMLProperties operator=(const HTMLProperties& properties); + HTMLProperties operator=(const std::vector& properties); + HTMLProperties operator=(const HTMLProperty& property); void operator+=(const HTMLProperty& property); }; + using HTMLElementProperties = HTMLProperties; + /** * @brief A class to represent an HTML element */ @@ -214,7 +294,7 @@ namespace docpp { std::string tag{}; std::string data{}; int type{TYPE_NON_SELF_CLOSING}; - HTMLElementProperties properties{}; + HTMLProperties properties{}; protected: public: /** @@ -228,7 +308,7 @@ namespace docpp { * @param properties The properties of the element * @param data The data of the element */ - HTMLElement(const std::string& tag, const HTMLElementProperties& properties = {}, const std::string& data = {}, const int type = TYPE_NON_SELF_CLOSING); + HTMLElement(const std::string& tag, const HTMLProperties& properties = {}, const std::string& data = {}, const int type = TYPE_NON_SELF_CLOSING); /** * @brief Construct a new HTMLElement object */ @@ -239,7 +319,7 @@ namespace docpp { * @param id The id of the element * @param classes The classes of the element */ - void set(const std::string& tag, const HTMLElementProperties& properties = {}, const std::string& data = {}, const int type = TYPE_NON_SELF_CLOSING); + void set(const std::string& tag, const HTMLProperties& properties = {}, const std::string& data = {}, const int type = TYPE_NON_SELF_CLOSING); /** * @brief Get the element in the form of an HTML tag. @@ -269,12 +349,41 @@ namespace docpp { private: int index{}; std::string tag{}; - HTMLElementProperties properties{}; + HTMLProperties properties{}; - std::unordered_map elements{}; + std::map elements{}; std::unordered_map sections{}; protected: public: + /** + * @brief A class to represent an iterator for the HTMLSection class + */ + template + class sect_iterator { + private: + T element{}; + public: + sect_iterator(const T& element) : element(element) {} + sect_iterator operator++() { return ++element; } + HTMLElement operator*() { return element->second; } + bool operator==(const sect_iterator& other) { return element == other.element; } + bool operator!=(const sect_iterator& other) { return element != other.element; } + }; + + using iterator = sect_iterator::iterator>; + using const_iterator = sect_iterator::const_iterator>; + using reverse_iterator = sect_iterator::reverse_iterator>; + using const_reverse_iterator = sect_iterator::const_reverse_iterator>; + + iterator begin() { return iterator(elements.begin()); } + iterator end() { return iterator(elements.end()); } + const_iterator cbegin() const { return const_iterator(elements.cbegin()); } + const_iterator cend() const { return const_iterator(elements.cend()); } + reverse_iterator rbegin() { return reverse_iterator(elements.rbegin()); } + reverse_iterator rend() { return reverse_iterator(elements.rend()); } + const_reverse_iterator crbegin() { return const_reverse_iterator(elements.crbegin()); } + const_reverse_iterator crend() { return const_reverse_iterator(elements.crend()); } + /** * @brief The npos value */ @@ -388,13 +497,13 @@ namespace docpp { * @param tag The tag of the section * @param properties The properties of the section */ - HTMLSection(const std::string& tag, const HTMLElementProperties& properties = {}); + HTMLSection(const std::string& tag, const HTMLProperties& properties = {}); /** * @brief Construct a new HTMLSection object * @param tag The tag of the section * @param properties The properties of the section */ - HTMLSection(const int tag, const HTMLElementProperties& properties = {}); + HTMLSection(const int tag, const HTMLProperties& properties = {}); /** * @brief Construct a new HTMLSection object */ @@ -405,14 +514,14 @@ namespace docpp { * @param id The id of the section * @param classes The classes of the section */ - void set(const std::string& tag, const HTMLElementProperties& properties = {}); + void set(const std::string& tag, const HTMLProperties& properties = {}); /** * @brief Set the tag, id, and classes of the section * @param tag The tag of the section * @param id The id of the section * @param classes The classes of the section */ - void set(const int tag, const HTMLElementProperties& properties = {}); + void set(const int tag, const HTMLProperties& properties = {}); /** * @brief Swap two elements in the section * @param index1 The index of the first element @@ -512,6 +621,9 @@ namespace docpp { }; } // namespace HTML + /** + * @brief A namespace to represent CSS elements and documents + */ namespace CSS { enum { FORMATTING_NONE, @@ -519,6 +631,9 @@ namespace docpp { FORMATTING_NEWLINE, }; + /** + * @brief A class to represent a CSS property + */ class CSSProperty { private: std::pair property{}; @@ -588,6 +703,52 @@ namespace docpp { std::pair> element{}; protected: public: + using iterator = std::vector::iterator; + using const_iterator = std::vector::const_iterator; + using reverse_iterator = std::vector::reverse_iterator; + using const_reverse_iterator = std::vector::const_reverse_iterator; + + /** + * @brief Return an iterator to the beginning. + * @return iterator The iterator to the beginning. + */ + iterator begin() { return element.second.begin(); } + /** + * @brief Return an iterator to the end. + * @return iterator The iterator to the end. + */ + iterator end() { return element.second.end(); } + /** + * @brief Return a const iterator to the beginning. + * @return const_iterator The const iterator to the beginning. + */ + const_iterator cbegin() const { return element.second.cbegin(); } + /** + * @brief Return a const iterator to the end. + * @return const_iterator The const iterator to the end. + */ + const_iterator cend() const { return element.second.cend(); } + /** + * @brief Return a reverse iterator to the beginning. + * @return reverse_iterator The reverse iterator to the beginning. + */ + reverse_iterator rbegin() { return element.second.rbegin(); } + /** + * @brief Return a reverse iterator to the end. + * @return reverse_iterator The reverse iterator to the end. + */ + reverse_iterator rend() { return element.second.rend(); } + /** + * @brief Return a const reverse iterator to the beginning. + * @return const_reverse_iterator The const reverse iterator to the beginning. + */ + const_reverse_iterator crbegin() { return element.second.crbegin(); } + /** + * @brief Return a const reverse iterator to the end. + * @return const_reverse_iterator The const reverse iterator to the end. + */ + const_reverse_iterator crend() { return element.second.crend(); } + /** * @brief The npos value */ @@ -712,6 +873,52 @@ namespace docpp { std::vector elements{}; protected: public: + using iterator = std::vector::iterator; + using const_iterator = std::vector::const_iterator; + using reverse_iterator = std::vector::reverse_iterator; + using const_reverse_iterator = std::vector::const_reverse_iterator; + + /** + * @brief Return an iterator to the beginning. + * @return iterator The iterator to the beginning. + */ + iterator begin() { return elements.begin(); } + /** + * @brief Return an iterator to the end. + * @return iterator The iterator to the end. + */ + iterator end() { return elements.end(); } + /** + * @brief Return a const iterator to the beginning. + * @return const_iterator The const iterator to the beginning. + */ + const_iterator cbegin() const { return elements.cbegin(); } + /** + * @brief Return a const iterator to the end. + * @return const_iterator The const iterator to the end. + */ + const_iterator cend() const { return elements.cend(); } + /** + * @brief Return a reverse iterator to the beginning. + * @return reverse_iterator The reverse iterator to the beginning. + */ + reverse_iterator rbegin() { return elements.rbegin(); } + /** + * @brief Return a reverse iterator to the end. + * @return reverse_iterator The reverse iterator to the end. + */ + reverse_iterator rend() { return elements.rend(); } + /** + * @brief Return a const reverse iterator to the beginning. + * @return const_reverse_iterator The const reverse iterator to the beginning. + */ + const_reverse_iterator crbegin() { return elements.crbegin(); } + /** + * @brief Return a const reverse iterator to the end. + * @return const_reverse_iterator The const reverse iterator to the end. + */ + const_reverse_iterator crend() { return elements.crend(); } + /** * @brief The npos value */ diff --git a/src/docpp.cpp b/src/docpp.cpp index d7fbed7..fc1fa12 100644 --- a/src/docpp.cpp +++ b/src/docpp.cpp @@ -15,8 +15,6 @@ #include #include #include -#include -#include docpp::HTML::HTMLProperty::HTMLProperty(const std::string& key, const std::string& value) { this->setKey(key); @@ -51,74 +49,74 @@ void docpp::HTML::HTMLProperty::set(const std::pair& p this->property = property; } -docpp::HTML::HTMLElementProperties::HTMLElementProperties(const std::vector& properties) { +docpp::HTML::HTMLProperties::HTMLProperties(const std::vector& properties) { this->set(properties); } -docpp::HTML::HTMLElementProperties::HTMLElementProperties(const docpp::HTML::HTMLProperty& property) { +docpp::HTML::HTMLProperties::HTMLProperties(const docpp::HTML::HTMLProperty& property) { this->push_back(property); } -docpp::HTML::HTMLElementProperties docpp::HTML::HTMLElementProperties::operator=(const docpp::HTML::HTMLProperty& property) { +docpp::HTML::HTMLProperties docpp::HTML::HTMLProperties::operator=(const docpp::HTML::HTMLProperty& property) { this->properties = {property}; return *this; } -docpp::HTML::HTMLElementProperties docpp::HTML::HTMLElementProperties::operator=(const docpp::HTML::HTMLElementProperties& properties) { +docpp::HTML::HTMLProperties docpp::HTML::HTMLProperties::operator=(const docpp::HTML::HTMLProperties& properties) { this->set(properties.getProperties()); return *this; } -docpp::HTML::HTMLElementProperties docpp::HTML::HTMLElementProperties::operator=(const std::vector& properties) { +docpp::HTML::HTMLProperties docpp::HTML::HTMLProperties::operator=(const std::vector& properties) { this->set(properties); return *this; } -void docpp::HTML::HTMLElementProperties::operator+=(const docpp::HTML::HTMLProperty& property) { +void docpp::HTML::HTMLProperties::operator+=(const docpp::HTML::HTMLProperty& property) { this->push_back(property); } -std::vector docpp::HTML::HTMLElementProperties::getProperties() const { +std::vector docpp::HTML::HTMLProperties::getProperties() const { return this->properties; } -docpp::HTML::HTMLProperty docpp::HTML::HTMLElementProperties::at(const int index) const { +docpp::HTML::HTMLProperty docpp::HTML::HTMLProperties::at(const int index) const { if (index < 0 || index >= this->properties.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } return this->properties.at(index); } -void docpp::HTML::HTMLElementProperties::set(const std::vector& properties) { +void docpp::HTML::HTMLProperties::set(const std::vector& properties) { this->properties = properties; } -void docpp::HTML::HTMLElementProperties::insert(const int index, const docpp::HTML::HTMLProperty& property) { +void docpp::HTML::HTMLProperties::insert(const int index, const docpp::HTML::HTMLProperty& property) { if (index < 0 || index >= this->properties.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } this->properties.insert(this->properties.begin() + index, property); } -void docpp::HTML::HTMLElementProperties::erase(const int index) { +void docpp::HTML::HTMLProperties::erase(const int index) { if (index < 0 || index >= this->properties.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } this->properties.erase(this->properties.begin() + index); } -void docpp::HTML::HTMLElementProperties::push_front(const docpp::HTML::HTMLProperty& property) { +void docpp::HTML::HTMLProperties::push_front(const docpp::HTML::HTMLProperty& property) { this->properties.insert(this->properties.begin(), property); } -void docpp::HTML::HTMLElementProperties::push_back(const docpp::HTML::HTMLProperty& property) { +void docpp::HTML::HTMLProperties::push_back(const docpp::HTML::HTMLProperty& property) { this->properties.push_back(property); } -int docpp::HTML::HTMLElementProperties::find(const docpp::HTML::HTMLProperty& property) { +int docpp::HTML::HTMLProperties::find(const docpp::HTML::HTMLProperty& property) { for (int i{0}; i < this->properties.size(); i++) { if (!this->properties.at(i).getKey().compare(property.getKey())) { return i; @@ -133,10 +131,10 @@ int docpp::HTML::HTMLElementProperties::find(const docpp::HTML::HTMLProperty& pr } } - return docpp::HTML::HTMLElementProperties::npos; + return docpp::HTML::HTMLProperties::npos; } -int docpp::HTML::HTMLElementProperties::find(const std::string& str) { +int docpp::HTML::HTMLProperties::find(const std::string& str) { for (int i{0}; i < this->properties.size(); i++) { if (!this->properties.at(i).getKey().compare(str) || !this->properties.at(i).getValue().compare(str)) { return i; @@ -145,34 +143,34 @@ int docpp::HTML::HTMLElementProperties::find(const std::string& str) { } } - return docpp::HTML::HTMLElementProperties::npos; + return docpp::HTML::HTMLProperties::npos; } -docpp::HTML::HTMLProperty docpp::HTML::HTMLElementProperties::front() const { +docpp::HTML::HTMLProperty docpp::HTML::HTMLProperties::front() const { return this->properties.front(); } -docpp::HTML::HTMLProperty docpp::HTML::HTMLElementProperties::back() const { +docpp::HTML::HTMLProperty docpp::HTML::HTMLProperties::back() const { return this->properties.back(); } -int docpp::HTML::HTMLElementProperties::size() const { +int docpp::HTML::HTMLProperties::size() const { return this->properties.size(); } -void docpp::HTML::HTMLElementProperties::swap(const int index1, const int index2) { +void docpp::HTML::HTMLProperties::swap(const int index1, const int index2) { if (index1 < 0 || index1 >= this->properties.size() || index2 < 0 || index2 >= this->properties.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } std::swap(this->properties[index1], this->properties[index2]); } -void docpp::HTML::HTMLElementProperties::swap(const docpp::HTML::HTMLProperty& property1, const docpp::HTML::HTMLProperty& property2) { +void docpp::HTML::HTMLProperties::swap(const docpp::HTML::HTMLProperty& property1, const docpp::HTML::HTMLProperty& property2) { this->swap(this->find(property1), this->find(property2)); } -docpp::HTML::HTMLElement::HTMLElement(const std::string& tag, const HTMLElementProperties& properties, const std::string& data, const int type) { +docpp::HTML::HTMLElement::HTMLElement(const std::string& tag, const HTMLProperties& properties, const std::string& data, const int type) { this->set(tag, properties, data, type); } @@ -185,7 +183,7 @@ void docpp::HTML::HTMLElement::operator+=(const std::string& data) { this->data += data; } -void docpp::HTML::HTMLElement::set(const std::string& tag, const HTMLElementProperties& properties, const std::string& data, const int type) { +void docpp::HTML::HTMLElement::set(const std::string& tag, const HTMLProperties& properties, const std::string& data, const int type) { this->tag = tag; this->data = data; this->properties = properties; @@ -245,7 +243,7 @@ std::string docpp::HTML::HTMLElement::getData() const { return this->data; } -docpp::HTML::HTMLSection::HTMLSection(const std::string& tag, const HTMLElementProperties& properties) { +docpp::HTML::HTMLSection::HTMLSection(const std::string& tag, const HTMLProperties& properties) { this->tag = tag; this->properties = properties; } @@ -272,16 +270,16 @@ docpp::HTML::HTMLElement docpp::HTML::HTMLSection::operator[](const int& index) return this->at(index); } -docpp::HTML::HTMLSection::HTMLSection(const int tag, const HTMLElementProperties& properties) { +docpp::HTML::HTMLSection::HTMLSection(const int tag, const HTMLProperties& properties) { this->set(tag, properties); } -void docpp::HTML::HTMLSection::set(const std::string& tag, const HTMLElementProperties& properties) { +void docpp::HTML::HTMLSection::set(const std::string& tag, const HTMLProperties& properties) { this->tag = tag; this->properties = properties; } -void docpp::HTML::HTMLSection::set(const int tag, const HTMLElementProperties& properties) { +void docpp::HTML::HTMLSection::set(const int tag, const HTMLProperties& properties) { if (tag == docpp::HTML::SECTION_DIV) { this->tag = "div"; } else if (tag == docpp::HTML::SECTION_BODY) { @@ -335,7 +333,7 @@ void docpp::HTML::HTMLSection::erase(const int index) { } if (!erased) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } } @@ -349,7 +347,7 @@ void docpp::HTML::HTMLSection::erase(const HTMLSection& section) { } } - throw std::out_of_range("Section not found"); + throw docpp::out_of_range("Section not found"); } void docpp::HTML::HTMLSection::erase(const HTMLElement& element) { @@ -362,12 +360,12 @@ void docpp::HTML::HTMLSection::erase(const HTMLElement& element) { } } - throw std::out_of_range("Element not found"); + throw docpp::out_of_range("Element not found"); } void docpp::HTML::HTMLSection::insert(const int index, const HTMLElement& element) { if (this->sections.find(index) != this->sections.end()) { - throw std::invalid_argument("Index already occupied by a section"); + throw docpp::invalid_argument("Index already occupied by a section"); } else { this->elements[index] = element; } @@ -385,7 +383,7 @@ docpp::HTML::HTMLElement docpp::HTML::HTMLSection::at(const int index) const { return this->elements.at(index); } - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } docpp::HTML::HTMLSection docpp::HTML::HTMLSection::at_section(const int index) const { @@ -393,7 +391,7 @@ docpp::HTML::HTMLSection docpp::HTML::HTMLSection::at_section(const int index) c return this->sections.at(index); } - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } int docpp::HTML::HTMLSection::find(const HTMLElement& element) { @@ -445,7 +443,7 @@ docpp::HTML::HTMLElement docpp::HTML::HTMLSection::front() const { return this->elements.at(0); } - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } docpp::HTML::HTMLSection docpp::HTML::HTMLSection::front_section() const { @@ -453,7 +451,7 @@ docpp::HTML::HTMLSection docpp::HTML::HTMLSection::front_section() const { return this->sections.at(0); } - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } docpp::HTML::HTMLElement docpp::HTML::HTMLSection::back() const { @@ -461,7 +459,7 @@ docpp::HTML::HTMLElement docpp::HTML::HTMLSection::back() const { return this->elements.at(this->index - 1); } - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } docpp::HTML::HTMLSection docpp::HTML::HTMLSection::back_section() const { @@ -469,7 +467,7 @@ docpp::HTML::HTMLSection docpp::HTML::HTMLSection::back_section() const { return this->sections.at(this->index - 1); } - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } int docpp::HTML::HTMLSection::size() const { @@ -564,7 +562,7 @@ void docpp::HTML::HTMLSection::swap(const int index1, const int index2) { } else if (this->sections.find(index1) != this->sections.end() && this->sections.find(index2) != this->sections.end()) { std::swap(this->sections[index1], this->sections[index2]); } else { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } } @@ -698,7 +696,7 @@ void docpp::CSS::CSSElement::push_back(const CSSProperty& property) { void docpp::CSS::CSSElement::insert(const int index, const CSSProperty& property) { if (index < 0 || index >= this->element.second.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } this->element.second.insert(this->element.second.begin() + index, property); @@ -706,7 +704,7 @@ void docpp::CSS::CSSElement::insert(const int index, const CSSProperty& property void docpp::CSS::CSSElement::erase(const int index) { if (index < 0 || index >= this->element.second.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } this->element.second.erase(this->element.second.begin() + index); @@ -714,7 +712,7 @@ void docpp::CSS::CSSElement::erase(const int index) { docpp::CSS::CSSProperty docpp::CSS::CSSElement::at(const int index) const { if (index < 0 || index >= this->element.second.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } return this->element.second.at(index); @@ -754,7 +752,7 @@ int docpp::CSS::CSSElement::size() const { void docpp::CSS::CSSElement::swap(const int index1, const int index2) { if (index1 < 0 || index1 >= this->element.second.size() || index2 < 0 || index2 >= this->element.second.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } std::swap(this->element.second[index1], this->element.second[index2]); @@ -827,7 +825,7 @@ void docpp::CSS::CSSStylesheet::push_back(const CSSElement& element) { void docpp::CSS::CSSStylesheet::insert(const int index, const CSSElement& element) { if (index < 0 || index >= this->elements.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } this->elements.insert(this->elements.begin() + index, element); @@ -835,7 +833,7 @@ void docpp::CSS::CSSStylesheet::insert(const int index, const CSSElement& elemen void docpp::CSS::CSSStylesheet::erase(const int index) { if (index < 0 || index >= this->elements.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } this->elements.erase(this->elements.begin() + index); @@ -856,7 +854,7 @@ docpp::CSS::CSSElement docpp::CSS::CSSStylesheet::operator[](const int& index) c docpp::CSS::CSSElement docpp::CSS::CSSStylesheet::at(const int index) const { if (index < 0 || index >= this->elements.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } return this->elements.at(index); @@ -896,7 +894,7 @@ docpp::CSS::CSSElement docpp::CSS::CSSStylesheet::back() const { void docpp::CSS::CSSStylesheet::swap(const int index1, const int index2) { if (index1 < 0 || index1 >= this->elements.size() || index2 < 0 || index2 >= this->elements.size()) { - throw std::out_of_range("Index out of range"); + throw docpp::out_of_range("Index out of range"); } std::swap(this->elements[index1], this->elements[index2]); diff --git a/tests/test.cpp b/tests/test.cpp index 31e2707..a5fd8e2 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -7,7 +7,7 @@ * @brief Test cases for the docpp namespace. */ SCENARIO("Test HTML", "[HTML]") { - auto test1 = []() { + const auto test1 = []() { docpp::HTML::HTMLDocument doc{}; docpp::HTML::HTMLSection html(docpp::HTML::SECTION_HTML, {}); @@ -20,7 +20,7 @@ SCENARIO("Test HTML", "[HTML]") { body.push_back(docpp::HTML::HTMLElement("h1", {}, "Test Header")); body.push_back(docpp::HTML::HTMLElement("p", {}, "Test Paragraph")); - docpp::HTML::HTMLElementProperties prop{}; + docpp::HTML::HTMLProperties prop{}; prop.push_back(docpp::HTML::HTMLProperty(std::pair("id", "test_id"))); body.push_back(docpp::HTML::HTMLElement("p", prop, "Test Paragraph With ID")); @@ -44,7 +44,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(doc.get(docpp::HTML::FORMATTING_NEWLINE) == "\n\n\nTest Title\n\n\n

Test Header

\n

Test Paragraph

\n

Test Paragraph With ID

\n
\n

Test Paragraph In Div

\n
\n

Test Paragraph With ID And Class

\n\n
\n
\n"); }; - auto test2 = []() { + const auto test2 = []() { docpp::HTML::HTMLSection section(docpp::HTML::SECTION_HTML, {}); section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -57,7 +57,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(section.get(docpp::HTML::FORMATTING_NEWLINE) == "\n

Test 1

\n

Test 3

\n"); }; - auto test3 = []() { + const auto test3 = []() { docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_HTML, {}); section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -71,7 +71,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(section.get(docpp::HTML::FORMATTING_NEWLINE) == "\n

Test 1

\n

Test 2.5

\n

Test 3

\n"); }; - auto test4 = []() { + const auto test4 = []() { docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_HTML, {}); section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -86,7 +86,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(section.get(docpp::HTML::FORMATTING_NEWLINE) == "\n

Test 1

\n

Test 3

\n"); }; - auto test5 = []() { + const auto test5 = []() { docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_HTML, {}); docpp::HTML::HTMLSection subsection(docpp::HTML::SECTION_DIV, {}); @@ -106,7 +106,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(doc.get(docpp::HTML::FORMATTING_NEWLINE) == "\n\n
\n

Test 1

\n
\n

Test 2

\n
\n
\n"); }; - auto test6 = []() { + const auto test6 = []() { docpp::CSS::CSSStylesheet css{}; docpp::CSS::CSSElement element{"p", {{"color", "red"}, {"font-size", "16px"}, {"font-family", "Arial"}}}; @@ -116,7 +116,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(css.get(docpp::CSS::FORMATTING_NEWLINE) == "p {\ncolor: red;\nfont-size: 16px;\nfont-family: Arial;\n}\n"); }; - auto test7 = []() { + const auto test7 = []() { docpp::CSS::CSSStylesheet css = docpp::CSS::CSSStylesheet{}; docpp::CSS::CSSElement element = docpp::CSS::CSSElement{"p", {{"color", "red"}, {"font-size", "16px"}, {"font-family", "Arial"}}}; docpp::CSS::CSSElement element2{"div", {{"color", "blue"}, {"font-size", "12px"}, {"font-family", "Arial"}}}; @@ -127,7 +127,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(css.get() == "div {color: blue;font-size: 12px;font-family: Arial;}p {color: red;font-size: 16px;font-family: Arial;}"); }; - auto test8 = []() { + const auto test8 = []() { docpp::CSS::CSSStylesheet css = docpp::CSS::CSSStylesheet{}; docpp::CSS::CSSElement element = docpp::CSS::CSSElement{"p", {{"color", "red"}, {"font-size", "16px"}, {"font-family", "Arial"}}}; docpp::CSS::CSSElement element2{"div", {{"color", "blue"}, {"font-size", "12px"}, {"font-family", "Arial"}}}; @@ -140,7 +140,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(css.get() == "p {color: red;font-size: 16px;font-family: Arial;}"); }; - auto test9 = []() { + const auto test9 = []() { docpp::CSS::CSSStylesheet css = docpp::CSS::CSSStylesheet{}; docpp::CSS::CSSElement element = docpp::CSS::CSSElement{"p", {{"color", "red"}, {"font-size", "16px"}, {"font-family", "Arial"}}}; docpp::CSS::CSSElement element2{"div", {{"color", "blue"}, {"font-size", "12px"}, {"font-family", "Arial"}}}; @@ -160,7 +160,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(element.get() == "p {font-weight: bold;color: red;font-size: 16px;font-family: Arial;}"); }; - auto test10 = []() { + const auto test10 = []() { docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_HTML, {}); section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -172,7 +172,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(section.get() == "

Test 1

Test 3

Test 2

"); }; - auto test11 = []() { + const auto test11 = []() { docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_HTML, {}); section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -184,7 +184,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(section.get() == "

Test 1

Test 3

Test 2

"); }; - auto test12 = []() { + const auto test12 = []() { docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_HTML, {}); section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -196,7 +196,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(section.get() == "

Test 0

Test 1

Test 2

Test 3

"); }; - auto test13 = []() { + const auto test13 = []() { docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_HTML, {}); section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -218,7 +218,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(section.get() == "

Test 1

Test 3

Test 4

Test 5

"); }; - auto test14 = []() { + const auto test14 = []() { docpp::CSS::CSSElement element{"p", {{"color", "red"}, {"font-size", "16px"}, {"font-family", "Arial"}}}; const int red = element.find("color"); @@ -238,8 +238,8 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(element.get() == "p {color: red;font-size: 16px;font-family: Arial;}"); }; - auto test15 = []() { - docpp::HTML::HTMLElementProperties prop{}; + const auto test15 = []() { + docpp::HTML::HTMLProperties prop{}; prop.push_back(docpp::HTML::HTMLProperty(std::pair("id", "test_id"))); prop.push_back(docpp::HTML::HTMLProperty(std::pair("class", "class1 class2 class3"))); @@ -248,25 +248,25 @@ SCENARIO("Test HTML", "[HTML]") { const int pos = prop.find("class"); - REQUIRE(pos != docpp::HTML::HTMLElementProperties::npos); + REQUIRE(pos != docpp::HTML::HTMLProperties::npos); const int pos2 = prop.find("class2"); REQUIRE(prop.at(pos2).getKey() == "class"); REQUIRE(prop.at(pos2).getValue() == "class1 class2 class3"); - REQUIRE(pos2 != docpp::HTML::HTMLElementProperties::npos); + REQUIRE(pos2 != docpp::HTML::HTMLProperties::npos); const int pos3 = prop.find("class4"); - REQUIRE(pos3 == docpp::HTML::HTMLElementProperties::npos); + REQUIRE(pos3 == docpp::HTML::HTMLProperties::npos); prop.erase(pos); REQUIRE(docpp::HTML::HTMLElement("p", prop, {}).get() == "

"); }; - auto test16 = []() { + const auto test16 = []() { docpp::HTML::HTMLDocument doc = docpp::HTML::HTMLSection({}); doc.getSection().push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -284,7 +284,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(doc.get() == "

Test 4

Test 5

Test 6

Test 7

"); }; - auto test17 = []() { + const auto test17 = []() { docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_HTML, {}); section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -296,7 +296,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(doc.get(docpp::HTML::FORMATTING_PRETTY) == "\n\n\t

Test 1

\n\t

Test 2

\n\t

Test 3

\n"); }; - auto test18 = []() { + const auto test18 = []() { docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_EMPTY, {}); section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -306,7 +306,7 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(section.get() == "

Test 1

Test 2

Test 3

"); }; - auto test19 = []() { + const auto test19 = []() { docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_HTML, {}); section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); @@ -317,6 +317,62 @@ SCENARIO("Test HTML", "[HTML]") { REQUIRE(section.back().get() == "

Test 3

"); }; + const auto test20 = []() { + docpp::HTML::HTMLProperties prop{}; + + prop.push_back(docpp::HTML::HTMLProperty(std::pair("id", "test_id"))); + prop.push_back(docpp::HTML::HTMLProperty(std::pair("class", "class1 class2 class3"))); + prop.push_back(docpp::HTML::HTMLProperty(std::pair("style", "color: red; font-size: 16px; font-family: Arial;"))); + + for (const docpp::HTML::HTMLProperty& p : prop) { + REQUIRE(p.getKey() == "id"); + REQUIRE(p.getValue() == "test_id"); + break; + } + + for (docpp::HTML::HTMLProperties::iterator it = ++prop.begin(); it != prop.end(); ++it) { + REQUIRE(it->getKey() == "class"); + REQUIRE(it->getValue() == "class1 class2 class3"); + break; + } + }; + + const auto test21 = []() { + docpp::HTML::HTMLSection sect{}; + + sect.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); + sect.push_back(docpp::HTML::HTMLElement("p", {}, "Test 2")); + sect.push_back(docpp::HTML::HTMLElement("p", {}, "Test 3")); + + for (const docpp::HTML::HTMLElement& elem : sect) { + REQUIRE(elem.get() == "

Test 1

"); + break; + } + + for (docpp::HTML::HTMLSection::iterator it = ++sect.begin(); it != sect.end(); ++it) { + docpp::HTML::HTMLElement elem = *it; + REQUIRE(elem.get() == "

Test 2

"); + break; + } + }; + + const auto test22 = []() { + docpp::HTML::HTMLSection sect{}; + + sect.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1")); + sect.push_back(docpp::HTML::HTMLElement("p", {}, "Test 2")); + sect.push_back(docpp::HTML::HTMLElement("p", {}, "Test 3")); + + bool caught{false}; + try { + sect.at(1337); + } catch (const docpp::out_of_range& e) { + caught = true; + } + + REQUIRE(caught); + }; + std::vector tests{ test1, test2, @@ -337,6 +393,9 @@ SCENARIO("Test HTML", "[HTML]") { test17, test18, test19, + test20, + test21, + test22, }; for (const auto& test : tests) {