mirror of
https://github.com/progsource/maddy.git
synced 2026-03-25 07:50:39 +01:00
feat: add optional latex block support
This commit is contained in:
@@ -24,6 +24,7 @@ maddy uses [semver versioning](https://semver.org/).
|
||||
*  config flags `isEmphasizedParserEnabled` and `isHTMLWrappedInParagraph`
|
||||
*  config flag `enabledParsers` to en-/disable each parser separately
|
||||
*  class attribute to code blocks if there is text after the three backticks like ` ```cpp`
|
||||
*  optional support for latex blocks - it's off by default
|
||||
* ?
|
||||
|
||||
## version 1.1.2 2020-10-04
|
||||
|
||||
@@ -376,3 +376,29 @@ becomes
|
||||
</table>
|
||||
```
|
||||
table header and footer are optional
|
||||
|
||||
## LaTeX(MathJax) block support
|
||||
|
||||
To turn on the LaTeX support - which basically is only a
|
||||
[MathJax](https://www.mathjax.org/) support and makes sure, that formulas aren't
|
||||
internally checked for other parsers - it has to be enabled in config:
|
||||
|
||||
```cpp
|
||||
std::shared_ptr<maddy::ParserConfig> config = std::make_shared<maddy::ParserConfig>();
|
||||
config->enabledParsers |= maddy::types::LATEX_BLOCK_PARSER;
|
||||
|
||||
std::shared_ptr<maddy::Parser> parser = std::make_shared<maddy::Parser>(config);
|
||||
std::string htmlOutput = parser->Parse(markdownInput);
|
||||
```
|
||||
|
||||
After this you can do the following in Markdown:
|
||||
|
||||
```
|
||||
$$x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.$$
|
||||
```
|
||||
|
||||
Which results in
|
||||
|
||||
```html
|
||||
$$x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.$$\n
|
||||
```
|
||||
|
||||
135
include/maddy/latexblockparser.h
Normal file
135
include/maddy/latexblockparser.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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 {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* LatexBlockParser
|
||||
*
|
||||
* Support for https://www.mathjax.org/
|
||||
* Be aware, that if you want to make MathJax work, you need also their
|
||||
* JavaScript library added to your HTML code.
|
||||
* maddy does not itself add that code to be more flexible in how you write your
|
||||
* head and full body.
|
||||
*
|
||||
* From Markdown: `$$` surrounded text
|
||||
*
|
||||
* ```
|
||||
* $$some formula
|
||||
* $$
|
||||
* ```
|
||||
*
|
||||
* To HTML:
|
||||
*
|
||||
* ```
|
||||
* $$some formula
|
||||
* $$
|
||||
* ```
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
class LatexBlockParser : public BlockParser
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* ctor
|
||||
*
|
||||
* @method
|
||||
* @param {std::function<void(std::string&)>} parseLineCallback
|
||||
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
||||
*/
|
||||
LatexBlockParser(
|
||||
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 two dollars, then it is a latex block.
|
||||
*
|
||||
* ```
|
||||
* $$
|
||||
* ```
|
||||
*
|
||||
* @method
|
||||
* @param {const std::string&} line
|
||||
* @return {bool}
|
||||
*/
|
||||
static bool
|
||||
IsStartingLine(const std::string& line)
|
||||
{
|
||||
static std::regex re("^(?:\\$){2}(.*)$");
|
||||
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 (!this->isStarted && line.substr(0, 2) == "$$")
|
||||
{
|
||||
this->isStarted = true;
|
||||
this->isFinished = false;
|
||||
}
|
||||
|
||||
if (this->isStarted && !this->isFinished && line.size() > 1 && line.substr(line.size() - 2, 2) == "$$")
|
||||
{
|
||||
this->isFinished = true;
|
||||
this->isStarted = false;
|
||||
}
|
||||
|
||||
line += "\n";
|
||||
}
|
||||
|
||||
private:
|
||||
bool isStarted;
|
||||
bool isFinished;
|
||||
}; // class LatexBlockParser
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
} // namespace maddy
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "maddy/headlineparser.h"
|
||||
#include "maddy/horizontallineparser.h"
|
||||
#include "maddy/htmlparser.h"
|
||||
#include "maddy/latexblockparser.h"
|
||||
#include "maddy/orderedlistparser.h"
|
||||
#include "maddy/paragraphparser.h"
|
||||
#include "maddy/quoteparser.h"
|
||||
@@ -259,6 +260,17 @@ private:
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
else if (
|
||||
this->config &&
|
||||
(this->config->enabledParsers & maddy::types::LATEX_BLOCK_PARSER) != 0 &&
|
||||
maddy::LatexBlockParser::IsStartingLine(line)
|
||||
)
|
||||
{
|
||||
parser = std::make_shared<LatexBlockParser>(
|
||||
nullptr,
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
else if (
|
||||
(
|
||||
!this->config ||
|
||||
|
||||
@@ -41,9 +41,10 @@ enum PARSER_TYPE : uint32_t
|
||||
STRONG_PARSER = 0b1000000000000000,
|
||||
TABLE_PARSER = 0b10000000000000000,
|
||||
UNORDERED_LIST_PARSER = 0b100000000000000000,
|
||||
LATEX_BLOCK_PARSER = 0b1000000000000000000,
|
||||
|
||||
DEFAULT = 0b111111111110111111,
|
||||
ALL = 0b111111111111111111,
|
||||
DEFAULT = 0b0111111111110111111,
|
||||
ALL = 0b1111111111111111111,
|
||||
};
|
||||
|
||||
} // namespace types
|
||||
|
||||
102
tests/maddy/test_maddy_latexblockparser.cpp
Normal file
102
tests/maddy/test_maddy_latexblockparser.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#include <memory>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
#include "maddy/latexblockparser.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class MADDY_LATEXBLOCKPARSER : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
std::shared_ptr<maddy::LatexBlockParser> lbParser;
|
||||
|
||||
void
|
||||
SetUp() override
|
||||
{
|
||||
this->lbParser = std::make_shared<maddy::LatexBlockParser>(
|
||||
nullptr,
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
TEST_F(MADDY_LATEXBLOCKPARSER, IsStartingLineReturnsTrueWhenFacedWithTwoDollars)
|
||||
{
|
||||
ASSERT_TRUE(maddy::LatexBlockParser::IsStartingLine("$$"));
|
||||
}
|
||||
|
||||
TEST_F(MADDY_LATEXBLOCKPARSER, IsFinishedReturnsFalseInTheBeginning)
|
||||
{
|
||||
ASSERT_FALSE(lbParser->IsFinished());
|
||||
}
|
||||
|
||||
TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesOneLineMarkdownWithALatexBlock)
|
||||
{
|
||||
std::vector<std::string> markdown = {
|
||||
"$$x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.$$"
|
||||
};
|
||||
|
||||
std::string expected = "$$x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.$$\n";
|
||||
|
||||
for (std::string md : markdown)
|
||||
{
|
||||
lbParser->AddLine(md);
|
||||
}
|
||||
ASSERT_TRUE(lbParser->IsFinished());
|
||||
|
||||
std::stringstream& output(lbParser->GetResult());
|
||||
const std::string& outputString = output.str();
|
||||
|
||||
ASSERT_EQ(expected, outputString);
|
||||
}
|
||||
|
||||
TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesABlockMarkdownWithALatexBlock)
|
||||
{
|
||||
std::vector<std::string> markdown = {
|
||||
"$$",
|
||||
"x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.",
|
||||
"$$"
|
||||
};
|
||||
|
||||
std::string expected = "$$\nx = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.\n$$\n";
|
||||
|
||||
for (std::string md : markdown)
|
||||
{
|
||||
lbParser->AddLine(md);
|
||||
}
|
||||
ASSERT_TRUE(lbParser->IsFinished());
|
||||
|
||||
std::stringstream& output(lbParser->GetResult());
|
||||
const std::string& outputString = output.str();
|
||||
|
||||
ASSERT_EQ(expected, outputString);
|
||||
}
|
||||
|
||||
TEST_F(MADDY_LATEXBLOCKPARSER, ItReplacesAMultilineBlockMarkdownWithALatexBlock)
|
||||
{
|
||||
std::vector<std::string> markdown = {
|
||||
"$$",
|
||||
"x = {-b \\pm \\sqrt{b^2-4ac}",
|
||||
"\\over 2a}.$$"
|
||||
};
|
||||
|
||||
std::string expected = "$$\nx = {-b \\pm \\sqrt{b^2-4ac}\n\\over 2a}.$$\n";
|
||||
|
||||
for (std::string md : markdown)
|
||||
{
|
||||
lbParser->AddLine(md);
|
||||
}
|
||||
ASSERT_TRUE(lbParser->IsFinished());
|
||||
|
||||
std::stringstream& output(lbParser->GetResult());
|
||||
const std::string& outputString = output.str();
|
||||
|
||||
ASSERT_EQ(expected, outputString);
|
||||
}
|
||||
Reference in New Issue
Block a user