ref: 358dcce7a6b4a8100964597f81cf371451f6c4d3
parent: fbcda03029ae6ca04253b7008cfd62921baa092a
author: Anthony Fok <foka@debian.org>
date: Fri Jan 23 06:59:14 EST 2015
Experimental AsciiDoc support with external helpers
See #470
* Based on existing support for reStructuredText files
* Handles content files with extensions `.asciidoc` and `.ad`
* Pipes content through `asciidoctor --safe -`.
If `asciidoctor` is not installed, then `asciidoc --safe -`.
* To make sure `asciidoctor` or `asciidoc` is found, after adding
a piece of AsciiDoc content, run `hugo` with the `-v` flag
and look for this message:
INFO: 2015/01/23 Rendering with /usr/bin/asciidoctor ...
Caveats:
* The final "Last updated" timestamp is currently not stripped.
* When `hugo` is run with `-v`, you may see a lot of these messages
INFO: 2015/01/23 Rendering with /usr/bin/asciidoctor ...
if you have lots of `*.ad`, `*.adoc` or `*.asciidoc` files.
* Some versions of `asciidoc` may have trouble with its safe mode.
To test if you are affected, try this:
$ echo "Hello" | asciidoc --safe -
asciidoc: ERROR: unsafe: ifeval invalid
asciidoc: FAILED: ifeval invalid safe document
If so, I recommend that you install `asciidoctor` instead.
Feedback and patches welcome!
Ideally, we should be using https://github.com/VonC/asciidocgo,
@VonC's wonderful Go implementation of Asciidoctor. However,
there is still a bit of work needed for asciidocgo to expose
its API so that Hugo can actually use it.
Until then, hope this "experimental AsciiDoc support through external
helpers" can serve as a stopgap solution for our community. :-)
2015-01-30: Updated for the replaceShortcodeTokens() syntax change
2015-02-21: Add `.adoc` extension as suggested by @Fale
Conflicts:
helpers/content.go
--- a/helpers/content.go
+++ b/helpers/content.go
@@ -230,6 +230,8 @@
return markdownRenderWithTOC(ctx)
case "markdown":
return markdownRenderWithTOC(ctx)
+ case "asciidoc":
+ return []byte(GetAsciidocContent(ctx.Content))
case "rst":
return []byte(GetRstContent(ctx.Content))
}
@@ -242,6 +244,8 @@
return markdownRender(ctx)
case "markdown":
return markdownRender(ctx)
+ case "asciidoc":
+ return []byte(GetAsciidocContent(ctx.Content))
case "rst":
return []byte(GetRstContent(ctx.Content))
}
@@ -297,6 +301,39 @@
}
return strings.Join(words[:max], " "), true
+}
+
+// GetAsciidocContent calls asciidoctor or asciidoc as an external helper
+// to convert AsciiDoc content to HTML.
+func GetAsciidocContent(content []byte) string {+ cleanContent := bytes.Replace(content, SummaryDivider, []byte(""), 1)+
+ path, err := exec.LookPath("asciidoctor")+ if err != nil {+ path, err = exec.LookPath("asciidoc")+ if err != nil {+ jww.ERROR.Println("asciidoctor / asciidoc not found in $PATH: Please install.\n",+ " Leaving AsciiDoc content unrendered.")
+ return (string(content))
+ }
+ }
+
+ jww.INFO.Println("Rendering with", path, "...")+ cmd := exec.Command(path, "--safe", "-")
+ cmd.Stdin = bytes.NewReader(cleanContent)
+ var out bytes.Buffer
+ cmd.Stdout = &out
+ if err := cmd.Run(); err != nil {+ jww.ERROR.Println(err)
+ }
+
+ asciidocLines := strings.Split(out.String(), "\n")
+ for i, line := range asciidocLines {+ if strings.HasPrefix(line, "<body") {+ asciidocLines = (asciidocLines[i+1 : len(asciidocLines)-3])
+ }
+ }
+ return strings.Join(asciidocLines, "\n")
}
// GetRstContent calls the Python script rst2html as an external helper
--- a/helpers/general.go
+++ b/helpers/general.go
@@ -63,6 +63,8 @@
switch strings.ToLower(in) {case "md", "markdown", "mdown":
return "markdown"
+ case "asciidoc", "adoc", "ad":
+ return "asciidoc"
case "rst":
return "rst"
case "html", "htm":
--- a/helpers/general_test.go
+++ b/helpers/general_test.go
@@ -15,6 +15,9 @@
{"md", "markdown"}, {"markdown", "markdown"}, {"mdown", "markdown"},+ {"asciidoc", "asciidoc"},+ {"adoc", "asciidoc"},+ {"ad", "asciidoc"}, {"rst", "rst"}, {"html", "html"}, {"htm", "html"},--- a/hugolib/handler_page.go
+++ b/hugolib/handler_page.go
@@ -95,7 +95,22 @@
func (h asciidocHandler) PageConvert(p *Page, t tpl.Template) HandledResult {p.ProcessShortcodes(t)
- // TODO(spf13) Add Ascii Doc Logic here
+ // TODO(spf13) Add/Refactor AsciiDoc Logic here
+ tmpContent, tmpTableOfContents := helpers.ExtractTOC(p.renderContent(helpers.RemoveSummaryDivider(p.rawContent)))
+
+ if len(p.contentShortCodes) > 0 {+ tmpContentWithTokensReplaced, err := replaceShortcodeTokens(tmpContent, shortcodePlaceholderPrefix, true, p.contentShortCodes)
+
+ if err != nil {+ jww.FATAL.Printf("Fail to replace short code tokens in %s:\n%s", p.BaseFileName(), err.Error())+ return HandledResult{err: err}+ } else {+ tmpContent = tmpContentWithTokensReplaced
+ }
+ }
+
+ p.Content = helpers.BytesToHTML(tmpContent)
+ p.TableOfContents = helpers.BytesToHTML(tmpTableOfContents)
//err := p.Convert()
return HandledResult{page: p, err: nil}--
⑨