@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,401 @@
1
+ import {LANGUAGES} from "@fiduswriter/document/schema/const"
2
+ import {escapeText, localizeDate} from "fwtoolkit"
3
+ import {mathliveOpfIncludes} from "@fiduswriter/document/mathlive/opf_includes"
4
+
5
+ import type {Book} from "../../types.js"
6
+ import {bookTerm} from "../../i18n.js"
7
+
8
+ export const containerTemplate = () => `<?xml version="1.0" encoding="UTF-8"?>
9
+ <container xmlns="urn:oasis:names:tc:opendocument:xmlns:container" version="1.0">
10
+ <rootfiles>
11
+ <rootfile full-path="EPUB/document.opf" media-type="application/oebps-package+xml"/>
12
+ </rootfiles>
13
+ </container>`
14
+
15
+ interface CoverImage {
16
+ image: string
17
+ }
18
+
19
+ export const epubBookCoverTemplate = ({
20
+ book,
21
+ coverImage,
22
+ shortLang
23
+ }: {
24
+ book: Book
25
+ coverImage: CoverImage
26
+ shortLang: string
27
+ }) =>
28
+ `<?xml version="1.0" encoding="UTF-8"?>
29
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="${shortLang}" lang="${shortLang}">
30
+ <head>
31
+ <title>${escapeText(book.title)}</title>
32
+ <meta charset="utf-8"/>
33
+ </head>
34
+ <body class="epub cover">
35
+ <div id="cover">
36
+ <img src="${coverImage.image.split("/").pop()?.split("?")[0]}"
37
+ alt="${bookTerm("Cover image", book.settings.language)}"
38
+ title="${bookTerm("Cover image", book.settings.language)}"/>
39
+ </div>
40
+ </body>
41
+ </html>`
42
+
43
+ export const epubBookTitlepageTemplate = ({
44
+ book,
45
+ shortLang
46
+ }: {
47
+ book: Book
48
+ shortLang: string
49
+ }) =>
50
+ `<?xml version="1.0" encoding="UTF-8"?>
51
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="${shortLang}" lang="${shortLang}">
52
+ <head>
53
+ <title>${escapeText(book.title)}</title>
54
+ <meta charset="utf-8"/>
55
+ </head>
56
+ <body class="epub titlepage">
57
+ <div id="title" epub:type="frontmatter titlepage">
58
+ <h1 class="booktitle">${escapeText(book.title)}</h1>
59
+ ${
60
+ book.metadata.subtitle
61
+ ? `<h2 class="booksubtitle">${escapeText(book.metadata.subtitle)}</h2>`
62
+ : ""
63
+ }
64
+ ${
65
+ book.metadata.author
66
+ ? `<h3 class="bookauthor">${bookTerm("by", book.settings.language)} ${escapeText(book.metadata.author)}</h3>`
67
+ : ""
68
+ }
69
+ ${
70
+ book.metadata.version
71
+ ? `<h4 class="bookversion">${escapeText(book.metadata.version)}</h4>`
72
+ : ""
73
+ }
74
+ ${
75
+ book.metadata.series_title
76
+ ? `<p class="bookseries">${escapeText(book.metadata.series_title)}${
77
+ book.metadata.series_position
78
+ ? ` \u2013 ${bookTerm("Series position", book.settings.language)} ${escapeText(book.metadata.series_position)}`
79
+ : ""
80
+ }</p>`
81
+ : ""
82
+ }
83
+ </div>
84
+ </body>
85
+ </html>`
86
+
87
+ export const epubBookCopyrightTemplate = ({
88
+ book,
89
+ language,
90
+ shortLang,
91
+ creator
92
+ }: {
93
+ book: Book
94
+ language: string
95
+ shortLang: string
96
+ creator: string
97
+ }) =>
98
+ `<?xml version="1.0" encoding="UTF-8"?>
99
+ <html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="${shortLang}" lang="${shortLang}">
100
+ <head>
101
+ <title>${escapeText(book.title)}</title>
102
+ <meta charset="utf-8"/>
103
+ </head>
104
+ <body class="epub copyrightpage">
105
+ <section epub:type="frontmatter copyright-page">
106
+ <div id="copyright">
107
+ <p>${escapeText(book.title)}${
108
+ book.metadata.author
109
+ ? ` ${bookTerm("by", book.settings.language)} ${escapeText(book.metadata.author)}`
110
+ : ""
111
+ }</p>
112
+ ${
113
+ book.metadata.copyright
114
+ ? `<p>${escapeText(book.metadata.copyright)}</p>`
115
+ : ""
116
+ }
117
+ <p>${bookTerm("Title", book.settings.language)}: ${escapeText(book.title)}</p>
118
+ ${
119
+ book.metadata.author
120
+ ? `<p>${bookTerm("Author", book.settings.language)}: ${escapeText(book.metadata.author)}</p>`
121
+ : ""
122
+ }
123
+ ${
124
+ book.metadata.publisher
125
+ ? `<p>${bookTerm("Published by", book.settings.language)}: ${escapeText(book.metadata.publisher)}</p>`
126
+ : ""
127
+ }
128
+ ${
129
+ book.metadata.isbn
130
+ ? `<p>${bookTerm("ISBN", book.settings.language)}: ${escapeText(book.metadata.isbn)}</p>`
131
+ : ""
132
+ }
133
+ ${
134
+ book.metadata.publication_date
135
+ ? `<p>${bookTerm("Publication date", book.settings.language)}: ${escapeText(book.metadata.publication_date)}</p>`
136
+ : ""
137
+ }
138
+ ${
139
+ book.metadata.series_title
140
+ ? `<p>${bookTerm("Series", book.settings.language)}: ${escapeText(book.metadata.series_title)}${
141
+ book.metadata.series_position
142
+ ? ` (${bookTerm("Series position", book.settings.language)}: ${escapeText(book.metadata.series_position)})`
143
+ : ""
144
+ }</p>`
145
+ : ""
146
+ }
147
+ ${
148
+ book.metadata.description
149
+ ? `<p class="book-description">${escapeText(book.metadata.description).replace(/\n/g, "<br>")}</p>`
150
+ : ""
151
+ }
152
+ <p>${bookTerm("Last updated", book.settings.language)}: ${localizeDate(
153
+ (book.updated || 0) * 1000,
154
+ "sortable-date"
155
+ )}</p>
156
+ <p>${bookTerm("Created", book.settings.language)}: ${localizeDate(
157
+ (book.added || 0) * 1000,
158
+ "sortable-date"
159
+ )}</p>
160
+ <p>${bookTerm("Language", book.settings.language)}: ${
161
+ LANGUAGES.find(lang => lang[0] === language)?.[1]
162
+ }</p>
163
+ <p>${bookTerm("Created by", book.settings.language)}: ${escapeText(creator)}</p>
164
+ </div>
165
+ </section>
166
+ </body>
167
+ </html>`
168
+
169
+ export const epubBookOpfTemplate = ({
170
+ book,
171
+ language,
172
+ idType,
173
+ date,
174
+ modified,
175
+ styleSheets,
176
+ math,
177
+ images,
178
+ fontFiles,
179
+ chapters,
180
+ user
181
+ }: {
182
+ book: Book
183
+ language: string
184
+ idType: string
185
+ date: string
186
+ modified: string
187
+ styleSheets: Array<{filename: string}>
188
+ math: boolean
189
+ images: Array<{coverImage?: boolean; filename: string; mimeType?: string}>
190
+ fontFiles: Array<{filename: string; mimeType?: string}>
191
+ chapters: Array<{number: number}>
192
+ user: Record<string, string>
193
+ }) => `<?xml version="1.0" encoding="UTF-8"?>
194
+ <package xmlns="http://www.idpf.org/2007/opf" version="3.0"
195
+ unique-identifier="${idType}" xml:lang="${language}"
196
+ prefix="cc: http://creativecommons.org/ns#">
197
+ <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
198
+ <dc:identifier id="${idType}">${book.id}</dc:identifier>
199
+ <dc:title>${escapeText(book.title)}</dc:title>
200
+ <dc:creator>${
201
+ book.metadata.author?.length
202
+ ? escapeText(book.metadata.author)
203
+ : escapeText(user.name)
204
+ }</dc:creator>
205
+ <dc:language>${language}</dc:language>
206
+ <meta property="dcterms:modified">${modified}</meta>
207
+ <dc:date>${book.metadata.publication_date || date}</dc:date>
208
+ ${
209
+ book.metadata.copyright
210
+ ? `<dc:rights>${escapeText(book.metadata.copyright)}</dc:rights>`
211
+ : ""
212
+ }
213
+ ${
214
+ book.metadata.publisher
215
+ ? `<dc:publisher>${escapeText(book.metadata.publisher)}</dc:publisher>`
216
+ : ""
217
+ }
218
+ ${
219
+ book.metadata.description
220
+ ? `<dc:description>${escapeText(book.metadata.description)}</dc:description>`
221
+ : ""
222
+ }
223
+ ${
224
+ book.metadata.isbn
225
+ ? `<dc:identifier id="isbn">${escapeText(book.metadata.isbn)}</dc:identifier>`
226
+ : ""
227
+ }
228
+ ${
229
+ book.metadata.series_title
230
+ ? `<meta property="belongs-to-collection" id="series01">${escapeText(book.metadata.series_title)}</meta>
231
+ <meta refines="#series01" property="collection-type">series</meta>
232
+ ${
233
+ book.metadata.series_position
234
+ ? `<meta refines="#series01" property="group-position">${escapeText(book.metadata.series_position)}</meta>`
235
+ : ""
236
+ }`
237
+ : ""
238
+ }
239
+ ${
240
+ book.metadata.keywords
241
+ ? book.metadata.keywords
242
+ .split(",")
243
+ .map(
244
+ keyword =>
245
+ `<dc:subject>${escapeText(keyword.trim())}</dc:subject>`
246
+ )
247
+ .join("")
248
+ : ""
249
+ }
250
+ </metadata>
251
+ <manifest>
252
+ ${
253
+ book.cover_image
254
+ ? '<item id="cover" href="cover.xhtml" media-type="application/xhtml+xml"/>'
255
+ : ""
256
+ }
257
+ <item id="titlepage" href="titlepage.xhtml" media-type="application/xhtml+xml"/>
258
+ ${chapters
259
+ .map(
260
+ chapter =>
261
+ `<item id="t${chapter.number}" href="document-${chapter.number}.xhtml"
262
+ media-type="application/xhtml+xml" />`
263
+ )
264
+ .join("")}
265
+ <item id="nav" href="document-nav.xhtml" properties="nav"
266
+ media-type="application/xhtml+xml" />
267
+ <item id="copyright" href="copyright.xhtml" media-type="application/xhtml+xml"/>
268
+ ${images
269
+ .map(
270
+ (image, index) =>
271
+ `<item ${
272
+ image.coverImage
273
+ ? 'id="cover-image" properties="cover-image"'
274
+ : `id="img${index}"`
275
+ } href="${image.filename}" media-type="${image.mimeType}"/>`
276
+ )
277
+ .join("")}
278
+ ${fontFiles
279
+ .map(
280
+ (font, index) =>
281
+ `<item id="font${index}" href="${font.filename}"
282
+ media-type="${font.mimeType}" />`
283
+ )
284
+ .join("")}
285
+ ${styleSheets
286
+ .map(
287
+ (sheet, index) =>
288
+ `<item id="css${index}" href="${sheet.filename}"
289
+ media-type="text/css" />`
290
+ )
291
+ .join("")}
292
+ ${math ? mathliveOpfIncludes : ""}
293
+ <item id="ncx" href="document.ncx" media-type="application/x-dtbncx+xml" />
294
+ </manifest>
295
+ <spine toc="ncx">
296
+ ${book.cover_image ? '<itemref idref="cover" linear="no"/>' : ""}
297
+ <itemref idref="titlepage" linear="yes"/>
298
+ ${chapters
299
+ .map(chapter => `<itemref idref="t${chapter.number}" linear="yes" />`)
300
+ .join("")}
301
+ <itemref idref="copyright" linear="yes"/>
302
+ <itemref idref="nav" linear="no"/>
303
+ </spine>
304
+ </package>`
305
+
306
+ interface TocItem {
307
+ link: string
308
+ title: string
309
+ children?: TocItem[]
310
+ }
311
+
312
+ export const navTemplate = ({
313
+ shortLang,
314
+ toc,
315
+ styleSheets
316
+ }: {
317
+ shortLang: string
318
+ toc: TocItem[]
319
+ styleSheets: Array<{filename: string}>
320
+ }) =>
321
+ `<?xml version="1.0" encoding="UTF-8"?>
322
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="${shortLang}"
323
+ lang="${shortLang}" xmlns:epub="http://www.idpf.org/2007/ops">
324
+ <head>
325
+ <meta charset="utf-8"/>
326
+ <title>Navigation</title>
327
+ ${styleSheets
328
+ .map(
329
+ sheet =>
330
+ `<link rel="stylesheet" type="text/css" href="${sheet.filename}" />`
331
+ )
332
+ .join("")}
333
+ </head>
334
+ <body class="epub navigation">
335
+ <nav epub:type="toc" id="toc">
336
+ <ol>
337
+ ${renderTocItems(toc)}
338
+ </ol>
339
+ </nav>
340
+ </body>
341
+ </html>`
342
+
343
+ const renderTocItems = (items: TocItem[]): string =>
344
+ items
345
+ .map(
346
+ item => `
347
+ <li>
348
+ <a href="${item.link}">${escapeText(item.title)}</a>
349
+ ${
350
+ item.children?.length
351
+ ? `<ol>${renderTocItems(item.children)}</ol>`
352
+ : ""
353
+ }
354
+ </li>
355
+ `
356
+ )
357
+ .join("")
358
+
359
+ export const ncxTemplate = ({
360
+ shortLang,
361
+ idType,
362
+ id,
363
+ title,
364
+ toc
365
+ }: {
366
+ shortLang: string
367
+ idType: string
368
+ id: number | undefined
369
+ title: string
370
+ toc: TocItem[]
371
+ }) =>
372
+ `<?xml version="1.0" encoding="UTF-8"?>
373
+ <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" xml:lang="${shortLang}">
374
+ <head>
375
+ <meta name="dtb:${idType}" content="${id}"/\u003e
376
+ </head>
377
+ <docTitle>
378
+ <text>${escapeText(title)}</text>
379
+ </docTitle>
380
+ <navMap>
381
+ ${renderNcxItems(toc)}
382
+ </navMap>
383
+ </ncx>`
384
+
385
+ const renderNcxItems = (
386
+ items: TocItem[],
387
+ counter: {count: number} = {count: 1}
388
+ ): string =>
389
+ items
390
+ .map(
391
+ item => `
392
+ <navPoint id="np-${counter.count++}" playOrder="${counter.count}">
393
+ <navLabel>
394
+ <text>${escapeText(item.title)}</text>
395
+ </navLabel>
396
+ <content src="${item.link}"/\u003e
397
+ ${item.children?.length ? renderNcxItems(item.children, counter) : ""}
398
+ </navPoint>
399
+ `
400
+ )
401
+ .join("")
@@ -0,0 +1,68 @@
1
+ export function getTimestamp(date: Date): string {
2
+ return date.toISOString().replace(/\.\d{3}/, "")
3
+ }
4
+
5
+ export function getFontMimeType(filename: string): string | null {
6
+ const fontMimeTypes: Record<string, string> = {
7
+ ttf: "font/ttf",
8
+ otf: "font/otf",
9
+ woff: "font/woff",
10
+ woff2: "font/woff2"
11
+ }
12
+ const ext = filename.split(".").pop()?.toLowerCase()
13
+ return ext ? fontMimeTypes[ext] || null : null
14
+ }
15
+
16
+ export function getImageMimeType(filename: string): string | null {
17
+ const imageMimeTypes: Record<string, string> = {
18
+ jpg: "image/jpeg",
19
+ jpeg: "image/jpeg",
20
+ png: "image/png",
21
+ gif: "image/gif",
22
+ svg: "image/svg+xml"
23
+ }
24
+ const ext = filename.split(".").pop()?.toLowerCase()
25
+ return ext ? imageMimeTypes[ext] || null : null
26
+ }
27
+
28
+ export function buildHierarchy(
29
+ flatItems: Array<Record<string, unknown>>
30
+ ): Array<Record<string, unknown>> {
31
+ const root: Array<Record<string, unknown>> = []
32
+ const idMap: Record<string | number, Record<string, unknown>> = {}
33
+
34
+ flatItems.forEach(item => {
35
+ idMap[item.id as string | number] = {
36
+ ...item,
37
+ children: []
38
+ }
39
+ })
40
+
41
+ flatItems.forEach(item => {
42
+ const node = idMap[item.id as string | number]
43
+ if (item.level === -1 || item.level === 0) {
44
+ root.push(node)
45
+ } else {
46
+ let parentLevel = (item.level as number) - 1
47
+ let parent: Record<string, unknown> | undefined
48
+ while (parentLevel >= 0 && !parent) {
49
+ parent = flatItems.find(
50
+ p =>
51
+ p.level === parentLevel &&
52
+ p.docNum === item.docNum &&
53
+ (p.id as number) < (item.id as number)
54
+ )
55
+ parentLevel--
56
+ }
57
+ if (parent) {
58
+ ;(idMap[parent.id as string | number].children as Array<
59
+ Record<string, unknown>
60
+ >).push(node)
61
+ } else {
62
+ root.push(node)
63
+ }
64
+ }
65
+ })
66
+
67
+ return root
68
+ }