-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(renderer): support caret in links (#996)
Fixes #391 Fixes #682 Signed-off-by: Xavier Coulon <[email protected]>
- Loading branch information
Showing
5 changed files
with
330 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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:[email protected][the [email protected] email]." | ||
expected := &types.Document{ | ||
Elements: []interface{}{ | ||
&types.Paragraph{ | ||
|
@@ -279,10 +279,10 @@ a link to <{example}>.` | |
&types.InlineLink{ | ||
Location: &types.Location{ | ||
Scheme: "mailto:", | ||
Path: "foo@bar", | ||
Path: "[email protected]", | ||
}, | ||
Attributes: types.Attributes{ | ||
types.AttrInlineLinkText: "the foo@bar email", | ||
types.AttrInlineLinkText: "the [email protected] email", | ||
}, | ||
}, | ||
&types.StringElement{ | ||
|
@@ -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:[email protected][the [email protected] email, foo=bar]" | ||
expected := &types.Document{ | ||
Elements: []interface{}{ | ||
&types.Paragraph{ | ||
|
@@ -305,10 +305,10 @@ a link to <{example}>.` | |
&types.InlineLink{ | ||
Location: &types.Location{ | ||
Scheme: "mailto:", | ||
Path: "foo@bar", | ||
Path: "[email protected]", | ||
}, | ||
Attributes: types.Attributes{ | ||
types.AttrInlineLinkText: "the foo@bar email", | ||
types.AttrInlineLinkText: "the [email protected] email", | ||
"foo": "bar", | ||
}, | ||
}, | ||
|
@@ -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() { | ||
|
@@ -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", | ||
}, | ||
}, | ||
}, | ||
|
@@ -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", | ||
}, | ||
}, | ||
}, | ||
|
@@ -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{ | ||
|
@@ -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", | ||
}, | ||
}, | ||
}, | ||
|
@@ -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{ | ||
|
@@ -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", | ||
}, | ||
}, | ||
|
@@ -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`]" | ||
|
@@ -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{}{ | ||
|
@@ -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", | ||
}, | ||
}, | ||
}, | ||
|
@@ -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() { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>` | ||
) |
Oops, something went wrong.