Changes
diff --git a/src/parser.cpp b/src/parser.cpp
index 10f8ebc..e159661 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -3,6 +3,7 @@
#include "uni_algo/all.h"
#include <iostream>
#include <regex>
+#include <optional>
namespace macrodown
{
@@ -64,6 +65,7 @@ public:
if (handleDelimitedMarkup()) continue;
if (handleMacro()) continue;
if (handleCode()) continue;
+ if (handleImage()) continue;
if (handleLink()) continue;
if (handleEmphasis()) continue;
@@ -310,57 +312,91 @@ private:
return false;
}
+ // Handles Markdown images ().
+ bool handleImage()
+ {
+ if (pos_ + 1 >= input32_.length() || input32_[pos_] != '!' || input32_[pos_ + 1] != '[')
+ return false;
+
+ auto res = findLabelAndUrl(pos_ + 2);
+ if (!res) return false;
+
+ flushText();
+ addLinkLikeMacro("img", res->url, res->label);
+ pos_ = res->end_pos;
+ return true;
+ }
+
// Handles Markdown links ([text](url)).
// Recursively parses the link text.
bool handleLink()
{
- if (input32_[pos_] == '[')
- {
- size_t label_start = pos_ + 1;
- size_t j = label_start;
- int bracket_bal = 1;
- while (j < input32_.length() && bracket_bal > 0)
- {
- if (input32_[j] == '[') bracket_bal++;
- else if (input32_[j] == ']') bracket_bal--;
- if (bracket_bal > 0) j++;
- }
+ if (input32_[pos_] != '[')
+ return false;
- if (j < input32_.length() && bracket_bal == 0)
- {
- size_t close_bracket = j;
- if (close_bracket + 1 < input32_.length() && input32_[close_bracket + 1] == '(')
- {
- size_t url_start = close_bracket + 2;
- size_t url_end = input32_.find(')', url_start);
- if (url_end != std::u32string::npos)
- {
- flushText();
- std::u32string label32 = input32_.substr(label_start, close_bracket - label_start);
- std::u32string url32 = input32_.substr(url_start, url_end - url_start);
-
- Macro macro;
- macro.name = "link";
-
- // Arg 1: URL
- Group group1;
- group1.addChild(std::make_unique<Node>(Text{una::utf32to8(url32)}));
- macro.arguments.push_back(std::make_unique<Node>(std::move(group1)));
-
- // Arg 2: Text (parsed)
- Group group2;
- auto sub = Parser::parse(una::utf32to8(label32), prefix_markups_, delimited_markups_);
- for (auto& n : sub) group2.addChild(std::move(n));
- macro.arguments.push_back(std::make_unique<Node>(std::move(group2)));
-
- nodes_.push_back(std::make_unique<Node>(std::move(macro)));
- pos_ = url_end + 1;
- return true;
- }
- }
- }
+ auto res = findLabelAndUrl(pos_ + 1);
+ if (!res) return false;
+
+ flushText();
+ addLinkLikeMacro("link", res->url, res->label);
+ pos_ = res->end_pos;
+ return true;
+ }
+
+ struct LinkResult
+ {
+ std::u32string label;
+ std::u32string url;
+ size_t end_pos;
+ };
+
+ std::optional<LinkResult> findLabelAndUrl(size_t label_start)
+ {
+ size_t j = label_start;
+ int bracket_bal = 1;
+ while (j < input32_.length() && bracket_bal > 0)
+ {
+ if (input32_[j] == '[') bracket_bal++;
+ else if (input32_[j] == ']') bracket_bal--;
+ if (bracket_bal > 0) j++;
}
- return false;
+
+ if (j >= input32_.length() || bracket_bal != 0)
+ return std::nullopt;
+
+ size_t close_bracket = j;
+ if (close_bracket + 1 >= input32_.length() || input32_[close_bracket + 1] != '(')
+ return std::nullopt;
+
+ size_t url_start = close_bracket + 2;
+ size_t url_end = input32_.find(')', url_start);
+ if (url_end == std::u32string::npos)
+ return std::nullopt;
+
+ return LinkResult{
+ input32_.substr(label_start, close_bracket - label_start),
+ input32_.substr(url_start, url_end - url_start),
+ url_end + 1
+ };
+ }
+
+ void addLinkLikeMacro(const std::string& name, const std::u32string& url, const std::u32string& label)
+ {
+ Macro macro;
+ macro.name = name;
+
+ // Arg 1: URL
+ Group group1;
+ group1.addChild(std::make_unique<Node>(Text{una::utf32to8(url)}));
+ macro.arguments.push_back(std::make_unique<Node>(std::move(group1)));
+
+ // Arg 2: Label (parsed)
+ Group group2;
+ auto sub = Parser::parse(una::utf32to8(label), prefix_markups_, delimited_markups_);
+ for (auto& n : sub) group2.addChild(std::move(n));
+ macro.arguments.push_back(std::make_unique<Node>(std::move(group2)));
+
+ nodes_.push_back(std::make_unique<Node>(std::move(macro)));
}
// Handles emphasis (*em*) and strong emphasis (**strong**).
diff --git a/tests/test_macrodown.cpp b/tests/test_macrodown.cpp
index 64d7c66..9e16cd3 100644
--- a/tests/test_macrodown.cpp
+++ b/tests/test_macrodown.cpp
@@ -40,6 +40,9 @@ TEST(MacroDownTest, MarkdownElements)
// Link
EXPECT_EQ(md.render(*md.parse("[Link](url)")), "<p><a href=\"url\">Link</a></p>\n");
+ // Image
+ EXPECT_EQ(md.render(*md.parse("")), "<p><img src=\"img.jpg\" alt=\"Alt Text\" /></p>\n");
+
// Code
EXPECT_EQ(md.render(*md.parse("`code`")), "<p><code>code</code></p>\n");
}