Skip to content

Commit

Permalink
Mime
Browse files Browse the repository at this point in the history
  • Loading branch information
bep committed May 12, 2024
1 parent 0efb5bf commit bab274e
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 28 deletions.
2 changes: 2 additions & 0 deletions config/allconfig/allconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
DisabledLanguages: disabledLangs,
IgnoredLogs: ignoredLogIDs,
KindOutputFormats: kindOutputFormats,
ContentTypes: media.DefaultContentTypes.FromTypes(c.MediaTypes.Config),
CreateTitle: helpers.GetTitleFunc(c.TitleCaseStyle),
IsUglyURLSection: isUglyURL,
IgnoreFile: ignoreFile,
Expand Down Expand Up @@ -402,6 +403,7 @@ type ConfigCompiled struct {
BaseURLLiveReload urls.BaseURL
ServerInterface string
KindOutputFormats map[string]output.Formats
ContentTypes media.ContentTypes
DisabledKinds map[string]bool
DisabledLanguages map[string]bool
IgnoredLogs map[string]bool
Expand Down
18 changes: 18 additions & 0 deletions config/allconfig/allconfig_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,21 @@ logPathWarnings = true
b.Assert(conf.PrintI18nWarnings, qt.Equals, true)
b.Assert(conf.PrintPathWarnings, qt.Equals, true)
}

