mirror of
https://github.com/jimeh/go-golden.git
synced 2026-02-19 11:16:47 +00:00
wip: refactor Golden to a interface, improve testability of main implementation
This commit is contained in:
34
sanitize/filename.go
Normal file
34
sanitize/filename.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package sanitize
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
whitespaceChars = regexp.MustCompile(`\s`)
|
||||
illegalChars = regexp.MustCompile(`[\/\?<>\\:\*\|"]`)
|
||||
controlChars = regexp.MustCompile(`[\x00-\x1f\x80-\x9f]`)
|
||||
reservedNames = regexp.MustCompile(`^\.+$`)
|
||||
winReserved = regexp.MustCompile(
|
||||
`(?i)^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$`,
|
||||
)
|
||||
)
|
||||
|
||||
func Filename(name string) string {
|
||||
if reservedNames.MatchString(name) || winReserved.MatchString(name) {
|
||||
var b []byte
|
||||
for i := 0; i < len(name); i++ {
|
||||
b = append(b, byte('_'))
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
r := strings.TrimRight(name, ". ")
|
||||
r = whitespaceChars.ReplaceAllString(r, "_")
|
||||
r = illegalChars.ReplaceAllString(r, "_")
|
||||
r = controlChars.ReplaceAllString(r, "_")
|
||||
|
||||
return r
|
||||
}
|
||||
126
sanitize/filename_test.go
Normal file
126
sanitize/filename_test.go
Normal file
@@ -0,0 +1,126 @@
|
||||
package sanitize_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jimeh/go-golden/sanitize"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFilename(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
filename string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
filename: "",
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: ".",
|
||||
filename: ".",
|
||||
want: "_",
|
||||
},
|
||||
{
|
||||
name: "..",
|
||||
filename: "..",
|
||||
want: "__",
|
||||
},
|
||||
{
|
||||
name: "...",
|
||||
filename: "...",
|
||||
want: "___",
|
||||
},
|
||||
{
|
||||
name: "clean",
|
||||
filename: "foo-bar-nope.golden",
|
||||
want: "foo-bar-nope.golden",
|
||||
},
|
||||
{
|
||||
name: "with spaces",
|
||||
filename: "foo bar nope.golden",
|
||||
want: "foo__bar_nope.golden",
|
||||
},
|
||||
{
|
||||
name: "illegal chars",
|
||||
filename: `foo/?<>\:*|"bar.golden`,
|
||||
want: "foo_________bar.golden",
|
||||
},
|
||||
{
|
||||
name: "control chars",
|
||||
filename: "foo\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b" +
|
||||
"\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a" +
|
||||
"\x1b\x1c\x1d\x1e\x1fbar.golden",
|
||||
want: "foo________________________________bar.golden",
|
||||
},
|
||||
{
|
||||
name: "trailing whitespace",
|
||||
filename: "foobar.golden ",
|
||||
want: "foobar.golden",
|
||||
},
|
||||
{
|
||||
name: "trailing dots",
|
||||
filename: "foobar.golden......",
|
||||
want: "foobar.golden",
|
||||
},
|
||||
{
|
||||
name: "trailing whitespace and dots",
|
||||
filename: "foobar.golden .. .. .. ",
|
||||
want: "foobar.golden",
|
||||
},
|
||||
// Protected Windows filenames.
|
||||
{name: "con", filename: "con", want: "___"},
|
||||
{name: "prn", filename: "prn", want: "___"},
|
||||
{name: "aux", filename: "aux", want: "___"},
|
||||
{name: "nul", filename: "nul", want: "___"},
|
||||
{name: "com1", filename: "com1", want: "____"},
|
||||
{name: "com2", filename: "com2", want: "____"},
|
||||
{name: "com3", filename: "com3", want: "____"},
|
||||
{name: "com4", filename: "com4", want: "____"},
|
||||
{name: "com5", filename: "com5", want: "____"},
|
||||
{name: "com6", filename: "com6", want: "____"},
|
||||
{name: "com7", filename: "com7", want: "____"},
|
||||
{name: "com8", filename: "com8", want: "____"},
|
||||
{name: "com9", filename: "com9", want: "____"},
|
||||
{name: "lpt1", filename: "lpt1", want: "____"},
|
||||
{name: "lpt2", filename: "lpt2", want: "____"},
|
||||
{name: "lpt3", filename: "lpt3", want: "____"},
|
||||
{name: "lpt4", filename: "lpt4", want: "____"},
|
||||
{name: "lpt5", filename: "lpt5", want: "____"},
|
||||
{name: "lpt6", filename: "lpt6", want: "____"},
|
||||
{name: "lpt7", filename: "lpt7", want: "____"},
|
||||
{name: "lpt8", filename: "lpt8", want: "____"},
|
||||
{name: "lpt9", filename: "lpt9", want: "____"},
|
||||
{name: "CON", filename: "CON", want: "___"},
|
||||
{name: "PRN", filename: "PRN", want: "___"},
|
||||
{name: "AUX", filename: "AUX", want: "___"},
|
||||
{name: "NUL", filename: "NUL", want: "___"},
|
||||
{name: "COM1", filename: "COM1", want: "____"},
|
||||
{name: "COM2", filename: "COM2", want: "____"},
|
||||
{name: "COM3", filename: "COM3", want: "____"},
|
||||
{name: "COM4", filename: "COM4", want: "____"},
|
||||
{name: "COM5", filename: "COM5", want: "____"},
|
||||
{name: "COM6", filename: "COM6", want: "____"},
|
||||
{name: "COM7", filename: "COM7", want: "____"},
|
||||
{name: "COM8", filename: "COM8", want: "____"},
|
||||
{name: "COM9", filename: "COM9", want: "____"},
|
||||
{name: "LPT1", filename: "LPT1", want: "____"},
|
||||
{name: "LPT2", filename: "LPT2", want: "____"},
|
||||
{name: "LPT3", filename: "LPT3", want: "____"},
|
||||
{name: "LPT4", filename: "LPT4", want: "____"},
|
||||
{name: "LPT5", filename: "LPT5", want: "____"},
|
||||
{name: "LPT6", filename: "LPT6", want: "____"},
|
||||
{name: "LPT7", filename: "LPT7", want: "____"},
|
||||
{name: "LPT8", filename: "LPT8", want: "____"},
|
||||
{name: "LPT9", filename: "LPT9", want: "____"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := sanitize.Filename(tt.filename)
|
||||
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
21
sanitize/line_breaks.go
Normal file
21
sanitize/line_breaks.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package sanitize
|
||||
|
||||
import "bytes"
|
||||
|
||||
var (
|
||||
lf = []byte{10}
|
||||
cr = []byte{13}
|
||||
crlf = []byte{13, 10}
|
||||
)
|
||||
|
||||
// LineBreaks replaces Windows CRLF (\r\n) and MacOS Classic CR (\r)
|
||||
// line-breaks with Unix LF (\n) line breaks.
|
||||
func LineBreaks(data []byte) []byte {
|
||||
// Replace Windows CRLF (\r\n) with Unix LF (\n)
|
||||
result := bytes.ReplaceAll(data, crlf, lf)
|
||||
|
||||
// Replace Classic MacOS CR (\r) with Unix LF (\n)
|
||||
result = bytes.ReplaceAll(result, cr, lf)
|
||||
|
||||
return result
|
||||
}
|
||||
67
sanitize/line_breaks_test.go
Normal file
67
sanitize/line_breaks_test.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package sanitize_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/jimeh/go-golden/sanitize"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLineBreaks(t *testing.T) {
|
||||
type args struct {
|
||||
data []byte
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []byte
|
||||
}{
|
||||
{
|
||||
name: "nil",
|
||||
args: args{data: nil},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "empty",
|
||||
args: args{data: []byte{}},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "no line breaks",
|
||||
args: args{data: []byte("hello world")},
|
||||
want: []byte("hello world"),
|
||||
},
|
||||
{
|
||||
name: "UNIX line breaks",
|
||||
args: args{data: []byte("hello\nworld\nhow are you?")},
|
||||
want: []byte("hello\nworld\nhow are you?"),
|
||||
},
|
||||
{
|
||||
name: "Windows line breaks",
|
||||
args: args{data: []byte("hello\r\nworld\r\nhow are you?")},
|
||||
want: []byte("hello\nworld\nhow are you?"),
|
||||
},
|
||||
{
|
||||
name: "MacOS Classic line breaks",
|
||||
args: args{data: []byte("hello\rworld\rhow are you?")},
|
||||
want: []byte("hello\nworld\nhow are you?"),
|
||||
},
|
||||
{
|
||||
name: "Windows and MacOS Classic line breaks",
|
||||
args: args{data: []byte("hello\r\nworld\rhow are you?")},
|
||||
want: []byte("hello\nworld\nhow are you?"),
|
||||
},
|
||||
{
|
||||
name: "Windows, MacOS Classic, and UNIX line breaks",
|
||||
args: args{data: []byte("hello\r\nworld\rhow are you?\nGood!")},
|
||||
want: []byte("hello\nworld\nhow are you?\nGood!"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := sanitize.LineBreaks(tt.args.data)
|
||||
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user