diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2022-03-09 18:26:32 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2022-03-09 22:30:10 +0100 |
commit | 5697348e1732a5f64ee7467283eb0335f2ec36e8 (patch) | |
tree | af121a9de0890e66f9edde46fd4f084a750b3f6f /markup | |
parent | f98e570b17d99e0ca7a6e6792a4c741cfc8b81e8 (diff) |
markup/goldmark: Default to https for linkify
Fixes #9639
Diffstat (limited to 'markup')
-rw-r--r-- | markup/goldmark/convert.go | 2 | ||||
-rw-r--r-- | markup/goldmark/goldmark_config/config.go | 24 | ||||
-rw-r--r-- | markup/goldmark/integration_test.go | 67 | ||||
-rw-r--r-- | markup/goldmark/render_hooks.go | 31 |
4 files changed, 105 insertions, 19 deletions
diff --git a/markup/goldmark/convert.go b/markup/goldmark/convert.go index 4c1641a0b..9442ee9e7 100644 --- a/markup/goldmark/convert.go +++ b/markup/goldmark/convert.go @@ -94,7 +94,7 @@ func newMarkdown(pcfg converter.ProviderConfig) goldmark.Markdown { var ( extensions = []goldmark.Extender{ - newLinks(), + newLinks(cfg), newTocExtension(rendererOptions), } parserOptions []parser.Option diff --git a/markup/goldmark/goldmark_config/config.go b/markup/goldmark/goldmark_config/config.go index 82b8d9630..a3238091b 100644 --- a/markup/goldmark/goldmark_config/config.go +++ b/markup/goldmark/goldmark_config/config.go @@ -23,13 +23,14 @@ const ( // DefaultConfig holds the default Goldmark configuration. var Default = Config{ Extensions: Extensions{ - Typographer: true, - Footnote: true, - DefinitionList: true, - Table: true, - Strikethrough: true, - Linkify: true, - TaskList: true, + Typographer: true, + Footnote: true, + DefinitionList: true, + Table: true, + Strikethrough: true, + Linkify: true, + LinkifyProtocol: "https", + TaskList: true, }, Renderer: Renderer{ Unsafe: false, @@ -57,10 +58,11 @@ type Extensions struct { DefinitionList bool // GitHub flavored markdown - Table bool - Strikethrough bool - Linkify bool - TaskList bool + Table bool + Strikethrough bool + Linkify bool + LinkifyProtocol string + TaskList bool } type Renderer struct { diff --git a/markup/goldmark/integration_test.go b/markup/goldmark/integration_test.go index 89cd5bbb6..d8f218b31 100644 --- a/markup/goldmark/integration_test.go +++ b/markup/goldmark/integration_test.go @@ -423,3 +423,70 @@ title: "p1" <img src="b.jpg" alt=""a""> `) } + +func TestLinkifyProtocol(t *testing.T) { + t.Parallel() + + runTest := func(protocol string, withHook bool) *hugolib.IntegrationTestBuilder { + + files := ` +-- config.toml -- +[markup.goldmark] +[markup.goldmark.extensions] +linkify = true +linkifyProtocol = "PROTOCOL" +-- content/p1.md -- +--- +title: "p1" +--- +Link no procol: www.example.org +Link http procol: http://www.example.org +Link https procol: https://www.example.org + +-- layouts/_default/single.html -- +{{ .Content }} +` + files = strings.ReplaceAll(files, "PROTOCOL", protocol) + + if withHook { + files += `-- layouts/_default/_markup/render-link.html -- +<a href="{{ .Destination | safeURL }}">{{ .Text | safeHTML }}</a>` + } + + return hugolib.NewIntegrationTestBuilder( + hugolib.IntegrationTestConfig{ + T: t, + TxtarString: files, + }, + ).Build() + + } + + for _, withHook := range []bool{false, true} { + + b := runTest("https", withHook) + + b.AssertFileContent("public/p1/index.html", + "Link no procol: <a href=\"https://www.example.org\">www.example.org</a>", + "Link http procol: <a href=\"http://www.example.org\">http://www.example.org</a>", + "Link https procol: <a href=\"https://www.example.org\">https://www.example.org</a></p>", + ) + + b = runTest("http", withHook) + + b.AssertFileContent("public/p1/index.html", + "Link no procol: <a href=\"http://www.example.org\">www.example.org</a>", + "Link http procol: <a href=\"http://www.example.org\">http://www.example.org</a>", + "Link https procol: <a href=\"https://www.example.org\">https://www.example.org</a></p>", + ) + + b = runTest("gopher", withHook) + + b.AssertFileContent("public/p1/index.html", + "Link no procol: <a href=\"gopher://www.example.org\">www.example.org</a>", + "Link http procol: <a href=\"http://www.example.org\">http://www.example.org</a>", + "Link https procol: <a href=\"https://www.example.org\">https://www.example.org</a></p>", + ) + + } +} diff --git a/markup/goldmark/render_hooks.go b/markup/goldmark/render_hooks.go index 138a60d26..a22030f54 100644 --- a/markup/goldmark/render_hooks.go +++ b/markup/goldmark/render_hooks.go @@ -18,6 +18,7 @@ import ( "strings" "github.com/gohugoio/hugo/markup/converter/hooks" + "github.com/gohugoio/hugo/markup/goldmark/goldmark_config" "github.com/gohugoio/hugo/markup/goldmark/internal/render" "github.com/gohugoio/hugo/markup/internal/attributes" @@ -30,8 +31,9 @@ import ( var _ renderer.SetOptioner = (*hookedRenderer)(nil) -func newLinkRenderer() renderer.NodeRenderer { +func newLinkRenderer(cfg goldmark_config.Config) renderer.NodeRenderer { r := &hookedRenderer{ + linkifyProtocol: []byte(cfg.Extensions.LinkifyProtocol), Config: html.Config{ Writer: html.DefaultWriter, }, @@ -39,8 +41,8 @@ func newLinkRenderer() renderer.NodeRenderer { return r } -func newLinks() goldmark.Extender { - return &links{} +func newLinks(cfg goldmark_config.Config) goldmark.Extender { + return &links{cfg: cfg} } type linkContext struct { @@ -105,6 +107,7 @@ func (ctx headingContext) PlainText() string { } type hookedRenderer struct { + linkifyProtocol []byte html.Config } @@ -279,7 +282,7 @@ func (r *hookedRenderer) renderAutoLink(w util.BufWriter, source []byte, node as return r.renderAutoLinkDefault(w, source, node, entering) } - url := string(n.URL(source)) + url := string(r.autoLinkURL(n, source)) label := string(n.Label(source)) if n.AutoLinkType == ast.AutoLinkEmail && !strings.HasPrefix(strings.ToLower(url), "mailto:") { url = "mailto:" + url @@ -310,8 +313,9 @@ func (r *hookedRenderer) renderAutoLinkDefault(w util.BufWriter, source []byte, if !entering { return ast.WalkContinue, nil } + _, _ = w.WriteString(`<a href="`) - url := n.URL(source) + url := r.autoLinkURL(n, source) label := n.Label(source) if n.AutoLinkType == ast.AutoLinkEmail && !bytes.HasPrefix(bytes.ToLower(url), []byte("mailto:")) { _, _ = w.WriteString("mailto:") @@ -329,6 +333,17 @@ func (r *hookedRenderer) renderAutoLinkDefault(w util.BufWriter, source []byte, return ast.WalkContinue, nil } +func (r *hookedRenderer) autoLinkURL(n *ast.AutoLink, source []byte) []byte { + url := n.URL(source) + if len(n.Protocol) > 0 && !bytes.Equal(n.Protocol, r.linkifyProtocol) { + // The CommonMark spec says "http" is the correct protocol for links, + // but this doesn't make much sense (the fact that they should care about the rendered output). + // Note that n.Protocol is not set if protocol is provided by user. + url = append(r.linkifyProtocol, url[len(n.Protocol):]...) + } + return url +} + func (r *hookedRenderer) renderHeading(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { n := node.(*ast.Heading) var hr hooks.HeadingRenderer @@ -394,11 +409,13 @@ func (r *hookedRenderer) renderHeadingDefault(w util.BufWriter, source []byte, n return ast.WalkContinue, nil } -type links struct{} +type links struct { + cfg goldmark_config.Config +} // Extend implements goldmark.Extender. func (e *links) Extend(m goldmark.Markdown) { m.Renderer().AddOptions(renderer.WithNodeRenderers( - util.Prioritized(newLinkRenderer(), 100), + util.Prioritized(newLinkRenderer(e.cfg), 100), )) } |