summaryrefslogtreecommitdiffstats
path: root/parser/metadecoders/format.go
blob: 719fbf100a8d327daf8f1e03193e08e297b6c144 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// 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 metadecoders

import (
	"path/filepath"
	"strings"

	"github.com/gohugoio/hugo/media"

	"github.com/gohugoio/hugo/parser/pageparser"
)

type Format string

const (
	// These are the supported metdata  formats in Hugo. Most of these are also
	// supported as /data formats.
	ORG  Format = "org"
	JSON Format = "json"
	TOML Format = "toml"
	YAML Format = "yaml"
	CSV  Format = "csv"
)

// FormatFromString turns formatStr, typically a file extension without any ".",
// into a Format. It returns an empty string for unknown formats.
func FormatFromString(formatStr string) Format {
	formatStr = strings.ToLower(formatStr)
	if strings.Contains(formatStr, ".") {
		// Assume a filename
		formatStr = strings.TrimPrefix(filepath.Ext(formatStr), ".")

	}
	switch formatStr {
	case "yaml", "yml":
		return YAML
	case "json":
		return JSON
	case "toml":
		return TOML
	case "org":
		return ORG
	case "csv":
		return CSV
	}

	return ""

}

// FormatFromMediaType gets the Format given a MIME type, empty string
// if unknown.
func FormatFromMediaType(m media.Type) Format {
	for _, suffix := range m.Suffixes {
		if f := FormatFromString(suffix); f != "" {
			return f
		}
	}

	return ""
}

// FormatFromFrontMatterType will return empty if not supported.
func FormatFromFrontMatterType(typ pageparser.ItemType) Format {
	switch typ {
	case pageparser.TypeFrontMatterJSON:
		return JSON
	case pageparser.TypeFrontMatterORG:
		return ORG
	case pageparser.TypeFrontMatterTOML:
		return TOML
	case pageparser.TypeFrontMatterYAML:
		return YAML
	default:
		return ""
	}
}

// FormatFromContentString tries to detect the format (JSON, YAML or TOML)
// in the given string.
// It return an empty string if no format could be detected.
func (d Decoder) FormatFromContentString(data string) Format {
	csvIdx := strings.IndexRune(data, d.Comma)
	jsonIdx := strings.Index(data, "{")
	yamlIdx := strings.Index(data, ":")
	tomlIdx := strings.Index(data, "=")

	if isLowerIndexThan(csvIdx, jsonIdx, yamlIdx, tomlIdx) {
		return CSV
	}

	if isLowerIndexThan(jsonIdx, yamlIdx, tomlIdx) {
		return JSON
	}

	if isLowerIndexThan(yamlIdx, tomlIdx) {
		return YAML
	}

	if tomlIdx != -1 {
		return TOML
	}

	return ""
}

func isLowerIndexThan(first int, others ...int) bool {
	if first == -1 {
		return false
	}
	for _, other := range others {
		if other != -1 && other < first {
			return false
		}
	}

	return true
}