summaryrefslogtreecommitdiffstats
path: root/media/mediaType.go
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2017-04-03 22:39:37 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2017-04-04 15:12:30 +0200
commitf8d555cca59a48df9cde2e7323ff2d500e0590a3 (patch)
treed11b02e24b1c75ad48deaf9e016a66298222d4c7 /media/mediaType.go
parentc9aee467d387c4c3489c23f120a7ef2fed4d12df (diff)
media: Add DecodeTypes
And clean up the media package.
Diffstat (limited to 'media/mediaType.go')
-rw-r--r--media/mediaType.go132
1 files changed, 121 insertions, 11 deletions
diff --git a/media/mediaType.go b/media/mediaType.go
index b56904cd9..bc54986be 100644
--- a/media/mediaType.go
+++ b/media/mediaType.go
@@ -15,19 +15,11 @@ package media
import (
"fmt"
+ "sort"
"strings"
-)
-
-type Types []Type
-func (t Types) GetByType(tp string) (Type, bool) {
- for _, tt := range t {
- if strings.EqualFold(tt.Type(), tp) {
- return tt, true
- }
- }
- return Type{}, false
-}
+ "github.com/mitchellh/mapstructure"
+)
// A media type (also known as MIME type and content type) is a two-part identifier for
// file formats and format contents transmitted on the Internet.
@@ -41,6 +33,29 @@ type Type struct {
Suffix string // i.e html
}
+// FromTypeString creates a new Type given a type sring on the form MainType/SubType and
+// an optional suffix, e.g. "text/html" or "text/html+html".
+func FromString(t string) (Type, error) {
+ t = strings.ToLower(t)
+ parts := strings.Split(t, "/")
+ if len(parts) != 2 {
+ return Type{}, fmt.Errorf("cannot parse %q as a media type", t)
+ }
+ mainType := parts[0]
+ subParts := strings.Split(parts[1], "+")
+
+ subType := subParts[0]
+ var suffix string
+
+ if len(subParts) == 1 {
+ suffix = subType
+ } else {
+ suffix = subParts[1]
+ }
+
+ return Type{MainType: mainType, SubType: subType, Suffix: suffix}, nil
+}
+
// Type returns a string representing the main- and sub-type of a media type, i.e. "text/css".
// Hugo will register a set of default media types.
// These can be overridden by the user in the configuration,
@@ -68,4 +83,99 @@ var (
TextType = Type{"text", "plain", "txt"}
)
+var DefaultTypes = Types{
+ CalendarType,
+ CSSType,
+ CSVType,
+ HTMLType,
+ JavascriptType,
+ JSONType,
+ RSSType,
+ XMLType,
+ TextType,
+}
+
+func init() {
+ sort.Sort(DefaultTypes)
+}
+
+type Types []Type
+
+func (t Types) Len() int { return len(t) }
+func (t Types) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
+func (t Types) Less(i, j int) bool { return t[i].Type() < t[j].Type() }
+
+func (t Types) GetByType(tp string) (Type, bool) {
+ for _, tt := range t {
+ if strings.EqualFold(tt.Type(), tp) {
+ return tt, true
+ }
+ }
+ return Type{}, false
+}
+
+// GetBySuffix gets a media type given as suffix, e.g. "html".
+// It will return false if no format could be found, or if the suffix given
+// is ambiguous.
+// The lookup is case insensitive.
+func (t Types) GetBySuffix(suffix string) (tp Type, found bool) {
+ for _, tt := range t {
+ if strings.EqualFold(suffix, tt.Suffix) {
+ if found {
+ // ambiguous
+ found = false
+ return
+ }
+ tp = tt
+ found = true
+ }
+ }
+ return
+}
+
+// DecodeTypes takes a list of media type configurations and merges those,
+// in ther order given, with the Hugo defaults as the last resort.
+func DecodeTypes(maps ...map[string]interface{}) (Types, error) {
+ m := make(Types, len(DefaultTypes))
+ copy(m, DefaultTypes)
+
+ for _, mm := range maps {
+ for k, v := range mm {
+ // It may be tempting to put the full media type in the key, e.g.
+ // "text/css+css", but that will break the logic below.
+ if strings.Contains(k, "+") {
+ return Types{}, fmt.Errorf("media type keys cannot contain any '+' chars. Valid example is %q", "text/css")
+ }
+
+ found := false
+ for i, vv := range m {
+ // Match by type, i.e. "text/css"
+ if strings.EqualFold(k, vv.Type()) {
+ // Merge it with the existing
+ if err := mapstructure.WeakDecode(v, &m[i]); err != nil {
+ return m, err
+ }
+ found = true
+ }
+ }
+ if !found {
+ mediaType, err := FromString(k)
+ if err != nil {
+ return m, err
+ }
+
+ if err := mapstructure.WeakDecode(v, &mediaType); err != nil {
+ return m, err
+ }
+
+ m = append(m, mediaType)
+ }
+ }
+ }
+
+ sort.Sort(m)
+
+ return m, nil
+}
+
// TODO(bep) output mime.AddExtensionType