1354 lines
55 KiB
C++
1354 lines
55 KiB
C++
/*
|
|
* docpp - C++ library for generating XML, HTML and CSS.
|
|
*
|
|
* SPDX-License-Identifier: LGPL-3.0-or-later
|
|
* Copyright (c) 2024 speedie <speedie@speedie.site>
|
|
*/
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
#include <map>
|
|
#include <exception>
|
|
#include <utility>
|
|
#include <type_traits>
|
|
|
|
/**
|
|
* @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;
|
|
explicit 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;
|
|
explicit invalid_argument(const char* message) : message(message) {};
|
|
};
|
|
|
|
/**
|
|
* @brief A namespace to represent HTML elements and documents
|
|
*/
|
|
namespace HTML {
|
|
/**
|
|
* @brief Enum for element tags.
|
|
*/
|
|
enum Tag {
|
|
ELEMENT_EMPTY,
|
|
ELEMENT_ABBREVIATION,
|
|
ELEMENT_ABBR,
|
|
ELEMENT_ACRONYM,
|
|
ELEMENT_ADDRESS,
|
|
ELEMENT_ANCHOR,
|
|
ELEMENT_A,
|
|
ELEMENT_APPLET,
|
|
ELEMENT_ARTICLE,
|
|
ELEMENT_AREA,
|
|
ELEMENT_ASIDE,
|
|
ELEMENT_AUDIO,
|
|
ELEMENT_BASE,
|
|
ELEMENT_BASEFONT,
|
|
ELEMENT_BDI,
|
|
ELEMENT_BDO,
|
|
ELEMENT_BGSOUND,
|
|
ELEMENT_BIG,
|
|
ELEMENT_BLOCKQUOTE,
|
|
ELEMENT_BODY,
|
|
ELEMENT_BOLD,
|
|
ELEMENT_B,
|
|
ELEMENT_BR,
|
|
ELEMENT_BREAK,
|
|
ELEMENT_BUTTON,
|
|
ELEMENT_CAPTION,
|
|
ELEMENT_CANVAS,
|
|
ELEMENT_CENTER,
|
|
ELEMENT_CITE,
|
|
ELEMENT_CODE,
|
|
ELEMENT_COLGROUP,
|
|
ELEMENT_COL,
|
|
ELEMENT_COLUMN,
|
|
ELEMENT_DATA,
|
|
ELEMENT_DATALIST,
|
|
ELEMENT_DD,
|
|
ELEMENT_DFN,
|
|
ELEMENT_DEFINE,
|
|
ELEMENT_DELETE,
|
|
ELEMENT_DEL,
|
|
ELEMENT_DETAILS,
|
|
ELEMENT_DIALOG,
|
|
ELEMENT_DIR,
|
|
ELEMENT_DIV,
|
|
ELEMENT_DL,
|
|
ELEMENT_DT,
|
|
ELEMENT_EMBED,
|
|
ELEMENT_FIELDSET,
|
|
ELEMENT_FIGCAPTION,
|
|
ELEMENT_FIGURE,
|
|
ELEMENT_FONT,
|
|
ELEMENT_FOOTER,
|
|
ELEMENT_FORM,
|
|
ELEMENT_FRAME,
|
|
ELEMENT_FRAMESET,
|
|
ELEMENT_HEAD,
|
|
ELEMENT_HEADER,
|
|
ELEMENT_H1,
|
|
ELEMENT_H2,
|
|
ELEMENT_H3,
|
|
ELEMENT_H4,
|
|
ELEMENT_H5,
|
|
ELEMENT_H6,
|
|
ELEMENT_HGROUP,
|
|
ELEMENT_HR,
|
|
ELEMENT_HTML,
|
|
ELEMENT_IFRAME,
|
|
ELEMENT_IMAGE,
|
|
ELEMENT_IMG,
|
|
ELEMENT_INPUT,
|
|
ELEMENT_INS,
|
|
ELEMENT_ISINDEX,
|
|
ELEMENT_ITALIC,
|
|
ELEMENT_I,
|
|
ELEMENT_KBD,
|
|
ELEMENT_KEYGEN,
|
|
ELEMENT_LABEL,
|
|
ELEMENT_LEGEND,
|
|
ELEMENT_LIST,
|
|
ELEMENT_LI,
|
|
ELEMENT_LINK,
|
|
ELEMENT_MAIN,
|
|
ELEMENT_MARK,
|
|
ELEMENT_MARQUEE,
|
|
ELEMENT_MENUITEM,
|
|
ELEMENT_META,
|
|
ELEMENT_METER,
|
|
ELEMENT_NAV,
|
|
ELEMENT_NOBREAK,
|
|
ELEMENT_NOBR,
|
|
ELEMENT_NOEMBED,
|
|
ELEMENT_NOSCRIPT,
|
|
ELEMENT_OBJECT,
|
|
ELEMENT_OPTGROUP,
|
|
ELEMENT_OPTION,
|
|
ELEMENT_OUTPUT,
|
|
ELEMENT_PARAGRAPH,
|
|
ELEMENT_P,
|
|
ELEMENT_PARAM,
|
|
ELEMENT_PHRASE,
|
|
ELEMENT_PRE,
|
|
ELEMENT_PROGRESS,
|
|
ELEMENT_QUOTE,
|
|
ELEMENT_Q,
|
|
ELEMENT_RP,
|
|
ELEMENT_RT,
|
|
ELEMENT_RUBY,
|
|
ELEMENT_OUTDATED,
|
|
ELEMENT_S,
|
|
ELEMENT_SAMPLE,
|
|
ELEMENT_SAMP,
|
|
ELEMENT_SCRIPT,
|
|
ELEMENT_SECTION,
|
|
ELEMENT_SMALL,
|
|
ELEMENT_SOURCE,
|
|
ELEMENT_SPACER,
|
|
ELEMENT_SPAN,
|
|
ELEMENT_STRIKE,
|
|
ELEMENT_STRONG,
|
|
ELEMENT_STYLE,
|
|
ELEMENT_SUB,
|
|
ELEMENT_SUBSCRIPT,
|
|
ELEMENT_SUP,
|
|
ELEMENT_SUPERSCRIPT,
|
|
ELEMENT_SUMMARY,
|
|
ELEMENT_SVG,
|
|
ELEMENT_TABLE,
|
|
ELEMENT_TBODY,
|
|
ELEMENT_TD,
|
|
ELEMENT_TEMPLATE,
|
|
ELEMENT_TFOOT,
|
|
ELEMENT_TH,
|
|
ELEMENT_THEAD,
|
|
ELEMENT_TIME,
|
|
ELEMENT_TITLE,
|
|
ELEMENT_TR,
|
|
ELEMENT_TRACK,
|
|
ELEMENT_TT,
|
|
ELEMENT_UNDERLINE,
|
|
ELEMENT_U,
|
|
ELEMENT_VAR,
|
|
ELEMENT_VIDEO,
|
|
ELEMENT_WBR,
|
|
ELEMENT_XMP,
|
|
};
|
|
|
|
/**
|
|
* @brief Enum for element types.
|
|
*/
|
|
enum Type {
|
|
TYPE_SELF_CLOSING,
|
|
TYPE_NON_SELF_CLOSING,
|
|
TYPE_NON_CLOSED,
|
|
TYPE_TEXT,
|
|
TYPE_TEXT_TAB,
|
|
};
|
|
|
|
/**
|
|
* @brief Enum for formatting options.
|
|
*/
|
|
enum Formatting {
|
|
FORMATTING_NONE,
|
|
FORMATTING_PRETTY,
|
|
FORMATTING_NEWLINE,
|
|
};
|
|
|
|
/**
|
|
* @brief Resolve a tag to a string and type.
|
|
* @param tag The tag to resolve
|
|
* @return std::pair<std::string, Type> The resolved tag
|
|
*/
|
|
std::pair<std::string, Type> resolve_tag(const Tag tag);
|
|
|
|
/**
|
|
* @brief A class to represent an HTML property
|
|
*/
|
|
class Property {
|
|
private:
|
|
std::pair<std::string, std::string> property{};
|
|
protected:
|
|
public:
|
|
using size_type = std::size_t;
|
|
|
|
/**
|
|
* @brief The npos value
|
|
*/
|
|
static const size_type npos = -1;
|
|
|
|
/**
|
|
* @brief Construct a new Property object
|
|
* @param key The key of the property
|
|
* @param value The value of the property
|
|
*/
|
|
Property(const std::string& key, const std::string& value) : property(std::make_pair(key, value)) {};
|
|
/**
|
|
* @brief Construct a new Property object
|
|
* @param property The property to set
|
|
*/
|
|
explicit Property(const std::pair<std::string, std::string>& property) : property(property) {};
|
|
Property() = default;
|
|
|
|
/**
|
|
* @brief Get the key of the property
|
|
* @return std::string The key of the property
|
|
*/
|
|
std::string get_key() const;
|
|
/**
|
|
* @brief Get the key of the property in a specific type
|
|
* @return T The key of the property
|
|
*/
|
|
template <typename T> T get_key() const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->property.first;
|
|
}
|
|
|
|
return T(this->property.first);
|
|
};
|
|
/**
|
|
* @brief Get the value of the property
|
|
* @return std::string The value of the property
|
|
*/
|
|
std::string get_value() const;
|
|
/**
|
|
* @brief Get the value of the property in a specific type
|
|
* @return T The value of the property
|
|
*/
|
|
template <typename T> T get_value() const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->property.second;
|
|
}
|
|
return T(this->property.second);
|
|
}
|
|
/**
|
|
* @brief Get the property.
|
|
* @return std::pair<std::string, std::string> The value of the property
|
|
*/
|
|
std::pair<std::string, std::string> get() const;
|
|
/**
|
|
* @brief Get the property in a specific type.
|
|
* @return std::pair<T, T> The value of the property
|
|
*/
|
|
template <typename T> std::pair<T, T> get() const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->property;
|
|
}
|
|
|
|
return T(this->property);
|
|
}
|
|
/**
|
|
* @brief Set the key of the property.
|
|
* @param key The key.
|
|
*/
|
|
void set_key(const std::string& key);
|
|
/**
|
|
* @brief Set the value of the property.
|
|
* @param value The value.
|
|
*/
|
|
void set_value(const std::string& value);
|
|
/**
|
|
* @brief Set the property
|
|
* @param property The property.
|
|
*/
|
|
void set(const std::pair<std::string, std::string>& property);
|
|
};
|
|
|
|
/**
|
|
* @brief A class to represent the properties of an HTML element
|
|
*/
|
|
class Properties {
|
|
private:
|
|
std::vector<Property> properties{};
|
|
protected:
|
|
public:
|
|
using size_type = std::size_t;
|
|
using iterator = std::vector<Property>::iterator;
|
|
using const_iterator = std::vector<Property>::const_iterator;
|
|
using reverse_iterator = std::vector<Property>::reverse_iterator;
|
|
using const_reverse_iterator = std::vector<Property>::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
|
|
*/
|
|
static const size_type npos = -1;
|
|
|
|
/**
|
|
* @brief Get the properties of the element
|
|
* @return std::vector<Property> The properties of the element
|
|
*/
|
|
std::vector<Property> get_properties() const;
|
|
/**
|
|
* @brief Set the properties of the element
|
|
* @param properties The properties to set
|
|
*/
|
|
void set(const std::vector<Property>& properties);
|
|
/**
|
|
* @brief Get the property at an index
|
|
* @param index The index of the property
|
|
* @return Property The property at the index
|
|
*/
|
|
Property at(const size_type index) const;
|
|
/**
|
|
* @brief Insert a property into the element
|
|
* @param index The index to insert the property
|
|
* @param property The property to insert
|
|
*/
|
|
void insert(const size_type index, const Property& property);
|
|
/**
|
|
* @brief Erase a property from the element
|
|
* @param index The index of the property to erase
|
|
*/
|
|
void erase(const size_type index);
|
|
/**
|
|
* @brief Find a property in the element
|
|
* @param property The property to find
|
|
* @return size_type The index of the property
|
|
*/
|
|
size_type find(const Property& property);
|
|
/**
|
|
* @brief Find a property in the element
|
|
* @param str The property to find
|
|
* @return size_type The index of the property
|
|
*/
|
|
size_type find(const std::string& str);
|
|
/**
|
|
* @brief Swap two properties in the element
|
|
* @param index1 The index of the first property
|
|
* @param index2 The index of the second property
|
|
*/
|
|
void swap(const size_type index1, const size_type index2);
|
|
/**
|
|
* @brief Swap two properties in the element
|
|
* @param property1 The first property
|
|
* @param property2 The second property
|
|
*/
|
|
void swap(const Property& property1, const Property& property2);
|
|
/**
|
|
* @brief Get the first property of the element
|
|
* @return Property The first property of the element
|
|
*/
|
|
Property front() const;
|
|
/**
|
|
* @brief Get the last property of the element
|
|
* @return Property The last property of the element
|
|
*/
|
|
Property back() const;
|
|
/**
|
|
* @brief Get the size of the element
|
|
* @return size_type The size of the element
|
|
*/
|
|
size_type size() const;
|
|
/**
|
|
* @brief Prepend a property to the element
|
|
* @param property The property to add
|
|
*/
|
|
void push_front(const Property& property);
|
|
/**
|
|
* @brief Append a property to the element
|
|
* @param property The property to add
|
|
*/
|
|
void push_back(const Property& property);
|
|
/**
|
|
* @brief Construct a new Properties object
|
|
* @param properties The properties to set
|
|
*/
|
|
Properties(const std::vector<Property>& properties) : properties(properties) {};
|
|
/**
|
|
* @brief Construct a new Properties object
|
|
* @param property The property to add
|
|
*/
|
|
Properties(const Property& property) : properties({property}) {};
|
|
/**
|
|
* @brief Construct a new Properties object
|
|
*/
|
|
Properties() = default;
|
|
Properties operator=(const Properties& properties);
|
|
Properties operator=(const std::vector<Property>& properties);
|
|
Properties operator=(const Property& property);
|
|
void operator+=(const Property& property);
|
|
};
|
|
|
|
/**
|
|
* @brief A class to represent an HTML element
|
|
*/
|
|
class Element {
|
|
private:
|
|
std::string tag{};
|
|
std::string data{};
|
|
Type type{TYPE_NON_SELF_CLOSING};
|
|
Properties properties{};
|
|
protected:
|
|
public:
|
|
using size_type = std::size_t;
|
|
/**
|
|
* @brief The npos value
|
|
*/
|
|
static const size_type npos = -1;
|
|
|
|
/**
|
|
* @brief Construct a new Element object
|
|
* @param tag The tag of the element
|
|
* @param properties The properties of the element
|
|
* @param data The data of the element
|
|
* @param type The close tag type.
|
|
*/
|
|
Element(const std::string& tag, const Properties& properties = {}, const std::string& data = {}, const Type type = TYPE_NON_SELF_CLOSING) : tag(tag), properties(properties), data(data), type(type) {};
|
|
/**
|
|
* @brief Construct a new Element object
|
|
* @param tag The tag of the element
|
|
* @param properties The properties of the element
|
|
* @param data The data of the element
|
|
*/
|
|
Element(const Tag tag, const Properties& properties = {}, const std::string& data = {}) : tag(resolve_tag(tag).first), properties(properties), data(data), type(resolve_tag(tag).second) {};
|
|
/**
|
|
* @brief Construct a new Element object
|
|
*/
|
|
Element() = default;
|
|
/**
|
|
* @brief Set the tag, id, and classes of the element
|
|
* @param tag The tag of the element
|
|
* @param id The id of the element
|
|
* @param classes The classes of the element
|
|
*/
|
|
void set(const std::string& tag, const Properties& properties = {}, const std::string& data = {}, const Type = TYPE_NON_SELF_CLOSING);
|
|
|
|
/**
|
|
* @brief Get the element in the form of an HTML tag.
|
|
* @return std::string The tag of the element
|
|
*/
|
|
std::string get(const Formatting formatting = FORMATTING_NONE, const int tabc = 0) const;
|
|
/**
|
|
* @brief Get the element in the form of a specific type.
|
|
* @return T The element in the form of a specific type
|
|
*/
|
|
template <typename T> T get(const Formatting formatting = FORMATTING_NONE, const int tabc = 0) const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->get(formatting, tabc);
|
|
}
|
|
return T(this->get(formatting, tabc));
|
|
}
|
|
|
|
/**
|
|
* @brief Get the tag of the element
|
|
* @return std::string The data of the element
|
|
*/
|
|
std::string get_tag() const;
|
|
/**
|
|
* @brief Get the tag of the element in a specific type
|
|
* @return T The tag of the element
|
|
*/
|
|
template <typename T> T get_tag() const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->tag;
|
|
}
|
|
return T(this->tag);
|
|
}
|
|
|
|
/**
|
|
* @brief Get the data of the element
|
|
* @return std::string The data of the element
|
|
*/
|
|
std::string get_data() const;
|
|
/**
|
|
* @brief Get the data of the element in a specific type
|
|
* @return T The data of the element
|
|
*/
|
|
template <typename T> T get_data() const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->data;
|
|
}
|
|
return T(this->data);
|
|
}
|
|
|
|
Element operator=(const Element& element);
|
|
void operator+=(const std::string& data);
|
|
};
|
|
|
|
/**
|
|
* @brief A class to represent an HTML section (head, body, etc.)
|
|
*/
|
|
class Section {
|
|
protected:
|
|
public:
|
|
using size_type = std::size_t;
|
|
|
|
/**
|
|
* @brief A class to represent an iterator for the Section class
|
|
*/
|
|
template <typename T>
|
|
class sect_iterator {
|
|
private:
|
|
T element{};
|
|
public:
|
|
sect_iterator(const T& element) : element(element) {}
|
|
sect_iterator operator++() { return ++element; }
|
|
Element 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<std::map<int, Element>::iterator>;
|
|
using const_iterator = sect_iterator<std::map<int, Element>::const_iterator>;
|
|
using reverse_iterator = sect_iterator<std::map<int, Element>::reverse_iterator>;
|
|
using const_reverse_iterator = sect_iterator<std::map<int, Element>::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
|
|
*/
|
|
static const size_type npos = -1;
|
|
|
|
/**
|
|
* @brief Prepend an element to the section
|
|
* @param element The element to add
|
|
*/
|
|
void push_front(const Element& element);
|
|
/**
|
|
* @brief Prepend a section to the section
|
|
* @param section The section to add
|
|
*/
|
|
void push_front(const Section& section);
|
|
/**
|
|
* @brief Append an element to the section
|
|
* @param element The element to add
|
|
*/
|
|
void push_back(const Element& element);
|
|
/**
|
|
* @brief Append a section to the section
|
|
* @param section The section to add
|
|
*/
|
|
void push_back(const Section& section);
|
|
/**
|
|
* @brief Get the element at an index. To get a section, use at_section()
|
|
* @param index The index of the element
|
|
* @return Element The element at the index
|
|
*/
|
|
Element at(const size_type index) const;
|
|
/**
|
|
* @brief Get the section at an index. To get an element, use at()
|
|
* @param index The index of the section
|
|
* @return Section The section at the index
|
|
*/
|
|
Section at_section(const size_type index) const;
|
|
/**
|
|
* @brief Erase an element from the section. Note that this will NOT change the size/index.
|
|
* @param index The index of the element to erase
|
|
*/
|
|
void erase(const size_type index);
|
|
/**
|
|
* @brief Erase a section from the section, by reading from a section. The section will be erased if it's identical to section. Note that this will NOT change the size/index.
|
|
* @param section The section to erase
|
|
*/
|
|
void erase(const Section& section);
|
|
/**
|
|
* @brief Erase an element from the section, by reading from an element. The element will be erased if it's identical to element. Note that this will NOT change the size/index.
|
|
* @param element The element to erase
|
|
*/
|
|
void erase(const Element& element);
|
|
/**
|
|
* @brief Find an element in the section
|
|
* @param element The element to find
|
|
* @return size_type The index of the element
|
|
*/
|
|
size_type find(const Element& element);
|
|
/**
|
|
* @brief Find a section in the section
|
|
* @param section The section to find
|
|
* @return size_type The index of the section
|
|
*/
|
|
size_type find(const Section& section);
|
|
/**
|
|
* @brief Find an element or section in the section
|
|
* @param str The element or section to find
|
|
* @return size_type The index of the element or section
|
|
*/
|
|
size_type find(const std::string& str);
|
|
/**
|
|
* @brief Insert an element into the section
|
|
* @param index The index to insert the element
|
|
* @param element The element to insert
|
|
*/
|
|
void insert(const size_type index, const Element& element);
|
|
/**
|
|
* @brief Insert a section into the section
|
|
* @param index The index to insert the section
|
|
* @param section The section to insert
|
|
*/
|
|
void insert(const size_type index, const Section& section);
|
|
/**
|
|
* @brief Get the first element of the section
|
|
* @return Element The first element of the section
|
|
*/
|
|
Element front() const;
|
|
/**
|
|
* @brief Get the last element of the section
|
|
* @return Element The last element of the section
|
|
*/
|
|
Element back() const;
|
|
/**
|
|
* @brief Get the first section of the section
|
|
* @return Section The first section of the section
|
|
*/
|
|
Section front_section() const;
|
|
/**
|
|
* @brief Get the last section of the section
|
|
* @return Section The last section of the section
|
|
*/
|
|
Section back_section() const;
|
|
/**
|
|
* @brief Get the size of the section
|
|
* @return size_type The size of the section
|
|
*/
|
|
size_type size() const;
|
|
|
|
/**
|
|
* @brief Construct a new Section object
|
|
* @param tag The tag of the section
|
|
* @param properties The properties of the section
|
|
*/
|
|
Section(const std::string& tag, const Properties& properties = {}) : tag(tag), properties(properties) {};
|
|
/**
|
|
* @brief Construct a new Section object
|
|
* @param tag The tag of the section
|
|
* @param properties The properties of the section
|
|
*/
|
|
Section(const Tag tag, const Properties& properties = {}) : tag(resolve_tag(tag).first), properties(properties) {};
|
|
/**
|
|
* @brief Construct a new Section object
|
|
*/
|
|
Section() = default;
|
|
/**
|
|
* @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 std::string& tag, const Properties& 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 Tag tag, const Properties& properties = {});
|
|
/**
|
|
* @brief Swap two elements in the section
|
|
* @param index1 The index of the first element
|
|
* @param index2 The index of the second element
|
|
*/
|
|
void swap(const size_type index1, const size_type index2);
|
|
/**
|
|
* @brief Swap two elements in the section
|
|
* @param element1 The first element
|
|
* @param element2 The second element
|
|
*/
|
|
void swap(const Element& element1, const Element& element2);
|
|
/**
|
|
* @brief Swap two sections in the section
|
|
* @param index1 The index of the first section
|
|
* @param index2 The index of the second section
|
|
*/
|
|
void swap(const Section& section1, const Section& section2);
|
|
/**
|
|
* @brief Get the elements of the section
|
|
* @return std::vector<Element> The elements of the section
|
|
*/
|
|
std::vector<Element> get_elements() const;
|
|
/**
|
|
* @brief Get the sections of the section
|
|
* @return std::vector<Section> The sections of the section
|
|
*/
|
|
std::vector<Section> get_sections() const;
|
|
|
|
/**
|
|
* @brief Dump the entire section.
|
|
* @return std::string The section
|
|
*/
|
|
std::string get(const Formatting formatting = FORMATTING_NONE, const int tabc = 0) const;
|
|
/**
|
|
* @brief Get the element in the form of a specific type.
|
|
* @return T The element in the form of a specific type
|
|
*/
|
|
template <typename T> T get(const Formatting formatting = FORMATTING_NONE, const int tabc = 0) const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->get(formatting, tabc);
|
|
}
|
|
return T(this->get(formatting, tabc));
|
|
}
|
|
|
|
Section operator=(const Section& section);
|
|
void operator+=(const Element& element);
|
|
void operator+=(const Section& section);
|
|
Element operator[](const int& index) const;
|
|
private:
|
|
size_type index{};
|
|
std::string tag{};
|
|
Properties properties{};
|
|
|
|
std::map<int, Element> elements{};
|
|
std::unordered_map<int, Section> sections{};
|
|
};
|
|
|
|
/**
|
|
* @brief A class to represent an HTML document
|
|
*/
|
|
class Document {
|
|
private:
|
|
std::string doctype{"<!DOCTYPE html>"};
|
|
Section document{};
|
|
protected:
|
|
public:
|
|
using size_type = std::size_t;
|
|
|
|
/**
|
|
* @brief The npos value
|
|
*/
|
|
static const size_type npos = -1;
|
|
|
|
/**
|
|
* @brief Get the document
|
|
* @param std::string The type to return
|
|
* @return std::string The document
|
|
*/
|
|
std::string get(const Formatting formatting = FORMATTING_NONE, const int tabc = 0) const;
|
|
/**
|
|
* @brief Get the document in the form of a specific type.
|
|
* @return T The document in the form of a specific type
|
|
*/
|
|
template <typename T> T get(const Formatting formatting = FORMATTING_NONE, const int tabc = 0) const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->get(formatting, tabc);
|
|
}
|
|
return T(this->get(formatting, tabc));
|
|
}
|
|
|
|
/**
|
|
* @brief Get the section
|
|
* @return Section The section
|
|
*/
|
|
Section& get_section();
|
|
|
|
/**
|
|
* @brief Get the doctype of the document
|
|
* @return std::string The doctype of the document
|
|
*/
|
|
std::string get_doctype() const;
|
|
/**
|
|
* @brief Get the doctype of the document in a specific type
|
|
* @return T The doctype of the document
|
|
*/
|
|
template <typename T> T get_doctype() const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->doctype;
|
|
}
|
|
return T(this->doctype);
|
|
}
|
|
|
|
/**
|
|
* @brief Set the document
|
|
* @param document The document to set
|
|
*/
|
|
void set(const Section& document);
|
|
/**
|
|
* @brief Set the doctype of the document
|
|
* @param doctype The doctype to set
|
|
*/
|
|
void set_doctype(const std::string& doctype);
|
|
/**
|
|
* @brief Construct a new Document object
|
|
*/
|
|
Document() = default;
|
|
/**
|
|
* @brief Construct a new Document object
|
|
* @param document The document to set
|
|
*/
|
|
Document(const Section& document, const std::string& doctype = "<!DOCTYPE html>") : document(document), doctype(doctype) {};
|
|
|
|
Document operator=(const Document& document);
|
|
Document operator=(const Section& section);
|
|
};
|
|
} // namespace HTML
|
|
|
|
/**
|
|
* @brief A namespace to represent CSS elements and documents
|
|
*/
|
|
namespace CSS {
|
|
/**
|
|
* @brief Enum for formatting options.
|
|
*/
|
|
enum Formatting {
|
|
FORMATTING_NONE,
|
|
FORMATTING_PRETTY,
|
|
FORMATTING_NEWLINE,
|
|
};
|
|
|
|
/**
|
|
* @brief A class to represent a CSS property
|
|
*/
|
|
class Property {
|
|
private:
|
|
std::pair<std::string, std::string> property{};
|
|
protected:
|
|
public:
|
|
using size_type = std::size_t;
|
|
/**
|
|
* @brief The npos value
|
|
*/
|
|
static const size_type npos = -1;
|
|
|
|
/**
|
|
* @brief Construct a new Property object
|
|
* @param key The key of the property
|
|
* @param value The value of the property
|
|
*/
|
|
Property(const std::string& key, const std::string& value) : property(std::make_pair(key, value)) {};
|
|
/**
|
|
* @brief Construct a new Property object
|
|
* @param property The property to set
|
|
*/
|
|
explicit Property(const std::pair<std::string, std::string>& property) : property(property) {};
|
|
Property() = default;
|
|
|
|
/**
|
|
* @brief Get the key of the property
|
|
* @return std::string The key of the property
|
|
*/
|
|
std::string get_key() const;
|
|
/**
|
|
* @brief Get the key of the property in a specific type
|
|
* @return T The key of the property
|
|
*/
|
|
template <typename T> T get_key() const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->property.first;
|
|
}
|
|
return T(this->property.first);
|
|
}
|
|
/**
|
|
* @brief Get the value of the property
|
|
* @return std::string The value of the property
|
|
*/
|
|
std::string get_value() const;
|
|
/**
|
|
* @brief Get the value of the property in a specific type
|
|
* @return T The value of the property
|
|
*/
|
|
template <typename T> T get_value() const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->property.second;
|
|
}
|
|
return T(this->property.second);
|
|
}
|
|
/**
|
|
* @brief Get the property.
|
|
* @return std::pair<std::string, std::string> The value of the property
|
|
*/
|
|
std::pair<std::string, std::string> get() const;
|
|
/**
|
|
* @brief Get the property in a specific type.
|
|
* @return std::pair<T, T> The value of the property
|
|
*/
|
|
template <typename T> std::pair<T, T> get() const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return std::make_pair(this->property.first, this->property.second);
|
|
}
|
|
return std::pair<T, T>(this->property.first, this->property.second);
|
|
}
|
|
/**
|
|
* @brief Set the key of the property.
|
|
* @param key The key.
|
|
*/
|
|
void set_key(const std::string& key);
|
|
/**
|
|
* @brief Set the value of the property.
|
|
* @param value The value.
|
|
*/
|
|
void set_value(const std::string& value);
|
|
/**
|
|
* @brief Set the property
|
|
* @param property The property.
|
|
*/
|
|
void set(const std::pair<std::string, std::string>& property);
|
|
/**
|
|
* @brief Set the property
|
|
* @param key The key of the property
|
|
* @param value The value of the property
|
|
*/
|
|
void set(const std::string& key, const std::string& value);
|
|
|
|
Property operator=(const Property& property);
|
|
Property operator=(const std::pair<std::string, std::string>& property);
|
|
};
|
|
|
|
/**
|
|
* @brief A class to represent the properties of a CSS element
|
|
*/
|
|
class Element {
|
|
private:
|
|
std::pair<std::string, std::vector<Property>> element{};
|
|
protected:
|
|
public:
|
|
using size_type = std::size_t;
|
|
using iterator = std::vector<Property>::iterator;
|
|
using const_iterator = std::vector<Property>::const_iterator;
|
|
using reverse_iterator = std::vector<Property>::reverse_iterator;
|
|
using const_reverse_iterator = std::vector<Property>::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
|
|
*/
|
|
static const size_type npos = -1;
|
|
|
|
/**
|
|
* @brief Construct a new Element object
|
|
* @param tag The tag of the element
|
|
* @param properties The properties of the element
|
|
*/
|
|
Element(const std::string& tag, const std::vector<Property>& properties) : element(std::make_pair(tag, properties)) {};
|
|
/**
|
|
* @brief Construct a new Element object
|
|
* @param element The element to set
|
|
*/
|
|
explicit Element(const std::pair<std::string, std::vector<Property>>& element) : element(element) {};
|
|
Element() = default;
|
|
|
|
/**
|
|
* @brief Prepend a property to the element
|
|
* @param property The property to push
|
|
*/
|
|
void push_front(const Property& property);
|
|
/**
|
|
* @brief Append a property to the element
|
|
* @param property The property to push
|
|
*/
|
|
void push_back(const Property& property);
|
|
/**
|
|
* @brief Insert a property into the element
|
|
* @param index The index to insert the property
|
|
* @param property The property to insert
|
|
*/
|
|
void insert(const size_type index, const Property& property);
|
|
/**
|
|
* @brief Erase a property from the element
|
|
* @param index The index of the property to erase
|
|
*/
|
|
void erase(const size_type index);
|
|
/**
|
|
* @brief Find a property in the element
|
|
* @param property The property to find
|
|
* @return size_type The index of the property
|
|
*/
|
|
size_type find(const Property& property);
|
|
/**
|
|
* @brief Get the property at an index
|
|
* @param index The index of the property
|
|
* @return Property The property at the index
|
|
*/
|
|
Property at(const size_type index) const;
|
|
/**
|
|
* @brief Find a property in the element
|
|
* @param str The property to find
|
|
* @return size_type The index of the property
|
|
*/
|
|
size_type find(const std::string& str);
|
|
/**
|
|
* @brief Swap two properties in the element
|
|
* @param index1 The index of the first property
|
|
* @param index2 The index of the second property
|
|
*/
|
|
void swap(const size_type index1, const size_type index2);
|
|
/**
|
|
* @brief Swap two properties in the element
|
|
* @param property1 The first property
|
|
* @param property2 The second property
|
|
*/
|
|
void swap(const Property& property1, const Property& property2);
|
|
/**
|
|
* @brief Get the first property of the element
|
|
* @return Property The first property of the element
|
|
*/
|
|
Property front() const;
|
|
/**
|
|
* @brief Get the last property of the element
|
|
* @return Property The last property of the element
|
|
*/
|
|
Property back() const;
|
|
/**
|
|
* @brief Get the size of the element
|
|
* @return size_type The size of the element
|
|
*/
|
|
size_type size() const;
|
|
/**
|
|
* @brief Set the properties of the element
|
|
* @param properties The properties to set
|
|
*/
|
|
void set(const std::string& tag, const std::vector<Property>& properties);
|
|
/**
|
|
* @brief Set the properties of the element
|
|
* @param element The element to set
|
|
*/
|
|
void set(const std::pair<std::string, std::vector<Property>>& element);
|
|
/**
|
|
* @brief Get the element
|
|
* @return std::pair<std::string, std::vector<Property>> The element
|
|
*/
|
|
std::string get(const Formatting formatting = FORMATTING_NONE, const int tabc = 0) const;
|
|
/**
|
|
* @brief Get the element in the form of a specific type.
|
|
* @return T The element in the form of a specific type
|
|
*/
|
|
template <typename T> T get(const Formatting formatting = FORMATTING_NONE, const int tabc = 0) const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->get(formatting, tabc);
|
|
}
|
|
return T(this->get(formatting, tabc));
|
|
}
|
|
/**
|
|
* @brief Get the tag of the element
|
|
* @return std::string The tag of the element
|
|
*/
|
|
std::string get_tag() const;
|
|
/**
|
|
* @brief Get the tag of the element in a specific type
|
|
* @return T The tag of the element
|
|
*/
|
|
template <typename T> T get_tag() const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->element.first;
|
|
}
|
|
return T(this->element.first);
|
|
}
|
|
/**
|
|
* @brief Get the properties of the element
|
|
* @return std::vector<Property> The properties of the element
|
|
*/
|
|
std::vector<Property> get_properties() const;
|
|
|
|
Element operator=(const Element& element);
|
|
Element operator=(const std::pair<std::string, std::vector<Property>>& element);
|
|
void operator+=(const Property& property);
|
|
Property operator[](const int& index) const;
|
|
};
|
|
|
|
/**
|
|
* @brief A class to represent a CSS stylesheet
|
|
*/
|
|
class Stylesheet {
|
|
private:
|
|
std::vector<Element> elements{};
|
|
protected:
|
|
public:
|
|
using size_type = std::size_t;
|
|
using iterator = std::vector<Element>::iterator;
|
|
using const_iterator = std::vector<Element>::const_iterator;
|
|
using reverse_iterator = std::vector<Element>::reverse_iterator;
|
|
using const_reverse_iterator = std::vector<Element>::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
|
|
*/
|
|
static const size_type npos = -1;
|
|
|
|
/**
|
|
* @brief Construct a new Stylesheet object
|
|
* @param elements The elements to set
|
|
*/
|
|
explicit Stylesheet(const std::vector<Element>& elements) : elements(elements) {};
|
|
Stylesheet() = default;
|
|
|
|
/**
|
|
* @brief Prepend an element to the stylesheet
|
|
* @param element The element to add
|
|
*/
|
|
void push_front(const Element& element);
|
|
/**
|
|
* @brief Append an element to the stylesheet
|
|
* @param element The element to add
|
|
*/
|
|
void push_back(const Element& element);
|
|
/**
|
|
* @brief Insert an element into the stylesheet
|
|
* @param index The index to insert the element
|
|
* @param element The element to insert
|
|
*/
|
|
void insert(const size_type index, const Element& element);
|
|
/**
|
|
* @brief Erase an element from the stylesheet. Note that this will NOT change the size/index.
|
|
* @param index The index of the element to erase
|
|
*/
|
|
void erase(const size_type index);
|
|
/**
|
|
* @brief Find an element in the stylesheet
|
|
* @param element The element to find
|
|
* @return size_type The index of the element
|
|
*/
|
|
size_type find(const Element& element);
|
|
/**
|
|
* @brief Find an element in the stylesheet
|
|
* @param str The element to find, either the tag or the stylesheet itself
|
|
* @return size_type The index of the element
|
|
*/
|
|
size_type find(const std::string& str);
|
|
/**
|
|
* @brief Get the element at an index
|
|
* @param index The index of the element
|
|
* @return Element The element at the index
|
|
*/
|
|
Element at(const size_type index) const;
|
|
/**
|
|
* @brief Get the size of the stylesheet
|
|
* @return size_type The size of the stylesheet
|
|
*/
|
|
size_type size() const;
|
|
/**
|
|
* @brief Get the first element of the stylesheet
|
|
* @return Element The first element of the stylesheet
|
|
*/
|
|
Element front() const;
|
|
/**
|
|
* @brief Get the last element of the stylesheet
|
|
* @return Element The last element of the stylesheet
|
|
*/
|
|
Element back() const;
|
|
/**
|
|
* @brief Swap two elements in the stylesheet
|
|
* @param index1 The index of the first element
|
|
* @param index2 The index of the second element
|
|
*/
|
|
void swap(const size_type index1, const size_type index2);
|
|
/**
|
|
* @brief Swap two elements in the stylesheet
|
|
* @param element1 The first element
|
|
* @param element2 The second element
|
|
*/
|
|
void swap(const Element& element1, const Element& element2);
|
|
/**
|
|
* @brief Set the elements of the stylesheet
|
|
* @param elements The elements to set
|
|
*/
|
|
void set(const std::vector<Element>& elements);
|
|
/**
|
|
* @brief Get the elements of the stylesheet
|
|
* @return std::vector<Element> The elements of the stylesheet
|
|
*/
|
|
std::vector<Element> get_elements() const;
|
|
/**
|
|
* @brief Get the stylesheet
|
|
* @return std::string The stylesheet
|
|
*/
|
|
std::string get(const Formatting formatting = FORMATTING_NONE, const int tabc = 0) const;
|
|
/**
|
|
* @brief Get the stylesheet in the form of a specific type.
|
|
* @return T The stylesheet in the form of a specific type
|
|
*/
|
|
template <typename T> T get(const Formatting formatting = FORMATTING_NONE, const int tabc = 0) const {
|
|
if (std::is_same<T, std::string>::value) {
|
|
return this->get(formatting, tabc);
|
|
}
|
|
return T(this->get(formatting, tabc));
|
|
}
|
|
|
|
Stylesheet operator=(const Stylesheet& stylesheet);
|
|
void operator+=(const Element& element);
|
|
Element operator[](const int& index) const;
|
|
};
|
|
} // namespace CSS
|
|
} // namespace docpp
|