summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/mediaType.go198
-rw-r--r--media/mediaType_test.go98
2 files changed, 178 insertions, 118 deletions
diff --git a/media/mediaType.go b/media/mediaType.go
index 9e35212b2..a35d80e3e 100644
--- a/media/mediaType.go
+++ b/media/mediaType.go
@@ -20,6 +20,8 @@ import (
"sort"
"strings"
+ "github.com/spf13/cast"
+
"github.com/gohugoio/hugo/common/maps"
"github.com/mitchellh/mapstructure"
@@ -36,28 +38,37 @@ const (
// If suffix is not provided, the sub type will be used.
// See // https://en.wikipedia.org/wiki/Media_type
type Type struct {
- MainType string `json:"mainType"` // i.e. text
- SubType string `json:"subType"` // i.e. html
+ MainType string `json:"mainType"` // i.e. text
+ SubType string `json:"subType"` // i.e. html
+ Delimiter string `json:"delimiter"` // e.g. "."
+
+ // FirstSuffix holds the first suffix defined for this Type.
+ FirstSuffix SuffixInfo `json:"firstSuffix"`
// This is the optional suffix after the "+" in the MIME type,
// e.g. "xml" in "application/rss+xml".
mimeSuffix string
- Delimiter string `json:"delimiter"` // e.g. "."
-
- Suffixes []string `json:"suffixes"`
+ // E.g. "jpg,jpeg"
+ // Stored as a string to make Type comparable.
+ suffixesCSV string
+}
- // Set when doing lookup by suffix.
- fileSuffix string
+// SuffixInfo holds information about a Type's suffix.
+type SuffixInfo struct {
+ Suffix string `json:"suffix"`
+ FullSuffix string `json:"fullSuffix"`
}
-// FromStringAndExt is same as FromString, but adds the file extension to the type.
+// FromStringAndExt creates a Type from a MIME string and a given extension.
func FromStringAndExt(t, ext string) (Type, error) {
tp, err := fromString(t)
if err != nil {
return tp, err
}
- tp.Suffixes = []string{strings.TrimPrefix(ext, ".")}
+ tp.suffixesCSV = strings.TrimPrefix(ext, ".")
+ tp.Delimiter = defaultDelimiter
+ tp.init()
return tp, nil
}
@@ -102,61 +113,83 @@ func (m Type) String() string {
return m.Type()
}
-// FullSuffix returns the file suffix with any delimiter prepended.
-func (m Type) FullSuffix() string {
- return m.Delimiter + m.Suffix()
+// Suffixes returns all valid file suffixes for this type.
+func (m Type) Suffixes() []string {
+ if m.suffixesCSV == "" {
+ return nil
+ }
+
+ return strings.Split(m.suffixesCSV, ",")
}
-// Suffix returns the file suffix without any delimiter prepended.
-func (m Type) Suffix() string {
- if m.fileSuffix != "" {
- return m.fileSuffix
- }
- if len(m.Suffixes) > 0 {
- return m.Suffixes[0]
+func (m *Type) init() {
+ m.FirstSuffix.FullSuffix = ""
+ m.FirstSuffix.Suffix = ""
+ if suffixes := m.Suffixes(); suffixes != nil {
+ m.FirstSuffix.Suffix = suffixes[0]
+ m.FirstSuffix.FullSuffix = m.Delimiter + m.FirstSuffix.Suffix
}
- // There are MIME types without file suffixes.
- return ""
+}
+
+// WithDelimiterAndSuffixes is used in tests.
+func WithDelimiterAndSuffixes(t Type, delimiter, suffixesCSV string) Type {
+ t.Delimiter = delimiter
+ t.suffixesCSV = suffixesCSV
+ t.init()
+ return t
+}
+
+func newMediaType(main, sub string, suffixes []string) Type {
+ t := Type{MainType: main, SubType: sub, suffixesCSV: strings.Join(suffixes, ","), Delimiter: defaultDelimiter}
+ t.init()
+ return t
+}
+
+func newMediaTypeWithMimeSuffix(main, sub, mimeSuffix string, suffixes []string) Type {
+ mt := newMediaType(main, sub, suffixes)
+ mt.mimeSuffix = mimeSuffix
+ mt.init()
+ return mt
}
// Definitions from https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types etc.
// Note that from Hugo 0.44 we only set Suffix if it is part of the MIME type.
var (
- CalendarType = Type{MainType: "text", SubType: "calendar", Suffixes: []string{"ics"}, Delimiter: defaultDelimiter}
- CSSType = Type{MainType: "text", SubType: "css", Suffixes: []string{"css"}, Delimiter: defaultDelimiter}
- SCSSType = Type{MainType: "text", SubType: "x-scss", Suffixes: []string{"scss"}, Delimiter: defaultDelimiter}
- SASSType = Type{MainType: "text", SubType: "x-sass", Suffixes: []string{"sass"}, Delimiter: defaultDelimiter}
- CSVType = Type{MainType: "text", SubType: "csv", Suffixes: []string{"csv"}, Delimiter: defaultDelimiter}
- HTMLType = Type{MainType: "text", SubType: "html", Suffixes: []string{"html"}, Delimiter: defaultDelimiter}
- JavascriptType = Type{MainType: "application", SubType: "javascript", Suffixes: []string{"js"}, Delimiter: defaultDelimiter}
- TypeScriptType = Type{MainType: "application", SubType: "typescript", Suffixes: []string{"ts"}, Delimiter: defaultDelimiter}
- TSXType = Type{MainType: "text", SubType: "tsx", Suffixes: []string{"tsx"}, Delimiter: defaultDelimiter}
- JSXType = Type{MainType: "text", SubType: "jsx", Suffixes: []string{"jsx"}, Delimiter: defaultDelimiter}
-
- JSONType = Type{MainType: "application", SubType: "json", Suffixes: []string{"json"}, Delimiter: defaultDelimiter}
- RSSType = Type{MainType: "application", SubType: "rss", mimeSuffix: "xml", Suffixes: []string{"xml"}, Delimiter: defaultDelimiter}
- XMLType = Type{MainType: "application", SubType: "xml", Suffixes: []string{"xml"}, Delimiter: defaultDelimiter}
- SVGType = Type{MainType: "image", SubType: "svg", mimeSuffix: "xml", Suffixes: []string{"svg"}, Delimiter: defaultDelimiter}
- TextType = Type{MainType: "text", SubType: "plain", Suffixes: []string{"txt"}, Delimiter: defaultDelimiter}
- TOMLType = Type{MainType: "application", SubType: "toml", Suffixes: []string{"toml"}, Delimiter: defaultDelimiter}
- YAMLType = Type{MainType: "application", SubType: "yaml", Suffixes: []string{"yaml", "yml"}, Delimiter: defaultDelimiter}
+ CalendarType = newMediaType("text", "calendar", []string{"ics"})
+ CSSType = newMediaType("text", "css", []string{"css"})
+ SCSSType = newMediaType("text", "x-scss", []string{"scss"})
+ SASSType = newMediaType("text", "x-sass", []string{"sass"})
+ CSVType = newMediaType("text", "csv", []string{"csv"})
+ HTMLType = newMediaType("text", "html", []string{"html"})
+ JavascriptType = newMediaType("application", "javascript", []string{"js"})
+ TypeScriptType = newMediaType("application", "typescript", []string{"ts"})
+ TSXType = newMediaType("text", "tsx", []string{"tsx"})
+ JSXType = newMediaType("text", "jsx", []string{"jsx"})
+
+ JSONType = newMediaType("application", "json", []string{"json"})
+ RSSType = newMediaTypeWithMimeSuffix("application", "rss", "xml", []string{"xml"})
+ XMLType = newMediaType("application", "xml", []string{"xml"})
+ SVGType = newMediaTypeWithMimeSuffix("image", "svg", "xml", []string{"svg"})
+ TextType = newMediaType("text", "plain", []string{"txt"})
+ TOMLType = newMediaType("application", "toml", []string{"toml"})
+ YAMLType = newMediaType("application", "yaml", []string{"yaml", "yml"})
// Common image types
- PNGType = Type{MainType: "image", SubType: "png", Suffixes: []string{"png"}, Delimiter: defaultDelimiter}
- JPEGType = Type{MainType: "image", SubType: "jpeg", Suffixes: []string{"jpg", "jpeg"}, Delimiter: defaultDelimiter}
- GIFType = Type{MainType: "image", SubType: "gif", Suffixes: []string{"gif"}, Delimiter: defaultDelimiter}
- TIFFType = Type{MainType: "image", SubType: "tiff", Suffixes: []string{"tif", "tiff"}, Delimiter: defaultDelimiter}
- BMPType = Type{MainType: "image", SubType: "bmp", Suffixes: []string{"bmp"}, Delimiter: defaultDelimiter}
+ PNGType = newMediaType("image", "png", []string{"png"})
+ JPEGType = newMediaType("image", "jpeg", []string{"jpg", "jpeg"})
+ GIFType = newMediaType("image", "gif", []string{"gif"})
+ TIFFType = newMediaType("image", "tiff", []string{"tif", "tiff"})
+ BMPType = newMediaType("image", "bmp", []string{"bmp"})
// Common video types
- AVIType = Type{MainType: "video", SubType: "x-msvideo", Suffixes: []string{"avi"}, Delimiter: defaultDelimiter}
- MPEGType = Type{MainType: "video", SubType: "mpeg", Suffixes: []string{"mpg", "mpeg"}, Delimiter: defaultDelimiter}
- MP4Type = Type{MainType: "video", SubType: "mp4", Suffixes: []string{"mp4"}, Delimiter: defaultDelimiter}
- OGGType = Type{MainType: "video", SubType: "ogg", Suffixes: []string{"ogv"}, Delimiter: defaultDelimiter}
- WEBMType = Type{MainType: "video", SubType: "webm", Suffixes: []string{"webm"}, Delimiter: defaultDelimiter}
- GPPType = Type{MainType: "video", SubType: "3gpp", Suffixes: []string{"3gpp", "3gp"}, Delimiter: defaultDelimiter}
-
- OctetType = Type{MainType: "application", SubType: "octet-stream"}
+ AVIType = newMediaType("video", "x-msvideo", []string{"avi"})
+ MPEGType = newMediaType("video", "mpeg", []string{"mpg", "mpeg"})
+ MP4Type = newMediaType("video", "mp4", []string{"mp4"})
+ OGGType = newMediaType("video", "ogg", []string{"ogv"})
+ WEBMType = newMediaType("video", "webm", []string{"webm"})
+ GPPType = newMediaType("video", "3gpp", []string{"3gpp", "3gp"})
+
+ OctetType = newMediaType("application", "octet-stream", nil)
)
// DefaultTypes is the default media types supported by Hugo.
@@ -221,54 +254,56 @@ func (t Types) GetByType(tp string) (Type, bool) {
// BySuffix will return all media types matching a suffix.
func (t Types) BySuffix(suffix string) []Type {
+ suffix = strings.ToLower(suffix)
var types []Type
for _, tt := range t {
- if match := tt.matchSuffix(suffix); match != "" {
+ if tt.hasSuffix(suffix) {
types = append(types, tt)
}
}
return types
}
-// GetFirstBySuffix will return the first media type matching the given suffix.
-func (t Types) GetFirstBySuffix(suffix string) (Type, bool) {
+// GetFirstBySuffix will return the first type matching the given suffix.
+func (t Types) GetFirstBySuffix(suffix string) (Type, SuffixInfo, bool) {
+ suffix = strings.ToLower(suffix)
for _, tt := range t {
- if match := tt.matchSuffix(suffix); match != "" {
- tt.fileSuffix = match
- return tt, true
+ if tt.hasSuffix(suffix) {
+ return tt, SuffixInfo{
+ FullSuffix: tt.Delimiter + suffix,
+ Suffix: suffix,
+ }, true
}
}
- return Type{}, false
+ return Type{}, SuffixInfo{}, 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) {
+func (t Types) GetBySuffix(suffix string) (tp Type, si SuffixInfo, found bool) {
+ suffix = strings.ToLower(suffix)
for _, tt := range t {
- if match := tt.matchSuffix(suffix); match != "" {
+ if tt.hasSuffix(suffix) {
if found {
// ambiguous
found = false
return
}
tp = tt
- tp.fileSuffix = match
+ si = SuffixInfo{
+ FullSuffix: tt.Delimiter + suffix,
+ Suffix: suffix,
+ }
found = true
}
}
return
}
-func (m Type) matchSuffix(suffix string) string {
- for _, s := range m.Suffixes {
- if strings.EqualFold(suffix, s) {
- return s
- }
- }
-
- return ""
+func (m Type) hasSuffix(suffix string) bool {
+ return strings.Contains(m.suffixesCSV, suffix)
}
// GetByMainSubType gets a media type given a main and a sub type e.g. "text" and "plain".
@@ -328,9 +363,6 @@ func DecodeTypes(mms ...map[string]interface{}) (Types, error) {
// Maps type string to Type. Type string is the full application/svg+xml.
mmm := make(map[string]Type)
for _, dt := range DefaultTypes {
- suffixes := make([]string, len(dt.Suffixes))
- copy(suffixes, dt.Suffixes)
- dt.Suffixes = suffixes
mmm[dt.Type()] = dt
}
@@ -360,11 +392,17 @@ func DecodeTypes(mms ...map[string]interface{}) (Types, error) {
return Types{}, suffixIsRemoved()
}
+ if suffixes, found := vm["suffixes"]; found {
+ mediaType.suffixesCSV = strings.TrimSpace(strings.ToLower(strings.Join(cast.ToStringSlice(suffixes), ",")))
+ }
+
// The user may set the delimiter as an empty string.
- if !delimiterSet && len(mediaType.Suffixes) != 0 {
+ if !delimiterSet && mediaType.suffixesCSV != "" {
mediaType.Delimiter = defaultDelimiter
}
+ mediaType.init()
+
mmm[k] = mediaType
}
@@ -387,12 +425,14 @@ func (m Type) IsZero() bool {
func (m Type) MarshalJSON() ([]byte, error) {
type Alias Type
return json.Marshal(&struct {
- Type string `json:"type"`
- String string `json:"string"`
Alias
+ Type string `json:"type"`
+ String string `json:"string"`
+ Suffixes []string `json:"suffixes"`
}{
- Type: m.Type(),
- String: m.String(),
- Alias: (Alias)(m),
+ Alias: (Alias)(m),
+ Type: m.Type(),
+ String: m.String(),
+ Suffixes: strings.Split(m.suffixesCSV, ","),
})
}
diff --git a/media/mediaType_test.go b/media/mediaType_test.go
index a846ac6ad..e44ab27ec 100644
--- a/media/mediaType_test.go
+++ b/media/mediaType_test.go
@@ -14,16 +14,12 @@
package media
import (
+ "encoding/json"
"testing"
qt "github.com/frankban/quicktest"
- "github.com/google/go-cmp/cmp"
)
-var eq = qt.CmpEquals(cmp.Comparer(func(m1, m2 Type) bool {
- return m1.Type() == m2.Type()
-}))
-
func TestDefaultTypes(t *testing.T) {
c := qt.New(t)
for _, test := range []struct {
@@ -53,8 +49,6 @@ func TestDefaultTypes(t *testing.T) {
} {
c.Assert(test.tp.MainType, qt.Equals, test.expectedMainType)
c.Assert(test.tp.SubType, qt.Equals, test.expectedSubType)
- c.Assert(test.tp.Suffix(), qt.Equals, test.expectedSuffix)
- c.Assert(test.tp.Delimiter, qt.Equals, defaultDelimiter)
c.Assert(test.tp.Type(), qt.Equals, test.expectedType)
c.Assert(test.tp.String(), qt.Equals, test.expectedString)
@@ -71,25 +65,25 @@ func TestGetByType(t *testing.T) {
mt, found := types.GetByType("text/HTML")
c.Assert(found, qt.Equals, true)
- c.Assert(HTMLType, eq, mt)
+ c.Assert(HTMLType, qt.Equals, mt)
_, found = types.GetByType("text/nono")
c.Assert(found, qt.Equals, false)
mt, found = types.GetByType("application/rss+xml")
c.Assert(found, qt.Equals, true)
- c.Assert(RSSType, eq, mt)
+ c.Assert(RSSType, qt.Equals, mt)
mt, found = types.GetByType("application/rss")
c.Assert(found, qt.Equals, true)
- c.Assert(RSSType, eq, mt)
+ c.Assert(RSSType, qt.Equals, mt)
}
func TestGetByMainSubType(t *testing.T) {
c := qt.New(t)
f, found := DefaultTypes.GetByMainSubType("text", "plain")
c.Assert(found, qt.Equals, true)
- c.Assert(TextType, eq, f)
+ c.Assert(f, qt.Equals, TextType)
_, found = DefaultTypes.GetByMainSubType("foo", "plain")
c.Assert(found, qt.Equals, false)
}
@@ -104,48 +98,63 @@ func TestBySuffix(t *testing.T) {
func TestGetFirstBySuffix(t *testing.T) {
c := qt.New(t)
- f, found := DefaultTypes.GetFirstBySuffix("xml")
+ _, f, found := DefaultTypes.GetFirstBySuffix("xml")
c.Assert(found, qt.Equals, true)
- c.Assert(f, eq, Type{MainType: "application", SubType: "rss", mimeSuffix: "xml", Delimiter: ".", Suffixes: []string{"xml"}, fileSuffix: "xml"})
+ c.Assert(f, qt.Equals, SuffixInfo{
+ Suffix: "xml",
+ FullSuffix: ".xml"})
}
func TestFromTypeString(t *testing.T) {
c := qt.New(t)
f, err := fromString("text/html")
c.Assert(err, qt.IsNil)
- c.Assert(f.Type(), eq, HTMLType.Type())
+ c.Assert(f.Type(), qt.Equals, HTMLType.Type())
f, err = fromString("application/custom")
c.Assert(err, qt.IsNil)
- c.Assert(f, eq, Type{MainType: "application", SubType: "custom", mimeSuffix: "", fileSuffix: ""})
+ c.Assert(f, qt.Equals, Type{MainType: "application", SubType: "custom", mimeSuffix: ""})
f, err = fromString("application/custom+sfx")
c.Assert(err, qt.IsNil)
- c.Assert(f, eq, Type{MainType: "application", SubType: "custom", mimeSuffix: "sfx"})
+ c.Assert(f, qt.Equals, Type{MainType: "application", SubType: "custom", mimeSuffix: "sfx"})
_, err = fromString("noslash")
c.Assert(err, qt.Not(qt.IsNil))
f, err = fromString("text/xml; charset=utf-8")
c.Assert(err, qt.IsNil)
- c.Assert(f, eq, Type{MainType: "text", SubType: "xml", mimeSuffix: ""})
- c.Assert(f.Suffix(), qt.Equals, "")
+
+ c.Assert(f, qt.Equals, Type{MainType: "text", SubType: "xml", mimeSuffix: ""})
+
+}
+
+func TestFromStringAndExt(t *testing.T) {
+ c := qt.New(t)
+ f, err := FromStringAndExt("text/html", "html")
+ c.Assert(err, qt.IsNil)
+ c.Assert(f, qt.Equals, HTMLType)
+ f, err = FromStringAndExt("text/html", ".html")
+ c.Assert(err, qt.IsNil)
+ c.Assert(f, qt.Equals, HTMLType)
}
// Add a test for the SVG case
// https://github.com/gohugoio/hugo/issues/4920
func TestFromExtensionMultipleSuffixes(t *testing.T) {
c := qt.New(t)
- tp, found := DefaultTypes.GetBySuffix("svg")
+ tp, si, found := DefaultTypes.GetBySuffix("svg")
c.Assert(found, qt.Equals, true)
c.Assert(tp.String(), qt.Equals, "image/svg+xml")
- c.Assert(tp.fileSuffix, qt.Equals, "svg")
- c.Assert(tp.FullSuffix(), qt.Equals, ".svg")
- tp, found = DefaultTypes.GetByType("image/svg+xml")
+ c.Assert(si.Suffix, qt.Equals, "svg")
+ c.Assert(si.FullSuffix, qt.Equals, ".svg")
+ c.Assert(tp.FirstSuffix.Suffix, qt.Equals, si.Suffix)
+ c.Assert(tp.FirstSuffix.FullSuffix, qt.Equals, si.FullSuffix)
+ ftp, found := DefaultTypes.GetByType("image/svg+xml")
c.Assert(found, qt.Equals, true)
- c.Assert(tp.String(), qt.Equals, "image/svg+xml")
+ c.Assert(ftp.String(), qt.Equals, "image/svg+xml")
c.Assert(found, qt.Equals, true)
- c.Assert(tp.FullSuffix(), qt.Equals, ".svg")
+
}
func TestDecodeTypes(t *testing.T) {
@@ -169,10 +178,10 @@ func TestDecodeTypes(t *testing.T) {
false,
func(t *testing.T, name string, tt Types) {
c.Assert(len(tt), qt.Equals, len(DefaultTypes))
- json, found := tt.GetBySuffix("jasn")
+ json, si, found := tt.GetBySuffix("jasn")
c.Assert(found, qt.Equals, true)
c.Assert(json.String(), qt.Equals, "application/json")
- c.Assert(json.FullSuffix(), qt.Equals, ".jasn")
+ c.Assert(si.FullSuffix, qt.Equals, ".jasn")
},
},
{
@@ -180,7 +189,7 @@ func TestDecodeTypes(t *testing.T) {
[]map[string]interface{}{
{
"application/hugo+hg": map[string]interface{}{
- "suffixes": []string{"hg1", "hg2"},
+ "suffixes": []string{"hg1", "hG2"},
"Delimiter": "_",
},
},
@@ -188,15 +197,18 @@ func TestDecodeTypes(t *testing.T) {
false,
func(t *testing.T, name string, tt Types) {
c.Assert(len(tt), qt.Equals, len(DefaultTypes)+1)
- hg, found := tt.GetBySuffix("hg2")
+ hg, si, found := tt.GetBySuffix("hg2")
c.Assert(found, qt.Equals, true)
c.Assert(hg.mimeSuffix, qt.Equals, "hg")
- c.Assert(hg.Suffix(), qt.Equals, "hg2")
- c.Assert(hg.FullSuffix(), qt.Equals, "_hg2")
+ c.Assert(hg.FirstSuffix.Suffix, qt.Equals, "hg1")
+ c.Assert(hg.FirstSuffix.FullSuffix, qt.Equals, "_hg1")
+ c.Assert(si.Suffix, qt.Equals, "hg2")
+ c.Assert(si.FullSuffix, qt.Equals, "_hg2")
c.Assert(hg.String(), qt.Equals, "application/hugo+hg")
- hg, found = tt.GetByType("application/hugo+hg")
+ _, found = tt.GetByType("application/hugo+hg")
c.Assert(found, qt.Equals, true)
+
},
},
{
@@ -209,14 +221,14 @@ func TestDecodeTypes(t *testing.T) {
},
},
false,
- func(t *testing.T, name string, tt Types) {
- c.Assert(len(tt), qt.Equals, len(DefaultTypes)+1)
+ func(t *testing.T, name string, tp Types) {
+ c.Assert(len(tp), qt.Equals, len(DefaultTypes)+1)
// Make sure we have not broken the default config.
- _, found := tt.GetBySuffix("json")
+ _, _, found := tp.GetBySuffix("json")
c.Assert(found, qt.Equals, true)
- hugo, found := tt.GetBySuffix("hgo2")
+ hugo, _, found := tp.GetBySuffix("hgo2")
c.Assert(found, qt.Equals, true)
c.Assert(hugo.String(), qt.Equals, "text/hugo+hgo")
},
@@ -234,25 +246,33 @@ func TestDecodeTypes(t *testing.T) {
}
}
+func TestToJSON(t *testing.T) {
+ c := qt.New(t)
+ b, err := json.Marshal(MPEGType)
+ c.Assert(err, qt.IsNil)
+ c.Assert(string(b), qt.Equals, `{"mainType":"video","subType":"mpeg","delimiter":".","firstSuffix":{"suffix":"mpg","fullSuffix":".mpg"},"type":"video/mpeg","string":"video/mpeg","suffixes":["mpg","mpeg"]}`)
+}
+
func BenchmarkTypeOps(b *testing.B) {
mt := MPEGType
mts := DefaultTypes
for i := 0; i < b.N; i++ {
- _ = mt.FullSuffix()
+ ff := mt.FirstSuffix
+ _ = ff.FullSuffix
_ = mt.IsZero()
c, err := mt.MarshalJSON()
if c == nil || err != nil {
b.Fatal("failed")
}
_ = mt.String()
- _ = mt.Suffix()
+ _ = ff.Suffix
_ = mt.Suffixes
_ = mt.Type()
_ = mts.BySuffix("xml")
_, _ = mts.GetByMainSubType("application", "xml")
- _, _ = mts.GetBySuffix("xml")
+ _, _, _ = mts.GetBySuffix("xml")
_, _ = mts.GetByType("application")
- _, _ = mts.GetFirstBySuffix("xml")
+ _, _, _ = mts.GetFirstBySuffix("xml")
}
}