1
0
mirror of https://github.com/danog/liquid.git synced 2024-12-02 16:17:47 +01:00
liquid/render/trimwriter.go

63 lines
1.5 KiB
Go
Raw Normal View History

2017-07-16 23:43:04 +02:00
package render
import (
"bytes"
"io"
"unicode"
)
2017-07-17 00:02:07 +02:00
// A trimWriter provides whitespace control around a wrapped io.Writer.
// The caller should call TrimLeft(bool) and TrimRight(bool) respectively
// before and after processing a tag or expression, and Flush() at completion.
2017-07-16 23:43:04 +02:00
type trimWriter struct {
w io.Writer
2017-07-17 00:02:07 +02:00
buf bytes.Buffer
2017-07-16 23:43:04 +02:00
trimRight bool
}
2017-07-17 00:02:07 +02:00
// This violates the letter of the protocol by returning the count of the
// bytes, rather than the actual number of bytes written. We can't know the
// number of bytes written until later, and it won't in general be the same
// as the argument length (that's the whole point of trimming), but speaking
// truthfully here would cause some callers to return io.ErrShortWrite, ruining
// this as an io.Writer.
2017-07-16 23:43:04 +02:00
func (tw *trimWriter) Write(b []byte) (int, error) {
2017-07-17 00:02:07 +02:00
n := len(b)
2017-07-16 23:43:04 +02:00
if tw.trimRight {
b = bytes.TrimLeftFunc(b, unicode.IsSpace)
2017-07-17 00:02:07 +02:00
} else if tw.buf.Len() > 0 {
if err := tw.Flush(); err != nil {
2017-07-16 23:43:04 +02:00
return 0, err
}
}
nonWS := bytes.TrimRightFunc(b, unicode.IsSpace)
if len(nonWS) < len(b) {
2017-07-17 00:02:07 +02:00
if _, err := tw.buf.Write(b[len(nonWS):]); err != nil {
return 0, err
}
2017-07-16 23:43:04 +02:00
}
2017-07-17 00:02:07 +02:00
_, err := tw.w.Write(nonWS)
return n, err
2017-07-16 23:43:04 +02:00
}
func (tw *trimWriter) Flush() (err error) {
2017-07-17 00:02:07 +02:00
if tw.buf.Len() > 0 {
_, err = tw.buf.WriteTo(tw.w)
tw.buf.Reset()
2017-07-16 23:43:04 +02:00
}
return
}
func (tw *trimWriter) TrimLeft(f bool) {
2017-07-17 00:02:07 +02:00
if !f && tw.buf.Len() > 0 {
2017-07-16 23:43:04 +02:00
if err := tw.Flush(); err != nil {
panic(err)
}
}
2017-07-17 00:02:07 +02:00
tw.buf.Reset()
2017-07-16 23:43:04 +02:00
tw.trimRight = false
}
func (tw *trimWriter) TrimRight(f bool) {
tw.trimRight = f
}