@@ -71,11 +71,15 @@ func init() {
7171 EmacsOrgMode : Builtin .EmacsOrgModeType ,
7272 }
7373
74- DefaultContentTypes .init ()
74+ DefaultContentTypes .init (nil )
7575}
7676
7777var DefaultContentTypes ContentTypes
7878
79+ type ContentTypeConfig struct {
80+ // Empty for now.
81+ }
82+
7983// ContentTypes holds the media types that are considered content in Hugo.
8084type ContentTypes struct {
8185 HTML Type
@@ -85,13 +89,36 @@ type ContentTypes struct {
8589 ReStructuredText Type
8690 EmacsOrgMode Type
8791
92+ types Types
93+
8894 // Created in init().
89- types Types
9095 extensionSet map [string ]bool
9196}
9297
93- func (t * ContentTypes ) init () {
94- t .types = Types {t .HTML , t .Markdown , t .AsciiDoc , t .Pandoc , t .ReStructuredText , t .EmacsOrgMode }
98+ func (t * ContentTypes ) init (types Types ) {
99+ sort .Slice (t .types , func (i , j int ) bool {
100+ return t .types [i ].Type < t .types [j ].Type
101+ })
102+
103+ if tt , ok := types .GetByType (t .HTML .Type ); ok {
104+ t .HTML = tt
105+ }
106+ if tt , ok := types .GetByType (t .Markdown .Type ); ok {
107+ t .Markdown = tt
108+ }
109+ if tt , ok := types .GetByType (t .AsciiDoc .Type ); ok {
110+ t .AsciiDoc = tt
111+ }
112+ if tt , ok := types .GetByType (t .Pandoc .Type ); ok {
113+ t .Pandoc = tt
114+ }
115+ if tt , ok := types .GetByType (t .ReStructuredText .Type ); ok {
116+ t .ReStructuredText = tt
117+ }
118+ if tt , ok := types .GetByType (t .EmacsOrgMode .Type ); ok {
119+ t .EmacsOrgMode = tt
120+ }
121+
95122 t .extensionSet = make (map [string ]bool )
96123 for _ , mt := range t .types {
97124 for _ , suffix := range mt .Suffixes () {
@@ -135,32 +162,6 @@ func (t ContentTypes) Types() Types {
135162 return t .types
136163}
137164
138- // FromTypes creates a new ContentTypes updated with the values from the given Types.
139- func (t ContentTypes ) FromTypes (types Types ) ContentTypes {
140- if tt , ok := types .GetByType (t .HTML .Type ); ok {
141- t .HTML = tt
142- }
143- if tt , ok := types .GetByType (t .Markdown .Type ); ok {
144- t .Markdown = tt
145- }
146- if tt , ok := types .GetByType (t .AsciiDoc .Type ); ok {
147- t .AsciiDoc = tt
148- }
149- if tt , ok := types .GetByType (t .Pandoc .Type ); ok {
150- t .Pandoc = tt
151- }
152- if tt , ok := types .GetByType (t .ReStructuredText .Type ); ok {
153- t .ReStructuredText = tt
154- }
155- if tt , ok := types .GetByType (t .EmacsOrgMode .Type ); ok {
156- t .EmacsOrgMode = tt
157- }
158-
159- t .init ()
160-
161- return t
162- }
163-
164165// Hold the configuration for a given media type.
165166type MediaTypeConfig struct {
166167 // The file suffixes used for this media type.
@@ -169,6 +170,58 @@ type MediaTypeConfig struct {
169170 Delimiter string
170171}
171172
173+ var defaultContentTypesConfig = map [string ]ContentTypeConfig {
174+ Builtin .HTMLType .Type : {},
175+ Builtin .MarkdownType .Type : {},
176+ Builtin .AsciiDocType .Type : {},
177+ Builtin .PandocType .Type : {},
178+ Builtin .ReStructuredTextType .Type : {},
179+ Builtin .EmacsOrgModeType .Type : {},
180+ }
181+
182+ // DecodeContentTypes decodes the given map of content types.
183+ func DecodeContentTypes (in map [string ]any , types Types ) (* config.ConfigNamespace [map [string ]ContentTypeConfig , ContentTypes ], error ) {
184+ buildConfig := func (v any ) (ContentTypes , any , error ) {
185+ var s map [string ]ContentTypeConfig
186+ c := DefaultContentTypes
187+ m , err := maps .ToStringMapE (v )
188+ if err != nil {
189+ return c , nil , err
190+ }
191+ if len (m ) == 0 {
192+ s = defaultContentTypesConfig
193+ } else {
194+ s = make (map [string ]ContentTypeConfig )
195+ m = maps .CleanConfigStringMap (m )
196+ for k , v := range m {
197+ var ctc ContentTypeConfig
198+ if err := mapstructure .WeakDecode (v , & ctc ); err != nil {
199+ return c , nil , err
200+ }
201+ s [k ] = ctc
202+ }
203+ }
204+
205+ for k := range s {
206+ mediaType , found := types .GetByType (k )
207+ if ! found {
208+ return c , nil , fmt .Errorf ("unknown media type %q" , k )
209+ }
210+ c .types = append (c .types , mediaType )
211+ }
212+
213+ c .init (types )
214+
215+ return c , s , nil
216+ }
217+
218+ ns , err := config .DecodeNamespace [map [string ]ContentTypeConfig ](in , buildConfig )
219+ if err != nil {
220+ return nil , fmt .Errorf ("failed to decode media types: %w" , err )
221+ }
222+ return ns , nil
223+ }
224+
172225// DecodeTypes decodes the given map of media types.
173226func DecodeTypes (in map [string ]any ) (* config.ConfigNamespace [map [string ]MediaTypeConfig , Types ], error ) {
174227 buildConfig := func (v any ) (Types , any , error ) {
@@ -220,6 +273,6 @@ func DecodeTypes(in map[string]any) (*config.ConfigNamespace[map[string]MediaTyp
220273// TODO(bep) get rid of this.
221274var DefaultPathParser = & paths.PathParser {
222275 IsContentExt : func (ext string ) bool {
223- return DefaultContentTypes . IsContentSuffix ( ext )
276+ panic ( "not supported" )
224277 },
225278}
0 commit comments