Files
438c5a5cfa feat: markdown renderer (#10682)
* chore: custom notifiers in alert manager

* chore: lint fixs

* chore: fix email linter

* chore: added tracing to msteamsv2 notifier

* feat: alert manager template to template title and notification body

* chore: updated test name + code for timeout errors

* chore: added utils for using variables with $ notation

* chore: exposed templates for alertmanager types

* feat: added preprocessor for alert templater

* chore: hooked preProcess function in expandTitle and body, added labels and annotations in alertdata

* chore: fix lint issues

* chore: added handling for missing variable used in template

* feat: converted alerttemplater to interface and updated tests

* refactor: added extractCommonKV instead of 2 different functions

* test: fix preprocessor test case

* feat: added support for  and  in templating

* chore: lint fix

* chore: renamed the interface

* chore: added test for missing function

* refactor: test case and sb related changed

* refactor: comments and test improvements

* chore: lint fix

* chore: updated comments

* feat: added basic html markdown templater

* chore: updated newline to markdown format

* feat: slack blockkit renderer using goldmark

* test: added test for html rendering

* feat: integrated slack blockit in markdownrenderer package and removed plaintext format

* chore: updated br with new line in test and logs added

* refactor: review comments

* refactor: lint fixes

* chore: updated licenses for notifiers

* chore: updated email notifier from upstream

* feat: return single templating result from  with flag for template type

* fix: variables with symbols in template

* feat: slack mrkdwn renderer

* feat: custom raw html renderer to escape <no value>

* chore: integrated slack mrkdwn renderer and added NoOp formatter

* chore: removed notifier test files

* fix: concurrent rendering in markdown renderer

* refactor: changes as per internal review

* chore: lint issue

* chore: removed special handling for softline break

* refactor: removed logger as markdown renderer dependency

* refactor: changed markdown renderer from interface to package-level functions

---------

Co-authored-by: Srikanth Chekuri <[email protected]>
2026-04-22 21:22:45 +00:00

62 lines
1.9 KiB
Go

package markdownrenderer
import (
"github.com/yuin/goldmark"
gast "github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/renderer"
"github.com/yuin/goldmark/renderer/html"
"github.com/yuin/goldmark/util"
)
// Go text/template writes the literal string "<no value>" when a referenced
// key is missing. The default goldmark HTML path treats it as raw HTML and
// drops it, hiding the missing value. This renderer escapes it so operators
// can see which variable was unset in the rendered notification.
type noValueHTMLRenderer struct {
html.Config
}
func newNoValueHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
r := &noValueHTMLRenderer{Config: html.NewConfig()}
for _, opt := range opts {
opt.SetHTMLOption(&r.Config)
}
return r
}
func (r *noValueHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
reg.Register(gast.KindRawHTML, r.renderRawHTML)
}
func (r *noValueHTMLRenderer) renderRawHTML(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
if !entering {
return gast.WalkSkipChildren, nil
}
n := node.(*gast.RawHTML)
if r.Unsafe {
for i := 0; i < n.Segments.Len(); i++ {
segment := n.Segments.At(i)
_, _ = w.Write(segment.Value(source))
}
return gast.WalkSkipChildren, nil
}
if string(n.Segments.Value(source)) == "<no value>" {
_, _ = w.WriteString("&lt;no value&gt;")
return gast.WalkSkipChildren, nil
}
_, _ = w.WriteString("<!-- raw HTML omitted -->")
return gast.WalkSkipChildren, nil
}
type escapeNoValueExtension struct{}
// escapeNoValue renders the literal `<no value>` produced by Go's text/template
// as visible escaped text instead of dropping it as raw HTML.
var escapeNoValue = &escapeNoValueExtension{}
func (e *escapeNoValueExtension) Extend(m goldmark.Markdown) {
m.Renderer().AddOptions(renderer.WithNodeRenderers(
util.Prioritized(newNoValueHTMLRenderer(), 500),
))
}