github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/markup/mmark/convert.go (about)

     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  
    14  // Package mmark converts Markdown to HTML using MMark v1.
    15  package mmark
    16  
    17  import (
    18  	"github.com/gohugoio/hugo/identity"
    19  	"github.com/gohugoio/hugo/markup/blackfriday/blackfriday_config"
    20  	"github.com/gohugoio/hugo/markup/converter"
    21  	"github.com/miekg/mmark"
    22  )
    23  
    24  // Provider is the package entry point.
    25  var Provider converter.ProviderProvider = provider{}
    26  
    27  type provider struct {
    28  }
    29  
    30  func (p provider) New(cfg converter.ProviderConfig) (converter.Provider, error) {
    31  	defaultBlackFriday := cfg.MarkupConfig.BlackFriday
    32  	defaultExtensions := getMmarkExtensions(defaultBlackFriday)
    33  
    34  	return converter.NewProvider("mmark", func(ctx converter.DocumentContext) (converter.Converter, error) {
    35  		b := defaultBlackFriday
    36  		extensions := defaultExtensions
    37  
    38  		if ctx.ConfigOverrides != nil {
    39  			var err error
    40  			b, err = blackfriday_config.UpdateConfig(b, ctx.ConfigOverrides)
    41  			if err != nil {
    42  				return nil, err
    43  			}
    44  			extensions = getMmarkExtensions(b)
    45  		}
    46  
    47  		return &mmarkConverter{
    48  			ctx:        ctx,
    49  			b:          b,
    50  			extensions: extensions,
    51  			cfg:        cfg,
    52  		}, nil
    53  	}), nil
    54  }
    55  
    56  type mmarkConverter struct {
    57  	ctx        converter.DocumentContext
    58  	extensions int
    59  	b          blackfriday_config.Config
    60  	cfg        converter.ProviderConfig
    61  }
    62  
    63  func (c *mmarkConverter) Convert(ctx converter.RenderContext) (converter.Result, error) {
    64  	r := getHTMLRenderer(c.ctx, c.b, c.cfg)
    65  	return mmark.Parse(ctx.Src, r, c.extensions), nil
    66  }
    67  
    68  func (c *mmarkConverter) Supports(feature identity.Identity) bool {
    69  	return false
    70  }
    71  
    72  func getHTMLRenderer(
    73  	ctx converter.DocumentContext,
    74  	cfg blackfriday_config.Config,
    75  	pcfg converter.ProviderConfig) mmark.Renderer {
    76  	var (
    77  		flags      int
    78  		documentID string
    79  	)
    80  
    81  	documentID = ctx.DocumentID
    82  
    83  	renderParameters := mmark.HtmlRendererParameters{
    84  		FootnoteAnchorPrefix:       cfg.FootnoteAnchorPrefix,
    85  		FootnoteReturnLinkContents: cfg.FootnoteReturnLinkContents,
    86  	}
    87  
    88  	if documentID != "" && !cfg.PlainIDAnchors {
    89  		renderParameters.FootnoteAnchorPrefix = documentID + ":" + renderParameters.FootnoteAnchorPrefix
    90  	}
    91  
    92  	htmlFlags := flags
    93  	htmlFlags |= mmark.HTML_FOOTNOTE_RETURN_LINKS
    94  
    95  	return &mmarkRenderer{
    96  		BlackfridayConfig: cfg,
    97  		Config:            pcfg,
    98  		Renderer:          mmark.HtmlRendererWithParameters(htmlFlags, "", "", renderParameters),
    99  	}
   100  }
   101  
   102  func getMmarkExtensions(cfg blackfriday_config.Config) int {
   103  	flags := 0
   104  	flags |= mmark.EXTENSION_TABLES
   105  	flags |= mmark.EXTENSION_FENCED_CODE
   106  	flags |= mmark.EXTENSION_AUTOLINK
   107  	flags |= mmark.EXTENSION_SPACE_HEADERS
   108  	flags |= mmark.EXTENSION_CITATION
   109  	flags |= mmark.EXTENSION_TITLEBLOCK_TOML
   110  	flags |= mmark.EXTENSION_HEADER_IDS
   111  	flags |= mmark.EXTENSION_AUTO_HEADER_IDS
   112  	flags |= mmark.EXTENSION_UNIQUE_HEADER_IDS
   113  	flags |= mmark.EXTENSION_FOOTNOTES
   114  	flags |= mmark.EXTENSION_SHORT_REF
   115  	flags |= mmark.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK
   116  	flags |= mmark.EXTENSION_INCLUDE
   117  
   118  	for _, extension := range cfg.Extensions {
   119  		if flag, ok := mmarkExtensionMap[extension]; ok {
   120  			flags |= flag
   121  		}
   122  	}
   123  	return flags
   124  }
   125  
   126  var mmarkExtensionMap = map[string]int{
   127  	"tables":                 mmark.EXTENSION_TABLES,
   128  	"fencedCode":             mmark.EXTENSION_FENCED_CODE,
   129  	"autolink":               mmark.EXTENSION_AUTOLINK,
   130  	"laxHtmlBlocks":          mmark.EXTENSION_LAX_HTML_BLOCKS,
   131  	"spaceHeaders":           mmark.EXTENSION_SPACE_HEADERS,
   132  	"hardLineBreak":          mmark.EXTENSION_HARD_LINE_BREAK,
   133  	"footnotes":              mmark.EXTENSION_FOOTNOTES,
   134  	"noEmptyLineBeforeBlock": mmark.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK,
   135  	"headerIds":              mmark.EXTENSION_HEADER_IDS,
   136  	"autoHeaderIds":          mmark.EXTENSION_AUTO_HEADER_IDS,
   137  }