FEATURE: Node implementations #17
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
/build
|
||||
/build/*
|
||||
parser
|
||||
/.vscode
|
||||
|
||||
65
.vscode/settings.json
vendored
65
.vscode/settings.json
vendored
@ -1,65 +0,0 @@
|
||||
{
|
||||
"C_Cpp.errorSquiggles": "disabled",
|
||||
"files.associations": {
|
||||
"filesystem": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"cctype": "cpp",
|
||||
"charconv": "cpp",
|
||||
"chrono": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"deque": "cpp",
|
||||
"exception": "cpp",
|
||||
"format": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"ios": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"iterator": "cpp",
|
||||
"limits": "cpp",
|
||||
"locale": "cpp",
|
||||
"memory": "cpp",
|
||||
"new": "cpp",
|
||||
"optional": "cpp",
|
||||
"ostream": "cpp",
|
||||
"ratio": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stack": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"string": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"utility": "cpp",
|
||||
"vector": "cpp",
|
||||
"xfacet": "cpp",
|
||||
"xiosbase": "cpp",
|
||||
"xlocale": "cpp",
|
||||
"xlocbuf": "cpp",
|
||||
"xlocinfo": "cpp",
|
||||
"xlocmes": "cpp",
|
||||
"xlocmon": "cpp",
|
||||
"xlocnum": "cpp",
|
||||
"xloctime": "cpp",
|
||||
"xmemory": "cpp",
|
||||
"xstring": "cpp",
|
||||
"xtr1common": "cpp",
|
||||
"xutility": "cpp"
|
||||
}
|
||||
}
|
||||
3
Makefile
3
Makefile
@ -41,9 +41,6 @@ $(BUILD_DIR)/%.o: $(LIB_DIR)/%.cpp
|
||||
|
||||
test: all
|
||||
./$(TARGET)
|
||||
./$(TARGET) ' '
|
||||
./$(TARGET) ./test/input.md
|
||||
./$(TARGET) ./test/input.md ./test/output.html
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR) $(TARGET)
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
#ifndef INLINENODE_H
|
||||
#define INLINENODE_H
|
||||
|
||||
#include "node.h"
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @brief InlineNode class.
|
||||
*
|
||||
* Inherits from Node. Represents an inline object that is used
|
||||
* by the DOM tree to convert inline tags from a markup file
|
||||
* to an HTML file.
|
||||
*
|
||||
* @author Preston Shultz
|
||||
*/
|
||||
class InlineNode : public Node {
|
||||
public:
|
||||
InlineNode(const std::string& content) : content(content) {}
|
||||
|
||||
// Optional: allow access to the content
|
||||
std::string getContent() const { return content; }
|
||||
|
||||
protected:
|
||||
std::string content;
|
||||
};
|
||||
|
||||
// These classes inherit the InlineNode constructor using `using`
|
||||
class TextNode : public InlineNode {
|
||||
public:
|
||||
using InlineNode::InlineNode;
|
||||
};
|
||||
|
||||
class BoldNode : public InlineNode {
|
||||
public:
|
||||
using InlineNode::InlineNode;
|
||||
};
|
||||
|
||||
class ItalicNode : public InlineNode {
|
||||
public:
|
||||
using InlineNode::InlineNode;
|
||||
};
|
||||
|
||||
class BoldItalicNode : public InlineNode {
|
||||
public:
|
||||
using InlineNode::InlineNode;
|
||||
};
|
||||
|
||||
#endif // INLINENODE_H
|
||||
@ -0,0 +1,23 @@
|
||||
#include "inlineNode.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
void InlineNode::AddChild(std::unique_ptr<Node> child) {
|
||||
throw std::runtime_error("Cannot add a child to an InlineNode.");
|
||||
}
|
||||
|
||||
string TextNode::ToHtml() const { return this->content; }
|
||||
|
||||
string ItalicNode::ToHtml() const { return "<em>" + this->content + "</em>"; }
|
||||
|
||||
string BoldNode::ToHtml() const {
|
||||
return "<strong>" + this->content + "</strong>";
|
||||
}
|
||||
|
||||
string BoldItalicNode::ToHtml() const {
|
||||
return "<strong><em>" + this->content + "</em></strong>";
|
||||
}
|
||||
97
lib/inlineNode.h
Normal file
97
lib/inlineNode.h
Normal file
@ -0,0 +1,97 @@
|
||||
#ifndef INLINENODE_H
|
||||
#define INLINENODE_H
|
||||
|
||||
#include "node.h"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* @desc ABC inline node for textual nodes.
|
||||
*
|
||||
* An inline node has content, but no children. An attempt to add children to
|
||||
* this node will result in a runtime exception.
|
||||
* Inline nodes define text itself, not textual tags, but the actual text inside
|
||||
* the tags.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
class InlineNode : public Node {
|
||||
public:
|
||||
InlineNode(std::string content) : content(content) {};
|
||||
|
||||
/**
|
||||
* @brief Return node as HTML string.
|
||||
*
|
||||
* This method is virtual and required to be overridden.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
virtual std::string ToHtml() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Cannot add a child to this class.
|
||||
*
|
||||
* This method simply returns a runtime error, since there is no reason to add
|
||||
* a child to a textual node.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
void AddChild(std::unique_ptr<Node> child);
|
||||
|
||||
protected:
|
||||
std::string content;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc A raw textual node.
|
||||
*
|
||||
* This node is simple, it simple returns it's content with no formatting.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
class TextNode : public InlineNode {
|
||||
public:
|
||||
TextNode(std::string content) : InlineNode(content) {};
|
||||
std::string ToHtml() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc A italic textual node.
|
||||
*
|
||||
* This node returns it's content wrapped with <em></em> tags.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
class ItalicNode : public InlineNode {
|
||||
public:
|
||||
ItalicNode(std::string content) : InlineNode(content) {};
|
||||
std::string ToHtml() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc A bold textual node.
|
||||
*
|
||||
* This node returns it's content wrapped with <strong></strong> tags.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
class BoldNode : public InlineNode {
|
||||
public:
|
||||
BoldNode(std::string content) : InlineNode(content) {};
|
||||
std::string ToHtml() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc A bold and italic textual node.
|
||||
*
|
||||
* This node returns it's content wrapped with <strong></strong> AND <em>/<em>
|
||||
* tags.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
class BoldItalicNode : public InlineNode {
|
||||
public:
|
||||
BoldItalicNode(std::string content) : InlineNode(content) {};
|
||||
std::string ToHtml() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -16,6 +16,7 @@
|
||||
/// method is required. When calling a function that accepts a reference, the
|
||||
/// reference operator (*) works perfectly fine. Hence, in this project we will
|
||||
/// try to avoid using raw pointers, and only use references when needed.
|
||||
/// Reference: https://www.youtube.com/watch?v=AmjoK55h68Y&t=166s
|
||||
|
||||
// NOTE ABC
|
||||
class Node {
|
||||
|
||||
@ -1 +1,65 @@
|
||||
#include "structureNode.h"
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
string DocumentNode::ToHtml() const {
|
||||
std::stringstream ss;
|
||||
ss << "<!DOCTYPE html>\n\t<html lang=\"en\">\n\t\t<head>\n\t\t\t<meta "
|
||||
"charset=\"UTF-8\">\n\t\t\t<meta "
|
||||
"name=\"viewport\" content=\"width=device-width, "
|
||||
"initial-scale=1.0\">\n\t\t\t<title>Document</title>\n\t\t</"
|
||||
"head>\n\t<body>\n";
|
||||
|
||||
for (const auto &child : this->GetChilren()) {
|
||||
ss << child->ToHtml();
|
||||
}
|
||||
|
||||
ss << "\n\t</body>\n</html>";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
HeadingNode::HeadingNode(int size) {
|
||||
if (1 <= size && size <= 6) {
|
||||
this->size = size;
|
||||
return;
|
||||
}
|
||||
|
||||
throw std::runtime_error("HeadingNode.size must be between 1 and 6.");
|
||||
}
|
||||
|
||||
string HeadingNode::ToHtml() const {
|
||||
std::stringstream ss;
|
||||
ss << "<h" << size << ">";
|
||||
|
||||
for (const auto &child : this->GetChilren()) {
|
||||
ss << child->ToHtml();
|
||||
}
|
||||
|
||||
ss << "</h" << size << ">\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
string ParagraphNode::ToHtml() const {
|
||||
std::stringstream ss;
|
||||
ss << "<p>";
|
||||
|
||||
for (const auto &child : this->GetChilren()) {
|
||||
ss << child->ToHtml();
|
||||
}
|
||||
|
||||
ss << "</p>\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// TODO: Implement
|
||||
string ListNode::ToHtml() const {
|
||||
std::stringstream ss;
|
||||
ss << (this->ordered ? "<ol>NOT YET IMPLEMENTED</ol>"
|
||||
: "<ul>NOT YET IMPLEMENTED</ul>");
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@ -2,12 +2,103 @@
|
||||
#define STRUCTURENODE_H
|
||||
|
||||
#include "node.h"
|
||||
#include <string>
|
||||
|
||||
class StructureNode : public Node {};
|
||||
/**
|
||||
* @desc ABC inline node for structure nodes.
|
||||
*
|
||||
* A structure node has no content, but instead it has children which contain
|
||||
* content. These children can be other structure nodes, or they can be inline
|
||||
* nodes. Inline nodes allow this node to display textual content.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
class StructureNode : public Node {
|
||||
public:
|
||||
/**
|
||||
* @brief Return node as HTML string.
|
||||
*
|
||||
* This method is virtual and required to be overridden.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
virtual std::string ToHtml() const = 0;
|
||||
};
|
||||
|
||||
class ListNode : public StructureNode {};
|
||||
class HeadingNode : public StructureNode {};
|
||||
class DocumentNode : public StructureNode {};
|
||||
class ParagraphNode : public StructureNode {};
|
||||
/**
|
||||
* @desc A main HTML document node.
|
||||
*
|
||||
* This node should be used as the root of the DOM. Calling `ToHtml` will yield
|
||||
* an HTML document boiler plate with it's children rendered as the body.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
class DocumentNode : public StructureNode {
|
||||
public:
|
||||
std::string ToHtml() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc A heading node.
|
||||
*
|
||||
* A heading contains children that are expected to be inline nodes. These
|
||||
* children represent the textual content of the node. This heading node simply
|
||||
* stores the children and the size of the heading. A size of 1 means <h1>, etc.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
class HeadingNode : public StructureNode {
|
||||
protected:
|
||||
/**
|
||||
* @brief Size of the heading.
|
||||
*
|
||||
* The constructor will enforce size requirements.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
int size;
|
||||
|
||||
public:
|
||||
HeadingNode(int size);
|
||||
std::string ToHtml() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc A paragraph node.
|
||||
*
|
||||
* A paragraph contains children that are expected to be inline nodes. These
|
||||
* children represent the textual content of the node. This heading node simply
|
||||
* stores the children.
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
class ParagraphNode : public StructureNode {
|
||||
public:
|
||||
std::string ToHtml() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc A list container node.
|
||||
*
|
||||
* This node is used to wrap list elements. Not to be confused with the list
|
||||
* elements themselves. This is the parent (<ul> or <ol>), and must be created
|
||||
* with a boolean which defines whether the list should be ordered or not.
|
||||
* i.e., should have numbers (use the <ol> tags).
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
class ListNode : public StructureNode {
|
||||
protected:
|
||||
/**
|
||||
* @brief Should the list be ordered (numeric).
|
||||
*
|
||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||
*/
|
||||
bool ordered;
|
||||
|
||||
public:
|
||||
ListNode(bool ordered = false) : ordered(ordered) {};
|
||||
std::string ToHtml() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
87
src/main.cpp
87
src/main.cpp
@ -1,10 +1,64 @@
|
||||
/*#include "../lib/parser.h"
|
||||
#include "../lib/inlineNode.h"
|
||||
#include "../lib/parser.h"
|
||||
#include "../lib/structureNode.h"
|
||||
#include "../lib/watchDog.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
void test_nodes() {
|
||||
// For simplicity
|
||||
using std::make_unique;
|
||||
using std::unique_ptr;
|
||||
|
||||
DocumentNode root;
|
||||
unique_ptr<TextNode> node = make_unique<TextNode>("text node");
|
||||
unique_ptr<BoldNode> bold = make_unique<BoldNode>("bold node");
|
||||
unique_ptr<ItalicNode> italic = make_unique<ItalicNode>("italic node");
|
||||
unique_ptr<BoldItalicNode> bolditalic =
|
||||
make_unique<BoldItalicNode>("bold italic node");
|
||||
|
||||
unique_ptr<HeadingNode> heading = make_unique<HeadingNode>(2);
|
||||
heading->AddChild(std::move(node));
|
||||
heading->AddChild(std::move(bold));
|
||||
|
||||
std::unique_ptr<ParagraphNode> para = std::make_unique<ParagraphNode>();
|
||||
para->AddChild(std::move(italic));
|
||||
para->AddChild(std::move(bolditalic));
|
||||
|
||||
unique_ptr<ListNode> list = make_unique<ListNode>();
|
||||
|
||||
root.AddChild(std::move(heading));
|
||||
root.AddChild(std::move(para));
|
||||
root.AddChild(std::move(list));
|
||||
|
||||
std::cout << root.ToHtml() << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
*Preston: Test to see if watchdog works :)
|
||||
*/
|
||||
void test_watchdog() {
|
||||
WatchDog wd("test/input.md");
|
||||
wd.start();
|
||||
|
||||
std::cout << "Initial check (should do nothing if file unchanged):\n";
|
||||
wd.checkFile();
|
||||
|
||||
std::cout << "Now, modify or create the file 'example.txt' manually and "
|
||||
"press Enter:\n";
|
||||
std::cin.get(); // Wait for user to press Enter
|
||||
|
||||
// Check again after manual change
|
||||
wd.checkFile();
|
||||
|
||||
std::cout << "Done testing.\n";
|
||||
}
|
||||
|
||||
void test_input(int argc, char **argv) {
|
||||
if (argc <= 1) {
|
||||
std::cerr << "Usage: <input_file> <?output_file>" << std::endl;
|
||||
return 0; // TODO: Should return 1?
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
@ -22,31 +76,6 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
*Preston: Test to see if watchdog works :)
|
||||
*/
|
||||
|
||||
#include "watchDog.h"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
WatchDog wd("test/input.md");
|
||||
wd.start();
|
||||
|
||||
std::cout << "Initial check (should do nothing if file unchanged):\n";
|
||||
wd.checkFile();
|
||||
|
||||
std::cout << "Now, modify or create the file 'example.txt' manually and press Enter:\n";
|
||||
std::cin.get(); //Wait for user to press Enter
|
||||
|
||||
//Check again after manual change
|
||||
wd.checkFile();
|
||||
|
||||
std::cout << "Done testing.\n";
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char **argv) { test_nodes(); }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user