diff --git a/helpers/url.go b/helpers/url.go index 502d64a6c..ce36bc184 100644 --- a/helpers/url.go +++ b/helpers/url.go @@ -151,7 +151,36 @@ func AbsURL(path string) string { if strings.HasPrefix(path, "http") || strings.HasPrefix(path, "//") { return path } - return MakePermalink(string(viper.GetString("BaseURL")), path).String() + return MakePermalink(viper.GetString("BaseURL"), path).String() +} + +// RelURL creates a URL relative to the BaseURL root. +// Note: The result URL will not include the context root if canonifyURLs is enabled. +func RelURL(path string) string { + baseURL := viper.GetString("BaseURL") + canonifyURLs := viper.GetBool("canonifyURLs") + if (!strings.HasPrefix(path, baseURL) && strings.HasPrefix(path, "http")) || strings.HasPrefix(path, "//") { + return path + } + + u := path + + if strings.HasPrefix(path, baseURL) { + u = strings.TrimPrefix(u, baseURL) + } + + if !canonifyURLs { + u = AddContextRoot(baseURL, u) + } + if path == "" && !strings.HasSuffix(u, "/") && strings.HasSuffix(baseURL, "/") { + u += "/" + } + + if !strings.HasPrefix(u, "/") { + u = "/" + u + } + + return u } // AddContextRoot adds the context root to an URL if it's not already set. diff --git a/helpers/url_test.go b/helpers/url_test.go index 3286c0f37..bfd211b89 100644 --- a/helpers/url_test.go +++ b/helpers/url_test.go @@ -49,6 +49,37 @@ func TestAbsURL(t *testing.T) { } } +func TestRelURL(t *testing.T) { + defer viper.Set("canonifyURLs", viper.GetBool("canonifyURLs")) + tests := []struct { + input string + baseURL string + canonify bool + expected string + }{ + {"/test/foo", "http://base/", false, "/test/foo"}, + {"test.css", "http://base/sub", false, "/sub/test.css"}, + {"test.css", "http://base/sub", true, "/test.css"}, + {"/test/", "http://base/", false, "/test/"}, + {"/test/", "http://base/sub/", false, "/sub/test/"}, + {"/test/", "http://base/sub/", true, "/test/"}, + {"", "http://base/ace/", false, "/ace/"}, + {"", "http://base/ace", false, "/ace"}, + {"http://abs", "http://base/", false, "http://abs"}, + {"//schemaless", "http://base/", false, "//schemaless"}, + } + + for i, test := range tests { + viper.Set("BaseURL", test.baseURL) + viper.Set("canonifyURLs", test.canonify) + + output := RelURL(test.input) + if output != test.expected { + t.Errorf("[%d][%t] Expected %#v, got %#v\n", i, test.canonify, test.expected, output) + } + } +} + func TestSanitizeURL(t *testing.T) { tests := []struct { input string diff --git a/tpl/template_funcs.go b/tpl/template_funcs.go index dea33254c..a78e4cce1 100644 --- a/tpl/template_funcs.go +++ b/tpl/template_funcs.go @@ -1197,6 +1197,7 @@ func init() { "safeCSS": SafeCSS, "safeURL": SafeURL, "absURL": func(a string) template.HTML { return template.HTML(helpers.AbsURL(a)) }, + "relURL": func(a string) template.HTML { return template.HTML(helpers.RelURL(a)) }, "markdownify": Markdownify, "first": First, "where": Where,