mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-25 22:00:58 +02:00
Prepare for Goldmark
This commmit prepares for the addition of Goldmark as the new Markdown renderer in Hugo. This introduces a new `markup` package with some common interfaces and each implementation in its own package. See #5963
This commit is contained in:
108
markup/internal/blackfriday.go
Normal file
108
markup/internal/blackfriday.go
Normal file
@@ -0,0 +1,108 @@
|
||||
// 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 internal
|
||||
|
||||
import (
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/gohugoio/hugo/markup/converter"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// BlackFriday holds configuration values for BlackFriday rendering.
|
||||
// It is kept here because it's used in several packages.
|
||||
type BlackFriday struct {
|
||||
Smartypants bool
|
||||
SmartypantsQuotesNBSP bool
|
||||
AngledQuotes bool
|
||||
Fractions bool
|
||||
HrefTargetBlank bool
|
||||
NofollowLinks bool
|
||||
NoreferrerLinks bool
|
||||
SmartDashes bool
|
||||
LatexDashes bool
|
||||
TaskLists bool
|
||||
PlainIDAnchors bool
|
||||
Extensions []string
|
||||
ExtensionsMask []string
|
||||
SkipHTML bool
|
||||
|
||||
FootnoteAnchorPrefix string
|
||||
FootnoteReturnLinkContents string
|
||||
}
|
||||
|
||||
func UpdateBlackFriday(old *BlackFriday, m map[string]interface{}) (*BlackFriday, error) {
|
||||
// Create a copy so we can modify it.
|
||||
bf := *old
|
||||
if err := mapstructure.Decode(m, &bf); err != nil {
|
||||
return nil, errors.WithMessage(err, "failed to decode rendering config")
|
||||
}
|
||||
return &bf, nil
|
||||
}
|
||||
|
||||
// NewBlackfriday creates a new Blackfriday filled with site config or some sane defaults.
|
||||
func NewBlackfriday(cfg converter.ProviderConfig) (*BlackFriday, error) {
|
||||
var siteConfig map[string]interface{}
|
||||
if cfg.Cfg != nil {
|
||||
siteConfig = cfg.Cfg.GetStringMap("blackfriday")
|
||||
}
|
||||
|
||||
defaultParam := map[string]interface{}{
|
||||
"smartypants": true,
|
||||
"angledQuotes": false,
|
||||
"smartypantsQuotesNBSP": false,
|
||||
"fractions": true,
|
||||
"hrefTargetBlank": false,
|
||||
"nofollowLinks": false,
|
||||
"noreferrerLinks": false,
|
||||
"smartDashes": true,
|
||||
"latexDashes": true,
|
||||
"plainIDAnchors": true,
|
||||
"taskLists": true,
|
||||
"skipHTML": false,
|
||||
}
|
||||
|
||||
maps.ToLower(defaultParam)
|
||||
|
||||
config := make(map[string]interface{})
|
||||
|
||||
for k, v := range defaultParam {
|
||||
config[k] = v
|
||||
}
|
||||
|
||||
for k, v := range siteConfig {
|
||||
config[k] = v
|
||||
}
|
||||
|
||||
combinedConfig := &BlackFriday{}
|
||||
if err := mapstructure.Decode(config, combinedConfig); err != nil {
|
||||
return nil, errors.Errorf("failed to decode Blackfriday config: %s", err)
|
||||
}
|
||||
|
||||
// TODO(bep) update/consolidate docs
|
||||
if combinedConfig.FootnoteAnchorPrefix == "" {
|
||||
combinedConfig.FootnoteAnchorPrefix = cfg.Cfg.GetString("footnoteAnchorPrefix")
|
||||
}
|
||||
|
||||
if combinedConfig.FootnoteReturnLinkContents == "" {
|
||||
combinedConfig.FootnoteReturnLinkContents = cfg.Cfg.GetString("footnoteReturnLinkContents")
|
||||
}
|
||||
|
||||
return combinedConfig, nil
|
||||
}
|
52
markup/internal/external.go
Normal file
52
markup/internal/external.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/markup/converter"
|
||||
)
|
||||
|
||||
func ExternallyRenderContent(
|
||||
cfg converter.ProviderConfig,
|
||||
ctx converter.DocumentContext,
|
||||
content []byte, path string, args []string) []byte {
|
||||
|
||||
logger := cfg.Logger
|
||||
cmd := exec.Command(path, args...)
|
||||
cmd.Stdin = bytes.NewReader(content)
|
||||
var out, cmderr bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &cmderr
|
||||
err := cmd.Run()
|
||||
// Most external helpers exit w/ non-zero exit code only if severe, i.e.
|
||||
// halting errors occurred. -> log stderr output regardless of state of err
|
||||
for _, item := range strings.Split(cmderr.String(), "\n") {
|
||||
item := strings.TrimSpace(item)
|
||||
if item != "" {
|
||||
logger.ERROR.Printf("%s: %s", ctx.DocumentName, item)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
logger.ERROR.Printf("%s rendering %s: %v", path, ctx.DocumentName, err)
|
||||
}
|
||||
|
||||
return normalizeExternalHelperLineFeeds(out.Bytes())
|
||||
}
|
||||
|
||||
// Strips carriage returns from third-party / external processes (useful for Windows)
|
||||
func normalizeExternalHelperLineFeeds(content []byte) []byte {
|
||||
return bytes.Replace(content, []byte("\r"), []byte(""), -1)
|
||||
}
|
||||
|
||||
func GetPythonExecPath() string {
|
||||
path, err := exec.LookPath("python")
|
||||
if err != nil {
|
||||
path, err = exec.LookPath("python.exe")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
return path
|
||||
}
|
Reference in New Issue
Block a user