thematic_break.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. package parser
  2. import (
  3. "github.com/yuin/goldmark/ast"
  4. "github.com/yuin/goldmark/text"
  5. "github.com/yuin/goldmark/util"
  6. )
  7. type thematicBreakPraser struct {
  8. }
  9. var defaultThematicBreakPraser = &thematicBreakPraser{}
  10. // NewThematicBreakParser returns a new BlockParser that
  11. // parses thematic breaks.
  12. func NewThematicBreakParser() BlockParser {
  13. return defaultThematicBreakPraser
  14. }
  15. func isThematicBreak(line []byte, offset int) bool {
  16. w, pos := util.IndentWidth(line, offset)
  17. if w > 3 {
  18. return false
  19. }
  20. mark := byte(0)
  21. count := 0
  22. for i := pos; i < len(line); i++ {
  23. c := line[i]
  24. if util.IsSpace(c) {
  25. continue
  26. }
  27. if mark == 0 {
  28. mark = c
  29. count = 1
  30. if mark == '*' || mark == '-' || mark == '_' {
  31. continue
  32. }
  33. return false
  34. }
  35. if c != mark {
  36. return false
  37. }
  38. count++
  39. }
  40. return count > 2
  41. }
  42. func (b *thematicBreakPraser) Trigger() []byte {
  43. return []byte{'-', '*', '_'}
  44. }
  45. func (b *thematicBreakPraser) Open(parent ast.Node, reader text.Reader, pc Context) (ast.Node, State) {
  46. line, segment := reader.PeekLine()
  47. if isThematicBreak(line, reader.LineOffset()) {
  48. reader.Advance(segment.Len() - 1)
  49. return ast.NewThematicBreak(), NoChildren
  50. }
  51. return nil, NoChildren
  52. }
  53. func (b *thematicBreakPraser) Continue(node ast.Node, reader text.Reader, pc Context) State {
  54. return Close
  55. }
  56. func (b *thematicBreakPraser) Close(node ast.Node, reader text.Reader, pc Context) {
  57. // nothing to do
  58. }
  59. func (b *thematicBreakPraser) CanInterruptParagraph() bool {
  60. return true
  61. }
  62. func (b *thematicBreakPraser) CanAcceptIndentedLine() bool {
  63. return false
  64. }