Commit 9463f5c for mammothjs

commit 9463f5c6ba7161477a6be98e2620044ad2c967db
Author: Michael Williamson <mike@zwobble.org>
Date:   Sat Sep 26 22:35:04 2026 +0100

    Escape markdown link hrefs

diff --git a/NEWS b/NEWS
index a820136..9ecbecd 100644
--- a/NEWS
+++ b/NEWS
@@ -17,7 +17,7 @@

 * Handle paragraphs and runs that have been moved and tracked as a revision.

-* Escape HTML IDs in Markdown writer.
+* Improve escaping in Markdown writer.

 # 1.12.3

diff --git a/lib/writers/markdown-writer.js b/lib/writers/markdown-writer.js
index a5b572e..02961fe 100644
--- a/lib/writers/markdown-writer.js
+++ b/lib/writers/markdown-writer.js
@@ -17,7 +17,7 @@ function markdownLink(attributes) {
     if (href) {
         return {
             start: "[",
-            end: "](" + href + ")",
+            end: "](" + escapeMarkdown(href) + ")",
             anchorPosition: "before"
         };
     } else {
diff --git a/test/writers/markdown-writer.tests.js b/test/writers/markdown-writer.tests.js
index e7ab9e1..d66cc79 100644
--- a/test/writers/markdown-writer.tests.js
+++ b/test/writers/markdown-writer.tests.js
@@ -3,7 +3,7 @@ var test = require("../test")(module);

 var mdWriter = require("../../lib/writers/markdown-writer");

-test('special markdown characters are escaped', function() {
+test('special markdown characters in text are escaped', function() {
     var writer = mdWriter.writer();
     writer.text("\\*");
     return assert.equal(writer.asString(), "\\\\\\*");
@@ -71,7 +71,15 @@ test('anchor tags are written as hyperlinks', function() {
     writer.open("a", {"href": "http://example.com"});
     writer.text("Hello");
     writer.close("a");
-    return assert.equal(writer.asString(), "[Hello](http://example.com)");
+    return assert.equal(writer.asString(), "[Hello](http://example\\.com)");
+});
+
+test('special markdown characters in anchor href are escaped', function() {
+    var writer = mdWriter.writer();
+    writer.open("a", {"href": "http://example.com)Oops"});
+    writer.text("Hello");
+    writer.close("a");
+    return assert.equal(writer.asString(), "[Hello](http://example\\.com\\)Oops)");
 });

 test('anchor tags without href attribute are treated as ordinary text', function() {
@@ -103,7 +111,7 @@ test('links have anchors before opening square bracket', function() {
     writer.open("a", {href: "http://example.com", id: "start"});
     writer.text("Hello");
     writer.close("a");
-    return assert.equal(writer.asString(), '<a id="start"></a>[Hello](http://example.com)');
+    return assert.equal(writer.asString(), '<a id="start"></a>[Hello](http://example\\.com)');
 });

 test('can generate images', function() {