summaryrefslogtreecommitdiffhomepage
path: root/helpers
diff options
context:
space:
mode:
authorBrian Chen <[email protected]>2017-11-30 06:15:52 -0500
committerBjørn Erik Pedersen <[email protected]>2017-11-30 12:15:52 +0100
commite69da7a4cb725987f153707bf2fc59c135007e2a (patch)
treec3eab00b91bdbc6d4ed2f9da3b43e1c63909f859 /helpers
parente7652180a13ce149041c48a1c2754c471df569c8 (diff)
downloadhugo-e69da7a4cb725987f153707bf2fc59c135007e2a.tar.gz
hugo-e69da7a4cb725987f153707bf2fc59c135007e2a.zip
Add Pandoc support, refactor external helpers
Recognize the Pandoc format under the file extension .pandoc or .pdc, and shell out to pandoc as an external helper to format Pandoc content. Refactor out repeated code with external helpers. Change the error output formatting. I did not see any of the external helpers print the string "<input>" to represent stdin as a file; just prepending the file name to error output is more general and doesn't sacrifice that much in terms of readability. Closes #234
Diffstat (limited to 'helpers')
-rw-r--r--helpers/content.go104
-rw-r--r--helpers/general.go2
-rw-r--r--helpers/general_test.go2
3 files changed, 52 insertions, 56 deletions
diff --git a/helpers/content.go b/helpers/content.go
index a79da090b..b776d0813 100644
--- a/helpers/content.go
+++ b/helpers/content.go
@@ -454,6 +454,8 @@ func (c ContentSpec) RenderBytes(ctx *RenderingContext) []byte {
return getRstContent(ctx)
case "org":
return orgRender(ctx, c)
+ case "pandoc":
+ return getPandocContent(ctx)
}
}
@@ -578,11 +580,6 @@ func getAsciidocExecPath() string {
return path
}
-// HasAsciidoc returns whether Asciidoc is installed on this computer.
-func HasAsciidoc() bool {
- return getAsciidocExecPath() != ""
-}
-
func getAsciidoctorExecPath() string {
path, err := exec.LookPath("asciidoctor")
if err != nil {
@@ -591,17 +588,15 @@ func getAsciidoctorExecPath() string {
return path
}
-// HasAsciidoctor returns whether Asciidoctor is installed on this computer.
-func HasAsciidoctor() bool {
- return getAsciidoctorExecPath() != ""
+// HasAsciidoc returns whether Asciidoc or Asciidoctor is installed on this computer.
+func HasAsciidoc() bool {
+ return (getAsciidoctorExecPath() != "" ||
+ getAsciidocExecPath() != "")
}
// getAsciidocContent calls asciidoctor or asciidoc as an external helper
// to convert AsciiDoc content to HTML.
func getAsciidocContent(ctx *RenderingContext) []byte {
- content := ctx.Content
- cleanContent := bytes.Replace(content, SummaryDivider, []byte(""), 1)
-
var isAsciidoctor bool
path := getAsciidoctorExecPath()
if path == "" {
@@ -609,7 +604,7 @@ func getAsciidocContent(ctx *RenderingContext) []byte {
if path == "" {
jww.ERROR.Println("asciidoctor / asciidoc not found in $PATH: Please install.\n",
" Leaving AsciiDoc content unrendered.")
- return content
+ return ctx.Content
}
} else {
isAsciidoctor = true
@@ -622,25 +617,7 @@ func getAsciidocContent(ctx *RenderingContext) []byte {
args = append(args, "--trace")
}
args = append(args, "-")
- cmd := exec.Command(path, args...)
- cmd.Stdin = bytes.NewReader(cleanContent)
- var out, cmderr bytes.Buffer
- cmd.Stdout = &out
- cmd.Stderr = &cmderr
- err := cmd.Run()
- // asciidoctor has exit code 0 even if there are errors in stderr
- // -> log stderr output regardless of state of err
- for _, item := range strings.Split(string(cmderr.Bytes()), "\n") {
- item := strings.TrimSpace(item)
- if item != "" {
- jww.ERROR.Println(strings.Replace(item, "<stdin>", ctx.DocumentName, 1))
- }
- }
- if err != nil {
- jww.ERROR.Printf("%s rendering %s: %v", path, ctx.DocumentName, err)
- }
-
- return normalizeExternalHelperLineFeeds(out.Bytes())
+ return externallyRenderContent(ctx, path, args)
}
// HasRst returns whether rst2html is installed on this computer.
@@ -673,40 +650,18 @@ func getPythonExecPath() string {
// getRstContent calls the Python script rst2html as an external helper
// to convert reStructuredText content to HTML.
func getRstContent(ctx *RenderingContext) []byte {
- content := ctx.Content
- cleanContent := bytes.Replace(content, SummaryDivider, []byte(""), 1)
-
python := getPythonExecPath()
path := getRstExecPath()
if path == "" {
jww.ERROR.Println("rst2html / rst2html.py not found in $PATH: Please install.\n",
" Leaving reStructuredText content unrendered.")
- return content
+ return ctx.Content
}
-
jww.INFO.Println("Rendering", ctx.DocumentName, "with", path, "...")
- cmd := exec.Command(python, path, "--leave-comments", "--initial-header-level=2")
- cmd.Stdin = bytes.NewReader(cleanContent)
- var out, cmderr bytes.Buffer
- cmd.Stdout = &out
- cmd.Stderr = &cmderr
- err := cmd.Run()
- // By default rst2html exits 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(string(cmderr.Bytes()), "\n") {
- item := strings.TrimSpace(item)
- if item != "" {
- jww.ERROR.Println(strings.Replace(item, "<stdin>", ctx.DocumentName, 1))
- }
- }
- if err != nil {
- jww.ERROR.Printf("%s rendering %s: %v", path, ctx.DocumentName, err)
- }
-
- result := normalizeExternalHelperLineFeeds(out.Bytes())
-
+ args := []string{path, "--leave-comments", "--initial-header-level=2"}
+ result := externallyRenderContent(ctx, python, args)
// TODO(bep) check if rst2html has a body only option.
bodyStart := bytes.Index(result, []byte("<body>\n"))
if bodyStart < 0 {
@@ -724,9 +679,46 @@ func getRstContent(ctx *RenderingContext) []byte {
return result[bodyStart+7 : bodyEnd]
}
+// getPandocContent calls pandoc as an external helper to convert pandoc markdown to HTML.
+func getPandocContent(ctx *RenderingContext) []byte {
+ path, err := exec.LookPath("pandoc")
+ if err != nil {
+ jww.ERROR.Println("pandoc not found in $PATH: Please install.\n",
+ " Leaving pandoc content unrendered.")
+ return ctx.Content
+ }
+ args := []string{"--mathjax"}
+ return externallyRenderContent(ctx, path, args)
+}
+
func orgRender(ctx *RenderingContext, c ContentSpec) []byte {
content := ctx.Content
cleanContent := bytes.Replace(content, []byte("# more"), []byte(""), 1)
return goorgeous.Org(cleanContent,
c.getHTMLRenderer(blackfriday.HTML_TOC, ctx))
}
+
+func externallyRenderContent(ctx *RenderingContext, path string, args []string) []byte {
+ content := ctx.Content
+ cleanContent := bytes.Replace(content, SummaryDivider, []byte(""), 1)
+
+ cmd := exec.Command(path, args...)
+ cmd.Stdin = bytes.NewReader(cleanContent)
+ 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(string(cmderr.Bytes()), "\n") {
+ item := strings.TrimSpace(item)
+ if item != "" {
+ jww.ERROR.Printf("%s: %s", ctx.DocumentName, item)
+ }
+ }
+ if err != nil {
+ jww.ERROR.Printf("%s rendering %s: %v", path, ctx.DocumentName, err)
+ }
+
+ return normalizeExternalHelperLineFeeds(out.Bytes())
+}
diff --git a/helpers/general.go b/helpers/general.go
index a064309d3..4517a3232 100644
--- a/helpers/general.go
+++ b/helpers/general.go
@@ -78,6 +78,8 @@ func GuessType(in string) string {
return "mmark"
case "rst":
return "rst"
+ case "pandoc", "pdc":
+ return "pandoc"
case "html", "htm":
return "html"
case "org":
diff --git a/helpers/general_test.go b/helpers/general_test.go
index 561f59522..2bca632e0 100644
--- a/helpers/general_test.go
+++ b/helpers/general_test.go
@@ -34,6 +34,8 @@ func TestGuessType(t *testing.T) {
{"adoc", "asciidoc"},
{"ad", "asciidoc"},
{"rst", "rst"},
+ {"pandoc", "pandoc"},
+ {"pdc", "pandoc"},
{"mmark", "mmark"},
{"html", "html"},
{"htm", "html"},