Skip to content

Commit

Permalink
Partial rebase of jamieconnolly:trim-trailing-slash
Browse files Browse the repository at this point in the history
See gohugoio#3934 . I did not rebase some
of the added tests because their merge conflicts were more complicated;
this is a proof of concept, and there are apparently licensing issues
that need to be resolved.
  • Loading branch information
betaveros committed Feb 10, 2020
1 parent 4f43c90 commit 21c5d23
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 17 deletions.
9 changes: 9 additions & 0 deletions commands/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,15 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro

}
}

if f.c.Cfg.GetBool("trimTrailingSlash") {
path := strings.Split(r.URL.Path, "/")

if !strings.Contains(path[len(path)-1], ".") && !strings.HasSuffix(r.URL.Path, "/") {
r.URL.Path += ".html"
}
}

h.ServeHTTP(w, r)
})
}
Expand Down
8 changes: 6 additions & 2 deletions helpers/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,14 +305,18 @@ func (p *PathSpec) URLizeAndPrep(in string) string {

// URLPrep applies misc sanitation to the given URL.
func (p *PathSpec) URLPrep(in string) string {
if p.UglyURLs {
if p.UglyURLs && !p.TrimTrailingSlash {
return Uglify(SanitizeURL(in))
}
pretty := PrettifyURL(SanitizeURL(in))
if path.Ext(pretty) == ".xml" {
return pretty
}
url, err := purell.NormalizeURLString(pretty, purell.FlagAddTrailingSlash)
flag := purell.FlagAddTrailingSlash
if p.TrimTrailingSlash {
flag = purell.FlagRemoveTrailingSlash
}
url, err := purell.NormalizeURLString(pretty, flag)
if err != nil {
return pretty
}
Expand Down
27 changes: 21 additions & 6 deletions helpers/url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,19 +242,34 @@ func TestMakePermalink(t *testing.T) {

func TestURLPrep(t *testing.T) {
type test struct {
ugly bool
input string
output string
trimTrailingSlash bool
uglyURLs bool
input string
output string
}

data := []test{
{false, "/section/name.html", "/section/name/"},
{true, "/section/name/index.html", "/section/name.html"},
// trimTrailingSlash=false, uglyURLs=false
{false, false, "/section/name.html", "/section/name/"},
{false, false, "/section/name/index.html", "/section/name/"},

// trimTrailingSlash=false, uglyURLs=true
{false, true, "/section/name.html", "/section/name.html"},
{false, true, "/section/name/index.html", "/section/name.html"},

// trimTrailingSlash=true, uglyURLs=false
{true, false, "/section/name.html", "/section/name"},
{true, false, "/section/name/index.html", "/section/name"},

// trimTrailingSlash=true, uglyURLs=true
{true, true, "/section/name.html", "/section/name"},
{true, true, "/section/name/index.html", "/section/name"},
}

for i, d := range data {
v := newTestCfg()
v.Set("uglyURLs", d.ugly)
v.Set("trimTrailingSlash", d.trimTrailingSlash)
v.Set("uglyURLs", d.uglyURLs)
l := langs.NewDefaultLanguage(v)
p, _ := NewPathSpec(hugofs.NewMem(v), l, nil)

Expand Down
1 change: 1 addition & 0 deletions hugolib/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ func loadDefaultSettingsFor(v *viper.Viper) error {
v.SetDefault("ignoreCache", false)
v.SetDefault("canonifyURLs", false)
v.SetDefault("relativeURLs", false)
v.SetDefault("trimTrailingSlash", false)
v.SetDefault("removePathAccents", false)
v.SetDefault("titleCaseStyle", "AP")
v.SetDefault("taxonomies", map[string]string{"tag": "tags", "category": "categories"})
Expand Down
15 changes: 8 additions & 7 deletions hugolib/page__paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,14 @@ func createTargetPathDescriptor(s *Site, p page.Page, pm *pageMeta) (page.Target
alwaysInSubDir := p.Kind() == kindSitemap

desc := page.TargetPathDescriptor{
PathSpec: d.PathSpec,
Kind: p.Kind(),
Sections: p.SectionsEntries(),
UglyURLs: s.Info.uglyURLs(p),
ForcePrefix: s.h.IsMultihost() || alwaysInSubDir,
Dir: dir,
URL: pm.urlPaths.URL,
PathSpec: d.PathSpec,
Kind: p.Kind(),
Sections: p.SectionsEntries(),
UglyURLs: s.Info.uglyURLs(p),
TrimTrailingSlash: s.Info.trimTrailingSlash,
ForcePrefix: s.h.IsMultihost() || alwaysInSubDir,
Dir: dir,
URL: pm.urlPaths.URL,
}

if pm.Slug() != "" {
Expand Down
2 changes: 2 additions & 0 deletions hugolib/paths/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type Paths struct {

DisablePathToLower bool
RemovePathAccents bool
TrimTrailingSlash bool
UglyURLs bool
CanonifyURLs bool

Expand Down Expand Up @@ -156,6 +157,7 @@ func New(fs *hugofs.Fs, cfg config.Provider) (*Paths, error) {
DisablePathToLower: cfg.GetBool("disablePathToLower"),
RemovePathAccents: cfg.GetBool("removePathAccents"),
UglyURLs: cfg.GetBool("uglyURLs"),
TrimTrailingSlash: cfg.GetBool("trimTrailingSlash"),
CanonifyURLs: cfg.GetBool("canonifyURLs"),

ThemesDir: cfg.GetString("themesDir"),
Expand Down
3 changes: 3 additions & 0 deletions hugolib/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,8 @@ type SiteInfo struct {
relativeURLs bool
uglyURLs func(p page.Page) bool

trimTrailingSlash bool

owner *HugoSites
s *Site
language *langs.Language
Expand Down Expand Up @@ -1204,6 +1206,7 @@ func (s *Site) initializeSiteInfo() error {
canonifyURLs: s.Cfg.GetBool("canonifyURLs"),
relativeURLs: s.Cfg.GetBool("relativeURLs"),
uglyURLs: uglyURLs,
trimTrailingSlash: s.Cfg.GetBool("trimTrailingSlash"),
permalinks: permalinks,
owner: s.h,
s: s,
Expand Down
23 changes: 21 additions & 2 deletions resources/page/page_paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ type TargetPathDescriptor struct {
// The expanded permalink if defined for the section, ready to use.
ExpandedPermalink string

// Whether to trim the trailing slash from URLs
TrimTrailingSlash bool

// Some types cannot have uglyURLs, even if globally enabled, RSS being one example.
UglyURLs bool
}
Expand Down Expand Up @@ -141,7 +144,7 @@ func CreateTargetPaths(d TargetPathDescriptor) (tp TargetPaths) {
// the index base even when uglyURLs is enabled.
needsBase := true

isUgly := d.UglyURLs && !d.Type.NoUgly
isUgly := (d.UglyURLs || d.TrimTrailingSlash) && !d.Type.NoUgly
baseNameSameAsType := d.BaseName != "" && d.BaseName == d.Type.BaseName

if d.ExpandedPermalink == "" && baseNameSameAsType {
Expand Down Expand Up @@ -174,13 +177,21 @@ func CreateTargetPaths(d TargetPathDescriptor) (tp TargetPaths) {
hasSlash := strings.HasSuffix(d.URL, slash)

if hasSlash || !hasDot {
pagePath = pjoin(pagePath, d.Type.BaseName+d.Type.MediaType.FullSuffix())
if d.TrimTrailingSlash {
pagePath += d.Type.MediaType.FullSuffix()
} else {
pagePath = pjoin(pagePath, d.Type.BaseName+d.Type.MediaType.FullSuffix())
}
} else if hasDot {
pagePathDir = path.Dir(pagePathDir)
}

if !isHtmlIndex(pagePath) {
link = pagePath

if d.TrimTrailingSlash {
link = strings.TrimSuffix(link, ".html")
}
} else if !hasSlash {
link += slash
}
Expand Down Expand Up @@ -239,6 +250,10 @@ func CreateTargetPaths(d TargetPathDescriptor) (tp TargetPaths) {

if !isHtmlIndex(pagePath) {
link = pagePath

if d.TrimTrailingSlash {
link = strings.TrimSuffix(link, ".html")
}
}

if d.PrefixFilePath != "" {
Expand Down Expand Up @@ -278,6 +293,10 @@ func CreateTargetPaths(d TargetPathDescriptor) (tp TargetPaths) {

if !isHtmlIndex(pagePath) {
link = pagePath

if d.TrimTrailingSlash {
link = strings.TrimSuffix(link, ".html")
}
} else {
link += slash
}
Expand Down

0 comments on commit 21c5d23

Please sign in to comment.