diff --git a/.gitignore b/.gitignore index 267697e..3943bed 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /build /build/* parser +/.vscode diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 0e113dc..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -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" - } -} \ No newline at end of file diff --git a/Makefile b/Makefile index 4f8f571..9f77ed3 100644 --- a/Makefile +++ b/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) diff --git a/flake.nix b/flake.nix index e544aa4..07909a0 100644 --- a/flake.nix +++ b/flake.nix @@ -1,42 +1,42 @@ -{ - description = "Blank development flake. Adjust as needed"; - - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - flake-utils.url = "github:numtide/flake-utils"; - }; - - outputs = { self, nixpkgs, flake-utils, ... }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs { inherit system; }; - in - { - # Define the development shell. - # When you run `nix develop` (or direnv activates), you'll enter this shell. - devShells.default = pkgs.mkShell { - # List all the development tools you need available in this shell's PATH. - packages = with pkgs; [ - gcc - gdb - stdenv - ]; - - # Define the shell that will be executed. - # Here, we explicitly use zsh. - # Note: pkgs.zsh needs to be included in `packages` or `nativeBuildInputs` - # for it to be found in the shell's environment. `inherit pkgs.zsh;` is concise. - inherit (pkgs) zsh; - - # Environment variables and commands to run when the shell starts. - shellHook = '' - # Add any exports, hooks, aliases, or anything else here - - # Exec zsh to replace the current shell process with zsh. - # This ensures your prompt and zsh configurations load correctly. - exec zsh - ''; - }; - } - ); -} +{ + description = "Blank development flake. Adjust as needed"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + in + { + # Define the development shell. + # When you run `nix develop` (or direnv activates), you'll enter this shell. + devShells.default = pkgs.mkShell { + # List all the development tools you need available in this shell's PATH. + packages = with pkgs; [ + gcc + gdb + stdenv + ]; + + # Define the shell that will be executed. + # Here, we explicitly use zsh. + # Note: pkgs.zsh needs to be included in `packages` or `nativeBuildInputs` + # for it to be found in the shell's environment. `inherit pkgs.zsh;` is concise. + inherit (pkgs) zsh; + + # Environment variables and commands to run when the shell starts. + shellHook = '' + # Add any exports, hooks, aliases, or anything else here + + # Exec zsh to replace the current shell process with zsh. + # This ensures your prompt and zsh configurations load correctly. + exec zsh + ''; + }; + } + ); +} diff --git a/lib/inlindeNode.h b/lib/inlindeNode.h deleted file mode 100644 index 956efbb..0000000 --- a/lib/inlindeNode.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef INLINENODE_H -#define INLINENODE_H - -#include "node.h" -#include - -/** - * @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 diff --git a/lib/inlineNode.cpp b/lib/inlineNode.cpp index e69de29..22b4788 100644 --- a/lib/inlineNode.cpp +++ b/lib/inlineNode.cpp @@ -0,0 +1,23 @@ +#include "inlineNode.h" + +#include +#include +#include + +using std::string; + +void InlineNode::AddChild(std::unique_ptr child) { + throw std::runtime_error("Cannot add a child to an InlineNode."); +} + +string TextNode::ToHtml() const { return this->content; } + +string ItalicNode::ToHtml() const { return "" + this->content + ""; } + +string BoldNode::ToHtml() const { + return "" + this->content + ""; +} + +string BoldItalicNode::ToHtml() const { + return "" + this->content + ""; +} diff --git a/lib/inlineNode.h b/lib/inlineNode.h new file mode 100644 index 0000000..7655afd --- /dev/null +++ b/lib/inlineNode.h @@ -0,0 +1,97 @@ +#ifndef INLINENODE_H +#define INLINENODE_H + +#include "node.h" +#include + +/** + * @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 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 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 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 AND / + * tags. + * + * @author Hayden Hargreaves (hhargreaves2006@gmail.com) + */ +class BoldItalicNode : public InlineNode { +public: + BoldItalicNode(std::string content) : InlineNode(content) {}; + std::string ToHtml() const; +}; + +#endif diff --git a/lib/node.h b/lib/node.h index 9ee7023..390b004 100644 --- a/lib/node.h +++ b/lib/node.h @@ -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 { diff --git a/lib/structureNode.cpp b/lib/structureNode.cpp index 6d4d8f4..55ac4d1 100644 --- a/lib/structureNode.cpp +++ b/lib/structureNode.cpp @@ -1 +1,65 @@ #include "structureNode.h" +#include +#include +#include +#include + +using std::string; + +string DocumentNode::ToHtml() const { + std::stringstream ss; + ss << "\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\tDocument\n\t\t\n\t\n"; + + for (const auto &child : this->GetChilren()) { + ss << child->ToHtml(); + } + + ss << "\n\t\n"; + 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 << ""; + + for (const auto &child : this->GetChilren()) { + ss << child->ToHtml(); + } + + ss << "\n"; + return ss.str(); +} + +string ParagraphNode::ToHtml() const { + std::stringstream ss; + ss << "

"; + + for (const auto &child : this->GetChilren()) { + ss << child->ToHtml(); + } + + ss << "

\n"; + return ss.str(); +} + +// TODO: Implement +string ListNode::ToHtml() const { + std::stringstream ss; + ss << (this->ordered ? "
    NOT YET IMPLEMENTED
" + : "
    NOT YET IMPLEMENTED
"); + + return ss.str(); +} diff --git a/lib/structureNode.h b/lib/structureNode.h index 576de51..c45feea 100644 --- a/lib/structureNode.h +++ b/lib/structureNode.h @@ -2,12 +2,103 @@ #define STRUCTURENODE_H #include "node.h" +#include -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

, 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 (
    or
      ), and must be created + * with a boolean which defines whether the list should be ordered or not. + * i.e., should have numbers (use the
        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 diff --git a/src/main.cpp b/src/main.cpp index 63885a2..9a67d41 100644 --- a/src/main.cpp +++ b/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 #include -int main(int argc, char **argv) { +void test_nodes() { + // For simplicity + using std::make_unique; + using std::unique_ptr; + + DocumentNode root; + unique_ptr node = make_unique("text node"); + unique_ptr bold = make_unique("bold node"); + unique_ptr italic = make_unique("italic node"); + unique_ptr bolditalic = + make_unique("bold italic node"); + + unique_ptr heading = make_unique(2); + heading->AddChild(std::move(node)); + heading->AddChild(std::move(bold)); + + std::unique_ptr para = std::make_unique(); + para->AddChild(std::move(italic)); + para->AddChild(std::move(bolditalic)); + + unique_ptr list = make_unique(); + + 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: " << 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 - -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; -} \ No newline at end of file +int main(int argc, char **argv) { test_nodes(); }