@fiduswriter/books-document 0.1.2 → 0.1.4

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 (80) hide show
  1. package/README.md +3 -3
  2. package/dist/exporter/bits/index.d.ts.map +1 -1
  3. package/dist/exporter/bits/index.js +3 -7
  4. package/dist/exporter/bits/index.js.map +1 -1
  5. package/dist/exporter/bits/templates.d.ts.map +1 -1
  6. package/dist/exporter/bits/templates.js.map +1 -1
  7. package/dist/exporter/docx/index.d.ts.map +1 -1
  8. package/dist/exporter/docx/index.js +2 -4
  9. package/dist/exporter/docx/index.js.map +1 -1
  10. package/dist/exporter/docx/render.d.ts.map +1 -1
  11. package/dist/exporter/docx/render.js.map +1 -1
  12. package/dist/exporter/epub/index.d.ts.map +1 -1
  13. package/dist/exporter/epub/index.js +5 -12
  14. package/dist/exporter/epub/index.js.map +1 -1
  15. package/dist/exporter/epub/templates.d.ts.map +1 -1
  16. package/dist/exporter/epub/templates.js.map +1 -1
  17. package/dist/exporter/epub/tools.d.ts.map +1 -1
  18. package/dist/exporter/epub/tools.js.map +1 -1
  19. package/dist/exporter/html/index.d.ts.map +1 -1
  20. package/dist/exporter/html/index.js +2 -5
  21. package/dist/exporter/html/index.js.map +1 -1
  22. package/dist/exporter/html/templates.d.ts.map +1 -1
  23. package/dist/exporter/html/templates.js +3 -1
  24. package/dist/exporter/html/templates.js.map +1 -1
  25. package/dist/exporter/html/tools.d.ts.map +1 -1
  26. package/dist/exporter/html/tools.js +1 -2
  27. package/dist/exporter/html/tools.js.map +1 -1
  28. package/dist/exporter/latex/index.d.ts.map +1 -1
  29. package/dist/exporter/latex/index.js.map +1 -1
  30. package/dist/exporter/latex/templates.d.ts.map +1 -1
  31. package/dist/exporter/latex/templates.js.map +1 -1
  32. package/dist/exporter/native/index.d.ts.map +1 -1
  33. package/dist/exporter/native/index.js.map +1 -1
  34. package/dist/exporter/odt/index.d.ts.map +1 -1
  35. package/dist/exporter/odt/index.js +2 -4
  36. package/dist/exporter/odt/index.js.map +1 -1
  37. package/dist/exporter/odt/render.d.ts.map +1 -1
  38. package/dist/exporter/odt/render.js.map +1 -1
  39. package/dist/exporter/print/index.d.ts.map +1 -1
  40. package/dist/exporter/print/index.js +2 -1
  41. package/dist/exporter/print/index.js.map +1 -1
  42. package/dist/exporter/print/templates.js.map +1 -1
  43. package/dist/exporter/tools.d.ts.map +1 -1
  44. package/dist/exporter/tools.js +2 -4
  45. package/dist/exporter/tools.js.map +1 -1
  46. package/dist/importer/native/index.d.ts +13 -2
  47. package/dist/importer/native/index.d.ts.map +1 -1
  48. package/dist/importer/native/index.js +20 -8
  49. package/dist/importer/native/index.js.map +1 -1
  50. package/dist/importer/native/reader.d.ts.map +1 -1
  51. package/dist/importer/native/reader.js +1 -3
  52. package/dist/importer/native/reader.js.map +1 -1
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js.map +1 -1
  55. package/dist/types.d.ts.map +1 -1
  56. package/package.json +1 -1
  57. package/src/exporter/bits/index.ts +27 -31
  58. package/src/exporter/bits/templates.ts +4 -4
  59. package/src/exporter/docx/index.ts +33 -32
  60. package/src/exporter/docx/render.ts +16 -17
  61. package/src/exporter/epub/index.ts +23 -43
  62. package/src/exporter/epub/templates.ts +12 -14
  63. package/src/exporter/epub/tools.ts +3 -5
  64. package/src/exporter/html/index.ts +32 -46
  65. package/src/exporter/html/templates.ts +15 -13
  66. package/src/exporter/html/tools.ts +4 -9
  67. package/src/exporter/latex/index.ts +17 -20
  68. package/src/exporter/latex/templates.ts +2 -6
  69. package/src/exporter/native/index.ts +14 -14
  70. package/src/exporter/odt/index.ts +27 -26
  71. package/src/exporter/odt/render.ts +16 -17
  72. package/src/exporter/print/index.ts +15 -11
  73. package/src/exporter/print/templates.ts +1 -1
  74. package/src/exporter/tools.ts +15 -44
  75. package/src/global.d.ts +2 -0
  76. package/src/importer/native/index.ts +56 -32
  77. package/src/importer/native/reader.ts +9 -18
  78. package/src/index.ts +1 -1
  79. package/src/modules.d.ts +1 -1
  80. package/src/types.ts +2 -2
