@fiduswriter/books-document 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +24 -0
  3. package/dist/exporter/bits/index.d.ts +42 -0
  4. package/dist/exporter/bits/index.d.ts.map +1 -0
  5. package/dist/exporter/bits/index.js +98 -0
  6. package/dist/exporter/bits/index.js.map +1 -0
  7. package/dist/exporter/bits/templates.d.ts +7 -0
  8. package/dist/exporter/bits/templates.d.ts.map +1 -0
  9. package/dist/exporter/bits/templates.js +78 -0
  10. package/dist/exporter/bits/templates.js.map +1 -0
  11. package/dist/exporter/docx/index.d.ts +27 -0
  12. package/dist/exporter/docx/index.d.ts.map +1 -0
  13. package/dist/exporter/docx/index.js +129 -0
  14. package/dist/exporter/docx/index.js.map +1 -0
  15. package/dist/exporter/docx/render.d.ts +14 -0
  16. package/dist/exporter/docx/render.d.ts.map +1 -0
  17. package/dist/exporter/docx/render.js +116 -0
  18. package/dist/exporter/docx/render.js.map +1 -0
  19. package/dist/exporter/epub/index.d.ts +65 -0
  20. package/dist/exporter/epub/index.d.ts.map +1 -0
  21. package/dist/exporter/epub/index.js +268 -0
  22. package/dist/exporter/epub/index.js.map +1 -0
  23. package/dist/exporter/epub/templates.d.ts +65 -0
  24. package/dist/exporter/epub/templates.d.ts.map +1 -0
  25. package/dist/exporter/epub/templates.js +223 -0
  26. package/dist/exporter/epub/templates.js.map +1 -0
  27. package/dist/exporter/epub/tools.d.ts +5 -0
  28. package/dist/exporter/epub/tools.d.ts.map +1 -0
  29. package/dist/exporter/epub/tools.js +59 -0
  30. package/dist/exporter/epub/tools.js.map +1 -0
  31. package/dist/exporter/html/index.d.ts +67 -0
  32. package/dist/exporter/html/index.d.ts.map +1 -0
  33. package/dist/exporter/html/index.js +300 -0
  34. package/dist/exporter/html/index.js.map +1 -0
  35. package/dist/exporter/html/templates.d.ts +40 -0
  36. package/dist/exporter/html/templates.d.ts.map +1 -0
  37. package/dist/exporter/html/templates.js +226 -0
  38. package/dist/exporter/html/templates.js.map +1 -0
  39. package/dist/exporter/html/tools.d.ts +2 -0
  40. package/dist/exporter/html/tools.d.ts.map +1 -0
  41. package/dist/exporter/html/tools.js +23 -0
  42. package/dist/exporter/html/tools.js.map +1 -0
  43. package/dist/exporter/latex/index.d.ts +32 -0
  44. package/dist/exporter/latex/index.d.ts.map +1 -0
  45. package/dist/exporter/latex/index.js +102 -0
  46. package/dist/exporter/latex/index.js.map +1 -0
  47. package/dist/exporter/latex/templates.d.ts +4 -0
  48. package/dist/exporter/latex/templates.d.ts.map +1 -0
  49. package/dist/exporter/latex/templates.js +26 -0
  50. package/dist/exporter/latex/templates.js.map +1 -0
  51. package/dist/exporter/native/index.d.ts +20 -0
  52. package/dist/exporter/native/index.d.ts.map +1 -0
  53. package/dist/exporter/native/index.js +109 -0
  54. package/dist/exporter/native/index.js.map +1 -0
  55. package/dist/exporter/odt/index.d.ts +27 -0
  56. package/dist/exporter/odt/index.d.ts.map +1 -0
  57. package/dist/exporter/odt/index.js +123 -0
  58. package/dist/exporter/odt/index.js.map +1 -0
  59. package/dist/exporter/odt/render.d.ts +15 -0
  60. package/dist/exporter/odt/render.d.ts.map +1 -0
  61. package/dist/exporter/odt/render.js +119 -0
  62. package/dist/exporter/odt/render.js.map +1 -0
  63. package/dist/exporter/print/index.d.ts +24 -0
  64. package/dist/exporter/print/index.d.ts.map +1 -0
  65. package/dist/exporter/print/index.js +60 -0
  66. package/dist/exporter/print/index.js.map +1 -0
  67. package/dist/exporter/print/templates.d.ts +2 -0
  68. package/dist/exporter/print/templates.d.ts.map +1 -0
  69. package/dist/exporter/print/templates.js +5 -0
  70. package/dist/exporter/print/templates.js.map +1 -0
  71. package/dist/exporter/tools.d.ts +29 -0
  72. package/dist/exporter/tools.d.ts.map +1 -0
  73. package/dist/exporter/tools.js +151 -0
  74. package/dist/exporter/tools.js.map +1 -0
  75. package/dist/i18n.d.ts +7 -0
  76. package/dist/i18n.d.ts.map +1 -0
  77. package/dist/i18n.js +918 -0
  78. package/dist/i18n.js.map +1 -0
  79. package/dist/importer/native/index.d.ts +34 -0
  80. package/dist/importer/native/index.d.ts.map +1 -0
  81. package/dist/importer/native/index.js +152 -0
  82. package/dist/importer/native/index.js.map +1 -0
  83. package/dist/importer/native/reader.d.ts +26 -0
  84. package/dist/importer/native/reader.d.ts.map +1 -0
  85. package/dist/importer/native/reader.js +105 -0
  86. package/dist/importer/native/reader.js.map +1 -0
  87. package/dist/index.d.ts +3 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +2 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/schema/index.d.ts +4 -0
  92. package/dist/schema/index.d.ts.map +1 -0
  93. package/dist/schema/index.js +4 -0
  94. package/dist/schema/index.js.map +1 -0
  95. package/dist/types.d.ts +151 -0
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +5 -0
  98. package/dist/types.js.map +1 -0
  99. package/package.json +101 -0
  100. package/src/exporter/bits/index.ts +163 -0
  101. package/src/exporter/bits/templates.ts +107 -0
  102. package/src/exporter/docx/index.ts +239 -0
  103. package/src/exporter/docx/render.ts +142 -0
  104. package/src/exporter/epub/index.ts +426 -0
  105. package/src/exporter/epub/templates.ts +401 -0
  106. package/src/exporter/epub/tools.ts +68 -0
  107. package/src/exporter/html/index.ts +443 -0
  108. package/src/exporter/html/templates.ts +363 -0
  109. package/src/exporter/html/tools.ts +26 -0
  110. package/src/exporter/latex/index.ts +161 -0
  111. package/src/exporter/latex/templates.ts +35 -0
  112. package/src/exporter/native/index.ts +187 -0
  113. package/src/exporter/odt/index.ts +211 -0
  114. package/src/exporter/odt/render.ts +146 -0
  115. package/src/exporter/print/index.ts +92 -0
  116. package/src/exporter/print/templates.ts +8 -0
  117. package/src/exporter/tools.ts +233 -0
  118. package/src/global.d.ts +2 -0
  119. package/src/i18n.ts +936 -0
  120. package/src/importer/native/index.ts +233 -0
  121. package/src/importer/native/reader.ts +165 -0
  122. package/src/index.ts +19 -0
  123. package/src/modules.d.ts +11 -0
  124. package/src/schema/index.ts +4 -0
  125. package/src/types.ts +188 -0
