textmachine/backend/internal/bookfile/txt.go

37 lines
1.4 KiB
Go

package bookfile
import (
"io"
"strings"
)
// txt.go: the plain-text book. No audit banners, no flags in brackets, no operator vocabulary — the file
// is prose plus what the model carries: the title first, the notice (when there is one), then every
// chapter as its title line followed by its paragraphs. Blocks are separated by ONE blank line, chapters
// by TWO, so a chapter boundary reads differently from a paragraph boundary even in a viewer that shows
// nothing but text. The file ends with a newline.
//
// The same block list the EPUB renders (Blocks) is what lands here, so the two formats say the same thing —
// cleaned the same way too: every string the EPUB passes through xmlText goes through CleanText here, so
// a control character in a title or a notice cannot reach the text reader when the EPUB reader is spared it.
// WriteTXT writes b as plain UTF-8 text to w. Deterministic.
func WriteTXT(w io.Writer, b *Book) error {
if err := b.validate(); err != nil {
return err
}
var sb strings.Builder
sb.WriteString(strings.TrimSpace(CleanText(b.Title)))
for _, p := range b.Notice {
sb.WriteString("\n\n" + CleanText(p))
}
for _, ch := range b.Chapters {
sb.WriteString("\n\n\n" + CleanText(ch.Title))
for _, p := range ch.Paragraphs {
sb.WriteString("\n\n" + CleanText(p))
}
}
sb.WriteString("\n")
_, err := io.WriteString(w, sb.String())
return err
}