Allow custom tag processing in md
This commit is contained in:
parent
22157169c0
commit
101bfb4207
12 changed files with 214 additions and 43 deletions
|
@ -3,6 +3,7 @@
|
|||
#include "MarkdownParser.h"
|
||||
#include "MarkdownDocument.h"
|
||||
#include "MarkdownElement.h"
|
||||
#include "MarkdownCustomElement.h"
|
||||
|
||||
#include "File.h"
|
||||
|
||||
|
@ -37,9 +38,20 @@ std::pair<MarkdownContentParser::FileMetadata, std::unique_ptr<MarkdownDocument>
|
|||
}
|
||||
|
||||
MarkdownParser md_parser;
|
||||
auto content = md_parser.run(content_body);
|
||||
|
||||
return {output_metadata, std::move(content)};
|
||||
auto document = std::make_unique<MarkdownDocument>();
|
||||
|
||||
auto custom_math_inline = std::make_unique<MarkdownCustomInlineElementContext>("$");
|
||||
custom_math_inline->setReplacementDelimiters("\\(", "\\)");
|
||||
|
||||
auto custom_math_multiline = std::make_unique<MarkdownCustomMultilineElementContext>("$$");
|
||||
|
||||
document->registerCustomInlineElement(std::move(custom_math_inline));
|
||||
document->registerCustomMultilineElement(std::move(custom_math_multiline));
|
||||
|
||||
md_parser.run(content_body, document.get());
|
||||
|
||||
return {output_metadata, std::move(document)};
|
||||
}
|
||||
|
||||
std::optional<MarkdownContentParser::FileMetadataItem> MarkdownContentParser::checkForMetadataItem(const std::string& line) const
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "MarkdownComponents.h"
|
||||
|
||||
#include "MarkdownCustomElement.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
MarkdownTextSpan::Type MarkdownTextSpan::getType() const
|
||||
|
@ -98,8 +99,8 @@ MarkdownInlineQuote::Type MarkdownInlineQuote::getType() const
|
|||
return Type::INLINE_QUOTE;
|
||||
}
|
||||
|
||||
MarkdownCustomInline::MarkdownCustomInline(const std::string& delimiter)
|
||||
: mDelimiter(delimiter)
|
||||
MarkdownCustomInline::MarkdownCustomInline(MarkdownCustomElementContext* customElement)
|
||||
: mCustomElement(customElement)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -108,6 +109,11 @@ MarkdownCustomInline::Type MarkdownCustomInline::getType() const
|
|||
return Type::CUSTOM_INLINE;
|
||||
};
|
||||
|
||||
std::string MarkdownCustomInline::getTextContent() const
|
||||
{
|
||||
return mCustomElement->getOutputLeftDelimiter() + MarkdownElement::getTextContent() + mCustomElement->getOutputRightDelimiter();
|
||||
}
|
||||
|
||||
MarkdownLink::MarkdownLink(const std::string& target)
|
||||
: mTarget(target)
|
||||
{
|
||||
|
@ -158,13 +164,19 @@ MarkdownMultilineQuote::Type MarkdownMultilineQuote::getType() const
|
|||
}
|
||||
|
||||
|
||||
MarkdownCustomMultiLine::MarkdownCustomMultiLine(const std::string& tag, const std::string& delimiter)
|
||||
MarkdownCustomMultiLine::MarkdownCustomMultiLine(const std::string& tag, MarkdownCustomElementContext* customElement)
|
||||
: mTag(tag),
|
||||
mDelimiter(delimiter)
|
||||
mCustomElement(customElement)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MarkdownCustomMultiLine::Type MarkdownCustomMultiLine::getType() const
|
||||
{
|
||||
return Type::CUSTOM_MULTILINE;
|
||||
}
|
||||
|
||||
std::string MarkdownCustomMultiLine::getTextContent() const
|
||||
{
|
||||
return mCustomElement->getOutputLeftDelimiter() + "\n" + MarkdownElement::getTextContent() + mCustomElement->getOutputRightDelimiter();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "MarkdownElement.h"
|
||||
#include "MarkdownCustomElement.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
@ -120,12 +121,14 @@ public:
|
|||
class MarkdownCustomInline : public MarkdownInlineElement
|
||||
{
|
||||
public:
|
||||
MarkdownCustomInline(const std::string& delimiter);
|
||||
MarkdownCustomInline(MarkdownCustomElementContext* customElement);
|
||||
virtual ~MarkdownCustomInline() = default;
|
||||
|
||||
Type getType() const override;
|
||||
|
||||
std::string getTextContent() const override;
|
||||
private:
|
||||
std::string mDelimiter;
|
||||
MarkdownCustomElementContext* mCustomElement{nullptr};
|
||||
};
|
||||
|
||||
class MarkdownImage : public MarkdownInlineElement
|
||||
|
@ -161,12 +164,14 @@ private:
|
|||
class MarkdownCustomMultiLine : public MarkdownMultilineElement
|
||||
{
|
||||
public:
|
||||
MarkdownCustomMultiLine(const std::string& tag, const std::string& delimiter);
|
||||
MarkdownCustomMultiLine(const std::string& tag, MarkdownCustomElementContext* customElement);
|
||||
|
||||
virtual ~MarkdownCustomMultiLine() = default;
|
||||
|
||||
Type getType() const override;
|
||||
|
||||
std::string getTextContent() const override;
|
||||
private:
|
||||
std::string mTag;
|
||||
std::string mDelimiter;
|
||||
MarkdownCustomElementContext* mCustomElement{nullptr};
|
||||
};
|
||||
|
|
|
@ -21,6 +21,12 @@ void MarkdownConverter::onBlockElement(MarkdownElementWithChildren* mdElement, H
|
|||
html_quote->setText(child->getTextContent());
|
||||
htmlElement->addChild(std::move(html_quote));
|
||||
}
|
||||
else if (child->getType() == MarkdownElement::Type::CUSTOM_INLINE)
|
||||
{
|
||||
auto html_text = std::make_unique<HtmlTextRun>();
|
||||
html_text->setText(child->getTextContent());
|
||||
htmlElement->addChild(std::move(html_text));
|
||||
}
|
||||
else if(child->getType() == MarkdownElement::Type::TEXT_SPAN)
|
||||
{
|
||||
auto html_text = std::make_unique<HtmlTextRun>();
|
||||
|
@ -87,6 +93,12 @@ void MarkdownConverter::convert(MarkdownDocument* markdownDoc, HtmlElement* pare
|
|||
html_quote->setText(md_element->getTextContent());
|
||||
parentElement->addChild(std::move(html_quote));
|
||||
}
|
||||
else if(md_element->getType() == MarkdownElement::Type::CUSTOM_MULTILINE)
|
||||
{
|
||||
auto html_text = std::make_unique<HtmlTextRun>();
|
||||
html_text->setText("\n" + md_element->getTextContent() + "\n");
|
||||
parentElement->addChild(std::move(html_text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
0
src/web/markdown/MarkdownCustomElement.cpp
Normal file
0
src/web/markdown/MarkdownCustomElement.cpp
Normal file
79
src/web/markdown/MarkdownCustomElement.h
Normal file
79
src/web/markdown/MarkdownCustomElement.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
class MarkdownCustomElementContext
|
||||
{
|
||||
public:
|
||||
MarkdownCustomElementContext(const std::string& delimiter)
|
||||
: mDelimiter(delimiter)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual ~MarkdownCustomElementContext() = default;
|
||||
|
||||
void setReplacementDelimiters(const std::string& leftReplacement, const std::string& rightReplacement)
|
||||
{
|
||||
mReplacementLeftDelimiter = leftReplacement;
|
||||
mReplacementRightDelimiter = rightReplacement;
|
||||
if (mReplacementRightDelimiter.empty())
|
||||
{
|
||||
mReplacementRightDelimiter = mReplacementLeftDelimiter;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& getDelimiter() const
|
||||
{
|
||||
return mDelimiter;
|
||||
}
|
||||
|
||||
const std::string& getOutputLeftDelimiter() const
|
||||
{
|
||||
if (!mReplacementLeftDelimiter.empty())
|
||||
{
|
||||
return mReplacementLeftDelimiter;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mDelimiter;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& getOutputRightDelimiter() const
|
||||
{
|
||||
if (!mReplacementRightDelimiter.empty())
|
||||
{
|
||||
return mReplacementRightDelimiter;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mDelimiter;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mReplacementLeftDelimiter;
|
||||
std::string mReplacementRightDelimiter;
|
||||
std::string mDelimiter;
|
||||
};
|
||||
|
||||
class MarkdownCustomInlineElementContext : public MarkdownCustomElementContext
|
||||
{
|
||||
public:
|
||||
MarkdownCustomInlineElementContext(const std::string& delimiter)
|
||||
: MarkdownCustomElementContext(delimiter)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class MarkdownCustomMultilineElementContext : public MarkdownCustomElementContext
|
||||
{
|
||||
public:
|
||||
MarkdownCustomMultilineElementContext(const std::string& delimiter)
|
||||
: MarkdownCustomElementContext(delimiter)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
|
@ -3,6 +3,10 @@
|
|||
#include "MarkdownElement.h"
|
||||
#include "MarkdownComponents.h"
|
||||
|
||||
MarkdownDocument::~MarkdownDocument()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MarkdownDocument::addElement(std::unique_ptr<MarkdownElement> element)
|
||||
{
|
||||
|
@ -19,14 +23,6 @@ MarkdownElement* MarkdownDocument::getElement(std::size_t idx) const
|
|||
return mElements[idx].get();
|
||||
}
|
||||
|
||||
void MarkdownDocument::doLinkTargetSubstitution(const std::string& targetString, const std::string& replacementString)
|
||||
{
|
||||
for(auto& element : mElements)
|
||||
{
|
||||
element->doFieldSubstitution(MarkdownElement::Type::LINK, targetString, replacementString);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<MarkdownLink*> MarkdownDocument::getAllLinks() const
|
||||
{
|
||||
std::vector<MarkdownLink*> links;
|
||||
|
@ -49,3 +45,33 @@ std::vector<MarkdownLink*> MarkdownDocument::getAllLinks() const
|
|||
}
|
||||
return links;
|
||||
}
|
||||
|
||||
std::size_t MarkdownDocument::getNumMultilineContexts() const
|
||||
{
|
||||
return mCustomMultilineContexts.size();
|
||||
}
|
||||
|
||||
std::size_t MarkdownDocument::getNumInlineContexts() const
|
||||
{
|
||||
return mCustomInlineContexts.size();
|
||||
}
|
||||
|
||||
MarkdownCustomMultilineElementContext* MarkdownDocument::getMultilineContext(std::size_t idx) const
|
||||
{
|
||||
return mCustomMultilineContexts[idx].get();
|
||||
}
|
||||
|
||||
MarkdownCustomInlineElementContext* MarkdownDocument::getInlineContext(std::size_t idx) const
|
||||
{
|
||||
return mCustomInlineContexts[idx].get();
|
||||
}
|
||||
|
||||
void MarkdownDocument::registerCustomInlineElement(std::unique_ptr<MarkdownCustomInlineElementContext> context)
|
||||
{
|
||||
mCustomInlineContexts.push_back(std::move(context));
|
||||
}
|
||||
|
||||
void MarkdownDocument::registerCustomMultilineElement(std::unique_ptr<MarkdownCustomMultilineElementContext> context)
|
||||
{
|
||||
mCustomMultilineContexts.push_back(std::move(context));
|
||||
}
|
||||
|
|
|
@ -5,22 +5,38 @@
|
|||
|
||||
class MarkdownElement;
|
||||
class MarkdownLink;
|
||||
class MarkdownCustomMultilineElementContext;
|
||||
class MarkdownCustomInlineElementContext;
|
||||
|
||||
class MarkdownDocument
|
||||
{
|
||||
public:
|
||||
~MarkdownDocument();
|
||||
|
||||
void addElement(std::unique_ptr<MarkdownElement> element);
|
||||
|
||||
std::size_t getNumElements() const;
|
||||
|
||||
MarkdownElement* getElement(std::size_t idx) const;
|
||||
|
||||
void doLinkTargetSubstitution(const std::string& targetString, const std::string& replacementString);
|
||||
|
||||
std::vector<MarkdownLink*> getAllLinks() const;
|
||||
|
||||
std::size_t getNumMultilineContexts() const;
|
||||
|
||||
std::size_t getNumInlineContexts() const;
|
||||
|
||||
MarkdownCustomMultilineElementContext* getMultilineContext(std::size_t idx) const;
|
||||
|
||||
MarkdownCustomInlineElementContext* getInlineContext(std::size_t idx) const;
|
||||
|
||||
void registerCustomInlineElement(std::unique_ptr<MarkdownCustomInlineElementContext> context);
|
||||
|
||||
void registerCustomMultilineElement(std::unique_ptr<MarkdownCustomMultilineElementContext> context);
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<MarkdownElement> > mElements;
|
||||
std::vector<std::unique_ptr<MarkdownCustomMultilineElementContext> > mCustomMultilineContexts;
|
||||
std::vector<std::unique_ptr<MarkdownCustomInlineElementContext> > mCustomInlineContexts;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ void MarkdownElement::appendTextContent(const std::string& content)
|
|||
mTextContent += content;
|
||||
}
|
||||
|
||||
const std::string& MarkdownElement::getTextContent() const
|
||||
std::string MarkdownElement::getTextContent() const
|
||||
{
|
||||
return mTextContent;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ public:
|
|||
|
||||
void addLine(const std::string& line);
|
||||
|
||||
const std::string& getTextContent() const;
|
||||
virtual std::string getTextContent() const;
|
||||
|
||||
virtual Type getType() const = 0;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "MarkdownDocument.h"
|
||||
#include "MarkdownComponents.h"
|
||||
#include "MarkdownCustomElement.h"
|
||||
|
||||
#include "Lexer.h"
|
||||
#include "StringUtils.h"
|
||||
|
@ -13,8 +14,7 @@ static constexpr char HEADING_DELIMITER{'#'};
|
|||
|
||||
MarkdownParser::MarkdownParser()
|
||||
{
|
||||
mCustomMultilineDelimiters = {{"$$"}};
|
||||
mCustomInlineDelimiters = {{"$"}};
|
||||
|
||||
}
|
||||
|
||||
MarkdownParser::~MarkdownParser()
|
||||
|
@ -121,9 +121,9 @@ unsigned MarkdownParser::checkForCustomInline(const std::string& lineSection)
|
|||
std::vector<std::string> hits;
|
||||
unsigned hit_size{0};
|
||||
|
||||
for(unsigned idx=0; idx<mCustomInlineDelimiters.size(); idx++)
|
||||
for(unsigned idx=0; idx<mWorkingDocument->getNumInlineContexts(); idx++)
|
||||
{
|
||||
const auto delimiter = mCustomInlineDelimiters[idx];
|
||||
const auto delimiter = mWorkingDocument->getInlineContext(idx)->getDelimiter();
|
||||
if (Lexer::matchPattern(delimiter + "@" + delimiter, lineSection, '@', hits))
|
||||
{
|
||||
if (hits.size() == 1)
|
||||
|
@ -132,7 +132,7 @@ unsigned MarkdownParser::checkForCustomInline(const std::string& lineSection)
|
|||
|
||||
onTextSpanFinished();
|
||||
|
||||
auto element = std::make_unique<MarkdownCustomInline>(delimiter);
|
||||
auto element = std::make_unique<MarkdownCustomInline>(mWorkingDocument->getInlineContext(idx));
|
||||
element->appendTextContent(content);
|
||||
|
||||
addChildToWorkingElement(std::move(element));
|
||||
|
@ -182,7 +182,7 @@ void MarkdownParser::processLine(const std::string& line)
|
|||
{
|
||||
auto paragraph = std::make_unique<MarkdownParagraph>();
|
||||
mWorkingElement = paragraph.get();
|
||||
mMarkdownDocument->addElement(std::move(paragraph));
|
||||
mWorkingDocument->addElement(std::move(paragraph));
|
||||
}
|
||||
|
||||
if (mWorkingElement && mWorkingElement->getType() == MarkdownElement::Type::PARAGRAPH)
|
||||
|
@ -239,9 +239,9 @@ bool MarkdownParser::startsWithMultiLineQuote(const std::string& line) const
|
|||
|
||||
int MarkdownParser::startsWithCustomMultilineBlock(const std::string& line) const
|
||||
{
|
||||
for(unsigned idx=0; idx<mCustomMultilineDelimiters.size(); idx++)
|
||||
for(unsigned idx=0; idx<mWorkingDocument->getNumMultilineContexts(); idx++)
|
||||
{
|
||||
if (StringUtils::startsWith(line, mCustomMultilineDelimiters[idx], true))
|
||||
if (StringUtils::startsWith(line, mWorkingDocument->getMultilineContext(idx)->getDelimiter(), true))
|
||||
{
|
||||
return idx;
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ void MarkdownParser::onFoundMultiLineQuote(const std::string& line)
|
|||
const auto tag = StringUtils::removeUpTo(line, MULTILINE_QUOTE_DELIMITER);
|
||||
auto quote = std::make_unique<MarkdownMultilineQuote>(tag);
|
||||
mWorkingElement = quote.get();
|
||||
mMarkdownDocument->addElement(std::move(quote));
|
||||
mWorkingDocument->addElement(std::move(quote));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,11 +290,11 @@ void MarkdownParser::onFoundCustomMultiLineBlock(const std::string& line, unsign
|
|||
}
|
||||
else
|
||||
{
|
||||
const auto delimiter = mCustomMultilineDelimiters[blockSlot];
|
||||
const auto delimiter = mWorkingDocument->getMultilineContext(blockSlot)->getDelimiter();
|
||||
const auto tag = StringUtils::removeUpTo(line, delimiter);
|
||||
auto quote = std::make_unique<MarkdownCustomMultiLine>(tag, delimiter);
|
||||
auto quote = std::make_unique<MarkdownCustomMultiLine>(tag, mWorkingDocument->getMultilineContext(blockSlot));
|
||||
mWorkingElement = quote.get();
|
||||
mMarkdownDocument->addElement(std::move(quote));
|
||||
mWorkingDocument->addElement(std::move(quote));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,7 +317,7 @@ void MarkdownParser::onFoundHeading(const std::string& line)
|
|||
prefix += HEADING_DELIMITER;
|
||||
}
|
||||
heading->appendTextContent(StringUtils::stripSurroundingWhitepsace(StringUtils::removeUpTo(line, prefix)));
|
||||
mMarkdownDocument->addElement(std::move(heading));
|
||||
mWorkingDocument->addElement(std::move(heading));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,7 +340,7 @@ void MarkdownParser::onFoundBulletItem(const std::string& line)
|
|||
auto bullet_list = std::make_unique<MarkdownBulletList>();
|
||||
mWorkingBulletList = bullet_list.get();
|
||||
|
||||
mMarkdownDocument->addElement(std::move(bullet_list));
|
||||
mWorkingDocument->addElement(std::move(bullet_list));
|
||||
|
||||
auto bullet_item = std::make_unique<MarkdownBulletItem>();
|
||||
mWorkingElement = bullet_item.get();
|
||||
|
@ -357,9 +357,9 @@ void MarkdownParser::onSectionFinished()
|
|||
mWorkingTextSpan = nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<MarkdownDocument> MarkdownParser::run(const std::string& content)
|
||||
void MarkdownParser::run(const std::string& content, MarkdownDocument* document)
|
||||
{
|
||||
mMarkdownDocument = std::make_unique<MarkdownDocument>();
|
||||
mWorkingDocument = document;
|
||||
|
||||
std::stringstream ss(content);
|
||||
std::string line;
|
||||
|
@ -392,6 +392,13 @@ std::unique_ptr<MarkdownDocument> MarkdownParser::run(const std::string& content
|
|||
processLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(mMarkdownDocument);
|
||||
}
|
||||
|
||||
std::unique_ptr<MarkdownDocument> MarkdownParser::run(const std::string& content)
|
||||
{
|
||||
auto doc = std::make_unique<MarkdownDocument>();
|
||||
|
||||
run(content, doc.get());
|
||||
|
||||
return std::move(doc);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ class MarkdownDocument;
|
|||
class MarkdownElement;
|
||||
class MarkdownInlineElement;
|
||||
class MarkdownBulletList;
|
||||
class MarkdownCustomInlineElementContext;
|
||||
class MarkdownCustomMultilineElementContext;
|
||||
|
||||
class MarkdownParser
|
||||
{
|
||||
|
@ -18,6 +20,8 @@ public:
|
|||
|
||||
std::unique_ptr<MarkdownDocument> run(const std::string& content);
|
||||
|
||||
void run(const std::string& content, MarkdownDocument* document);
|
||||
|
||||
private:
|
||||
void addChildToWorkingElement(std::unique_ptr<MarkdownInlineElement> child);
|
||||
|
||||
|
@ -45,8 +49,6 @@ private:
|
|||
bool startsWithBulletItem(const std::string& line) const;
|
||||
|
||||
unsigned mCustomDelimiterIndex{0};
|
||||
std::vector<std::string> mCustomMultilineDelimiters;
|
||||
std::vector<std::string> mCustomInlineDelimiters;
|
||||
|
||||
MarkdownElement* mWorkingElement{nullptr};
|
||||
MarkdownBulletList* mWorkingBulletList{nullptr};
|
||||
|
@ -54,5 +56,5 @@ private:
|
|||
MarkdownInlineElement* mWorkingTextSpan{nullptr};
|
||||
std::string mWorkingLine;
|
||||
|
||||
std::unique_ptr<MarkdownDocument> mMarkdownDocument;
|
||||
MarkdownDocument* mWorkingDocument{nullptr};
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue