mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-30 07:32:16 -05:00
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
This commit is contained in:
parent
fbcda03029
commit
358dcce7a6
4 changed files with 58 additions and 1 deletions
|
@ -230,6 +230,8 @@ func RenderBytesWithTOC(ctx *RenderingContext) []byte {
|
||||||
return markdownRenderWithTOC(ctx)
|
return markdownRenderWithTOC(ctx)
|
||||||
case "markdown":
|
case "markdown":
|
||||||
return markdownRenderWithTOC(ctx)
|
return markdownRenderWithTOC(ctx)
|
||||||
|
case "asciidoc":
|
||||||
|
return []byte(GetAsciidocContent(ctx.Content))
|
||||||
case "rst":
|
case "rst":
|
||||||
return []byte(GetRstContent(ctx.Content))
|
return []byte(GetRstContent(ctx.Content))
|
||||||
}
|
}
|
||||||
|
@ -242,6 +244,8 @@ func RenderBytes(ctx *RenderingContext) []byte {
|
||||||
return markdownRender(ctx)
|
return markdownRender(ctx)
|
||||||
case "markdown":
|
case "markdown":
|
||||||
return markdownRender(ctx)
|
return markdownRender(ctx)
|
||||||
|
case "asciidoc":
|
||||||
|
return []byte(GetAsciidocContent(ctx.Content))
|
||||||
case "rst":
|
case "rst":
|
||||||
return []byte(GetRstContent(ctx.Content))
|
return []byte(GetRstContent(ctx.Content))
|
||||||
}
|
}
|
||||||
|
@ -299,6 +303,39 @@ func TruncateWordsToWholeSentence(words []string, max int) (string, bool) {
|
||||||
return strings.Join(words[:max], " "), true
|
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
|
// GetRstContent calls the Python script rst2html as an external helper
|
||||||
// to convert reStructuredText content to HTML.
|
// to convert reStructuredText content to HTML.
|
||||||
func GetRstContent(content []byte) string {
|
func GetRstContent(content []byte) string {
|
||||||
|
|
|
@ -63,6 +63,8 @@ func GuessType(in string) string {
|
||||||
switch strings.ToLower(in) {
|
switch strings.ToLower(in) {
|
||||||
case "md", "markdown", "mdown":
|
case "md", "markdown", "mdown":
|
||||||
return "markdown"
|
return "markdown"
|
||||||
|
case "asciidoc", "adoc", "ad":
|
||||||
|
return "asciidoc"
|
||||||
case "rst":
|
case "rst":
|
||||||
return "rst"
|
return "rst"
|
||||||
case "html", "htm":
|
case "html", "htm":
|
||||||
|
|
|
@ -15,6 +15,9 @@ func TestGuessType(t *testing.T) {
|
||||||
{"md", "markdown"},
|
{"md", "markdown"},
|
||||||
{"markdown", "markdown"},
|
{"markdown", "markdown"},
|
||||||
{"mdown", "markdown"},
|
{"mdown", "markdown"},
|
||||||
|
{"asciidoc", "asciidoc"},
|
||||||
|
{"adoc", "asciidoc"},
|
||||||
|
{"ad", "asciidoc"},
|
||||||
{"rst", "rst"},
|
{"rst", "rst"},
|
||||||
{"html", "html"},
|
{"html", "html"},
|
||||||
{"htm", "html"},
|
{"htm", "html"},
|
||||||
|
|
|
@ -95,7 +95,22 @@ func (h asciidocHandler) Extensions() []string { return []string{"asciidoc", "ad
|
||||||
func (h asciidocHandler) PageConvert(p *Page, t tpl.Template) HandledResult {
|
func (h asciidocHandler) PageConvert(p *Page, t tpl.Template) HandledResult {
|
||||||
p.ProcessShortcodes(t)
|
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()
|
//err := p.Convert()
|
||||||
return HandledResult{page: p, err: nil}
|
return HandledResult{page: p, err: nil}
|
||||||
|
|
Loading…
Reference in a new issue