-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.go
289 lines (243 loc) · 7.39 KB
/
content.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
package gopub
import (
"io"
"path"
"strings"
)
type ContentType int
const (
ContentTypeImageGif ContentType = iota + 1
ContentTypeImageJpeg
ContentTypeImagePng
ContentTypeImageSvg
ContentTypeImageWebp
ContentTypeAudioMp3
ContentTypeAudioMp4
ContentTypeAudioOgg
ContentTypeCss
ContentTypeFontTruetype
ContentTypeFontSfnt
ContentTypeFontOpentype
ContentTypeFontWoff
ContentTypeFontWoff2
ContentTypeXhtml
ContentTypeXml
ContentTypeScript
ContentTypeDtb
ContentTypeDtbNcx
ContentTypeSmil
ContentTypeOeb1Document
ContentTypeOeb1Css
ContentTypeOther
)
type ContentLocation int
const (
ContentLocationLocal ContentLocation = iota + 1
ContentLocationRemote
)
type ContentFileType int
const (
ContentFileTypeText ContentFileType = iota + 1
ContentFileTypeByteArray
)
type ContentFile struct {
Key string
ContentType ContentType
ContentMimeType string
ContentLocation ContentLocation
ContentFileType ContentFileType
}
func newContentFile(item ManifestItem, contentDirectoryPath string, contentLocation ContentLocation, contentFileType ContentFileType) ContentFile {
href := item.Href
contentMimeType := item.MediaType
contentType := getContentTypeByMimeType(contentMimeType)
contentFile := ContentFile{
Key: href,
ContentType: contentType,
ContentMimeType: contentMimeType,
ContentLocation: contentLocation,
ContentFileType: contentFileType,
}
return contentFile
}
type LocalContentFile struct {
FilePath string
ContentFile
}
type LocalByteContentFile struct {
Content []byte
ContentFile
}
func newLocalByteContentFile(er epubReader, contentFile ContentFile, contentFilePath string) (LocalByteContentFile, error) {
var localByteContentFile LocalByteContentFile
rc, size, err := findFileInZip(er.zipReader, contentFilePath)
if err != nil {
return localByteContentFile, err
}
defer rc.Close()
byteContent := make([]byte, size)
_, err = io.ReadFull(rc, byteContent)
if err != nil {
if err != io.EOF {
return localByteContentFile, err
}
}
localByteContentFile.Content = byteContent
localByteContentFile.ContentFile = contentFile
return localByteContentFile, nil
}
type LocalTextContentFile struct {
Content string
ContentFile
}
func newLocalTextContentFile(er epubReader, contentFile ContentFile, contentFilePath string) (LocalTextContentFile, error) {
var localTextContentFile LocalTextContentFile
rc, size, err := findFileInZip(er.zipReader, contentFilePath)
if err != nil {
return localTextContentFile, err
}
defer rc.Close()
buf := make([]byte, size)
_, err = io.ReadFull(rc, buf)
if err != nil {
if err != io.EOF {
return localTextContentFile, err
}
}
localTextContentFile.Content = string(buf)
localTextContentFile.ContentFile = contentFile
return localTextContentFile, nil
}
type Content struct {
Cover LocalByteContentFile
NavigationHtmlFile LocalTextContentFile
Html []LocalTextContentFile
Css []LocalTextContentFile
Images []LocalByteContentFile
Fonts []LocalByteContentFile
Audios []LocalByteContentFile
AllFiles []LocalContentFile
}
func readContent(sc schema, er epubReader) (Content, error) {
var content Content
var cover LocalByteContentFile
var navigationHtmlFile LocalTextContentFile
var htmlLocal []LocalTextContentFile
var cssLocal []LocalTextContentFile
var imagesLocal []LocalByteContentFile
var fontsLocal []LocalByteContentFile
var audiosLocal []LocalByteContentFile
var allFilesLocal []LocalContentFile
for _, item := range sc.pkg.Manifest.Items {
href := item.Href
contentMimeType := item.MediaType
contentType := getContentTypeByMimeType(contentMimeType)
contentDirectoryPath := sc.contentDirectoryPath
contentFilePath := path.Join(contentDirectoryPath, href)
contentFile := ContentFile{
Key: href,
ContentType: contentType,
ContentMimeType: contentMimeType,
ContentLocation: ContentLocationLocal,
ContentFileType: ContentFileTypeText,
}
localContentFile := LocalContentFile{
FilePath: contentFilePath,
ContentFile: contentFile,
}
switch contentType {
case ContentTypeXhtml, ContentTypeCss, ContentTypeOeb1Document, ContentTypeOeb1Css, ContentTypeXml, ContentTypeDtb, ContentTypeDtbNcx, ContentTypeSmil, ContentTypeScript:
localTextContentFile, err := newLocalTextContentFile(er, contentFile, contentFilePath)
if err != nil {
return content, err
}
if contentType == ContentTypeXhtml {
if navigationHtmlFile.Content == "" && item.Properties != "" && strings.Contains(item.Properties, "nav") {
navigationHtmlFile = localTextContentFile
} else {
htmlLocal = append(htmlLocal, localTextContentFile)
}
} else if contentType == ContentTypeCss {
cssLocal = append(cssLocal, localTextContentFile)
}
allFilesLocal = append(allFilesLocal, localContentFile)
default:
localByteContentFile, err := newLocalByteContentFile(er, contentFile, contentFilePath)
if err != nil {
return content, err
}
switch contentType {
case ContentTypeImageGif, ContentTypeImageJpeg, ContentTypeImagePng, ContentTypeImageSvg, ContentTypeImageWebp:
if strings.Contains(item.Properties, "cover-image") {
cover = localByteContentFile
} else {
imagesLocal = append(imagesLocal, localByteContentFile)
}
case ContentTypeFontTruetype, ContentTypeFontOpentype, ContentTypeFontSfnt, ContentTypeFontWoff, ContentTypeFontWoff2:
fontsLocal = append(fontsLocal, localByteContentFile)
case ContentTypeAudioMp3, ContentTypeAudioMp4, ContentTypeAudioOgg:
audiosLocal = append(audiosLocal, localByteContentFile)
}
allFilesLocal = append(allFilesLocal, localContentFile)
}
}
content.Cover = cover
content.NavigationHtmlFile = navigationHtmlFile
content.Html = htmlLocal
content.Css = cssLocal
content.Images = imagesLocal
content.Fonts = fontsLocal
content.Audios = audiosLocal
content.AllFiles = allFilesLocal
return content, nil
}
func getContentTypeByMimeType(contentMimeType string) ContentType {
switch strings.ToLower(contentMimeType) {
case "application/xhtml+xml":
return ContentTypeXhtml
case "application/x-dtbook+xml":
return ContentTypeDtb
case "application/x-dtbncx+xml":
return ContentTypeDtbNcx
case "text/x-oeb1-document":
return ContentTypeOeb1Css
case "application/xml":
return ContentTypeXml
case "text/css":
return ContentTypeCss
case "text/x-oeb1-css":
return ContentTypeOeb1Css
case "application/javascript", "application/ecmascript", "text/javascript":
return ContentTypeScript
case "image/gif":
return ContentTypeImageGif
case "image/jpeg":
return ContentTypeImageJpeg
case "image/png":
return ContentTypeImagePng
case "image/svg+xml":
return ContentTypeImageSvg
case "image/webp":
return ContentTypeImageWebp
case "font/truetype", "font/ttf", "application/x-font-truetype":
return ContentTypeFontTruetype
case "font/opentype", "font/otf", "application/vnd.ms-opentype":
return ContentTypeFontOpentype
case "font/sfnt", "application/font-sfnt":
return ContentTypeFontSfnt
case "font/woff", "application/font-woff":
return ContentTypeFontWoff
case "font/woff2":
return ContentTypeFontWoff2
case "application/smil+xml":
return ContentTypeSmil
case "audio/mpeg":
return ContentTypeAudioMp3
case "audio/mp4":
return ContentTypeAudioMp4
case "audio/ogg", "audio/ogg; codecs=opus":
return ContentTypeAudioOgg
default:
return ContentTypeOther
}
}