mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2024-11-14 04:57:21 +01:00
Added maddy and switched to markdown from bbcode in ListPage.
This commit is contained in:
parent
e20f1c98a2
commit
6c56380d90
@ -1,10 +1,28 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <memory>
|
||||||
|
#include <maddy/parser.h>
|
||||||
|
|
||||||
void Utils::newline_to_br(std::string *str) {
|
void Utils::newline_to_br(std::string *str) {
|
||||||
str_replace(str, "\r\n", "<br>");
|
str_replace(str, "\r\n", "<br>");
|
||||||
str_replace(str, "\n", "<br>");
|
str_replace(str, "\n", "<br>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Utils::markdown_to_html(std::string *str) {
|
||||||
|
std::shared_ptr<maddy::ParserConfig> config = std::make_shared<maddy::ParserConfig>();
|
||||||
|
config->isEmphasizedParserEnabled = true;
|
||||||
|
config->isHTMLWrappedInParagraph = true;
|
||||||
|
|
||||||
|
std::shared_ptr<maddy::Parser> parser = std::make_shared<maddy::Parser>(config);
|
||||||
|
|
||||||
|
std::stringstream ss((*str));
|
||||||
|
|
||||||
|
std::string htmlOutput = parser->Parse(ss);
|
||||||
|
|
||||||
|
(*str) = htmlOutput;
|
||||||
|
}
|
||||||
|
|
||||||
void Utils::bbcode_evaluate_simple(std::string *str) {
|
void Utils::bbcode_evaluate_simple(std::string *str) {
|
||||||
bbcpp::BBDocumentPtr doc = bbcode((*str));
|
bbcpp::BBDocumentPtr doc = bbcode((*str));
|
||||||
|
|
||||||
|
@ -5,11 +5,14 @@
|
|||||||
|
|
||||||
#include <bbcpp/BBDocument.h>
|
#include <bbcpp/BBDocument.h>
|
||||||
|
|
||||||
|
|
||||||
class Utils {
|
class Utils {
|
||||||
public:
|
public:
|
||||||
static void newline_to_br(std::string *str);
|
static void newline_to_br(std::string *str);
|
||||||
//htmlspecialchars
|
//htmlspecialchars
|
||||||
|
|
||||||
|
static void markdown_to_html(std::string *str);
|
||||||
|
|
||||||
static void bbcode_evaluate_simple(std::string *str);
|
static void bbcode_evaluate_simple(std::string *str);
|
||||||
static bbcpp::BBDocumentPtr bbcode(const std::string &str);
|
static bbcpp::BBDocumentPtr bbcode(const std::string &str);
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
RapidJSON 0ccdbf364c577803e2a751f5aededce935314313
|
RapidJSON 0ccdbf364c577803e2a751f5aededce935314313
|
||||||
brynet b0d13e7419628d0f7051a2bb310daaf8a506e08b
|
brynet b0d13e7419628d0f7051a2bb310daaf8a506e08b
|
||||||
rapidxml 1.13
|
rapidxml 1.13
|
||||||
bbcpp a035c4942ed9e5277833fe80e444406f959c3d88
|
bbcpp a035c4942ed9e5277833fe80e444406f959c3d88
|
||||||
|
maddy adb1a910d4aadea09cb7b200f2ec204f61214596
|
18
libs/maddy/LICENSE
Normal file
18
libs/maddy/LICENSE
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Copyright 2017, 2018, 2019, 2020 M. Petra Baranski
|
||||||
|
|
||||||
|
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 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.
|
82
libs/maddy/README.md
Normal file
82
libs/maddy/README.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# maddy
|
||||||
|
|
||||||
|
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
||||||
|
[![Version: 1.1.2](https://img.shields.io/badge/Version-1.1.2-brightgreen.svg)](https://semver.org/)
|
||||||
|
[![Travis Build Status](https://travis-ci.org/progsource/maddy.svg?branch=master)](https://travis-ci.org/progsource/maddy)
|
||||||
|
[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/04m0lg27kigv1pg8/branch/master?svg=true)](https://ci.appveyor.com/project/progsource/maddy/branch/master)
|
||||||
|
|
||||||
|
maddy is a C++ Markdown to HTML **header-only** parser library.
|
||||||
|
|
||||||
|
## Supported OS
|
||||||
|
|
||||||
|
It actually should work on any OS, that supports the C++14 standard library.
|
||||||
|
|
||||||
|
It is tested to work on:
|
||||||
|
|
||||||
|
* Linux (gcc)
|
||||||
|
* OSX (clang)
|
||||||
|
* Windows (Visual Studio 2017)
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
* C++14
|
||||||
|
|
||||||
|
## Why maddy?
|
||||||
|
|
||||||
|
When I was needing a Markdown parser in C++ I couldn't find any, that was
|
||||||
|
fitting my needs. So I simply wrote my own one.
|
||||||
|
|
||||||
|
## Markdown syntax
|
||||||
|
|
||||||
|
The supported syntax can be found in the [definitions docs](docs/definitions.md).
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
To use maddy in your project, simply add the include path of maddy to yours
|
||||||
|
and in the code, you can then do the following:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "maddy/parser.h"
|
||||||
|
|
||||||
|
std::stringstream markdownInput("");
|
||||||
|
|
||||||
|
// config is optional
|
||||||
|
std::shared_ptr<maddy::ParserConfig> config = std::make_shared<maddy::ParserConfig>();
|
||||||
|
config->isEmphasizedParserEnabled = true; // default
|
||||||
|
config->isHTMLWrappedInParagraph = true; // default
|
||||||
|
|
||||||
|
std::shared_ptr<maddy::Parser> parser = std::make_shared<maddy::Parser>(config);
|
||||||
|
std::string htmlOutput = parser->Parse(markdownInput);
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to run the tests
|
||||||
|
|
||||||
|
*(tested on Linux with
|
||||||
|
[git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and
|
||||||
|
[cmake](https://cmake.org/install/) installed)*
|
||||||
|
|
||||||
|
Open your preferred terminal and type:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git clone https://github.com/progsource/maddy.git
|
||||||
|
cd maddy
|
||||||
|
git submodule update --init --recursive
|
||||||
|
mkdir tmp
|
||||||
|
cd tmp
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make test # or run the executable in ../build/MaddyTests
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to contribute
|
||||||
|
|
||||||
|
There are different possibilities:
|
||||||
|
|
||||||
|
* [Create a GitHub issue](https://github.com/progsource/maddy/issues/new)
|
||||||
|
* Create a pull request with an own branch (don't forget to put yourself in the
|
||||||
|
AUTHORS file)
|
||||||
|
|
||||||
|
Please also read [CONTRIBUTING.md](CONTRIBUTING.md).
|
203
libs/maddy/blockparser.h
Normal file
203
libs/maddy/blockparser.h
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
// windows compatibility includes
|
||||||
|
#include <cctype>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BlockParser
|
||||||
|
*
|
||||||
|
* The code expects every child to have the following static function to be
|
||||||
|
* implemented:
|
||||||
|
* `static bool IsStartingLine(const std::string& line)`
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
BlockParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: result("", std::ios_base::ate | std::ios_base::in | std::ios_base::out)
|
||||||
|
, childParser(nullptr)
|
||||||
|
, parseLineCallback(parseLineCallback)
|
||||||
|
, getBlockParserForLineCallback(getBlockParserForLineCallback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dtor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
*/
|
||||||
|
virtual ~BlockParser() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AddLine
|
||||||
|
*
|
||||||
|
* Adding a line which has to be parsed.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
virtual void
|
||||||
|
AddLine(std::string& line)
|
||||||
|
{
|
||||||
|
this->parseBlock(line);
|
||||||
|
|
||||||
|
if (this->isInlineBlockAllowed() && !this->childParser)
|
||||||
|
{
|
||||||
|
this->childParser = this->getBlockParserForLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->childParser)
|
||||||
|
{
|
||||||
|
this->childParser->AddLine(line);
|
||||||
|
|
||||||
|
if (this->childParser->IsFinished())
|
||||||
|
{
|
||||||
|
this->result << this->childParser->GetResult().str();
|
||||||
|
this->childParser = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->isLineParserAllowed())
|
||||||
|
{
|
||||||
|
this->parseLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->result << line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* Check if the BlockParser is done
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
virtual bool IsFinished() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GetResult
|
||||||
|
*
|
||||||
|
* Get the parsed HTML output.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {std::stringstream}
|
||||||
|
*/
|
||||||
|
std::stringstream&
|
||||||
|
GetResult()
|
||||||
|
{
|
||||||
|
return this->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear
|
||||||
|
*
|
||||||
|
* Clear the result to reuse the parser object.
|
||||||
|
*
|
||||||
|
* It is only used by one test for now.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Clear()
|
||||||
|
{
|
||||||
|
this->result.str("");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::stringstream result;
|
||||||
|
std::shared_ptr<BlockParser> childParser;
|
||||||
|
|
||||||
|
virtual bool isInlineBlockAllowed() const = 0;
|
||||||
|
virtual bool isLineParserAllowed() const = 0;
|
||||||
|
virtual void parseBlock(std::string& line) = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
parseLine(std::string& line)
|
||||||
|
{
|
||||||
|
if (parseLineCallback)
|
||||||
|
{
|
||||||
|
parseLineCallback(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
getIndentationWidth(const std::string& line) const
|
||||||
|
{
|
||||||
|
bool hasMetNonSpace = false;
|
||||||
|
|
||||||
|
uint32_t indentation = static_cast<uint32_t>(
|
||||||
|
std::count_if(
|
||||||
|
line.begin(),
|
||||||
|
line.end(),
|
||||||
|
[&hasMetNonSpace](unsigned char c)
|
||||||
|
{
|
||||||
|
if (hasMetNonSpace)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::isspace(c))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasMetNonSpace = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return indentation;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockParser>
|
||||||
|
getBlockParserForLine(const std::string& line)
|
||||||
|
{
|
||||||
|
if (getBlockParserForLineCallback)
|
||||||
|
{
|
||||||
|
return getBlockParserForLineCallback(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::function<void(std::string&)> parseLineCallback;
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback;
|
||||||
|
}; // class BlockParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
51
libs/maddy/breaklineparser.h
Normal file
51
libs/maddy/breaklineparser.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BreakLineParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class BreakLineParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `text\r\n text`
|
||||||
|
*
|
||||||
|
* To HTML: `text<br> text`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re(R"((\r\n|\r))");
|
||||||
|
static std::string replacement = "<br>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class BreakLineParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
140
libs/maddy/checklistparser.h
Normal file
140
libs/maddy/checklistparser.h
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChecklistParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class ChecklistParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
ChecklistParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* An unordered list starts with `* `.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^- \\[[x| ]\\] .*");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
bool isStartOfNewListItem = IsStartingLine(line);
|
||||||
|
uint32_t indentation = getIndentationWidth(line);
|
||||||
|
|
||||||
|
static std::regex lineRegex("^(- )");
|
||||||
|
line = std::regex_replace(line, lineRegex, "");
|
||||||
|
|
||||||
|
static std::regex emptyBoxRegex("^\\[ \\]");
|
||||||
|
static std::string emptyBoxReplacement = "<input type=\"checkbox\"/>";
|
||||||
|
line = std::regex_replace(line, emptyBoxRegex, emptyBoxReplacement);
|
||||||
|
|
||||||
|
static std::regex boxRegex("^\\[x\\]");
|
||||||
|
static std::string boxReplacement = "<input type=\"checkbox\" checked=\"checked\"/>";
|
||||||
|
line = std::regex_replace(line, boxRegex, boxReplacement);
|
||||||
|
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
line = "<ul class=\"checklist\"><li><label>" + line;
|
||||||
|
this->isStarted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indentation >= 2)
|
||||||
|
{
|
||||||
|
line = line.substr(2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
line.empty() ||
|
||||||
|
line.find("</label></li><li><label>") != std::string::npos ||
|
||||||
|
line.find("</label></li></ul>") != std::string::npos
|
||||||
|
)
|
||||||
|
{
|
||||||
|
line = "</label></li></ul>" + line;
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStartOfNewListItem)
|
||||||
|
{
|
||||||
|
line = "</label></li><li><label>" + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
}; // class ChecklistParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
137
libs/maddy/codeblockparser.h
Normal file
137
libs/maddy/codeblockparser.h
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CodeBlockParser
|
||||||
|
*
|
||||||
|
* From Markdown: 3 times surrounded code (without space in the beginning)
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* ```
|
||||||
|
* some code
|
||||||
|
* ```
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* To HTML:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <pre><code>
|
||||||
|
* some code
|
||||||
|
* </code></pre>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class CodeBlockParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
CodeBlockParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line starts with three code signs, then it is a code block.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* ```
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^(?:`){3}$");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
if (line == "```")
|
||||||
|
{
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
line = "<pre><code>\n";
|
||||||
|
this->isStarted = true;
|
||||||
|
this->isFinished = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line = "</code></pre>";
|
||||||
|
this->isFinished = true;
|
||||||
|
this->isStarted = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
}; // class CodeBlockParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
53
libs/maddy/emphasizedparser.h
Normal file
53
libs/maddy/emphasizedparser.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EmphasizedParser
|
||||||
|
*
|
||||||
|
* Has to be used after the `StrongParser`.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class EmphasizedParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `text _text_`
|
||||||
|
*
|
||||||
|
* To HTML: `text <em>text</em>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("(?!.*`.*|.*<code>.*)_(?!.*`.*|.*<\\/code>.*)([^_]*)_(?!.*`.*|.*<\\/code>.*)");
|
||||||
|
static std::string replacement = "<em>$1</em>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class EmphasizedParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
138
libs/maddy/headlineparser.h
Normal file
138
libs/maddy/headlineparser.h
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HeadlineParser
|
||||||
|
*
|
||||||
|
* From Markdown:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* # Headline 1
|
||||||
|
* ## Headline 2
|
||||||
|
* ### Headline 3
|
||||||
|
* #### Headline 4
|
||||||
|
* ##### Headline 5
|
||||||
|
* ###### Headline 6
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* To HTML:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <h1>Headline 1</h1>
|
||||||
|
* <h2>Headline 2</h2>
|
||||||
|
* <h3>Headline 3</h3>
|
||||||
|
* <h4>Headline 4</h4>
|
||||||
|
* <h5>Headline 5</h5>
|
||||||
|
* <h6>Headline 6</h6>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class HeadlineParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
HeadlineParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line starts with 1 - 6 `#`, then it is a headline.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^(?:#){1,6} (.*)");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* The headline is always only one line long, so this method always returns
|
||||||
|
* true.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::vector<std::regex> hlRegex = {
|
||||||
|
std::regex("^# (.*)")
|
||||||
|
, std::regex("^(?:#){2} (.*)")
|
||||||
|
, std::regex("^(?:#){3} (.*)")
|
||||||
|
, std::regex("^(?:#){4} (.*)")
|
||||||
|
, std::regex("^(?:#){5} (.*)")
|
||||||
|
, std::regex("^(?:#){6} (.*)")
|
||||||
|
};
|
||||||
|
static std::vector<std::string> hlReplacement = {
|
||||||
|
"<h1>$1</h1>"
|
||||||
|
, "<h2>$1</h2>"
|
||||||
|
, "<h3>$1</h3>"
|
||||||
|
, "<h4>$1</h4>"
|
||||||
|
, "<h5>$1</h5>"
|
||||||
|
, "<h6>$1</h6>"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
line = std::regex_replace(line, hlRegex[i], hlReplacement[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}; // class HeadlineParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
106
libs/maddy/horizontallineparser.h
Normal file
106
libs/maddy/horizontallineparser.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HorizontalLineParser
|
||||||
|
*
|
||||||
|
* From Markdown: `---`
|
||||||
|
*
|
||||||
|
* To HTML: `<hr/>`
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class HorizontalLineParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
HorizontalLineParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, lineRegex("^---$")
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line has exact three dashes `---`, then it is a horizontal line.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^---$");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* The horizontal line is always only one line long, so this method always
|
||||||
|
* returns true.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::string replacement = "<hr/>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, lineRegex, replacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::regex lineRegex;
|
||||||
|
}; // class HorizontalLineParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
127
libs/maddy/htmlparser.h
Normal file
127
libs/maddy/htmlparser.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HtmlParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class HtmlParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
HtmlParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
, isGreaterThanFound(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line is starting with `<`, HTML is expected to follow.
|
||||||
|
* Nothing after that will be parsed, it only is copied.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
return line[0] == '<';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* `>` followed by an empty line will end the HTML block.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
this->isStarted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line.empty() && line[line.size() - 1] == '>')
|
||||||
|
{
|
||||||
|
this->isGreaterThanFound = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.empty() && this->isGreaterThanFound)
|
||||||
|
{
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line.empty() && this->isGreaterThanFound)
|
||||||
|
{
|
||||||
|
this->isGreaterThanFound = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!line.empty())
|
||||||
|
{
|
||||||
|
line += " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
bool isGreaterThanFound;
|
||||||
|
}; // class HtmlParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
53
libs/maddy/imageparser.h
Normal file
53
libs/maddy/imageparser.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ImageParser
|
||||||
|
*
|
||||||
|
* Has to be used before the `LinkParser`.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class ImageParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `![text](http://example.com/a.png)`
|
||||||
|
*
|
||||||
|
* To HTML: `<img src="http://example.com/a.png" alt="text"/>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("\\!\\[([^\\]]*)\\]\\(([^\\]]*)\\)");
|
||||||
|
static std::string replacement = "<img src=\"$2\" alt=\"$1\"/>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class ImageParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
51
libs/maddy/inlinecodeparser.h
Normal file
51
libs/maddy/inlinecodeparser.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InlineCodeParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class InlineCodeParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `text `some code``
|
||||||
|
*
|
||||||
|
* To HTML: `text <code>some code</code>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("`([^`]*)`");
|
||||||
|
static std::string replacement = "<code>$1</code>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class InlineCodeParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
50
libs/maddy/italicparser.h
Normal file
50
libs/maddy/italicparser.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ItalicParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class ItalicParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `text *text*`
|
||||||
|
*
|
||||||
|
* To HTML: `text <i>text</i>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
std::regex re("(?!.*`.*|.*<code>.*)\\*(?!.*`.*|.*<\\/code>.*)([^\\*]*)\\*(?!.*`.*|.*<\\/code>.*)");
|
||||||
|
static std::string replacement = "<i>$1</i>";
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class ItalicParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
46
libs/maddy/lineparser.h
Normal file
46
libs/maddy/lineparser.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LineParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* dtor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
*/
|
||||||
|
virtual ~LineParser() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown to HTML
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
virtual void Parse(std::string& line) = 0;
|
||||||
|
}; // class LineParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
53
libs/maddy/linkparser.h
Normal file
53
libs/maddy/linkparser.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LinkParser
|
||||||
|
*
|
||||||
|
* Has to be used after the `ImageParser`.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class LinkParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `[text](http://example.com)`
|
||||||
|
*
|
||||||
|
* To HTML: `<a href="http://example.com">text</a>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("\\[([^\\]]*)\\]\\(([^\\]]*)\\)");
|
||||||
|
static std::string replacement = "<a href=\"$2\">$1</a>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class LinkParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
142
libs/maddy/orderedlistparser.h
Normal file
142
libs/maddy/orderedlistparser.h
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OrderedListParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class OrderedListParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
OrderedListParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* An ordered list starts with `1. `.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^1\\. .*");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
bool isStartOfNewListItem = this->isStartOfNewListItem(line);
|
||||||
|
uint32_t indentation = getIndentationWidth(line);
|
||||||
|
|
||||||
|
static std::regex orderedlineRegex("^[1-9]+[0-9]*\\. ");
|
||||||
|
line = std::regex_replace(line, orderedlineRegex, "");
|
||||||
|
static std::regex unorderedlineRegex("^\\* ");
|
||||||
|
line = std::regex_replace(line, unorderedlineRegex, "");
|
||||||
|
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
line = "<ol><li>" + line;
|
||||||
|
this->isStarted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indentation >= 2)
|
||||||
|
{
|
||||||
|
line = line.substr(2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
line.empty() ||
|
||||||
|
line.find("</li><li>") != std::string::npos ||
|
||||||
|
line.find("</li></ol>") != std::string::npos ||
|
||||||
|
line.find("</li></ul>") != std::string::npos
|
||||||
|
)
|
||||||
|
{
|
||||||
|
line = "</li></ol>" + line;
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStartOfNewListItem)
|
||||||
|
{
|
||||||
|
line = "</li><li>" + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
|
||||||
|
bool
|
||||||
|
isStartOfNewListItem(const std::string& line) const
|
||||||
|
{
|
||||||
|
static std::regex re("^(?:[1-9]+[0-9]*\\. |\\* ).*");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
}; // class OrderedListParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
115
libs/maddy/paragraphparser.h
Normal file
115
libs/maddy/paragraphparser.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ParagraphParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class ParagraphParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
ParagraphParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line is not empty, it will be a paragraph.
|
||||||
|
*
|
||||||
|
* This block parser has to always run as the last one!
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
return !line.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* An empty line will end the paragraph.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
line = "<p>" + line + " ";
|
||||||
|
this->isStarted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.empty())
|
||||||
|
{
|
||||||
|
line += "</p>";
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line += " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
}; // class ParagraphParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
294
libs/maddy/parser.h
Normal file
294
libs/maddy/parser.h
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "maddy/parserconfig.h"
|
||||||
|
|
||||||
|
// BlockParser
|
||||||
|
#include "maddy/checklistparser.h"
|
||||||
|
#include "maddy/codeblockparser.h"
|
||||||
|
#include "maddy/headlineparser.h"
|
||||||
|
#include "maddy/horizontallineparser.h"
|
||||||
|
#include "maddy/htmlparser.h"
|
||||||
|
#include "maddy/orderedlistparser.h"
|
||||||
|
#include "maddy/paragraphparser.h"
|
||||||
|
#include "maddy/quoteparser.h"
|
||||||
|
#include "maddy/tableparser.h"
|
||||||
|
#include "maddy/unorderedlistparser.h"
|
||||||
|
|
||||||
|
// LineParser
|
||||||
|
#include "maddy/breaklineparser.h"
|
||||||
|
#include "maddy/emphasizedparser.h"
|
||||||
|
#include "maddy/imageparser.h"
|
||||||
|
#include "maddy/inlinecodeparser.h"
|
||||||
|
#include "maddy/italicparser.h"
|
||||||
|
#include "maddy/linkparser.h"
|
||||||
|
#include "maddy/strikethroughparser.h"
|
||||||
|
#include "maddy/strongparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser
|
||||||
|
*
|
||||||
|
* Transforms Markdown to HTML
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class Parser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* Initializes all `LineParser`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
*/
|
||||||
|
Parser(std::shared_ptr<ParserConfig> config = nullptr)
|
||||||
|
: config(config)
|
||||||
|
, breakLineParser(std::make_shared<BreakLineParser>())
|
||||||
|
, emphasizedParser(std::make_shared<EmphasizedParser>())
|
||||||
|
, imageParser(std::make_shared<ImageParser>())
|
||||||
|
, inlineCodeParser(std::make_shared<InlineCodeParser>())
|
||||||
|
, italicParser(std::make_shared<ItalicParser>())
|
||||||
|
, linkParser(std::make_shared<LinkParser>())
|
||||||
|
, strikeThroughParser(std::make_shared<StrikeThroughParser>())
|
||||||
|
, strongParser(std::make_shared<StrongParser>())
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::istream&} markdown
|
||||||
|
* @return {std::string} HTML
|
||||||
|
*/
|
||||||
|
std::string
|
||||||
|
Parse(std::istream& markdown) const
|
||||||
|
{
|
||||||
|
std::string result = "";
|
||||||
|
std::shared_ptr<BlockParser> currentBlockParser = nullptr;
|
||||||
|
|
||||||
|
for (std::string line; std::getline(markdown, line);)
|
||||||
|
{
|
||||||
|
if (!currentBlockParser)
|
||||||
|
{
|
||||||
|
currentBlockParser = getBlockParserForLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentBlockParser)
|
||||||
|
{
|
||||||
|
currentBlockParser->AddLine(line);
|
||||||
|
|
||||||
|
if (currentBlockParser->IsFinished())
|
||||||
|
{
|
||||||
|
result += currentBlockParser->GetResult().str();
|
||||||
|
currentBlockParser = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure, that all parsers are finished
|
||||||
|
if (currentBlockParser)
|
||||||
|
{
|
||||||
|
std::string emptyLine = "";
|
||||||
|
currentBlockParser->AddLine(emptyLine);
|
||||||
|
if (currentBlockParser->IsFinished())
|
||||||
|
{
|
||||||
|
result += currentBlockParser->GetResult().str();
|
||||||
|
currentBlockParser = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<ParserConfig> config;
|
||||||
|
std::shared_ptr<BreakLineParser> breakLineParser;
|
||||||
|
std::shared_ptr<EmphasizedParser> emphasizedParser;
|
||||||
|
std::shared_ptr<ImageParser> imageParser;
|
||||||
|
std::shared_ptr<InlineCodeParser> inlineCodeParser;
|
||||||
|
std::shared_ptr<ItalicParser> italicParser;
|
||||||
|
std::shared_ptr<LinkParser> linkParser;
|
||||||
|
std::shared_ptr<StrikeThroughParser> strikeThroughParser;
|
||||||
|
std::shared_ptr<StrongParser> strongParser;
|
||||||
|
|
||||||
|
// block parser have to run before
|
||||||
|
void
|
||||||
|
runLineParser(std::string& line) const
|
||||||
|
{
|
||||||
|
// Attention! ImageParser has to be before LinkParser
|
||||||
|
this->imageParser->Parse(line);
|
||||||
|
this->linkParser->Parse(line);
|
||||||
|
|
||||||
|
// Attention! StrongParser has to be before EmphasizedParser
|
||||||
|
this->strongParser->Parse(line);
|
||||||
|
|
||||||
|
if (!this->config || this->config->isEmphasizedParserEnabled)
|
||||||
|
{
|
||||||
|
this->emphasizedParser->Parse(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->strikeThroughParser->Parse(line);
|
||||||
|
|
||||||
|
this->inlineCodeParser->Parse(line);
|
||||||
|
|
||||||
|
this->italicParser->Parse(line);
|
||||||
|
|
||||||
|
this->breakLineParser->Parse(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockParser>
|
||||||
|
getBlockParserForLine(const std::string& line) const
|
||||||
|
{
|
||||||
|
std::shared_ptr<BlockParser> parser;
|
||||||
|
|
||||||
|
if (maddy::CodeBlockParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::CodeBlockParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (maddy::HeadlineParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::HeadlineParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (maddy::HorizontalLineParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::HorizontalLineParser>(
|
||||||
|
nullptr,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (maddy::QuoteParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::QuoteParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
[this](const std::string& line){ return this->getBlockParserForLine(line); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (maddy::TableParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::TableParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (maddy::ChecklistParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createChecklistParser();
|
||||||
|
}
|
||||||
|
else if (maddy::OrderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createOrderedListParser();
|
||||||
|
}
|
||||||
|
else if (maddy::UnorderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createUnorderedListParser();
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
this->config &&
|
||||||
|
!this->config->isHTMLWrappedInParagraph &&
|
||||||
|
maddy::HtmlParser::IsStartingLine(line)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::HtmlParser>(nullptr, nullptr);
|
||||||
|
}
|
||||||
|
else if (maddy::ParagraphParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = std::make_shared<maddy::ParagraphParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockParser>
|
||||||
|
createChecklistParser() const
|
||||||
|
{
|
||||||
|
return std::make_shared<maddy::ChecklistParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
[this](const std::string& line)
|
||||||
|
{
|
||||||
|
std::shared_ptr<BlockParser> parser;
|
||||||
|
|
||||||
|
if (maddy::ChecklistParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createChecklistParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockParser>
|
||||||
|
createOrderedListParser() const
|
||||||
|
{
|
||||||
|
return std::make_shared<maddy::OrderedListParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
[this](const std::string& line)
|
||||||
|
{
|
||||||
|
std::shared_ptr<BlockParser> parser;
|
||||||
|
|
||||||
|
if (maddy::OrderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createOrderedListParser();
|
||||||
|
}
|
||||||
|
else if (maddy::UnorderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createUnorderedListParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<BlockParser>
|
||||||
|
createUnorderedListParser() const
|
||||||
|
{
|
||||||
|
return std::make_shared<maddy::UnorderedListParser>(
|
||||||
|
[this](std::string& line){ this->runLineParser(line); },
|
||||||
|
[this](const std::string& line)
|
||||||
|
{
|
||||||
|
std::shared_ptr<BlockParser> parser;
|
||||||
|
|
||||||
|
if (maddy::OrderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createOrderedListParser();
|
||||||
|
}
|
||||||
|
else if (maddy::UnorderedListParser::IsStartingLine(line))
|
||||||
|
{
|
||||||
|
parser = this->createUnorderedListParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}; // class Parser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
31
libs/maddy/parserconfig.h
Normal file
31
libs/maddy/parserconfig.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ParserConfig
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
struct ParserConfig
|
||||||
|
{
|
||||||
|
bool isEmphasizedParserEnabled;
|
||||||
|
bool isHTMLWrappedInParagraph;
|
||||||
|
|
||||||
|
ParserConfig()
|
||||||
|
: isEmphasizedParserEnabled(true)
|
||||||
|
, isHTMLWrappedInParagraph(true)
|
||||||
|
{}
|
||||||
|
}; // class ParserConfig
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
165
libs/maddy/quoteparser.h
Normal file
165
libs/maddy/quoteparser.h
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QuoteParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class QuoteParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
QuoteParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* A quote starts with `> `.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^\\>.*");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AddLine
|
||||||
|
*
|
||||||
|
* Adding a line which has to be parsed.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
AddLine(std::string& line) override
|
||||||
|
{
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
this->result << "<blockquote>";
|
||||||
|
this->isStarted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool finish = false;
|
||||||
|
if (line.empty())
|
||||||
|
{
|
||||||
|
finish = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->parseBlock(line);
|
||||||
|
|
||||||
|
if (this->isInlineBlockAllowed() && !this->childParser)
|
||||||
|
{
|
||||||
|
this->childParser = this->getBlockParserForLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->childParser)
|
||||||
|
{
|
||||||
|
this->childParser->AddLine(line);
|
||||||
|
|
||||||
|
if (this->childParser->IsFinished())
|
||||||
|
{
|
||||||
|
this->result << this->childParser->GetResult().str();
|
||||||
|
this->childParser = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->isLineParserAllowed())
|
||||||
|
{
|
||||||
|
this->parseLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finish)
|
||||||
|
{
|
||||||
|
this->result << "</blockquote>";
|
||||||
|
this->isFinished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->result << line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex lineRegexWithSpace("^\\> ");
|
||||||
|
line = std::regex_replace(line, lineRegexWithSpace, "");
|
||||||
|
static std::regex lineRegexWithoutSpace("^\\>");
|
||||||
|
line = std::regex_replace(line, lineRegexWithoutSpace, "");
|
||||||
|
|
||||||
|
if (!line.empty())
|
||||||
|
{
|
||||||
|
line += " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
}; // class QuoteParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
51
libs/maddy/strikethroughparser.h
Normal file
51
libs/maddy/strikethroughparser.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StrikeThroughParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class StrikeThroughParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `text ~~text~~`
|
||||||
|
*
|
||||||
|
* To HTML: `text <s>text</s>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::regex re("(?!.*`.*|.*<code>.*)\\~\\~(?!.*`.*|.*<\\/code>.*)([^\\~]*)\\~\\~(?!.*`.*|.*<\\/code>.*)");
|
||||||
|
static std::string replacement = "<s>$1</s>";
|
||||||
|
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}; // class StrikeThroughParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
59
libs/maddy/strongparser.h
Normal file
59
libs/maddy/strongparser.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/lineparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StrongParser
|
||||||
|
*
|
||||||
|
* Has to be used before the `EmphasizedParser`.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class StrongParser : public LineParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Parse
|
||||||
|
*
|
||||||
|
* From Markdown: `text **text** __text__`
|
||||||
|
*
|
||||||
|
* To HTML: `text <strong>text</strong> <strong>text</strong>`
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line The line to interpret
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
Parse(std::string& line) override
|
||||||
|
{
|
||||||
|
static std::vector<std::regex> res
|
||||||
|
{
|
||||||
|
std::regex{"(?!.*`.*|.*<code>.*)\\*\\*(?!.*`.*|.*<\\/code>.*)([^\\*\\*]*)\\*\\*(?!.*`.*|.*<\\/code>.*)"},
|
||||||
|
std::regex{"(?!.*`.*|.*<code>.*)__(?!.*`.*|.*<\\/code>.*)([^__]*)__(?!.*`.*|.*<\\/code>.*)"}
|
||||||
|
};
|
||||||
|
static std::string replacement = "<strong>$1</strong>";
|
||||||
|
for (const auto& re : res)
|
||||||
|
{
|
||||||
|
line = std::regex_replace(line, re, replacement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}; // class StrongParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
246
libs/maddy/tableparser.h
Normal file
246
libs/maddy/tableparser.h
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TableParser
|
||||||
|
*
|
||||||
|
* For more information, see the docs folder.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class TableParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
TableParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
, currentBlock(0)
|
||||||
|
, currentRow(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* If the line has exact `|table>`, then it is starting the table.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::string matchString("|table>");
|
||||||
|
return line == matchString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AddLine
|
||||||
|
*
|
||||||
|
* Adding a line which has to be parsed.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::string&} line
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
AddLine(std::string& line) override
|
||||||
|
{
|
||||||
|
if (!this->isStarted && line == "|table>")
|
||||||
|
{
|
||||||
|
this->isStarted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->isStarted)
|
||||||
|
{
|
||||||
|
if (line == "- | - | -")
|
||||||
|
{
|
||||||
|
++this->currentBlock;
|
||||||
|
this->currentRow = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line == "|<table")
|
||||||
|
{
|
||||||
|
static std::string emptyLine = "";
|
||||||
|
this->parseBlock(emptyLine);
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->table.size() < this->currentBlock + 1)
|
||||||
|
{
|
||||||
|
this->table.push_back(std::vector<std::vector<std::string>>());
|
||||||
|
}
|
||||||
|
this->table[this->currentBlock].push_back(std::vector<std::string>());
|
||||||
|
|
||||||
|
std::string segment;
|
||||||
|
std::stringstream streamToSplit(line);
|
||||||
|
|
||||||
|
while (std::getline(streamToSplit, segment, '|'))
|
||||||
|
{
|
||||||
|
this->parseLine(segment);
|
||||||
|
this->table[this->currentBlock][this->currentRow].push_back(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
++this->currentRow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* A table ends with `|<table`.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string&) override
|
||||||
|
{
|
||||||
|
result << "<table>";
|
||||||
|
|
||||||
|
bool hasHeader = false;
|
||||||
|
bool hasFooter = false;
|
||||||
|
bool isFirstBlock = true;
|
||||||
|
uint32_t currentBlockNumber = 0;
|
||||||
|
|
||||||
|
if (this->table.size() > 1)
|
||||||
|
{
|
||||||
|
hasHeader = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->table.size() >= 3)
|
||||||
|
{
|
||||||
|
hasFooter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const std::vector<std::vector<std::string>>& block : this->table)
|
||||||
|
{
|
||||||
|
bool isInHeader = false;
|
||||||
|
bool isInFooter = false;
|
||||||
|
++currentBlockNumber;
|
||||||
|
|
||||||
|
if (hasHeader && isFirstBlock)
|
||||||
|
{
|
||||||
|
result << "<thead>";
|
||||||
|
isInHeader = true;
|
||||||
|
}
|
||||||
|
else if (hasFooter && currentBlockNumber == this->table.size())
|
||||||
|
{
|
||||||
|
result << "<tfoot>";
|
||||||
|
isInFooter = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result << "<tbody>";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const std::vector<std::string>& row : block)
|
||||||
|
{
|
||||||
|
result << "<tr>";
|
||||||
|
|
||||||
|
for (const std::string& column : row)
|
||||||
|
{
|
||||||
|
if (isInHeader)
|
||||||
|
{
|
||||||
|
result << "<th>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result << "<td>";
|
||||||
|
}
|
||||||
|
|
||||||
|
result << column;
|
||||||
|
|
||||||
|
if (isInHeader)
|
||||||
|
{
|
||||||
|
result << "</th>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result << "</td>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result << "</tr>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInHeader)
|
||||||
|
{
|
||||||
|
result << "</thead>";
|
||||||
|
}
|
||||||
|
else if (isInFooter)
|
||||||
|
{
|
||||||
|
result << "</tfoot>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result << "</tbody>";
|
||||||
|
}
|
||||||
|
|
||||||
|
isFirstBlock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result << "</table>";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
uint32_t currentBlock;
|
||||||
|
uint32_t currentRow;
|
||||||
|
std::vector<std::vector<std::vector<std::string>>> table;
|
||||||
|
}; // class TableParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
133
libs/maddy/unorderedlistparser.h
Normal file
133
libs/maddy/unorderedlistparser.h
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* This project is licensed under the MIT license. For more information see the
|
||||||
|
* LICENSE file.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <regex>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "maddy/blockparser.h"
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace maddy {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UnorderedListParser
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
class UnorderedListParser : public BlockParser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* ctor
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||||
|
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||||
|
*/
|
||||||
|
UnorderedListParser(
|
||||||
|
std::function<void(std::string&)> parseLineCallback,
|
||||||
|
std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
||||||
|
)
|
||||||
|
: BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
||||||
|
, isStarted(false)
|
||||||
|
, isFinished(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsStartingLine
|
||||||
|
*
|
||||||
|
* An unordered list starts with `* `.
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @param {const std::string&} line
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
IsStartingLine(const std::string& line)
|
||||||
|
{
|
||||||
|
static std::regex re("^[+*-] .*");
|
||||||
|
return std::regex_match(line, re);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IsFinished
|
||||||
|
*
|
||||||
|
* @method
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsFinished() const override
|
||||||
|
{
|
||||||
|
return this->isFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool
|
||||||
|
isInlineBlockAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isLineParserAllowed() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parseBlock(std::string& line) override
|
||||||
|
{
|
||||||
|
bool isStartOfNewListItem = IsStartingLine(line);
|
||||||
|
uint32_t indentation = getIndentationWidth(line);
|
||||||
|
|
||||||
|
static std::regex lineRegex("^([+*-] )");
|
||||||
|
line = std::regex_replace(line, lineRegex, "");
|
||||||
|
|
||||||
|
if (!this->isStarted)
|
||||||
|
{
|
||||||
|
line = "<ul><li>" + line;
|
||||||
|
this->isStarted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indentation >= 2)
|
||||||
|
{
|
||||||
|
line = line.substr(2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
line.empty() ||
|
||||||
|
line.find("</li><li>") != std::string::npos ||
|
||||||
|
line.find("</li></ol>") != std::string::npos ||
|
||||||
|
line.find("</li></ul>") != std::string::npos
|
||||||
|
)
|
||||||
|
{
|
||||||
|
line = "</li></ul>" + line;
|
||||||
|
this->isFinished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStartOfNewListItem)
|
||||||
|
{
|
||||||
|
line = "</li><li>" + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isStarted;
|
||||||
|
bool isFinished;
|
||||||
|
}; // class UnorderedListParser
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
} // namespace maddy
|
@ -73,7 +73,7 @@ void ListPage::load() {
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
Utils::newline_to_br(&fd);
|
Utils::newline_to_br(&fd);
|
||||||
Utils::bbcode_evaluate_simple(&fd);
|
Utils::markdown_to_html(&fd);
|
||||||
|
|
||||||
list_entries.push_back(fd);
|
list_entries.push_back(fd);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user