remarshal.go - hugo - [fork] hugo port for 9front
HTML git clone https://git.drkhsh.at/hugo.git
DIR Log
DIR Files
DIR Refs
DIR Submodules
DIR README
DIR LICENSE
---
remarshal.go (2089B)
---
1 package transform
2
3 import (
4 "bytes"
5 "errors"
6 "strings"
7
8 "github.com/gohugoio/hugo/parser"
9 "github.com/gohugoio/hugo/parser/metadecoders"
10 "github.com/spf13/cast"
11 )
12
13 // Remarshal is used in the Hugo documentation to convert configuration
14 // examples from YAML to JSON, TOML (and possibly the other way around).
15 // The is primarily a helper for the Hugo docs site.
16 // It is not a general purpose YAML to TOML converter etc., and may
17 // change without notice if it serves a purpose in the docs.
18 // Format is one of json, yaml or toml.
19 func (ns *Namespace) Remarshal(format string, data any) (string, error) {
20 var meta map[string]any
21
22 format = strings.TrimSpace(strings.ToLower(format))
23
24 mark, err := toFormatMark(format)
25 if err != nil {
26 return "", err
27 }
28
29 if m, ok := data.(map[string]any); ok {
30 meta = m
31 } else {
32 from, err := cast.ToStringE(data)
33 if err != nil {
34 return "", err
35 }
36
37 from = strings.TrimSpace(from)
38 if from == "" {
39 return "", nil
40 }
41
42 fromFormat := metadecoders.Default.FormatFromContentString(from)
43 if fromFormat == "" {
44 return "", errors.New("failed to detect format from content")
45 }
46
47 meta, err = metadecoders.Default.UnmarshalToMap([]byte(from), fromFormat)
48 if err != nil {
49 return "", err
50 }
51 }
52
53 // Make it so 1.0 float64 prints as 1 etc.
54 applyMarshalTypes(meta)
55
56 var result bytes.Buffer
57 if err := parser.InterfaceToConfig(meta, mark, &result); err != nil {
58 return "", err
59 }
60
61 return result.String(), nil
62 }
63
64 // The unmarshal/marshal dance is extremely type lossy, and we need
65 // to make sure that integer types prints as "43" and not "43.0" in
66 // all formats, hence this hack.
67 func applyMarshalTypes(m map[string]any) {
68 for k, v := range m {
69 switch t := v.(type) {
70 case map[string]any:
71 applyMarshalTypes(t)
72 case float64:
73 i := int64(t)
74 if t == float64(i) {
75 m[k] = i
76 }
77 }
78 }
79 }
80
81 func toFormatMark(format string) (metadecoders.Format, error) {
82 if f := metadecoders.FormatFromString(format); f != "" {
83 return f, nil
84 }
85
86 return "", errors.New("failed to detect target data serialization format")
87 }