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 converter
15
16import (
17	"bytes"
18
19	"github.com/gohugoio/hugo/common/hexec"
20	"github.com/gohugoio/hugo/common/loggers"
21	"github.com/gohugoio/hugo/config"
22	"github.com/gohugoio/hugo/identity"
23	"github.com/gohugoio/hugo/markup/converter/hooks"
24	"github.com/gohugoio/hugo/markup/markup_config"
25	"github.com/gohugoio/hugo/markup/tableofcontents"
26	"github.com/spf13/afero"
27)
28
29// ProviderConfig configures a new Provider.
30type ProviderConfig struct {
31	MarkupConfig markup_config.Config
32
33	Cfg       config.Provider // Site config
34	ContentFs afero.Fs
35	Logger    loggers.Logger
36	Exec      *hexec.Exec
37	Highlight func(code, lang, optsStr string) (string, error)
38}
39
40// ProviderProvider creates converter providers.
41type ProviderProvider interface {
42	New(cfg ProviderConfig) (Provider, error)
43}
44
45// Provider creates converters.
46type Provider interface {
47	New(ctx DocumentContext) (Converter, error)
48	Name() string
49}
50
51// NewProvider creates a new Provider with the given name.
52func NewProvider(name string, create func(ctx DocumentContext) (Converter, error)) Provider {
53	return newConverter{
54		name:   name,
55		create: create,
56	}
57}
58
59type newConverter struct {
60	name   string
61	create func(ctx DocumentContext) (Converter, error)
62}
63
64func (n newConverter) New(ctx DocumentContext) (Converter, error) {
65	return n.create(ctx)
66}
67
68func (n newConverter) Name() string {
69	return n.name
70}
71
72var NopConverter = new(nopConverter)
73
74type nopConverter int
75
76func (nopConverter) Convert(ctx RenderContext) (Result, error) {
77	return &bytes.Buffer{}, nil
78}
79
80func (nopConverter) Supports(feature identity.Identity) bool {
81	return false
82}
83
84// Converter wraps the Convert method that converts some markup into
85// another format, e.g. Markdown to HTML.
86type Converter interface {
87	Convert(ctx RenderContext) (Result, error)
88	Supports(feature identity.Identity) bool
89}
90
91// Result represents the minimum returned from Convert.
92type Result interface {
93	Bytes() []byte
94}
95
96// DocumentInfo holds additional information provided by some converters.
97type DocumentInfo interface {
98	AnchorSuffix() string
99}
100
101// TableOfContentsProvider provides the content as a ToC structure.
102type TableOfContentsProvider interface {
103	TableOfContents() tableofcontents.Root
104}
105
106// AnchorNameSanitizer tells how a converter sanitizes anchor names.
107type AnchorNameSanitizer interface {
108	SanitizeAnchorName(s string) string
109}
110
111// Bytes holds a byte slice and implements the Result interface.
112type Bytes []byte
113
114// Bytes returns itself
115func (b Bytes) Bytes() []byte {
116	return b
117}
118
119// DocumentContext holds contextual information about the document to convert.
120type DocumentContext struct {
121	Document        interface{} // May be nil. Usually a page.Page
122	DocumentID      string
123	DocumentName    string
124	Filename        string
125	ConfigOverrides map[string]interface{}
126}
127
128// RenderContext holds contextual information about the content to render.
129type RenderContext struct {
130	Src         []byte
131	RenderTOC   bool
132	RenderHooks hooks.Renderers
133}
134
135var FeatureRenderHooks = identity.NewPathIdentity("markup", "renderingHooks")
136