1
0
html/indent.go
2025-10-06 00:37:10 +02:00

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
}