Add a Markdown to Html converted, to display help written in markdown in a wxHtmlWindow.
The help file bridget_tee_formula.md can be displayed in pcb_calculator. For Help messages, a markdown text (with some basic html tags) is often enough and is more easy to translate than full html texts.
This commit is contained in:
parent
ce62941bb8
commit
8ed49b3f68
|
@ -312,6 +312,7 @@ set( COMMON_SRCS
|
|||
lib_tree_model.cpp
|
||||
lib_tree_model_adapter.cpp
|
||||
lockfile.cpp
|
||||
../markdown2html/markdown2html.cpp
|
||||
marker_base.cpp
|
||||
md5_hash.cpp
|
||||
msgpanel.cpp
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <common.h> // EDA_UNITS_T
|
||||
#include <../common/dialogs/dialog_list_selector_base.h>
|
||||
|
||||
void ConvertMarkdown2Html( const wxString& aMarkdownInput, wxString& aHtmlOutput );
|
||||
|
||||
class EDA_DRAW_FRAME;
|
||||
|
||||
|
|
|
@ -0,0 +1,327 @@
|
|||
# Markdown Definitions
|
||||
|
||||
This specification defines which markdown syntax can be parsed by maddy.
|
||||
There is no HTML allowed in the markdown syntax - or said otherwise - it might
|
||||
destroy the output, if there was HTML in your markdown.
|
||||
|
||||
The Parser expects you to use spaces and not tabs for indentation in the
|
||||
markdown.
|
||||
|
||||
## Headlines
|
||||
|
||||
```
|
||||
# h1 heading
|
||||
## h2 heading
|
||||
### h3 heading
|
||||
#### h4 heading
|
||||
##### h5 heading
|
||||
###### h6 heading
|
||||
```
|
||||
results in:
|
||||
```html
|
||||
<h1>h1 heading</h1>
|
||||
<h2>h2 heading</h2>
|
||||
<h3>h3 heading</h3>
|
||||
<h4>h4 heading</h4>
|
||||
<h5>h5 heading</h5>
|
||||
<h6>h6 heading</h6>
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
```
|
||||
[Text of the link](http://example.com)
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<a href="http://example.com">Text of the link</a>
|
||||
```
|
||||
|
||||
## Lists
|
||||
|
||||
### unordered
|
||||
```
|
||||
|
||||
* unordered
|
||||
* list
|
||||
* items
|
||||
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<ul>
|
||||
<li>unordered</li>
|
||||
<li>list</li>
|
||||
<li>items</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
* unordered
|
||||
* list
|
||||
* items
|
||||
* in
|
||||
* an
|
||||
* hierarchy
|
||||
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<ul>
|
||||
<li>unordered
|
||||
<ul>
|
||||
<li>list</li>
|
||||
<li>items
|
||||
<ul>
|
||||
<li>in</li>
|
||||
<li>an</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>hierarchy</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
### ordered
|
||||
|
||||
```
|
||||
|
||||
1. ordered
|
||||
* list
|
||||
* items
|
||||
|
||||
```
|
||||
|
||||
results in
|
||||
|
||||
```html
|
||||
|
||||
<ol>
|
||||
<li>ordered</li>
|
||||
<li>list</li>
|
||||
<li>items</li>
|
||||
</ol>
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
1. ordered
|
||||
* list
|
||||
1. items
|
||||
* in
|
||||
1. an
|
||||
* hierarchy
|
||||
|
||||
```
|
||||
|
||||
results in
|
||||
|
||||
```html
|
||||
<ol>
|
||||
<li>ordered</li>
|
||||
<li>list
|
||||
<ol>
|
||||
<li>items</li>
|
||||
<li>in
|
||||
<ol>
|
||||
<li>an</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>hierarchy</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
```
|
||||
|
||||
### combination
|
||||
|
||||
```
|
||||
|
||||
* combination
|
||||
* of
|
||||
1. unordered and
|
||||
* ordered
|
||||
* list
|
||||
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<ul>
|
||||
<li>combination</li>
|
||||
<li>of
|
||||
<ol>
|
||||
<li>unordered and</li>
|
||||
<li>ordered</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>list</li>
|
||||
</ul>
|
||||
```
|
||||
|
||||
### checklist
|
||||
|
||||
```
|
||||
|
||||
- [ ] some item
|
||||
- [ ] another item
|
||||
- [x] some checked item
|
||||
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<ul class="checklist">
|
||||
<li><label><input type="checkbox"/>some item
|
||||
<ul class="checklist">
|
||||
<li><label><input type="checkbox"/><span>another item</label></li>
|
||||
</ul>
|
||||
</label></li>
|
||||
<li><label><input type="checkbox" checked="checked"/>some checked item</label></li>
|
||||
</ul>
|
||||
```
|
||||
might not work in combination with other lists
|
||||
|
||||
## Code Blocks
|
||||
|
||||
```
|
||||
some code
|
||||
```
|
||||
|
||||
results in
|
||||
```html
|
||||
<pre><code>
|
||||
some code
|
||||
</code></pre>
|
||||
```
|
||||
|
||||
## Inline code
|
||||
|
||||
some text `some inline code` some other text
|
||||
|
||||
results in
|
||||
```html
|
||||
some text <code>some inline code</code> some other text
|
||||
```
|
||||
|
||||
## quotes
|
||||
|
||||
```
|
||||
> Some quote
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<blockqoute>
|
||||
<p>Some quote</p>
|
||||
</blockquote>
|
||||
```
|
||||
|
||||
## bold
|
||||
|
||||
```
|
||||
**bold text**
|
||||
__bold text__
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<strong>bold text</strong>
|
||||
<strong>bold text</strong>
|
||||
```
|
||||
|
||||
## italic
|
||||
|
||||
```
|
||||
*italic text*
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<i>italic text</i>
|
||||
```
|
||||
|
||||
## emphasized
|
||||
|
||||
```
|
||||
_emphasized text_
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<em>emphasized text</em>
|
||||
```
|
||||
|
||||
## strikethrough
|
||||
|
||||
```
|
||||
~~striked through text~~
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<s>striked through text</s>
|
||||
```
|
||||
|
||||
## horizontal line
|
||||
|
||||
```
|
||||
---
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<hr/>
|
||||
```
|
||||
|
||||
## Images
|
||||
|
||||
```
|
||||
![Image alt text](http://example.com/example.png)
|
||||
```
|
||||
results in
|
||||
```html
|
||||
<img src="http://example.com/example.png" alt="Image alt text"/>
|
||||
```
|
||||
|
||||
## Tables
|
||||
|
||||
```
|
||||
|
||||
|table>
|
||||
Left header | middle header | last header
|
||||
- | - | -
|
||||
cell 1 | cell 2 | cell 3
|
||||
cell 4 | cell 5 | cell 6
|
||||
- | - | -
|
||||
foot a | foot b | foot c
|
||||
|<table
|
||||
|
||||
```
|
||||
becomes
|
||||
```html
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Left header</th>
|
||||
<th>middle header</th>
|
||||
<th>last header</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>cell 1</td>
|
||||
<td>cell 2</td>
|
||||
<td>cell 3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>cell 4</td>
|
||||
<td>cell 5</td>
|
||||
<td>cell 6</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td>foot a</td>
|
||||
<td>foot b</td>
|
||||
<td>foot c</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
```
|
||||
table header and footer are optional
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <macros.h>
|
||||
|
||||
#include "md2html/parser.h"
|
||||
|
||||
|
||||
void ConvertMarkdown2Html( const wxString& aMarkdownInput, wxString& aHtmlOutput )
|
||||
{
|
||||
std::stringstream markdownInput( TO_UTF8( aMarkdownInput ) );
|
||||
|
||||
std::shared_ptr<maddy::Parser> parser = std::make_shared<maddy::Parser>();
|
||||
std::string htmlOutput = parser->Parse(markdownInput);
|
||||
|
||||
aHtmlOutput = FROM_UTF8( htmlOutput.c_str() );
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
The following authors have all licensed their contributions to maddy under the
|
||||
licensing terms detailed in LICENSE.
|
||||
|
||||
(Authors keep copyright of their contributions, of course; they just grant
|
||||
a license to everyone to use it as detailed in LICENSE.)
|
||||
|
||||
M. Petra Baranski (info@progsource.de)
|
||||
Patrick José Pereira (patrickelectric@gmail.com)
|
||||
|
||||
Github site:
|
||||
https://github.com/progsource/maddy
|
|
@ -0,0 +1,18 @@
|
|||
Copyright 2017, 2018, 2019 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.
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* 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&)>} aParseLineCallback
|
||||
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} aGetBlockParserForLineCallback
|
||||
*/
|
||||
BlockParser( std::function<void(std::string&)> aParseLineCallback,
|
||||
std::function<std::shared_ptr<BlockParser>(const std::string& line)> aGetBlockParserForLineCallback
|
||||
)
|
||||
: result( "", std::ios_base::ate | std::ios_base::in | std::ios_base::out ),
|
||||
childParser( nullptr ),
|
||||
parseLineCallback( aParseLineCallback ),
|
||||
getBlockParserForLineCallback( aGetBlockParserForLineCallback )
|
||||
{}
|
||||
|
||||
/**
|
||||
* 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
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <functional>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
#include "blockparser.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace maddy {
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* ChecklistParser
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
class ChecklistParser : public BlockParser
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* ctor
|
||||
*
|
||||
* @method
|
||||
* @param {std::function<void(std::string&)>} aParseLineCallback
|
||||
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} aGetBlockParserForLineCallback
|
||||
*/
|
||||
ChecklistParser( std::function<void(std::string&)> aParseLineCallback,
|
||||
std::function<std::shared_ptr<BlockParser>(const std::string& line)> aGetBlockParserForLineCallback
|
||||
)
|
||||
: BlockParser( aParseLineCallback, aGetBlockParserForLineCallback ),
|
||||
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
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include "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&)>} aParseLineCallback
|
||||
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} aGetBlockParserForLineCallback
|
||||
*/
|
||||
CodeBlockParser( std::function<void(std::string&)> aParseLineCallback,
|
||||
std::function<std::shared_ptr<BlockParser>(const std::string& line)> aGetBlockParserForLineCallback
|
||||
)
|
||||
: BlockParser( aParseLineCallback, aGetBlockParserForLineCallback ),
|
||||
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
|
|
@ -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 "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
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include "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&)>} aParseLineCallback
|
||||
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} aGetBlockParserForLineCallback
|
||||
*/
|
||||
HeadlineParser( std::function<void(std::string&)> aParseLineCallback,
|
||||
std::function<std::shared_ptr<BlockParser>(const std::string& line)> aGetBlockParserForLineCallback
|
||||
)
|
||||
: BlockParser( aParseLineCallback, aGetBlockParserForLineCallback )
|
||||
{}
|
||||
|
||||
/**
|
||||
* 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
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include "blockparser.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace maddy {
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* HorizontalLineParser
|
||||
*
|
||||
* From Markdown: `---`
|
||||
*
|
||||
* To HTML: `<hr/>`
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
class HorizontalLineParser : public BlockParser
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* ctor
|
||||
*
|
||||
* @method
|
||||
* @param {std::function<void(std::string&)>} aParseLineCallback
|
||||
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} aGetBlockParserForLineCallback
|
||||
*/
|
||||
HorizontalLineParser( std::function<void(std::string&)> aParseLineCallback,
|
||||
std::function<std::shared_ptr<BlockParser>(const std::string& line)> aGetBlockParserForLineCallback
|
||||
)
|
||||
: BlockParser( aParseLineCallback, aGetBlockParserForLineCallback ),
|
||||
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
|
|
@ -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 "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
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include "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
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include "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
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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
|
|
@ -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 "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
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <functional>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
#include "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&)> aParseLineCallback,
|
||||
std::function<std::shared_ptr<BlockParser>(const std::string& line)> aGetBlockParserForLineCallback
|
||||
)
|
||||
: BlockParser( aParseLineCallback, aGetBlockParserForLineCallback ),
|
||||
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\\. " );
|
||||
|
||||
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\\. |\\* ).*" );
|
||||
|
||||
return std::regex_match( line, re );
|
||||
}
|
||||
}; // class OrderedListParser
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
} // namespace maddy
|
|
@ -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 "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&)> aParseLineCallback,
|
||||
std::function<std::shared_ptr<BlockParser>(const std::string& line)> aGetBlockParserForLineCallback
|
||||
)
|
||||
: BlockParser( aParseLineCallback, aGetBlockParserForLineCallback ),
|
||||
isStarted( false ),
|
||||
isFinished( false )
|
||||
{}
|
||||
|
||||
/**
|
||||
* IsStartingLine
|
||||
*
|
||||
* If the line is not empty, it will be a paragraph. So 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
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
// BlockParser
|
||||
#include "checklistparser.h"
|
||||
#include "codeblockparser.h"
|
||||
#include "headlineparser.h"
|
||||
#include "horizontallineparser.h"
|
||||
#include "orderedlistparser.h"
|
||||
#include "paragraphparser.h"
|
||||
#include "quoteparser.h"
|
||||
#include "tableparser.h"
|
||||
#include "unorderedlistparser.h"
|
||||
|
||||
// LineParser
|
||||
#include "emphasizedparser.h"
|
||||
#include "imageparser.h"
|
||||
#include "inlinecodeparser.h"
|
||||
#include "italicparser.h"
|
||||
#include "linkparser.h"
|
||||
#include "strikethroughparser.h"
|
||||
#include "strongparser.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace maddy {
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parser
|
||||
*
|
||||
* Transforms Markdown to HTML
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* ctor
|
||||
*
|
||||
* Initializes all `LineParser`
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
Parser()
|
||||
: 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::stringstream&} markdown
|
||||
* @return {std::string} HTML
|
||||
*/
|
||||
std::string Parse( std::stringstream& 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<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 );
|
||||
this->emphasizedParser->Parse( line );
|
||||
|
||||
this->strikeThroughParser->Parse( line );
|
||||
|
||||
this->inlineCodeParser->Parse( line );
|
||||
|
||||
this->italicParser->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& aLine ) { this->runLineParser( aLine ); },
|
||||
[this]( const std::string& aLine )
|
||||
{ return this->getBlockParserForLine( aLine ); }
|
||||
);
|
||||
}
|
||||
else if( maddy::TableParser::IsStartingLine( line ) )
|
||||
{
|
||||
parser = std::make_shared<maddy::TableParser>(
|
||||
[this]( std::string& aLine ) { this->runLineParser( aLine ); },
|
||||
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( maddy::ParagraphParser::IsStartingLine( line ) )
|
||||
{
|
||||
parser = std::make_shared<maddy::ParagraphParser>(
|
||||
[this]( std::string& aLine ) { this->runLineParser( aLine ); },
|
||||
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
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <functional>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
#include "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&)> aParseLineCallback,
|
||||
std::function<std::shared_ptr<BlockParser>(const std::string& line)> aGetBlockParserForLineCallback
|
||||
)
|
||||
: BlockParser( aParseLineCallback, aGetBlockParserForLineCallback ),
|
||||
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
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include "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
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include "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
|
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include "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&)>} aParseLineCallback
|
||||
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} aGetBlockParserForLineCallback
|
||||
*/
|
||||
TableParser( std::function<void(std::string&)> aParseLineCallback,
|
||||
std::function<std::shared_ptr<BlockParser>(const std::string& line)> aGetBlockParserForLineCallback
|
||||
)
|
||||
: BlockParser( aParseLineCallback, aGetBlockParserForLineCallback ),
|
||||
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
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* This project is licensed under the MIT license. For more information see the
|
||||
* LICENSE file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <functional>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
|
||||
#include "blockparser.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace maddy {
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* UnorderedListParser
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
class UnorderedListParser : public BlockParser
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* ctor
|
||||
*
|
||||
* @method
|
||||
* @param {std::function<void(std::string&)>} aParseLineCallback
|
||||
* @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} aGetBlockParserForLineCallback
|
||||
*/
|
||||
UnorderedListParser( std::function<void(std::string&)> aParseLineCallback,
|
||||
std::function<std::shared_ptr<BlockParser>(const std::string& line)> aGetBlockParserForLineCallback
|
||||
)
|
||||
: BlockParser( aParseLineCallback, aGetBlockParserForLineCallback ),
|
||||
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
|
|
@ -171,8 +171,22 @@ function( html_doc2h inputFile )
|
|||
COMMENT "creating ${inputFile}.h from ${inputFile}.html"
|
||||
)
|
||||
endfunction()
|
||||
#
|
||||
# Conversion of .md doc source files to .h files included in cpp sources
|
||||
#
|
||||
# Function md_doc2h : converts a single *.md text file to a *.h header
|
||||
function( md_doc2h inputFile )
|
||||
add_custom_command(
|
||||
OUTPUT ${inputFile}.h
|
||||
|
||||
html_doc2h( ${CMAKE_CURRENT_SOURCE_DIR}/attenuators/bridget_tee_formula )
|
||||
COMMAND ${CMAKE_COMMAND} -DinputFile=${inputFile}.md -DoutputFile=${inputFile}.h
|
||||
-P ${CMAKE_MODULE_PATH}/markdown2C.cmake
|
||||
DEPENDS ${inputFile}.md ${CMAKE_MODULE_PATH}/markdown2C.cmake
|
||||
COMMENT "creating ${inputFile}.h from ${inputFile}.md"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
md_doc2h( ${CMAKE_CURRENT_SOURCE_DIR}/attenuators/bridget_tee_formula )
|
||||
html_doc2h( ${CMAKE_CURRENT_SOURCE_DIR}/attenuators/splitter_formula )
|
||||
html_doc2h( ${CMAKE_CURRENT_SOURCE_DIR}/attenuators/pi_formula )
|
||||
html_doc2h( ${CMAKE_CURRENT_SOURCE_DIR}/attenuators/tee_formula )
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <wx/wx.h>
|
||||
|
||||
#include <pcb_calculator.h>
|
||||
#include <attenuator_classes.h>
|
||||
#include <dialog_helpers.h>
|
||||
|
||||
|
||||
extern double DoubleFromString( const wxString& TextValue );
|
||||
|
@ -97,7 +97,16 @@ void PCB_CALCULATOR_FRAME::TransfAttenuatorDataToPanel()
|
|||
m_ZoutValueCtrl->SetValue( msg );
|
||||
|
||||
if( m_currAttenuator->m_FormulaName )
|
||||
m_panelAttFormula->SetPage( *m_currAttenuator->m_FormulaName );
|
||||
{
|
||||
if( m_currAttenuator->m_FormulaName->StartsWith( "<!" ) )
|
||||
m_panelAttFormula->SetPage( *m_currAttenuator->m_FormulaName );
|
||||
else
|
||||
{
|
||||
wxString html_txt;
|
||||
ConvertMarkdown2Html( wxGetTranslation( *m_currAttenuator->m_FormulaName ), html_txt );
|
||||
m_panelAttFormula->SetPage( html_txt );
|
||||
}
|
||||
}
|
||||
else
|
||||
m_panelAttFormula->SetPage( wxEmptyString );
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <cmath>
|
||||
|
||||
#include <attenuator_classes.h>
|
||||
#include <i18n_utility.h>
|
||||
|
||||
// Bitmaps:
|
||||
#include <att_pi.xpm>
|
||||
|
@ -25,9 +26,9 @@ wxString tee_formula(
|
|||
#include <tee_formula.h>
|
||||
);
|
||||
|
||||
wxString bridget_tee_formula(
|
||||
wxString bridget_tee_formula =
|
||||
#include <bridget_tee_formula.h>
|
||||
);
|
||||
;
|
||||
|
||||
wxString splitter_formula(
|
||||
#include <splitter_formula.h>
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
double m_R2; // value of R2
|
||||
double m_R3; // value of R3 (if any)
|
||||
wxBitmap* m_SchBitMap; // The schema of this attenuator
|
||||
wxString* m_FormulaName; // The HTML text name of the formula used to calculate this attenuator
|
||||
wxString* m_FormulaName; // The HTML/markdown text name of the formula
|
||||
|
||||
protected:
|
||||
double Lmin, L, A; // internal variable for temporary use
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
__Zin__ desired input impedance in Ω<br>
|
||||
__Zout__ desired output impedance __Zin = Zout__
|
||||
|
||||
### Bridged tee attenuator:
|
||||
* __a__ attenuation in dB
|
||||
* __L = 10<sup>a/20</sup>__ (the loss)
|
||||
* ___R1 = Zin * (L - 1)___
|
||||
* ___R2 = Zin / (L - 1)___
|
Loading…
Reference in New Issue