Merge pull request '(FEAT): Defined the structureNode classes for the node.' (#14) from feature/nodes-implementation into main
Reviewed-on: azpect/MarkdownToHtmlCompiler#14 Reviewed-by: shultzp1 <shultzp1@my.erau.edu>
This commit is contained in:
commit
4b973abf6c
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,4 +1,4 @@
|
|||||||
*.o
|
*.o
|
||||||
/build
|
/build
|
||||||
/build/*
|
/build/*
|
||||||
parser
|
parser
|
||||||
|
|||||||
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"C_Cpp.errorSquiggles": "disabled"
|
||||||
|
}
|
||||||
18
LICENSE
18
LICENSE
@ -1,9 +1,9 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2025 azpect
|
Copyright (c) 2025 azpect
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|||||||
98
Makefile
98
Makefile
@ -1,49 +1,49 @@
|
|||||||
# Define the C++ compiler and flags
|
# Define the C++ compiler and flags
|
||||||
CXX = g++
|
CXX = g++
|
||||||
CXXFLAGS = -Wall -g
|
CXXFLAGS = -Wall -g
|
||||||
|
|
||||||
# Directories
|
# Directories
|
||||||
BUILD_DIR = build
|
BUILD_DIR = build
|
||||||
SRC_DIR = src
|
SRC_DIR = src
|
||||||
LIB_DIR = lib
|
LIB_DIR = lib
|
||||||
|
|
||||||
# Executable name
|
# Executable name
|
||||||
TARGET = parser
|
TARGET = parser
|
||||||
|
|
||||||
# Automatically find all source files
|
# Automatically find all source files
|
||||||
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
|
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
|
||||||
LIB_FILES := $(wildcard $(LIB_DIR)/*.cpp)
|
LIB_FILES := $(wildcard $(LIB_DIR)/*.cpp)
|
||||||
ALL_SOURCES = $(SRC_FILES) $(LIB_FILES)
|
ALL_SOURCES = $(SRC_FILES) $(LIB_FILES)
|
||||||
|
|
||||||
# Generate object file paths in the build directory
|
# Generate object file paths in the build directory
|
||||||
OBJECTS := $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(notdir $(ALL_SOURCES)))
|
OBJECTS := $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(notdir $(ALL_SOURCES)))
|
||||||
|
|
||||||
# Include directories
|
# Include directories
|
||||||
INCLUDES = -I$(LIB_DIR) -I$(SRC_DIR)
|
INCLUDES = -I$(LIB_DIR) -I$(SRC_DIR)
|
||||||
|
|
||||||
.PHONY: all clean test
|
.PHONY: all clean test
|
||||||
|
|
||||||
all: $(BUILD_DIR) $(TARGET)
|
all: $(BUILD_DIR) $(TARGET)
|
||||||
|
|
||||||
$(BUILD_DIR):
|
$(BUILD_DIR):
|
||||||
mkdir -p $(BUILD_DIR)
|
mkdir -p $(BUILD_DIR)
|
||||||
|
|
||||||
$(TARGET): $(OBJECTS)
|
$(TARGET): $(OBJECTS)
|
||||||
$(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $@
|
$(CXX) $(CXXFLAGS) $(INCLUDES) $^ -o $@
|
||||||
|
|
||||||
# Generic rule for all .cpp files in the src/ directory
|
# Generic rule for all .cpp files in the src/ directory
|
||||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
|
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
|
||||||
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
|
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
|
||||||
|
|
||||||
# Generic rule for all .cpp files in the lib/ directory
|
# Generic rule for all .cpp files in the lib/ directory
|
||||||
$(BUILD_DIR)/%.o: $(LIB_DIR)/%.cpp
|
$(BUILD_DIR)/%.o: $(LIB_DIR)/%.cpp
|
||||||
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
|
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
|
||||||
|
|
||||||
test: all
|
test: all
|
||||||
./$(TARGET)
|
./$(TARGET)
|
||||||
./$(TARGET) ' '
|
./$(TARGET) ' '
|
||||||
./$(TARGET) ./test/input.md
|
./$(TARGET) ./test/input.md
|
||||||
./$(TARGET) ./test/input.md ./test/output.html
|
./$(TARGET) ./test/input.md ./test/output.html
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR) $(TARGET)
|
rm -rf $(BUILD_DIR) $(TARGET)
|
||||||
|
|||||||
230
README.md
230
README.md
@ -1,115 +1,115 @@
|
|||||||
# MarkdownToHtmlCompiler
|
# MarkdownToHtmlCompiler
|
||||||
|
|
||||||
### Project Overview
|
### Project Overview
|
||||||
|
|
||||||
The goal is to create a program that reads a file containing text formatted in a simple version of
|
The goal is to create a program that reads a file containing text formatted in a simple version of
|
||||||
Markdown and converts it into a valid HTML file. The program will need to identify and translate
|
Markdown and converts it into a valid HTML file. The program will need to identify and translate
|
||||||
specific syntax (e.g., `# Heading` to `<h1>Heading</h1>`, `*text*` to `<em>text</em>`).
|
specific syntax (e.g., `# Heading` to `<h1>Heading</h1>`, `*text*` to `<em>text</em>`).
|
||||||
|
|
||||||
|
|
||||||
### Implementation Requirements (Generated by Gemini)
|
### Implementation Requirements (Generated by Gemini)
|
||||||
|
|
||||||
Class Hierarchy: Design a class hierarchy to represent the components of your Markdown document. An
|
Class Hierarchy: Design a class hierarchy to represent the components of your Markdown document. An
|
||||||
abstract base class, Element, can define common behavior. Derived classes would then represent specific
|
abstract base class, Element, can define common behavior. Derived classes would then represent specific
|
||||||
types of elements, such as Heading, Paragraph, BoldText, and ListItem. This is a perfect example of
|
types of elements, such as Heading, Paragraph, BoldText, and ListItem. This is a perfect example of
|
||||||
inheritance and polymorphism.
|
inheritance and polymorphism.
|
||||||
|
|
||||||
Object Composition: A Document class can be composed of multiple Element objects, representing the
|
Object Composition: A Document class can be composed of multiple Element objects, representing the
|
||||||
entire file. A Parser class would be composed of helper methods to break down the input string and
|
entire file. A Parser class would be composed of helper methods to break down the input string and
|
||||||
build the Document object. This shows how you can build a complex system from smaller, self-contained
|
build the Document object. This shows how you can build a complex system from smaller, self-contained
|
||||||
objects.
|
objects.
|
||||||
|
|
||||||
File I/O and Exceptions: You will need to use ifstream to read the Markdown file and ofstream to write
|
File I/O and Exceptions: You will need to use ifstream to read the Markdown file and ofstream to write
|
||||||
the generated HTML file. Your code should use exceptions to gracefully handle potential errors, such
|
the generated HTML file. Your code should use exceptions to gracefully handle potential errors, such
|
||||||
as a file not being found.
|
as a file not being found.
|
||||||
|
|
||||||
Operator Overloading: Overload the << stream insertion operator for your Element and Document classes.
|
Operator Overloading: Overload the << stream insertion operator for your Element and Document classes.
|
||||||
This would allow you to easily print the generated HTML to the console or write it to a file, making
|
This would allow you to easily print the generated HTML to the console or write it to a file, making
|
||||||
your code cleaner and more readable.
|
your code cleaner and more readable.
|
||||||
|
|
||||||
UML Diagram: The complexity of the class relationships makes a UML diagram an essential part of the
|
UML Diagram: The complexity of the class relationships makes a UML diagram an essential part of the
|
||||||
project. It will help you plan your design and will be a key component of your submission.
|
project. It will help you plan your design and will be a key component of your submission.
|
||||||
|
|
||||||
Recursive Descent Parser: This is the primary algorithm you'll use. It's a top-down parsing technique
|
Recursive Descent Parser: This is the primary algorithm you'll use. It's a top-down parsing technique
|
||||||
where a set of recursive functions "descend" through the grammar of your simple Markdown language. For
|
where a set of recursive functions "descend" through the grammar of your simple Markdown language. For
|
||||||
example, a parse_document() function would call parse_line(), which in turn might call parse_bold_text()
|
example, a parse_document() function would call parse_line(), which in turn might call parse_bold_text()
|
||||||
or parse_italic_text(). This method is intuitive and easy to implement for a simple grammar.
|
or parse_italic_text(). This method is intuitive and easy to implement for a simple grammar.
|
||||||
|
|
||||||
Stack: A stack is essential for handling nested elements. For instance, if you allow bold text inside
|
Stack: A stack is essential for handling nested elements. For instance, if you allow bold text inside
|
||||||
italic text (_This is *bold and italic* text_), you can push the _ token onto the stack and then push
|
italic text (_This is *bold and italic* text_), you can push the _ token onto the stack and then push
|
||||||
the * token. When you encounter the closing *, you check if the top of the stack matches. This ensures
|
the * token. When you encounter the closing *, you check if the top of the stack matches. This ensures
|
||||||
that all tags are correctly opened and closed. Your presentation can visually demonstrate this process
|
that all tags are correctly opened and closed. Your presentation can visually demonstrate this process
|
||||||
with a stack diagram.
|
with a stack diagram.
|
||||||
|
|
||||||
Hash Map or Map: A hash map (std::unordered_map) or a map (std::map) can be used to efficiently store
|
Hash Map or Map: A hash map (std::unordered_map) or a map (std::map) can be used to efficiently store
|
||||||
and retrieve the HTML equivalent for each Markdown tag. For example, you could map `#` to `<h1>`or `*`
|
and retrieve the HTML equivalent for each Markdown tag. For example, you could map `#` to `<h1>`or `*`
|
||||||
to `<em>`. This provides O(1) average-case lookup time.
|
to `<em>`. This provides O(1) average-case lookup time.
|
||||||
|
|
||||||
|
|
||||||
### Contribution Policy
|
### Contribution Policy
|
||||||
|
|
||||||
###### Branching
|
###### Branching
|
||||||
When working on this project, please use a feature branch (i.e. `feature/parser`) with a descriptive name.
|
When working on this project, please use a feature branch (i.e. `feature/parser`) with a descriptive name.
|
||||||
`feature/a` is not a descriptive name. These branches should be branched off the most recent `main` branch,
|
`feature/a` is not a descriptive name. These branches should be branched off the most recent `main` branch,
|
||||||
we will not make use of a `dev` or `staging` branch since the project is small in scale as well as time.
|
we will not make use of a `dev` or `staging` branch since the project is small in scale as well as time.
|
||||||
**However, if the project becomes larger or out-of-control, a dev/staging branch will be implemented.**
|
**However, if the project becomes larger or out-of-control, a dev/staging branch will be implemented.**
|
||||||
|
|
||||||
###### Commits
|
###### Commits
|
||||||
|
|
||||||
When working, it is best practice to commit code as much as possible, without being over zealous. For
|
When working, it is best practice to commit code as much as possible, without being over zealous. For
|
||||||
example, when a feature or bug is complete, its time to commit. But when you have to make a new function,
|
example, when a feature or bug is complete, its time to commit. But when you have to make a new function,
|
||||||
that does not mean its time. Each team member should use their best judgment.
|
that does not mean its time. Each team member should use their best judgment.
|
||||||
|
|
||||||
Commit messages a little bit more important, when working in a team, it is important to provide strong,
|
Commit messages a little bit more important, when working in a team, it is important to provide strong,
|
||||||
clear and concise commit messages. In this project, the team will use a simple formula:
|
clear and concise commit messages. In this project, the team will use a simple formula:
|
||||||
|
|
||||||
**(SUBJECT) Title: textual description**
|
**(SUBJECT) Title: textual description**
|
||||||
|
|
||||||
i.e. (FIX) Rendering completed: explain what changed in short.
|
i.e. (FIX) Rendering completed: explain what changed in short.
|
||||||
|
|
||||||
###### Pushing
|
###### Pushing
|
||||||
|
|
||||||
When working in a feature branch, pushing and pulling has no restrictions. Feel free to do as much
|
When working in a feature branch, pushing and pulling has no restrictions. Feel free to do as much
|
||||||
(or as little) as possible. However, you **CANNOT** push directly to `main`, the VCS will not allow you
|
(or as little) as possible. However, you **CANNOT** push directly to `main`, the VCS will not allow you
|
||||||
to do so, but do not make that mistake. When you are ready to merge a feature, you will create a PR
|
to do so, but do not make that mistake. When you are ready to merge a feature, you will create a PR
|
||||||
and once it has been reviewed and approved it will be automatically merged in.
|
and once it has been reviewed and approved it will be automatically merged in.
|
||||||
|
|
||||||
###### Pull Requests (PR)
|
###### Pull Requests (PR)
|
||||||
|
|
||||||
Once a feature is complete, you will create a pull request. Before a request can be merged into `main`,
|
Once a feature is complete, you will create a pull request. Before a request can be merged into `main`,
|
||||||
one approval is required (which cannot be the author). This practice is to promote team work and encourage
|
one approval is required (which cannot be the author). This practice is to promote team work and encourage
|
||||||
code reviews. Each team member is expected to check in frequently and review as often as they are able to,
|
code reviews. Each team member is expected to check in frequently and review as often as they are able to,
|
||||||
however, there is no defined time requirement. Personal communication is totally acceptable as a means to
|
however, there is no defined time requirement. Personal communication is totally acceptable as a means to
|
||||||
request approval, since I am unsure if this platform will notify members.
|
request approval, since I am unsure if this platform will notify members.
|
||||||
|
|
||||||
###### Issues
|
###### Issues
|
||||||
|
|
||||||
If a bug, issue, or otherwise concern is noticed the first thing the team member should do is create an
|
If a bug, issue, or otherwise concern is noticed the first thing the team member should do is create an
|
||||||
issue. An issue should be descriptive and contain everything another team member needs to understand the
|
issue. An issue should be descriptive and contain everything another team member needs to understand the
|
||||||
issue and its context. This way, a new team member can tackle the issue without contextual gaps.
|
issue and its context. This way, a new team member can tackle the issue without contextual gaps.
|
||||||
|
|
||||||
If a member would like to work on the issue themself, the `assignee` field is where this should be defined.
|
If a member would like to work on the issue themself, the `assignee` field is where this should be defined.
|
||||||
If a member would like help from another member, they should assign the other team member to the issue, and
|
If a member would like help from another member, they should assign the other team member to the issue, and
|
||||||
leave a comment in the issue itself describing what help is needed.
|
leave a comment in the issue itself describing what help is needed.
|
||||||
|
|
||||||
**Labels** are important for understanding what type of issues/bugs exist in the application. When a bug is
|
**Labels** are important for understanding what type of issues/bugs exist in the application. When a bug is
|
||||||
created, make sure the proper labels are applied. These labels will be abstract, such as: `bug`, `fix` or `feature`
|
created, make sure the proper labels are applied. These labels will be abstract, such as: `bug`, `fix` or `feature`
|
||||||
and they will also be specific, such as: `parser`, `i/o` or `processer`. A combination of both styles of labels
|
and they will also be specific, such as: `parser`, `i/o` or `processer`. A combination of both styles of labels
|
||||||
allows other team members to understand what is going on. If a member feels an issue is missing, they are free
|
allows other team members to understand what is going on. If a member feels an issue is missing, they are free
|
||||||
to create new ones, but there is a such thing as **too many labels** a few per issue is totally fine. They are
|
to create new ones, but there is a such thing as **too many labels** a few per issue is totally fine. They are
|
||||||
not meant to replace the description.
|
not meant to replace the description.
|
||||||
|
|
||||||
**Priority** is the final important factor to consider. In this project, priority will be defined using labels
|
**Priority** is the final important factor to consider. In this project, priority will be defined using labels
|
||||||
as well. The policy defined above will apply here to priority labels as well. However, these labels are
|
as well. The policy defined above will apply here to priority labels as well. However, these labels are
|
||||||
**mutually exclusive**.
|
**mutually exclusive**.
|
||||||
|
|
||||||
###### Projects (Sprints)
|
###### Projects (Sprints)
|
||||||
|
|
||||||
The use of the `projects` tab in the VCS will allow the team to remain organized as create notes and action
|
The use of the `projects` tab in the VCS will allow the team to remain organized as create notes and action
|
||||||
items that should be completed before one another. These resemble `sprints` from the `AGILE` development life cycle.
|
items that should be completed before one another. These resemble `sprints` from the `AGILE` development life cycle.
|
||||||
A new "project" should be created when a large piece of functionality needs to be created. Issues can **and should**
|
A new "project" should be created when a large piece of functionality needs to be created. Issues can **and should**
|
||||||
be attached to the projects they are related too. This will continue to encourage teamwork and organization.
|
be attached to the projects they are related too. This will continue to encourage teamwork and organization.
|
||||||
|
|
||||||
Projects should have defined criteria, such as input and outputs, expectations and a semi-defined timeline.
|
Projects should have defined criteria, such as input and outputs, expectations and a semi-defined timeline.
|
||||||
Once a description and is defined, tasks can be added and moved around as needed. The team will use **Kanban**
|
Once a description and is defined, tasks can be added and moved around as needed. The team will use **Kanban**
|
||||||
project types, as they are simple and easy to understand for new team members.
|
project types, as they are simple and easy to understand for new team members.
|
||||||
|
|||||||
122
flake.lock
generated
122
flake.lock
generated
@ -1,61 +1,61 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1731533236,
|
"lastModified": 1731533236,
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1760284886,
|
"lastModified": 1760284886,
|
||||||
"narHash": "sha256-TK9Kr0BYBQ/1P5kAsnNQhmWWKgmZXwUQr4ZMjCzWf2c=",
|
"narHash": "sha256-TK9Kr0BYBQ/1P5kAsnNQhmWWKgmZXwUQr4ZMjCzWf2c=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "cf3f5c4def3c7b5f1fc012b3d839575dbe552d43",
|
"rev": "cf3f5c4def3c7b5f1fc012b3d839575dbe552d43",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "nixos-unstable",
|
"ref": "nixos-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"systems": {
|
"systems": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1681028828,
|
"lastModified": 1681028828,
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
"owner": "nix-systems",
|
"owner": "nix-systems",
|
||||||
"repo": "default",
|
"repo": "default",
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nix-systems",
|
"owner": "nix-systems",
|
||||||
"repo": "default",
|
"repo": "default",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root": "root",
|
||||||
"version": 7
|
"version": 7
|
||||||
}
|
}
|
||||||
|
|||||||
84
flake.nix
84
flake.nix
@ -1,42 +1,42 @@
|
|||||||
{
|
{
|
||||||
description = "Blank development flake. Adjust as needed";
|
description = "Blank development flake. Adjust as needed";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, flake-utils, ... }:
|
outputs = { self, nixpkgs, flake-utils, ... }:
|
||||||
flake-utils.lib.eachDefaultSystem (system:
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
# Define the development shell.
|
# Define the development shell.
|
||||||
# When you run `nix develop` (or direnv activates), you'll enter this shell.
|
# When you run `nix develop` (or direnv activates), you'll enter this shell.
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
# List all the development tools you need available in this shell's PATH.
|
# List all the development tools you need available in this shell's PATH.
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
gcc
|
gcc
|
||||||
gdb
|
gdb
|
||||||
stdenv
|
stdenv
|
||||||
];
|
];
|
||||||
|
|
||||||
# Define the shell that will be executed.
|
# Define the shell that will be executed.
|
||||||
# Here, we explicitly use zsh.
|
# Here, we explicitly use zsh.
|
||||||
# Note: pkgs.zsh needs to be included in `packages` or `nativeBuildInputs`
|
# 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.
|
# for it to be found in the shell's environment. `inherit pkgs.zsh;` is concise.
|
||||||
inherit (pkgs) zsh;
|
inherit (pkgs) zsh;
|
||||||
|
|
||||||
# Environment variables and commands to run when the shell starts.
|
# Environment variables and commands to run when the shell starts.
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
# Add any exports, hooks, aliases, or anything else here
|
# Add any exports, hooks, aliases, or anything else here
|
||||||
|
|
||||||
# Exec zsh to replace the current shell process with zsh.
|
# Exec zsh to replace the current shell process with zsh.
|
||||||
# This ensures your prompt and zsh configurations load correctly.
|
# This ensures your prompt and zsh configurations load correctly.
|
||||||
exec zsh
|
exec zsh
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
17
lib/inlindeNode.h
Normal file
17
lib/inlindeNode.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef INLINENODE_H
|
||||||
|
#define INLINENODE_H
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
|
class InlineNode : public Node{
|
||||||
|
public:
|
||||||
|
InlineNode(std::string content) : content(content);
|
||||||
|
protected:
|
||||||
|
std::string content;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextNode : public InlineNode{};
|
||||||
|
class BoldNode : public InlineNode{};
|
||||||
|
class Italic : public InlineNode{};
|
||||||
|
class BoldItalic : public InlineNode{};
|
||||||
|
|
||||||
|
#endif
|
||||||
0
lib/inlineNode.cpp
Normal file
0
lib/inlineNode.cpp
Normal file
@ -1,4 +1,4 @@
|
|||||||
#include "./node.h"
|
#include "node.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|||||||
142
lib/node.h
142
lib/node.h
@ -1,71 +1,71 @@
|
|||||||
#ifndef NODE_H
|
#ifndef NODE_H
|
||||||
#define NODE_H
|
#define NODE_H
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/// NOTE: What the heck are unique pointers (unique_ptrs)
|
/// NOTE: What the heck are unique pointers (unique_ptrs)
|
||||||
/// They are basically an abstraction over the typical (raw) pointer.
|
/// They are basically an abstraction over the typical (raw) pointer.
|
||||||
/// They handle ownership and deletion of the pointer for us, to prevent memory
|
/// They handle ownership and deletion of the pointer for us, to prevent memory
|
||||||
/// leaks.
|
/// leaks.
|
||||||
/// They are pretty easy to use, and only need to exist in places where new ones
|
/// They are pretty easy to use, and only need to exist in places where new ones
|
||||||
/// are created. i.e., functions should not accept unique_ptrs, instead they
|
/// are created. i.e., functions should not accept unique_ptrs, instead they
|
||||||
/// should accept normal pointers or references.
|
/// should accept normal pointers or references.
|
||||||
/// When calling a function that accepts a raw pointer, the unique_ptrs.get()
|
/// When calling a function that accepts a raw pointer, the unique_ptrs.get()
|
||||||
/// method is required. When calling a function that accepts a reference, the
|
/// method is required. When calling a function that accepts a reference, the
|
||||||
/// reference operator (*) works perfectly fine. Hence, in this project we will
|
/// reference operator (*) works perfectly fine. Hence, in this project we will
|
||||||
/// try to avoid using raw pointers, and only use references when needed.
|
/// try to avoid using raw pointers, and only use references when needed.
|
||||||
|
|
||||||
// NOTE ABC
|
// NOTE ABC
|
||||||
class Node {
|
class Node {
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief List of children nodes.
|
* @brief List of children nodes.
|
||||||
*
|
*
|
||||||
* Most nodes will not have children, but some may, therefore this class must
|
* Most nodes will not have children, but some may, therefore this class must
|
||||||
* have it.
|
* have it.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
std::vector<std::unique_ptr<Node>> children;
|
std::vector<std::unique_ptr<Node>> children;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Inspect (view) the contents of the Node.
|
* @brief Inspect (view) the contents of the Node.
|
||||||
*
|
*
|
||||||
* This is a recursive approach to allow for indentation for easier viewing.
|
* This is a recursive approach to allow for indentation for easier viewing.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
virtual void Inspect(int indent = 0);
|
virtual void Inspect(int indent = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return the node as a string.
|
* @brief Return the node as a string.
|
||||||
*
|
*
|
||||||
* In this ABC the content is just returned with no modifications. The child
|
* In this ABC the content is just returned with no modifications. The child
|
||||||
* nodes are expected to modify this behavior. i.e. wrapping in HTML tags.
|
* nodes are expected to modify this behavior. i.e. wrapping in HTML tags.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
virtual std::string ToHtml() const = 0;
|
virtual std::string ToHtml() const = 0;
|
||||||
|
|
||||||
virtual void AddChild(std::unique_ptr<Node> child) {
|
virtual void AddChild(std::unique_ptr<Node> child) {
|
||||||
// Move ownership from the existing owner, to this class
|
// Move ownership from the existing owner, to this class
|
||||||
this->children.push_back(std::move(child));
|
this->children.push_back(std::move(child));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return a read-only (const) list of children.
|
* @brief Return a read-only (const) list of children.
|
||||||
*
|
*
|
||||||
* Return our list of unique ptrs, they are const and therefore only have read
|
* Return our list of unique ptrs, they are const and therefore only have read
|
||||||
* access.
|
* access.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
virtual const std::vector<std::unique_ptr<Node>> &GetChilren() const {
|
virtual const std::vector<std::unique_ptr<Node>> &GetChilren() const {
|
||||||
return this->children;
|
return this->children;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#include "./parser.h"
|
#include "parser.h"
|
||||||
#include "./util.h"
|
#include "util.h"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|||||||
208
lib/parser.h
208
lib/parser.h
@ -1,104 +1,104 @@
|
|||||||
#ifndef PARSER_H
|
#ifndef PARSER_H
|
||||||
#define PARSER_H
|
#define PARSER_H
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Markdown parser class.
|
* @brief Markdown parser class.
|
||||||
*
|
*
|
||||||
* Converts a Markdown file into an HTML output. This is done using a
|
* Converts a Markdown file into an HTML output. This is done using a
|
||||||
* recursive descent parser and converting the Markdown into a DOM tree.
|
* recursive descent parser and converting the Markdown into a DOM tree.
|
||||||
* Once the DOM tree exists, it is converted into an HTML string and
|
* Once the DOM tree exists, it is converted into an HTML string and
|
||||||
* written to the output file provided.
|
* written to the output file provided.
|
||||||
*
|
*
|
||||||
* This class will have a `DOM` and a `DOMParser` which are used in this
|
* This class will have a `DOM` and a `DOMParser` which are used in this
|
||||||
* process.
|
* process.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
class Parser {
|
class Parser {
|
||||||
public:
|
public:
|
||||||
Parser(string input_file_path, string output_file_path = "");
|
Parser(string input_file_path, string output_file_path = "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Inspect (view) contents of the class.
|
* @brief Inspect (view) contents of the class.
|
||||||
*
|
*
|
||||||
* Print each member of the class in its current state. Used for debugging.
|
* Print each member of the class in its current state. Used for debugging.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
void Inspect();
|
void Inspect();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief Parse an entire document.
|
* @brief Parse an entire document.
|
||||||
*
|
*
|
||||||
* This function will be called to yield the result. This is the entry point
|
* This function will be called to yield the result. This is the entry point
|
||||||
* to the recursive descent parser.
|
* to the recursive descent parser.
|
||||||
*
|
*
|
||||||
* Currently, there are no parameters, they are still under consideration.
|
* Currently, there are no parameters, they are still under consideration.
|
||||||
*
|
*
|
||||||
* It will be important to remember states between lines. For example, a
|
* It will be important to remember states between lines. For example, a
|
||||||
* paragraph that spans many lines should be inside the same node. But
|
* paragraph that spans many lines should be inside the same node. But
|
||||||
* white space causes the node to be broken.
|
* white space causes the node to be broken.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
void ParseDocument(void);
|
void ParseDocument(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief Input file path.
|
* @brief Input file path.
|
||||||
*
|
*
|
||||||
* Must be provided by the user.
|
* Must be provided by the user.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
string input_file_path;
|
string input_file_path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Output file path.
|
* @brief Output file path.
|
||||||
*
|
*
|
||||||
* If not provided, will be generated using the `input_file_path` by removing
|
* If not provided, will be generated using the `input_file_path` by removing
|
||||||
* the extension and appending `.html`.
|
* the extension and appending `.html`.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
string output_file_path;
|
string output_file_path;
|
||||||
|
|
||||||
// NOTE: We need a stack, just not sure what goes in it yet
|
// NOTE: We need a stack, just not sure what goes in it yet
|
||||||
// std::stack<any> stack;
|
// std::stack<any> stack;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Parse a single line.
|
* @brief Parse a single line.
|
||||||
*
|
*
|
||||||
* How does this function work...
|
* How does this function work...
|
||||||
* This is where the magic happens.
|
* This is where the magic happens.
|
||||||
*
|
*
|
||||||
* @param line Target line to parse, as string.
|
* @param line Target line to parse, as string.
|
||||||
* @return DOMNode, once exists
|
* @return DOMNode, once exists
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
void ParseLine(string line);
|
void ParseLine(string line);
|
||||||
|
|
||||||
// NOTE: Parser operations, again, abstract, just for brainstorming now
|
// NOTE: Parser operations, again, abstract, just for brainstorming now
|
||||||
// These should operate on internal state, not lines themselves
|
// These should operate on internal state, not lines themselves
|
||||||
void ParseHeader();
|
void ParseHeader();
|
||||||
void ParseParagraph();
|
void ParseParagraph();
|
||||||
void ParseItalic();
|
void ParseItalic();
|
||||||
void ParseBold();
|
void ParseBold();
|
||||||
void ParseBoldItalic();
|
void ParseBoldItalic();
|
||||||
|
|
||||||
// NOTE: Character operations, these are just for brainstorming
|
// NOTE: Character operations, these are just for brainstorming
|
||||||
char Peek();
|
char Peek();
|
||||||
void Consume();
|
void Consume();
|
||||||
bool EndOfLine();
|
bool EndOfLine();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
1
lib/structureNode.cpp
Normal file
1
lib/structureNode.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "structureNode.h"
|
||||||
13
lib/structureNode.h
Normal file
13
lib/structureNode.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef STRUCTURENODE_H
|
||||||
|
#define STRUCTURENODE_H
|
||||||
|
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
|
class StructureNode : public Node {};
|
||||||
|
|
||||||
|
class ListNode : public StructureNode {};
|
||||||
|
class HeadingNode : public StructureNode {};
|
||||||
|
class DocumentNode : public StructureNode {};
|
||||||
|
class ParagraphNode : public StructureNode {};
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "./util.h"
|
#include "util.h"
|
||||||
|
|
||||||
void removeTrailingWhitespace(std::string &input) {
|
void removeTrailingWhitespace(std::string &input) {
|
||||||
size_t start = input.find_first_not_of(" \t\n\r\f\v");
|
size_t start = input.find_first_not_of(" \t\n\r\f\v");
|
||||||
|
|||||||
60
lib/util.h
60
lib/util.h
@ -1,30 +1,30 @@
|
|||||||
#ifndef UTIL_H
|
#ifndef UTIL_H
|
||||||
#define UTIL_H
|
#define UTIL_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remove all white space after the content.
|
* @brief Remove all white space after the content.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
void removeTrailingWhitespace(std::string &input);
|
void removeTrailingWhitespace(std::string &input);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remove all white space before the content.
|
* @brief Remove all white space before the content.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
void removeLeadingWhitespace(std::string &input);
|
void removeLeadingWhitespace(std::string &input);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remove all white space before and after the content.
|
* @brief Remove all white space before and after the content.
|
||||||
*
|
*
|
||||||
* This uses the removeTrailingWhitespace and the removeLeadingWhitespace
|
* This uses the removeTrailingWhitespace and the removeLeadingWhitespace
|
||||||
* methods together on the same string.
|
* methods together on the same string.
|
||||||
*
|
*
|
||||||
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
* @author Hayden Hargreaves (hhargreaves2006@gmail.com)
|
||||||
*/
|
*/
|
||||||
void removeWhitespace(std::string &input);
|
void removeWhitespace(std::string &input);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
54
src/main.cpp
54
src/main.cpp
@ -1,27 +1,27 @@
|
|||||||
#include "../lib/parser.h"
|
#include "../lib/parser.h"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
std::cerr << "Usage: <input_file> <?output_file>" << std::endl;
|
std::cerr << "Usage: <input_file> <?output_file>" << std::endl;
|
||||||
return 0; // TODO: Should return 1?
|
return 0; // TODO: Should return 1?
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (argc >= 3) {
|
if (argc >= 3) {
|
||||||
Parser p(argv[1], argv[2]);
|
Parser p(argv[1], argv[2]);
|
||||||
p.Inspect();
|
p.Inspect();
|
||||||
} else {
|
} else {
|
||||||
Parser p(argv[1]);
|
Parser p(argv[1]);
|
||||||
p.Inspect();
|
p.Inspect();
|
||||||
}
|
}
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
std::cout << "Caught an error: " << e.what() << std::endl;
|
std::cout << "Caught an error: " << e.what() << std::endl;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
std::cout << "Caught an error: UNKNOWN" << std::endl;
|
std::cout << "Caught an error: UNKNOWN" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
90
syntax.md
90
syntax.md
@ -1,45 +1,45 @@
|
|||||||
|
|
||||||
Reference [here](https://www.markdownguide.org/basic-syntax/)
|
Reference [here](https://www.markdownguide.org/basic-syntax/)
|
||||||
|
|
||||||
Headings, h# tags
|
Headings, h# tags
|
||||||
|
|
||||||
|
|
||||||
# Header Level 1 -> <h1> Content </h1>
|
# Header Level 1 -> <h1> Content </h1>
|
||||||
## Header Level 2 -> <h2> Content </h2>
|
## Header Level 2 -> <h2> Content </h2>
|
||||||
### Header Level 3 -> <h3> Content </h3>
|
### Header Level 3 -> <h3> Content </h3>
|
||||||
#### Header Level 4 -> <h4> Content </h4>
|
#### Header Level 4 -> <h4> Content </h4>
|
||||||
##### Header Level 5 -> <h5> Content </h5>
|
##### Header Level 5 -> <h5> Content </h5>
|
||||||
###### Header Level 6 -> <h6> Content </h6>
|
###### Header Level 6 -> <h6> Content </h6>
|
||||||
|
|
||||||
|
|
||||||
Alternate syntax (n number of =/-)
|
Alternate syntax (n number of =/-)
|
||||||
|
|
||||||
Header Level 1 -> <h1> Content </h1>
|
Header Level 1 -> <h1> Content </h1>
|
||||||
================
|
================
|
||||||
|
|
||||||
|
|
||||||
Header Level 2 -> <h2> Content </h2>
|
Header Level 2 -> <h2> Content </h2>
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|
||||||
Paragraph tags
|
Paragraph tags
|
||||||
|
|
||||||
Hello world -> <p> Hello world </p>
|
Hello world -> <p> Hello world </p>
|
||||||
|
|
||||||
This is also
|
This is also
|
||||||
a paragraph -> <p> this is also a paragraph regardless </p>
|
a paragraph -> <p> this is also a paragraph regardless </p>
|
||||||
regardless
|
regardless
|
||||||
|
|
||||||
However
|
However
|
||||||
this is a break, because it ends with two spaces -> <p> However <br> this is a break, because it ends with two spaces </p>
|
this is a break, because it ends with two spaces -> <p> However <br> this is a break, because it ends with two spaces </p>
|
||||||
|
|
||||||
Double returns also
|
Double returns also
|
||||||
|
|
||||||
yields new paragraphs -> <p> Double returns also</p> <p> yields new paragraphs </p>
|
yields new paragraphs -> <p> Double returns also</p> <p> yields new paragraphs </p>
|
||||||
|
|
||||||
|
|
||||||
*italic* -> <em>italic</em>
|
*italic* -> <em>italic</em>
|
||||||
**bold** -> <strong>bold</strong>
|
**bold** -> <strong>bold</strong>
|
||||||
***italic bold*** -> <strong><em>italic bold</em></strong>
|
***italic bold*** -> <strong><em>italic bold</em></strong>
|
||||||
|
|
||||||
hello **world** -> [TextClass: hello, BoldClass: world]
|
hello **world** -> [TextClass: hello, BoldClass: world]
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
|
|
||||||
|
|
||||||
# Hello world in an h1 tag
|
# Hello world in an h1 tag
|
||||||
|
|
||||||
|
|
||||||
## This is a h2 tag
|
## This is a h2 tag
|
||||||
|
|
||||||
|
|
||||||
### h3
|
### h3
|
||||||
|
|
||||||
|
|
||||||
#### h4
|
#### h4
|
||||||
|
|
||||||
##### h5
|
##### h5
|
||||||
|
|
||||||
###### h6
|
###### h6
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user