1// Copyright 2019 The Hugo Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package markup
15
16import (
17	"strings"
18
19	"github.com/gohugoio/hugo/markup/highlight"
20
21	"github.com/gohugoio/hugo/markup/markup_config"
22
23	"github.com/gohugoio/hugo/markup/goldmark"
24
25	"github.com/gohugoio/hugo/markup/org"
26
27	"github.com/gohugoio/hugo/markup/asciidocext"
28	"github.com/gohugoio/hugo/markup/blackfriday"
29	"github.com/gohugoio/hugo/markup/converter"
30	"github.com/gohugoio/hugo/markup/mmark"
31	"github.com/gohugoio/hugo/markup/pandoc"
32	"github.com/gohugoio/hugo/markup/rst"
33)
34
35func NewConverterProvider(cfg converter.ProviderConfig) (ConverterProvider, error) {
36	converters := make(map[string]converter.Provider)
37
38	markupConfig, err := markup_config.Decode(cfg.Cfg)
39	if err != nil {
40		return nil, err
41	}
42
43	if cfg.Highlight == nil {
44		h := highlight.New(markupConfig.Highlight)
45		cfg.Highlight = func(code, lang, optsStr string) (string, error) {
46			return h.Highlight(code, lang, optsStr)
47		}
48	}
49
50	cfg.MarkupConfig = markupConfig
51
52	add := func(p converter.ProviderProvider, aliases ...string) error {
53		c, err := p.New(cfg)
54		if err != nil {
55			return err
56		}
57
58		name := c.Name()
59
60		aliases = append(aliases, name)
61
62		if strings.EqualFold(name, cfg.MarkupConfig.DefaultMarkdownHandler) {
63			aliases = append(aliases, "markdown")
64		}
65
66		addConverter(converters, c, aliases...)
67		return nil
68	}
69
70	if err := add(goldmark.Provider); err != nil {
71		return nil, err
72	}
73	if err := add(blackfriday.Provider); err != nil {
74		return nil, err
75	}
76	if err := add(mmark.Provider); err != nil {
77		return nil, err
78	}
79	if err := add(asciidocext.Provider, "ad", "adoc"); err != nil {
80		return nil, err
81	}
82	if err := add(rst.Provider); err != nil {
83		return nil, err
84	}
85	if err := add(pandoc.Provider, "pdc"); err != nil {
86		return nil, err
87	}
88	if err := add(org.Provider); err != nil {
89		return nil, err
90	}
91
92	return &converterRegistry{
93		config:     cfg,
94		converters: converters,
95	}, nil
96}
97
98type ConverterProvider interface {
99	Get(name string) converter.Provider
100	// Default() converter.Provider
101	GetMarkupConfig() markup_config.Config
102	Highlight(code, lang, optsStr string) (string, error)
103}
104
105type converterRegistry struct {
106	// Maps name (md, markdown, blackfriday etc.) to a converter provider.
107	// Note that this is also used for aliasing, so the same converter
108	// may be registered multiple times.
109	// All names are lower case.
110	converters map[string]converter.Provider
111
112	config converter.ProviderConfig
113}
114
115func (r *converterRegistry) Get(name string) converter.Provider {
116	return r.converters[strings.ToLower(name)]
117}
118
119func (r *converterRegistry) Highlight(code, lang, optsStr string) (string, error) {
120	return r.config.Highlight(code, lang, optsStr)
121}
122
123func (r *converterRegistry) GetMarkupConfig() markup_config.Config {
124	return r.config.MarkupConfig
125}
126
127func addConverter(m map[string]converter.Provider, c converter.Provider, aliases ...string) {
128	for _, alias := range aliases {
129		m[alias] = c
130	}
131}
132