109 lines
1.5 KiB
Go
109 lines
1.5 KiB
Go
package html
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"errors"
|
|
"io"
|
|
"unicode"
|
|
)
|
|
|
|
type indentWriter struct {
|
|
out *bufio.Writer
|
|
indent string
|
|
started, lineStarted bool
|
|
err error
|
|
}
|
|
|
|
func indentLen(indent string) int {
|
|
var l int
|
|
r := []rune(indent)
|
|
for _, ri := range r {
|
|
if ri == '\t' {
|
|
l += 8
|
|
continue
|
|
}
|
|
|
|
l++
|
|
}
|
|
|
|
return l
|
|
}
|
|
|
|
func newIndentWriter(out io.Writer, indent string) *indentWriter {
|
|
return &indentWriter{
|
|
out: bufio.NewWriter(out),
|
|
indent: indent,
|
|
}
|
|
}
|
|
|
|
func (w *indentWriter) write(r ...rune) {
|
|
if w.err != nil {
|
|
return
|
|
}
|
|
|
|
for _, ri := range r {
|
|
if _, w.err = w.out.WriteRune(ri); w.err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func (w *indentWriter) Write(p []byte) (int, error) {
|
|
if w.err != nil {
|
|
return 0, w.err
|
|
}
|
|
|
|
if len(p) == 0 {
|
|
return 0, nil
|
|
}
|
|
|
|
runes := bytes.NewBuffer(nil)
|
|
if n, err := runes.Write(p); err != nil {
|
|
w.err = err
|
|
return n, w.err
|
|
}
|
|
|
|
for {
|
|
r, _, err := runes.ReadRune()
|
|
if errors.Is(err, io.EOF) {
|
|
return len(p), nil
|
|
}
|
|
|
|
if err != nil {
|
|
w.err = err
|
|
return len(p), w.err
|
|
}
|
|
|
|
if r == unicode.ReplacementChar {
|
|
continue
|
|
}
|
|
|
|
if r == '\n' {
|
|
w.write('\n')
|
|
w.started = true
|
|
w.lineStarted = false
|
|
continue
|
|
}
|
|
|
|
if w.started && !w.lineStarted {
|
|
w.write([]rune(w.indent)...)
|
|
}
|
|
|
|
w.write(r)
|
|
w.started = true
|
|
w.lineStarted = true
|
|
}
|
|
|
|
return len(p), w.err
|
|
}
|
|
|
|
func (w *indentWriter) Flush() error {
|
|
if w.err != nil {
|
|
return w.err
|
|
}
|
|
|
|
w.err = w.out.Flush()
|
|
return w.err
|
|
}
|