format.go (2756B)
1 // Copyright 2018 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package metadecoders
15
16 import (
17 "path/filepath"
18 "strings"
19
20 "github.com/gohugoio/hugo/media"
21 )
22
23 type Format string
24
25 const (
26 // These are the supported metdata formats in Hugo. Most of these are also
27 // supported as /data formats.
28 ORG Format = "org"
29 JSON Format = "json"
30 TOML Format = "toml"
31 YAML Format = "yaml"
32 CSV Format = "csv"
33 XML Format = "xml"
34 )
35
36 // FormatFromString turns formatStr, typically a file extension without any ".",
37 // into a Format. It returns an empty string for unknown formats.
38 func FormatFromString(formatStr string) Format {
39 formatStr = strings.ToLower(formatStr)
40 if strings.Contains(formatStr, ".") {
41 // Assume a filename
42 formatStr = strings.TrimPrefix(filepath.Ext(formatStr), ".")
43 }
44 switch formatStr {
45 case "yaml", "yml":
46 return YAML
47 case "json":
48 return JSON
49 case "toml":
50 return TOML
51 case "org":
52 return ORG
53 case "csv":
54 return CSV
55 case "xml":
56 return XML
57 }
58
59 return ""
60 }
61
62 // FormatFromMediaType gets the Format given a MIME type, empty string
63 // if unknown.
64 func FormatFromMediaType(m media.Type) Format {
65 for _, suffix := range m.Suffixes() {
66 if f := FormatFromString(suffix); f != "" {
67 return f
68 }
69 }
70
71 return ""
72 }
73
74 // FormatFromContentString tries to detect the format (JSON, YAML, TOML or XML)
75 // in the given string.
76 // It return an empty string if no format could be detected.
77 func (d Decoder) FormatFromContentString(data string) Format {
78 csvIdx := strings.IndexRune(data, d.Delimiter)
79 jsonIdx := strings.Index(data, "{")
80 yamlIdx := strings.Index(data, ":")
81 xmlIdx := strings.Index(data, "<")
82 tomlIdx := strings.Index(data, "=")
83
84 if isLowerIndexThan(csvIdx, jsonIdx, yamlIdx, xmlIdx, tomlIdx) {
85 return CSV
86 }
87
88 if isLowerIndexThan(jsonIdx, yamlIdx, xmlIdx, tomlIdx) {
89 return JSON
90 }
91
92 if isLowerIndexThan(yamlIdx, xmlIdx, tomlIdx) {
93 return YAML
94 }
95
96 if isLowerIndexThan(xmlIdx, tomlIdx) {
97 return XML
98 }
99
100 if tomlIdx != -1 {
101 return TOML
102 }
103
104 return ""
105 }
106
107 func isLowerIndexThan(first int, others ...int) bool {
108 if first == -1 {
109 return false
110 }
111 for _, other := range others {
112 if other != -1 && other < first {
113 return false
114 }
115 }
116
117 return true
118 }