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 }