From a24bf0cfc8afc55f01bc961f7b8166ea6f8cf50f Mon Sep 17 00:00:00 2001
From: celogeek <65178+celogeek@users.noreply.github.com>
Date: Fri, 7 Apr 2023 18:23:53 +0200
Subject: [PATCH 1/5] fill nav files to get toc
---
internal/epub/core.go | 49 ++++++++++++++++++++++++--
internal/epub/image_processing.go | 15 ++++++++
internal/epub/templates/nav.xhtml.tmpl | 14 ++++----
internal/epub/templates/toc.ncx.tmpl | 4 +--
internal/epub/toc.go | 20 +++++++++++
5 files changed, 90 insertions(+), 12 deletions(-)
create mode 100644 internal/epub/toc.go
diff --git a/internal/epub/core.go b/internal/epub/core.go
index bcb1582..bc17265 100644
--- a/internal/epub/core.go
+++ b/internal/epub/core.go
@@ -1,6 +1,7 @@
package epub
import (
+ "encoding/xml"
"fmt"
"image/color"
"path/filepath"
@@ -92,6 +93,7 @@ func (e *ePub) render(templateString string, data any) string {
func (e *ePub) getParts() ([]*epubPart, error) {
images, err := LoadImages(e.Input, e.ImageOptions)
+
if err != nil {
return nil, err
}
@@ -139,6 +141,37 @@ func (e *ePub) getParts() ([]*epubPart, error) {
return parts, nil
}
+func (e *ePub) getToc(title string, images []*Image) ([]byte, error) {
+ paths := map[string]*TocPart{
+ ".": {},
+ }
+ for _, img := range images {
+ currentPath := "."
+ for _, path := range strings.Split(img.Path, string(filepath.Separator)) {
+ parentPath := currentPath
+ currentPath = filepath.Join(currentPath, path)
+ if _, ok := paths[currentPath]; ok {
+ continue
+ }
+ part := &TocPart{
+ Title: TocTitle{
+ Value: path,
+ Link: fmt.Sprintf("Text/%d_p%d.xhtml", img.Id, img.Part),
+ },
+ }
+ paths[currentPath] = part
+ if paths[parentPath].Children == nil {
+ paths[parentPath].Children = &TocChildren{}
+ }
+ paths[parentPath].Children.Tags = append(paths[parentPath].Children.Tags, part)
+ }
+ }
+ if paths["."].Children == nil {
+ return []byte{}, nil
+ }
+ return xml.MarshalIndent(paths["."].Children.Tags, " ", " ")
+}
+
func (e *ePub) Write() error {
type zipContent struct {
Name string
@@ -170,6 +203,11 @@ func (e *ePub) Write() error {
if totalParts > 1 {
title = fmt.Sprintf("%s [%d/%d]", title, i+1, totalParts)
}
+ toc, err := e.getToc(title, part.Images)
+ if err != nil {
+ return err
+ }
+
content := []zipContent{
{"META-INF/container.xml", containerTmpl},
{"OEBPS/content.opf", e.render(contentTmpl, map[string]any{
@@ -180,8 +218,15 @@ func (e *ePub) Write() error {
"Part": i + 1,
"Total": totalParts,
})},
- {"OEBPS/toc.ncx", e.render(tocTmpl, map[string]any{"Info": e})},
- {"OEBPS/nav.xhtml", e.render(navTmpl, map[string]any{"Info": e})},
+ {"OEBPS/toc.ncx", e.render(tocTmpl, map[string]any{
+ "Info": e,
+ "Title": title,
+ })},
+ {"OEBPS/nav.xhtml", e.render(navTmpl, map[string]any{
+ "Title": title,
+ "TOC": string(toc),
+ "Last": part.Images[len(part.Images)-1],
+ })},
{"OEBPS/Text/style.css", styleTmpl},
{"OEBPS/Text/part.xhtml", e.render(partTmpl, map[string]any{
"Info": e,
diff --git a/internal/epub/image_processing.go b/internal/epub/image_processing.go
index 6a60e51..b723efb 100644
--- a/internal/epub/image_processing.go
+++ b/internal/epub/image_processing.go
@@ -31,11 +31,13 @@ type Image struct {
Height int
IsCover bool
NeedSpace bool
+ Path string
}
type imageTask struct {
Id int
Reader io.ReadCloser
+ Path string
Filename string
}
@@ -162,6 +164,7 @@ func LoadImages(path string, options *ImageOptions) ([]*Image, error) {
dst.Bounds().Dy(),
img.Id == 0,
false,
+ img.Path,
}
// Auto split double page
@@ -185,6 +188,7 @@ func LoadImages(path string, options *ImageOptions) ([]*Image, error) {
dst.Bounds().Dy(),
false,
false, // NeedSpace reajust during parts computation
+ img.Path,
}
}
}
@@ -235,6 +239,7 @@ func isSupportedImage(path string) bool {
func loadDir(input string) (int, chan *imageTask, error) {
images := make([]string, 0)
+ input = filepath.Clean(input)
err := filepath.WalkDir(input, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
@@ -263,9 +268,16 @@ func loadDir(input string) (int, chan *imageTask, error) {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
+ p := filepath.Dir(img)
+ if p == input {
+ p = ""
+ } else {
+ p = p[len(input)+1:]
+ }
output <- &imageTask{
Id: i,
Reader: f,
+ Path: p,
Filename: img,
}
}
@@ -306,6 +318,7 @@ func loadCbz(input string) (int, chan *imageTask, error) {
output <- &imageTask{
Id: i,
Reader: f,
+ Path: filepath.Dir(filepath.Clean(img.Name)),
Filename: img.Name,
}
}
@@ -374,6 +387,7 @@ func loadCbr(input string) (int, chan *imageTask, error) {
output <- &imageTask{
Id: idx,
Reader: io.NopCloser(b),
+ Path: filepath.Dir(filepath.Clean(f.Name)),
Filename: f.Name,
}
}
@@ -409,6 +423,7 @@ func loadPdf(input string) (int, chan *imageTask, error) {
output <- &imageTask{
Id: i,
Reader: io.NopCloser(b),
+ Path: "/",
Filename: fmt.Sprintf("page %d", i+1),
}
}
diff --git a/internal/epub/templates/nav.xhtml.tmpl b/internal/epub/templates/nav.xhtml.tmpl
index 0492d4f..322ce44 100644
--- a/internal/epub/templates/nav.xhtml.tmpl
+++ b/internal/epub/templates/nav.xhtml.tmpl
@@ -2,18 +2,16 @@
- {{ .Info.Title }}
+ {{ .Title }}
-