$1";
+ std::smatch match;
- line = std::regex_replace(line, re, replacement);
+ if (std::regex_search(line, match, re))
+ {
+ std::string replacement =
+ "" + escapeHTML(match[1].str()) + "";
+
+ line = match.prefix().str() + replacement + match.suffix().str();
+ }
}
}; // class InlineCodeParser
diff --git a/include/maddy/parser.h b/include/maddy/parser.h
index 660752f..675893f 100644
--- a/include/maddy/parser.h
+++ b/include/maddy/parser.h
@@ -394,6 +394,35 @@ class Parser
}
);
}
+
+ static std::string escapeHTML(const std::string& input)
+ {
+ std::string result;
+ for (char c : input)
+ {
+ switch (c)
+ {
+ case '&':
+ result += "&";
+ break;
+ case '<':
+ result += "<";
+ break;
+ case '>':
+ result += ">";
+ break;
+ case '"':
+ result += """;
+ break;
+ case '\'':
+ result += "'";
+ break;
+ default:
+ result += c;
+ }
+ }
+ return result;
+ }
}; // class Parser
// -----------------------------------------------------------------------------
From 28e04206e851b8edb61dab3fef43338c3d0dfc78 Mon Sep 17 00:00:00 2001
From: Vardan2009 <70532109+Vardan2009@users.noreply.github.com>
Date: Fri, 20 Feb 2026 15:39:22 +0400
Subject: [PATCH 2/7] Moved escapeHTML to common
---
include/maddy/codeblockparser.h | 3 ++-
include/maddy/common.h | 42 ++++++++++++++++++++++++++++++++
include/maddy/inlinecodeparser.h | 3 ++-
3 files changed, 46 insertions(+), 2 deletions(-)
create mode 100644 include/maddy/common.h
diff --git a/include/maddy/codeblockparser.h b/include/maddy/codeblockparser.h
index 162f762..62405fd 100644
--- a/include/maddy/codeblockparser.h
+++ b/include/maddy/codeblockparser.h
@@ -11,6 +11,7 @@
#include " + escapeHTML(match[1].str()) + "";
+ "" + common::escapeHTML(match[1].str()) + "";
line = match.prefix().str() + replacement + match.suffix().str();
}
From 1c3c94d71423691405ac513c0067a8e8ed9fc5c6 Mon Sep 17 00:00:00 2001
From: Vardan2009 <70532109+Vardan2009@users.noreply.github.com>
Date: Fri, 20 Feb 2026 15:50:31 +0400
Subject: [PATCH 3/7] Updated changelog
---
CHANGELOG.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a16cc40..d4487bc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,7 +14,7 @@ maddy uses [semver versioning](https://semver.org/).
## Upcoming
-* ...
+*  HTML escaping in code blocks and inline code
## version 1.6.0 2025-07-26
From 3e19c78ee8dc8b3a2f1edda4016c1bad55431763 Mon Sep 17 00:00:00 2001
From: Vardan2009 <70532109+Vardan2009@users.noreply.github.com>
Date: Fri, 20 Feb 2026 16:12:13 +0400
Subject: [PATCH 4/7] Added HTML escape tests
---
AUTHORS | 1 +
tests/maddy/test_maddy_codeblockparser.cpp | 22 +++++++++++++++++++++
tests/maddy/test_maddy_inlinecodeparser.cpp | 14 +++++++++++++
3 files changed, 37 insertions(+)
diff --git a/AUTHORS b/AUTHORS
index 698a0d0..23d3aa7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -12,3 +12,4 @@ Evan Klitzke (evan@eklitzke.org)
Albert Schwarzkopf (dev-maddy@quitesimple.org)
Ivans Saponenko (ivans.saponenko+maddy@gmail.com)
Lucian Smith (lpsmith@uw.edu)
+Vardan Petrosyan (github.com/Vardan2009)
diff --git a/tests/maddy/test_maddy_codeblockparser.cpp b/tests/maddy/test_maddy_codeblockparser.cpp
index 5306658..dd04578 100644
--- a/tests/maddy/test_maddy_codeblockparser.cpp
+++ b/tests/maddy/test_maddy_codeblockparser.cpp
@@ -74,3 +74,25 @@ TEST_F(MADDY_CODEBLOCKPARSER, ItShouldUseAnythingBehindFirstBackticksAsClass)
ASSERT_EQ(expected, outputString);
}
+
+TEST_F(MADDY_CODEBLOCKPARSER, ItProperlyEscapesHTML)
+{
+ std::vector\n<h1>Hello, "
+ "World!</h1>\n";
+
+ for (std::string md : markdown)
+ {
+ cbParser->AddLine(md);
+ }
+ ASSERT_TRUE(cbParser->IsFinished());
+
+ std::stringstream& output(cbParser->GetResult());
+ const std::string& outputString = output.str();
+
+ ASSERT_EQ(expected, outputString);
+}
diff --git a/tests/maddy/test_maddy_inlinecodeparser.cpp b/tests/maddy/test_maddy_inlinecodeparser.cpp
index 14bfa56..cd2a058 100644
--- a/tests/maddy/test_maddy_inlinecodeparser.cpp
+++ b/tests/maddy/test_maddy_inlinecodeparser.cpp
@@ -21,3 +21,17 @@ TEST(MADDY_INLINECODEPARSER, ItReplacesMarkdownWithCodeHTML)
ASSERT_EQ(expected, text);
}
+
+TEST(MADDY_INLINECODEPARSER, ItProperlyEscapesHTML)
+{
+ std::string text =
+ "some text `<h1>Test</h1> text testing "
+ "<span>it</span> out";
+ auto emphasizedParser = std::make_shared" + common::escapeHTML(match[1].str()) + "";
+ result.append(match.prefix());
+
+ result += "" + common::escapeHTML(match[1].str()) + "";
- line = match.prefix().str() + replacement + match.suffix().str();
+ searchStart = match.suffix().first;
}
+
+ result.append(searchStart, line.cend());
+
+ line = std::move(result);
}
}; // class InlineCodeParser
From 10f52fca1621c4e23639f2e6ab24dd154982bc96 Mon Sep 17 00:00:00 2001
From: Vardan2009 <70532109+Vardan2009@users.noreply.github.com>
Date: Fri, 20 Feb 2026 16:25:42 +0400
Subject: [PATCH 6/7] escapeHTML only replaces angle brackets
---
include/maddy/common.h | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/include/maddy/common.h b/include/maddy/common.h
index 129c583..1b10c3d 100644
--- a/include/maddy/common.h
+++ b/include/maddy/common.h
@@ -14,21 +14,12 @@ inline std::string escapeHTML(const std::string& input)
{
switch (c)
{
- case '&':
- result += "&";
- break;
case '<':
result += "<";
break;
case '>':
result += ">";
break;
- case '"':
- result += """;
- break;
- case '\'':
- result += "'";
- break;
default:
result += c;
}
From b2e04d95ac333b16868b05f6e760e80da6c6d052 Mon Sep 17 00:00:00 2001
From: Vardan2009 <70532109+Vardan2009@users.noreply.github.com>
Date: Fri, 20 Feb 2026 16:39:37 +0400
Subject: [PATCH 7/7] More escape cases in escapeHTML
---
include/maddy/common.h | 9 +++++++++
tests/maddy/test_maddy_parser.h | 6 ++++--
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/include/maddy/common.h b/include/maddy/common.h
index 1b10c3d..129c583 100644
--- a/include/maddy/common.h
+++ b/include/maddy/common.h
@@ -14,12 +14,21 @@ inline std::string escapeHTML(const std::string& input)
{
switch (c)
{
+ case '&':
+ result += "&";
+ break;
case '<':
result += "<";
break;
case '>':
result += ">";
break;
+ case '"':
+ result += """;
+ break;
+ case '\'':
+ result += "'";
+ break;
default:
result += c;
}
diff --git a/tests/maddy/test_maddy_parser.h b/tests/maddy/test_maddy_parser.h
index 576f30a..387703c 100644
--- a/tests/maddy/test_maddy_parser.h
+++ b/tests/maddy/test_maddy_parser.h
@@ -76,7 +76,8 @@ const std::string testHtml =
"hierarchy\nvar c = "
- "'blub';\nA Quote
With some
text" + "'blub';\nA Quote
With some " + "
text" "blocks inside
- even a list
- should be
- possible " "
And well
inline codeshould also " "work.Another Headline