summaryrefslogtreecommitdiffstats
path: root/markup/internal
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2019-08-16 15:55:03 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2019-11-06 19:09:08 +0100
commit5f6b6ec68936ebbbf590894c02a1a3ecad30735f (patch)
treef6c91e225a3f24f51af1bde5cfb5b88515d0665d /markup/internal
parent366ee4d8da1c2b0c1751e9bf6d54638439735296 (diff)
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
Diffstat (limited to 'markup/internal')
-rw-r--r--markup/internal/blackfriday.go108
-rw-r--r--markup/internal/external.go52
2 files changed, 160 insertions, 0 deletions
diff --git a/markup/internal/blackfriday.go b/markup/internal/blackfriday.go
new file mode 100644
index 000000000..373df0c50
--- /dev/null
+++ b/markup/internal/blackfriday.go
@@ -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
+}
diff --git a/markup/internal/external.go b/markup/internal/external.go
new file mode 100644
index 000000000..2105e7cff
--- /dev/null
+++ b/markup/internal/external.go
@@ -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
+}