From 64d163d2e6b2719affe4fd40d31eefa44bf52711 Mon Sep 17 00:00:00 2001
From: Robin Stocker <robin@nibor.org>
Date: Tue, 23 Jan 2024 22:45:29 +1100
Subject: [PATCH] Escape # in headings too

---
 .../java/org/commonmark/internal/util/AsciiMatcher.java   | 4 ++++
 .../renderer/markdown/CoreMarkdownNodeRenderer.java       | 8 ++++++--
 .../renderer/markdown/SpecMarkdownRendererTest.java       | 2 +-
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/commonmark/src/main/java/org/commonmark/internal/util/AsciiMatcher.java b/commonmark/src/main/java/org/commonmark/internal/util/AsciiMatcher.java
index 35769f82..d31020fa 100644
--- a/commonmark/src/main/java/org/commonmark/internal/util/AsciiMatcher.java
+++ b/commonmark/src/main/java/org/commonmark/internal/util/AsciiMatcher.java
@@ -22,6 +22,10 @@ public class AsciiMatcher implements CharMatcher {
         return new Builder(new BitSet());
     }
 
+    public static Builder builder(AsciiMatcher matcher) {
+        return new Builder((BitSet) matcher.set.clone());
+    }
+
     public static class Builder {
         private final BitSet set;
 
diff --git a/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java b/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java
index fe5725ae..8cb67e0f 100644
--- a/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java
+++ b/commonmark/src/main/java/org/commonmark/renderer/markdown/CoreMarkdownNodeRenderer.java
@@ -24,6 +24,8 @@ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRen
 
     private final AsciiMatcher textEscape =
             AsciiMatcher.builder().anyOf("[]<>`*&").build();
+    private final CharMatcher textEscapeInHeading =
+            AsciiMatcher.builder(textEscape).anyOf("#").build();
     private final CharMatcher linkDestinationNeedsAngleBrackets =
             AsciiMatcher.builder().c(' ').c('(').c(')').c('<').c('>').c('\\').build();
     private final CharMatcher linkDestinationEscapeInAngleBrackets =
@@ -366,11 +368,13 @@ public class CoreMarkdownNodeRenderer extends AbstractVisitor implements NodeRen
             }
         }
 
+        CharMatcher escape = text.getParent() instanceof Heading ? textEscapeInHeading : textEscape;
+
         if (literal.endsWith("!") && text.getNext() instanceof Link) {
-            writer.writeEscaped(literal.substring(0, literal.length() - 1), textEscape);
+            writer.writeEscaped(literal.substring(0, literal.length() - 1), escape);
             writer.write("\\!");
         } else {
-            writer.writeEscaped(literal, textEscape);
+            writer.writeEscaped(literal, escape);
         }
     }
 
diff --git a/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java b/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java
index 632f4acf..d6bdf9cf 100644
--- a/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java
+++ b/commonmark/src/test/java/org/commonmark/renderer/markdown/SpecMarkdownRendererTest.java
@@ -62,7 +62,7 @@ public class SpecMarkdownRendererTest {
             System.out.println();
         }
 
-        int expectedPassed = 646;
+        int expectedPassed = 647;
         assertTrue("Expected at least " + expectedPassed + " examples to pass but was " + passes.size(), passes.size() >= expectedPassed);
     }
 
-- 
GitLab