Skip to content

Commit

Permalink
Experimental AsciiDoc support with external helpers
Browse files Browse the repository at this point in the history
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
  • Loading branch information
anthonyfok authored and spf13 committed Mar 13, 2015
1 parent fbcda03 commit 358dcce
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 1 deletion.
37 changes: 37 additions & 0 deletions helpers/content.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ func RenderBytesWithTOC(ctx *RenderingContext) []byte {
return markdownRenderWithTOC(ctx)
case "markdown":
return markdownRenderWithTOC(ctx)
case "asciidoc":
return []byte(GetAsciidocContent(ctx.Content))
case "rst":
return []byte(GetRstContent(ctx.Content))
}
Expand All @@ -242,6 +244,8 @@ func RenderBytes(ctx *RenderingContext) []byte {
return markdownRender(ctx)
case "markdown":
return markdownRender(ctx)
case "asciidoc":
return []byte(GetAsciidocContent(ctx.Content))
case "rst":
return []byte(GetRstContent(ctx.Content))
}
Expand Down Expand Up @@ -299,6 +303,39 @@ func TruncateWordsToWholeSentence(words []string, max int) (string, bool) {
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
// to convert reStructuredText content to HTML.
func GetRstContent(content []byte) string {
Expand Down
2 changes: 2 additions & 0 deletions helpers/general.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ func GuessType(in string) string {
switch strings.ToLower(in) {
case "md", "markdown", "mdown":
return "markdown"
case "asciidoc", "adoc", "ad":
return "asciidoc"
case "rst":
return "rst"
case "html", "htm":
Expand Down
3 changes: 3 additions & 0 deletions helpers/general_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ func TestGuessType(t *testing.T) {
{"md", "markdown"},
{"markdown", "markdown"},
{"mdown", "markdown"},
{"asciidoc", "asciidoc"},
{"adoc", "asciidoc"},
{"ad", "asciidoc"},
{"rst", "rst"},
{"html", "html"},
{"htm", "html"},
Expand Down
17 changes: 16 additions & 1 deletion hugolib/handler_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,22 @@ func (h asciidocHandler) Extensions() []string { return []string{"asciidoc", "ad
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}
Expand Down

0 comments on commit 358dcce

Please sign in to comment.