summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2017-03-23 20:05:10 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2017-03-27 15:43:56 +0200
commitd851d6b98fefbe7de91c8c58b883cca4da17eea9 (patch)
tree5171cf499aef5d69ef00ef3b4bcdca777363060b
parent8bcc08e3b0ddd5762101bb2f061e0be04ecd8d57 (diff)
Add custom protocol support in Permalink
-rw-r--r--helpers/baseURL.go74
-rw-r--r--helpers/baseURL_test.go51
-rw-r--r--helpers/url.go27
-rw-r--r--hugolib/page.go7
-rw-r--r--hugolib/page_output.go3
-rw-r--r--hugolib/site.go22
-rw-r--r--hugolib/site_output_test.go10
-rw-r--r--output/outputFormat.go11
-rw-r--r--output/outputFormat_test.go1
9 files changed, 170 insertions, 36 deletions
diff --git a/helpers/baseURL.go b/helpers/baseURL.go
new file mode 100644
index 000000000..9a4b77edd
--- /dev/null
+++ b/helpers/baseURL.go
@@ -0,0 +1,74 @@
+// Copyright 2017-present The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package helpers
+
+import (
+ "fmt"
+ "net/url"
+ "strings"
+)
+
+// A BaseURL in Hugo is normally on the form scheme://path, but the
+// form scheme: is also valid (mailto:hugo@rules.com).
+type BaseURL struct {
+ url *url.URL
+ urlStr string
+}
+
+func (b BaseURL) String() string {
+ return b.urlStr
+}
+
+// Protocol is normaly on the form "scheme://", i.e. "webcal://".
+func (b BaseURL) WithProtocol(protocol string) (string, error) {
+ u := b.URL()
+
+ scheme := protocol
+ isFullProtocol := strings.HasSuffix(scheme, "://")
+ isOpaqueProtocol := strings.HasSuffix(scheme, ":")
+
+ if isFullProtocol {
+ scheme = strings.TrimSuffix(scheme, "://")
+ } else if isOpaqueProtocol {
+ scheme = strings.TrimSuffix(scheme, ":")
+ }
+
+ u.Scheme = scheme
+
+ if isFullProtocol && u.Opaque != "" {
+ u.Opaque = "//" + u.Opaque
+ } else if isOpaqueProtocol && u.Opaque == "" {
+ return "", fmt.Errorf("Cannot determine BaseURL for protocol %q", protocol)
+ }
+
+ return u.String(), nil
+}
+
+func (b BaseURL) URL() *url.URL {
+ // create a copy as it will be modified.
+ c := *b.url
+ return &c
+}
+
+func newBaseURLFromString(b string) (BaseURL, error) {
+ var result BaseURL
+
+ base, err := url.Parse(b)
+ if err != nil {
+ return result, err
+ }
+
+ // TODO(bep) output consider saving original URL?
+ return BaseURL{url: base, urlStr: base.String()}, nil
+}
diff --git a/helpers/baseURL_test.go b/helpers/baseURL_test.go
new file mode 100644
index 000000000..eaa27ddb9
--- /dev/null
+++ b/helpers/baseURL_test.go
@@ -0,0 +1,51 @@
+// Copyright 2017-present The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package helpers
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestBaseURL(t *testing.T) {
+ b, err := newBaseURLFromString("http://example.com")
+ require.NoError(t, err)
+ require.Equal(t, "http://example.com", b.String())
+
+ p, err := b.WithProtocol("webcal://")
+ require.NoError(t, err)
+ require.Equal(t, "webcal://example.com", p)
+
+ p, err = b.WithProtocol("webcal")
+ require.NoError(t, err)
+ require.Equal(t, "webcal://example.com", p)
+
+ _, err = b.WithProtocol("mailto:")
+ require.Error(t, err)
+
+ b, err = newBaseURLFromString("mailto:hugo@rules.com")
+ require.NoError(t, err)
+ require.Equal(t, "mailto:hugo@rules.com", b.String())
+
+ // These are pretty constructed
+ p, err = b.WithProtocol("webcal")
+ require.NoError(t, err)
+ require.Equal(t, "webcal:hugo@rules.com", p)
+
+ p, err = b.WithProtocol("webcal://")
+ require.NoError(t, err)
+ require.Equal(t, "webcal://hugo@rules.com", p)
+
+}
diff --git a/helpers/url.go b/helpers/url.go
index a73e54999..defde6a17 100644
--- a/helpers/url.go
+++ b/helpers/url.go
@@ -23,33 +23,6 @@ import (
"github.com/PuerkitoBio/purell"
)
-type BaseURL struct {
- url *url.URL
- urlStr string
-}
-
-func (b BaseURL) String() string {
- return b.urlStr
-}
-
-func (b BaseURL) URL() *url.URL {
- // create a copy as it will be modified.
- c := *b.url
- return &c
-}
-
-func newBaseURLFromString(b string) (BaseURL, error) {
- var result BaseURL
-
- base, err := url.Parse(b)
- if err != nil {
- return result, err
- }
-
- // TODO(bep) output consider saving original URL?
- return BaseURL{url: base, urlStr: base.String()}, nil
-}
-
type pathBridge struct {
}
diff --git a/hugolib/page.go b/hugolib/page.go
index 4e9ea2e78..dba3942de 100644
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -862,7 +862,12 @@ func (p *Page) initURLs() error {
p.outputFormats = p.s.outputFormats[p.Kind]
}
rel := p.createRelativePermalink()
- p.permalink = p.s.permalink(rel)
+
+ var err error
+ p.permalink, err = p.s.permalinkForOutputFormat(rel, p.outputFormats[0])
+ if err != nil {
+ return err
+ }
rel = p.s.PathSpec.PrependBasePath(rel)
p.relPermalink = rel
p.layoutDescriptor = p.createLayoutDescriptor()
diff --git a/hugolib/page_output.go b/hugolib/page_output.go
index 0038b7fdd..ec662bf23 100644
--- a/hugolib/page_output.go
+++ b/hugolib/page_output.go
@@ -197,7 +197,8 @@ func (o OutputFormats) Get(name string) *OutputFormat {
// Permalink returns the absolute permalink to this output format.
func (o *OutputFormat) Permalink() string {
rel := o.p.createRelativePermalinkForOutputFormat(o.f)
- return o.p.s.permalink(rel)
+ perm, _ := o.p.s.permalinkForOutputFormat(rel, o.f)
+ return perm
}
// Permalink returns the relative permalink to this output format.
diff --git a/hugolib/site.go b/hugolib/site.go
index 1cdb285ba..e3a896148 100644
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -1766,9 +1766,29 @@ func (s *SiteInfo) GetPage(typ string, path ...string) *Page {
return s.getPage(typ, path...)
}
+func (s *Site) permalinkForOutputFormat(link string, f output.Format) (string, error) {
+ var (
+ baseURL string
+ err error
+ )
+
+ if f.Protocol != "" {
+ baseURL, err = s.PathSpec.BaseURL.WithProtocol(f.Protocol)
+ if err != nil {
+ return "", err
+ }
+ } else {
+ baseURL = s.PathSpec.BaseURL.String()
+ }
+ return s.permalinkForBaseURL(link, baseURL), nil
+}
+
func (s *Site) permalink(link string) string {
- baseURL := s.PathSpec.BaseURL.String()
+ return s.permalinkForBaseURL(link, s.PathSpec.BaseURL.String())
+
+}
+func (s *Site) permalinkForBaseURL(link, baseURL string) string {
link = strings.TrimPrefix(link, "/")
if !strings.HasSuffix(baseURL, "/") {
baseURL += "/"
diff --git a/hugolib/site_output_test.go b/hugolib/site_output_test.go
index 6694a9bfd..006f3bad0 100644
--- a/hugolib/site_output_test.go
+++ b/hugolib/site_output_test.go
@@ -52,7 +52,7 @@ func TestDefaultOutputFormats(t *testing.T) {
}
func TestSiteWithPageOutputs(t *testing.T) {
- for _, outputs := range [][]string{{"html", "json"}, {"json"}} {
+ for _, outputs := range [][]string{{"html", "json", "calendar"}, {"json"}} {
t.Run(fmt.Sprintf("%v", outputs), func(t *testing.T) {
doTestSiteWithPageOutputs(t, outputs)
})
@@ -146,4 +146,12 @@ Output/Rel: {{ .Name -}}/{{ .Rel }}|
require.Equal(t, "/blog/index.json", json.RelPermalink())
require.Equal(t, "http://example.com/blog/index.json", json.Permalink())
+ if helpers.InStringArray(outputs, "cal") {
+ // TODO(bep) output have do some protocil handling for the default too if set.
+ cal := of.Get("calendar")
+ require.NotNil(t, cal)
+ require.Equal(t, "/blog/index.ics", cal.RelPermalink())
+ require.Equal(t, "webcal://example.com/blog/index.ics", cal.Permalink())
+ }
+
}
diff --git a/output/outputFormat.go b/output/outputFormat.go
index efc0cd85f..c50d74f3f 100644
--- a/output/outputFormat.go
+++ b/output/outputFormat.go
@@ -72,11 +72,12 @@ var (
)
var builtInTypes = map[string]Format{
- strings.ToLower(AMPType.Name): AMPType,
- strings.ToLower(CSSType.Name): CSSType,
- strings.ToLower(HTMLType.Name): HTMLType,
- strings.ToLower(JSONType.Name): JSONType,
- strings.ToLower(RSSType.Name): RSSType,
+ strings.ToLower(AMPType.Name): AMPType,
+ strings.ToLower(CalendarType.Name): CalendarType,
+ strings.ToLower(CSSType.Name): CSSType,
+ strings.ToLower(HTMLType.Name): HTMLType,
+ strings.ToLower(JSONType.Name): JSONType,
+ strings.ToLower(RSSType.Name): RSSType,
}
type Formats []Format
diff --git a/output/outputFormat_test.go b/output/outputFormat_test.go
index efc31a223..a76c50aee 100644
--- a/output/outputFormat_test.go
+++ b/output/outputFormat_test.go
@@ -30,6 +30,7 @@ func TestDefaultTypes(t *testing.T) {
require.Equal(t, "HTML", HTMLType.Name)
require.Equal(t, media.HTMLType, HTMLType.MediaType)
require.Empty(t, HTMLType.Path)
+ require.Empty(t, HTMLType.Protocol) // Will inherit the BaseURL protocol.
require.False(t, HTMLType.IsPlainText)
require.Equal(t, "RSS", RSSType.Name)