8 Commits

Author SHA1 Message Date
4ded03bd72 chore(release): 1.0.2 2020-12-14 14:55:43 +00:00
68a97519d5 Merge pull request #4 from jimeh/fix-bytes-method
fix(bytes): change Bytes function to accept string input but return a byte slice
2020-12-14 14:55:04 +00:00
5dbdbbf341 fix(bytes): change Bytes function to accept string input but return a byte slice
The old method signature was just nonsensical, as you would always be
providing indented values via a string literal. So it makes much more
sense to have all methods accept a string argument, and then return
different types.

This also allows use of a `Bytesf` method.

This is technically a breaking change, but I'm classifying it as a
bugfix cause the old method signature was basically useless.
2020-12-14 14:52:32 +00:00
d79e413e8e chore(release): 1.0.1 2020-12-07 10:48:40 +00:00
cc372da881 Merge pull request #3 from jimeh/remove-leading-line-break-on-undented-values
fix(whitespace): remove leading line-break from input
2020-12-07 10:46:31 +00:00
b2057429a1 fix(whitespace): remove leading line-break from input
This effectively cleans up what I consider syntactical sugar required
due to Go's syntax. For example:

    str := undent.String(`
        hello
        world`,
    )

In the above example I would consider the initial line-break after the
opening back-tick (`) character syntactical sugar, and hence should be
discarded from the final undented string.

However if the literal string contains more than one initial line-break,
only the first one should be removed, as the rest would intentionally be
part of the input.
2020-12-07 10:43:26 +00:00
24e64f6c39 docs(readme): fix readme description to match godoc description 2020-11-26 12:42:41 +00:00
30dba69951 docs(readme): add Benchmarks section, update Go Reference link 2020-11-26 12:32:58 +00:00
5 changed files with 161 additions and 63 deletions

View File

@@ -2,6 +2,20 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [1.0.2](https://github.com/jimeh/undent/compare/v1.0.1...v1.0.2) (2020-12-14)
### Bug Fixes
* **bytes:** change Bytes function to accept string input but return a byte slice ([5dbdbbf](https://github.com/jimeh/undent/commit/5dbdbbf3416b024aac8fca4e218802d6ad49ea74))
### [1.0.1](https://github.com/jimeh/undent/compare/v1.0.0...v1.0.1) (2020-12-07)
### Bug Fixes
* **whitespace:** remove leading line-break from input ([b205742](https://github.com/jimeh/undent/commit/b2057429a1181724ae50acaed26fe434231362b4))
## 1.0.0 (2020-11-26)

View File

@@ -4,8 +4,8 @@
<p align="center">
<strong>
Go package which removes leading indentation/white-space from multi-line
strings and byte slices.
Go package which removes leading indentation/white-space from strings and
byte slices.
</strong>
</p>
@@ -52,8 +52,14 @@ fmt.Println(s)
## Documentation
Please see the [Go Reference](https://pkg.go.dev/github.com/jimeh/undent) for
documentation and examples.
Please see the
[Go Reference](https://pkg.go.dev/github.com/jimeh/undent#section-documentation)
for documentation and examples.
## Benchmarks
Benchmark reports and graphs are available here:
https://jimeh.me/undent/dev/bench/
## License

View File

@@ -9,36 +9,25 @@ import (
var matcher = regexp.MustCompile(`(?m)^([ \t]*)(?:\S)`)
// Bytes removes leading indentation/white-space from given byte slice.
func Bytes(b []byte) []byte {
matches := matcher.FindAll(b, -1)
if len(matches) == 0 {
return b
}
// Bytes removes leading indentation/white-space from given string and returns
// it as a byte slice.
func Bytes(s string) []byte {
return []byte(String(s))
}
index := 0
length := len(matches[0])
for i, s := range matches[1:] {
l := len(s)
if l < length {
index = i + 1
length = l
}
}
if length <= 1 {
return b
}
indent := matches[index][0 : length-1]
return regexp.MustCompile(
`(?m)^`+regexp.QuoteMeta(string(indent)),
).ReplaceAllLiteral(b, []byte{})
// Bytesf removes leading indentation/white-space from given format string
// before passing format and all additional arguments to fmt.Sprintf, returning
// the result as a byte slice.
func Bytesf(format string, a ...interface{}) []byte {
return []byte(Stringf(format, a...))
}
// String removes leading indentation/white-space from given string.
func String(s string) string {
if len(s) > 0 && s[0] == '\n' {
s = s[1:]
}
matches := matcher.FindAllString(s, -1)
if len(matches) == 0 {
return s

View File

@@ -7,15 +7,28 @@ import (
)
func ExampleBytes() {
b := undent.Bytes([]byte(`
b := undent.Bytes(`
{
"hello": "world"
}`,
))
)
fmt.Println(string(b))
// Output:
//
// {
// "hello": "world"
// }
}
func ExampleBytesf() {
s := undent.Bytesf(`
{
"hello": "%s"
}`,
"world",
)
fmt.Println(string(s))
// Output:
// {
// "hello": "world"
// }
@@ -29,7 +42,6 @@ func ExampleString() {
)
fmt.Println(s)
// Output:
//
// {
// "hello": "world"
// }
@@ -44,7 +56,6 @@ func ExampleStringf() {
)
fmt.Println(s)
// Output:
//
// {
// "hello": "world"
// }

View File

@@ -35,8 +35,7 @@ var stringTestCases = []struct {
"bar"
]
}`,
want: `
{
want: `{
"hello": "world",
"foo": [
"bar"
@@ -46,6 +45,24 @@ var stringTestCases = []struct {
{
name: "multi-line space indented",
s: `
{
"hello": "world",
"foo": [
"bar"
]
}`,
want: `{
"hello": "world",
"foo": [
"bar"
]
}`,
},
{
name: "multi-line space indented with leading line-breaks",
s: `
{
"hello": "world",
"foo": [
@@ -53,6 +70,7 @@ var stringTestCases = []struct {
]
}`,
want: `
{
"hello": "world",
"foo": [
@@ -63,6 +81,24 @@ var stringTestCases = []struct {
{
name: "multi-line tab indented",
s: `
{
"hello": "world",
"foo": [
"bar"
]
}`,
want: `{
"hello": "world",
"foo": [
"bar"
]
}`,
},
{
name: "multi-line tab indented with leading line breaks",
s: `
{
"hello": "world",
"foo": [
@@ -70,6 +106,7 @@ var stringTestCases = []struct {
]
}`,
want: `
{
"hello": "world",
"foo": [
@@ -86,8 +123,7 @@ var stringTestCases = []struct {
"bar"
]
}`,
want: `
{
want: `{
"hello": "world",
"foo": [
"bar"
@@ -105,8 +141,7 @@ var stringTestCases = []struct {
]
}`,
want: `
{
want: `{
"hello": "world",
"foo": [
@@ -126,8 +161,7 @@ var stringTestCases = []struct {
]
}`,
want: `
{
want: `{
"hello": "world",
"foo": [
@@ -143,8 +177,7 @@ var stringTestCases = []struct {
world
foo
bar`,
want: `
hello
want: ` hello
world
foo
bar`,
@@ -156,8 +189,7 @@ world
world
foo
bar`,
want: `
hello
want: ` hello
world
foo
bar`,
@@ -197,8 +229,7 @@ var stringfTestCases = []struct {
]
}`,
a: []interface{}{"world", 42},
want: `
{
want: `{
"hello": "world",
"foo": [
42
@@ -208,6 +239,25 @@ var stringfTestCases = []struct {
{
name: "multi-line space indented",
s: `
{
"hello": "%s",
"foo": [
%d
]
}`,
a: []interface{}{"world", 42},
want: `{
"hello": "world",
"foo": [
42
]
}`,
},
{
name: "multi-line space indented with leading line-breaks",
s: `
{
"hello": "%s",
"foo": [
@@ -216,6 +266,7 @@ var stringfTestCases = []struct {
}`,
a: []interface{}{"world", 42},
want: `
{
"hello": "world",
"foo": [
@@ -233,7 +284,27 @@ var stringfTestCases = []struct {
]
}`,
a: []interface{}{"world", 42},
want: `{
"hello": "world",
"foo": [
42
]
}`,
},
{
name: "multi-line tab indented with leading line-breaks",
s: `
{
"hello": "%s",
"foo": [
%d
]
}`,
a: []interface{}{"world", 42},
want: `
{
"hello": "world",
"foo": [
@@ -251,8 +322,7 @@ var stringfTestCases = []struct {
]
}`,
a: []interface{}{"world", 42},
want: `
{
want: `{
"hello": "world",
"foo": [
42
@@ -271,8 +341,7 @@ var stringfTestCases = []struct {
]
}`,
a: []interface{}{"world", 42},
want: `
{
want: `{
"hello": "world",
"foo": [
@@ -293,8 +362,7 @@ var stringfTestCases = []struct {
]
}`,
a: []interface{}{"world", 42},
want: `
{
want: `{
"hello": "world",
"foo": [
@@ -311,8 +379,7 @@ var stringfTestCases = []struct {
foo
%d`,
a: []interface{}{"world", 42},
want: `
hello
want: ` hello
world
foo
42`,
@@ -325,8 +392,7 @@ world
foo
%d`,
a: []interface{}{"world", 42},
want: `
hello
want: ` hello
world
foo
42`,
@@ -336,9 +402,21 @@ world
func TestBytes(t *testing.T) {
for _, tt := range stringTestCases {
t.Run(tt.name, func(t *testing.T) {
got := Bytes([]byte(tt.s))
got := Bytes(tt.s)
assert.Equal(t, []byte(tt.want), got)
assert.IsType(t, []byte{}, got)
assert.Equal(t, tt.want, string(got))
})
}
}
func TestBytesf(t *testing.T) {
for _, tt := range stringfTestCases {
t.Run(tt.name, func(t *testing.T) {
got := Bytesf(tt.s, tt.a...)
assert.IsType(t, []byte{}, got)
assert.Equal(t, tt.want, string(got))
})
}
}
@@ -348,6 +426,7 @@ func TestString(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
got := String(tt.s)
assert.IsType(t, "", got)
assert.Equal(t, tt.want, got)
})
}
@@ -358,6 +437,7 @@ func TestStringf(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
got := Stringf(tt.s, tt.a...)
assert.IsType(t, "", got)
assert.Equal(t, tt.want, got)
})
}
@@ -366,10 +446,8 @@ func TestStringf(t *testing.T) {
func BenchmarkBytes(b *testing.B) {
for _, tt := range stringTestCases {
b.Run(tt.name, func(b *testing.B) {
input := []byte(tt.s)
for i := 0; i < b.N; i++ {
Bytes(input)
Bytes(tt.s)
}
})
}