Calculate block width from BlockStack & RenderContext

This commit is contained in:
Christian Muehlhaeuser
2019-12-07 19:49:24 +01:00
parent 7404a91eb4
commit 71e84251b3
8 changed files with 41 additions and 37 deletions
+7
View File
@@ -51,6 +51,13 @@ func (s BlockStack) Margin() uint {
return i return i
} }
func (s BlockStack) Width(ctx RenderContext) uint {
if s.Indent()+s.Margin()*2 > uint(ctx.options.WordWrap) {
return 0
}
return uint(ctx.options.WordWrap) - s.Indent() - s.Margin()*2
}
func (s BlockStack) Parent() BlockElement { func (s BlockStack) Parent() BlockElement {
if len(s) < 2 { if len(s) < 2 {
return s.Current() return s.Current()
+1
View File
@@ -4,4 +4,5 @@ type RenderContext struct {
style map[StyleType]ElementStyle style map[StyleType]ElementStyle
blockStack *BlockStack blockStack *BlockStack
table *TableElement table *TableElement
options Options
} }
+1 -2
View File
@@ -6,7 +6,6 @@ import (
) )
type DocumentElement struct { type DocumentElement struct {
Width uint
} }
func (e *DocumentElement) Render(w io.Writer, ctx RenderContext) error { func (e *DocumentElement) Render(w io.Writer, ctx RenderContext) error {
@@ -37,7 +36,7 @@ func (e *DocumentElement) Finish(w io.Writer, ctx RenderContext) error {
suffix := rules.Suffix suffix := rules.Suffix
pw := &PaddingWriter{ pw := &PaddingWriter{
Padding: e.Width - margin, Padding: uint(ctx.options.WordWrap) - margin,
PadFunc: func(wr io.Writer) { PadFunc: func(wr io.Writer) {
renderText(w, rules, " ") renderText(w, rules, " ")
}, },
+3 -8
View File
@@ -28,9 +28,7 @@ func (tr *TermRenderer) NewElement(node *bf.Node) Element {
switch node.Type { switch node.Type {
case bf.Document: case bf.Document:
de := &DocumentElement{ de := &DocumentElement{}
Width: uint(tr.WordWrap),
}
return Element{ return Element{
Renderer: de, Renderer: de,
Finisher: de, Finisher: de,
@@ -46,7 +44,6 @@ func (tr *TermRenderer) NewElement(node *bf.Node) Element {
} }
case bf.List: case bf.List:
le := &ListElement{ le := &ListElement{
Width: uint(tr.WordWrap),
Nested: node.Parent.Type == bf.Item, Nested: node.Parent.Type == bf.Item,
} }
return Element{ return Element{
@@ -72,7 +69,6 @@ func (tr *TermRenderer) NewElement(node *bf.Node) Element {
} }
case bf.Paragraph: case bf.Paragraph:
pe := &ParagraphElement{ pe := &ParagraphElement{
Width: uint(tr.WordWrap),
InsideList: node.Parent != nil && node.Parent.Type == bf.Item, InsideList: node.Parent != nil && node.Parent.Type == bf.Item,
} }
return Element{ return Element{
@@ -83,7 +79,6 @@ func (tr *TermRenderer) NewElement(node *bf.Node) Element {
return Element{ return Element{
Exiting: "\n", Exiting: "\n",
Renderer: &HeadingElement{ Renderer: &HeadingElement{
Width: uint(tr.WordWrap),
Text: string(node.FirstChild.Literal), Text: string(node.FirstChild.Literal),
Level: node.HeadingData.Level, Level: node.HeadingData.Level,
First: node.Prev == nil, First: node.Prev == nil,
@@ -126,7 +121,7 @@ func (tr *TermRenderer) NewElement(node *bf.Node) Element {
return Element{ return Element{
Renderer: &LinkElement{ Renderer: &LinkElement{
Text: text, Text: text,
BaseURL: tr.BaseURL, BaseURL: tr.context.options.BaseURL,
URL: string(node.LinkData.Destination), URL: string(node.LinkData.Destination),
}, },
} }
@@ -138,7 +133,7 @@ func (tr *TermRenderer) NewElement(node *bf.Node) Element {
return Element{ return Element{
Renderer: &ImageElement{ Renderer: &ImageElement{
Text: text, Text: text,
BaseURL: tr.BaseURL, BaseURL: tr.context.options.BaseURL,
URL: string(node.LinkData.Destination), URL: string(node.LinkData.Destination),
}, },
} }
+21 -15
View File
@@ -15,10 +15,12 @@ var (
stripper = bluemonday.StrictPolicy() stripper = bluemonday.StrictPolicy()
) )
type TermRenderer struct { type Options struct {
BaseURL string BaseURL string
WordWrap int WordWrap int
}
type TermRenderer struct {
context RenderContext context RenderContext
} }
@@ -27,43 +29,46 @@ func Render(in string, stylePath string) ([]byte, error) {
} }
func RenderBytes(in []byte, stylePath string) ([]byte, error) { func RenderBytes(in []byte, stylePath string) ([]byte, error) {
r, err := NewTermRenderer(stylePath) r, err := NewTermRenderer(stylePath, Options{
WordWrap: 80,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
return r.RenderBytes(in), nil return r.RenderBytes(in), nil
} }
func NewPlainTermRenderer() *TermRenderer { func NewPlainTermRenderer(options Options) *TermRenderer {
return &TermRenderer{} return &TermRenderer{
context: RenderContext{
style: make(map[StyleType]ElementStyle),
blockStack: &BlockStack{},
table: &TableElement{},
options: options,
},
}
} }
func NewTermRenderer(stylePath string) (*TermRenderer, error) { func NewTermRenderer(stylePath string, options Options) (*TermRenderer, error) {
if stylePath == "" { if stylePath == "" {
return NewTermRendererFromBytes([]byte("{}")) return NewTermRendererFromBytes([]byte("{}"), options)
} }
b, err := loadStyle(stylePath) b, err := loadStyle(stylePath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return NewTermRendererFromBytes(b) return NewTermRendererFromBytes(b, options)
} }
func NewTermRendererFromBytes(b []byte) (*TermRenderer, error) { func NewTermRendererFromBytes(b []byte, options Options) (*TermRenderer, error) {
e := make(map[string]ElementStyle) e := make(map[string]ElementStyle)
err := json.Unmarshal(b, &e) err := json.Unmarshal(b, &e)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tr := &TermRenderer{ tr := NewPlainTermRenderer(options)
context: RenderContext{
style: make(map[StyleType]ElementStyle),
blockStack: &BlockStack{},
table: &TableElement{},
},
}
for k, v := range e { for k, v := range e {
t, err := keyToType(k) t, err := keyToType(k)
if err != nil { if err != nil {
@@ -72,6 +77,7 @@ func NewTermRendererFromBytes(b []byte) (*TermRenderer, error) {
} }
tr.context.style[t] = v tr.context.style[t] = v
} }
return tr, nil return tr, nil
} }
+1 -4
View File
@@ -7,7 +7,6 @@ import (
) )
type HeadingElement struct { type HeadingElement struct {
Width uint
Text string Text string
Level int Level int
First bool First bool
@@ -51,9 +50,7 @@ func (e *HeadingElement) Render(w io.Writer, ctx RenderContext) error {
}, },
} }
flow := reflow.NewReflow(int(e.Width) - flow := reflow.NewReflow(int(bs.Width(ctx) - indent - margin*2))
int(indent) - int(margin*2) -
int(bs.Indent()) - int(bs.Margin())*2)
var pre string var pre string
if !e.First { if !e.First {
+4 -4
View File
@@ -8,7 +8,6 @@ import (
) )
type ListElement struct { type ListElement struct {
Width uint
Nested bool Nested bool
} }
@@ -39,11 +38,12 @@ func (e *ListElement) Finish(w io.Writer, ctx RenderContext) error {
if rules.Margin != nil { if rules.Margin != nil {
margin = *rules.Margin margin = *rules.Margin
} }
suffix := rules.Suffix suffix := rules.Suffix
renderText(bs.Current().Block, rules, suffix) renderText(bs.Current().Block, rules, suffix)
pw := &PaddingWriter{ pw := &PaddingWriter{
Padding: uint(int(e.Width) - int(bs.Indent()) - int(bs.Margin()*2)), Padding: bs.Width(ctx),
PadFunc: func(wr io.Writer) { PadFunc: func(wr io.Writer) {
renderText(w, rules, " ") renderText(w, rules, " ")
}, },
@@ -61,8 +61,8 @@ func (e *ListElement) Finish(w io.Writer, ctx RenderContext) error {
}, },
} }
_, err := iw.Write(reflow.Bytes(bs.Current().Block.Bytes(), _, err := iw.Write(
int(e.Width)-int(bs.Indent())-int(bs.Margin())*2)) reflow.Bytes(bs.Current().Block.Bytes(), int(bs.Width(ctx))))
if err != nil { if err != nil {
return err return err
} }
+3 -4
View File
@@ -9,7 +9,6 @@ import (
) )
type ParagraphElement struct { type ParagraphElement struct {
Width uint
InsideList bool InsideList bool
} }
@@ -53,12 +52,12 @@ func (e *ParagraphElement) Finish(w io.Writer, ctx RenderContext) error {
if rules.Margin != nil { if rules.Margin != nil {
margin = *rules.Margin margin = *rules.Margin
} }
suffix := rules.Suffix
suffix := rules.Suffix
renderText(bs.Current().Block, rules, suffix) renderText(bs.Current().Block, rules, suffix)
pw := &PaddingWriter{ pw := &PaddingWriter{
Padding: uint(int(e.Width) - int(bs.Indent()) - int(bs.Margin()*2)), Padding: bs.Width(ctx),
PadFunc: func(wr io.Writer) { PadFunc: func(wr io.Writer) {
renderText(w, rules, " ") renderText(w, rules, " ")
}, },
@@ -77,7 +76,7 @@ func (e *ParagraphElement) Finish(w io.Writer, ctx RenderContext) error {
} }
if len(strings.TrimSpace(bs.Current().Block.String())) > 0 { if len(strings.TrimSpace(bs.Current().Block.String())) > 0 {
flow := reflow.NewReflow(int(e.Width) - int(bs.Indent()) - int(bs.Margin())*2) flow := reflow.NewReflow(int(bs.Width(ctx)))
flow.KeepNewlines = keepNewlines flow.KeepNewlines = keepNewlines
_, _ = flow.Write(bs.Current().Block.Bytes()) _, _ = flow.Write(bs.Current().Block.Bytes())
flow.Close() flow.Close()