Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure the URL part of links is not escaped #71

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/to_markdown.ts
Expand Up @@ -112,18 +112,21 @@ export const defaultMarkdownSerializer = new MarkdownSerializer({
}
},
text(state, node) {
state.text(node.text!)
state.text(node.text!, !state.isAutolink)
}
}, {
em: {open: "*", close: "*", mixable: true, expelEnclosingWhitespace: true},
strong: {open: "**", close: "**", mixable: true, expelEnclosingWhitespace: true},
link: {
open(_state, mark, parent, index) {
return isPlainURL(mark, parent, index, 1) ? "<" : "["
_state.isAutolink = isPlainURL(mark, parent, index, 1)
return _state.isAutolink ? "<" : "["
},
close(_state, mark, parent, index) {
return isPlainURL(mark, parent, index, -1) ? ">"
const cont = _state.isAutolink ? ">"
: "](" + mark.attrs.href + (mark.attrs.title ? ' "' + mark.attrs.title.replace(/"/g, '\\"') + '"' : "") + ")"
_state.isAutolink = undefined
return cont
}
},
code: {open(_state, _mark, parent, index) { return backticksFor(parent.child(index), -1) },
Expand Down Expand Up @@ -159,6 +162,8 @@ export class MarkdownSerializerState {
out: string = ""
/// @internal
closed: Node | null = null
/// @intermal
isAutolink?: boolean = undefined
/// @internal
inTightList: boolean = false

Expand Down
70 changes: 43 additions & 27 deletions test/test-parse.ts
Expand Up @@ -150,39 +150,55 @@ describe("markdown", () => {
})

it("doesn't put a code block after a list item inside the list item", () =>
same("* list item\n\n```\ncode\n```",
doc(ul({tight: true}, li(p("list item"))), pre("code"))))
same("* list item\n\n```\ncode\n```",
doc(ul({tight: true}, li(p("list item"))), pre("code")))
)

it("doesn't escape characters in code", () =>
same("foo`*`", doc(p("foo", code("*")))))
same("foo`*`", doc(p("foo", code("*"))))
)

it("doesn't escape underscores between word characters", () =>
same(
"abc_def",
doc(p("abc_def"))
)
same(
"abc_def",
doc(p("abc_def"))
)
)

it("doesn't escape strips of underscores between word characters", () =>
same(
"abc___def",
doc(p("abc___def"))
)
)

it("escapes underscores at word boundaries", () =>
same(
"\\_abc\\_",
doc(p("_abc_"))
)
)

it("escapes underscores surrounded by non-word characters", () =>
same(
"/\\_abc\\_)",
doc(p("/_abc_)"))
)
)
it("doesn't escape strips of underscores between word characters", () =>
same(
"abc___def",
doc(p("abc___def"))
)
)

it("escapes underscores at word boundaries", () =>
same(
"\\_abc\\_",
doc(p("_abc_"))
)
)

it("escapes underscores surrounded by non-word characters", () =>
same(
"/\\_abc\\_)",
doc(p("/_abc_)"))
)
)

it("ensure no escapes in url", () =>
parse(
"[text](https://example.com/_file/#~anchor)",
doc(p(a({href: "https://example.com/_file/#~anchor"}, "text")))
)
)

it("ensure no escapes in autolinks", () =>
same(
"<https://example.com/_file/#~anchor>",
doc(p(a({href: "https://example.com/_file/#~anchor"}, "https://example.com/_file/#~anchor")))
)
)

it("escapes extra characters from options", () => {
let markdownSerializer = new MarkdownSerializer(defaultMarkdownSerializer.nodes,
Expand Down