gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

strikethrough.go (3376B)


      1 package extension
      2 
      3 import (
      4 	"github.com/yuin/goldmark"
      5 	gast "github.com/yuin/goldmark/ast"
      6 	"github.com/yuin/goldmark/extension/ast"
      7 	"github.com/yuin/goldmark/parser"
      8 	"github.com/yuin/goldmark/renderer"
      9 	"github.com/yuin/goldmark/renderer/html"
     10 	"github.com/yuin/goldmark/text"
     11 	"github.com/yuin/goldmark/util"
     12 )
     13 
     14 type strikethroughDelimiterProcessor struct {
     15 }
     16 
     17 func (p *strikethroughDelimiterProcessor) IsDelimiter(b byte) bool {
     18 	return b == '~'
     19 }
     20 
     21 func (p *strikethroughDelimiterProcessor) CanOpenCloser(opener, closer *parser.Delimiter) bool {
     22 	return opener.Char == closer.Char
     23 }
     24 
     25 func (p *strikethroughDelimiterProcessor) OnMatch(consumes int) gast.Node {
     26 	return ast.NewStrikethrough()
     27 }
     28 
     29 var defaultStrikethroughDelimiterProcessor = &strikethroughDelimiterProcessor{}
     30 
     31 type strikethroughParser struct {
     32 }
     33 
     34 var defaultStrikethroughParser = &strikethroughParser{}
     35 
     36 // NewStrikethroughParser return a new InlineParser that parses
     37 // strikethrough expressions.
     38 func NewStrikethroughParser() parser.InlineParser {
     39 	return defaultStrikethroughParser
     40 }
     41 
     42 func (s *strikethroughParser) Trigger() []byte {
     43 	return []byte{'~'}
     44 }
     45 
     46 func (s *strikethroughParser) Parse(parent gast.Node, block text.Reader, pc parser.Context) gast.Node {
     47 	before := block.PrecendingCharacter()
     48 	line, segment := block.PeekLine()
     49 	node := parser.ScanDelimiter(line, before, 2, defaultStrikethroughDelimiterProcessor)
     50 	if node == nil {
     51 		return nil
     52 	}
     53 	node.Segment = segment.WithStop(segment.Start + node.OriginalLength)
     54 	block.Advance(node.OriginalLength)
     55 	pc.PushDelimiter(node)
     56 	return node
     57 }
     58 
     59 func (s *strikethroughParser) CloseBlock(parent gast.Node, pc parser.Context) {
     60 	// nothing to do
     61 }
     62 
     63 // StrikethroughHTMLRenderer is a renderer.NodeRenderer implementation that
     64 // renders Strikethrough nodes.
     65 type StrikethroughHTMLRenderer struct {
     66 	html.Config
     67 }
     68 
     69 // NewStrikethroughHTMLRenderer returns a new StrikethroughHTMLRenderer.
     70 func NewStrikethroughHTMLRenderer(opts ...html.Option) renderer.NodeRenderer {
     71 	r := &StrikethroughHTMLRenderer{
     72 		Config: html.NewConfig(),
     73 	}
     74 	for _, opt := range opts {
     75 		opt.SetHTMLOption(&r.Config)
     76 	}
     77 	return r
     78 }
     79 
     80 // RegisterFuncs implements renderer.NodeRenderer.RegisterFuncs.
     81 func (r *StrikethroughHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
     82 	reg.Register(ast.KindStrikethrough, r.renderStrikethrough)
     83 }
     84 
     85 // StrikethroughAttributeFilter defines attribute names which dd elements can have.
     86 var StrikethroughAttributeFilter = html.GlobalAttributeFilter
     87 
     88 func (r *StrikethroughHTMLRenderer) renderStrikethrough(w util.BufWriter, source []byte, n gast.Node, entering bool) (gast.WalkStatus, error) {
     89 	if entering {
     90 		if n.Attributes() != nil {
     91 			_, _ = w.WriteString("<del")
     92 			html.RenderAttributes(w, n, StrikethroughAttributeFilter)
     93 			_ = w.WriteByte('>')
     94 		} else {
     95 			_, _ = w.WriteString("<del>")
     96 		}
     97 	} else {
     98 		_, _ = w.WriteString("</del>")
     99 	}
    100 	return gast.WalkContinue, nil
    101 }
    102 
    103 type strikethrough struct {
    104 }
    105 
    106 // Strikethrough is an extension that allow you to use strikethrough expression like '~~text~~' .
    107 var Strikethrough = &strikethrough{}
    108 
    109 func (e *strikethrough) Extend(m goldmark.Markdown) {
    110 	m.Parser().AddOptions(parser.WithInlineParsers(
    111 		util.Prioritized(NewStrikethroughParser(), 500),
    112 	))
    113 	m.Renderer().AddOptions(renderer.WithNodeRenderers(
    114 		util.Prioritized(NewStrikethroughHTMLRenderer(), 500),
    115 	))
    116 }