mirror of
https://codeberg.org/scip/epuppy.git
synced 2026-02-04 17:50:58 +01:00
Compare commits
16 Commits
fix-mobi-c
...
woodpecker
| Author | SHA1 | Date | |
|---|---|---|---|
| ee26834054 | |||
| cce26c562b | |||
| 6ceed77fd0 | |||
| 60a1d545ed | |||
| 3a72204915 | |||
| 0516534526 | |||
| d260f5299f | |||
| 1f93d2d37d | |||
| 55addf2a77 | |||
| 06dec42e83 | |||
| fceee7bc04 | |||
| 8edca6d367 | |||
| 1ab65e69a0 | |||
| 7a62b2d19d | |||
| 030c1ba495 | |||
| 9b6f062c65 |
30
README.md
30
README.md
@@ -1,5 +1,5 @@
|
|||||||
[](https://ci.codeberg.org/repos/15473)
|
[](https://ci.codeberg.org/repos/15473)
|
||||||
[](https://codeberg.org/scip/epuppy/raw/branch/main/LICENSE)
|
[](https://codeberg.org/scip/epuppy/raw/branch/master/LICENSE)
|
||||||
[](https://goreportcard.com/report/codeberg.org/scip/epuppy)
|
[](https://goreportcard.com/report/codeberg.org/scip/epuppy)
|
||||||
|
|
||||||
|
|
||||||
@@ -20,20 +20,16 @@ long run.
|
|||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
### Viewing an ebook in dark mode
|
- Viewing an ebook in dark mode
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Viewing an ebook in light mode
|
- Viewing an ebook in light mode
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### You can interactively adjust text width
|
- You can interactively adjust text width
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Showing the help
|
- Showing the help
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -46,7 +42,7 @@ progress.
|
|||||||
Sometimes you may be unhappy with the colors. Depending on your
|
Sometimes you may be unhappy with the colors. Depending on your
|
||||||
terminal style you can enable dark mode with `-D`, light mode is the
|
terminal style you can enable dark mode with `-D`, light mode is the
|
||||||
default. You can also configure custom colors in a config file in
|
default. You can also configure custom colors in a config file in
|
||||||
`$HOME/.config/epuppy/config.toml`:
|
`$HOME/.config/epuppy/confit.toml`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
# color setting for dark mode
|
# color setting for dark mode
|
||||||
@@ -96,16 +92,6 @@ Options:
|
|||||||
-v --version show program version
|
-v --version show program version
|
||||||
```
|
```
|
||||||
|
|
||||||
## Reading mobi files
|
|
||||||
|
|
||||||
`epuppy` doesn't support mobi files, but you can install
|
|
||||||
[mobitool](https://github.com/bfabiszewski/libmobi/) and use it to
|
|
||||||
convert mobi files to epub. The ubuntu package is `libmobi-tools`. To convert, execute:
|
|
||||||
|
|
||||||
```default
|
|
||||||
mobitool -e somebook.epub
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
The tool does not have any dependencies. Just download the binary for
|
The tool does not have any dependencies. Just download the binary for
|
||||||
@@ -118,7 +104,7 @@ You can use [stew](https://github.com/marwanhawari/stew) to install epuppy:
|
|||||||
stew install https://codeberg.org/scip/epuppy
|
stew install https://codeberg.org/scip/epuppy
|
||||||
```
|
```
|
||||||
|
|
||||||
Or go to the [latest release page](https://codeberg.org/scip/epuppy/releases/)
|
Or go to the [latest release page](https://codeberg.org/scip/epuppy/releases/latest)
|
||||||
and look for your OS and platform. There are two options to install the binary:
|
and look for your OS and platform. There are two options to install the binary:
|
||||||
|
|
||||||
Directly download the binary for your platform,
|
Directly download the binary for your platform,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version string = `v0.0.8`
|
Version string = `v0.0.7`
|
||||||
Usage string = `This is epuppy, a terminal ui ebook viewer.
|
Usage string = `This is epuppy, a terminal ui ebook viewer.
|
||||||
|
|
||||||
Usage: epuppy [options] <epub file>
|
Usage: epuppy [options] <epub file>
|
||||||
|
|||||||
@@ -8,12 +8,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cleanenTitles = regexp.MustCompile(`&[a-z]+;`)
|
cleanentitles = regexp.MustCompile(`&[a-z]+;`)
|
||||||
isEmpty = regexp.MustCompile(`(?s)^[\s ]*$`)
|
empty = regexp.MustCompile(`(?s)^[\s ]*$`)
|
||||||
cleanNewlines = regexp.MustCompile(`[\r\n\s]+`)
|
newlines = regexp.MustCompile(`[\r\n\s]+`)
|
||||||
cleanSVG = regexp.MustCompile(`(<svg.+</svg>|<!\[CDATA\[.+\]\]>)`)
|
cleansvg = regexp.MustCompile(`(<svg.+</svg>|<!\[CDATA\[.+\]\]>)`)
|
||||||
cleanMarkup = regexp.MustCompile(`<[^<>]+>`)
|
cleanmarkup = regexp.MustCompile(`<[^<>]+>`)
|
||||||
cleanMobiPageBreaks = regexp.MustCompile(`<mbp:pagebreak/>`)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Content nav-point content
|
// Content nav-point content
|
||||||
@@ -26,28 +25,13 @@ type Content struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse XML, look for title and <p>.*</p> stuff
|
// parse XML, look for title and <p>.*</p> stuff
|
||||||
func (c *Content) Extract(content []byte) error {
|
func (c *Content) String(content []byte) error {
|
||||||
rawXML := cleanSVG.ReplaceAllString(
|
doc, err := xmlquery.Parse(
|
||||||
cleanenTitles.ReplaceAllString(string(content), " "), "")
|
strings.NewReader(
|
||||||
|
cleansvg.ReplaceAllString(
|
||||||
var doc *xmlquery.Node
|
cleanentitles.ReplaceAllString(string(content), " "), "")))
|
||||||
var err error
|
|
||||||
|
|
||||||
doc, err = xmlquery.Parse(strings.NewReader(rawXML))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), `namespace mbp is missing`) {
|
return err
|
||||||
fixedmbp := strings.NewReader(
|
|
||||||
cleanMobiPageBreaks.ReplaceAllString(
|
|
||||||
rawXML, `<span style="page-break-after: always" />`))
|
|
||||||
|
|
||||||
doc, err = xmlquery.Parse(fixedmbp)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Title == "" {
|
if c.Title == "" {
|
||||||
@@ -63,9 +47,9 @@ func (c *Content) Extract(content []byte) error {
|
|||||||
txt := strings.Builder{}
|
txt := strings.Builder{}
|
||||||
var have_p bool
|
var have_p bool
|
||||||
for _, item := range xmlquery.Find(doc, "//p") {
|
for _, item := range xmlquery.Find(doc, "//p") {
|
||||||
if !isEmpty.MatchString(item.InnerText()) {
|
if !empty.MatchString(item.InnerText()) {
|
||||||
have_p = true
|
have_p = true
|
||||||
txt.WriteString(cleanNewlines.ReplaceAllString(item.InnerText(), " ") + "\n\n")
|
txt.WriteString(newlines.ReplaceAllString(item.InnerText(), " ") + "\n\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,9 +57,9 @@ func (c *Content) Extract(content []byte) error {
|
|||||||
// try <div></div>, which some ebooks use, so get all divs,
|
// try <div></div>, which some ebooks use, so get all divs,
|
||||||
// remove markup and paragraphify the parts
|
// remove markup and paragraphify the parts
|
||||||
for _, item := range xmlquery.Find(doc, "//div") {
|
for _, item := range xmlquery.Find(doc, "//div") {
|
||||||
if !isEmpty.MatchString(item.InnerText()) {
|
if !empty.MatchString(item.InnerText()) {
|
||||||
cleaned := cleanMarkup.ReplaceAllString(item.InnerText(), "")
|
cleaned := cleanmarkup.ReplaceAllString(item.InnerText(), "")
|
||||||
txt.WriteString(cleanNewlines.ReplaceAllString(cleaned, " ") + "\n\n")
|
txt.WriteString(newlines.ReplaceAllString(cleaned, " ") + "\n\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,8 +112,6 @@ func (bk *Book) getSections() error {
|
|||||||
|
|
||||||
// we have ncx points from the TOC, try those
|
// we have ncx points from the TOC, try those
|
||||||
if len(bk.Ncx.Points) > 0 {
|
if len(bk.Ncx.Points) > 0 {
|
||||||
known := map[string]int{}
|
|
||||||
|
|
||||||
for _, block := range bk.Ncx.Points {
|
for _, block := range bk.Ncx.Points {
|
||||||
sect := Section{
|
sect := Section{
|
||||||
File: "OEBPS/" + block.Content.Src,
|
File: "OEBPS/" + block.Content.Src,
|
||||||
@@ -130,13 +128,7 @@ func (bk *Book) getSections() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, haveFile := known[sect.File]; !haveFile {
|
sections = append(sections, sect)
|
||||||
// sometimes epub's have many sections but they all
|
|
||||||
// point to the same file. To avoid duplicate content
|
|
||||||
// we ignore sections (thus files) we have already seen.
|
|
||||||
sections = append(sections, sect)
|
|
||||||
known[sect.File] = 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(sections) < manifestcount {
|
if len(sections) < manifestcount {
|
||||||
@@ -197,7 +189,7 @@ func (bk *Book) readSectionContent() error {
|
|||||||
ct := Content{Src: section.File, Title: section.Title}
|
ct := Content{Src: section.File, Title: section.Title}
|
||||||
|
|
||||||
if types.MatchString(section.MediaType) {
|
if types.MatchString(section.MediaType) {
|
||||||
if err := ct.Extract(content); err != nil {
|
if err := ct.String(content); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user