From 2781233e8ad1aeb359b1ecb0c0c3609d94458094 Mon Sep 17 00:00:00 2001 From: Jan-Lukas Else Date: Thu, 20 May 2021 20:18:13 +0200 Subject: [PATCH] Support mark tag markdown syntax --- go.mod | 6 +++-- go.sum | 8 +++---- markdown.go | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c5cf1b6..34a1b3c 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,10 @@ require ( github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de github.com/boombuler/barcode v1.0.1 // indirect github.com/caddyserver/certmagic v0.13.1 + // master github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f + // master github.com/dgraph-io/ristretto v0.0.4-0.20210504190834-0bf2acd73aa3 github.com/elnormous/contenttype v1.0.0 github.com/felixge/httpsnoop v1.0.2 // indirect @@ -54,14 +56,14 @@ require ( github.com/thoas/go-funk v0.8.0 github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 github.com/vcraescu/go-paginator v1.0.1-0.20201114172518-2cfc59fe05c2 - github.com/yuin/goldmark v1.3.5 + github.com/yuin/goldmark v1.3.7 github.com/yuin/goldmark-emoji v1.0.1 go.uber.org/multierr v1.7.0 // indirect go.uber.org/zap v1.16.0 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect golang.org/x/mod v0.4.1 // indirect - golang.org/x/net v0.0.0-20210510120150-4163338589ed + golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 // indirect golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect diff --git a/go.sum b/go.sum index f79a796..95e6a97 100644 --- a/go.sum +++ b/go.sum @@ -345,8 +345,8 @@ github.com/vcraescu/go-paginator v1.0.1-0.20201114172518-2cfc59fe05c2 h1:l5j4nE6 github.com/vcraescu/go-paginator v1.0.1-0.20201114172518-2cfc59fe05c2/go.mod h1:NEDNuq1asYbAeX+uy6w56MDQSFmBQz9k+N9Hy6m4r2U= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.3.7 h1:NSaHgaeJFCtWXCBkBKXw0rhgMuJ0VoE9FB5mWldcrQ4= +github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os= github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -423,8 +423,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I= -golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 h1:ADo5wSpq2gqaCGQWzk7S5vd//0iyyLeAratkEoG5dLE= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/markdown.go b/markdown.go index a45eb2c..7100287 100644 --- a/markdown.go +++ b/markdown.go @@ -14,6 +14,7 @@ import ( "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" ) @@ -87,6 +88,9 @@ type customExtension struct { } func (l *customExtension) Extend(m goldmark.Markdown) { + m.Parser().AddOptions(parser.WithInlineParsers( + util.Prioritized(&markdownMarkParser{}, 500), + )) m.Renderer().AddOptions(renderer.WithNodeRenderers( util.Prioritized(&customRenderer{ absoluteLinks: l.absoluteLinks, @@ -101,6 +105,7 @@ type customRenderer struct { func (c *customRenderer) RegisterFuncs(r renderer.NodeRendererFuncRegisterer) { r.Register(ast.KindLink, c.renderLink) r.Register(ast.KindImage, c.renderImage) + r.Register(kindMarkdownMark, c.renderMarkTag) } func (c *customRenderer) renderLink(w util.BufWriter, _ []byte, node ast.Node, entering bool) (ast.WalkStatus, error) { @@ -160,3 +165,66 @@ func (c *customRenderer) renderImage(w util.BufWriter, source []byte, node ast.N _, _ = w.WriteString(">") return ast.WalkSkipChildren, nil } + +type markdownMark struct { + ast.BaseInline +} + +func (n *markdownMark) Kind() ast.NodeKind { + return kindMarkdownMark +} + +func (n *markdownMark) Dump(source []byte, level int) { + ast.DumpHelper(n, source, level, nil, nil) +} + +type markDelimiterProcessor struct { +} + +func (p *markDelimiterProcessor) IsDelimiter(b byte) bool { + return b == '=' +} + +func (p *markDelimiterProcessor) CanOpenCloser(opener, closer *parser.Delimiter) bool { + return opener.Char == closer.Char +} + +func (p *markDelimiterProcessor) OnMatch(consumes int) ast.Node { + return &markdownMark{} +} + +var defaultMarkDelimiterProcessor = &markDelimiterProcessor{} + +type markdownMarkParser struct { +} + +func (s *markdownMarkParser) Trigger() []byte { + return []byte{'='} +} + +func (s *markdownMarkParser) Parse(parent ast.Node, block text.Reader, pc parser.Context) ast.Node { + before := block.PrecendingCharacter() + line, segment := block.PeekLine() + node := parser.ScanDelimiter(line, before, 2, defaultMarkDelimiterProcessor) + if node == nil { + return nil + } + node.Segment = segment.WithStop(segment.Start + node.OriginalLength) + block.Advance(node.OriginalLength) + pc.PushDelimiter(node) + return node +} + +func (s *markdownMarkParser) CloseBlock(parent ast.Node, pc parser.Context) { +} + +var kindMarkdownMark = ast.NewNodeKind("Mark") + +func (c *customRenderer) renderMarkTag(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) { + if entering { + _, _ = w.WriteString("") + } else { + _, _ = w.WriteString("") + } + return ast.WalkContinue, nil +}