Implement support for plain text elements and sections without a tag.

Also, add example replica of biteme.lol.
This commit is contained in:
Jacob 2024-05-07 21:21:58 +02:00
parent 21ddd1d82c
commit 43daa77f6d
6 changed files with 130 additions and 32 deletions

2
examples/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
a.out
*.html

69
examples/biteme.lol.cpp Normal file
View file

@ -0,0 +1,69 @@
/**
* @file biteme.lol.cpp
* @brief A simple program that replicates biteme.lol using docpp.
* @details This program creates a simple HTML document that replicates the biteme.lol website.
* @see https://biteme.lol
* @license LGPL-3.0
*
* g++ -std=c++11 biteme.lol.cpp -o biteme.lol -ldocpp
*/
#include <fstream>
#include <docpp/docpp.hpp>
int main() {
docpp::HTML::HTMLSection html(docpp::HTML::SECTION_HTML, {});
html.push_back({"title", {}, "Google"});
docpp::CSS::CSSStylesheet sheet{};
sheet.push_back(docpp::CSS::CSSElement(
".center", {
{"display", "flex"},
{"flex-wrap", "wrap"},
{"justify-content", "center"},
{"align-items", "center"},
{"font-size", "10vw"},
{"height", "10vw"},
{"padding", "10vw"},
}
));
sheet.push_back(docpp::CSS::CSSElement(
"input[type=text], select", {
{"width", "50vw"},
}
));
html.push_back({"style", {}, sheet.get(docpp::CSS::FORMATTING_PRETTY)});
docpp::HTML::HTMLSection div{docpp::HTML::SECTION_DIV, {docpp::HTML::HTMLProperty("class", "center")}};
div.push_back({"font", {docpp::HTML::HTMLProperty("color", "blue")}, "G"});
div.push_back({"font", {docpp::HTML::HTMLProperty("color", "red")}, "o"});
div.push_back({"font", {docpp::HTML::HTMLProperty("color", "yellow")}, "o"});
div.push_back({"font", {docpp::HTML::HTMLProperty("color", "blue")}, "g"});
div.push_back({"font", {docpp::HTML::HTMLProperty("color", "green")}, "l"});
div.push_back({"font", {docpp::HTML::HTMLProperty("color", "red")}, "e"});
html.push_back(div);
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});
div2.push_back(form);
html.push_back(div2);
docpp::HTML::HTMLDocument doc{html};
std::ofstream file("biteme.lol.html");
file << doc.get(docpp::HTML::FORMATTING_PRETTY);
file.close();
return 0;
}

View file

