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

feat(renderer): support caret in links #996

Merged
merged 1 commit into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
262 changes: 228 additions & 34 deletions pkg/parser/link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ a link to <{example}>.`
})

It("with text only", func() {
source := "a link to mailto:foo@bar[the foo@bar email]."
source := "a link to mailto:hello@example.com[the hello@example.com email]."
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Expand All @@ -279,10 +279,10 @@ a link to <{example}>.`
&types.InlineLink{
Location: &types.Location{
Scheme: "mailto:",
Path: "foo@bar",
Path: "hello@example.com",
},
Attributes: types.Attributes{
types.AttrInlineLinkText: "the foo@bar email",
types.AttrInlineLinkText: "the hello@example.com email",
},
},
&types.StringElement{
Expand All @@ -296,7 +296,7 @@ a link to <{example}>.`
})

It("with text and extra attributes", func() {
source := "a link to mailto:foo@bar[the foo@bar email, foo=bar]"
source := "a link to mailto:hello@example.com[the hello@example.com email, foo=bar]"
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Expand All @@ -305,10 +305,10 @@ a link to <{example}>.`
&types.InlineLink{
Location: &types.Location{
Scheme: "mailto:",
Path: "foo@bar",
Path: "hello@example.com",
},
Attributes: types.Attributes{
types.AttrInlineLinkText: "the foo@bar email",
types.AttrInlineLinkText: "the hello@example.com email",
"foo": "bar",
},
},
Expand Down Expand Up @@ -396,6 +396,103 @@ next lines`
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("with text and custom target", func() {
source := `a link to https://example.com[the doc,window=read-later]`
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{Content: "a link to "},
&types.InlineLink{
Attributes: types.Attributes{
types.AttrInlineLinkText: "the doc",
types.AttrInlineLinkTarget: "read-later",
},
Location: &types.Location{
Scheme: "https://",
Path: "example.com",
},
},
},
},
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("with text and custom target with noopener", func() {
source := `a link to https://example.com[the doc,window=read-later,opts=noopener]`
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{Content: "a link to "},
&types.InlineLink{
Attributes: types.Attributes{
types.AttrInlineLinkText: "the doc",
types.AttrInlineLinkTarget: "read-later",
types.AttrOptions: types.Options{"noopener"},
},
Location: &types.Location{
Scheme: "https://",
Path: "example.com",
},
},
},
},
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("with text and explicit blank target", func() {
source := `a link to https://example.com[the doc,window=_blank]`
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{Content: "a link to "},
&types.InlineLink{
Attributes: types.Attributes{
types.AttrInlineLinkText: "the doc",
types.AttrInlineLinkTarget: "_blank",
},
Location: &types.Location{
Scheme: "https://",
Path: "example.com",
},
},
},
},
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("with text and blank target short-hand", func() {
source := `a link to https://example.com[the doc^]` // the ^ character is used to define a `blank` target
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{Content: "a link to "},
&types.InlineLink{
Attributes: types.Attributes{
types.AttrInlineLinkText: "the doc",
types.AttrInlineLinkTarget: "_blank",
},
Location: &types.Location{
Scheme: "https://",
Path: "example.com",
},
},
},
},
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

Context("text attribute with comma", func() {

It("only with text having comma", func() {
Expand Down Expand Up @@ -1059,16 +1156,16 @@ a link to {scheme}://{path} and https://foo.com`
Context("relative links", func() {

It("to doc without text", func() {
source := "a link to link:foo.adoc[]"
source := "a link to link:https://example.com[]"
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{Content: "a link to "},
&types.InlineLink{
Location: &types.Location{
Scheme: "",
Path: "foo.adoc",
Scheme: "https://",
Path: "example.com",
},
},
},
Expand All @@ -1079,19 +1176,19 @@ a link to {scheme}://{path} and https://foo.com`
})

It("to doc with text", func() {
source := "a link to link:foo.adoc[foo doc]"
source := "a link to link:https://example.com[the doc]"
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{Content: "a link to "},
&types.InlineLink{
Location: &types.Location{
Scheme: "",
Path: "foo.adoc",
Scheme: "https://",
Path: "example.com",
},
Attributes: types.Attributes{
types.AttrInlineLinkText: "foo doc",
types.AttrInlineLinkText: "the doc",
},
},
},
Expand All @@ -1102,7 +1199,7 @@ a link to {scheme}://{path} and https://foo.com`
})

It("to external URL with text only", func() {
source := "a link to link:https://example.com[foo doc]"
source := "a link to link:https://example.com[the doc]"
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Expand All @@ -1114,7 +1211,7 @@ a link to {scheme}://{path} and https://foo.com`
Path: "example.com",
},
Attributes: types.Attributes{
types.AttrInlineLinkText: "foo doc",
types.AttrInlineLinkText: "the doc",
},
},
},
Expand All @@ -1125,7 +1222,7 @@ a link to {scheme}://{path} and https://foo.com`
})

It("to external URL with text and extra attributes", func() {
source := "a link to link:https://example.com[foo doc, foo=bar]"
source := "a link to link:https://example.com[the doc, foo=bar]"
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Expand All @@ -1137,7 +1234,7 @@ a link to {scheme}://{path} and https://foo.com`
Path: "example.com",
},
Attributes: types.Attributes{
types.AttrInlineLinkText: "foo doc",
types.AttrInlineLinkText: "the doc",
"foo": "bar",
},
},
Expand Down Expand Up @@ -1171,21 +1268,22 @@ a link to {scheme}://{path} and https://foo.com`
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("invalid syntax", func() {
source := "a link to link:foo.adoc"
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{
Content: "a link to link:foo.adoc",
},
},
},
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})
// skipped: should be consistent with other syntaxes, and allow for skipped/missing attributes?
// It("invalid syntax", func() {
// source := "a link to link:https://example.com"
// expected := &types.Document{
// Elements: []interface{}{
// &types.Paragraph{
// Elements: []interface{}{
// &types.StringElement{
// Content: "a link to link:https://example.com",
// },
// },
// },
// },
// }
// Expect(ParseDocument(source)).To(MatchDocument(expected))
// })

