summaryrefslogtreecommitdiffstats
path: root/markup/goldmark/convert.go
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2022-02-17 13:04:00 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2022-02-24 18:59:50 +0100
commit08fdca9d9365eaf1e496a12e2af5e18617bd0e66 (patch)
tree6c6942d1b74a4160d93a997860bafd52b92025f5 /markup/goldmark/convert.go
parent2c20f5bc00b604e72b3b7e401fbdbf9447fe3470 (diff)
Add Markdown diagrams and render hooks for code blocks
You can now create custom hook templates for code blocks, either one for all (`render-codeblock.html`) or for a given code language (e.g. `render-codeblock-go.html`). We also used this new hook to add support for diagrams in Hugo: * Goat (Go ASCII Tool) is built-in and enabled by default; just create a fenced code block with the language `goat` and start draw your Ascii diagrams. * Another popular alternative for diagrams in Markdown, Mermaid (supported by GitHub), can also be implemented with a simple template. See the Hugo documentation for more information. Updates #7765 Closes #9538 Fixes #9553 Fixes #8520 Fixes #6702 Fixes #9558
Diffstat (limited to 'markup/goldmark/convert.go')
-rw-r--r--markup/goldmark/convert.go146
1 files changed, 12 insertions, 134 deletions
diff --git a/markup/goldmark/convert.go b/markup/goldmark/convert.go
index c547fe1e0..4c1641a0b 100644
--- a/markup/goldmark/convert.go
+++ b/markup/goldmark/convert.go
@@ -17,12 +17,12 @@ package goldmark
import (
"bytes"
"fmt"
- "math/bits"
"path/filepath"
"runtime/debug"
+ "github.com/gohugoio/hugo/markup/goldmark/codeblocks"
"github.com/gohugoio/hugo/markup/goldmark/internal/extensions/attributes"
- "github.com/yuin/goldmark/ast"
+ "github.com/gohugoio/hugo/markup/goldmark/internal/render"
"github.com/gohugoio/hugo/identity"
@@ -32,16 +32,13 @@ import (
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/markup/converter"
- "github.com/gohugoio/hugo/markup/highlight"
"github.com/gohugoio/hugo/markup/tableofcontents"
"github.com/yuin/goldmark"
- hl "github.com/yuin/goldmark-highlighting"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/renderer"
"github.com/yuin/goldmark/renderer/html"
"github.com/yuin/goldmark/text"
- "github.com/yuin/goldmark/util"
)
// Provider is the package entry point.
@@ -104,7 +101,7 @@ func newMarkdown(pcfg converter.ProviderConfig) goldmark.Markdown {
)
if mcfg.Highlight.CodeFences {
- extensions = append(extensions, newHighlighting(mcfg.Highlight))
+ extensions = append(extensions, codeblocks.New())
}
if cfg.Extensions.Table {
@@ -178,65 +175,6 @@ func (c converterResult) GetIdentities() identity.Identities {
return c.ids
}
-type bufWriter struct {
- *bytes.Buffer
-}
-
-const maxInt = 1<<(bits.UintSize-1) - 1
-
-func (b *bufWriter) Available() int {
- return maxInt
-}
-
-func (b *bufWriter) Buffered() int {
- return b.Len()
-}
-
-func (b *bufWriter) Flush() error {
- return nil
-}
-
-type renderContext struct {
- *bufWriter
- positions []int
- renderContextData
-}
-
-func (ctx *renderContext) pushPos(n int) {
- ctx.positions = append(ctx.positions, n)
-}
-
-func (ctx *renderContext) popPos() int {
- i := len(ctx.positions) - 1
- p := ctx.positions[i]
- ctx.positions = ctx.positions[:i]
- return p
-}
-
-type renderContextData interface {
- RenderContext() converter.RenderContext
- DocumentContext() converter.DocumentContext
- AddIdentity(id identity.Provider)
-}
-
-type renderContextDataHolder struct {
- rctx converter.RenderContext
- dctx converter.DocumentContext
- ids identity.Manager
-}
-
-func (ctx *renderContextDataHolder) RenderContext() converter.RenderContext {
- return ctx.rctx
-}
-
-func (ctx *renderContextDataHolder) DocumentContext() converter.DocumentContext {
- return ctx.dctx
-}
-
-func (ctx *renderContextDataHolder) AddIdentity(id identity.Provider) {
- ctx.ids.Add(id)
-}
-
var converterIdentity = identity.KeyValueIdentity{Key: "goldmark", Value: "converter"}
func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result converter.Result, err error) {
@@ -251,7 +189,7 @@ func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result convert
}
}()
- buf := &bufWriter{Buffer: &bytes.Buffer{}}
+ buf := &render.BufWriter{Buffer: &bytes.Buffer{}}
result = buf
pctx := c.newParserContext(ctx)
reader := text.NewReader(ctx.Src)
@@ -261,15 +199,15 @@ func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result convert
parser.WithContext(pctx),
)
- rcx := &renderContextDataHolder{
- rctx: ctx,
- dctx: c.ctx,
- ids: identity.NewManager(converterIdentity),
+ rcx := &render.RenderContextDataHolder{
+ Rctx: ctx,
+ Dctx: c.ctx,
+ IDs: identity.NewManager(converterIdentity),
}
- w := &renderContext{
- bufWriter: buf,
- renderContextData: rcx,
+ w := &render.Context{
+ BufWriter: buf,
+ ContextData: rcx,
}
if err := c.md.Renderer().Render(w, ctx.Src, doc); err != nil {
@@ -278,7 +216,7 @@ func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result convert
return converterResult{
Result: buf,
- ids: rcx.ids.GetIdentities(),
+ ids: rcx.IDs.GetIdentities(),
toc: pctx.TableOfContents(),
}, nil
}
@@ -309,63 +247,3 @@ func (p *parserContext) TableOfContents() tableofcontents.Root {
}
return tableofcontents.Root{}
}
-
-func newHighlighting(cfg highlight.Config) goldmark.Extender {
- return hl.NewHighlighting(
- hl.WithStyle(cfg.Style),
- hl.WithGuessLanguage(cfg.GuessSyntax),
- hl.WithCodeBlockOptions(highlight.GetCodeBlockOptions()),
- hl.WithFormatOptions(
- cfg.ToHTMLOptions()...,
- ),
-
- hl.WithWrapperRenderer(func(w util.BufWriter, ctx hl.CodeBlockContext, entering bool) {
- var language string
- if l, hasLang := ctx.Language(); hasLang {
- language = string(l)
- }
-
- if ctx.Highlighted() {
- if entering {
- writeDivStart(w, ctx)
- } else {
- writeDivEnd(w)
- }
- } else {
- if entering {
- highlight.WritePreStart(w, language, "")
- } else {
- highlight.WritePreEnd(w)
- }
- }
- }),
- )
-}
-
-func writeDivStart(w util.BufWriter, ctx hl.CodeBlockContext) {
- w.WriteString(`<div class="highlight`)
-
- var attributes []ast.Attribute
- if ctx.Attributes() != nil {
- attributes = ctx.Attributes().All()
- }
-
- if attributes != nil {
- class, found := ctx.Attributes().GetString("class")
- if found {
- w.WriteString(" ")
- w.Write(util.EscapeHTML(class.([]byte)))
-
- }
- _, _ = w.WriteString("\"")
- renderAttributes(w, true, attributes...)
- } else {
- _, _ = w.WriteString("\"")
- }
-
- w.WriteString(">")
-}
-
-func writeDivEnd(w util.BufWriter) {
- w.WriteString("</div>")
-}