@ -1,5 +1,11 @@
// Compile with: g++ hello-world.cpp -o hello-world -ldocpp
#include <iostream>
/**
* @file hello-world.cpp
* @brief A simple Hello World program, demonstrating the use of docpp.
* @details This program creates a simple HTML document with a title, a meta description, a body with a div containing a header and a paragraph, and a footer with a paragraph. It also includes a CSS stylesheet that sets the background color of the body to black and the text color to white. It then writes the document to a file called hello-world.html.
* @license LGPL-3.0
*
* g++ -std=c++11 hello-world.cpp -o hello-world -ldocpp
*/
#include <fstream>
#include <docpp/docpp.hpp>
@ -78,7 +84,7 @@ int main() {
stylesheet.push_back(bodyStyling);
/* To get the stylesheet as an std::string object, call stylesheet.get(). It can then be used in an HTMLElement object. */
const std::string& css = stylesheet.get(); // body { background-color: black; color: white; }
const std::string& css = stylesheet.get(docpp::CSS::FORMATTING_PRETTY); // body { background-color: black; color: white; }
headSection.push_back(docpp::HTML::HTMLElement("style", {}, css)); // <style>body { background-color: black; color: white; }</style>
@ -114,8 +120,6 @@ int main() {
file.close();
std::cout << doc.get() << "\n";
/* And we're done! */
return 0;

View file

@ -23,6 +23,7 @@
namespace docpp {
namespace HTML {
enum {
SECTION_EMPTY,
SECTION_HTML,
SECTION_HEAD,
SECTION_BODY,
@ -31,6 +32,8 @@ namespace docpp {
TYPE_SELF_CLOSING,
TYPE_NON_SELF_CLOSING,
TYPE_NON_CLOSED,
TYPE_TEXT,
TYPE_TEXT_TAB,
FORMATTING_NONE,
FORMATTING_PRETTY,
FORMATTING_NEWLINE,

View file

@ -187,6 +187,16 @@ void docpp::HTML::HTMLElement::set(const std::string& tag, const HTMLElementProp
std::string docpp::HTML::HTMLElement::get(const int formatting, const int tabc) const {
std::string ret{};
if (this->type == docpp::HTML::TYPE_TEXT) {
return this->data;
} else if (this->type == docpp::HTML::TYPE_TEXT_TAB) {
for (int i{0}; i < tabc; i++) {
ret += "\t";
}
return ret + this->data;
}
if (formatting == docpp::HTML::FORMATTING_PRETTY) {
for (int i{0}; i < tabc; i++) {
ret += "\t";
@ -255,19 +265,7 @@ docpp::HTML::HTMLElement docpp::HTML::HTMLSection::operator[](const int& index)
}
docpp::HTML::HTMLSection::HTMLSection(const int tag, const HTMLElementProperties& properties) {
if (tag == docpp::HTML::SECTION_DIV) {
this->tag = "div";
} else if (tag == docpp::HTML::SECTION_BODY) {
this->tag = "body";
} else if (tag == docpp::HTML::SECTION_FOOTER) {
this->tag = "footer";
} else if (tag == docpp::HTML::SECTION_HEAD) {
this->tag = "head";
} else if (tag == docpp::HTML::SECTION_HTML) {
this->tag = "html";
}
this->properties = properties;
this->set(tag, properties);
}
void docpp::HTML::HTMLSection::set(const std::string& tag, const HTMLElementProperties& properties) {
@ -464,33 +462,44 @@ std::vector<docpp::HTML::HTMLSection> docpp::HTML::HTMLSection::getHTMLSections(
std::string docpp::HTML::HTMLSection::get(const int formatting, const int tabc) const {
std::string ret{};
int tabcount{tabc};
if (!this->tag.compare("")) {
--tabcount; // i guess this means the section only contains elements and sections, and isn't a tag itself
if (tabcount < -1) {
tabcount = -1; // will be incremented by 1, so it will be 0
}
}
if (formatting == docpp::HTML::FORMATTING_PRETTY) {
for (int i{0}; i < tabc; i++) {
for (int i{0}; i < tabcount; i++) {
ret += "\t";
}
}
ret += "<" + this->tag;
if (this->tag.compare("")) {
ret += "<" + this->tag;
for (const auto& it : this->properties.getProperties()) {
if (!it.getKey().compare("")) continue;
if (!it.getValue().compare("")) continue;
for (const auto& it : this->properties.getProperties()) {
if (!it.getKey().compare("")) continue;
if (!it.getValue().compare("")) continue;
ret += " " + it.getKey() + "=\"" + it.getValue() + "\"";
}
ret += " " + it.getKey() + "=\"" + it.getValue() + "\"";
}
ret += ">";
ret += ">";
if (formatting == docpp::HTML::FORMATTING_PRETTY || formatting == docpp::HTML::FORMATTING_NEWLINE) {
ret += "\n";
if (formatting == docpp::HTML::FORMATTING_PRETTY || formatting == docpp::HTML::FORMATTING_NEWLINE) {
ret += "\n";
}
}
for (int i{0}; i < this->index; i++) {
if (this->elements.find(i) != this->elements.end()) {
ret += this->elements.at(i).get(formatting, tabc + 1);
ret += this->elements.at(i).get(formatting, tabcount + 1);
} else if (this->sections.find(i) != this->sections.end()) {
ret += this->sections.at(i).get(formatting, tabc + 1);
ret += this->sections.at(i).get(formatting, tabcount + 1);
if (formatting == docpp::HTML::FORMATTING_PRETTY || formatting == docpp::HTML::FORMATTING_NEWLINE) {
ret += "\n";
@ -499,12 +508,12 @@ std::string docpp::HTML::HTMLSection::get(const int formatting, const int tabc)
}
if (formatting == docpp::HTML::FORMATTING_PRETTY) {
for (int i{0}; i < tabc; i++) {
for (int i{0}; i < tabcount; i++) {
ret += "\t";
}
}
ret += "</" + this->tag + ">";
ret += this->tag.compare("") ? ("</" + this->tag + ">") : "";
return std::move(ret);
}

View file

@ -296,6 +296,16 @@ SCENARIO("Test HTML", "[HTML]") {
REQUIRE(doc.get(docpp::HTML::FORMATTING_PRETTY) == "<!DOCTYPE html>\n<html>\n\t<p>Test 1</p>\n\t<p>Test 2</p>\n\t<p>Test 3</p>\n</html>");
};
auto test18 = []() {
docpp::HTML::HTMLSection section = docpp::HTML::HTMLSection(docpp::HTML::SECTION_EMPTY, {});
section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 1"));
section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 2"));
section.push_back(docpp::HTML::HTMLElement("p", {}, "Test 3"));
REQUIRE(section.get() == "<p>Test 1</p><p>Test 2</p><p>Test 3</p>");
};
std::vector<void (*)()> tests{
test1,
test2,
@ -314,6 +324,7 @@ SCENARIO("Test HTML", "[HTML]") {
test15,
test16,
test17,
test18,
};
for (const auto& test : tests) {