BareGit

Fix `*` inside code block

Author: MetroWind <chris.corsair@gmail.com>
Date: Wed Apr 1 09:20:19 2026 -0700
Commit: e7145c9dc76277d155009a48e803ab84f4361d23

Changes

diff --git a/src/block_parser.cpp b/src/block_parser.cpp
index 0f83f36..9c41be6 100644
--- a/src/block_parser.cpp
+++ b/src/block_parser.cpp
@@ -227,6 +227,13 @@ void BlockParser::process_line(const std::string& line)
     // 3. Open new blocks
     while(true)
     {
+        Block* tip = open_blocks.back().block;
+        if(tip->type == BlockType::FencedCode ||
+           tip->type == BlockType::IndentedCode)
+        {
+            break;
+        }
+
         size_t indent = count_indent(line, offset);
 
         // Check for BlockQuote
diff --git a/src/macrodown.cpp b/src/macrodown.cpp
index f98ec87..b8879b8 100644
--- a/src/macrodown.cpp
+++ b/src/macrodown.cpp
@@ -1,8 +1,9 @@
 #include "macrodown.h"
 
+#include <map>
 #include <regex>
 #include <sstream>
-#include <map>
+
 #include "block_parser.h"
 #include "converter.h"
 #include "standard_library.h"
@@ -37,19 +38,25 @@ std::unique_ptr<Node> MacroDown::parse(const std::string& input)
         else
         {
             // Reconstruct the input without the definition lines.
-            if(!first) processed_input += "\n";
+            if(!first)
+            {
+                processed_input += "\n";
+            }
             processed_input += line;
             first = false;
         }
     }
 
-    // Substitute reference-style links [text][id] with inline-style [text](url).
+    // Substitute reference-style links [text][id] with inline-style
+    // [text](url).
     for(const auto& pair : link_refs)
     {
         // Escape the ID for use in regex.
-        std::string id_escaped = std::regex_replace(pair.first, std::regex(R"([-[\]{}()*+?.,\^$|#\s])"), R"(\$&)");
+        std::string id_escaped = std::regex_replace(
+            pair.first, std::regex(R"([-[\]{}()*+?.,\^$|#\s])"), R"(\$&)");
         std::regex ref_link_re(R"(\[([^\]]+)\]\[)" + id_escaped + R"(\])");
-        processed_input = std::regex_replace(processed_input, ref_link_re, "[$1](" + pair.second + ")");
+        processed_input = std::regex_replace(processed_input, ref_link_re,
+                                             "[$1](" + pair.second + ")");
     }
 
     auto block_root = BlockParser::parse(processed_input);
diff --git a/tests/test_macrodown.cpp b/tests/test_macrodown.cpp
index 383ecdb..61de739 100644
--- a/tests/test_macrodown.cpp
+++ b/tests/test_macrodown.cpp
@@ -35,8 +35,10 @@ TEST(MacroDownTest, CommonMarkEmphasis)
     MacroDown md;
     EXPECT_EQ(md.render(*md.parse("*Italic*")), "<p><em>Italic</em></p>\n");
     EXPECT_EQ(md.render(*md.parse("_Italic_")), "<p><em>Italic</em></p>\n");
-    EXPECT_EQ(md.render(*md.parse("**Bold**")), "<p><strong>Bold</strong></p>\n");
-    EXPECT_EQ(md.render(*md.parse("__Bold__")), "<p><strong>Bold</strong></p>\n");
+    EXPECT_EQ(md.render(*md.parse("**Bold**")),
+              "<p><strong>Bold</strong></p>\n");
+    EXPECT_EQ(md.render(*md.parse("__Bold__")),
+              "<p><strong>Bold</strong></p>\n");
 }
 
 TEST(MacroDownTest, CommonMarkHeadings)
@@ -56,7 +58,7 @@ TEST(MacroDownTest, CommonMarkLinksAndImages)
     // Inline Image
     EXPECT_EQ(md.render(*md.parse("![Image](http://url/a.png)")),
               "<p><img src=\"http://url/a.png\" alt=\"Image\" /></p>\n");
-              
+
     // Reference Link
     EXPECT_EQ(md.render(*md.parse("[Link][1]\n\n[1]: http://b.org")),
               "<p><a href=\"http://b.org\">Link</a></p>\n");
@@ -77,13 +79,18 @@ TEST(MacroDownTest, CommonMarkLists)
 {
     MacroDown md;
     // Unordered List
-    EXPECT_EQ(md.render(*md.parse("* List")), "<ul>\n<li>\n<p>List</p>\n</li>\n</ul>\n");
-    EXPECT_EQ(md.render(*md.parse("- List")), "<ul>\n<li>\n<p>List</p>\n</li>\n</ul>\n");
-    EXPECT_EQ(md.render(*md.parse("+ List")), "<ul>\n<li>\n<p>List</p>\n</li>\n</ul>\n");
+    EXPECT_EQ(md.render(*md.parse("* List")),
+              "<ul>\n<li>\n<p>List</p>\n</li>\n</ul>\n");
+    EXPECT_EQ(md.render(*md.parse("- List")),
+              "<ul>\n<li>\n<p>List</p>\n</li>\n</ul>\n");
+    EXPECT_EQ(md.render(*md.parse("+ List")),
+              "<ul>\n<li>\n<p>List</p>\n</li>\n</ul>\n");
 
     // Ordered List
-    EXPECT_EQ(md.render(*md.parse("1. One")), "<ol>\n<li>\n<p>One</p>\n</li>\n</ol>\n");
-    EXPECT_EQ(md.render(*md.parse("1) One")), "<ol>\n<li>\n<p>One</p>\n</li>\n</ol>\n");
+    EXPECT_EQ(md.render(*md.parse("1. One")),
+              "<ol>\n<li>\n<p>One</p>\n</li>\n</ol>\n");
+    EXPECT_EQ(md.render(*md.parse("1) One")),
+              "<ol>\n<li>\n<p>One</p>\n</li>\n</ol>\n");
 }
 
 TEST(MacroDownTest, CommonMarkHorizontalRule)
@@ -98,7 +105,8 @@ TEST(MacroDownTest, CommonMarkCode)
 {
     MacroDown md;
     // Inline Code
-    EXPECT_EQ(md.render(*md.parse("`Inline code`")), "<p><code>Inline code</code></p>\n");
+    EXPECT_EQ(md.render(*md.parse("`Inline code`")),
+              "<p><code>Inline code</code></p>\n");
 
     // Fenced Code Block
     std::string fenced_input = "```\nCode block\n```";
@@ -145,3 +153,19 @@ TEST(MacroDownTest, InlineDefinition)
     std::string expected = "<p>This is <b>important</b>.</p>\n";
     EXPECT_EQ(md.render(*md.parse(input)), expected);
 }
+
+TEST(MacroDownTest, CodeBlockWithConfusingInternal)
+{
+    MacroDown md;
+    std::string input = R"(```
+* aaa
+
+bbb
+```
+
+ccc
+)";
+    std::string expected =
+        "<pre><code>* aaa\n\nbbb\n</code></pre>\n<p>ccc</p>\n";
+    EXPECT_EQ(md.render(*md.parse(input)), expected);
+}