@@ -7,10 +7,10 @@
7
7
  * decrypt end-to-end encrypted chapters.
8
8
  */
9
9
 
10
- import type { Schema } from "prosemirror-model"
11
- import { getSettings } from "@fiduswriter/document/schema/convert"
12
- import { acceptAllNoInsertions } from "@fiduswriter/document/transform"
13
- import { addAlert, gettext } from "fwtoolkit"
10
+ import type {Schema} from "prosemirror-model"
11
+ import {getSettings} from "@fiduswriter/document/schema/convert"
12
+ import {acceptAllNoInsertions} from "@fiduswriter/document/transform"
13
+ import {addAlert} from "fwtoolkit"
14
14
 
15
15
  import type {
16
16
  ChapterLoader,
@@ -60,11 +60,8 @@ export async function getMissingChapterData(
60
60
  e2ee?: E2EEStrategy
61
61
  } = {}
62
62
  ): Promise<void> {
63
- const {
64
- rawContent = false,
65
- loader = noopChapterLoader,
66
- e2ee = noopE2EEStrategy
67
- } = options
63
+ const {rawContent = false, loader = noopChapterLoader, e2ee = noopE2EEStrategy} =
64
+ options
68
65
 
69
66
  const bookDocuments = book.chapters.map(chapter =>
70
67
  documentList.find(doc => doc.id === chapter.text)
@@ -134,9 +131,7 @@ async function decryptE2EEChapters(
134
131
  "error",
135
132
  `${gettext("No encryption key found for chapter:")} ${chapterLabel}. ${gettext("The key may not have been shared with you.")}`
136
133
  )
137
- throw new Error(
138
- `No encryption key for document ${String(doc.id)}`
139
- )
134
+ throw new Error(`No encryption key for document ${String(doc.id)}`)
140
135
  }
141
136
 
142
137
  if (!doc.e2ee_salt) {
@@ -147,11 +142,7 @@ async function decryptE2EEChapters(
147
142
  const salt = base64ToUint8Array(doc.e2ee_salt)
148
143
  const iterations = doc.e2ee_iterations || 600000
149
144
 
150
- const key = await e2ee.resolvePasswordToKey(
151
- password,
152
- salt,
153
- iterations
154
- )
145
+ const key = await e2ee.resolvePasswordToKey(password, salt, iterations)
155
146
 
156
147
  try {
157
148
  const decryptedContent = (await e2ee.decryptObject(
@@ -160,18 +151,11 @@ async function decryptE2EEChapters(
160
151
  )) as Record<string, unknown>
161
152
 
162
153
  // Update the plaintext title.
163
- const titleNode = (
164
- decryptedContent.content as
165
- Record<string, unknown>[] | undefined
166
- )?.[0]
167
- const titleContent =
168
- (titleNode?.content as
169
- Record<string, unknown>[] | undefined) || []
154
+ const titleNode = (decryptedContent.content as Record<string, unknown>[] | undefined)?.[0]
155
+ const titleContent = (titleNode?.content as Record<string, unknown>[] | undefined) || []
170
156
  let title = ""
171
157
  titleContent.forEach(child => {
172
- const marks =
173
- (child.marks as
174
- Record<string, unknown>[] | undefined) || []
158
+ const marks = (child.marks as Record<string, unknown>[] | undefined) || []
175
159
  if (!marks.some(m => (m.type as string) === "deletion")) {
176
160
  title += (child.text as string) || ""
177
161
  }
@@ -179,36 +163,23 @@ async function decryptE2EEChapters(
179
163
  if (title) {
180
164
  doc.title = title.substring(0, 255)
181
165
  if (typeof sessionStorage !== "undefined") {
182
- sessionStorage.setItem(
183
- `e2ee_title_${String(doc.id)}`,
184
- doc.title
185
- )
166
+ sessionStorage.setItem(`e2ee_title_${String(doc.id)}`, doc.title)
186
167
  }
187
168
  }
188
169
 
189
170
  // Parse ProseMirror content.
190
171
  if (rawContent) {
191
172
  doc.rawContent = JSON.parse(
192
- JSON.stringify(
193
- schema
194
- .nodeFromJSON(
195
- decryptedContent as Record<string, unknown>
196
- )
197
- .toJSON()
198
- )
173
+ JSON.stringify(schema.nodeFromJSON(decryptedContent as Record<string, unknown>).toJSON())
199
174
  )
200
175
  }
201
176
  doc.content = acceptAllNoInsertions(
202
- schema.nodeFromJSON(
203
- decryptedContent as Record<string, unknown>
204
- )
177
+ schema.nodeFromJSON(decryptedContent as Record<string, unknown>)
205
178
  ).toJSON()
206
179
  doc.settings = getSettings(doc.content)
207
180
 
208
181
  // Decrypt encrypted images.
209
- const encryptedImageEntries = Object.entries(
210
- doc.images || {}
211
- ).filter(
182
+ const encryptedImageEntries = Object.entries(doc.images || {}).filter(
212
183
  ([, entry]) =>
213
184
  entry.file_type === "application/octet-stream" &&
214
185
  typeof entry.image === "string"
@@ -0,0 +1,2 @@
1
+ declare function gettext(text: string): string
2
+ declare function interpolate(fmt: string, ...args: unknown[]): string
@@ -5,14 +5,28 @@
5
5
  * chapter and delegates creation of the book record to a `BookImporterBackend`.
6
6
  */
7
7
 
8
- import type { NativeImporterBackend } from "@fiduswriter/document"
9
- import { NativeImporter } from "@fiduswriter/document/importer/native"
10
- import { addAlert, gettext } from "fwtoolkit"
8
+ import type {E2EEOptions, NativeImporterBackend} from "@fiduswriter/document"
9
+ import {NativeImporter} from "@fiduswriter/document/importer/native"
10
+ import {addAlert} from "fwtoolkit"
11
11
 
12
- import type { BookImporterBackend, Chapter, User } from "../../types.js"
12
+ import type {BookImporterBackend, Chapter, User} from "../../types.js"
13
13
 
14
- export { FIDUSBOOK_VERSION } from "./reader.js"
15
- export { readFidusBookFile, FidusBookReader } from "./reader.js"
14
+ export {FIDUSBOOK_VERSION} from "./reader.js"
15
+ export {readFidusBookFile, FidusBookReader} from "./reader.js"
16
+
17
+ export interface E2EEOptionsResult {
18
+ options: E2EEOptions
19
+ password: string
20
+ }
21
+
22
+ export interface NativeBookImporterOptions {
23
+ path?: string
24
+ getE2EEOptions?: () => Promise<E2EEOptionsResult | null>
25
+ onChapterImported?: (
26
+ doc: Record<string, unknown>,
27
+ password: string
28
+ ) => Promise<void>
29
+ }
16
30
 
17
31
  export class NativeBookImporter {
18
32
  file: Blob
@@ -20,6 +34,11 @@ export class NativeBookImporter {
20
34
  path: string
21
35
  nativeBackend: NativeImporterBackend
22
36
  bookBackend: BookImporterBackend
37
+ getE2EEOptions?: () => Promise<E2EEOptionsResult | null>
38
+ onChapterImported?: (
39
+ doc: Record<string, unknown>,
40
+ password: string
41
+ ) => Promise<void>
23
42
 
24
43
  ok: boolean
25
44
  statusText: string
@@ -30,13 +49,16 @@ export class NativeBookImporter {
30
49
  user: User,
31
50
  nativeBackend: NativeImporterBackend,
32
51
  bookBackend: BookImporterBackend,
33
- path = "/"
52
+ options: string | NativeBookImporterOptions = "/"
34
53
  ) {
54
+ const opts = typeof options === "string" ? {path: options} : options
35
55
  this.file = file
36
56
  this.user = user
37
- this.path = path.endsWith("/") ? path : path + "/"
57
+ this.path = opts.path?.endsWith("/") ? opts.path : `${opts.path || "/"}/`
38
58
  this.nativeBackend = nativeBackend
39
59
  this.bookBackend = bookBackend
60
+ this.getE2EEOptions = opts.getE2EEOptions
61
+ this.onChapterImported = opts.onChapterImported
40
62
 
41
63
  this.ok = false
42
64
  this.statusText = ""
@@ -68,8 +90,8 @@ export class NativeBookImporter {
68
90
  }
69
91
 
70
92
  async readZip(): Promise<void> {
71
- let textFiles: Array<{ filename: string; content: string }> = []
72
- let binaryFiles: Array<{ filename: string; content: Blob }> = []
93
+ let textFiles: Array<{filename: string; content: string}> = []
94
+ let binaryFiles: Array<{filename: string; content: Blob}> = []
73
95
 
74
96
  try {
75
97
  const JSZip = (await import("jszip")).default
@@ -113,15 +135,18 @@ export class NativeBookImporter {
113
135
  }
114
136
 
115
137
  async processFidusbookFile(
116
- textFiles: Array<{ filename: string; content: string }>,
117
- binaryFiles: Array<{ filename: string; content: Blob }>
138
+ textFiles: Array<{filename: string; content: string}>,
139
+ binaryFiles: Array<{filename: string; content: Blob}>
118
140
  ): Promise<void> {
119
141
  const versionEntry = textFiles.find(
120
142
  f => f.filename === "filetype-version"
121
143
  )
122
144
  const filetypeVersion = Number.parseFloat(versionEntry?.content || "")
123
145
 
124
- if (filetypeVersion < 1.0 || filetypeVersion > 1.0) {
146
+ if (
147
+ filetypeVersion < 1.0 ||
148
+ filetypeVersion > 1.0
149
+ ) {
125
150
  this.statusText =
126
151
  gettext(
127
152
  "The Fidusbook file version is not supported by this server: "
@@ -144,13 +169,9 @@ export class NativeBookImporter {
144
169
  textFiles.find(f => f.filename === "book.json")?.content || "{}"
145
170
  ) as Record<string, any>
146
171
 
147
- const sortedChapters = [
148
- ...(bookData.chapters as Array<{
149
- chapter_index: number
150
- number: number
151
- part?: string
152
- }>)
153
- ].sort((a, b) => a.chapter_index - b.chapter_index)
172
+ const sortedChapters = [...(bookData.chapters as Array<{chapter_index: number; number: number; part?: string}>)].sort(
173
+ (a, b) => a.chapter_index - b.chapter_index
174
+ )
154
175
 
155
176
  const importedDocIds: Record<number, number> = {}
156
177
 
@@ -177,10 +198,7 @@ export class NativeBookImporter {
177
198
  }
178
199
 
179
200
  const docJson = JSON.parse(docFile.content) as Record<string, any>
180
- const imagesJson = JSON.parse(imagesFile.content) as Record<
181
- string,
182
- any
183
- >
201
+ const imagesJson = JSON.parse(imagesFile.content) as Record<string, any>
184
202
  const bibJson = JSON.parse(bibFile.content) as Record<string, any>
185
203
 
186
204
  const chapterPrefix = `chapters/${ci}/images/`
@@ -194,21 +212,27 @@ export class NativeBookImporter {
194
212
  const safeBookTitle = (bookData.title as string) || "Untitled"
195
213
  const chapterPath = `${this.path}${safeBookTitle}/${(docJson.title as string) || "Untitled"}`
196
214
 
215
+ let e2eeResult: E2EEOptionsResult | null = null
216
+ if (this.getE2EEOptions) {
217
+ e2eeResult = await this.getE2EEOptions()
218
+ }
219
+
197
220
  const importer = new NativeImporter(
198
221
  docJson,
199
222
  bibJson,
200
- { db: imagesJson },
223
+ {db: imagesJson},
201
224
  chapterOtherFiles,
202
225
  this.user,
203
226
  this.nativeBackend,
204
227
  {
205
- requestedPath: chapterPath
228
+ requestedPath: chapterPath,
229
+ e2eeOptions: e2eeResult?.options ?? null
206
230
  }
207
231
  )
208
232
 
209
233
  let doc
210
234
  try {
211
- ;({ doc } = await importer.init())
235
+ ;({doc} = await importer.init())
212
236
  } catch (error) {
213
237
  addAlert(
214
238
  "error",
@@ -220,6 +244,10 @@ export class NativeBookImporter {
220
244
  }
221
245
 
222
246
  importedDocIds[ci] = doc.id as number
247
+
248
+ if (e2eeResult && this.onChapterImported) {
249
+ await this.onChapterImported(doc, e2eeResult.password)
250
+ }
223
251
  }
224
252
 
225
253
  const chapters: Chapter[] = sortedChapters.map(chapter => ({
@@ -228,11 +256,7 @@ export class NativeBookImporter {
228
256
  part: chapter.part || ""
229
257
  }))
230
258
 
231
- const book = await this.bookBackend.createBook(
232
- bookData as any,
233
- chapters,
234
- false
235
- )
259
+ const book = await this.bookBackend.createBook(bookData as any, chapters, false)
236
260
  this.bookId = book.id || null
237
261
  this.ok = true
238
262
  this.statusText = `"${bookData.title}" ${gettext("successfully imported.")}`
@@ -6,7 +6,7 @@
6
6
  * exporters. No server interaction.
7
7
  */
8
8
 
9
- import type { DocumentListEntry } from "../../types.js"
9
+ import type {DocumentListEntry} from "../../types.js"
10
10
 
11
11
  export const FIDUSBOOK_VERSION = "1.0"
12
12
  export const MIN_FIDUSBOOK_VERSION = 1.0
@@ -58,7 +58,7 @@ export async function readFidusBookFile(
58
58
  const content = await zipfs.files[filename].async(
59
59
  isText ? "string" : "blob"
60
60
  )
61
- const entry = { filename, content }
61
+ const entry = {filename, content}
62
62
  if (isText) {
63
63
  textFiles.push(entry as ArchiveFile)
64
64
  } else {
@@ -93,9 +93,9 @@ export async function readFidusBookFile(
93
93
  textFiles.find(f => f.filename === "book.json")?.content as string
94
94
  ) as Record<string, unknown>
95
95
 
96
- const sortedChapters = [
97
- ...(bookData.chapters as Array<{ chapter_index: number }>)
98
- ].sort((a, b) => a.chapter_index - b.chapter_index)
96
+ const sortedChapters = [...(bookData.chapters as Array<{chapter_index: number}>)].sort(
97
+ (a, b) => a.chapter_index - b.chapter_index
98
+ )
99
99
 
100
100
  const documentList: DocumentListEntry[] = []
101
101
 
@@ -116,18 +116,9 @@ export async function readFidusBookFile(
116
116
  throw new Error(`Missing chapter data for index ${ci}`)
117
117
  }
118
118
 
119
- const docJson = JSON.parse(docFile.content as string) as Record<
120
- string,
121
- unknown
122
- >
123
- const imagesJson = JSON.parse(imagesFile.content as string) as Record<
124
- string,
125
- { image: string; file?: Blob }
126
- >
127
- const bibJson = JSON.parse(bibFile.content as string) as Record<
128
- string,
129
- unknown
130
- >
119
+ const docJson = JSON.parse(docFile.content as string) as Record<string, unknown>
120
+ const imagesJson = JSON.parse(imagesFile.content as string) as Record<string, {image: string; file?: Blob}>
121
+ const bibJson = JSON.parse(bibFile.content as string) as Record<string, unknown>
131
122
 
132
123
  const chapterPrefix = `chapters/${ci}/images/`
133
124
  const chapterImages: Record<string, Blob> = {}
@@ -164,7 +155,7 @@ export async function readFidusBookFile(
164
155
  } as DocumentListEntry)
165
156
  }
166
157
 
167
- return { book: bookData, documentList }
158
+ return {book: bookData, documentList}
168
159
  }
169
160
 
170
161
  export class FidusBookReader {
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { FIDUSBOOK_VERSION } from "./schema/index.js"
1
+ export {FIDUSBOOK_VERSION} from "./schema/index.js"
2
2
  export type {
3
3
  Book,
4
4
  BookBaseMetadata,
package/src/modules.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  declare module "pretty" {
2
- function pretty(html: string, options?: { ocd?: boolean }): string
2
+ function pretty(html: string, options?: {ocd?: boolean}): string
3
3
  export default pretty
4
4
  }
5
5
 
package/src/types.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Core types for the @fiduswriter/books-document package.
3
3
  */
4
4
 
5
- import type { Schema } from "prosemirror-model"
5
+ import type {Schema} from "prosemirror-model"
6
6
  import type {
7
7
  BibDB,
8
8
  CSL,
@@ -12,7 +12,7 @@ import type {
12
12
  User
13
13
  } from "@fiduswriter/document"
14
14
 
15
- export type { CSL, User } from "@fiduswriter/document"
15
+ export type {CSL, User} from "@fiduswriter/document"
16
16
 
17
17
  /** A single chapter entry inside a book. */
18
18
  export interface Chapter {