mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-08 19:36:36 +02:00
transform: Add support for "format" option in transform.Unmarshal
Fixes #13887
This commit is contained in:
@@ -36,6 +36,10 @@ import (
|
|||||||
|
|
||||||
// Decoder provides some configuration options for the decoders.
|
// Decoder provides some configuration options for the decoders.
|
||||||
type Decoder struct {
|
type Decoder struct {
|
||||||
|
// Format specifies a specific format to decode from. If empty or
|
||||||
|
// unspecified, it's inferred from the contents or the filename.
|
||||||
|
Format string
|
||||||
|
|
||||||
// Delimiter is the field delimiter. Used in the CSV decoder. Default is
|
// Delimiter is the field delimiter. Used in the CSV decoder. Default is
|
||||||
// ','.
|
// ','.
|
||||||
Delimiter rune
|
Delimiter rune
|
||||||
@@ -57,6 +61,7 @@ type Decoder struct {
|
|||||||
// OptionsKey is used in cache keys.
|
// OptionsKey is used in cache keys.
|
||||||
func (d Decoder) OptionsKey() string {
|
func (d Decoder) OptionsKey() string {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
|
sb.WriteString(d.Format)
|
||||||
sb.WriteRune(d.Delimiter)
|
sb.WriteRune(d.Delimiter)
|
||||||
sb.WriteRune(d.Comment)
|
sb.WriteRune(d.Comment)
|
||||||
sb.WriteString(strconv.FormatBool(d.LazyQuotes))
|
sb.WriteString(strconv.FormatBool(d.LazyQuotes))
|
||||||
|
@@ -72,9 +72,17 @@ func (ns *Namespace) Unmarshal(args ...any) (any, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v, err := ns.cacheUnmarshal.GetOrCreate(key, func(string) (*resources.StaleValue[any], error) {
|
v, err := ns.cacheUnmarshal.GetOrCreate(key, func(string) (*resources.StaleValue[any], error) {
|
||||||
f := metadecoders.FormatFromStrings(r.MediaType().Suffixes()...)
|
var f metadecoders.Format
|
||||||
if f == "" {
|
if decoder.Format != "" {
|
||||||
return nil, fmt.Errorf("MIME %q not supported", r.MediaType())
|
f = metadecoders.FormatFromString(decoder.Format)
|
||||||
|
if f == "" {
|
||||||
|
return nil, fmt.Errorf("format %q not supported", decoder.Format)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f = metadecoders.FormatFromStrings(r.MediaType().Suffixes()...)
|
||||||
|
if f == "" {
|
||||||
|
return nil, fmt.Errorf("MIME %q not supported", r.MediaType())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reader, err := r.ReadSeekCloser()
|
reader, err := r.ReadSeekCloser()
|
||||||
@@ -119,10 +127,22 @@ func (ns *Namespace) Unmarshal(args ...any) (any, error) {
|
|||||||
|
|
||||||
key := hashing.MD5FromStringHexEncoded(dataStr)
|
key := hashing.MD5FromStringHexEncoded(dataStr)
|
||||||
|
|
||||||
|
if decoder != metadecoders.Default {
|
||||||
|
key += decoder.OptionsKey()
|
||||||
|
}
|
||||||
|
|
||||||
v, err := ns.cacheUnmarshal.GetOrCreate(key, func(string) (*resources.StaleValue[any], error) {
|
v, err := ns.cacheUnmarshal.GetOrCreate(key, func(string) (*resources.StaleValue[any], error) {
|
||||||
f := decoder.FormatFromContentString(dataStr)
|
var f metadecoders.Format
|
||||||
if f == "" {
|
if decoder.Format != "" {
|
||||||
return nil, errors.New("unknown format")
|
f = metadecoders.FormatFromString(decoder.Format)
|
||||||
|
if f == "" {
|
||||||
|
return nil, fmt.Errorf("format %q not supported", decoder.Format)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f = decoder.FormatFromContentString(dataStr)
|
||||||
|
if f == "" {
|
||||||
|
return nil, errors.New("unknown format")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := decoder.Unmarshal([]byte(dataStr), f)
|
v, err := decoder.Unmarshal([]byte(dataStr), f)
|
||||||
|
@@ -128,6 +128,9 @@ func TestUnmarshal(t *testing.T) {
|
|||||||
{testContentResource{key: "r1", content: `a;b;c`, mime: media.Builtin.CSVType}, map[string]any{"delimiter": ";"}, func(r [][]string) {
|
{testContentResource{key: "r1", content: `a;b;c`, mime: media.Builtin.CSVType}, map[string]any{"delimiter": ";"}, func(r [][]string) {
|
||||||
b.Assert([][]string{{"a", "b", "c"}}, qt.DeepEquals, r)
|
b.Assert([][]string{{"a", "b", "c"}}, qt.DeepEquals, r)
|
||||||
}},
|
}},
|
||||||
|
{testContentResource{key: "r1", content: `{p: [a, b]}`, mime: media.Builtin.JSONType}, map[string]any{"format": "yaml"}, func(m map[string]any) {
|
||||||
|
b.Assert(m, qt.DeepEquals, map[string]any{"p": []any{"a", "b"}})
|
||||||
|
}},
|
||||||
{"a,b,c", nil, func(r [][]string) {
|
{"a,b,c", nil, func(r [][]string) {
|
||||||
b.Assert([][]string{{"a", "b", "c"}}, qt.DeepEquals, r)
|
b.Assert([][]string{{"a", "b", "c"}}, qt.DeepEquals, r)
|
||||||
}},
|
}},
|
||||||
@@ -141,6 +144,9 @@ a;b;c`, mime: media.Builtin.CSVType}, map[string]any{"DElimiter": ";", "Comment"
|
|||||||
}},
|
}},
|
||||||
{``, nil, nil},
|
{``, nil, nil},
|
||||||
{` `, nil, nil},
|
{` `, nil, nil},
|
||||||
|
{`{p: [a, b]}`, map[string]any{"format": "yaml"}, func(m map[string]any) {
|
||||||
|
b.Assert(m, qt.DeepEquals, map[string]any{"p": []any{"a", "b"}})
|
||||||
|
}},
|
||||||
// errors
|
// errors
|
||||||
{"thisisnotavaliddataformat", nil, false},
|
{"thisisnotavaliddataformat", nil, false},
|
||||||
{testContentResource{key: "r1", content: `invalid&toml"`, mime: media.Builtin.TOMLType}, nil, false},
|
{testContentResource{key: "r1", content: `invalid&toml"`, mime: media.Builtin.TOMLType}, nil, false},
|
||||||
@@ -148,6 +154,8 @@ a;b;c`, mime: media.Builtin.CSVType}, map[string]any{"DElimiter": ";", "Comment"
|
|||||||
{"thisisnotavaliddataformat", nil, false},
|
{"thisisnotavaliddataformat", nil, false},
|
||||||
{`{ notjson }`, nil, false},
|
{`{ notjson }`, nil, false},
|
||||||
{tstNoStringer{}, nil, false},
|
{tstNoStringer{}, nil, false},
|
||||||
|
{"<root><a>notjson</a></root>", map[string]any{"format": "json"}, false},
|
||||||
|
{"anything", map[string]any{"format": "invalidformat"}, false},
|
||||||
} {
|
} {
|
||||||
|
|
||||||
ns.Reset()
|
ns.Reset()
|
||||||
|
Reference in New Issue
Block a user