@@ -0,0 +1,142 @@
1
+ import {DOCXExporterRender} from "@fiduswriter/document/exporter/docx/render"
2
+
3
+ export class DOCXBookExporterRender extends DOCXExporterRender {
4
+ preamble: any
5
+ bodyTemplate: any
6
+ postamble: any
7
+ fileXML: any
8
+ bodyParts: any[]
9
+
10
+ constructor(xml: any) {
11
+ super(xml)
12
+
13
+ this.preamble = null
14
+ this.bodyTemplate = null
15
+ this.postamble = null
16
+ this.fileXML = null
17
+ this.bodyParts = []
18
+ }
19
+
20
+ init(): Promise<void> {
21
+ return super.init().then(() => {
22
+ this.fileXML = this.text
23
+ const text = this.fileXML.query("w:body")
24
+ this.preamble = text.cloneNode(false)
25
+ this.bodyTemplate = text.cloneNode(false)
26
+ this.postamble = text.cloneNode(false)
27
+ let currentSection = this.bodyTemplate
28
+ const textChildren = Array.from(text.children)
29
+ textChildren.forEach((node: any) => {
30
+ const bookmarkStart = node.query("w:bookmarkStart")
31
+ if (bookmarkStart) {
32
+ const bookmarkName = String(
33
+ bookmarkStart.getAttribute("w:name")
34
+ ).toLowerCase()
35
+ if (bookmarkName === "preamble") {
36
+ currentSection = this.preamble
37
+ } else if (bookmarkName === "body") {
38
+ currentSection = this.bodyTemplate
39
+ } else if (bookmarkName === "postamble") {
40
+ currentSection = this.postamble
41
+ }
42
+ }
43
+ currentSection.appendChild(node)
44
+ })
45
+ return Promise.resolve()
46
+ })
47
+ }
48
+
49
+ render(...args: any[]): void {
50
+ const [docContent, pmBib, settings, richtext, citations, chapterIndex] = args
51
+ this.text = this.bodyTemplate.cloneNode(true)
52
+ const bodyBookmark = (this.text as any).query("w:bookmarkStart", {
53
+ "w:name": "body"
54
+ })
55
+ if (bodyBookmark) {
56
+ bodyBookmark.setAttribute("w:name", `chapter ${chapterIndex + 1}`)
57
+ }
58
+ super.render(docContent, pmBib, settings, richtext, citations)
59
+ this.bodyParts.push(this.text)
60
+ }
61
+
62
+ renderAmbles({
63
+ title,
64
+ subtitle,
65
+ version,
66
+ publisher,
67
+ copyright,
68
+ author,
69
+ keywords,
70
+ language,
71
+ description,
72
+ isbn,
73
+ publication_date,
74
+ series_title,
75
+ series_position
76
+ }: Record<string, unknown>): void {
77
+ const tags = [
78
+ {title: "book.title", content: title},
79
+ {title: "book.subtitle", content: subtitle},
80
+ {title: "book.version", content: version},
81
+ {title: "book.publisher", content: publisher},
82
+ {title: "book.copyright", content: copyright},
83
+ {title: "book.author", content: author},
84
+ {title: "book.keywords", content: keywords},
85
+ {title: "book.language", content: language},
86
+ {title: "book.description", content: description},
87
+ {title: "book.isbn", content: isbn},
88
+ {title: "book.publication_date", content: publication_date},
89
+ {title: "book.series_title", content: series_title},
90
+ {title: "book.series_position", content: series_position}
91
+ ]
92
+ const usedTags: any[] = []
93
+ const ambles = [this.preamble, this.postamble]
94
+ ambles.forEach(amble => {
95
+ const blocks = amble.queryAll(["w:p", "w:sectPr"])
96
+ blocks.forEach((block: any) => {
97
+ const text = block.textContent
98
+ tags.forEach(tag => {
99
+ const tagString = tag.title
100
+ if (text.includes(`{${tagString}}`)) {
101
+ usedTags.push(Object.assign({block}, tag))
102
+ }
103
+ })
104
+ })
105
+ })
106
+ usedTags.forEach(tag => this.inlineRender(tag))
107
+ }
108
+
109
+ assemble(): void {
110
+ const text = this.fileXML.query("w:body")
111
+ Array.from(this.preamble.children).forEach((node: any) =>
112
+ text.appendChild(node)
113
+ )
114
+ this.bodyParts.forEach((bodyPart: any, index: number) => {
115
+ const children = bodyPart.children.slice()
116
+ children.forEach((node: any) => {
117
+ text.appendChild(node)
118
+ })
119
+ if (index < this.bodyParts.length - 1) {
120
+ text.appendXML(
121
+ `<w:p>
122
+ <w:pPr>
123
+ <w:pStyle w:val="Normal"/>
124
+ <w:bidi w:val="0"/>
125
+ <w:jc w:val="start"/>
126
+ <w:rPr/>
127
+ </w:pPr>
128
+ <w:r>
129
+ <w:rPr/>
130
+ </w:r>
131
+ <w:r>
132
+ <w:br w:type="page"/>
133
+ </w:r>
134
+ </w:p>`
135
+ )
136
+ }
137
+ })
138
+ Array.from(this.postamble.children).forEach((node: any) =>
139
+ text.appendChild(node)
140
+ )
141
+ }
142
+ }
@@ -0,0 +1,426 @@
1
+ /**
2
+ * EPUB book exporter.
3
+ */
4
+
5
+ import type {Schema} from "prosemirror-model"
6
+ import {HTMLExporterConvert} from "@fiduswriter/document/exporter/html/convert"
7
+ import {htmlExportTemplate} from "@fiduswriter/document/exporter/html/templates"
8
+ import {removeHidden} from "@fiduswriter/document/exporter/tools/doc_content"
9
+ import {createSlug} from "@fiduswriter/document/exporter/tools/file"
10
+ import {ZipFileCreator} from "@fiduswriter/document/exporter/tools/zip"
11
+ import {addAlert, get, staticUrl} from "fwtoolkit"
12
+ import pretty from "pretty"
13
+
14
+ import type {Book, BookStyles, CSL, DocumentListEntry, User} from "../../types.js"
15
+ import {getMissingChapterData} from "../tools.js"
16
+ import {
17
+ containerTemplate,
18
+ epubBookCopyrightTemplate,
19
+ epubBookCoverTemplate,
20
+ epubBookOpfTemplate,
21
+ epubBookTitlepageTemplate,
22
+ navTemplate,
23
+ ncxTemplate
24
+ } from "./templates.js"
25
+ import {
26
+ buildHierarchy,
27
+ getFontMimeType,
28
+ getImageMimeType,
29
+ getTimestamp
30
+ } from "./tools.js"
31
+
32
+ interface StyleSheet {
33
+ url?: string
34
+ filename?: string
35
+ contents?: string
36
+ }
37
+
38
+ interface ImageFile {
39
+ url: string
40
+ filename: string
41
+ coverImage?: boolean
42
+ mimeType?: string
43
+ }
44
+
45
+ interface FontFile {
46
+ url: string
47
+ filename: string
48
+ mimeType?: string
49
+ }
50
+
51
+ interface TextFile {
52
+ filename: string
53
+ contents: string
54
+ }
55
+
56
+ interface IncludeZip {
57
+ directory: string
58
+ url: string
59
+ }
60
+
61
+ interface ChapterOutput {
62
+ number: number
63
+ part: string
64
+ title: string
65
+ docNum: number
66
+ metaData: Record<string, unknown>
67
+ }
68
+
69
+ export class EpubBookExporter {
70
+ schema: Schema
71
+ csl: CSL
72
+ bookStyles: BookStyles
73
+ book: Book
74
+ user: User
75
+ docList: DocumentListEntry[]
76
+ updated: number
77
+ textFiles: TextFile[]
78
+ images: ImageFile[]
79
+ fontFiles: FontFile[]
80
+ httpFiles: (ImageFile | FontFile)[]
81
+ styleSheets: StyleSheet[]
82
+ chapters: ChapterOutput[]
83
+ contentItems: Array<Record<string, unknown>>
84
+ includeZips: IncludeZip[]
85
+ math: boolean
86
+
87
+ constructor(
88
+ schema: Schema,
89
+ csl: CSL,
90
+ bookStyles: BookStyles,
91
+ book: Book,
92
+ user: User,
93
+ docList: DocumentListEntry[],
94
+ updated: number
95
+ ) {
96
+ this.schema = schema
97
+ this.csl = csl
98
+ this.bookStyles = bookStyles
99
+ this.book = book
100
+ this.user = user
101
+ this.docList = docList
102
+ this.updated = updated
103
+ this.textFiles = []
104
+ this.images = []
105
+ this.fontFiles = []
106
+ this.httpFiles = []
107
+ this.styleSheets = [{url: staticUrl("css/book.css")}]
108
+ this.chapters = []
109
+ this.contentItems = []
110
+ this.includeZips = []
111
+ this.math = false
112
+ }
113
+
114
+ async init(): Promise<Blob | false> {
115
+ if (this.book.chapters.length === 0) {
116
+ addAlert(
117
+ "error",
118
+ gettext("Book cannot be exported due to lack of chapters.")
119
+ )
120
+ return false
121
+ }
122
+
123
+ await getMissingChapterData(this.book, this.docList, this.schema)
124
+
125
+ this.addBookStyle()
126
+ return this.exportContents()
127
+ }
128
+
129
+ addBookStyle(): boolean {
130
+ const bookStyle = this.bookStyles.find(
131
+ style => style.slug === this.book.settings.book_style
132
+ )
133
+ if (!bookStyle) {
134
+ return false
135
+ }
136
+
137
+ let contents = bookStyle.contents
138
+ bookStyle.bookstylefile_set.forEach(([_url, filename]) => {
139
+ contents = contents.replace(
140
+ new RegExp(filename, "g"),
141
+ `media/${filename}`
142
+ )
143
+ })
144
+
145
+ this.styleSheets.push({contents, filename: `css/${bookStyle.slug}.css`})
146
+ this.fontFiles = this.fontFiles.concat(
147
+ bookStyle.bookstylefile_set.map(([url, filename]) => ({
148
+ filename: `css/media/${filename}`,
149
+ url
150
+ }))
151
+ )
152
+ return true
153
+ }
154
+
155
+ async exportContents(): Promise<Blob> {
156
+ await Promise.all(
157
+ this.styleSheets.map(async sheet => this.loadStyle(sheet))
158
+ )
159
+
160
+ if (this.book.cover_image) {
161
+ const coverImage = this.book.cover_image_data
162
+ if (coverImage?.image) {
163
+ this.images.push({
164
+ url: coverImage.image.split("?")[0],
165
+ filename: coverImage.image.split("/").pop()?.split("?")[0] || "cover",
166
+ coverImage: true
167
+ })
168
+
169
+ this.textFiles.push({
170
+ filename: "cover.xhtml",
171
+ contents: pretty(
172
+ epubBookCoverTemplate({
173
+ book: this.book,
174
+ coverImage: coverImage as any,
175
+ shortLang: this.book.settings.language.split("-")[0]
176
+ })
177
+ )
178
+ })
179
+ }
180
+ }
181
+
182
+ this.textFiles.push({
183
+ filename: "titlepage.xhtml",
184
+ contents: pretty(
185
+ epubBookTitlepageTemplate({
186
+ book: this.book,
187
+ shortLang: this.book.settings.language.split("-")[0]
188
+ })
189
+ )
190
+ })
191
+
192
+ this.chapters = (
193
+ await Promise.all(
194
+ this.book.chapters
195
+ .sort((a, b) => a.number - b.number)
196
+ .map(async chapter => {
197
+ const doc = this.docList.find(
198
+ d => d.id === chapter.text
199
+ )
200
+ if (!doc) {
201
+ return false
202
+ }
203
+
204
+ const docContent = removeHidden(doc.content as any) as any
205
+
206
+ const converter = new HTMLExporterConvert(
207
+ doc.title,
208
+ doc.settings,
209
+ docContent,
210
+ htmlExportTemplate,
211
+ {db: doc.images || {}},
212
+ {db: doc.bibliography || {}},
213
+ this.csl,
214
+ this.styleSheets,
215
+ {
216
+ xhtml: true,
217
+ epub: true,
218
+ footnoteNumbering: "decimal",
219
+ affiliationNumbering: "alpha",
220
+ idPrefix: `c-${chapter.number}-`
221
+ }
222
+ )
223
+ const {html, imageIds, metaData, extraStyleSheets} =
224
+ await converter.init()
225
+
226
+ if (!html) {
227
+ return false
228
+ }
229
+
230
+ imageIds.forEach((id: string | number) => {
231
+ const image = doc.images?.[id]
232
+ if (image?.image && typeof image.image === "string") {
233
+ this.images.push({
234
+ filename: `images/${image.image.split("/").pop()}`,
235
+ url: image.image
236
+ })
237
+ }
238
+ })
239
+
240
+ await Promise.all(
241
+ extraStyleSheets.map(
242
+ async (sheet: StyleSheet) => this.loadStyle(sheet)
243
+ )
244
+ )
245
+
246
+ if (converter.features.math) {
247
+ this.math = true
248
+ }
249
+
250
+ this.textFiles.push({
251
+ filename: `document-${chapter.number}.xhtml`,
252
+ contents: pretty(html)
253
+ })
254
+
255
+ return {
256
+ number: chapter.number,
257
+ part: chapter.part || "",
258
+ title: doc.title,
259
+ docNum: chapter.number,
260
+ metaData
261
+ }
262
+ })
263
+ )
264
+ ).filter((chapter): chapter is ChapterOutput => chapter !== false)
265
+
266
+ this.textFiles.push({
267
+ filename: "copyright.xhtml",
268
+ contents: pretty(
269
+ epubBookCopyrightTemplate({
270
+ book: this.book,
271
+ creator: this.user.name || "",
272
+ language: this.book.settings.language,
273
+ shortLang: this.book.settings.language.split("-")[0]
274
+ })
275
+ )
276
+ })
277
+
278
+ const contentItems = this.chapters.reduce(
279
+ (items: Array<Record<string, unknown>>, chapter) => {
280
+ if (chapter.part) {
281
+ items.push({
282
+ title: chapter.part,
283
+ docNum: chapter.number,
284
+ link: `document-${chapter.number}.xhtml`,
285
+ level: -1
286
+ })
287
+ }
288
+ items = items.concat(
289
+ (chapter.metaData.toc as Array<Record<string, unknown>>).map(item => ({
290
+ ...item,
291
+ docNum: chapter.number,
292
+ link: `document-${chapter.number}.xhtml#c-${chapter.number}-${item.id}`
293
+ }))
294
+ )
295
+ return items
296
+ },
297
+ []
298
+ )
299
+
300
+ const toc = buildHierarchy(contentItems)
301
+
302
+ this.textFiles = this.textFiles.concat([
303
+ {
304
+ filename: "META-INF/container.xml",
305
+ contents: pretty(containerTemplate())
306
+ },
307
+ {
308
+ filename: "document.opf",
309
+ contents: pretty(
310
+ epubBookOpfTemplate({
311
+ book: this.book,
312
+ language: this.book.settings.language,
313
+ idType: "fidus",
314
+ date: getTimestamp(new Date(this.updated * 1000)).slice(
315
+ 0,
316
+ 10
317
+ ),
318
+ modified: getTimestamp(new Date(this.updated * 1000)),
319
+ styleSheets: this.styleSheets as any,
320
+ math: this.math,
321
+ images: this.images.map(image => ({
322
+ ...image,
323
+ mimeType: getImageMimeType(image.filename)
324
+ })) as any,
325
+ fontFiles: this.fontFiles.map(font => ({
326
+ ...font,
327
+ mimeType: getFontMimeType(font.filename)
328
+ })) as any,
329
+ chapters: this.chapters as any,
330
+ user: this.user as any
331
+ } as any)
332
+ )
333
+ },
334
+ {
335
+ filename: "document.ncx",
336
+ contents: pretty(
337
+ ncxTemplate({
338
+ shortLang: this.book.settings.language.split("-")[0],
339
+ title: this.book.title,
340
+ idType: "fidus",
341
+ id: this.book.id,
342
+ toc: toc as any
343
+ } as any)
344
+ )
345
+ },
346
+ {
347
+ filename: "document-nav.xhtml",
348
+ contents: pretty(
349
+ navTemplate({
350
+ shortLang: this.book.settings.language.split("-")[0],
351
+ toc: toc as any,
352
+ styleSheets: this.styleSheets as any
353
+ } as any)
354
+ )
355
+ }
356
+ ])
357
+ if (this.math) {
358
+ this.includeZips.push({
359
+ directory: "css",
360
+ url: staticUrl("zip/mathlive_style.zip")
361
+ })
362
+ }
363
+
364
+ this.httpFiles = this.images.concat(this.fontFiles)
365
+ this.prefixFiles()
366
+ return this.createZip()
367
+ }
368
+
369
+ async loadStyle(sheet: StyleSheet): Promise<StyleSheet> {
370
+ const filename =
371
+ sheet.filename ||
372
+ `css/${sheet.url?.split("/").pop()?.split("?")[0]}`
373
+ const existing = this.textFiles.find(file => file.filename === filename)
374
+ if (existing) {
375
+ return Promise.resolve(existing as StyleSheet)
376
+ }
377
+ if (sheet.url) {
378
+ const response = await get(sheet.url)
379
+ const text = await response.text()
380
+ sheet.contents = text
381
+ sheet.filename = filename
382
+ delete sheet.url
383
+ }
384
+ if (sheet.filename) {
385
+ this.textFiles.push(sheet as TextFile)
386
+ }
387
+ return Promise.resolve(sheet)
388
+ }
389
+
390
+ prefixFiles(): void {
391
+ this.textFiles = this.textFiles.map(file => {
392
+ if (
393
+ ["META-INF/container.xml", "mimetype"].includes(file.filename)
394
+ ) {
395
+ return file
396
+ }
397
+ return Object.assign({}, file, {filename: `EPUB/${file.filename}`})
398
+ })
399
+ this.fontFiles = this.fontFiles.map(file =>
400
+ Object.assign({}, file, {filename: `EPUB/${file.filename}`})
401
+ )
402
+ this.includeZips = this.includeZips.map(file =>
403
+ Object.assign({}, file, {directory: `EPUB/${file.directory}`})
404
+ )
405
+ }
406
+
407
+ async createZip(): Promise<Blob> {
408
+ const zipper = new ZipFileCreator(
409
+ this.textFiles,
410
+ this.httpFiles,
411
+ this.includeZips,
412
+ "application/epub+zip",
413
+ new Date(this.updated * 1000)
414
+ )
415
+ const blob = await zipper.init()
416
+ return this.download(blob)
417
+ }
418
+
419
+ download(blob: Blob): Blob {
420
+ return blob
421
+ }
422
+
423
+ get defaultFilename(): string {
424
+ return `${createSlug(this.book.title)}.epub`
425
+ }
426
+ }