diff --git a/apps/website-generator/WebsiteGenerator.cpp b/apps/website-generator/WebsiteGenerator.cpp index 82cd8b0..0953933 100644 --- a/apps/website-generator/WebsiteGenerator.cpp +++ b/apps/website-generator/WebsiteGenerator.cpp @@ -16,6 +16,8 @@ #include "FileLogger.h" +#include + WebsiteGenerator::WebsiteGenerator() : mConfig(std::make_unique()), mTemplateEngine() diff --git a/src/compiler/template_engine/TemplateElements.cpp b/src/compiler/template_engine/TemplateElements.cpp index 4a18fed..422143b 100644 --- a/src/compiler/template_engine/TemplateElements.cpp +++ b/src/compiler/template_engine/TemplateElements.cpp @@ -35,8 +35,9 @@ void TemplateBlock::addLine(const std::string& line) std::string TemplateBlock::getRawContent() const { - std::string content = "TemplateBlock: " + mName + "\n"; + std::string content = "TemplateBlock: " + mName + " - Start \n"; content += TemplateNode::getRawContent(); + content += "TemplateBlock: " + mName + " - End"; return content; } @@ -53,10 +54,8 @@ std::string TemplateBlock::renderAsParent(TemplateSubstitutionContext* substitut if (child->getType() == Type::EXPRESSION) { auto expression = dynamic_cast(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); } } @@ -116,7 +115,7 @@ const std::string& TemplateExpression::getContent() const std::string TemplateExpression::render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext) { - if (substitutions->hasSubstitution(mContent)) + if (substitutions && substitutions->hasSubstitution(mContent)) { return substitutions->getSubstitution(mContent); } @@ -147,9 +146,13 @@ bool TemplateTextBody::hasContent() const std::string TemplateTextBody::render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext) { std::string content; - for (const auto& line : mContent) + for(unsigned idx=0; idx +#include "Lexer.h" +#include "File.h" +#include "StringUtils.h" TemplateFile::TemplateFile(const Path& path) : mPath(path), @@ -38,114 +40,119 @@ void TemplateFile::loadContent() { return; } - mRawContent = File(mPath).readLines(); - mWorkingLine = 0; + mWorkingNode = mRootNode.get(); - mWorkingTextBody = std::make_unique(mWorkingNode); + mWorkingTextSpan = std::make_unique(mWorkingNode); for (const auto& line : mRawContent) { processLine(line); - mWorkingLine++; } - onTextBodyFinished(); + onTextSpanFinished(); mHasLoaded = true; } -void TemplateFile::onTextBodyFinished(std::string working_string) +std::string TemplateFile::dumpContent() { - if (!working_string.empty()) + return mRootNode->getRawContent(); +} + +void TemplateFile::onTextSpanFinished() +{ + if (!mWorkingLineContent.empty()) { - mWorkingTextBody->addLine(working_string); + mWorkingTextSpan->addLine(mWorkingLineContent); } - if (mWorkingTextBody->hasContent()) + if (mWorkingTextSpan->hasContent()) { - mWorkingNode->addChild(std::move(mWorkingTextBody)); - mWorkingTextBody = std::make_unique(mWorkingNode); + mWorkingNode->addChild(std::move(mWorkingTextSpan)); + mWorkingTextSpan = std::make_unique(mWorkingNode); } + mWorkingLineContent.clear(); +} + +unsigned TemplateFile::checkForStatement(const std::string& lineSection) +{ + if (lineSection.empty()) + { + return 0; + } + + std::vector hits; + unsigned hit_size{0}; + if (Lexer::matchPattern("{%@%}", lineSection, '@', hits)) + { + if (hits.size() == 1) + { + auto content = hits[0]; + + onTextSpanFinished(); + + onFoundStatement(content); + hit_size = 4 + content.size(); + } + } + return hit_size; +} + +unsigned TemplateFile::checkForExpression(const std::string& lineSection) +{ + if (lineSection.empty()) + { + return 0; + } + + std::vector hits; + unsigned hit_size{0}; + if (Lexer::matchPattern("{{@}}", lineSection, '@', hits)) + { + if (hits.size() == 1) + { + auto content = hits[0]; + + onTextSpanFinished(); + + onFoundExpression(content); + hit_size = 4 + content.size(); + } + } + return hit_size; } void TemplateFile::processLine(const std::string& line) { - bool last_was_ldelimiter{ false }; - bool last_was_statement_rdelimiter{ false }; - bool last_was_expression_rdelimiter{ false }; - bool in_statement{ false }; - bool in_expression{ false }; - std::string working_string; - std::string last_working_string; - for (auto c : line) + unsigned line_position = 0; + mWorkingLineContent.clear(); + while(line_position < line.size()) { - if (c == '{') + const auto remaining = line.substr(line_position, line.size() - line_position); + if(auto length = checkForStatement(remaining)) { - if (last_was_ldelimiter) - { - in_expression = true; - last_was_ldelimiter = false; - working_string = ""; - } - else - { - last_was_ldelimiter = true; - } + line_position += length; } - else if (c == '%' && last_was_ldelimiter) + else if(auto length = checkForExpression(remaining)) { - last_was_ldelimiter = false; - in_statement = true; - last_working_string = working_string; - working_string = ""; - } - else if (c == '%' && in_statement) - { - last_was_statement_rdelimiter = true; - } - else if (c == '}' && (last_was_statement_rdelimiter || in_expression || last_was_expression_rdelimiter)) - { - if (last_was_statement_rdelimiter) - { - onTextBodyFinished(last_working_string); - onFoundStatement(working_string); - last_was_statement_rdelimiter = false; - working_string = ""; - } - else if (in_expression) - { - last_was_expression_rdelimiter = true; - in_expression = false; - } - else - { - onTextBodyFinished(); - onFoundExpression(working_string); - last_was_expression_rdelimiter = false; - working_string = ""; - } - } - else if (last_was_ldelimiter && (!in_statement && !in_expression)) - { - last_was_ldelimiter = false; - working_string += '{'; - working_string += c; + line_position += length; } else { - working_string += c; + mWorkingLineContent += line[line_position]; + line_position++; } } - if (!working_string.empty()) + if (!mWorkingLineContent.empty()) { - mWorkingTextBody->addLine(working_string); + mWorkingTextSpan->addLine(mWorkingLineContent); + mWorkingLineContent.clear(); } } void TemplateFile::onFoundStatement(const std::string& statement_string) { const auto statement_elements = StringUtils::split(statement_string); - if (statement_elements.size() == 0) { return; @@ -163,7 +170,13 @@ void TemplateFile::onFoundStatement(const std::string& statement_string) { onFoundExtends(statement_elements); } +} +void TemplateFile::onFoundExpression(const std::string& expression_string) +{ + const auto stripped = StringUtils::stripSurroundingWhitepsace(expression_string); + auto expression = std::make_unique(mWorkingNode, stripped); + mWorkingNode->addChild(std::move(expression)); } void TemplateFile::onFoundBlock(const std::vector args) @@ -192,15 +205,3 @@ void TemplateFile::onFoundExtends(const std::vector args) auto extends = std::make_unique(mWorkingNode, args[1]); mWorkingNode->addChild(std::move(extends)); } - -void TemplateFile::onFoundExpression(const std::string& expression_string) -{ - const auto stripped = StringUtils::stripSurroundingWhitepsace(expression_string); - auto expression = std::make_unique(mWorkingNode, stripped); - mWorkingNode->addChild(std::move(expression)); -} - -std::string TemplateFile::dumpContent() -{ - return mRootNode->getRawContent(); -} diff --git a/src/compiler/template_engine/TemplateFile.h b/src/compiler/template_engine/TemplateFile.h index c4a5b13..46209ea 100644 --- a/src/compiler/template_engine/TemplateFile.h +++ b/src/compiler/template_engine/TemplateFile.h @@ -1,14 +1,14 @@ #pragma once -#include "File.h" - -#include "TemplateNode.h" - #include +#include +#include class TemplateNode; class TemplateTextBody; +using Path = std::filesystem::path; + class TemplateFile { public: @@ -27,27 +27,32 @@ public: void loadContent(); private: - void onTextBodyFinished(std::string working_string = {}); + unsigned checkForStatement(const std::string& lineSection); - void processLine(const std::string& line); + unsigned checkForExpression(const std::string& lineSection); + + void onTextSpanFinished(); void onFoundStatement(const std::string& statement_string); + void onFoundExpression(const std::string& expression_string); + void onFoundBlock(const std::vector args); void onFoundEndBlock(const std::vector args); void onFoundExtends(const std::vector args); - void onFoundExpression(const std::string& expression_string); + void processLine(const std::string& line); Path mPath; std::string mParentName; std::vector mRawContent; bool mHasLoaded{false}; - unsigned mWorkingLine{ 0 }; std::unique_ptr mRootNode; TemplateNode* mWorkingNode{ nullptr }; - std::unique_ptr mWorkingTextBody; + + std::string mWorkingLineContent; + std::unique_ptr mWorkingTextSpan; }; diff --git a/src/compiler/template_engine/TemplateNode.cpp b/src/compiler/template_engine/TemplateNode.cpp index 732157e..9f76817 100644 --- a/src/compiler/template_engine/TemplateNode.cpp +++ b/src/compiler/template_engine/TemplateNode.cpp @@ -75,8 +75,18 @@ void TemplateNode::setExtensionParent(TemplateNode* parent) mExtensionParent = parent; } +void TemplateNode::setExtensionBase(TemplateNode* base) +{ + mExtensionBase = base; +} + std::string TemplateNode::render(TemplateSubstitutionContext* substitutions, TemplateNode* parentContext) { + if (mExtensionBase) + { + return mExtensionBase->render(substitutions, this); + } + if (!parentContext && mExtensionParent) { parentContext = mExtensionParent; diff --git a/src/compiler/template_engine/TemplateNode.h b/src/compiler/template_engine/TemplateNode.h index 06cc64a..ab573ad 100644 --- a/src/compiler/template_engine/TemplateNode.h +++ b/src/compiler/template_engine/TemplateNode.h @@ -42,10 +42,13 @@ public: void setExtensionParent(TemplateNode* parent); + void setExtensionBase(TemplateNode* base); + protected: std::vector > mChildren; TemplateNode* mParent{ nullptr }; TemplateNode* mExtensionParent{ nullptr }; + TemplateNode* mExtensionBase{ nullptr }; }; using TemplateNodePtr = std::unique_ptr; diff --git a/src/compiler/template_engine/TemplatingEngine.cpp b/src/compiler/template_engine/TemplatingEngine.cpp index 008807a..4f62684 100644 --- a/src/compiler/template_engine/TemplatingEngine.cpp +++ b/src/compiler/template_engine/TemplatingEngine.cpp @@ -26,18 +26,16 @@ std::string TemplatingEngine::renderTemplate(const std::string& name, TemplateSu if (!file->hasLoaded()) { file->loadContent(); - std::cout << file->dumpContent(); + //std::cout << file->dumpContent(); processTemplate(file, nullptr); } - return file->getContent()->render(substitutionContext, nullptr); } else { return {}; } - } void TemplatingEngine::loadTemplateFiles() @@ -62,21 +60,20 @@ TemplateFile* TemplatingEngine::getTemplateFile(const std::string& name) void TemplatingEngine::processTemplate(TemplateFile* file, TemplateNode* parent) { - std::cout << "Processing file " << file->getName() << std::endl; - auto content = file->getContent(); if (parent) { - std::cout << "Setting extension parent" << std::endl; content->setExtensionParent(parent); + parent->setExtensionBase(content); } if (auto extension_node = dynamic_cast(content->getFirstChildShallow(TemplateNode::Type::EXTENDS))) { - std::cout << "Found extension node " << std::endl; if (auto extension_template = getTemplateFile(Path(extension_node->getPath()))) { - std::cout << "Found extension template " << std::endl; + extension_template->loadContent(); + //std::cout << extension_template->dumpContent(); + processTemplate(extension_template, content); } } diff --git a/src/web/html/HtmlTextRun.h b/src/web/html/HtmlTextRun.h index 6832554..46ed8a7 100644 --- a/src/web/html/HtmlTextRun.h +++ b/src/web/html/HtmlTextRun.h @@ -17,7 +17,7 @@ public: std::string toString(unsigned depth = 0, bool keepInline = false) const override { - const auto prefix = std::string(2*depth, ' '); - return prefix + getText(); + + return getText(); } }; diff --git a/src/web/markdown/MarkdownDocument.cpp b/src/web/markdown/MarkdownDocument.cpp index 4007aaf..33e3865 100644 --- a/src/web/markdown/MarkdownDocument.cpp +++ b/src/web/markdown/MarkdownDocument.cpp @@ -34,9 +34,18 @@ std::vector MarkdownDocument::getAllLinks() const { if (element->getType() == MarkdownElement::Type::PARAGRAPH) { - auto para_links = dynamic_cast(element.get())->getAllLinks(); + auto para_links = dynamic_cast(element.get())->getAllLinks(); links.insert(links.end(), para_links.begin(), para_links.end()); } + else if (element->getType() == MarkdownElement::Type::BULLET_LIST) + { + auto bullet_list = dynamic_cast(element.get()); + for(unsigned idx=0; idxgetNumChildren(); idx++) + { + auto para_links = bullet_list->getChild(idx)->getAllLinks(); + links.insert(links.end(), para_links.begin(), para_links.end()); + } + } } return links; } diff --git a/src/web/markdown/MarkdownParser.cpp b/src/web/markdown/MarkdownParser.cpp index 3fb2aef..aedc6e1 100644 --- a/src/web/markdown/MarkdownParser.cpp +++ b/src/web/markdown/MarkdownParser.cpp @@ -7,7 +7,6 @@ #include "StringUtils.h" #include -#include static constexpr char MULTILINE_QUOTE_DELIMITER[]{"```"}; static constexpr char HEADING_DELIMITER{'#'}; @@ -151,12 +150,10 @@ void MarkdownParser::onTextSpanFinished() { if (mWorkingTextSpan) { - std::cout << "Adding to existing text span: " << std::endl; mWorkingTextSpan->appendTextContent(mWorkingLine); } else { - std::cout << "Adding new text span: " << mWorkingLine << std::endl; auto text_span = std::make_unique(); text_span->addLine(mWorkingLine); mWorkingTextSpan = text_span.get(); @@ -183,7 +180,6 @@ void MarkdownParser::processLine(const std::string& line) if (!mWorkingElement) { - std::cout << "Adding new paragraph " << std::endl; auto paragraph = std::make_unique(); mWorkingElement = paragraph.get(); mMarkdownDocument->addElement(std::move(paragraph)); @@ -341,7 +337,6 @@ void MarkdownParser::onFoundBulletItem(const std::string& line) } else { - std::cout << "Starting new bullet list" << std::endl; auto bullet_list = std::make_unique(); mWorkingBulletList = bullet_list.get(); @@ -350,15 +345,13 @@ void MarkdownParser::onFoundBulletItem(const std::string& line) auto bullet_item = std::make_unique(); mWorkingElement = bullet_item.get(); mWorkingBulletList->addChild(std::move(bullet_item)); - - processLine(StringUtils::removeUpTo(line, "*")); } + processLine(StringUtils::removeUpTo(line, "*")); } } void MarkdownParser::onSectionFinished() { - std::cout << "Section is finished" << std::endl; mWorkingElement = nullptr; mWorkingBulletList = nullptr; mWorkingTextSpan = nullptr; @@ -373,36 +366,29 @@ std::unique_ptr MarkdownParser::run(const std::string& content while (std::getline(ss, line, '\n')) { - std::cout << "Processing line " << line << std::endl; if (StringUtils::isWhitespaceOnly(line)) { - std::cout << "Is whitespace only " << std::endl; onEmptyLine(); continue; } else if (startsWithMultiLineQuote(line)) { - std::cout << "Found multiline quote" << std::endl; onFoundMultiLineQuote(line); } else if (auto result = startsWithCustomMultilineBlock(line); result >= 0) { - std::cout << "Found custom multiline" << std::endl; onFoundCustomMultiLineBlock(line, result); } else if (startsWithHeading(line)) { - std::cout << "Found heading" << std::endl; onFoundHeading(line); } else if(startsWithBulletItem(line)) { - std::cout << "Found bulletitem" << std::endl; onFoundBulletItem(line); } else { - std::cout << "Found nothing - process line" << std::endl; processLine(line); } } diff --git a/src/web/markdown/MarkdownParser.h b/src/web/markdown/MarkdownParser.h index 65a2dbd..45ea61b 100644 --- a/src/web/markdown/MarkdownParser.h +++ b/src/web/markdown/MarkdownParser.h @@ -28,11 +28,6 @@ private: bool isInMultilineBlock() const; - bool startsWithMultiLineQuote(const std::string& line) const; - int startsWithCustomMultilineBlock(const std::string& line) const; - bool startsWithHeading(const std::string& line) const; - bool startsWithBulletItem(const std::string& line) const; - void onFoundMultiLineQuote(const std::string& line); void onFoundCustomMultiLineBlock(const std::string& line, unsigned blockSlot); void onFoundHeading(const std::string& line); @@ -44,6 +39,11 @@ private: void processLine(const std::string& line); + bool startsWithMultiLineQuote(const std::string& line) const; + int startsWithCustomMultilineBlock(const std::string& line) const; + bool startsWithHeading(const std::string& line) const; + bool startsWithBulletItem(const std::string& line) const; + unsigned mCustomDelimiterIndex{0}; std::vector mCustomMultilineDelimiters; std::vector mCustomInlineDelimiters; diff --git a/test/compiler/TestTemplatingEngine.cpp b/test/compiler/TestTemplatingEngine.cpp index 852b916..ad90327 100644 --- a/test/compiler/TestTemplatingEngine.cpp +++ b/test/compiler/TestTemplatingEngine.cpp @@ -1,15 +1,29 @@ #include "TemplatingEngine.h" +#include "TemplateSubstitutionContext.h" #include "File.h" #include "TestFramework.h" #include "TestUtils.h" -TEST_CASE(TestTemplatingEngine, "compiler") +TEST_CASE(TestTemplatingEngine_BlockInherit, "compiler") { auto engine = TemplatingEngine(TestUtils::getTestDataDir()); const auto content = engine.renderTemplate("index", nullptr); - File outfile(TestUtils::getTestOutputDir() / "index.html"); + File outfile(TestUtils::getTestOutputDir(__FILE__) / "BlockInherit.html"); + outfile.writeText(content); +} + +TEST_CASE(TestTemplatingEngine_Simple, "compiler") +{ + auto engine = TemplatingEngine(TestUtils::getTestDataDir()); + + TemplateSubstitutionContext sub_context; + sub_context.addSubstitution("content", "

test

"); + + const auto content = engine.renderTemplate("simple_template", &sub_context); + + File outfile(TestUtils::getTestOutputDir(__FILE__) / "Simple.html"); outfile.writeText(content); } diff --git a/test/data/simple_markdown.md b/test/data/simple_markdown.md index 2decf41..1de2350 100644 --- a/test/data/simple_markdown.md +++ b/test/data/simple_markdown.md @@ -1,30 +1,7 @@ -# I'm a level one header -I'm some text under level one - -## I'm a level two header -I'm some text under level two - -``` -I'm a code block -``` - -I'm a line under the code block, with some `inline code`. - -### I'm a level three header I'm a bullet point list: * First point * Second point * Third point -With a [hyperlink](www.imahyperlink.com) embedded. - -# I'm another level one header - -I'm some inline math $a = b + c$ and I'm some standalone math: - -$$ -d = e + f -$$ - -![This is an image](https://myoctocat.com/assets/images/base-octocat.svg) +With some test after. diff --git a/test/data/simple_template.html b/test/data/simple_template.html new file mode 100644 index 0000000..6dc7772 --- /dev/null +++ b/test/data/simple_template.html @@ -0,0 +1,10 @@ + + + + + My title + + +
{{ content }}
+ +