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:
jean-pierre charras 2019-09-29 17:25:56 +02:00
parent ce62941bb8
commit 8ed49b3f68
30 changed files with 2560 additions and 6 deletions

View File

@ -312,6 +312,7 @@ set( COMMON_SRCS
lib_tree_model.cpp lib_tree_model.cpp
lib_tree_model_adapter.cpp lib_tree_model_adapter.cpp
lockfile.cpp lockfile.cpp
../markdown2html/markdown2html.cpp
marker_base.cpp marker_base.cpp
md5_hash.cpp md5_hash.cpp
msgpanel.cpp msgpanel.cpp

View File

@ -35,6 +35,7 @@
#include <common.h> // EDA_UNITS_T #include <common.h> // EDA_UNITS_T
#include <../common/dialogs/dialog_list_selector_base.h> #include <../common/dialogs/dialog_list_selector_base.h>
void ConvertMarkdown2Html( const wxString& aMarkdownInput, wxString& aHtmlOutput );
class EDA_DRAW_FRAME; class EDA_DRAW_FRAME;

View File

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

View File

@ -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() );
}

View File

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

View File

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

View File

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

View File

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

View File

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

View 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 "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

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

View File

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

View 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 "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

View File

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

View File

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

View File

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

View 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 "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

View File

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

View 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 "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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

@ -171,8 +171,22 @@ function( html_doc2h inputFile )
COMMENT "creating ${inputFile}.h from ${inputFile}.html" COMMENT "creating ${inputFile}.h from ${inputFile}.html"
) )
endfunction() 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/splitter_formula )
html_doc2h( ${CMAKE_CURRENT_SOURCE_DIR}/attenuators/pi_formula ) html_doc2h( ${CMAKE_CURRENT_SOURCE_DIR}/attenuators/pi_formula )
html_doc2h( ${CMAKE_CURRENT_SOURCE_DIR}/attenuators/tee_formula ) html_doc2h( ${CMAKE_CURRENT_SOURCE_DIR}/attenuators/tee_formula )

View File

@ -28,7 +28,7 @@
#include <wx/wx.h> #include <wx/wx.h>
#include <pcb_calculator.h> #include <pcb_calculator.h>
#include <attenuator_classes.h> #include <dialog_helpers.h>
extern double DoubleFromString( const wxString& TextValue ); extern double DoubleFromString( const wxString& TextValue );
@ -97,7 +97,16 @@ void PCB_CALCULATOR_FRAME::TransfAttenuatorDataToPanel()
m_ZoutValueCtrl->SetValue( msg ); m_ZoutValueCtrl->SetValue( msg );
if( m_currAttenuator->m_FormulaName ) if( m_currAttenuator->m_FormulaName )
{
if( m_currAttenuator->m_FormulaName->StartsWith( "<!" ) )
m_panelAttFormula->SetPage( *m_currAttenuator->m_FormulaName ); 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 else
m_panelAttFormula->SetPage( wxEmptyString ); m_panelAttFormula->SetPage( wxEmptyString );
} }

View File

@ -8,6 +8,7 @@
#include <cmath> #include <cmath>
#include <attenuator_classes.h> #include <attenuator_classes.h>
#include <i18n_utility.h>
// Bitmaps: // Bitmaps:
#include <att_pi.xpm> #include <att_pi.xpm>
@ -25,9 +26,9 @@ wxString tee_formula(
#include <tee_formula.h> #include <tee_formula.h>
); );
wxString bridget_tee_formula( wxString bridget_tee_formula =
#include <bridget_tee_formula.h> #include <bridget_tee_formula.h>
); ;
wxString splitter_formula( wxString splitter_formula(
#include <splitter_formula.h> #include <splitter_formula.h>

View File

@ -40,7 +40,7 @@ public:
double m_R2; // value of R2 double m_R2; // value of R2
double m_R3; // value of R3 (if any) double m_R3; // value of R3 (if any)
wxBitmap* m_SchBitMap; // The schema of this attenuator 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: protected:
double Lmin, L, A; // internal variable for temporary use double Lmin, L, A; // internal variable for temporary use

View File

@ -0,0 +1,8 @@
__Zin__ desired input impedance in &#8486<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)___