···
"github.com/yuin/goldmark"
9
+
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/parser"
12
+
"github.com/yuin/goldmark/text"
13
+
"github.com/yuin/goldmark/util"
12
-
func RenderMarkdown(source string) string {
16
+
// RendererType defines the type of renderer to use based on context
17
+
type RendererType int
20
+
// RendererTypeRepoMarkdown is for repository documentation markdown files
21
+
RendererTypeRepoMarkdown RendererType = iota
22
+
// RendererTypeIssueComment is for issue comments
23
+
RendererTypeIssueComment
24
+
// RendererTypePullComment is for pull request comments
25
+
RendererTypePullComment
26
+
// RendererTypeDefault is the default renderer with minimal transformations
30
+
// RenderContext holds the contextual data for rendering markdown.
31
+
// It can be initialized empty, and that'll skip any transformations
32
+
// and use the default renderer (RendererTypeDefault).
33
+
type RenderContext struct {
36
+
RendererType RendererType
39
+
func (rctx *RenderContext) RenderMarkdown(source string) string {
goldmark.WithExtensions(extension.GFM),
goldmark.WithParserOptions(
parser.WithAutoHeadingID(),
48
+
var transformers []util.PrioritizedValue
50
+
transformers = append(transformers, util.Prioritized(&MarkdownTransformer{rctx: rctx}, 10000))
52
+
md.Parser().AddOptions(
53
+
parser.WithASTTransformers(transformers...),
if err := md.Convert([]byte(source), &buf); err != nil {
64
+
type MarkdownTransformer struct {
68
+
func (a *MarkdownTransformer) Transform(node *ast.Document, reader text.Reader, pc parser.Context) {
69
+
_ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
71
+
return ast.WalkContinue, nil
74
+
switch a.rctx.RendererType {
75
+
case RendererTypeRepoMarkdown:
76
+
a.rctx.relativeLinkTransformer(n.(*ast.Link))
77
+
case RendererTypeDefault:
78
+
a.rctx.relativeLinkTransformer(n.(*ast.Link))
79
+
// more types here like RendererTypeIssue/Pull etc.
82
+
return ast.WalkContinue, nil
86
+
func (rctx *RenderContext) relativeLinkTransformer(link *ast.Link) {
87
+
dst := string(link.Destination)
89
+
if len(dst) == 0 || dst[0] == '#' ||
90
+
bytes.Contains(link.Destination, []byte("://")) ||
91
+
bytes.HasPrefix(link.Destination, []byte("mailto:")) {
95
+
newPath := path.Join("/", rctx.FullRepoName, "tree", rctx.Ref, dst)
96
+
link.Destination = []byte(newPath)