// Copyright 2019 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package helpers implements general utility functions that work with // and on content. The helper functions defined here lay down the // foundation of how Hugo works with files and filepaths, and perform // string operations on content. package helpers import ( "bytes" "html/template" "strings" "unicode" "unicode/utf8" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/loggers" "github.com/spf13/afero" "github.com/gohugoio/hugo/markup/converter" "github.com/gohugoio/hugo/markup" "github.com/gohugoio/hugo/config" ) var ( openingPTag = []byte("

") closingPTag = []byte("

") ) // ContentSpec provides functionality to render markdown content. type ContentSpec struct { Converters markup.ConverterProvider anchorNameSanitizer converter.AnchorNameSanitizer Cfg config.AllProvider } // NewContentSpec returns a ContentSpec initialized // with the appropriate fields from the given config.Provider. func NewContentSpec(cfg config.AllProvider, logger loggers.Logger, contentFs afero.Fs, ex *hexec.Exec) (*ContentSpec, error) { spec := &ContentSpec{ Cfg: cfg, } converterProvider, err := markup.NewConverterProvider(converter.ProviderConfig{ Conf: cfg, ContentFs: contentFs, Logger: logger, Exec: ex, }) if err != nil { return nil, err } spec.Converters = converterProvider p := converterProvider.Get("markdown") conv, err := p.New(converter.DocumentContext{}) if err != nil { return nil, err } if as, ok := conv.(converter.AnchorNameSanitizer); ok { spec.anchorNameSanitizer = as } else { // Use Goldmark's sanitizer p := converterProvider.Get("goldmark") conv, err := p.New(converter.DocumentContext{}) if err != nil { return nil, err } spec.anchorNameSanitizer = conv.(converter.AnchorNameSanitizer) } return spec, nil } // stripEmptyNav strips out empty