It("with quoted text attribute", func() {
source := "link:/[a _a_ b *b* c `c`]"
Expand Down Expand Up @@ -1400,7 +1498,7 @@ a link to {scheme}:{path}[] and https://foo.com`
})

It("with line breaks in attributes", func() {
source := `link:x[
source := `link:example.com[
title]`
expected := &types.Document{
Elements: []interface{}{
Expand All @@ -1411,7 +1509,80 @@ title]`
types.AttrInlineLinkText: "title",
},
Location: &types.Location{
Path: "x",
Path: "example.com",
},
},
},
},
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("with text and custom target", func() {
source := `a link to link:https://example.com[the doc,window=read-later]`
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{Content: "a link to "},
&types.InlineLink{
Attributes: types.Attributes{
types.AttrInlineLinkText: "the doc",
types.AttrInlineLinkTarget: "read-later",
},
Location: &types.Location{
Scheme: "https://",
Path: "example.com",
},
},
},
},
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("with text and custom target with noopener", func() {
source := `a link to link:https://example.com[the doc,window=read-later,opts=noopener]`
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{Content: "a link to "},
&types.InlineLink{
Attributes: types.Attributes{
types.AttrInlineLinkText: "the doc",
types.AttrInlineLinkTarget: "read-later",
types.AttrOptions: types.Options{"noopener"},
},
Location: &types.Location{
Scheme: "https://",
Path: "example.com",
},
},
},
},
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("with text and explicit blank target", func() {
source := `a link to link:https://example.com[the doc,window=_blank]`
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{Content: "a link to "},
&types.InlineLink{
Attributes: types.Attributes{
types.AttrInlineLinkText: "the doc",
types.AttrInlineLinkTarget: "_blank",
},
Location: &types.Location{
Scheme: "https://",
Path: "example.com",
},
},
},
Expand All @@ -1421,6 +1592,29 @@ title]`
Expect(ParseDocument(source)).To(MatchDocument(expected))
})

It("with text and blank target short-hand", func() {
source := `a link to link:https://example.com[the doc^]` // the ^ character is used to define a `blank` target
expected := &types.Document{
Elements: []interface{}{
&types.Paragraph{
Elements: []interface{}{
&types.StringElement{Content: "a link to "},
&types.InlineLink{
Attributes: types.Attributes{
types.AttrInlineLinkText: "the doc",
types.AttrInlineLinkTarget: "_blank",
},
Location: &types.Location{
Scheme: "https://",
Path: "example.com",
},
},
},
},
},
}
Expect(ParseDocument(source)).To(MatchDocument(expected))
})
Context("text attribute with comma", func() {

It("with text having comma", func() {
Expand Down
2 changes: 1 addition & 1 deletion pkg/renderer/sgml/html5/link.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package html5

const (
linkTmpl = `<a{{ if .ID }} id="{{ .ID }}"{{ end }}{{ if .URL }} href="{{ escape .URL }}"{{ end }}{{if .Class}} class="{{ .Class }}"{{ end }}{{if .Target}} target="{{ .Target }}"{{ end }}>{{ .Text }}</a>`
linkTmpl = `<a{{ if .ID }} id="{{ .ID }}"{{ end }}{{ if .URL }} href="{{ escape .URL }}"{{ end }}{{if .Class}} class="{{ .Class }}"{{ end }}{{if .Target}} target="{{ .Target }}"{{ end }}{{ if .NoOpener}} rel="noopener"{{ end }}>{{ .Text }}</a>`
)
Loading