-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgopub.go
119 lines (97 loc) · 2.29 KB
/
gopub.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package gopub
import (
"archive/zip"
"encoding/xml"
"fmt"
"path"
"strings"
)
type epubReader struct {
zipReader *zip.ReadCloser
options epubReaderOptions
}
type epubReaderOptions struct {
rootFilePath string
}
type Book struct {
FilePath string
Title string
Author string
Authors []string
Description string
CoverImage []byte
ReadingOrder []LocalTextContentFile
Navigation []Navigation
Content Content
}
func ReadBook(filePath string) (Book, error) {
var book Book
zf, err := zip.OpenReader(filePath)
if err != nil {
return book, err
}
defer zf.Close()
container, err := findRootFile(zf)
if err != nil {
return book, err
}
reader := epubReader{
zipReader: zf,
options: epubReaderOptions{
rootFilePath: container.FullPath,
},
}
schema, err := readSchema(reader)
if err != nil {
return book, err
}
coverImage, err := schema.pkg.Manifest.getCoverImage(zf)
if err != nil {
return book, err
}
readingOrder, err := schema.getReadingOrder(reader)
if err != nil {
return book, err
}
navigationPath, err := schema.pkg.Manifest.getNavigationFilePath()
if err != nil {
return book, err
}
navDoc, err := readNavigation(zf, path.Join(schema.contentDirectoryPath, navigationPath))
if err != nil {
return book, err
}
schema.navigationDocument = navDoc
content, err := readContent(schema, reader)
if err != nil {
return book, err
}
book.FilePath = filePath
book.Title = schema.pkg.Metadata.Titles[0].Value
book.Author = schema.pkg.Metadata.Creators[0].Value
book.Authors = schema.pkg.Metadata.getCreators()
book.Description = schema.pkg.Metadata.getFirstOrDefaultDescription()
book.CoverImage = coverImage
book.ReadingOrder = readingOrder
book.Navigation = navDoc.Navigations
book.Content = content
return book, nil
}
func findRootFile(r *zip.ReadCloser) (RootFile, error) {
var rootFile RootFile
for _, f := range r.File {
if strings.HasSuffix(f.Name, "META-INF/container.xml") {
rc, err := f.Open()
if err != nil {
return rootFile, err
}
defer rc.Close()
var container Container
if err := xml.NewDecoder(rc).Decode(&container); err != nil {
return rootFile, err
}
return container.RootFile, nil
}
}
return rootFile, fmt.Errorf("root file not found in META-INF/container.xml")
}