summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/collections/append.go152
-rw-r--r--common/collections/append_test.go148
-rw-r--r--common/collections/collections.go21
-rw-r--r--common/collections/order.go20
-rw-r--r--common/collections/slice.go95
-rw-r--r--common/collections/slice_test.go138
-rw-r--r--common/collections/stack.go67
-rw-r--r--common/constants/constants.go45
-rw-r--r--common/docs.go2
-rw-r--r--common/hcontext/context.go46
-rw-r--r--common/herrors/error_locator.go176
-rw-r--r--common/herrors/error_locator_test.go152
-rw-r--r--common/herrors/errors.go139
-rw-r--r--common/herrors/errors_test.go45
-rw-r--r--common/herrors/file_error.go422
-rw-r--r--common/herrors/file_error_test.go80
-rw-r--r--common/herrors/line_number_extractors.go63
-rw-r--r--common/hexec/exec.go274
-rw-r--r--common/hreflect/helpers.go274
-rw-r--r--common/hreflect/helpers_test.go123
-rw-r--r--common/hstrings/strings.go129
-rw-r--r--common/hstrings/strings_test.go56
-rw-r--r--common/htime/htime_integration_test.go78
-rw-r--r--common/htime/time.go177
-rw-r--r--common/htime/time_test.go144
-rw-r--r--common/hugio/copy.go93
-rw-r--r--common/hugio/hasBytesWriter.go57
-rw-r--r--common/hugio/hasBytesWriter_test.go64
-rw-r--r--common/hugio/readers.go106
-rw-r--r--common/hugio/writers.go83
-rw-r--r--common/hugo/hugo.go399
-rw-r--r--common/hugo/hugo_test.go83
-rw-r--r--common/hugo/vars_extended.go19
-rw-r--r--common/hugo/vars_regular.go19
-rw-r--r--common/hugo/version.go302
-rw-r--r--common/hugo/version_current.go23
-rw-r--r--common/hugo/version_test.go88
-rw-r--r--common/loggers/handlerdefault.go106
-rw-r--r--common/loggers/handlersmisc.go145
-rw-r--r--common/loggers/handlerterminal.go90
-rw-r--r--common/loggers/logger.go379
-rw-r--r--common/loggers/logger_test.go154
-rw-r--r--common/loggers/loggerglobal.go54
-rw-r--r--common/maps/cache.go90
-rw-r--r--common/maps/maps.go236
-rw-r--r--common/maps/maps_test.go195
-rw-r--r--common/maps/params.go345
-rw-r--r--common/maps/params_test.go169
-rw-r--r--common/maps/scratch.go173
-rw-r--r--common/maps/scratch_test.go221
-rw-r--r--common/math/math.go135
-rw-r--r--common/math/math_test.go106
-rw-r--r--common/para/para.go73
-rw-r--r--common/para/para_test.go96
-rw-r--r--common/paths/path.go399
-rw-r--r--common/paths/path_test.go264
-rw-r--r--common/paths/pathparser.go559
-rw-r--r--common/paths/pathparser_test.go357
-rw-r--r--common/paths/paths_integration_test.go80
-rw-r--r--common/paths/pathtype_string.go27
-rw-r--r--common/paths/url.go195
-rw-r--r--common/paths/url_test.go100
-rw-r--r--common/predicate/predicate.go72
-rw-r--r--common/predicate/predicate_test.go83
-rw-r--r--common/rungroup/rungroup.go93
-rw-r--r--common/rungroup/rungroup_test.go44
-rw-r--r--common/terminal/colors.go79
-rw-r--r--common/text/position.go100
-rw-r--r--common/text/position_test.go32
-rw-r--r--common/text/transform.go78
-rw-r--r--common/text/transform_test.go72
-rw-r--r--common/types/convert.go129
-rw-r--r--common/types/convert_test.go48
-rw-r--r--common/types/css/csstypes.go20
-rw-r--r--common/types/evictingqueue.go107
-rw-r--r--common/types/evictingqueue_test.go74
-rw-r--r--common/types/hstring/stringtypes.go20
-rw-r--r--common/types/hstring/stringtypes_test.go30
-rw-r--r--common/types/types.go114
-rw-r--r--common/types/types_test.go29
-rw-r--r--common/urls/baseURL.go112
-rw-r--r--common/urls/baseURL_test.go81
-rw-r--r--common/urls/ref.go22
83 files changed, 10589 insertions, 0 deletions
diff --git a/common/collections/append.go b/common/collections/append.go
new file mode 100644
index 000000000..8f1e21ea3
--- /dev/null
+++ b/common/collections/append.go
@@ -0,0 +1,152 @@
+// Copyright 2019 The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package collections
+
+import (
+ "fmt"
+ "reflect"
+)
+
+// Append appends from to a slice to and returns the resulting slice.
+// If length of from is one and the only element is a slice of same type as to,
+// it will be appended.
+func Append(to any, from ...any) (any, error) {
+ if len(from) == 0 {
+ return to, nil
+ }
+ tov, toIsNil := indirect(reflect.ValueOf(to))
+
+ toIsNil = toIsNil || to == nil
+ var tot reflect.Type
+
+ if !toIsNil {
+ if tov.Kind() == reflect.Slice {
+ // Create a copy of tov, so we don't modify the original.
+ c := reflect.MakeSlice(tov.Type(), tov.Len(), tov.Len()+len(from))
+ reflect.Copy(c, tov)
+ tov = c
+ }
+
+ if tov.Kind() != reflect.Slice {
+ return nil, fmt.Errorf("expected a slice, got %T", to)
+ }
+
+ tot = tov.Type().Elem()
+ if tot.Kind() == reflect.Slice {
+ totvt := tot.Elem()
+ fromvs := make([]reflect.Value, len(from))
+ for i, f := range from {
+ fromv := reflect.ValueOf(f)
+ fromt := fromv.Type()
+ if fromt.Kind() == reflect.Slice {
+ fromt = fromt.Elem()
+ }
+ if totvt != fromt {
+ return nil, fmt.Errorf("cannot append slice of %s to slice of %s", fromt, totvt)
+ } else {
+ fromvs[i] = fromv
+ }
+ }
+ return reflect.Append(tov, fromvs...).Interface(), nil
+
+ }
+
+ toIsNil = tov.Len() == 0
+
+ if len(from) == 1 {
+ fromv := reflect.ValueOf(from[0])
+ if !fromv.IsValid() {
+ // from[0] is nil
+ return appendToInterfaceSliceFromValues(tov, fromv)
+ }
+ fromt := fromv.Type()
+ if fromt.Kind() == reflect.Slice {
+ fromt = fromt.Elem()
+ }
+ if fromv.Kind() == reflect.Slice {
+ if toIsNil {
+ // If we get nil []string, we just return the []string
+ return from[0], nil
+ }
+
+ // If we get []string []string, we append the from slice to to
+ if tot == fromt {
+ return reflect.AppendSlice(tov, fromv).Interface(), nil
+ } else if !fromt.AssignableTo(tot) {
+ // Fall back to a []interface{} slice.
+ return appendToInterfaceSliceFromValues(tov, fromv)
+ }
+
+ }
+ }
+ }
+
+ if toIsNil {
+ return Slice(from...), nil
+ }
+
+ for _, f := range from {
+ fv := reflect.ValueOf(f)
+ if !fv.IsValid() || !fv.Type().AssignableTo(tot) {
+ // Fall back to a []interface{} slice.
+ tov, _ := indirect(reflect.ValueOf(to))
+ return appendToInterfaceSlice(tov, from...)
+ }
+ tov = reflect.Append(tov, fv)
+ }
+
+ return tov.Interface(), nil
+}
+
+func appendToInterfaceSliceFromValues(slice1, slice2 reflect.Value) ([]any, error) {
+ var tos []any
+
+ for _, slice := range []reflect.Value{slice1, slice2} {
+ if !slice.IsValid() {
+ tos = append(tos, nil)
+ continue
+ }
+ for i := 0; i < slice.Len(); i++ {
+ tos = append(tos, slice.Index(i).Interface())
+ }
+ }
+
+ return tos, nil
+}
+
+func appendToInterfaceSlice(tov reflect.Value, from ...any) ([]any, error) {
+ var tos []any
+
+ for i := 0; i < tov.Len(); i++ {
+ tos = append(tos, tov.Index(i).Interface())
+ }
+
+ tos = append(tos, from...)
+
+ return tos, nil
+}
+
+// indirect is borrowed from the Go stdlib: 'text/template/exec.go'
+// TODO(bep) consolidate
+func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
+ for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
+ if v.IsNil() {
+ return v, true
+ }
+ if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
+ break
+ }
+ }
+ return v, false
+}
diff --git a/common/collections/append_test.go b/common/collections/append_test.go
new file mode 100644
index 000000000..f791b731a
--- /dev/null
+++ b/common/collections/append_test.go
@@ -0,0 +1,148 @@
+// Copyright 2018 The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package collections
+
+import (
+ "html/template"
+ "testing"
+
+ qt "github.com/frankban/quicktest"
+)
+
+func TestAppend(t *testing.T) {
+ t.Parallel()
+ c := qt.New(t)
+
+ for i, test := range []struct {
+ start any
+ addend []any
+ expected any
+ }{
+ {[]string{"a", "b"}, []any{"c"}, []string{"a", "b", "c"}},
+ {[]string{"a", "b"}, []any{"c", "d", "e"}, []string{"a", "b", "c", "d", "e"}},
+ {[]string{"a", "b"}, []any{[]string{"c", "d", "e"}}, []string{"a", "b", "c", "d", "e"}},
+ {[]string{"a"}, []any{"b", template.HTML("c")}, []any{"a", "b", template.HTML("c")}},
+ {nil, []any{"a", "b"}, []string{"a", "b"}},
+ {nil, []any{nil}, []any{nil}},
+ {[]any{}, []any{[]string{"c", "d", "e"}}, []string{"c", "d", "e"}},
+ {
+ tstSlicers{&tstSlicer{"a"}, &tstSlicer{"b"}},
+ []any{&tstSlicer{"c"}},
+ tstSlicers{&tstSlicer{"a"}, &tstSlicer{"b"}, &tstSlicer{"c"}},
+ },
+ {
+ &tstSlicers{&tstSlicer{"a"}, &tstSlicer{"b"}},
+ []any{&tstSlicer{"c"}},
+ tstSlicers{
+ &tstSlicer{"a"},
+ &tstSlicer{"b"},
+ &tstSlicer{"c"},
+ },
+ },
+ {
+ testSlicerInterfaces{&tstSlicerIn1{"a"}, &tstSlicerIn1{"b"}},
+ []any{&tstSlicerIn1{"c"}},
+ testSlicerInterfaces{&tstSlicerIn1{"a"}, &tstSlicerIn1{"b"}, &tstSlicerIn1{"c"}},
+ },
+ // https://github.com/gohugoio/hugo/issues/5361
+ {
+ []string{"a", "b"},
+ []any{tstSlicers{&tstSlicer{"a"}, &tstSlicer{"b"}}},
+ []any{"a", "b", &tstSlicer{"a"}, &tstSlicer{"b"}},