mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
Normalize paths within hugo
filepath was used inconsistently throughout the hugolib. With the introduction of source and target modules, all path are normalized to "/". This simplifies the processing of paths. It does mean that contributors need to be aware of using path/filepath in any module other than source or target is not recommended. The current exception is hugolib/config.go
This commit is contained in:
parent
998b2f73f8
commit
74b55fc7c8
8 changed files with 46 additions and 43 deletions
|
@ -103,7 +103,7 @@ func (c *Config) readInConfig() {
|
||||||
|
|
||||||
func (c *Config) setPath(p string) {
|
func (c *Config) setPath(p string) {
|
||||||
if p == "" {
|
if p == "" {
|
||||||
path, err := FindPath()
|
path, err := findPath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error finding path: %s", err)
|
fmt.Printf("Error finding path: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ func (c *Config) GetPath() string {
|
||||||
return c.Path
|
return c.Path
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindPath() (string, error) {
|
func findPath() (string, error) {
|
||||||
serverFile, err := filepath.Abs(os.Args[0])
|
serverFile, err := filepath.Abs(os.Args[0])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -147,13 +147,14 @@ func FindPath() (string, error) {
|
||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAbsPath return the absolute path for a given path with the internal slashes
|
||||||
|
// properly converted.
|
||||||
func (c *Config) GetAbsPath(name string) string {
|
func (c *Config) GetAbsPath(name string) string {
|
||||||
if filepath.IsAbs(name) {
|
if filepath.IsAbs(name) {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
p := filepath.Join(c.GetPath(), name)
|
return filepath.ToSlash(filepath.Join(c.GetPath(), name))
|
||||||
return p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) findConfigFile(configFileName string) (string, error) {
|
func (c *Config) findConfigFile(configFileName string) (string, error) {
|
||||||
|
|
|
@ -26,16 +26,13 @@ import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"launchpad.net/goyaml"
|
"launchpad.net/goyaml"
|
||||||
"os"
|
"path"
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = filepath.Base("")
|
|
||||||
|
|
||||||
type Page struct {
|
type Page struct {
|
||||||
Status string
|
Status string
|
||||||
Images []string
|
Images []string
|
||||||
|
@ -135,7 +132,7 @@ func StripHTML(s string) string {
|
||||||
|
|
||||||
func (p *Page) guessSection() {
|
func (p *Page) guessSection() {
|
||||||
if p.Section == "" {
|
if p.Section == "" {
|
||||||
x := strings.Split(p.FileName, string(os.PathSeparator))
|
x := strings.Split(p.FileName, "/")
|
||||||
if len(x) > 1 {
|
if len(x) > 1 {
|
||||||
if section := x[len(x)-2]; section != "content" {
|
if section := x[len(x)-2]; section != "content" {
|
||||||
p.Section = section
|
p.Section = section
|
||||||
|
@ -223,26 +220,26 @@ func (p *Page) Permalink() template.HTML {
|
||||||
section := strings.TrimSpace(p.Section)
|
section := strings.TrimSpace(p.Section)
|
||||||
pSlug := strings.TrimSpace(p.Slug)
|
pSlug := strings.TrimSpace(p.Slug)
|
||||||
pUrl := strings.TrimSpace(p.Url)
|
pUrl := strings.TrimSpace(p.Url)
|
||||||
var path string
|
var permalink string
|
||||||
if len(pSlug) > 0 {
|
if len(pSlug) > 0 {
|
||||||
if p.Site.Config.UglyUrls {
|
if p.Site.Config.UglyUrls {
|
||||||
path = section + "/" + p.Slug + "." + p.Extension
|
permalink = section + "/" + p.Slug + "." + p.Extension
|
||||||
} else {
|
} else {
|
||||||
path = section + "/" + p.Slug + "/"
|
permalink = section + "/" + p.Slug + "/"
|
||||||
}
|
}
|
||||||
} else if len(pUrl) > 2 {
|
} else if len(pUrl) > 2 {
|
||||||
path = pUrl
|
permalink = pUrl
|
||||||
} else {
|
} else {
|
||||||
_, t := filepath.Split(p.FileName)
|
_, t := path.Split(p.FileName)
|
||||||
if p.Site.Config.UglyUrls {
|
if p.Site.Config.UglyUrls {
|
||||||
x := replaceExtension(strings.TrimSpace(t), p.Extension)
|
x := replaceExtension(strings.TrimSpace(t), p.Extension)
|
||||||
path = section + "/" + x
|
permalink = section + "/" + x
|
||||||
} else {
|
} else {
|
||||||
file, _ := fileExt(strings.TrimSpace(t))
|
file, _ := fileExt(strings.TrimSpace(t))
|
||||||
path = section + "/" + file
|
permalink = section + "/" + file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return template.HTML(MakePermalink(baseUrl, path))
|
return template.HTML(MakePermalink(baseUrl, permalink))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (page *Page) handleTomlMetaData(datum []byte) (interface{}, error) {
|
func (page *Page) handleTomlMetaData(datum []byte) (interface{}, error) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package hugolib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"path/filepath"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -260,7 +260,7 @@ func TestDegenerateInvalidFrontMatterLeadingWhitespace(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSectionEvaluation(t *testing.T) {
|
func TestSectionEvaluation(t *testing.T) {
|
||||||
page, _ := ReadFrom(strings.NewReader(SIMPLE_PAGE), filepath.FromSlash("blue/file1.md"))
|
page, _ := ReadFrom(strings.NewReader(SIMPLE_PAGE), "blue/file1.md")
|
||||||
if page.Section != "blue" {
|
if page.Section != "blue" {
|
||||||
t.Errorf("Section should be %s, got: %s", "blue", page.Section)
|
t.Errorf("Section should be %s, got: %s", "blue", page.Section)
|
||||||
}
|
}
|
||||||
|
@ -268,11 +268,11 @@ func TestSectionEvaluation(t *testing.T) {
|
||||||
|
|
||||||
func TestLayoutOverride(t *testing.T) {
|
func TestLayoutOverride(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
path_content_one_dir = filepath.Join("content", "gub", "file1.md")
|
path_content_one_dir = path.Join("content", "gub", "file1.md")
|
||||||
path_content_two_dir = filepath.Join("content", "dub", "sub", "file1.md")
|
path_content_two_dir = path.Join("content", "dub", "sub", "file1.md")
|
||||||
path_content_no_dir = filepath.Join("content", "file1")
|
path_content_no_dir = path.Join("content", "file1")
|
||||||
path_one_directory = filepath.Join("fub", "file1.md")
|
path_one_directory = path.Join("fub", "file1.md")
|
||||||
path_no_directory = filepath.Join("file1.md")
|
path_no_directory = path.Join("file1.md")
|
||||||
)
|
)
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
content string
|
content string
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package hugolib
|
package hugolib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -13,7 +13,7 @@ Sample Text
|
||||||
`
|
`
|
||||||
|
|
||||||
func TestDegenerateMissingFolderInPageFilename(t *testing.T) {
|
func TestDegenerateMissingFolderInPageFilename(t *testing.T) {
|
||||||
p, err := ReadFrom(strings.NewReader(SIMPLE_PAGE_YAML), filepath.Join("foobar"))
|
p, err := ReadFrom(strings.NewReader(SIMPLE_PAGE_YAML), path.Join("foobar"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error in ReadFrom")
|
t.Fatalf("Error in ReadFrom")
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,9 @@ func TestNewPageWithFilePath(t *testing.T) {
|
||||||
section string
|
section string
|
||||||
layout string
|
layout string
|
||||||
}{
|
}{
|
||||||
{filepath.Join("sub", "foobar.html"), "sub", "sub/single.html"},
|
{path.Join("sub", "foobar.html"), "sub", "sub/single.html"},
|
||||||
{filepath.Join("content", "sub", "foobar.html"), "sub", "sub/single.html"},
|
{path.Join("content", "sub", "foobar.html"), "sub", "sub/single.html"},
|
||||||
{filepath.Join("content", "dub", "sub", "foobar.html"), "sub", "sub/single.html"},
|
{path.Join("content", "dub", "sub", "foobar.html"), "sub", "sub/single.html"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, el := range toCheck {
|
for _, el := range toCheck {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
"github.com/spf13/nitro"
|
"github.com/spf13/nitro"
|
||||||
"html/template"
|
"html/template"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -264,7 +264,9 @@ func (s *Site) CreatePages() (err error) {
|
||||||
}
|
}
|
||||||
page.Site = s.Info
|
page.Site = s.Info
|
||||||
page.Tmpl = s.Tmpl
|
page.Tmpl = s.Tmpl
|
||||||
_ = s.setUrlPath(page)
|
if err = s.setUrlPath(page); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
s.setOutFile(page)
|
s.setOutFile(page)
|
||||||
if s.Config.BuildDrafts || !page.Draft {
|
if s.Config.BuildDrafts || !page.Draft {
|
||||||
s.Pages = append(s.Pages, page)
|
s.Pages = append(s.Pages, page)
|
||||||
|
@ -288,15 +290,15 @@ func (s *Site) setupPrevNext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) setUrlPath(p *Page) error {
|
func (s *Site) setUrlPath(p *Page) error {
|
||||||
y := strings.TrimPrefix(p.FileName, s.Config.GetAbsPath(s.Config.ContentDir))
|
y := strings.TrimPrefix(p.FileName, s.absContentDir())
|
||||||
x := strings.Split(y, string(os.PathSeparator))
|
x := strings.Split(y, "/")
|
||||||
|
|
||||||
if len(x) <= 1 {
|
if len(x) <= 1 {
|
||||||
return fmt.Errorf("Zero length page name")
|
return fmt.Errorf("Zero length page name")
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Section = strings.Trim(x[1], "/\\")
|
p.Section = strings.Trim(x[1], "/")
|
||||||
p.Path = strings.Trim(strings.Join(x[:len(x)-1], string(os.PathSeparator)), "/\\")
|
p.Path = path.Join(x[:len(x)-1]...)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,11 +322,11 @@ func (s *Site) setOutFile(p *Page) {
|
||||||
outfile = strings.TrimSpace(p.Slug) + "." + p.Extension
|
outfile = strings.TrimSpace(p.Slug) + "." + p.Extension
|
||||||
} else {
|
} else {
|
||||||
// Fall back to filename
|
// Fall back to filename
|
||||||
_, t := filepath.Split(p.FileName)
|
_, t := path.Split(p.FileName)
|
||||||
outfile = replaceExtension(strings.TrimSpace(t), p.Extension)
|
outfile = replaceExtension(strings.TrimSpace(t), p.Extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
p.OutFile = p.Path + string(os.PathSeparator) + strings.TrimSpace(outfile)
|
p.OutFile = p.Path + "/" + strings.TrimSpace(outfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) BuildSiteMeta() (err error) {
|
func (s *Site) BuildSiteMeta() (err error) {
|
||||||
|
@ -524,7 +526,7 @@ func (s *Site) RenderLists() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = s.WritePublic(section+"/index.html", content.Bytes())
|
err = s.WritePublic(section, content.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package hugolib
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -49,8 +48,8 @@ func TestPageCount(t *testing.T) {
|
||||||
s := &Site{Target: target}
|
s := &Site{Target: target}
|
||||||
s.prepTemplates()
|
s.prepTemplates()
|
||||||
must(s.addTemplate("indexes/blue.html", INDEX_TEMPLATE))
|
must(s.addTemplate("indexes/blue.html", INDEX_TEMPLATE))
|
||||||
s.Pages = append(s.Pages, mustReturn(ReadFrom(strings.NewReader(SLUG_DOC_1), filepath.FromSlash("content/blue/doc1.md"))))
|
s.Pages = append(s.Pages, mustReturn(ReadFrom(strings.NewReader(SLUG_DOC_1), "content/blue/doc1.md")))
|
||||||
s.Pages = append(s.Pages, mustReturn(ReadFrom(strings.NewReader(SLUG_DOC_2), filepath.FromSlash("content/blue/doc2.md"))))
|
s.Pages = append(s.Pages, mustReturn(ReadFrom(strings.NewReader(SLUG_DOC_2), "content/blue/doc2.md")))
|
||||||
|
|
||||||
if err := s.BuildSiteMeta(); err != nil {
|
if err := s.BuildSiteMeta(); err != nil {
|
||||||
t.Errorf("Unable to build site metadata: %s", err)
|
t.Errorf("Unable to build site metadata: %s", err)
|
||||||
|
@ -60,7 +59,7 @@ func TestPageCount(t *testing.T) {
|
||||||
t.Errorf("Unable to render site lists: %s", err)
|
t.Errorf("Unable to render site lists: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
blueIndex := target.files["blue/index.html"]
|
blueIndex := target.files["blue"]
|
||||||
if blueIndex == nil {
|
if blueIndex == nil {
|
||||||
t.Errorf("No indexed rendered. %v", target.files)
|
t.Errorf("No indexed rendered. %v", target.files)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ func (f *Filesystem) Files() []*File {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Filesystem) add(name string, reader io.Reader) {
|
func (f *Filesystem) add(name string, reader io.Reader) {
|
||||||
|
name = filepath.ToSlash(name)
|
||||||
f.files = append(f.files, &File{Name: name, Contents: reader})
|
f.files = append(f.files, &File{Name: name, Contents: reader})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ func TestFileTranslator(t *testing.T) {
|
||||||
{"foo", "foo/index.html"},
|
{"foo", "foo/index.html"},
|
||||||
{"foo.html", "foo/index.html"},
|
{"foo.html", "foo/index.html"},
|
||||||
{"foo.xhtml", "foo/index.xhtml"},
|
{"foo.xhtml", "foo/index.xhtml"},
|
||||||
|
{"section", "section/index.html"},
|
||||||
|
{"section/", "section/index.html"},
|
||||||
{"section/foo", "section/foo/index.html"},
|
{"section/foo", "section/foo/index.html"},
|
||||||
{"section/foo.html", "section/foo/index.html"},
|
{"section/foo.html", "section/foo/index.html"},
|
||||||
{"section/foo.rss", "section/foo/index.rss"},
|
{"section/foo.rss", "section/foo/index.rss"},
|
||||||
|
@ -34,7 +36,7 @@ func TestFileTranslator(t *testing.T) {
|
||||||
|
|
||||||
func TestFileTranslatorBase(t *testing.T) {
|
func TestFileTranslatorBase(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
content string
|
content string
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{"/", "a/base/index.html"},
|
{"/", "a/base/index.html"},
|
||||||
|
@ -64,6 +66,7 @@ func TestTranslateUglyUrls(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{"foo.html", "foo.html"},
|
{"foo.html", "foo.html"},
|
||||||
{"/", "index.html"},
|
{"/", "index.html"},
|
||||||
|
{"section", "section.html"},
|
||||||
{"index.html", "index.html"},
|
{"index.html", "index.html"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue