Very experimental support for mmark

Either name the content files as `*.mmark`,
or add `markup = "mmark"` in the front matter
of your `*.md` content files.
This commit is contained in:
Anthony Fok 2015-01-30 07:17:50 -07:00 committed by spf13
parent d4acacd4f5
commit 563a6302a0
4 changed files with 109 additions and 4 deletions

View file

@ -22,6 +22,7 @@ import (
"html/template" "html/template"
"os/exec" "os/exec"
"github.com/miekg/mmark"
"github.com/russross/blackfriday" "github.com/russross/blackfriday"
bp "github.com/spf13/hugo/bufferpool" bp "github.com/spf13/hugo/bufferpool"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
@ -74,6 +75,19 @@ var blackfridayExtensionMap = map[string]int{
var stripHTMLReplacer = strings.NewReplacer("\n", " ", "</p>", "\n", "<br>", "\n", "<br />", "\n") var stripHTMLReplacer = strings.NewReplacer("\n", " ", "</p>", "\n", "<br>", "\n", "<br />", "\n")
var mmarkExtensionMap = map[string]int{
"tables": mmark.EXTENSION_TABLES,
"fencedCode": mmark.EXTENSION_FENCED_CODE,
"autolink": mmark.EXTENSION_AUTOLINK,
"laxHtmlBlocks": mmark.EXTENSION_LAX_HTML_BLOCKS,
"spaceHeaders": mmark.EXTENSION_SPACE_HEADERS,
"hardLineBreak": mmark.EXTENSION_HARD_LINE_BREAK,
"footnotes": mmark.EXTENSION_FOOTNOTES,
"noEmptyLineBeforeBlock": mmark.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK,
"headerIds": mmark.EXTENSION_HEADER_IDS,
"autoHeaderIds": mmark.EXTENSION_AUTO_HEADER_IDS,
}
// StripHTML accepts a string, strips out all HTML tags and returns it. // StripHTML accepts a string, strips out all HTML tags and returns it.
func StripHTML(s string) string { func StripHTML(s string) string {
@ -174,6 +188,61 @@ func markdownRenderWithTOC(ctx *RenderingContext) []byte {
getMarkdownExtensions(ctx)) getMarkdownExtensions(ctx))
} }
// mmark
func GetMmarkHtmlRenderer(defaultFlags int, ctx *RenderingContext) mmark.Renderer {
renderParameters := mmark.HtmlRendererParameters{
FootnoteAnchorPrefix: viper.GetString("FootnoteAnchorPrefix"),
FootnoteReturnLinkContents: viper.GetString("FootnoteReturnLinkContents"),
}
b := len(ctx.DocumentID) != 0
if b && !ctx.getConfig().PlainIDAnchors {
renderParameters.FootnoteAnchorPrefix = ctx.DocumentID + ":" + renderParameters.FootnoteAnchorPrefix
// renderParameters.HeaderIDSuffix = ":" + ctx.DocumentId
}
htmlFlags := defaultFlags
htmlFlags |= mmark.HTML_FOOTNOTE_RETURN_LINKS
return mmark.HtmlRendererWithParameters(htmlFlags, "", "", renderParameters)
}
func GetMmarkExtensions(ctx RenderingContext) int {
flags := 0
flags |= mmark.EXTENSION_TABLES
flags |= mmark.EXTENSION_FENCED_CODE
flags |= mmark.EXTENSION_AUTOLINK
flags |= mmark.EXTENSION_SPACE_HEADERS
flags |= mmark.EXTENSION_CITATION
flags |= mmark.EXTENSION_TITLEBLOCK_TOML
flags |= mmark.EXTENSION_HEADER_IDS
flags |= mmark.EXTENSION_AUTO_HEADER_IDS
flags |= mmark.EXTENSION_UNIQUE_HEADER_IDS
flags |= mmark.EXTENSION_FOOTNOTES
flags |= mmark.EXTENSION_SHORT_REF
flags |= mmark.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK
flags |= mmark.EXTENSION_INCLUDE
for _, extension := range ctx.getConfig().Extensions {
if flag, ok := mmarkExtensionMap[extension]; ok {
flags |= flag
}
}
return flags
}
func MmarkRender(ctx *RenderingContext) []byte {
return mmark.Parse(ctx.Content, GetMmarkHtmlRenderer(0, ctx),
GetMmarkExtensions(*ctx)).Bytes()
}
func MmarkRenderWithTOC(ctx *RenderingContext) []byte {
return mmark.Parse(ctx.Content,
GetMmarkHtmlRenderer(0, ctx),
GetMmarkExtensions(*ctx)).Bytes()
}
// ExtractTOC extracts Table of Contents from content. // ExtractTOC extracts Table of Contents from content.
func ExtractTOC(content []byte) (newcontent []byte, toc []byte) { func ExtractTOC(content []byte) (newcontent []byte, toc []byte) {
origContent := make([]byte, len(content)) origContent := make([]byte, len(content))
@ -238,6 +307,8 @@ func RenderBytesWithTOC(ctx *RenderingContext) []byte {
return markdownRenderWithTOC(ctx) return markdownRenderWithTOC(ctx)
case "asciidoc": case "asciidoc":
return []byte(GetAsciidocContent(ctx.Content)) return []byte(GetAsciidocContent(ctx.Content))
case "mmark":
return MmarkRenderWithTOC(ctx)
case "rst": case "rst":
return []byte(GetRstContent(ctx.Content)) return []byte(GetRstContent(ctx.Content))
} }
@ -252,6 +323,8 @@ func RenderBytes(ctx *RenderingContext) []byte {
return markdownRender(ctx) return markdownRender(ctx)
case "asciidoc": case "asciidoc":
return []byte(GetAsciidocContent(ctx.Content)) return []byte(GetAsciidocContent(ctx.Content))
case "mmark":
return MmarkRender(ctx)
case "rst": case "rst":
return []byte(GetRstContent(ctx.Content)) return []byte(GetRstContent(ctx.Content))
} }

View file

@ -19,16 +19,17 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"github.com/spf13/cast"
bp "github.com/spf13/hugo/bufferpool"
jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/viper"
"io" "io"
"net" "net"
"path/filepath" "path/filepath"
"reflect" "reflect"
"strings" "strings"
"sync" "sync"
"github.com/spf13/cast"
bp "github.com/spf13/hugo/bufferpool"
jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/viper"
) )
// Filepath separator defined by os.Separator. // Filepath separator defined by os.Separator.
@ -66,6 +67,8 @@ func GuessType(in string) string {
return "markdown" return "markdown"
case "asciidoc", "adoc", "ad": case "asciidoc", "adoc", "ad":
return "asciidoc" return "asciidoc"
case "mmark":
return "mmark"
case "rst": case "rst":
return "rst" return "rst"
case "html", "htm": case "html", "htm":

View file

@ -21,6 +21,7 @@ func TestGuessType(t *testing.T) {
{"adoc", "asciidoc"}, {"adoc", "asciidoc"},
{"ad", "asciidoc"}, {"ad", "asciidoc"},
{"rst", "rst"}, {"rst", "rst"},
{"mmark", "mmark"},
{"html", "html"}, {"html", "html"},
{"htm", "html"}, {"htm", "html"},
{"excel", "unknown"}, {"excel", "unknown"},

View file

@ -25,6 +25,7 @@ func init() {
RegisterHandler(new(htmlHandler)) RegisterHandler(new(htmlHandler))
RegisterHandler(new(asciidocHandler)) RegisterHandler(new(asciidocHandler))
RegisterHandler(new(rstHandler)) RegisterHandler(new(rstHandler))
RegisterHandler(new(mmarkHandler))
} }
type basicPageHandler Handle type basicPageHandler Handle
@ -156,3 +157,30 @@ func (h rstHandler) PageConvert(p *Page, t tpl.Template) HandledResult {
return HandledResult{err: nil} return HandledResult{err: nil}
} }
type mmarkHandler struct {
basicPageHandler
}
func (h mmarkHandler) Extensions() []string { return []string{"mmark"} }
func (h mmarkHandler) PageConvert(p *Page, t tpl.Template) HandledResult {
p.ProcessShortcodes(t)
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)
return HandledResult{err: nil}
}