func TestRedefineContentTypes(t *testing.T) {
files := `
-- hugo.toml --
baseURL = "https://example.com"
[mediaTypes]
[mediaTypes."text/html"]
suffixes = ["html", "xhtml"]
`

b := hugolib.Test(t, files)

conf := b.H.Configs.Base
contentTypes := conf.C.ContentTypes

b.Assert(contentTypes.HTML.Suffixes(), qt.DeepEquals, []string{"html", "xhtml"})
b.Assert(contentTypes.Markdown.Suffixes(), qt.DeepEquals, []string{"md", "mdown", "markdown"})
}
6 changes: 3 additions & 3 deletions hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ allow = ['asciidoctor', 'pandoc','rst2html']
-- layouts/_default/single.html --
|Content: {{ .Content }}|Title: {{ .Title }}|Path: {{ .Path }}|
-- content/docs/_content.gotmpl --
{{ $.AddPage (dict "path" "asciidoc" "content" (dict "value" "Mark my words, #automation is essential#." "mediaType" "text/x-asciidoc" )) }}
{{ $.AddPage (dict "path" "pandoc" "content" (dict "value" "This ~~is deleted text.~~" "mediaType" "text/x-pandoc" )) }}
{{ $.AddPage (dict "path" "rst" "content" (dict "value" "This is *bold*." "mediaType" "text/x-restructuredtext" )) }}
{{ $.AddPage (dict "path" "asciidoc" "content" (dict "value" "Mark my words, #automation is essential#." "mediaType" "text/asciidoc" )) }}
{{ $.AddPage (dict "path" "pandoc" "content" (dict "value" "This ~~is deleted text.~~" "mediaType" "text/pandoc" )) }}
{{ $.AddPage (dict "path" "rst" "content" (dict "value" "This is *bold*." "mediaType" "text/x-rst" )) }}
{{ $.AddPage (dict "path" "org" "content" (dict "value" "the ability to use +strikethrough+ is a plus" "mediaType" "text/org" )) }}
{{ $.AddPage (dict "path" "nocontent" "title" "No Content" ) }}
Expand Down
23 changes: 10 additions & 13 deletions media/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ var Builtin = BuiltinTypes{
// Common document types
PDFType: Type{Type: "application/pdf"},
MarkdownType: Type{Type: "text/markdown"},
AsciiDocType: Type{Type: "text/x-asciidoc"},
PandocType: Type{Type: "text/x-pandoc"},
ReStructuredTextType: Type{Type: "text/x-restructuredtext"},
AsciiDocType: Type{Type: "text/asciidoc"}, // https://github.com/asciidoctor/asciidoctor/issues/2502
PandocType: Type{Type: "text/pandoc"},
ReStructuredTextType: Type{Type: "text/x-rst"}, // https://docutils.sourceforge.io/FAQ.html#what-s-the-official-mime-type-for-restructuredtext-data
EmacsOrgModeType: Type{Type: "text/org"},
GoTmplType: Type{Type: "text/x-gotmpl"},

Expand Down Expand Up @@ -151,13 +151,13 @@ var defaultMediaTypesConfig = map[string]any{
"font/otf": map[string]any{"suffixes": []string{"otf"}},

// Common document types
"application/pdf": map[string]any{"suffixes": []string{"pdf"}},
"text/markdown": map[string]any{"suffixes": []string{"md", "mdown", "markdown"}},
"text/x-asciidoc": map[string]any{"suffixes": []string{"adoc", "asciidoc", "ad"}},
"text/x-pandoc": map[string]any{"suffixes": []string{"pandoc", "pdc"}},
"text/x-restructuredtext": map[string]any{"suffixes": []string{"rst"}},
"text/org": map[string]any{"suffixes": []string{"org"}},
"text/x-gotmpl": map[string]any{"suffixes": []string{"gotmpl"}},
"application/pdf": map[string]any{"suffixes": []string{"pdf"}},
"text/markdown": map[string]any{"suffixes": []string{"md", "mdown", "markdown"}},
"text/asciidoc": map[string]any{"suffixes": []string{"adoc", "asciidoc", "ad"}},
"text/pandoc": map[string]any{"suffixes": []string{"pandoc", "pdc"}},
"text/x-rst": map[string]any{"suffixes": []string{"rst"}},
"text/org": map[string]any{"suffixes": []string{"org"}},
"text/x-gotmpl": map[string]any{"suffixes": []string{"gotmpl"}},

// Common video types
"video/x-msvideo": map[string]any{"suffixes": []string{"avi"}},
Expand All @@ -173,9 +173,6 @@ var defaultMediaTypesConfig = map[string]any{
"application/octet-stream": map[string]any{},
}

// ContentMediaTypes list the media types that are considered content in Hugo.
var ContentMediaTypes Types

// IsContentSuffix returns whether the given suffix is a content media type.
func IsContentSuffix(suffix string) bool {
return contentMediaTypesExtensionsSet[suffix]
Expand Down
97 changes: 88 additions & 9 deletions media/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package media
import (
"errors"
"fmt"
"path/filepath"
"reflect"
"sort"
"strings"
Expand Down Expand Up @@ -57,24 +58,102 @@ func init() {
}

func init() {
// TODO1 move this to the config and make it configurable.
ContentMediaTypes = Types{
Builtin.HTMLType,
Builtin.MarkdownType,
Builtin.AsciiDocType,
Builtin.PandocType,
Builtin.ReStructuredTextType,
Builtin.EmacsOrgModeType,
DefaultContentTypes = ContentTypes{
HTML: Builtin.HTMLType,
Markdown: Builtin.MarkdownType,
AsciiDoc: Builtin.AsciiDocType,
Pandoc: Builtin.PandocType,
ReStructuredText: Builtin.ReStructuredTextType,
EmacsOrgMode: Builtin.EmacsOrgModeType,
}

DefaultContentTypes.init()

contentMediaTypesExtensionsSet = make(map[string]bool)
for _, mt := range ContentMediaTypes {
for _, mt := range DefaultContentTypes.Types() {
for _, suffix := range mt.Suffixes() {
contentMediaTypesExtensionsSet[suffix] = true
}
}
}

var DefaultContentTypes ContentTypes

// ContentTypes holds the media types that are considered content in Hugo.
type ContentTypes struct {
HTML Type
Markdown Type
AsciiDoc Type
Pandoc Type
ReStructuredText Type
EmacsOrgMode Type

// Created in init().
types Types
extensionSet map[string]bool
}

func (t *ContentTypes) init() {
t.types = Types{t.HTML, t.Markdown, t.AsciiDoc, t.Pandoc, t.ReStructuredText, t.EmacsOrgMode}
t.extensionSet = make(map[string]bool)
for _, mt := range t.types {
for _, suffix := range mt.Suffixes() {
t.extensionSet[suffix] = true
}
}
}

func (t ContentTypes) IsContentSuffix(suffix string) bool {
return t.extensionSet[suffix]
}

// IsContentFile returns whether the given filename is a content file.
func (t ContentTypes) IsContentFile(filename string) bool {
return t.IsContentSuffix(strings.TrimPrefix(filepath.Ext(filename), "."))
}

// IsIndexContentFile returns whether the given filename is an index content file.
func (t ContentTypes) IsIndexContentFile(filename string) bool {
if !t.IsContentFile(filename) {
return false
}

base := filepath.Base(filename)

return strings.HasPrefix(base, "index.") || strings.HasPrefix(base, "_index.")
}

// Types is a slice of media types.
func (t ContentTypes) Types() Types {
return t.types
}

// FromTypes creates a new ContentTypes updated with the values from the given Types.
func (t ContentTypes) FromTypes(types Types) ContentTypes {
if tt, ok := types.GetByType(t.HTML.Type); ok {
t.HTML = tt
}
if tt, ok := types.GetByType(t.Markdown.Type); ok {
t.Markdown = tt
}
if tt, ok := types.GetByType(t.AsciiDoc.Type); ok {
t.AsciiDoc = tt
}
if tt, ok := types.GetByType(t.Pandoc.Type); ok {
t.Pandoc = tt
}
if tt, ok := types.GetByType(t.ReStructuredText.Type); ok {
t.ReStructuredText = tt
}
if tt, ok := types.GetByType(t.EmacsOrgMode.Type); ok {
t.EmacsOrgMode = tt
}

t.init()

return t
}

// Hold the configuration for a given media type.
type MediaTypeConfig struct {
// The file suffixes used for this media type.
Expand Down
6 changes: 3 additions & 3 deletions media/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ func TestDefaultTypes(t *testing.T) {
{Builtin.HTMLType, "text", "html", "html,htm", "text/html", "text/html"},
{Builtin.MarkdownType, "text", "markdown", "md,mdown,markdown", "text/markdown", "text/markdown"},
{Builtin.EmacsOrgModeType, "text", "org", "org", "text/org", "text/org"},
{Builtin.PandocType, "text", "x-pandoc", "pandoc,pdc", "text/x-pandoc", "text/x-pandoc"},
{Builtin.ReStructuredTextType, "text", "x-restructuredtext", "rst", "text/x-restructuredtext", "text/x-restructuredtext"},
{Builtin.PandocType, "text", "x-pandoc", "pandoc,pdc", "text/pandoc", "text/pandoc"},
{Builtin.ReStructuredTextType, "text", "x-restructuredtext", "rst", "text/x-rst", "text/x-rst"},
{Builtin.GoTmplType, "text", "x-gotmpl", "gotmpl", "text/x-gotmpl", "text/x-gotmpl"},
{Builtin.AsciiDocType, "text", "x-asciidoc", "adoc,asciidoc,ad", "text/x-asciidoc", "text/x-asciidoc"},
{Builtin.AsciiDocType, "text", "x-asciidoc", "adoc,asciidoc,ad", "text/asciidoc", "text/asciidoc"},
{Builtin.JavascriptType, "text", "javascript", "js,jsm,mjs", "text/javascript", "text/javascript"},
{Builtin.TypeScriptType, "text", "typescript", "ts", "text/typescript", "text/typescript"},
{Builtin.TSXType, "text", "tsx", "tsx", "text/tsx", "text/tsx"},
Expand Down

0 comments on commit bab274e

Please sign in to comment.