Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple html generation in C++ using initializer_list's
#include <iostream>
#include <vector>
using namespace std;
class Node {
public:
/// Constructor for text nodes
Node (const char *text)
: tag(NULL), text(text)
{}
/// Constructor for full-fledged tag with attributes and children
Node (const char *tag,
initializer_list<pair<const char *, const char *>> attrs,
initializer_list<Node> children)
: tag(tag), text(NULL), attrs(attrs), children(children)
{}
/// Construcotr for tag without attributes
Node (const char *tag,
initializer_list<Node> children)
: tag(tag), text(NULL), children(children)
{}
/// Render HTML to output stream (level is indentation level)
void render(uint level, ostream& os) const {
indent(level, os);
if (tag) {
os << "<" << tag;
// render attributes in key="value" form
for (auto& attr : attrs) {
os << " " << attr.first << "=\"" << attr.second << "\"";
}
// render children recursively
if (!children.empty()) {
os << ">" << endl;
for (auto& child : children) {
child.render(level + 1, os);
}
// render closing tag
indent(level, os);
os << "</" << tag << ">";
} else { // if there's no children just close the tag.
os << " />";
}
} else if (text) {
os << text;
}
os << endl;
}
protected:
void indent(uint level, ostream& os) const {
const uint spaces = level * 2;
for (uint i = 0; i < spaces; ++i) {
os << " ";
}
}
const char *tag;
const char *text;
vector<pair<const char *, const char *>> attrs;
vector<Node> children;
};
ostream& operator<< (ostream& out, const Node& node) {
node.render(0, out);
return out;
}
int main(int argc, char ** argv) {
Node html
{"html", {{"lang", "pl"}}, { // tag with attributes
{"head", { // tag without attributes
{"title", {
"Page Title" // instead of tag struct we can pass
// a string, it will become a text node.
}}
}},
{"body", {{"style", "background-color: #fff;"}}, {
{"h1", {"Page Title"}},
{"div", {}} // empty tag, has to have empty children list,
// otherwise it will be treated as text node.
}}
}};
cout << html;
return 0;
}
<html lang="pl">
<head>
<title>
Page Title
</title>
</head>
<body style="background-color: #fff;">
<h1>
Page Title
</h1>
<div />
</body>
</html>
CPP = g++
CCOPTS += -Wall -std=c++0x
PROGRAMS = $(patsubst %.cpp,%,$(wildcard *.cpp))
.PHONY: run clean
test : cpphtml run
run : cpphtml
./cpphtml > example-output.html && \
cat example-output.html
cpphtml : cpphtml.cpp
$(CPP) $(CCOPTS) $< -o $@
clean :
rm cpphtml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment