Fix Permalink for resource, baseURL with path and canonifyURLs set

Fixes #5226
This commit is contained in:
Bjørn Erik Pedersen 2018-11-15 13:35:28 +01:00
parent 12742bac71
commit 5df2b79dd2
10 changed files with 212 additions and 198 deletions

View file

@ -652,7 +652,7 @@ func (c *commandeer) rebuildSites(events []fsnotify.Event) error {
if langPath != "" { if langPath != "" {
langPath = langPath + "/" langPath = langPath + "/"
} }
home := c.hugo.PathSpec.PrependBasePath("/" + langPath) home := c.hugo.PathSpec.PrependBasePath("/"+langPath, false)
visited[home] = true visited[home] = true
} }

View file

@ -69,12 +69,10 @@ func NewPathSpecWithBaseBaseFsProvided(fs *hugofs.Fs, cfg config.Provider, baseB
ProcessingStats: NewProcessingStats(p.Lang()), ProcessingStats: NewProcessingStats(p.Lang()),
} }
if !ps.CanonifyURLs {
basePath := ps.BaseURL.Path() basePath := ps.BaseURL.Path()
if basePath != "" && basePath != "/" { if basePath != "" && basePath != "/" {
ps.BasePath = basePath ps.BasePath = basePath
} }
}
return ps, nil return ps, nil
} }

View file

@ -283,15 +283,13 @@ func AddContextRoot(baseURL, relativePath string) string {
} }
// PrependBasePath prepends any baseURL sub-folder to the given resource // PrependBasePath prepends any baseURL sub-folder to the given resource
// if canonifyURLs is disabled. func (p *PathSpec) PrependBasePath(rel string, isAbs bool) string {
// If canonifyURLs is set, we will globally prepend the absURL with any sub-folder, basePath := p.GetBasePath(!isAbs)
// so avoid doing anything here to avoid getting double paths. if basePath != "" {
func (p *PathSpec) PrependBasePath(rel string) string {
if p.BasePath != "" {
rel = filepath.ToSlash(rel) rel = filepath.ToSlash(rel)
// Need to prepend any path from the baseURL // Need to prepend any path from the baseURL
hadSlash := strings.HasSuffix(rel, "/") hadSlash := strings.HasSuffix(rel, "/")
rel = path.Join(p.BasePath, rel) rel = path.Join(basePath, rel)
if hadSlash { if hadSlash {
rel += "/" rel += "/"
} }

View file

@ -316,5 +316,5 @@ func (o *OutputFormat) Permalink() string {
// RelPermalink returns the relative permalink to this output format. // RelPermalink returns the relative permalink to this output format.
func (o *OutputFormat) RelPermalink() string { func (o *OutputFormat) RelPermalink() string {
rel := o.p.createRelativePermalinkForOutputFormat(o.f) rel := o.p.createRelativePermalinkForOutputFormat(o.f)
return o.p.s.PathSpec.PrependBasePath(rel) return o.p.s.PathSpec.PrependBasePath(rel, false)
} }

View file

@ -144,7 +144,7 @@ func (p *Page) initURLs() error {
// Any language code in the path will be added later. // Any language code in the path will be added later.
p.relTargetPathBase = strings.TrimPrefix(p.relTargetPathBase, prefix+"/") p.relTargetPathBase = strings.TrimPrefix(p.relTargetPathBase, prefix+"/")
} }
p.relPermalink = p.s.PathSpec.PrependBasePath(rel) p.relPermalink = p.s.PathSpec.PrependBasePath(rel, false)
p.layoutDescriptor = p.createLayoutDescriptor() p.layoutDescriptor = p.createLayoutDescriptor()
return nil return nil
} }

View file

@ -45,13 +45,19 @@ func TestPageBundlerSiteRegular(t *testing.T) {
baseBaseURL := "https://example.com" baseBaseURL := "https://example.com"
for _, baseURLPath := range []string{"", "/hugo"} { for _, baseURLPath := range []string{"", "/hugo"} {
for _, canonify := range []bool{false, true} {
for _, ugly := range []bool{false, true} { for _, ugly := range []bool{false, true} {
t.Run(fmt.Sprintf("ugly=%t,path=%s", ugly, baseURLPath), t.Run(fmt.Sprintf("ugly=%t,canonify=%t,path=%s", ugly, canonify, baseURLPath),
func(t *testing.T) { func(t *testing.T) {
baseURL := baseBaseURL + baseURLPath baseURL := baseBaseURL + baseURLPath
relURLBase := baseURLPath
if canonify {
relURLBase = ""
}
assert := require.New(t) assert := require.New(t)
fs, cfg := newTestBundleSources(t) fs, cfg := newTestBundleSources(t)
cfg.Set("baseURL", baseURL) cfg.Set("baseURL", baseURL)
cfg.Set("canonifyURLs", canonify)
assert.NoError(loadDefaultSettingsFor(cfg)) assert.NoError(loadDefaultSettingsFor(cfg))
assert.NoError(loadLanguageSettings(cfg, nil)) assert.NoError(loadLanguageSettings(cfg, nil))
@ -94,11 +100,11 @@ func TestPageBundlerSiteRegular(t *testing.T) {
assert.Contains(singlePage.content(), "TheContent") assert.Contains(singlePage.content(), "TheContent")
if ugly { if ugly {
assert.Equal(baseURLPath+"/a/1.html", singlePage.RelPermalink()) assert.Equal(relURLBase+"/a/1.html", singlePage.RelPermalink())
th.assertFileContent(filepath.FromSlash("/work/public/a/1.html"), "TheContent") th.assertFileContent(filepath.FromSlash("/work/public/a/1.html"), "TheContent")
} else { } else {
assert.Equal(baseURLPath+"/a/1/", singlePage.RelPermalink()) assert.Equal(relURLBase+"/a/1/", singlePage.RelPermalink())
th.assertFileContent(filepath.FromSlash("/work/public/a/1/index.html"), "TheContent") th.assertFileContent(filepath.FromSlash("/work/public/a/1/index.html"), "TheContent")
} }
@ -122,9 +128,9 @@ func TestPageBundlerSiteRegular(t *testing.T) {
assert.NotNil(rootBundle) assert.NotNil(rootBundle)
assert.True(rootBundle.Parent().IsHome()) assert.True(rootBundle.Parent().IsHome())
if ugly { if ugly {
assert.Equal(baseURLPath+"/root.html", rootBundle.RelPermalink()) assert.Equal(relURLBase+"/root.html", rootBundle.RelPermalink())
} else { } else {
assert.Equal(baseURLPath+"/root/", rootBundle.RelPermalink()) assert.Equal(relURLBase+"/root/", rootBundle.RelPermalink())
} }
leafBundle2 := s.getPage(KindPage, "a/b/index.md") leafBundle2 := s.getPage(KindPage, "a/b/index.md")
@ -167,7 +173,7 @@ func TestPageBundlerSiteRegular(t *testing.T) {
assert.Len(leafBundle1.Resources.ByType("bepsays"), 1) assert.Len(leafBundle1.Resources.ByType("bepsays"), 1)
relPermalinker := func(s string) string { relPermalinker := func(s string) string {
return fmt.Sprintf(s, baseURLPath) return fmt.Sprintf(s, relURLBase)
} }
permalinker := func(s string) string { permalinker := func(s string) string {
@ -178,7 +184,7 @@ func TestPageBundlerSiteRegular(t *testing.T) {
} }
if ugly { if ugly {
assert.Equal(baseURLPath+"/2017/pageslug.html", leafBundle1.RelPermalink()) assert.Equal(relURLBase+"/2017/pageslug.html", leafBundle1.RelPermalink())
assert.Equal(baseURL+"/2017/pageslug.html", leafBundle1.Permalink()) assert.Equal(baseURL+"/2017/pageslug.html", leafBundle1.Permalink())
th.assertFileContent(filepath.FromSlash("/work/public/2017/pageslug.html"), th.assertFileContent(filepath.FromSlash("/work/public/2017/pageslug.html"),
"TheContent", "TheContent",
@ -196,28 +202,29 @@ func TestPageBundlerSiteRegular(t *testing.T) {
) )
th.assertFileContent(filepath.FromSlash("/work/public/cpath/2017/pageslug.html"), "TheContent") th.assertFileContent(filepath.FromSlash("/work/public/cpath/2017/pageslug.html"), "TheContent")
assert.Equal(baseURLPath+"/a/b.html", leafBundle2.RelPermalink()) assert.Equal(relURLBase+"/a/b.html", leafBundle2.RelPermalink())
// 은행 // 은행
assert.Equal(baseURLPath+"/c/%EC%9D%80%ED%96%89.html", unicodeBundle.RelPermalink()) assert.Equal(relURLBase+"/c/%EC%9D%80%ED%96%89.html", unicodeBundle.RelPermalink())
th.assertFileContent(filepath.FromSlash("/work/public/c/은행.html"), "Content for 은행") th.assertFileContent(filepath.FromSlash("/work/public/c/은행.html"), "Content for 은행")
th.assertFileContent(filepath.FromSlash("/work/public/c/은행/logo-은행.png"), "은행 PNG") th.assertFileContent(filepath.FromSlash("/work/public/c/은행/logo-은행.png"), "은행 PNG")
} else { } else {
assert.Equal(baseURLPath+"/2017/pageslug/", leafBundle1.RelPermalink()) assert.Equal(relURLBase+"/2017/pageslug/", leafBundle1.RelPermalink())
assert.Equal(baseURL+"/2017/pageslug/", leafBundle1.Permalink()) assert.Equal(baseURL+"/2017/pageslug/", leafBundle1.Permalink())
th.assertFileContent(filepath.FromSlash("/work/public/2017/pageslug/index.html"), "TheContent") th.assertFileContent(filepath.FromSlash("/work/public/2017/pageslug/index.html"), "TheContent")
th.assertFileContent(filepath.FromSlash("/work/public/cpath/2017/pageslug/cindex.html"), "TheContent") th.assertFileContent(filepath.FromSlash("/work/public/cpath/2017/pageslug/cindex.html"), "TheContent")
th.assertFileContent(filepath.FromSlash("/work/public/2017/pageslug/index.html"), "Single Title") th.assertFileContent(filepath.FromSlash("/work/public/2017/pageslug/index.html"), "Single Title")
th.assertFileContent(filepath.FromSlash("/work/public/root/index.html"), "Single Title") th.assertFileContent(filepath.FromSlash("/work/public/root/index.html"), "Single Title")
assert.Equal(baseURLPath+"/a/b/", leafBundle2.RelPermalink()) assert.Equal(relURLBase+"/a/b/", leafBundle2.RelPermalink())
} }
}) })
} }
} }
}
} }

View file

@ -588,7 +588,7 @@ func newPaginationURLFactory(d targetPathDescriptor) paginationURLFactory {
targetPath := createTargetPath(pathDescriptor) targetPath := createTargetPath(pathDescriptor)
targetPath = strings.TrimSuffix(targetPath, d.Type.BaseFilename()) targetPath = strings.TrimSuffix(targetPath, d.Type.BaseFilename())
link := d.PathSpec.PrependBasePath(targetPath) link := d.PathSpec.PrependBasePath(targetPath, false)
// Note: The targetPath is massaged with MakePathSanitized // Note: The targetPath is massaged with MakePathSanitized
return d.PathSpec.URLizeFilename(link) return d.PathSpec.URLizeFilename(link)
} }

View file

@ -34,7 +34,6 @@ type Paths struct {
BaseURL BaseURL
// If the baseURL contains a base path, e.g. https://example.com/docs, then "/docs" will be the BasePath. // If the baseURL contains a base path, e.g. https://example.com/docs, then "/docs" will be the BasePath.
// This will not be set if canonifyURLs is enabled.
BasePath string BasePath string
// Directories // Directories
@ -192,6 +191,15 @@ func New(fs *hugofs.Fs, cfg config.Provider) (*Paths, error) {
return p, nil return p, nil
} }
// GetBasePath returns any path element in baseURL if needed.
func (p *Paths) GetBasePath(isRelativeURL bool) string {
if isRelativeURL && p.CanonifyURLs {
// The baseURL will be prepended later.
return ""
}
return p.BasePath
}
func (p *Paths) Lang() string { func (p *Paths) Lang() string {
if p == nil || p.Language == nil { if p == nil || p.Language == nil {
return "" return ""

View file

@ -75,7 +75,7 @@ func (c *imageCache) getOrCreate(
parent *Image, conf imageConfig, createImage func() (*Image, image.Image, error)) (*Image, error) { parent *Image, conf imageConfig, createImage func() (*Image, image.Image, error)) (*Image, error) {
relTarget := parent.relTargetPathFromConfig(conf) relTarget := parent.relTargetPathFromConfig(conf)
key := parent.relTargetPathForRel(relTarget.path(), false, false) key := parent.relTargetPathForRel(relTarget.path(), false, false, false)
// First check the in-memory store, then the disk. // First check the in-memory store, then the disk.
c.mu.RLock() c.mu.RLock()

View file

@ -708,7 +708,7 @@ func (l *genericResource) publishIfNeeded() {
func (l *genericResource) Permalink() string { func (l *genericResource) Permalink() string {
l.publishIfNeeded() l.publishIfNeeded()
return l.spec.PermalinkForBaseURL(l.relPermalinkForRel(l.relTargetDirFile.path()), l.spec.BaseURL.HostURL()) return l.spec.PermalinkForBaseURL(l.relPermalinkForRel(l.relTargetDirFile.path(), true), l.spec.BaseURL.HostURL())
} }
func (l *genericResource) RelPermalink() string { func (l *genericResource) RelPermalink() string {
@ -717,11 +717,11 @@ func (l *genericResource) RelPermalink() string {
} }
func (l *genericResource) relPermalinkFor(target string) string { func (l *genericResource) relPermalinkFor(target string) string {
return l.relPermalinkForRel(target) return l.relPermalinkForRel(target, false)
} }
func (l *genericResource) permalinkFor(target string) string { func (l *genericResource) permalinkFor(target string) string {
return l.spec.PermalinkForBaseURL(l.relPermalinkForRel(target), l.spec.BaseURL.HostURL()) return l.spec.PermalinkForBaseURL(l.relPermalinkForRel(target, true), l.spec.BaseURL.HostURL())
} }
func (l *genericResource) relTargetPathsFor(target string) []string { func (l *genericResource) relTargetPathsFor(target string) []string {
@ -766,23 +766,23 @@ func (l *genericResource) updateParams(params map[string]interface{}) {
} }
} }
func (l *genericResource) relPermalinkForRel(rel string) string { func (l *genericResource) relPermalinkForRel(rel string, isAbs bool) string {
return l.spec.PathSpec.URLizeFilename(l.relTargetPathForRel(rel, false, true)) return l.spec.PathSpec.URLizeFilename(l.relTargetPathForRel(rel, false, isAbs, true))
} }
func (l *genericResource) relTargetPathsForRel(rel string) []string { func (l *genericResource) relTargetPathsForRel(rel string) []string {
if len(l.baseTargetPathDirs) == 0 { if len(l.baseTargetPathDirs) == 0 {
return []string{l.relTargetPathForRelAndBasePath(rel, "", false)} return []string{l.relTargetPathForRelAndBasePath(rel, "", false, false)}
} }
var targetPaths = make([]string, len(l.baseTargetPathDirs)) var targetPaths = make([]string, len(l.baseTargetPathDirs))
for i, dir := range l.baseTargetPathDirs { for i, dir := range l.baseTargetPathDirs {
targetPaths[i] = l.relTargetPathForRelAndBasePath(rel, dir, false) targetPaths[i] = l.relTargetPathForRelAndBasePath(rel, dir, false, false)
} }
return targetPaths return targetPaths
} }
func (l *genericResource) relTargetPathForRel(rel string, addBaseTargetPath, isURL bool) string { func (l *genericResource) relTargetPathForRel(rel string, addBaseTargetPath, isAbs, isURL bool) string {
if addBaseTargetPath && len(l.baseTargetPathDirs) > 1 { if addBaseTargetPath && len(l.baseTargetPathDirs) > 1 {
panic("multiple baseTargetPathDirs") panic("multiple baseTargetPathDirs")
} }
@ -791,10 +791,10 @@ func (l *genericResource) relTargetPathForRel(rel string, addBaseTargetPath, isU
basePath = l.baseTargetPathDirs[0] basePath = l.baseTargetPathDirs[0]
} }
return l.relTargetPathForRelAndBasePath(rel, basePath, isURL) return l.relTargetPathForRelAndBasePath(rel, basePath, isAbs, isURL)
} }
func (l *genericResource) relTargetPathForRelAndBasePath(rel, basePath string, isURL bool) string { func (l *genericResource) relTargetPathForRelAndBasePath(rel, basePath string, isAbs, isURL bool) string {
if l.targetPathBuilder != nil { if l.targetPathBuilder != nil {
rel = l.targetPathBuilder(rel) rel = l.targetPathBuilder(rel)
} }
@ -811,8 +811,11 @@ func (l *genericResource) relTargetPathForRelAndBasePath(rel, basePath string, i
rel = path.Join(l.baseOffset, rel) rel = path.Join(l.baseOffset, rel)
} }
if isURL && l.spec.PathSpec.BasePath != "" { if isURL {
rel = path.Join(l.spec.PathSpec.BasePath, rel) bp := l.spec.PathSpec.GetBasePath(!isAbs)
if bp != "" {
rel = path.Join(bp, rel)
}
} }
if len(rel) == 0 || rel[0] != '/' { if len(rel) == 0 || rel[0] != '/' {