mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Improve minifier MIME type resolution
This commit also removes the deprecated `Suffix` from MediaType. Now use `Suffixes` and put the MIME type suffix in the type, e.g. `application/svg+xml`. Fixes #5093
This commit is contained in:
parent
6b9934a266
commit
ebb56e8bdb
8 changed files with 87 additions and 106 deletions
|
@ -97,7 +97,7 @@ top = "top"
|
||||||
|
|
||||||
[mediaTypes]
|
[mediaTypes]
|
||||||
[mediaTypes."text/m1"]
|
[mediaTypes."text/m1"]
|
||||||
suffix = "m1main"
|
suffixes = ["m1main"]
|
||||||
|
|
||||||
[outputFormats.o1]
|
[outputFormats.o1]
|
||||||
mediaType = "text/m1"
|
mediaType = "text/m1"
|
||||||
|
@ -135,9 +135,9 @@ p3 = "p3 theme"
|
||||||
|
|
||||||
[mediaTypes]
|
[mediaTypes]
|
||||||
[mediaTypes."text/m1"]
|
[mediaTypes."text/m1"]
|
||||||
suffix = "m1theme"
|
suffixes = ["m1theme"]
|
||||||
[mediaTypes."text/m2"]
|
[mediaTypes."text/m2"]
|
||||||
suffix = "m2theme"
|
suffixes = ["m2theme"]
|
||||||
|
|
||||||
[outputFormats.o1]
|
[outputFormats.o1]
|
||||||
mediaType = "text/m1"
|
mediaType = "text/m1"
|
||||||
|
@ -207,10 +207,14 @@ map[string]interface {}{
|
||||||
b.AssertObject(`
|
b.AssertObject(`
|
||||||
map[string]interface {}{
|
map[string]interface {}{
|
||||||
"text/m1": map[string]interface {}{
|
"text/m1": map[string]interface {}{
|
||||||
"suffix": "m1main",
|
"suffixes": []interface {}{
|
||||||
|
"m1main",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"text/m2": map[string]interface {}{
|
"text/m2": map[string]interface {}{
|
||||||
"suffix": "m2theme",
|
"suffixes": []interface {}{
|
||||||
|
"m2theme",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}`, got["mediatypes"])
|
}`, got["mediatypes"])
|
||||||
|
|
||||||
|
@ -221,7 +225,6 @@ map[string]interface {}{
|
||||||
"mediatype": Type{
|
"mediatype": Type{
|
||||||
MainType: "text",
|
MainType: "text",
|
||||||
SubType: "m1",
|
SubType: "m1",
|
||||||
OldSuffix: "m1main",
|
|
||||||
Delimiter: ".",
|
Delimiter: ".",
|
||||||
Suffixes: []string{
|
Suffixes: []string{
|
||||||
"m1main",
|
"m1main",
|
||||||
|
@ -233,7 +236,6 @@ map[string]interface {}{
|
||||||
"mediatype": Type{
|
"mediatype": Type{
|
||||||
MainType: "text",
|
MainType: "text",
|
||||||
SubType: "m2",
|
SubType: "m2",
|
||||||
OldSuffix: "m2theme",
|
|
||||||
Delimiter: ".",
|
Delimiter: ".",
|
||||||
Suffixes: []string{
|
Suffixes: []string{
|
||||||
"m2theme",
|
"m2theme",
|
||||||
|
|
|
@ -435,7 +435,7 @@ func newTestBundleSources(t *testing.T) (*hugofs.Fs, *viper.Viper) {
|
||||||
cfg.Set("baseURL", "https://example.com")
|
cfg.Set("baseURL", "https://example.com")
|
||||||
cfg.Set("mediaTypes", map[string]interface{}{
|
cfg.Set("mediaTypes", map[string]interface{}{
|
||||||
"text/bepsays": map[string]interface{}{
|
"text/bepsays": map[string]interface{}{
|
||||||
"suffix": "bep",
|
"suffixes": []string{"bep"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -276,14 +276,12 @@ disableKinds = ["page", "section", "taxonomy", "taxonomyTerm", "sitemap", "robot
|
||||||
|
|
||||||
[mediaTypes]
|
[mediaTypes]
|
||||||
[mediaTypes."text/nodot"]
|
[mediaTypes."text/nodot"]
|
||||||
suffix = ""
|
|
||||||
delimiter = ""
|
delimiter = ""
|
||||||
[mediaTypes."text/defaultdelim"]
|
[mediaTypes."text/defaultdelim"]
|
||||||
suffix = "defd"
|
suffixes = ["defd"]
|
||||||
[mediaTypes."text/nosuffix"]
|
[mediaTypes."text/nosuffix"]
|
||||||
suffix = ""
|
|
||||||
[mediaTypes."text/customdelim"]
|
[mediaTypes."text/customdelim"]
|
||||||
suffix = "del"
|
suffixes = ["del"]
|
||||||
delimiter = "_"
|
delimiter = "_"
|
||||||
|
|
||||||
[outputs]
|
[outputs]
|
||||||
|
@ -321,7 +319,7 @@ baseName = "customdelimbase"
|
||||||
th.assertFileContent("public/_redirects", "a dotless")
|
th.assertFileContent("public/_redirects", "a dotless")
|
||||||
th.assertFileContent("public/defaultdelimbase.defd", "default delimim")
|
th.assertFileContent("public/defaultdelimbase.defd", "default delimim")
|
||||||
// This looks weird, but the user has chosen this definition.
|
// This looks weird, but the user has chosen this definition.
|
||||||
th.assertFileContent("public/nosuffixbase.", "no suffix")
|
th.assertFileContent("public/nosuffixbase", "no suffix")
|
||||||
th.assertFileContent("public/customdelimbase_del", "custom delim")
|
th.assertFileContent("public/customdelimbase_del", "custom delim")
|
||||||
|
|
||||||
s := h.Sites[0]
|
s := h.Sites[0]
|
||||||
|
@ -332,7 +330,7 @@ baseName = "customdelimbase"
|
||||||
|
|
||||||
require.Equal(t, "/blog/_redirects", outputs.Get("DOTLESS").RelPermalink())
|
require.Equal(t, "/blog/_redirects", outputs.Get("DOTLESS").RelPermalink())
|
||||||
require.Equal(t, "/blog/defaultdelimbase.defd", outputs.Get("DEF").RelPermalink())
|
require.Equal(t, "/blog/defaultdelimbase.defd", outputs.Get("DEF").RelPermalink())
|
||||||
require.Equal(t, "/blog/nosuffixbase.", outputs.Get("NOS").RelPermalink())
|
require.Equal(t, "/blog/nosuffixbase", outputs.Get("NOS").RelPermalink())
|
||||||
require.Equal(t, "/blog/customdelimbase_del", outputs.Get("CUS").RelPermalink())
|
require.Equal(t, "/blog/customdelimbase_del", outputs.Get("CUS").RelPermalink())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,13 @@ package media
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/common/maps"
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,10 +39,9 @@ type Type struct {
|
||||||
MainType string `json:"mainType"` // i.e. text
|
MainType string `json:"mainType"` // i.e. text
|
||||||
SubType string `json:"subType"` // i.e. html
|
SubType string `json:"subType"` // i.e. html
|
||||||
|
|
||||||
// Deprecated in Hugo 0.44. To be renamed and unexported.
|
// This is the optional suffix after the "+" in the MIME type,
|
||||||
// Was earlier used both to set file suffix and to augment the MIME type.
|
// e.g. "xml" in "applicatiion/rss+xml".
|
||||||
// This had its limitations and issues.
|
mimeSuffix string
|
||||||
OldSuffix string `json:"-" mapstructure:"suffix"`
|
|
||||||
|
|
||||||
Delimiter string `json:"delimiter"` // e.g. "."
|
Delimiter string `json:"delimiter"` // e.g. "."
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ func fromString(t string) (Type, error) {
|
||||||
suffix = subParts[1]
|
suffix = subParts[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
return Type{MainType: mainType, SubType: subType, OldSuffix: suffix}, nil
|
return Type{MainType: mainType, SubType: subType, mimeSuffix: suffix}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type returns a string representing the main- and sub-type of a media type, e.g. "text/css".
|
// Type returns a string representing the main- and sub-type of a media type, e.g. "text/css".
|
||||||
|
@ -91,8 +92,8 @@ func (m Type) Type() string {
|
||||||
// Examples are
|
// Examples are
|
||||||
// image/svg+xml
|
// image/svg+xml
|
||||||
// text/css
|
// text/css
|
||||||
if m.OldSuffix != "" {
|
if m.mimeSuffix != "" {
|
||||||
return fmt.Sprintf("%s/%s+%s", m.MainType, m.SubType, m.OldSuffix)
|
return fmt.Sprintf("%s/%s+%s", m.MainType, m.SubType, m.mimeSuffix)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s/%s", m.MainType, m.SubType)
|
return fmt.Sprintf("%s/%s", m.MainType, m.SubType)
|
||||||
|
|
||||||
|
@ -130,9 +131,9 @@ var (
|
||||||
HTMLType = Type{MainType: "text", SubType: "html", Suffixes: []string{"html"}, Delimiter: defaultDelimiter}
|
HTMLType = Type{MainType: "text", SubType: "html", Suffixes: []string{"html"}, Delimiter: defaultDelimiter}
|
||||||
JavascriptType = Type{MainType: "application", SubType: "javascript", Suffixes: []string{"js"}, Delimiter: defaultDelimiter}
|
JavascriptType = Type{MainType: "application", SubType: "javascript", Suffixes: []string{"js"}, Delimiter: defaultDelimiter}
|
||||||
JSONType = Type{MainType: "application", SubType: "json", Suffixes: []string{"json"}, Delimiter: defaultDelimiter}
|
JSONType = Type{MainType: "application", SubType: "json", Suffixes: []string{"json"}, Delimiter: defaultDelimiter}
|
||||||
RSSType = Type{MainType: "application", SubType: "rss", OldSuffix: "xml", Suffixes: []string{"xml"}, 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}
|
XMLType = Type{MainType: "application", SubType: "xml", Suffixes: []string{"xml"}, Delimiter: defaultDelimiter}
|
||||||
SVGType = Type{MainType: "image", SubType: "svg", OldSuffix: "xml", Suffixes: []string{"svg"}, 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}
|
TextType = Type{MainType: "text", SubType: "plain", Suffixes: []string{"txt"}, Delimiter: defaultDelimiter}
|
||||||
|
|
||||||
OctetType = Type{MainType: "application", SubType: "octet-stream"}
|
OctetType = Type{MainType: "application", SubType: "octet-stream"}
|
||||||
|
@ -182,6 +183,17 @@ func (t Types) GetByType(tp string) (Type, bool) {
|
||||||
return Type{}, false
|
return Type{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BySuffix will return all media types matching a suffix.
|
||||||
|
func (t Types) BySuffix(suffix string) []Type {
|
||||||
|
var types []Type
|
||||||
|
for _, tt := range t {
|
||||||
|
if match := tt.matchSuffix(suffix); match != "" {
|
||||||
|
types = append(types, tt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return types
|
||||||
|
}
|
||||||
|
|
||||||
// GetFirstBySuffix will return the first media type matching the given suffix.
|
// GetFirstBySuffix will return the first media type matching the given suffix.
|
||||||
func (t Types) GetFirstBySuffix(suffix string) (Type, bool) {
|
func (t Types) GetFirstBySuffix(suffix string) (Type, bool) {
|
||||||
for _, tt := range t {
|
for _, tt := range t {
|
||||||
|
@ -214,9 +226,6 @@ func (t Types) GetBySuffix(suffix string) (tp Type, found bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Type) matchSuffix(suffix string) string {
|
func (t Type) matchSuffix(suffix string) string {
|
||||||
if strings.EqualFold(suffix, t.OldSuffix) {
|
|
||||||
return t.OldSuffix
|
|
||||||
}
|
|
||||||
for _, s := range t.Suffixes {
|
for _, s := range t.Suffixes {
|
||||||
if strings.EqualFold(suffix, s) {
|
if strings.EqualFold(suffix, s) {
|
||||||
return s
|
return s
|
||||||
|
@ -246,9 +255,8 @@ func (t Types) GetByMainSubType(mainType, subType string) (tp Type, found bool)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func suffixIsDeprecated() {
|
func suffixIsRemoved() error {
|
||||||
helpers.Deprecated("MediaType", "Suffix in config.toml", `
|
return errors.New(`MediaType.Suffix is removed. Before Hugo 0.44 this was used both to set a custom file suffix and as way
|
||||||
Before Hugo 0.44 this was used both to set a custom file suffix and as way
|
|
||||||
to augment the mediatype definition (what you see after the "+", e.g. "image/svg+xml").
|
to augment the mediatype definition (what you see after the "+", e.g. "image/svg+xml").
|
||||||
|
|
||||||
This had its limitations. For one, it was only possible with one file extension per MIME type.
|
This had its limitations. For one, it was only possible with one file extension per MIME type.
|
||||||
|
@ -272,16 +280,13 @@ To:
|
||||||
[mediaTypes."my/custom-mediatype"]
|
[mediaTypes."my/custom-mediatype"]
|
||||||
suffixes = ["txt"]
|
suffixes = ["txt"]
|
||||||
|
|
||||||
Hugo will still respect values set in "suffix" if no value for "suffixes" is provided, but this will be removed
|
|
||||||
in a future release.
|
|
||||||
|
|
||||||
Note that you can still get the Media Type's suffix from a template: {{ $mediaType.Suffix }}. But this will now map to the MIME type filename.
|
Note that you can still get the Media Type's suffix from a template: {{ $mediaType.Suffix }}. But this will now map to the MIME type filename.
|
||||||
`, false)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeTypes takes a list of media type configurations and merges those,
|
// DecodeTypes takes a list of media type configurations and merges those,
|
||||||
// in the order given, with the Hugo defaults as the last resort.
|
// in the order given, with the Hugo defaults as the last resort.
|
||||||
func DecodeTypes(maps ...map[string]interface{}) (Types, error) {
|
func DecodeTypes(mms ...map[string]interface{}) (Types, error) {
|
||||||
var m Types
|
var m Types
|
||||||
|
|
||||||
// Maps type string to Type. Type string is the full application/svg+xml.
|
// Maps type string to Type. Type string is the full application/svg+xml.
|
||||||
|
@ -293,7 +298,7 @@ func DecodeTypes(maps ...map[string]interface{}) (Types, error) {
|
||||||
mmm[dt.Type()] = dt
|
mmm[dt.Type()] = dt
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mm := range maps {
|
for _, mm := range mms {
|
||||||
for k, v := range mm {
|
for k, v := range mm {
|
||||||
var mediaType Type
|
var mediaType Type
|
||||||
|
|
||||||
|
@ -311,24 +316,17 @@ func DecodeTypes(maps ...map[string]interface{}) (Types, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
vm := v.(map[string]interface{})
|
vm := v.(map[string]interface{})
|
||||||
|
maps.ToLower(vm)
|
||||||
_, delimiterSet := vm["delimiter"]
|
_, delimiterSet := vm["delimiter"]
|
||||||
_, suffixSet := vm["suffix"]
|
_, suffixSet := vm["suffix"]
|
||||||
|
|
||||||
if suffixSet {
|
if suffixSet {
|
||||||
suffixIsDeprecated()
|
return Types{}, suffixIsRemoved()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Before Hugo 0.44 we had a non-standard use of the Suffix
|
|
||||||
// attribute, and this is now deprecated (use Suffixes for file suffixes).
|
|
||||||
// But we need to keep old configurations working for a while.
|
|
||||||
if len(mediaType.Suffixes) == 0 && mediaType.OldSuffix != "" {
|
|
||||||
mediaType.Suffixes = []string{mediaType.OldSuffix}
|
|
||||||
}
|
|
||||||
// The user may set the delimiter as an empty string.
|
// The user may set the delimiter as an empty string.
|
||||||
if !delimiterSet && len(mediaType.Suffixes) != 0 {
|
if !delimiterSet && len(mediaType.Suffixes) != 0 {
|
||||||
mediaType.Delimiter = defaultDelimiter
|
mediaType.Delimiter = defaultDelimiter
|
||||||
} else if suffixSet && !delimiterSet {
|
|
||||||
mediaType.Delimiter = defaultDelimiter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mmm[k] = mediaType
|
mmm[k] = mediaType
|
||||||
|
|
|
@ -80,11 +80,19 @@ func TestGetByMainSubType(t *testing.T) {
|
||||||
assert.False(found)
|
assert.False(found)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBySuffix(t *testing.T) {
|
||||||
|
assert := require.New(t)
|
||||||
|
formats := DefaultTypes.BySuffix("xml")
|
||||||
|
assert.Equal(2, len(formats))
|
||||||
|
assert.Equal("rss", formats[0].SubType)
|
||||||
|
assert.Equal("xml", formats[1].SubType)
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetFirstBySuffix(t *testing.T) {
|
func TestGetFirstBySuffix(t *testing.T) {
|
||||||
assert := require.New(t)
|
assert := require.New(t)
|
||||||
f, found := DefaultTypes.GetFirstBySuffix("xml")
|
f, found := DefaultTypes.GetFirstBySuffix("xml")
|
||||||
assert.True(found)
|
assert.True(found)
|
||||||
assert.Equal(Type{MainType: "application", SubType: "rss", OldSuffix: "xml", Delimiter: ".", Suffixes: []string{"xml"}, fileSuffix: "xml"}, f)
|
assert.Equal(Type{MainType: "application", SubType: "rss", mimeSuffix: "xml", Delimiter: ".", Suffixes: []string{"xml"}, fileSuffix: "xml"}, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTypeString(t *testing.T) {
|
func TestFromTypeString(t *testing.T) {
|
||||||
|
@ -94,18 +102,18 @@ func TestFromTypeString(t *testing.T) {
|
||||||
|
|
||||||
f, err = fromString("application/custom")
|
f, err = fromString("application/custom")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, Type{MainType: "application", SubType: "custom", OldSuffix: "", fileSuffix: ""}, f)
|
require.Equal(t, Type{MainType: "application", SubType: "custom", mimeSuffix: "", fileSuffix: ""}, f)
|
||||||
|
|
||||||
f, err = fromString("application/custom+sfx")
|
f, err = fromString("application/custom+sfx")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, Type{MainType: "application", SubType: "custom", OldSuffix: "sfx"}, f)
|
require.Equal(t, Type{MainType: "application", SubType: "custom", mimeSuffix: "sfx"}, f)
|
||||||
|
|
||||||
_, err = fromString("noslash")
|
_, err = fromString("noslash")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
f, err = fromString("text/xml; charset=utf-8")
|
f, err = fromString("text/xml; charset=utf-8")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, Type{MainType: "text", SubType: "xml", OldSuffix: ""}, f)
|
require.Equal(t, Type{MainType: "text", SubType: "xml", mimeSuffix: ""}, f)
|
||||||
require.Equal(t, "", f.Suffix())
|
require.Equal(t, "", f.Suffix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,28 +154,24 @@ func TestDecodeTypes(t *testing.T) {
|
||||||
json, found := tt.GetBySuffix("jasn")
|
json, found := tt.GetBySuffix("jasn")
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, "application/json", json.String(), name)
|
require.Equal(t, "application/json", json.String(), name)
|
||||||
|
require.Equal(t, ".jasn", json.FullSuffix())
|
||||||
}},
|
}},
|
||||||
{
|
{
|
||||||
"Suffix from key, multiple file suffixes",
|
"MIME suffix in key, multiple file suffixes, custom delimiter",
|
||||||
[]map[string]interface{}{
|
[]map[string]interface{}{
|
||||||
{
|
{
|
||||||
"application/hugo+hg": map[string]interface{}{
|
"application/hugo+hg": map[string]interface{}{
|
||||||
"Suffixes": []string{"hg1", "hg2"},
|
"suffixes": []string{"hg1", "hg2"},
|
||||||
|
"Delimiter": "_",
|
||||||
}}},
|
}}},
|
||||||
false,
|
false,
|
||||||
func(t *testing.T, name string, tt Types) {
|
func(t *testing.T, name string, tt Types) {
|
||||||
require.Len(t, tt, len(DefaultTypes)+1)
|
require.Len(t, tt, len(DefaultTypes)+1)
|
||||||
hg, found := tt.GetBySuffix("hg")
|
hg, found := tt.GetBySuffix("hg2")
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, "hg", hg.OldSuffix)
|
require.Equal(t, "hg", hg.mimeSuffix)
|
||||||
require.Equal(t, "hg", hg.Suffix())
|
|
||||||
require.Equal(t, ".hg", hg.FullSuffix())
|
|
||||||
require.Equal(t, "application/hugo+hg", hg.String(), name)
|
|
||||||
hg, found = tt.GetBySuffix("hg2")
|
|
||||||
require.True(t, found)
|
|
||||||
require.Equal(t, "hg", hg.OldSuffix)
|
|
||||||
require.Equal(t, "hg2", hg.Suffix())
|
require.Equal(t, "hg2", hg.Suffix())
|
||||||
require.Equal(t, ".hg2", hg.FullSuffix())
|
require.Equal(t, "_hg2", hg.FullSuffix())
|
||||||
require.Equal(t, "application/hugo+hg", hg.String(), name)
|
require.Equal(t, "application/hugo+hg", hg.String(), name)
|
||||||
|
|
||||||
hg, found = tt.GetByType("application/hugo+hg")
|
hg, found = tt.GetByType("application/hugo+hg")
|
||||||
|
@ -178,8 +182,8 @@ func TestDecodeTypes(t *testing.T) {
|
||||||
"Add custom media type",
|
"Add custom media type",
|
||||||
[]map[string]interface{}{
|
[]map[string]interface{}{
|
||||||
{
|
{
|
||||||
"text/hugo": map[string]interface{}{
|
"text/hugo+hgo": map[string]interface{}{
|
||||||
"suffix": "hgo"}}},
|
"Suffixes": []string{"hgo2"}}}},
|
||||||
false,
|
false,
|
||||||
func(t *testing.T, name string, tt Types) {
|
func(t *testing.T, name string, tt Types) {
|
||||||
require.Len(t, tt, len(DefaultTypes)+1)
|
require.Len(t, tt, len(DefaultTypes)+1)
|
||||||
|
@ -188,7 +192,7 @@ func TestDecodeTypes(t *testing.T) {
|
||||||
_, found := tt.GetBySuffix("json")
|
_, found := tt.GetBySuffix("json")
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
|
|
||||||
hugo, found := tt.GetBySuffix("hgo")
|
hugo, found := tt.GetBySuffix("hgo2")
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, "text/hugo+hgo", hugo.String(), name)
|
require.Equal(t, "text/hugo+hgo", hugo.String(), name)
|
||||||
}},
|
}},
|
||||||
|
|
|
@ -71,60 +71,35 @@ func New(mediaTypes media.Types, outputFormats output.Formats) Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use the Type definition of the media types defined in the site if found.
|
// We use the Type definition of the media types defined in the site if found.
|
||||||
addMinifierFunc(m, mediaTypes, "text/css", "css", css.Minify)
|
addMinifierFunc(m, mediaTypes, "css", css.Minify)
|
||||||
addMinifierFunc(m, mediaTypes, "application/javascript", "js", js.Minify)
|
addMinifierFunc(m, mediaTypes, "js", js.Minify)
|
||||||
m.AddFuncRegexp(regexp.MustCompile("^(application|text)/(x-)?(java|ecma)script$"), js.Minify)
|
m.AddFuncRegexp(regexp.MustCompile("^(application|text)/(x-)?(java|ecma)script$"), js.Minify)
|
||||||
addMinifierFunc(m, mediaTypes, "application/json", "json", json.Minify)
|
addMinifierFunc(m, mediaTypes, "json", json.Minify)
|
||||||
addMinifierFunc(m, mediaTypes, "image/svg+xml", "svg", svg.Minify)
|
addMinifierFunc(m, mediaTypes, "svg", svg.Minify)
|
||||||
addMinifierFunc(m, mediaTypes, "application/xml", "xml", xml.Minify)
|
addMinifierFunc(m, mediaTypes, "xml", xml.Minify)
|
||||||
addMinifierFunc(m, mediaTypes, "application/rss", "xml", xml.Minify)
|
|
||||||
|
|
||||||
// HTML
|
// HTML
|
||||||
addMinifier(m, mediaTypes, "text/html", "html", htmlMin)
|
addMinifier(m, mediaTypes, "html", htmlMin)
|
||||||
for _, of := range outputFormats {
|
for _, of := range outputFormats {
|
||||||
if of.IsHTML {
|
if of.IsHTML {
|
||||||
addMinifier(m, mediaTypes, of.MediaType.Type(), "html", htmlMin)
|
m.Add(of.MediaType.Type(), htmlMin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Client{m: m}
|
return Client{m: m}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func addMinifier(m *minify.M, mt media.Types, typeString, suffix string, min minify.Minifier) {
|
func addMinifier(m *minify.M, mt media.Types, suffix string, min minify.Minifier) {
|
||||||
resolvedTypeStr := resolveMediaTypeString(mt, typeString, suffix)
|
types := mt.BySuffix(suffix)
|
||||||
m.Add(resolvedTypeStr, min)
|
for _, t := range types {
|
||||||
if resolvedTypeStr != typeString {
|
m.Add(t.Type(), min)
|
||||||
m.Add(typeString, min)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addMinifierFunc(m *minify.M, mt media.Types, typeString, suffix string, fn minify.MinifierFunc) {
|
func addMinifierFunc(m *minify.M, mt media.Types, suffix string, min minify.MinifierFunc) {
|
||||||
resolvedTypeStr := resolveMediaTypeString(mt, typeString, suffix)
|
types := mt.BySuffix(suffix)
|
||||||
m.AddFunc(resolvedTypeStr, fn)
|
for _, t := range types {
|
||||||
if resolvedTypeStr != typeString {
|
m.AddFunc(t.Type(), min)
|
||||||
m.AddFunc(typeString, fn)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveMediaTypeString(types media.Types, typeStr, suffix string) string {
|
|
||||||
if m, found := resolveMediaType(types, typeStr, suffix); found {
|
|
||||||
return m.Type()
|
|
||||||
}
|
|
||||||
// Fall back to the default.
|
|
||||||
return typeStr
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we match the matching pattern with what the user have actually defined
|
|
||||||
// in his or hers media types configuration.
|
|
||||||
func resolveMediaType(types media.Types, typeStr, suffix string) (media.Type, bool) {
|
|
||||||
if m, found := types.GetByType(typeStr); found {
|
|
||||||
return m, true
|
|
||||||
}
|
|
||||||
|
|
||||||
if m, found := types.GetFirstBySuffix(suffix); found {
|
|
||||||
return m, true
|
|
||||||
}
|
|
||||||
|
|
||||||
return media.Type{}, false
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -32,4 +32,10 @@ func TestNew(t *testing.T) {
|
||||||
|
|
||||||
assert.NoError(m.Minify(media.CSSType, &b, strings.NewReader("body { color: blue; }")))
|
assert.NoError(m.Minify(media.CSSType, &b, strings.NewReader("body { color: blue; }")))
|
||||||
assert.Equal("body{color:blue}", b.String())
|
assert.Equal("body{color:blue}", b.String())
|
||||||
|
|
||||||
|
b.Reset()
|
||||||
|
|
||||||
|
// RSS should be handled as XML
|
||||||
|
assert.NoError(m.Minify(media.RSSType, &b, strings.NewReader("<hello> Hugo! </hello> ")))
|
||||||
|
assert.Equal("<hello>Hugo!</hello>", b.String())
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,11 +93,9 @@ func TestGetFormatByExt(t *testing.T) {
|
||||||
|
|
||||||
func TestGetFormatByFilename(t *testing.T) {
|
func TestGetFormatByFilename(t *testing.T) {
|
||||||
noExtNoDelimMediaType := media.TextType
|
noExtNoDelimMediaType := media.TextType
|
||||||
noExtNoDelimMediaType.OldSuffix = ""
|
|
||||||
noExtNoDelimMediaType.Delimiter = ""
|
noExtNoDelimMediaType.Delimiter = ""
|
||||||
|
|
||||||
noExtMediaType := media.TextType
|
noExtMediaType := media.TextType
|
||||||
noExtMediaType.OldSuffix = ""
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
noExtDelimFormat = Format{
|
noExtDelimFormat = Format{
|
||||||
|
|
Loading…
Reference in a new issue