mirror of
https://codeberg.org/scip/epuppy.git
synced 2025-12-16 20:11:00 +01:00
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:
@@ -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
46
pkg/epub/content.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user