Initial site generation
This commit is contained in:
parent
f44c79dc1f
commit
fc44290e3f
35 changed files with 667 additions and 303 deletions
|
@ -1,8 +1,11 @@
|
||||||
#include "ContentFile.h"
|
#include "ContentFile.h"
|
||||||
|
|
||||||
#include "PathUtils.h"
|
#include "PathUtils.h"
|
||||||
|
#include "StringUtils.h"
|
||||||
|
|
||||||
#include "MarkdownDocument.h"
|
#include "MarkdownDocument.h"
|
||||||
#include "MarkdownElement.h"
|
#include "MarkdownElement.h"
|
||||||
|
#include "MarkdownComponents.h"
|
||||||
|
|
||||||
ContentFile::ContentFile(const Path& filename)
|
ContentFile::ContentFile(const Path& filename)
|
||||||
: mFilename(filename)
|
: mFilename(filename)
|
||||||
|
@ -35,6 +38,23 @@ void ContentFile::load()
|
||||||
mContentBody = std::move(result.second);
|
mContentBody = std::move(result.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContentFile::doLinkTagSubstitution(const Path& basePath)
|
||||||
|
{
|
||||||
|
auto links = mContentBody->getAllLinks();
|
||||||
|
for (const auto link : links)
|
||||||
|
{
|
||||||
|
auto target = link->getTarget();
|
||||||
|
auto replaced_target = StringUtils::removeUpTo(target, "{filename}");
|
||||||
|
if (replaced_target != target)
|
||||||
|
{
|
||||||
|
auto full_path = mFilename.parent_path() / Path(replaced_target);
|
||||||
|
auto base_relative_path = PathUtils::getRelativePath(full_path, basePath);
|
||||||
|
auto output_path = PathUtils::getPathDelimited(base_relative_path);
|
||||||
|
link->setTarget(Path(output_path).replace_extension(".html"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string ContentFile::getMetadataItem(const std::string& key) const
|
std::string ContentFile::getMetadataItem(const std::string& key) const
|
||||||
{
|
{
|
||||||
const auto check = mMetadata.find(key);
|
const auto check = mMetadata.find(key);
|
||||||
|
@ -50,5 +70,6 @@ std::string ContentFile::getMetadataItem(const std::string& key) const
|
||||||
|
|
||||||
void ContentFile::write(const Path& path)
|
void ContentFile::write(const Path& path)
|
||||||
{
|
{
|
||||||
|
File file(path);
|
||||||
|
file.writeText(mProcessedOutput);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,14 @@ public:
|
||||||
return mContentBody.get();
|
return mContentBody.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void doLinkTagSubstitution(const Path& basePath);
|
||||||
|
|
||||||
void write(const Path& path);
|
void write(const Path& path);
|
||||||
|
|
||||||
|
void setProcessedOutput(const std::string& output)
|
||||||
|
{
|
||||||
|
mProcessedOutput = output;
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
Path mFilename;
|
Path mFilename;
|
||||||
FileMetadata mMetadata;
|
FileMetadata mMetadata;
|
||||||
|
|
|
@ -6,9 +6,14 @@
|
||||||
#include "ContentPage.h"
|
#include "ContentPage.h"
|
||||||
#include "TemplateFile.h"
|
#include "TemplateFile.h"
|
||||||
#include "TemplatingEngine.h"
|
#include "TemplatingEngine.h"
|
||||||
|
#include "TemplateSubstitutionContext.h"
|
||||||
#include "SiteGeneratorConfig.h"
|
#include "SiteGeneratorConfig.h"
|
||||||
#include "PathUtils.h"
|
#include "PathUtils.h"
|
||||||
|
|
||||||
|
#include "MarkdownConverter.h"
|
||||||
|
#include "HtmlElement.h"
|
||||||
|
#include "HtmlWriter.h"
|
||||||
|
|
||||||
#include "FileLogger.h"
|
#include "FileLogger.h"
|
||||||
|
|
||||||
WebsiteGenerator::WebsiteGenerator()
|
WebsiteGenerator::WebsiteGenerator()
|
||||||
|
@ -104,18 +109,35 @@ void WebsiteGenerator::parseTemplateFiles()
|
||||||
{
|
{
|
||||||
const auto template_path = mProjectPath / mConfig->getThemePath() / mConfig->getActiveTheme();
|
const auto template_path = mProjectPath / mConfig->getThemePath() / mConfig->getActiveTheme();
|
||||||
mTemplateEngine = std::make_unique<TemplatingEngine>(template_path);
|
mTemplateEngine = std::make_unique<TemplatingEngine>(template_path);
|
||||||
mTemplateEngine->loadTemplateFiles();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebsiteGenerator::doSubstitutions()
|
void WebsiteGenerator::doSubstitutions()
|
||||||
{
|
{
|
||||||
auto article_template = mTemplateEngine->processTemplate("article");
|
MarkdownConverter converter;
|
||||||
|
|
||||||
for (auto& article : mArticles)
|
for (auto& article : mArticles)
|
||||||
{
|
{
|
||||||
|
article->doLinkTagSubstitution(getArticlesPath());
|
||||||
|
|
||||||
|
auto containing_div = std::make_unique<HtmlDivElement>();
|
||||||
|
converter.convert(article->getContentBody(), containing_div.get());
|
||||||
|
|
||||||
|
HtmlWriter writer;
|
||||||
|
auto md_html_content = writer.toString(containing_div.get());
|
||||||
|
|
||||||
|
TemplateSubstitutionContext sub_context;
|
||||||
|
sub_context.addSubstitution("content", md_html_content);
|
||||||
|
|
||||||
|
auto content = mTemplateEngine->renderTemplate("article", &sub_context);
|
||||||
|
article->setProcessedOutput(content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Path WebsiteGenerator::getOutputPath() const
|
||||||
|
{
|
||||||
|
return mProjectPath / "output";
|
||||||
|
}
|
||||||
|
|
||||||
void WebsiteGenerator::write()
|
void WebsiteGenerator::write()
|
||||||
{
|
{
|
||||||
// Setup output dir
|
// Setup output dir
|
||||||
|
@ -129,6 +151,7 @@ void WebsiteGenerator::write()
|
||||||
auto relative_path = PathUtils::getRelativePath(article_path, getArticlesPath());
|
auto relative_path = PathUtils::getRelativePath(article_path, getArticlesPath());
|
||||||
auto updated_filename = PathUtils::getPathDelimited(relative_path);
|
auto updated_filename = PathUtils::getPathDelimited(relative_path);
|
||||||
auto final_path = output_dir / Path(updated_filename).replace_extension(".html");
|
auto final_path = output_dir / Path(updated_filename).replace_extension(".html");
|
||||||
|
article->write(final_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ private:
|
||||||
|
|
||||||
Path getConfigPath() const;
|
Path getConfigPath() const;
|
||||||
|
|
||||||
|
Path getOutputPath() const;
|
||||||
|
|
||||||
std::filesystem::path mProjectPath;
|
std::filesystem::path mProjectPath;
|
||||||
|
|
||||||
std::unique_ptr<SiteGeneratorConfig> mConfig;
|
std::unique_ptr<SiteGeneratorConfig> mConfig;
|
||||||
|
|
|
@ -2,24 +2,27 @@ set(MODULE_NAME compiler)
|
||||||
|
|
||||||
list(APPEND TARGET_HEADERS
|
list(APPEND TARGET_HEADERS
|
||||||
Lexer.h
|
Lexer.h
|
||||||
TemplatingEngine.h
|
template_engine/TemplatingEngine.h
|
||||||
TemplateFile.h
|
template_engine/TemplateFile.h
|
||||||
TemplateNodes.h
|
template_engine/TemplateNode.h
|
||||||
|
template_engine/TemplateElements.h
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND TARGET_SOURCES
|
list(APPEND TARGET_SOURCES
|
||||||
Lexer.cpp
|
Lexer.cpp
|
||||||
TemplatingEngine.cpp
|
template_engine/TemplatingEngine.cpp
|
||||||
TemplateFile.cpp
|
template_engine/TemplateFile.cpp
|
||||||
TemplateNodes.cpp
|
template_engine/TemplateNode.cpp
|
||||||
|
template_engine/TemplateElements.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(${MODULE_NAME} SHARED ${TARGET_SOURCES} ${TARGET_HEADERS})
|
add_library(${MODULE_NAME} SHARED ${TARGET_SOURCES} ${TARGET_HEADERS})
|
||||||
|
|
||||||
target_include_directories(${MODULE_NAME} PUBLIC
|
target_include_directories(${MODULE_NAME} PUBLIC
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/template_engine
|
||||||
)
|
)
|
||||||
target_link_libraries( ${MODULE_NAME} PUBLIC core)
|
target_link_libraries( ${MODULE_NAME} PUBLIC core)
|
||||||
|
|
||||||
set_target_properties( ${MODULE_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
set_target_properties( ${MODULE_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
||||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src)
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src)
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class TemplateNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TemplateNode(TemplateNode* parent);
|
|
||||||
|
|
||||||
virtual ~TemplateNode() = default;
|
|
||||||
|
|
||||||
TemplateNode* getParent() const;
|
|
||||||
|
|
||||||
virtual void addChild(std::unique_ptr<TemplateNode> child);
|
|
||||||
|
|
||||||
std::size_t getNumChildren() const;
|
|
||||||
|
|
||||||
virtual std::string getIdentifier() const;
|
|
||||||
|
|
||||||
TemplateNode* getChild(std::size_t index) const;
|
|
||||||
|
|
||||||
virtual std::string getRawContent() const;
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T* getFirstChildShallow(const std::string& identifier = {}) const
|
|
||||||
{
|
|
||||||
for (const auto& child : mChildren)
|
|
||||||
{
|
|
||||||
if (auto ret = dynamic_cast<T*>(child.get()))
|
|
||||||
{
|
|
||||||
if (!identifier.empty())
|
|
||||||
{
|
|
||||||
if (child->getIdentifier() == identifier)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setExtensionParent(TemplateNode* parent);
|
|
||||||
|
|
||||||
virtual std::string render(TemplateNode* parentContext = nullptr);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::vector<std::unique_ptr<TemplateNode> > mChildren;
|
|
||||||
TemplateNode* mParent{ nullptr };
|
|
||||||
TemplateNode* mExtensionParent{ nullptr };
|
|
||||||
};
|
|
||||||
|
|
||||||
using TemplateNodePtr = std::unique_ptr<TemplateNode>;
|
|
||||||
|
|
||||||
class TemplateExtends : public TemplateNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TemplateExtends(TemplateNode* parent, const std::string& path);
|
|
||||||
|
|
||||||
virtual ~TemplateExtends() = default;
|
|
||||||
|
|
||||||
std::string getRawContent() const override;
|
|
||||||
std::string getPath() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string mPath;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TemplateBlock : public TemplateNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TemplateBlock(TemplateNode* parent, const std::string& name);
|
|
||||||
|
|
||||||
virtual ~TemplateBlock() = default;
|
|
||||||
|
|
||||||
void addLine(const std::string& line);
|
|
||||||
|
|
||||||
std::string getRawContent() const override;
|
|
||||||
|
|
||||||
std::string renderAsParent(TemplateNode* base);
|
|
||||||
|
|
||||||
std::string render(TemplateNode* parentContext) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string mName;
|
|
||||||
std::vector<std::string> mBody;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TemplateExpression : public TemplateNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TemplateExpression(TemplateNode* parent, const std::string& content);
|
|
||||||
|
|
||||||
virtual ~TemplateExpression() = default;
|
|
||||||
|
|
||||||
std::string getRawContent() const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string mContent;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TemplateTextBody : public TemplateNode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TemplateTextBody(TemplateNode* parent);
|
|
||||||
|
|
||||||
virtual ~TemplateTextBody() = default;
|
|
||||||
|
|
||||||
void addLine(const std::string& content);
|
|
||||||
|
|
||||||
std::string getRawContent() const override;
|
|
||||||
|
|
||||||
bool hasContent() const;
|
|
||||||
|
|
||||||
std::string render(TemplateNode* parentContext) override;
|
|
||||||
private:
|
|
||||||
std::vector<std::string> mContent;
|
|
||||||
};
|
|
|
@ -1,67 +1,9 @@
|
||||||
#include "TemplateNodes.h"
|
#include "TemplateElements.h"
|
||||||
|
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
#include "TemplateSubstitutionContext.h"
|
||||||
|
|
||||||
TemplateNode::TemplateNode(TemplateNode* parent)
|
#include <iostream>
|
||||||
: mParent(parent)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateNode* TemplateNode::getParent() const
|
|
||||||
{
|
|
||||||
return mParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TemplateNode::addChild(std::unique_ptr<TemplateNode> child)
|
|
||||||
{
|
|
||||||
mChildren.push_back(std::move(child));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t TemplateNode::getNumChildren() const
|
|
||||||
{
|
|
||||||
return mChildren.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TemplateNode::getIdentifier() const
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateNode* TemplateNode::getChild(std::size_t index) const
|
|
||||||
{
|
|
||||||
return mChildren[index].get();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TemplateNode::getRawContent() const
|
|
||||||
{
|
|
||||||
std::string content;
|
|
||||||
for (const auto& child : mChildren)
|
|
||||||
{
|
|
||||||
content += child->getRawContent() + "\n";
|
|
||||||
}
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TemplateNode::setExtensionParent(TemplateNode* parent)
|
|
||||||
{
|
|
||||||
mExtensionParent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TemplateNode::render(TemplateNode* parentContext)
|
|
||||||
{
|
|
||||||
if (!parentContext && mExtensionParent)
|
|
||||||
{
|
|
||||||
parentContext = mExtensionParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string content;
|
|
||||||
for (size_t idx = 0; idx < mChildren.size(); idx++)
|
|
||||||
{
|
|
||||||
content += mChildren[idx]->render(parentContext);
|
|
||||||
}
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateExtends::TemplateExtends(TemplateNode* parent, const std::string& path)
|
TemplateExtends::TemplateExtends(TemplateNode* parent, const std::string& path)
|
||||||
: TemplateNode(parent)
|
: TemplateNode(parent)
|
||||||
|
@ -98,24 +40,64 @@ std::string TemplateBlock::getRawContent() const
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TemplateBlock::renderAsParent(TemplateNode* base)
|
std::string TemplateBlock::getIdentifier() const
|
||||||
{
|
{
|
||||||
return {};
|
return mName;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TemplateBlock::render(TemplateNode* parentContext)
|
std::string TemplateBlock::renderAsParent(TemplateSubstitutionContext* substitutions, TemplateBlock* base)
|
||||||
|
{
|
||||||
|
std::string content;
|
||||||
|
for (auto& child : mChildren)
|
||||||
|
{
|
||||||
|
if (child->getType() == Type::EXPRESSION)
|
||||||
|
{
|
||||||
|
auto expression = dynamic_cast<TemplateExpression*>(child.get());
|
||||||
|
std::cout << "Got expression with content " << expression->getContent() << std::endl;
|
||||||
|
if (expression->getContent() == "super()")
|
||||||
|
{
|
||||||
|
std::cout << "Adding expression base" << std::endl;
|
||||||
|
content += base->render(substitutions, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(child->getType() == Type::TEXT_BODY)
|
||||||
|
{
|
||||||
|
content += child->render(substitutions, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TemplateBlock::renderAsLeaf(TemplateSubstitutionContext* substitutions)
|
||||||
|
{
|
||||||
|
std::string content;
|
||||||
|
for (auto& child : mChildren)
|
||||||
|
{
|
||||||
|
if(child->getType() == Type::TEXT_BODY)
|
||||||
|
{
|
||||||
|
content += child->render(substitutions, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TemplateBlock::render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext)
|
||||||
{
|
{
|
||||||
std::string content;
|
std::string content;
|
||||||
if (parentContext)
|
if (parentContext)
|
||||||
{
|
{
|
||||||
if (auto parent_node = parentContext->getFirstChildShallow<TemplateBlock>(getIdentifier()))
|
if (auto parent_node = parentContext->getFirstChildShallow(Type::BLOCK, getIdentifier()))
|
||||||
{
|
{
|
||||||
content = dynamic_cast<TemplateBlock*>(parent_node)->renderAsParent(this);
|
content = dynamic_cast<TemplateBlock*>(parent_node)->renderAsParent(substitutions, this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
content= renderAsLeaf(substitutions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
content= renderAsLeaf(substitutions);
|
||||||
}
|
}
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
@ -127,6 +109,20 @@ TemplateExpression::TemplateExpression(TemplateNode* parent, const std::string&
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& TemplateExpression::getContent() const
|
||||||
|
{
|
||||||
|
return mContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TemplateExpression::render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext)
|
||||||
|
{
|
||||||
|
if (substitutions->hasSubstitution(mContent))
|
||||||
|
{
|
||||||
|
return substitutions->getSubstitution(mContent);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::string TemplateExpression::getRawContent() const
|
std::string TemplateExpression::getRawContent() const
|
||||||
{
|
{
|
||||||
return "TemplateExpression: " + mContent;
|
return "TemplateExpression: " + mContent;
|
||||||
|
@ -148,7 +144,7 @@ bool TemplateTextBody::hasContent() const
|
||||||
return !mContent.empty();
|
return !mContent.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TemplateTextBody::render(TemplateNode* parentContext)
|
std::string TemplateTextBody::render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext)
|
||||||
{
|
{
|
||||||
std::string content;
|
std::string content;
|
||||||
for (const auto& line : mContent)
|
for (const auto& line : mContent)
|
96
src/compiler/template_engine/TemplateElements.h
Normal file
96
src/compiler/template_engine/TemplateElements.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "TemplateNode.h"
|
||||||
|
|
||||||
|
class TemplateExtends : public TemplateNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TemplateExtends(TemplateNode* parent, const std::string& path);
|
||||||
|
|
||||||
|
virtual ~TemplateExtends() = default;
|
||||||
|
|
||||||
|
std::string getRawContent() const override;
|
||||||
|
std::string getPath() const;
|
||||||
|
|
||||||
|
Type getType() const override
|
||||||
|
{
|
||||||
|
return Type::EXTENDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string mPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TemplateBlock : public TemplateNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TemplateBlock(TemplateNode* parent, const std::string& name);
|
||||||
|
|
||||||
|
virtual ~TemplateBlock() = default;
|
||||||
|
|
||||||
|
void addLine(const std::string& line);
|
||||||
|
|
||||||
|
std::string getRawContent() const override;
|
||||||
|
|
||||||
|
std::string getIdentifier() const override;
|
||||||
|
|
||||||
|
Type getType() const override
|
||||||
|
{
|
||||||
|
return Type::BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string renderAsParent(TemplateSubstitutionContext* substitutions, TemplateBlock* base);
|
||||||
|
|
||||||
|
std::string renderAsLeaf(TemplateSubstitutionContext* substitutions);
|
||||||
|
|
||||||
|
std::string render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string mName;
|
||||||
|
std::vector<std::string> mBody;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TemplateExpression : public TemplateNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TemplateExpression(TemplateNode* parent, const std::string& content);
|
||||||
|
|
||||||
|
virtual ~TemplateExpression() = default;
|
||||||
|
|
||||||
|
std::string getRawContent() const override;
|
||||||
|
|
||||||
|
const std::string& getContent() const;
|
||||||
|
|
||||||
|
Type getType() const override
|
||||||
|
{
|
||||||
|
return Type::EXPRESSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string mContent;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TemplateTextBody : public TemplateNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TemplateTextBody(TemplateNode* parent);
|
||||||
|
|
||||||
|
virtual ~TemplateTextBody() = default;
|
||||||
|
|
||||||
|
void addLine(const std::string& content);
|
||||||
|
|
||||||
|
std::string getRawContent() const override;
|
||||||
|
|
||||||
|
bool hasContent() const;
|
||||||
|
|
||||||
|
std::string render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext) override;
|
||||||
|
|
||||||
|
Type getType() const override
|
||||||
|
{
|
||||||
|
return Type::TEXT_BODY;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::vector<std::string> mContent;
|
||||||
|
};
|
|
@ -1,19 +1,20 @@
|
||||||
#include "TemplateFile.h"
|
#include "TemplateFile.h"
|
||||||
|
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
#include "TemplateElements.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
TemplateFile::TemplateFile(const Path& path)
|
TemplateFile::TemplateFile(const Path& path)
|
||||||
: mPath(path),
|
: mPath(path),
|
||||||
mRootNode(std::make_unique<TemplateNode>(nullptr))
|
mRootNode(std::make_unique<TemplateNode>(nullptr))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> TemplateFile::getProcessedContent() const
|
TemplateFile::~TemplateFile()
|
||||||
{
|
{
|
||||||
return mProcessedContent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TemplateFile::getName() const
|
std::string TemplateFile::getName() const
|
||||||
|
@ -21,9 +22,23 @@ std::string TemplateFile::getName() const
|
||||||
return mPath.stem().string();
|
return mPath.stem().string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TemplateFile::hasLoaded() const
|
||||||
|
{
|
||||||
|
return mHasLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateNode* TemplateFile::getContent() const
|
||||||
|
{
|
||||||
|
return mRootNode.get();
|
||||||
|
}
|
||||||
|
|
||||||
void TemplateFile::loadContent()
|
void TemplateFile::loadContent()
|
||||||
{
|
{
|
||||||
//std::cout << "Trying to load file at: " << mPath << std::endl;
|
if (mHasLoaded)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mRawContent = File(mPath).readLines();
|
mRawContent = File(mPath).readLines();
|
||||||
mWorkingLine = 0;
|
mWorkingLine = 0;
|
||||||
mWorkingNode = mRootNode.get();
|
mWorkingNode = mRootNode.get();
|
||||||
|
@ -34,6 +49,8 @@ void TemplateFile::loadContent()
|
||||||
mWorkingLine++;
|
mWorkingLine++;
|
||||||
}
|
}
|
||||||
onTextBodyFinished();
|
onTextBodyFinished();
|
||||||
|
|
||||||
|
mHasLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemplateFile::onTextBodyFinished(std::string working_string)
|
void TemplateFile::onTextBodyFinished(std::string working_string)
|
||||||
|
@ -178,12 +195,12 @@ void TemplateFile::onFoundExtends(const std::vector<std::string> args)
|
||||||
|
|
||||||
void TemplateFile::onFoundExpression(const std::string& expression_string)
|
void TemplateFile::onFoundExpression(const std::string& expression_string)
|
||||||
{
|
{
|
||||||
auto expression = std::make_unique<TemplateExpression>(mWorkingNode, expression_string);
|
auto stripped = StringUtils::strip(expression_string);
|
||||||
|
auto expression = std::make_unique<TemplateExpression>(mWorkingNode, stripped);
|
||||||
mWorkingNode->addChild(std::move(expression));
|
mWorkingNode->addChild(std::move(expression));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemplateFile::dumpContent()
|
std::string TemplateFile::dumpContent()
|
||||||
{
|
{
|
||||||
auto content = mRootNode->getRawContent();
|
return mRootNode->getRawContent();
|
||||||
//std::cout << content << std::endl;
|
|
||||||
}
|
}
|
|
@ -2,21 +2,31 @@
|
||||||
|
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
|
|
||||||
#include "TemplateNodes.h"
|
#include "TemplateNode.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class TemplateNode;
|
||||||
|
class TemplateTextBody;
|
||||||
|
|
||||||
class TemplateFile
|
class TemplateFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TemplateFile(const Path& path);
|
TemplateFile(const Path& path);
|
||||||
|
|
||||||
std::vector<std::string> getProcessedContent() const;
|
~TemplateFile();
|
||||||
|
|
||||||
|
std::string dumpContent();
|
||||||
|
|
||||||
std::string getName() const;
|
std::string getName() const;
|
||||||
|
|
||||||
|
TemplateNode* getContent() const;
|
||||||
|
|
||||||
|
bool hasLoaded() const;
|
||||||
|
|
||||||
void loadContent();
|
void loadContent();
|
||||||
|
|
||||||
|
private:
|
||||||
void onTextBodyFinished(std::string working_string = {});
|
void onTextBodyFinished(std::string working_string = {});
|
||||||
|
|
||||||
void processLine(const std::string& line);
|
void processLine(const std::string& line);
|
||||||
|
@ -31,19 +41,12 @@ public:
|
||||||
|
|
||||||
void onFoundExpression(const std::string& expression_string);
|
void onFoundExpression(const std::string& expression_string);
|
||||||
|
|
||||||
void dumpContent();
|
|
||||||
|
|
||||||
TemplateNode* getContent() const
|
|
||||||
{
|
|
||||||
return mRootNode.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Path mPath;
|
Path mPath;
|
||||||
unsigned mWorkingLine{ 0 };
|
|
||||||
std::string mParentName;
|
std::string mParentName;
|
||||||
std::vector<std::string> mRawContent;
|
std::vector<std::string> mRawContent;
|
||||||
std::vector<std::string> mProcessedContent;
|
bool mHasLoaded{false};
|
||||||
|
|
||||||
|
unsigned mWorkingLine{ 0 };
|
||||||
std::unique_ptr<TemplateNode> mRootNode;
|
std::unique_ptr<TemplateNode> mRootNode;
|
||||||
TemplateNode* mWorkingNode{ nullptr };
|
TemplateNode* mWorkingNode{ nullptr };
|
||||||
std::unique_ptr<TemplateTextBody> mWorkingTextBody;
|
std::unique_ptr<TemplateTextBody> mWorkingTextBody;
|
91
src/compiler/template_engine/TemplateNode.cpp
Normal file
91
src/compiler/template_engine/TemplateNode.cpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#include "TemplateNode.h"
|
||||||
|
|
||||||
|
#include "TemplateSubstitutionContext.h"
|
||||||
|
|
||||||
|
TemplateNode::TemplateNode(TemplateNode* parent)
|
||||||
|
: mParent(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateNode* TemplateNode::getParent() const
|
||||||
|
{
|
||||||
|
return mParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TemplateNode::addChild(std::unique_ptr<TemplateNode> child)
|
||||||
|
{
|
||||||
|
mChildren.push_back(std::move(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t TemplateNode::getNumChildren() const
|
||||||
|
{
|
||||||
|
return mChildren.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateNode* TemplateNode::getFirstChildShallow(Type type, const std::string& identifier) const
|
||||||
|
{
|
||||||
|
for (const auto& child : mChildren)
|
||||||
|
{
|
||||||
|
if (child->getType() == type)
|
||||||
|
{
|
||||||
|
if (!identifier.empty())
|
||||||
|
{
|
||||||
|
if (child->getIdentifier() == identifier)
|
||||||
|
{
|
||||||
|
return child.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return child.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateNode::Type TemplateNode::getType() const
|
||||||
|
{
|
||||||
|
return Type::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TemplateNode::getIdentifier() const
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateNode* TemplateNode::getChild(std::size_t index) const
|
||||||
|
{
|
||||||
|
return mChildren[index].get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TemplateNode::getRawContent() const
|
||||||
|
{
|
||||||
|
std::string content;
|
||||||
|
for (const auto& child : mChildren)
|
||||||
|
{
|
||||||
|
content += child->getRawContent() + "\n";
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TemplateNode::setExtensionParent(TemplateNode* parent)
|
||||||
|
{
|
||||||
|
mExtensionParent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TemplateNode::render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext)
|
||||||
|
{
|
||||||
|
if (!parentContext && mExtensionParent)
|
||||||
|
{
|
||||||
|
parentContext = mExtensionParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string content;
|
||||||
|
for (size_t idx = 0; idx < mChildren.size(); idx++)
|
||||||
|
{
|
||||||
|
content += mChildren[idx]->render(substitutions, parentContext);
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
51
src/compiler/template_engine/TemplateNode.h
Normal file
51
src/compiler/template_engine/TemplateNode.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class TemplateSubstitutionContext;
|
||||||
|
|
||||||
|
class TemplateNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Type
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
BLOCK,
|
||||||
|
EXPRESSION,
|
||||||
|
EXTENDS,
|
||||||
|
TEXT_BODY
|
||||||
|
};
|
||||||
|
|
||||||
|
TemplateNode(TemplateNode* parent);
|
||||||
|
|
||||||
|
virtual ~TemplateNode() = default;
|
||||||
|
|
||||||
|
virtual void addChild(std::unique_ptr<TemplateNode> child);
|
||||||
|
|
||||||
|
TemplateNode* getChild(std::size_t index) const;
|
||||||
|
|
||||||
|
TemplateNode* getFirstChildShallow(Type type, const std::string& identifier = {}) const;
|
||||||
|
|
||||||
|
virtual std::string getIdentifier() const;
|
||||||
|
|
||||||
|
std::size_t getNumChildren() const;
|
||||||
|
|
||||||
|
TemplateNode* getParent() const;
|
||||||
|
|
||||||
|
virtual std::string getRawContent() const;
|
||||||
|
|
||||||
|
virtual Type getType() const;
|
||||||
|
|
||||||
|
virtual std::string render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext = nullptr);
|
||||||
|
|
||||||
|
void setExtensionParent(TemplateNode* parent);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<std::unique_ptr<TemplateNode> > mChildren;
|
||||||
|
TemplateNode* mParent{ nullptr };
|
||||||
|
TemplateNode* mExtensionParent{ nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
|
using TemplateNodePtr = std::unique_ptr<TemplateNode>;
|
35
src/compiler/template_engine/TemplateSubstitutionContext.h
Normal file
35
src/compiler/template_engine/TemplateSubstitutionContext.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class TemplateSubstitutionContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void addSubstitution(const std::string& key, const std::string& value)
|
||||||
|
{
|
||||||
|
mSubstitutions[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasSubstitution(const std::string& key) const
|
||||||
|
{
|
||||||
|
return mSubstitutions.find(key) != mSubstitutions.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getSubstitution(const std::string& key) const
|
||||||
|
{
|
||||||
|
auto iter = mSubstitutions.find(key);
|
||||||
|
if(iter != mSubstitutions.end())
|
||||||
|
{
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, std::string> mSubstitutions;
|
||||||
|
};
|
|
@ -3,6 +3,9 @@
|
||||||
#include "Directory.h"
|
#include "Directory.h"
|
||||||
#include "FileLogger.h"
|
#include "FileLogger.h"
|
||||||
|
|
||||||
|
#include "TemplateElements.h"
|
||||||
|
#include "TemplateSubstitutionContext.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
TemplatingEngine::TemplatingEngine(const Path& workingDirectory)
|
TemplatingEngine::TemplatingEngine(const Path& workingDirectory)
|
||||||
|
@ -11,6 +14,32 @@ TemplatingEngine::TemplatingEngine(const Path& workingDirectory)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string TemplatingEngine::renderTemplate(const std::string& name, TemplateSubstitutionContext* substitutionContext)
|
||||||
|
{
|
||||||
|
if (mTemplateFiles.empty())
|
||||||
|
{
|
||||||
|
loadTemplateFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto file = getTemplateFile(name))
|
||||||
|
{
|
||||||
|
if (!file->hasLoaded())
|
||||||
|
{
|
||||||
|
file->loadContent();
|
||||||
|
std::cout << file->dumpContent();
|
||||||
|
|
||||||
|
processTemplate(file, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file->getContent()->render(substitutionContext, nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void TemplatingEngine::loadTemplateFiles()
|
void TemplatingEngine::loadTemplateFiles()
|
||||||
{
|
{
|
||||||
const auto files = Directory::getFilesWithExtension(mWorkingDirectory, mTemplateExtension);
|
const auto files = Directory::getFilesWithExtension(mWorkingDirectory, mTemplateExtension);
|
||||||
|
@ -21,15 +50,6 @@ void TemplatingEngine::loadTemplateFiles()
|
||||||
MLOG_INFO("Found: " << mTemplateFiles.size() << " templates in " << mWorkingDirectory);
|
MLOG_INFO("Found: " << mTemplateFiles.size() << " templates in " << mWorkingDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TemplatingEngine::processTemplate(const std::string& name)
|
|
||||||
{
|
|
||||||
if (auto file = getTemplateFile(name))
|
|
||||||
{
|
|
||||||
return processTemplate(file);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateFile* TemplatingEngine::getTemplateFile(const Path& path)
|
TemplateFile* TemplatingEngine::getTemplateFile(const Path& path)
|
||||||
{
|
{
|
||||||
return getTemplateFile(path.stem().string());
|
return getTemplateFile(path.stem().string());
|
||||||
|
@ -40,37 +60,24 @@ TemplateFile* TemplatingEngine::getTemplateFile(const std::string& name)
|
||||||
return mTemplateFiles[name].get();
|
return mTemplateFiles[name].get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TemplatingEngine::processTemplate(TemplateFile* file, TemplateNode* parent)
|
void TemplatingEngine::processTemplate(TemplateFile* file, TemplateNode* parent)
|
||||||
{
|
{
|
||||||
file->loadContent();
|
std::cout << "Processing file " << file->getName() << std::endl;
|
||||||
file->dumpContent();
|
|
||||||
|
|
||||||
auto content = file->getContent();
|
auto content = file->getContent();
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
|
std::cout << "Setting extension parent" << std::endl;
|
||||||
content->setExtensionParent(parent);
|
content->setExtensionParent(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto extension_node = content->getFirstChildShallow<TemplateExtends>())
|
if (auto extension_node = dynamic_cast<TemplateExtends*>(content->getFirstChildShallow(TemplateNode::Type::EXTENDS)))
|
||||||
{
|
{
|
||||||
//std::cout << "Found extension node" << std::endl;
|
std::cout << "Found extension node " << std::endl;
|
||||||
if (auto extension_template = getTemplateFile(Path(extension_node->getPath())))
|
if (auto extension_template = getTemplateFile(Path(extension_node->getPath())))
|
||||||
{
|
{
|
||||||
//std::cout << "Found extension template" << std::endl;
|
std::cout << "Found extension template " << std::endl;
|
||||||
return processTemplate(extension_template, parent);
|
processTemplate(extension_template, content);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return render(content);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return render(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TemplatingEngine::render(TemplateNode* content)
|
|
||||||
{
|
|
||||||
return content->render();
|
|
||||||
}
|
}
|
|
@ -8,20 +8,21 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class TemplateSubstitutionContext;
|
||||||
|
|
||||||
class TemplatingEngine
|
class TemplatingEngine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TemplatingEngine(const Path& workingDirectory);
|
TemplatingEngine(const Path& workingDirectory);
|
||||||
|
|
||||||
void loadTemplateFiles();
|
std::string renderTemplate(const std::string& name, TemplateSubstitutionContext* substitutionContext);
|
||||||
|
|
||||||
std::string processTemplate(const std::string& name);
|
|
||||||
private:
|
private:
|
||||||
TemplateFile* getTemplateFile(const std::string& name);
|
TemplateFile* getTemplateFile(const std::string& name);
|
||||||
TemplateFile* getTemplateFile(const Path& path);
|
TemplateFile* getTemplateFile(const Path& path);
|
||||||
std::string render(TemplateNode* content);
|
|
||||||
|
|
||||||
std::string processTemplate(TemplateFile* file, TemplateNode* parent = nullptr);
|
void loadTemplateFiles();
|
||||||
|
void processTemplate(TemplateFile* file, TemplateNode* parent = nullptr);
|
||||||
|
|
||||||
std::unordered_map<std::string, std::unique_ptr<TemplateFile> > mTemplateFiles;
|
std::unordered_map<std::string, std::unique_ptr<TemplateFile> > mTemplateFiles;
|
||||||
Path mWorkingDirectory;
|
Path mWorkingDirectory;
|
|
@ -53,13 +53,11 @@ std::string StringUtils::strip(const std::string& input)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::locale loc;
|
|
||||||
std::string working_string;
|
|
||||||
std::size_t first_nonspace = 0;
|
std::size_t first_nonspace = 0;
|
||||||
std::size_t last_nonspace = working_string.size() - 1;
|
std::size_t last_nonspace = input.size() - 1;
|
||||||
for (std::size_t idx = 0; idx < working_string.size(); idx++)
|
for (std::size_t idx = 0; idx < input.size(); idx++)
|
||||||
{
|
{
|
||||||
if (!std::isspace(working_string[idx], loc))
|
if (!std::isspace(input[idx]))
|
||||||
{
|
{
|
||||||
first_nonspace = idx;
|
first_nonspace = idx;
|
||||||
break;
|
break;
|
||||||
|
@ -73,13 +71,13 @@ std::string StringUtils::strip(const std::string& input)
|
||||||
|
|
||||||
for (std::size_t idx = last_nonspace; idx > 0; idx--)
|
for (std::size_t idx = last_nonspace; idx > 0; idx--)
|
||||||
{
|
{
|
||||||
if (!std::isspace(working_string[idx], loc))
|
if (!std::isspace(input[idx]))
|
||||||
{
|
{
|
||||||
last_nonspace = idx;
|
last_nonspace = idx;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return working_string.substr(first_nonspace, last_nonspace-first_nonspace);
|
return input.substr(first_nonspace, last_nonspace-first_nonspace + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> StringUtils::split(const std::string& input)
|
std::vector<std::string> StringUtils::split(const std::string& input)
|
||||||
|
@ -166,3 +164,21 @@ std::string StringUtils::stripQuotes(const std::string& input)
|
||||||
}
|
}
|
||||||
return input.substr(start_index, end_index - start_index + 1);
|
return input.substr(start_index, end_index - start_index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string StringUtils::replaceWith(const std::string& inputString, const std::string& searchString, const std::string& replaceString)
|
||||||
|
{
|
||||||
|
return inputString;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string StringUtils::removeUpTo(const std::string& input, const std::string& prefix)
|
||||||
|
{
|
||||||
|
std::size_t found = input.find(prefix);
|
||||||
|
if (found!=std::string::npos)
|
||||||
|
{
|
||||||
|
return input.substr(found, prefix.size());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@ public:
|
||||||
static std::vector<std::string> split(const std::string& input);
|
static std::vector<std::string> split(const std::string& input);
|
||||||
static std::string strip(const std::string& input);
|
static std::string strip(const std::string& input);
|
||||||
|
|
||||||
|
static std::string removeUpTo(const std::string& input, const std::string& prefix);
|
||||||
|
|
||||||
static std::vector<std::string> toLines(const std::string& input);
|
static std::vector<std::string> toLines(const std::string& input);
|
||||||
|
|
||||||
static std::string stripQuotes(const std::string& input);
|
static std::string stripQuotes(const std::string& input);
|
||||||
|
@ -34,4 +36,6 @@ public:
|
||||||
static std::vector<unsigned char> toBytes(const std::string& input);
|
static std::vector<unsigned char> toBytes(const std::string& input);
|
||||||
static std::string toString(const std::vector<unsigned char>& bytes);
|
static std::string toString(const std::vector<unsigned char>& bytes);
|
||||||
|
|
||||||
|
static std::string replaceWith(const std::string& inputString, const std::string& searchString, const std::string& replaceString);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "MarkdownParser.h"
|
#include "MarkdownParser.h"
|
||||||
#include "MarkdownDocument.h"
|
#include "MarkdownDocument.h"
|
||||||
#include "MarkdownConverter.h"
|
#include "MarkdownConverter.h"
|
||||||
|
#include "MarkdownElement.h"
|
||||||
|
|
||||||
#include "HtmlDocument.h"
|
#include "HtmlDocument.h"
|
||||||
#include "HtmlWriter.h"
|
#include "HtmlWriter.h"
|
||||||
|
|
|
@ -31,3 +31,8 @@ void HtmlDocument::addElementToBody(std::unique_ptr<HtmlElement> element)
|
||||||
body_element->addChild(std::move(element));
|
body_element->addChild(std::move(element));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HtmlBodyElement* HtmlDocument::getBodyElement() const
|
||||||
|
{
|
||||||
|
return dynamic_cast<HtmlBodyElement*>(getRoot()->getFirstChildWithTagName("body"));
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class HtmlElement;
|
class HtmlElement;
|
||||||
|
class HtmlBodyElement;
|
||||||
|
|
||||||
class HtmlDocument : public XmlDocument
|
class HtmlDocument : public XmlDocument
|
||||||
{
|
{
|
||||||
|
@ -17,6 +18,8 @@ public:
|
||||||
|
|
||||||
void addElementToBody(std::unique_ptr<HtmlElement> element);
|
void addElementToBody(std::unique_ptr<HtmlElement> element);
|
||||||
|
|
||||||
|
HtmlBodyElement* getBodyElement() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,8 @@ public:
|
||||||
HYPERLINK,
|
HYPERLINK,
|
||||||
IMAGE,
|
IMAGE,
|
||||||
UNORDERED_LIST,
|
UNORDERED_LIST,
|
||||||
LIST_ITEM
|
LIST_ITEM,
|
||||||
|
DIV
|
||||||
};
|
};
|
||||||
|
|
||||||
HtmlElement(const std::string& tagName);
|
HtmlElement(const std::string& tagName);
|
||||||
|
@ -27,6 +28,20 @@ public:
|
||||||
virtual Type getType() const = 0;
|
virtual Type getType() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HtmlDivElement : public HtmlElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HtmlDivElement() : HtmlElement("div")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Type getType() const override
|
||||||
|
{
|
||||||
|
return Type::DIV;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class HtmlCodeElement : public HtmlElement
|
class HtmlCodeElement : public HtmlElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
#include "HtmlWriter.h"
|
#include "HtmlWriter.h"
|
||||||
|
|
||||||
#include "HtmlDocument.h"
|
#include "HtmlDocument.h"
|
||||||
|
#include "HtmlElement.h"
|
||||||
#include "XmlElement.h"
|
#include "XmlElement.h"
|
||||||
#include "XmlAttribute.h"
|
#include "XmlAttribute.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
HtmlWriter::HtmlWriter()
|
HtmlWriter::HtmlWriter()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string HtmlWriter::toString(HtmlElement* element, unsigned startDepth)
|
||||||
|
{
|
||||||
|
return element->toString(startDepth);
|
||||||
|
}
|
||||||
|
|
||||||
std::string HtmlWriter::toString(HtmlDocument* document)
|
std::string HtmlWriter::toString(HtmlDocument* document)
|
||||||
{
|
{
|
||||||
std::string content = "<!DOCTYPE html>\n";
|
std::string content = "<!DOCTYPE html>\n";
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class HtmlDocument;
|
class HtmlDocument;
|
||||||
|
class HtmlElement;
|
||||||
|
|
||||||
class HtmlWriter
|
class HtmlWriter
|
||||||
{
|
{
|
||||||
|
@ -10,4 +11,6 @@ public:
|
||||||
HtmlWriter();
|
HtmlWriter();
|
||||||
|
|
||||||
std::string toString(HtmlDocument* document);
|
std::string toString(HtmlDocument* document);
|
||||||
|
|
||||||
|
std::string toString(HtmlElement* element, unsigned startDepth=0);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "MarkdownComponents.h"
|
#include "MarkdownComponents.h"
|
||||||
|
|
||||||
|
#include "StringUtils.h"
|
||||||
|
|
||||||
MarkdownTextSpan::Type MarkdownTextSpan::getType() const
|
MarkdownTextSpan::Type MarkdownTextSpan::getType() const
|
||||||
{
|
{
|
||||||
return Type::TEXT_SPAN;
|
return Type::TEXT_SPAN;
|
||||||
|
@ -87,6 +89,13 @@ MarkdownLink::Type MarkdownLink::getType() const
|
||||||
return Type::LINK;
|
return Type::LINK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MarkdownLink::doFieldSubstitution(Type elementType, const std::string& searchPhrase, const std::string& replacementPhrase)
|
||||||
|
{
|
||||||
|
if (elementType == Type::LINK)
|
||||||
|
{
|
||||||
|
mTarget = StringUtils::replaceWith(mTarget, searchPhrase, replacementPhrase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MarkdownImage::MarkdownImage(const std::string& source, const std::string& alt)
|
MarkdownImage::MarkdownImage(const std::string& source, const std::string& alt)
|
||||||
: mSource(source),
|
: mSource(source),
|
||||||
|
|
|
@ -13,6 +13,28 @@ public:
|
||||||
Type getType() const override;
|
Type getType() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownLink : public MarkdownInlineElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MarkdownLink(const std::string& target);
|
||||||
|
|
||||||
|
virtual ~MarkdownLink() = default;
|
||||||
|
|
||||||
|
const std::string& getTarget() const;
|
||||||
|
|
||||||
|
Type getType() const override;
|
||||||
|
|
||||||
|
void setTarget(const std::string& target)
|
||||||
|
{
|
||||||
|
mTarget = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
void doFieldSubstitution(Type elementType, const std::string& searchPhrase, const std::string& replacementPhrase) override;
|
||||||
|
private:
|
||||||
|
std::string mTarget;
|
||||||
|
};
|
||||||
|
|
||||||
class MarkdownParagraph : public MarkdownElement
|
class MarkdownParagraph : public MarkdownElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -26,6 +48,27 @@ public:
|
||||||
|
|
||||||
MarkdownInlineElement* getChild(std::size_t idx) const;
|
MarkdownInlineElement* getChild(std::size_t idx) const;
|
||||||
|
|
||||||
|
void doFieldSubstitution(Type elementType, const std::string& searchPhrase, const std::string& replacementPhrase) override
|
||||||
|
{
|
||||||
|
for(auto& child : mChildren)
|
||||||
|
{
|
||||||
|
child->doFieldSubstitution(elementType, searchPhrase, replacementPhrase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<MarkdownLink*> getAllLinks() const
|
||||||
|
{
|
||||||
|
std::vector<MarkdownLink*> links;
|
||||||
|
for(auto& child : mChildren)
|
||||||
|
{
|
||||||
|
if (child->getType() == Type::LINK)
|
||||||
|
{
|
||||||
|
links.push_back(dynamic_cast<MarkdownLink*>(child.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<MarkdownInlineElement> > mChildren;
|
std::vector<std::unique_ptr<MarkdownInlineElement> > mChildren;
|
||||||
};
|
};
|
||||||
|
@ -79,20 +122,6 @@ public:
|
||||||
Type getType() const override;
|
Type getType() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MarkdownLink : public MarkdownInlineElement
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MarkdownLink(const std::string& target);
|
|
||||||
|
|
||||||
virtual ~MarkdownLink() = default;
|
|
||||||
|
|
||||||
const std::string& getTarget() const;
|
|
||||||
|
|
||||||
Type getType() const override;
|
|
||||||
private:
|
|
||||||
std::string mTarget;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MarkdownImage : public MarkdownInlineElement
|
class MarkdownImage : public MarkdownInlineElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -3,16 +3,15 @@
|
||||||
#include "HtmlDocument.h"
|
#include "HtmlDocument.h"
|
||||||
#include "HtmlElement.h"
|
#include "HtmlElement.h"
|
||||||
#include "HtmlParagraphElement.h"
|
#include "HtmlParagraphElement.h"
|
||||||
|
#include "HtmlBodyElement.h"
|
||||||
#include "HtmlTextRun.h"
|
#include "HtmlTextRun.h"
|
||||||
#include "MarkdownElement.h"
|
#include "MarkdownElement.h"
|
||||||
#include "MarkdownComponents.h"
|
#include "MarkdownComponents.h"
|
||||||
|
|
||||||
#include "MarkdownDocument.h"
|
#include "MarkdownDocument.h"
|
||||||
|
|
||||||
std::unique_ptr<HtmlDocument> MarkdownConverter::convert(MarkdownDocument* markdownDoc) const
|
void MarkdownConverter::convert(MarkdownDocument* markdownDoc, HtmlElement* parentElement) const
|
||||||
{
|
{
|
||||||
auto html_doc = std::make_unique<HtmlDocument>();
|
|
||||||
|
|
||||||
for(unsigned idx=0; idx<markdownDoc->getNumElements();idx++)
|
for(unsigned idx=0; idx<markdownDoc->getNumElements();idx++)
|
||||||
{
|
{
|
||||||
auto md_element = markdownDoc->getElement(idx);
|
auto md_element = markdownDoc->getElement(idx);
|
||||||
|
@ -23,7 +22,7 @@ std::unique_ptr<HtmlDocument> MarkdownConverter::convert(MarkdownDocument* markd
|
||||||
auto html_element = std::make_unique<HtmlHeadingElement>(heading_level);
|
auto html_element = std::make_unique<HtmlHeadingElement>(heading_level);
|
||||||
html_element->setText(md_element->getTextContent());
|
html_element->setText(md_element->getTextContent());
|
||||||
|
|
||||||
html_doc->addElementToBody(std::move(html_element));
|
parentElement->addChild(std::move(html_element));
|
||||||
}
|
}
|
||||||
else if(md_element->getType() == MarkdownElement::Type::PARAGRAPH)
|
else if(md_element->getType() == MarkdownElement::Type::PARAGRAPH)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +58,7 @@ std::unique_ptr<HtmlDocument> MarkdownConverter::convert(MarkdownDocument* markd
|
||||||
html_p_element->addChild(std::move(html_text));
|
html_p_element->addChild(std::move(html_text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
html_doc->addElementToBody(std::move(html_p_element));
|
parentElement->addChild(std::move(html_p_element));
|
||||||
}
|
}
|
||||||
else if(md_element->getType() == MarkdownElement::Type::BULLET_LIST)
|
else if(md_element->getType() == MarkdownElement::Type::BULLET_LIST)
|
||||||
{
|
{
|
||||||
|
@ -72,15 +71,23 @@ std::unique_ptr<HtmlDocument> MarkdownConverter::convert(MarkdownDocument* markd
|
||||||
html_list_item->setText(child->getTextContent());
|
html_list_item->setText(child->getTextContent());
|
||||||
html_list->addChild(std::move(html_list_item));
|
html_list->addChild(std::move(html_list_item));
|
||||||
}
|
}
|
||||||
html_doc->addElementToBody(std::move(html_list));
|
parentElement->addChild(std::move(html_list));
|
||||||
}
|
}
|
||||||
else if(md_element->getType() == MarkdownElement::Type::MULTILINE_QUOTE)
|
else if(md_element->getType() == MarkdownElement::Type::MULTILINE_QUOTE)
|
||||||
{
|
{
|
||||||
auto html_quote = std::make_unique<HtmlCodeElement>();
|
auto html_quote = std::make_unique<HtmlCodeElement>();
|
||||||
html_quote->setText(md_element->getTextContent());
|
html_quote->setText(md_element->getTextContent());
|
||||||
html_doc->addElementToBody(std::move(html_quote));
|
parentElement->addChild(std::move(html_quote));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<HtmlDocument> MarkdownConverter::convert(MarkdownDocument* markdownDoc) const
|
||||||
|
{
|
||||||
|
auto html_doc = std::make_unique<HtmlDocument>();
|
||||||
|
|
||||||
|
auto body_element = html_doc->getBodyElement();
|
||||||
|
convert(markdownDoc, body_element);
|
||||||
|
|
||||||
return std::move(html_doc);
|
return std::move(html_doc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class HtmlDocument;
|
class HtmlDocument;
|
||||||
|
class HtmlElement;
|
||||||
class MarkdownDocument;
|
class MarkdownDocument;
|
||||||
|
|
||||||
class MarkdownConverter
|
class MarkdownConverter
|
||||||
|
@ -10,4 +11,6 @@ class MarkdownConverter
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<HtmlDocument> convert(MarkdownDocument* markdownDoc) const;
|
std::unique_ptr<HtmlDocument> convert(MarkdownDocument* markdownDoc) const;
|
||||||
|
|
||||||
|
void convert(MarkdownDocument* markdownDoc, HtmlElement* parentElement) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "MarkdownDocument.h"
|
#include "MarkdownDocument.h"
|
||||||
|
|
||||||
#include "MarkdownElement.h"
|
#include "MarkdownElement.h"
|
||||||
|
#include "MarkdownComponents.h"
|
||||||
|
|
||||||
|
|
||||||
void MarkdownDocument::addElement(std::unique_ptr<MarkdownElement> element)
|
void MarkdownDocument::addElement(std::unique_ptr<MarkdownElement> element)
|
||||||
{
|
{
|
||||||
|
@ -16,3 +18,25 @@ MarkdownElement* MarkdownDocument::getElement(std::size_t idx) const
|
||||||
{
|
{
|
||||||
return mElements[idx].get();
|
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;
|
||||||
|
for(auto& element : mElements)
|
||||||
|
{
|
||||||
|
if (element->getType() == MarkdownElement::Type::PARAGRAPH)
|
||||||
|
{
|
||||||
|
auto para_links = dynamic_cast<MarkdownParagraph*>(element.get())->getAllLinks();
|
||||||
|
links.insert(links.end(), para_links.begin(), para_links.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class MarkdownElement;
|
class MarkdownElement;
|
||||||
|
class MarkdownLink;
|
||||||
|
|
||||||
class MarkdownDocument
|
class MarkdownDocument
|
||||||
{
|
{
|
||||||
|
@ -14,6 +15,10 @@ public:
|
||||||
|
|
||||||
MarkdownElement* getElement(std::size_t idx) const;
|
MarkdownElement* getElement(std::size_t idx) const;
|
||||||
|
|
||||||
|
void doLinkTargetSubstitution(const std::string& targetString, const std::string& replacementString);
|
||||||
|
|
||||||
|
std::vector<MarkdownLink*> getAllLinks() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<MarkdownElement> > mElements;
|
std::vector<std::unique_ptr<MarkdownElement> > mElements;
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,6 +29,11 @@ public:
|
||||||
const std::string& getTextContent() const;
|
const std::string& getTextContent() const;
|
||||||
|
|
||||||
virtual Type getType() const = 0;
|
virtual Type getType() const = 0;
|
||||||
|
|
||||||
|
virtual void doFieldSubstitution(Type elementType, const std::string& searchPhrase, const std::string& replacementPhrase)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
std::string mTextContent;
|
std::string mTextContent;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,6 @@ MarkdownParser::~MarkdownParser()
|
||||||
|
|
||||||
void MarkdownParser::onMultilineQuote()
|
void MarkdownParser::onMultilineQuote()
|
||||||
{
|
{
|
||||||
std::cout << "Adding multiline quote " << mDocumentContent << std::endl;
|
|
||||||
auto quote = std::make_unique<MarkdownMultilineQuote>(mWorkingTag);
|
auto quote = std::make_unique<MarkdownMultilineQuote>(mWorkingTag);
|
||||||
quote->appendTextContent(mDocumentContent);
|
quote->appendTextContent(mDocumentContent);
|
||||||
|
|
||||||
|
@ -34,8 +33,6 @@ void MarkdownParser::onMultilineQuote()
|
||||||
|
|
||||||
void MarkdownParser::onInlineQuote()
|
void MarkdownParser::onInlineQuote()
|
||||||
{
|
{
|
||||||
std::cout << "Adding inline quote " << mLineContent << std::endl;
|
|
||||||
|
|
||||||
auto quote = std::make_unique<MarkdownInlineQuote>();
|
auto quote = std::make_unique<MarkdownInlineQuote>();
|
||||||
quote->appendTextContent(mLineContent);
|
quote->appendTextContent(mLineContent);
|
||||||
mLineContent.clear();
|
mLineContent.clear();
|
||||||
|
@ -49,8 +46,6 @@ void MarkdownParser::onInlineQuote()
|
||||||
|
|
||||||
void MarkdownParser::onHeading(unsigned level)
|
void MarkdownParser::onHeading(unsigned level)
|
||||||
{
|
{
|
||||||
std::cout << "Adding heading: " << mLineContent << std::endl;
|
|
||||||
|
|
||||||
auto heading = std::make_unique<MarkdownHeading>(level);
|
auto heading = std::make_unique<MarkdownHeading>(level);
|
||||||
heading->appendTextContent(mLineContent);
|
heading->appendTextContent(mLineContent);
|
||||||
mMarkdownDocument->addElement(std::move(heading));
|
mMarkdownDocument->addElement(std::move(heading));
|
||||||
|
@ -60,7 +55,6 @@ void MarkdownParser::onNewParagraph()
|
||||||
{
|
{
|
||||||
if (mWorkingBulletList)
|
if (mWorkingBulletList)
|
||||||
{
|
{
|
||||||
std::cout << "Adding bullets to document" << std::endl;
|
|
||||||
mMarkdownDocument->addElement(std::move(mWorkingBulletList));
|
mMarkdownDocument->addElement(std::move(mWorkingBulletList));
|
||||||
mWorkingBulletList.reset();
|
mWorkingBulletList.reset();
|
||||||
mDocumentState == DocumentState::NONE;
|
mDocumentState == DocumentState::NONE;
|
||||||
|
@ -71,7 +65,6 @@ void MarkdownParser::onNewParagraph()
|
||||||
|
|
||||||
if (!mWorkingParagraph->getNumChildren() == 0)
|
if (!mWorkingParagraph->getNumChildren() == 0)
|
||||||
{
|
{
|
||||||
std::cout << "Adding para to document" << std::endl;
|
|
||||||
mMarkdownDocument->addElement(std::move(mWorkingParagraph));
|
mMarkdownDocument->addElement(std::move(mWorkingParagraph));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,8 +77,6 @@ void MarkdownParser::onTextSpan()
|
||||||
|
|
||||||
if(mWorkingParagraph && !mDocumentContent.empty())
|
if(mWorkingParagraph && !mDocumentContent.empty())
|
||||||
{
|
{
|
||||||
std::cout << "Adding text " << mDocumentContent << std::endl;
|
|
||||||
|
|
||||||
auto text_span = std::make_unique<MarkdownTextSpan>();
|
auto text_span = std::make_unique<MarkdownTextSpan>();
|
||||||
text_span->appendTextContent(mDocumentContent);
|
text_span->appendTextContent(mDocumentContent);
|
||||||
mWorkingParagraph->addChild(std::move(text_span));
|
mWorkingParagraph->addChild(std::move(text_span));
|
||||||
|
@ -141,7 +132,6 @@ std::pair<unsigned, bool> MarkdownParser::onTick(unsigned tickCount)
|
||||||
|
|
||||||
void MarkdownParser::onLink()
|
void MarkdownParser::onLink()
|
||||||
{
|
{
|
||||||
std::cout << "Adding hyperlink to " << mLineContent << " with tag " << mWorkingTag << std::endl;
|
|
||||||
auto element = std::make_unique<MarkdownLink>(mLineContent);
|
auto element = std::make_unique<MarkdownLink>(mLineContent);
|
||||||
mLineContent.clear();
|
mLineContent.clear();
|
||||||
|
|
||||||
|
@ -157,7 +147,6 @@ void MarkdownParser::onLink()
|
||||||
|
|
||||||
void MarkdownParser::onImage()
|
void MarkdownParser::onImage()
|
||||||
{
|
{
|
||||||
std::cout << "Adding image with path " << mLineContent << " and alt" << mWorkingTag << std::endl;
|
|
||||||
auto element = std::make_unique<MarkdownImage>(mLineContent, mWorkingTag);
|
auto element = std::make_unique<MarkdownImage>(mLineContent, mWorkingTag);
|
||||||
mLineContent.clear();
|
mLineContent.clear();
|
||||||
|
|
||||||
|
@ -173,8 +162,6 @@ void MarkdownParser::onImage()
|
||||||
|
|
||||||
void MarkdownParser::onBulletItem()
|
void MarkdownParser::onBulletItem()
|
||||||
{
|
{
|
||||||
std::cout << "Adding bullet item " << mLineContent << std::endl;
|
|
||||||
|
|
||||||
if (!mWorkingBulletList)
|
if (!mWorkingBulletList)
|
||||||
{
|
{
|
||||||
mWorkingBulletList = std::make_unique<MarkdownBulletList>();
|
mWorkingBulletList = std::make_unique<MarkdownBulletList>();
|
||||||
|
@ -231,7 +218,6 @@ void MarkdownParser::processLine()
|
||||||
{
|
{
|
||||||
if (!flushed_pre_inline)
|
if (!flushed_pre_inline)
|
||||||
{
|
{
|
||||||
std::cout << "Flushing pre-line " << std::endl;
|
|
||||||
mDocumentContent += mLineContent;
|
mDocumentContent += mLineContent;
|
||||||
onTextSpan();
|
onTextSpan();
|
||||||
flushed_pre_inline = true;
|
flushed_pre_inline = true;
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
TEST_CASE(TestTemplatingEngine, "compiler")
|
TEST_CASE(TestTemplatingEngine, "compiler")
|
||||||
{
|
{
|
||||||
auto engine = TemplatingEngine(TestUtils::getTestDataDir());
|
auto engine = TemplatingEngine(TestUtils::getTestDataDir());
|
||||||
engine.loadTemplateFiles();
|
const auto content = engine.renderTemplate("index", nullptr);
|
||||||
const auto content = engine.processTemplate("index");
|
|
||||||
|
|
||||||
File outfile(TestUtils::getTestOutputDir() / "index.html");
|
File outfile(TestUtils::getTestOutputDir() / "index.html");
|
||||||
outfile.writeText(content);
|
outfile.writeText(content);
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
set(CORE_UNIT_TEST_FILES
|
set(CORE_UNIT_TEST_FILES
|
||||||
core/TestByteUtils.cpp
|
core/TestByteUtils.cpp
|
||||||
core/TestBitStream.cpp
|
core/TestBitStream.cpp
|
||||||
core/TestTomlReader.cpp
|
|
||||||
core/TestDataStructures.cpp
|
core/TestDataStructures.cpp
|
||||||
|
core/TestTomlReader.cpp
|
||||||
|
core/TestStringUtils.cpp
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
15
test/core/TestStringUtils.cpp
Normal file
15
test/core/TestStringUtils.cpp
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#include "StringUtils.h"
|
||||||
|
|
||||||
|
#include "TestFramework.h"
|
||||||
|
#include "TestUtils.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
TEST_CASE(TestStringUtils_Strip, "core")
|
||||||
|
{
|
||||||
|
std::string input = " super() ";
|
||||||
|
std::string stripped = StringUtils::strip(input);
|
||||||
|
|
||||||
|
auto predicate = stripped == "super()";
|
||||||
|
REQUIRE(predicate);
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
#include "HtmlDocument.h"
|
#include "HtmlDocument.h"
|
||||||
#include "MarkdownDocument.h"
|
#include "MarkdownDocument.h"
|
||||||
#include "MarkdownConverter.h"
|
#include "MarkdownConverter.h"
|
||||||
|
#include "MarkdownElement.h"
|
||||||
#include "HtmlWriter.h"
|
#include "HtmlWriter.h"
|
||||||
|
|
||||||
#include "TestFramework.h"
|
#include "TestFramework.h"
|
||||||
|
|
Loading…
Reference in a new issue