github.com/charmbracelet/glamour@v0.7.0/ansi/heading.go (about) 1 package ansi 2 3 import ( 4 "bytes" 5 "io" 6 7 "github.com/muesli/reflow/indent" 8 "github.com/muesli/reflow/wordwrap" 9 ) 10 11 // A HeadingElement is used to render headings. 12 type HeadingElement struct { 13 Level int 14 First bool 15 } 16 17 const ( 18 h1 = iota + 1 19 h2 20 h3 21 h4 22 h5 23 h6 24 ) 25 26 func (e *HeadingElement) Render(w io.Writer, ctx RenderContext) error { 27 bs := ctx.blockStack 28 rules := ctx.options.Styles.Heading 29 30 switch e.Level { 31 case h1: 32 rules = cascadeStyles(rules, ctx.options.Styles.H1) 33 case h2: 34 rules = cascadeStyles(rules, ctx.options.Styles.H2) 35 case h3: 36 rules = cascadeStyles(rules, ctx.options.Styles.H3) 37 case h4: 38 rules = cascadeStyles(rules, ctx.options.Styles.H4) 39 case h5: 40 rules = cascadeStyles(rules, ctx.options.Styles.H5) 41 case h6: 42 rules = cascadeStyles(rules, ctx.options.Styles.H6) 43 } 44 45 if !e.First { 46 renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, "\n") 47 } 48 49 be := BlockElement{ 50 Block: &bytes.Buffer{}, 51 Style: cascadeStyle(bs.Current().Style, rules, false), 52 } 53 bs.Push(be) 54 55 renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, rules.BlockPrefix) 56 renderText(bs.Current().Block, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.Prefix) 57 return nil 58 } 59 60 func (e *HeadingElement) Finish(w io.Writer, ctx RenderContext) error { 61 bs := ctx.blockStack 62 rules := bs.Current().Style 63 64 var indentation uint 65 var margin uint 66 if rules.Indent != nil { 67 indentation = *rules.Indent 68 } 69 if rules.Margin != nil { 70 margin = *rules.Margin 71 } 72 73 iw := indent.NewWriterPipe(w, indentation+margin, func(wr io.Writer) { 74 renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, " ") 75 }) 76 77 flow := wordwrap.NewWriter(int(bs.Width(ctx) - indentation - margin*2)) 78 _, err := flow.Write(bs.Current().Block.Bytes()) 79 if err != nil { 80 return err 81 } 82 flow.Close() 83 84 _, err = iw.Write(flow.Bytes()) 85 if err != nil { 86 return err 87 } 88 89 renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, rules.Suffix) 90 renderText(w, ctx.options.ColorProfile, bs.Parent().Style.StylePrimitive, rules.BlockSuffix) 91 92 bs.Current().Block.Reset() 93 bs.Pop() 94 return nil 95 }