lots of fixes and additions:

- add color and color config support
- fix epub parsing
- add variable margin (left and right arrow keys)
- add help screen (hit `?`)
- add config file support
This commit is contained in:
2025-10-15 14:36:43 +02:00
parent 0d4c44ee11
commit 7544f8877a
12 changed files with 337 additions and 65 deletions

View File

@@ -14,6 +14,7 @@ type Book struct {
Opf Opf `json:"opf"`
Container Container `json:"-"`
Mimetype string `json:"-"`
Content []Content
fd *zip.ReadCloser
}
@@ -49,7 +50,12 @@ func (p *Book) readXML(n string, v interface{}) error {
}
defer fd.Close()
dec := xml.NewDecoder(fd)
return dec.Decode(v)
if err := dec.Decode(v); err != nil {
return fmt.Errorf("XML decoder error %w", err)
}
return nil
}
func (p *Book) readBytes(n string) ([]byte, error) {
@@ -59,8 +65,12 @@ func (p *Book) readBytes(n string) ([]byte, error) {
}
defer fd.Close()
return io.ReadAll(fd)
data, err := io.ReadAll(fd)
if err != nil {
return nil, fmt.Errorf("failed to read contents from %s %w", n, err)
}
return data, nil
}
func (p *Book) open(n string) (io.ReadCloser, error) {
@@ -69,5 +79,6 @@ func (p *Book) open(n string) (io.ReadCloser, error) {
return f.Open()
}
}
return nil, fmt.Errorf("file %s not exist", n)
}

46
pkg/epub/content.go Normal file
View File

@@ -0,0 +1,46 @@
package epub
import (
"encoding/xml"
"fmt"
"strings"
)
// Content nav-point content
type Content struct {
Src string `xml:"src,attr" json:"src"`
Empty bool
Body string
Title string
XML []byte
}
func (c *Content) String(content []byte) error {
title := Title{}
err := xml.Unmarshal(content, &title)
if err != nil {
if !strings.HasPrefix(err.Error(), "XML syntax error") {
return fmt.Errorf("XML parser error %w", err)
}
}
c.Title = strings.TrimSpace(title.Content)
txt := cleantitle.ReplaceAllString(string(content), "")
txt = cleanh1.ReplaceAllString(txt, "")
txt = cleanmarkup.ReplaceAllString(txt, "")
txt = cleanentities.ReplaceAllString(txt, " ")
txt = cleancomments.ReplaceAllString(txt, "")
txt = strings.TrimSpace(txt)
c.Body = cleanspace.ReplaceAllString(txt, "")
c.XML = content
if len(c.Body) == 0 {
c.Empty = true
}
return nil
}

View File

@@ -1,9 +1,7 @@
package epub
import (
"encoding/xml"
"regexp"
"strings"
)
var (
@@ -22,50 +20,10 @@ type Ncx struct {
// NavPoint nav point
type NavPoint struct {
Text string `xml:"navLabel>text" json:"text"`
Content Content `xml:"content" json:"content"`
Points []NavPoint `xml:"navPoint" json:"points"`
Text string `xml:"navLabel>text" json:"text"`
Points []NavPoint `xml:"navPoint" json:"points"`
}
type Title struct {
Content string `xml:"head>title"`
}
// Content nav-point content
type Content struct {
Src string `xml:"src,attr" json:"src"`
Empty bool
Body string
Title string
XML []byte
}
func (c *Content) String(content []byte) error {
title := Title{}
err := xml.Unmarshal(content, &title)
if err != nil {
if !strings.HasPrefix(err.Error(), "XML syntax error") {
return err
}
}
c.Title = title.Content
txt := cleantitle.ReplaceAllString(string(content), "")
txt = cleanh1.ReplaceAllString(txt, "")
txt = cleanmarkup.ReplaceAllString(txt, "")
txt = cleanentities.ReplaceAllString(txt, " ")
txt = cleancomments.ReplaceAllString(txt, "")
txt = strings.TrimSpace(txt)
c.Body = cleanspace.ReplaceAllString(txt, "")
c.XML = content
if len(c.Body) == 0 {
c.Empty = true
}
return nil
}

View File

@@ -2,6 +2,7 @@ package epub
import (
"archive/zip"
"strings"
)
// Open open a epub file
@@ -34,19 +35,29 @@ func Open(fn string) (*Book, error) {
for _, mf := range bk.Opf.Manifest {
if mf.ID == bk.Opf.Spine.Toc {
err = bk.readXML(bk.filename(mf.Href), &bk.Ncx)
if err != nil {
return &bk, err
}
break
}
}
for _, ncx := range bk.Ncx.Points {
content, err := bk.readBytes(bk.filename(ncx.Content.Src))
for _, file := range bk.Files() {
content, err := bk.readBytes(file)
if err != nil {
return &bk, err
}
if err := ncx.Content.String(content); err != nil {
return &bk, err
ct := Content{Src: file}
if strings.Contains(string(content), "DOCTYPE") {
if err := ct.String(content); err != nil {
return &bk, err
}
}
bk.Content = append(bk.Content, ct)
}
return &bk, nil