Merge pull request #42 from progsource/latex-support

Latex support
This commit is contained in:
Petra Baranski
2023-07-27 15:34:47 +02:00
committed by GitHub
7 changed files with 291 additions and 6 deletions

4
.gitignore vendored
View File

@@ -161,10 +161,6 @@ tags
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history
### Xcode ###

View File

@@ -24,6 +24,7 @@ maddy uses [semver versioning](https://semver.org/).
* ![**DEPRECATED**](https://img.shields.io/badge/-DEPRECATED-%23666) config flags `isEmphasizedParserEnabled` and `isHTMLWrappedInParagraph`
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) config flag `enabledParsers` to en-/disable each parser separately
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) class attribute to code blocks if there is text after the three backticks like ` ```cpp`
* ![**ADDED**](https://img.shields.io/badge/-ADDED-%23099) optional support for latex blocks - it's off by default
* ?
## version 1.1.2 2020-10-04

View File

@@ -220,6 +220,18 @@ results in
<pre><code>
some code
</code></pre>
```
```cpp
int a = 42;
```
results in
```html
<pre class="cpp"><code>
int a = 42;
</code></pre>
```
## Inline code
@@ -364,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
```

View 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

View File

@@ -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 ||

View File

@@ -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

View 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);
}