Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.

Commit fa2fa56

Browse files
authored
Fix escaping of parentheses in links and images
FIX: Escape parentheses in images and links. Closes #78 Signed-off-by: Ferdinand Thiessen <rpm@fthiessen.de>
1 parent 375cb55 commit fa2fa56

2 files changed

Lines changed: 12 additions & 3 deletions

File tree

src/to_markdown.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export const defaultMarkdownSerializer = new MarkdownSerializer({
101101
},
102102

103103
image(state, node) {
104-
state.write("![" + state.esc(node.attrs.alt || "") + "](" + node.attrs.src +
104+
state.write("![" + state.esc(node.attrs.alt || "") + "](" + node.attrs.src.replace(/[\(\)]/g, "\\$&") +
105105
(node.attrs.title ? ' "' + node.attrs.title.replace(/"/g, '\\"') + '"' : "") + ")")
106106
},
107107
hard_break(state, node, parent, index) {
@@ -126,7 +126,7 @@ export const defaultMarkdownSerializer = new MarkdownSerializer({
126126
let {inAutolink} = state
127127
state.inAutolink = undefined
128128
return inAutolink ? ">"
129-
: "](" + mark.attrs.href + (mark.attrs.title ? ' "' + mark.attrs.title.replace(/"/g, '\\"') + '"' : "") + ")"
129+
: "](" + mark.attrs.href.replace(/[\(\)"]/g, "\\$&") + (mark.attrs.title ? ` "${mark.attrs.title.replace(/"/g, '\\"')}"` : "") + ")"
130130
}
131131
},
132132
code: {open(_state, _mark, parent, index) { return backticksFor(parent.child(index), -1) },

test/test-parse.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,21 @@ describe("markdown", () => {
181181
it("escape ! in front of links", () =>
182182
serialize(doc(p("!", a("text"))), "\\![text](foo)"))
183183

184+
// Issue #78
185+
it("escape of URL in links and images", () => {
186+
serialize(doc(p(a({href: "foo):"}, "link"))), "[link](foo\\):)")
187+
serialize(doc(p(a({href: "(foo"}, "link"))), "[link](\\(foo)")
188+
serialize(doc(p(img({src: "foo):"}))), "![x](foo\\):)")
189+
serialize(doc(p(img({src: "(foo"}))), "![x](\\(foo)")
190+
serialize(doc(p(a({title: "bar", href: "foo%20\""}, "link"))), "[link](foo%20\\\" \"bar\")")
191+
})
192+
184193
it("escapes extra characters from options", () => {
185194
let markdownSerializer = new MarkdownSerializer(defaultMarkdownSerializer.nodes,
186195
defaultMarkdownSerializer.marks,
187196
{escapeExtraCharacters: /[\|!]/g})
188197
ist(markdownSerializer.serialize(doc(p("foo|bar!"))), "foo\\|bar\\!")
189-
})
198+
})
190199

191200
it("escapes list markers inside lists", () => {
192201
same("* 1\\. hi\n\n* x", doc(ul(li(p("1. hi")), li(p("x")))))

0 commit comments

Comments
 (0)