return
}
-func prettifyPath(in string, b filepathPathBridge) string {
- if filepath.Ext(in) == "" {
- // /section/name/ -> /section/name/index.html
- if len(in) < 2 {
- return b.Separator()
- }
- return b.Join(in, "index.html")
- }
- name, ext := fileAndExt(in, b)
- if name == "index" {
- // /section/name/index.html -> /section/name/index.html
- return b.Clean(in)
- }
- // /section/name.html -> /section/name/index.html
- return b.Join(b.Dir(in), name, "index"+ext)
-}
-
// Sanitize sanitizes string to be used in Hugo's file paths and URLs, allowing only
// a predefined set of special Unicode characters.
//
package helpers
import (
- "bytes"
"fmt"
"io"
"net"
return b.String()
}
-// ReaderContains reports whether subslice is within r.
-func ReaderContains(r io.Reader, subslice []byte) bool {
- if r == nil || len(subslice) == 0 {
- return false
- }
-
- bufflen := len(subslice) * 4
- halflen := bufflen / 2
- buff := make([]byte, bufflen)
- var err error
- var n, i int
-
- for {
- i++
- if i == 1 {
- n, err = io.ReadAtLeast(r, buff[:halflen], halflen)
- } else {
- if i != 2 {
- // shift left to catch overlapping matches
- copy(buff[:], buff[halflen:])
- }
- n, err = io.ReadAtLeast(r, buff[halflen:], halflen)
- }
-
- if n > 0 && bytes.Contains(buff, subslice) {
- return true
- }
-
- if err != nil {
- break
- }
- }
- return false
-}
-
// GetTitleFunc returns a func that can be used to transform a string to
// title case.
//
package helpers_test
import (
- "strings"
"testing"
qt "github.com/frankban/quicktest"
}
}
-var containsTestText = (`На берегу пустынных волн
-Стоял он, дум великих полн,
-И вдаль глядел. Пред ним широко
-Река неслася; бедный чёлн
-По ней стремился одиноко.
-По мшистым, топким берегам
-Чернели избы здесь и там,
-Приют убогого чухонца;
-И лес, неведомый лучам
-В тумане спрятанного солнца,
-Кругом шумел.
-
-Τη γλώσσα μου έδωσαν ελληνική
-το σπίτι φτωχικό στις αμμουδιές του Ομήρου.
-Μονάχη έγνοια η γλώσσα μου στις αμμουδιές του Ομήρου.
-
-από το Άξιον Εστί
-του Οδυσσέα Ελύτη
-
-Sîne klâwen durh die wolken sint geslagen,
-er stîget ûf mit grôzer kraft,
-ich sih in grâwen tägelîch als er wil tagen,
-den tac, der im geselleschaft
-erwenden wil, dem werden man,
-den ich mit sorgen în verliez.
-ich bringe in hinnen, ob ich kan.
-sîn vil manegiu tugent michz leisten hiez.
-`)
-
-var containsBenchTestData = []struct {
- v1 string
- v2 []byte
- expect bool
-}{
- {"abc", []byte("a"), true},
- {"abc", []byte("b"), true},
- {"abcdefg", []byte("efg"), true},
- {"abc", []byte("d"), false},
- {containsTestText, []byte("стремился"), true},
- {containsTestText, []byte(containsTestText[10:80]), true},
- {containsTestText, []byte(containsTestText[100:111]), true},
- {containsTestText, []byte(containsTestText[len(containsTestText)-100 : len(containsTestText)-10]), true},
- {containsTestText, []byte(containsTestText[len(containsTestText)-20:]), true},
- {containsTestText, []byte("notfound"), false},
-}
-
-// some corner cases
-var containsAdditionalTestData = []struct {
- v1 string
- v2 []byte
- expect bool
-}{
- {"", nil, false},
- {"", []byte("a"), false},
- {"a", []byte(""), false},
- {"", []byte(""), false},
-}
-
func TestSliceToLower(t *testing.T) {
t.Parallel()
tests := []struct {
}
}
-func TestReaderContains(t *testing.T) {
- c := qt.New(t)
- for i, this := range append(containsBenchTestData, containsAdditionalTestData...) {
- result := helpers.ReaderContains(strings.NewReader(this.v1), this.v2)
- if result != this.expect {
- t.Errorf("[%d] got %t but expected %t", i, result, this.expect)
- }
- }
-
- c.Assert(helpers.ReaderContains(nil, []byte("a")), qt.Equals, false)
- c.Assert(helpers.ReaderContains(nil, nil), qt.Equals, false)
-}
-
func TestGetTitleFunc(t *testing.T) {
title := "somewhere over the Rainbow"
c := qt.New(t)
c.Assert(helpers.GetTitleFunc("firstupper")(title), qt.Equals, "Somewhere over the Rainbow")
}
-func BenchmarkReaderContains(b *testing.B) {
-
- for b.Loop() {
- for i, this := range containsBenchTestData {
- result := helpers.ReaderContains(strings.NewReader(this.v1), this.v2)
- if result != this.expect {
- b.Errorf("[%d] got %t but expected %t", i, result, this.expect)
- }
- }
- }
-}
-
func TestStringSliceToList(t *testing.T) {
for _, tt := range []struct {
slice []string
package helpers
import (
- "errors"
"fmt"
"io"
"os"
return strings.ToLower(p.MakePath(s))
}
-// MakeTitle converts the path given to a suitable title, trimming whitespace
-// and replacing hyphens with whitespace.
-func MakeTitle(inpath string) string {
- return strings.Replace(strings.TrimSpace(inpath), "-", " ", -1)
-}
-
-// MakeTitleInPath converts the path given to a suitable title, trimming whitespace
-func MakePathRelative(inPath string, possibleDirectories ...string) (string, error) {
- for _, currentPath := range possibleDirectories {
- if after, ok := strings.CutPrefix(inPath, currentPath); ok {
- return after, nil
- }
- }
- return inPath, errors.New("can't extract relative path, unknown prefix")
-}
-
// Should be good enough for Hugo.
var isFileRe = regexp.MustCompile(`.*\..{1,6}$`)
return groups
}
-// FindCWD returns the current working directory from where the Hugo
-// executable is run.
-func FindCWD() (string, error) {
- serverFile, err := filepath.Abs(os.Args[0])
- if err != nil {
- return "", fmt.Errorf("can't get absolute path for executable: %v", err)
- }
-
- path := filepath.Dir(serverFile)
- realFile, err := filepath.EvalSymlinks(serverFile)
- if err != nil {
- if _, err = os.Stat(serverFile + ".exe"); err == nil {
- realFile = filepath.Clean(serverFile + ".exe")
- }
- }
-
- if err == nil && realFile != serverFile {
- path = filepath.Dir(realFile)
- }
-
- return path, nil
-}
-
// Walk walks the file tree rooted at root, calling walkFn for each file or
// directory in the tree, including root.
func Walk(fs afero.Fs, root string, walker hugofs.WalkFunc) error {
return w.Walk()
}
-// SafeWriteToDisk is the same as WriteToDisk
-// but it also checks to see if file/directory already exists.
-func SafeWriteToDisk(inpath string, r io.Reader, fs afero.Fs) (err error) {
- return afero.SafeWriteReader(fs, inpath, r)
-}
-
// WriteToDisk writes content to disk.
func WriteToDisk(inpath string, r io.Reader, fs afero.Fs) (err error) {
return afero.WriteReader(fs, inpath, r)
}
}
-func TestMakePathRelative(t *testing.T) {
- type test struct {
- inPath, path1, path2, output string
- }
-
- data := []test{
- {"/abc/bcd/ab.css", "/abc/bcd", "/bbc/bcd", "/ab.css"},
- {"/abc/bcd/ab.css", "/abcd/bcd", "/abc/bcd", "/ab.css"},
- }
-
- for i, d := range data {
- output, _ := helpers.MakePathRelative(d.inPath, d.path1, d.path2)
- if d.output != output {
- t.Errorf("Test #%d failed. Expected %q got %q", i, d.output, output)
- }
- }
- _, error := helpers.MakePathRelative("a/b/c.ss", "/a/c", "/d/c", "/e/f")
-
- if error == nil {
- t.Errorf("Test failed, expected error")
- }
-}
-
func TestGetDottedRelativePath(t *testing.T) {
for _, f := range []func(string) string{filepath.FromSlash, func(s string) string { return s }} {
doTestGetDottedRelativePath(f, t)
}
}
-func TestMakeTitle(t *testing.T) {
- type test struct {
- input, expected string
- }
- data := []test{
- {"Make-Title", "Make Title"},
- {"MakeTitle", "MakeTitle"},
- {"make_title", "make_title"},
- }
- for i, d := range data {
- output := helpers.MakeTitle(d.input)
- if d.expected != output {
- t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output)
- }
- }
-}
-
func TestDirExists(t *testing.T) {
type test struct {
input string
}
}
-func TestFindCWD(t *testing.T) {
- type test struct {
- expectedDir string
- expectedErr error
- }
-
- // cwd, _ := os.Getwd()
- data := []test{
- //{cwd, nil},
- // Commenting this out. It doesn't work properly.
- // There's a good reason why we don't use os.Getwd(), it doesn't actually work the way we want it to.
- // I really don't know a better way to test this function. - SPF 2014.11.04
- }
- for i, d := range data {
- dir, err := helpers.FindCWD()
- if d.expectedDir != dir {
- t.Errorf("Test %d failed. Expected %q but got %q", i, d.expectedDir, dir)
- }
- if d.expectedErr != err {
- t.Errorf("Test %d failed. Expected %q but got %q", i, d.expectedErr, err)
- }
- }
-}
-
-func TestSafeWriteToDisk(t *testing.T) {
- emptyFile := createZeroSizedFileInTempDir(t)
- tmpDir := t.TempDir()
-
- randomString := "This is a random string!"
- reader := strings.NewReader(randomString)
-
- fileExists := fmt.Errorf("%v already exists", emptyFile.Name())
-
- type test struct {
- filename string
- expectedErr error
- }
-
- now := time.Now().Unix()
- nowStr := strconv.FormatInt(now, 10)
- data := []test{
- {emptyFile.Name(), fileExists},
- {tmpDir + "/" + nowStr, nil},
- }
-
- for i, d := range data {
- e := helpers.SafeWriteToDisk(d.filename, reader, new(afero.OsFs))
- if d.expectedErr != nil {
- if d.expectedErr.Error() != e.Error() {
- t.Errorf("Test %d failed. Expected error %q but got %q", i, d.expectedErr.Error(), e.Error())
- }
- } else {
- if d.expectedErr != e {
- t.Errorf("Test %d failed. Expected %q but got %q", i, d.expectedErr, e)
- }
- contents, _ := os.ReadFile(d.filename)
- if randomString != string(contents) {
- t.Errorf("Test %d failed. Expected contents %q but got %q", i, randomString, string(contents))
- }
- }
- reader.Seek(0, 0)
- }
-}
-
func TestWriteToDisk(t *testing.T) {
emptyFile := createZeroSizedFileInTempDir(t)
tmpDir := t.TempDir()
atomic.AddUint64(counter, 1)
}
-// Add adds an amount to a given counter.
-func (s *ProcessingStats) Add(counter *uint64, amount int) {
- atomic.AddUint64(counter, uint64(amount))
-}
-
// ProcessingStatsTable writes a table-formatted representation of stats to w.
func ProcessingStatsTable(w io.Writer, stats ...*ProcessingStats) {
names := make([]string, len(stats)+1)
return p.URLEscape(p.MakePathSanitized(uri))
}
-// URLizeFilename creates an URL from a filename by escaping unicode letters
-// and turn any filepath separator into forward slashes.
-func (p *PathSpec) URLizeFilename(filename string) string {
- return p.URLEscape(filepath.ToSlash(filename))
-}
-
// URLEscape escapes unicode letters.
func (p *PathSpec) URLEscape(uri string) string {
// escape unicode letters