mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
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:
parent
d4acacd4f5
commit
563a6302a0
4 changed files with 109 additions and 4 deletions
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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":
|
||||||
|
|
|
@ -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"},
|
||||||
|
|
|
@ -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}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue