@fiduswriter/bibliography-manager 0.1.6 → 0.1.8

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 (175) hide show
  1. package/dist/database/index.d.ts +12 -11
  2. package/dist/database/index.d.ts.map +1 -1
  3. package/dist/database/index.js +22 -16
  4. package/dist/database/index.js.map +1 -1
  5. package/dist/database/server_connector.d.ts +14 -15
  6. package/dist/database/server_connector.d.ts.map +1 -1
  7. package/dist/database/server_connector.js +17 -9
  8. package/dist/database/server_connector.js.map +1 -1
  9. package/dist/export/index.d.ts +6 -4
  10. package/dist/export/index.d.ts.map +1 -1
  11. package/dist/export/index.js +7 -1
  12. package/dist/export/index.js.map +1 -1
  13. package/dist/form/cats.d.ts +5 -4
  14. package/dist/form/cats.d.ts.map +1 -1
  15. package/dist/form/cats.js +2 -0
  16. package/dist/form/cats.js.map +1 -1
  17. package/dist/form/fields/date.d.ts +4 -4
  18. package/dist/form/fields/date.d.ts.map +1 -1
  19. package/dist/form/fields/date.js +5 -1
  20. package/dist/form/fields/date.js.map +1 -1
  21. package/dist/form/fields/key.d.ts +11 -9
  22. package/dist/form/fields/key.d.ts.map +1 -1
  23. package/dist/form/fields/key.js +13 -6
  24. package/dist/form/fields/key.js.map +1 -1
  25. package/dist/form/fields/key_list.d.ts +10 -8
  26. package/dist/form/fields/key_list.d.ts.map +1 -1
  27. package/dist/form/fields/key_list.js +4 -0
  28. package/dist/form/fields/key_list.js.map +1 -1
  29. package/dist/form/fields/literal.d.ts +4 -4
  30. package/dist/form/fields/literal.d.ts.map +1 -1
  31. package/dist/form/fields/literal.js +2 -1
  32. package/dist/form/fields/literal.js.map +1 -1
  33. package/dist/form/fields/literal_list.d.ts +8 -7
  34. package/dist/form/fields/literal_list.d.ts.map +1 -1
  35. package/dist/form/fields/literal_list.js +3 -0
  36. package/dist/form/fields/literal_list.js.map +1 -1
  37. package/dist/form/fields/literal_long.d.ts +4 -4
  38. package/dist/form/fields/literal_long.d.ts.map +1 -1
  39. package/dist/form/fields/literal_long.js +1 -0
  40. package/dist/form/fields/literal_long.js.map +1 -1
  41. package/dist/form/fields/name.d.ts +10 -27
  42. package/dist/form/fields/name.d.ts.map +1 -1
  43. package/dist/form/fields/name.js +22 -18
  44. package/dist/form/fields/name.js.map +1 -1
  45. package/dist/form/fields/name_list.d.ts +9 -7
  46. package/dist/form/fields/name_list.d.ts.map +1 -1
  47. package/dist/form/fields/name_list.js +5 -2
  48. package/dist/form/fields/name_list.js.map +1 -1
  49. package/dist/form/fields/range.d.ts +10 -8
  50. package/dist/form/fields/range.d.ts.map +1 -1
  51. package/dist/form/fields/range.js +13 -9
  52. package/dist/form/fields/range.js.map +1 -1
  53. package/dist/form/fields/range_list.d.ts +9 -7
  54. package/dist/form/fields/range_list.d.ts.map +1 -1
  55. package/dist/form/fields/range_list.js +3 -0
  56. package/dist/form/fields/range_list.js.map +1 -1
  57. package/dist/form/fields/tag_list.d.ts +7 -6
  58. package/dist/form/fields/tag_list.d.ts.map +1 -1
  59. package/dist/form/fields/tag_list.js +3 -0
  60. package/dist/form/fields/tag_list.js.map +1 -1
  61. package/dist/form/fields/title.d.ts +4 -4
  62. package/dist/form/fields/title.d.ts.map +1 -1
  63. package/dist/form/fields/title.js +1 -0
  64. package/dist/form/fields/title.js.map +1 -1
  65. package/dist/form/fields/uri.d.ts +4 -4
  66. package/dist/form/fields/uri.d.ts.map +1 -1
  67. package/dist/form/fields/uri.js +5 -1
  68. package/dist/form/fields/uri.js.map +1 -1
  69. package/dist/form/fields/verbatim.d.ts +4 -4
  70. package/dist/form/fields/verbatim.d.ts.map +1 -1
  71. package/dist/form/fields/verbatim.js +5 -1
  72. package/dist/form/fields/verbatim.js.map +1 -1
  73. package/dist/form/index.d.ts +32 -30
  74. package/dist/form/index.d.ts.map +1 -1
  75. package/dist/form/index.js +33 -11
  76. package/dist/form/index.js.map +1 -1
  77. package/dist/form/strings.d.ts +11 -11
  78. package/dist/form/strings.d.ts.map +1 -1
  79. package/dist/form/strings.js +5 -5
  80. package/dist/form/strings.js.map +1 -1
  81. package/dist/form/templates.d.ts +6 -5
  82. package/dist/form/templates.d.ts.map +1 -1
  83. package/dist/form/templates.js +2 -2
  84. package/dist/form/templates.js.map +1 -1
  85. package/dist/import/bibliography_import.d.ts +20 -7
  86. package/dist/import/bibliography_import.d.ts.map +1 -1
  87. package/dist/import/bibliography_import.js +15 -7
  88. package/dist/import/bibliography_import.js.map +1 -1
  89. package/dist/import/dialog.d.ts +6 -5
  90. package/dist/import/dialog.d.ts.map +1 -1
  91. package/dist/import/dialog.js +27 -12
  92. package/dist/import/dialog.js.map +1 -1
  93. package/dist/import/index.d.ts +2 -0
  94. package/dist/import/index.d.ts.map +1 -1
  95. package/dist/import/index.js +5 -0
  96. package/dist/import/index.js.map +1 -1
  97. package/dist/import/templates.d.ts +2 -1
  98. package/dist/import/templates.d.ts.map +1 -1
  99. package/dist/import/templates.js.map +1 -1
  100. package/dist/index.d.ts +2 -0
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js.map +1 -1
  103. package/dist/overview/index.d.ts +43 -27
  104. package/dist/overview/index.d.ts.map +1 -1
  105. package/dist/overview/index.js +59 -23
  106. package/dist/overview/index.js.map +1 -1
  107. package/dist/overview/menu.d.ts +13 -12
  108. package/dist/overview/menu.d.ts.map +1 -1
  109. package/dist/overview/menu.js +13 -10
  110. package/dist/overview/menu.js.map +1 -1
  111. package/dist/overview/templates.d.ts +5 -3
  112. package/dist/overview/templates.d.ts.map +1 -1
  113. package/dist/overview/templates.js.map +1 -1
  114. package/dist/plugins/bibliography_overview/index.d.ts +1 -1
  115. package/dist/plugins/bibliography_overview/index.d.ts.map +1 -1
  116. package/dist/plugins/bibliography_overview/index.js.map +1 -1
  117. package/dist/schema/csl_bib.d.ts +1 -1
  118. package/dist/schema/literal.d.ts +1 -1
  119. package/dist/schema/literal.d.ts.map +1 -1
  120. package/dist/schema/literal.js.map +1 -1
  121. package/dist/schema/literal_long.d.ts +1 -1
  122. package/dist/schema/literal_long.d.ts.map +1 -1
  123. package/dist/schema/literal_long.js +1 -7
  124. package/dist/schema/literal_long.js.map +1 -1
  125. package/dist/schema/title.d.ts +1 -1
  126. package/dist/schema/title.d.ts.map +1 -1
  127. package/dist/schema/title.js.map +1 -1
  128. package/dist/tools.d.ts +4 -3
  129. package/dist/tools.d.ts.map +1 -1
  130. package/dist/tools.js.map +1 -1
  131. package/dist/types/biblio.d.ts +138 -0
  132. package/dist/types/biblio.d.ts.map +1 -0
  133. package/dist/types/biblio.js +2 -0
  134. package/dist/types/biblio.js.map +1 -0
  135. package/package.json +1 -1
  136. package/src/database/{index.js → index.ts} +60 -38
  137. package/src/database/server_connector.ts +92 -0
  138. package/src/export/{index.js → index.ts} +16 -4
  139. package/src/form/{cats.js → cats.ts} +11 -3
  140. package/src/form/fields/{date.js → date.ts} +10 -5
  141. package/src/form/fields/{key.js → key.ts} +37 -19
  142. package/src/form/fields/{key_list.js → key_list.ts} +18 -7
  143. package/src/form/fields/{literal.js → literal.ts} +11 -5
  144. package/src/form/fields/{literal_list.js → literal_list.ts} +19 -10
  145. package/src/form/fields/{literal_long.js → literal_long.ts} +6 -4
  146. package/src/form/fields/{name.js → name.ts} +53 -39
  147. package/src/form/fields/name_list.ts +49 -0
  148. package/src/form/fields/{range.js → range.ts} +34 -22
  149. package/src/form/fields/{range_list.js → range_list.ts} +17 -10
  150. package/src/form/fields/{tag_list.js → tag_list.ts} +9 -5
  151. package/src/form/fields/{title.js → title.ts} +6 -4
  152. package/src/form/fields/{uri.js → uri.ts} +11 -6
  153. package/src/form/fields/{verbatim.js → verbatim.ts} +10 -5
  154. package/src/form/{index.js → index.ts} +113 -60
  155. package/src/form/{strings.js → strings.ts} +24 -22
  156. package/src/form/{templates.js → templates.ts} +14 -5
  157. package/src/global.d.ts +75 -0
  158. package/src/import/{bibliography_import.js → bibliography_import.ts} +42 -16
  159. package/src/import/{dialog.js → dialog.ts} +47 -23
  160. package/src/import/index.ts +14 -0
  161. package/src/import/{templates.js → templates.ts} +1 -1
  162. package/src/overview/{index.js → index.ts} +150 -81
  163. package/src/overview/{menu.js → menu.ts} +18 -12
  164. package/src/overview/{templates.js → templates.ts} +3 -2
  165. package/src/plugins/bibliography_overview/index.ts +1 -0
  166. package/src/schema/{literal_long.js → literal_long.ts} +3 -8
  167. package/src/schema/{title.js → title.ts} +1 -1
  168. package/src/{tools.js → tools.ts} +7 -5
  169. package/src/types/biblio.ts +189 -0
  170. package/src/database/server_connector.js +0 -57
  171. package/src/form/fields/name_list.js +0 -42
  172. package/src/import/index.js +0 -2
  173. package/src/plugins/bibliography_overview/index.js +0 -1
  174. /package/src/{index.js → index.ts} +0 -0
  175. /package/src/schema/{literal.js → literal.ts} +0 -0
@@ -12,17 +12,51 @@ import {
12
12
  setDocTitle,
13
13
  whenReady
14
14
  } from "fwtoolkit"
15
+ import type {DialogButtonSpec} from "fwtoolkit/dialog"
16
+ import type {DatatableBulk} from "fwtoolkit"
17
+ import type {OverviewMenuModel} from "fwtoolkit/overview_menu"
18
+ import type {ContentMenuInit} from "fwtoolkit/content_menu"
19
+ import type {DataTable} from "simple-datatables"
15
20
  import {baseBodyTemplate, FeedbackTab, SiteMenu} from "@fiduswriter/common"
16
- import {plugins} from "../plugins/bibliography_overview/index.js"
21
+ import {plugins as defaultBibPlugins} from "../plugins/bibliography_overview/index.js"
17
22
  import {getBibTypeTitle} from "../form/strings.js"
18
23
  import {litToText, nameToText} from "../tools.js"
24
+ import type {
25
+ BibCategory,
26
+ BibliographyApp,
27
+ IdTranslation,
28
+ NameDictObject,
29
+ NodeArray
30
+ } from "../types/biblio.js"
19
31
  import {bulkMenuModel, menuModel} from "./menu.js"
20
32
  import {editCategoriesTemplate} from "./templates.js"
21
33
 
34
+ interface PluginExport {
35
+ new (overview: BibliographyOverview): {init: () => Promise<unknown> | void}
36
+ name: string
37
+ }
38
+
39
+ type BibPlugin = [string, Record<string, PluginExport>]
40
+
22
41
  export class BibliographyOverview {
23
- constructor({app, user}) {
42
+ app: BibliographyApp
43
+ user: Record<string, unknown>
44
+ bibPlugins: BibPlugin[]
45
+ lastSort: {column: number; dir: "asc" | "desc"}
46
+ dom!: HTMLElement
47
+ overviewTable?: OverviewDataTable
48
+ table?: DataTable
49
+ dtBulk?: DatatableBulk
50
+ menu?: OverviewMenuView
51
+ plugins?: Record<string, {init: () => Promise<unknown> | void}>
52
+
53
+ constructor(
54
+ {app, user}: {app: BibliographyApp; user: Record<string, unknown>},
55
+ bibPlugins: BibPlugin[] = defaultBibPlugins as BibPlugin[]
56
+ ) {
24
57
  this.app = app
25
58
  this.user = user
59
+ this.bibPlugins = bibPlugins
26
60
 
27
61
  this.lastSort = {column: 0, dir: "asc"}
28
62
  }
@@ -30,12 +64,15 @@ export class BibliographyOverview {
30
64
  /** Bind the init function to doc loading.
31
65
  * @function bind
32
66
  */
33
- init() {
67
+ init(): Promise<void> {
34
68
  return whenReady().then(() => {
35
69
  this.render()
36
70
  const smenu = new SiteMenu(this.app, "bibliography")
37
71
  smenu.init()
38
- this.menu = new OverviewMenuView(this, menuModel)
72
+ this.menu = new OverviewMenuView(
73
+ this,
74
+ menuModel as () => OverviewMenuModel
75
+ )
39
76
  this.menu.init()
40
77
  this.setBibCategoryList(this.app.bibDB.cats)
41
78
  this.initTable(Object.keys(this.app.bibDB.db))
@@ -47,7 +84,7 @@ export class BibliographyOverview {
47
84
  })
48
85
  }
49
86
 
50
- render() {
87
+ render(): void {
51
88
  this.dom = document.createElement("body")
52
89
  this.dom.innerHTML = baseBodyTemplate({
53
90
  contents: "",
@@ -66,7 +103,7 @@ export class BibliographyOverview {
66
103
  feedbackTab.init()
67
104
  }
68
105
 
69
- onResize() {
106
+ onResize(): void {
70
107
  if (!this.table) {
71
108
  return
72
109
  }
@@ -74,18 +111,18 @@ export class BibliographyOverview {
74
111
  }
75
112
 
76
113
  /* Initialize the overview table */
77
- initTable(ids) {
114
+ initTable(ids: string[]): void {
78
115
  if (this.overviewTable) {
79
116
  this.overviewTable.destroy()
80
- this.overviewTable = null
117
+ this.overviewTable = undefined
81
118
  }
82
- this.table = null
83
- this.dtBulk = null
119
+ this.table = undefined
120
+ this.dtBulk = undefined
84
121
 
85
- const contentsEl = this.dom.querySelector(".fw-contents")
122
+ const contentsEl = this.dom.querySelector(".fw-contents") as HTMLElement
86
123
  contentsEl.innerHTML = ""
87
124
 
88
- const hiddenCols = [0]
125
+ const hiddenCols: number[] = [0]
89
126
 
90
127
  if (window.innerWidth < 500) {
91
128
  hiddenCols.push(1)
@@ -123,8 +160,8 @@ export class BibliographyOverview {
123
160
  data: ids.map(id => this.createTableRow(id)),
124
161
  idColumn: 0,
125
162
  checkboxColumn: 1,
126
- bulkMenu: bulkMenuModel(),
127
- bulkMenuPage: this,
163
+ bulkMenu: bulkMenuModel() as unknown as ContentMenuInit,
164
+ bulkMenuPage: this as Record<string, unknown>,
128
165
  searchable: true,
129
166
  scrollY: `${Math.max(window.innerHeight - 360, 100)}px`,
130
167
  tabIndex: 1,
@@ -145,19 +182,22 @@ export class BibliographyOverview {
145
182
  `<div class='${options.classes.container}'${options.scrollY.length ? ` style='height: ${options.scrollY}; overflow-Y: auto;'` : ""}></div>`,
146
183
  rowRender: (row, tr, _index) => {
147
184
  const id = row.cells[0].data
148
- const inputNode = {
185
+ const inputNode: {
186
+ nodeName: string
187
+ attributes: Record<string, string | boolean | number>
188
+ } = {
149
189
  nodeName: "input",
150
190
  attributes: {
151
191
  type: "checkbox",
152
192
  class: "entry-select fw-check",
153
- "data-id": id,
193
+ "data-id": id as number,
154
194
  id: `bib-${id}`
155
195
  }
156
196
  }
157
197
  if (row.cells[1].data) {
158
198
  inputNode.attributes.checked = true
159
199
  }
160
- tr.childNodes[0].childNodes = [
200
+ ;(tr as {childNodes: {childNodes: unknown[]}[]}).childNodes[0].childNodes = [
161
201
  inputNode,
162
202
  {
163
203
  nodeName: "label",
@@ -171,22 +211,22 @@ export class BibliographyOverview {
171
211
  if (this.getSelected().length > 0) {
172
212
  return
173
213
  }
174
- const rowIndex = this.table.data.data.indexOf(row)
175
- const editButton = this.table.dom.querySelector(
214
+ const rowIndex = this.table!.data.data.indexOf(row as never)
215
+ const editButton = this.table!.dom.querySelector(
176
216
  `tr[data-index="${rowIndex}"] span.edit-bib`
177
217
  )
178
218
  if (editButton) {
179
- editButton.click()
219
+ ;(editButton as HTMLElement).click()
180
220
  }
181
221
  },
182
222
  onDelete: row => {
183
- const bibId = row.cells[0].data
223
+ const bibId = row.cells[0].data as number
184
224
  this.deleteBibEntryDialog([bibId])
185
225
  }
186
226
  })
187
227
  this.overviewTable.init()
188
- this.table = this.overviewTable.table
189
- this.table.id = "bibliography"
228
+ this.table = this.overviewTable.table as DataTable
229
+ ;(this.table as unknown as {id: string}).id = "bibliography"
190
230
  this.dtBulk = this.overviewTable.dtBulk
191
231
 
192
232
  this.table.on("datatable.sort", (column, dir) => {
@@ -200,75 +240,79 @@ export class BibliographyOverview {
200
240
  * @function setBibCategoryList
201
241
  * @param newBibCategories The new categories which will be added to the existing ones.
202
242
  */
203
- setBibCategoryList(bibCategories) {
204
- const catSelector = this.menu.model.content.find(
243
+ setBibCategoryList(bibCategories: BibCategory[]): void {
244
+ const catSelector = this.menu!.model.content.find(
205
245
  menuItem => menuItem.id === "cat_selector"
206
246
  )
207
- catSelector.content = catSelector.content.filter(
208
- cat => cat.type !== "category"
209
- )
247
+ if (!catSelector) {
248
+ return
249
+ }
250
+ const dropdown = catSelector as {
251
+ content: {type?: string; title?: string; action?: unknown}[]
252
+ }
253
+ dropdown.content = dropdown.content.filter(cat => cat.type !== "category")
210
254
 
211
- catSelector.content = catSelector.content.concat(
255
+ dropdown.content = dropdown.content.concat(
212
256
  bibCategories.map(cat => ({
213
257
  title: cat.category_title,
214
258
  type: "category",
215
- action: _overview => {
259
+ action: (_overview: BibliographyOverview) => {
216
260
  const trs = this.dom.querySelectorAll(
217
261
  "#bibliography > tbody > tr"
218
262
  )
219
263
  trs.forEach(tr => {
264
+ const titleEl = tr.querySelector(".fw-data-table-title")
220
265
  if (
221
- tr
222
- .querySelector(".fw-data-table-title")
223
- .classList.contains(`cat_${cat.id}`)
266
+ titleEl &&
267
+ titleEl.classList.contains(`cat_${cat.id}`)
224
268
  ) {
225
- tr.style.display = ""
269
+ ;(tr as HTMLElement).style.display = ""
226
270
  } else {
227
- tr.style.display = "none"
271
+ ;(tr as HTMLElement).style.display = "none"
228
272
  }
229
273
  })
230
274
  }
231
275
  }))
232
276
  )
233
- this.menu.update()
277
+ this.menu!.update()
234
278
  }
235
279
 
236
280
  /** This takes a list of new bib entries and adds them to BibDB and the bibliography table
237
281
  * @function updateTable
238
282
  */
239
- updateTable(ids) {
283
+ updateTable(ids: number[]): void {
240
284
  // Remove items that already exist
241
285
  this.removeTableRows(ids)
242
- this.table.insert({data: ids.map(id => this.createTableRow(id))})
286
+ this.table!.insert({data: ids.map(id => this.createTableRow(id))})
243
287
  // Redo last sort
244
- this.table.columns.sort(this.lastSort.column, this.lastSort.dir)
288
+ this.table!.columns.sort(this.lastSort.column, this.lastSort.dir)
245
289
  }
246
290
 
247
- createTableRow(id) {
248
- const bibInfo = this.app.bibDB.db[id]
291
+ createTableRow(id: string | number): (string | number | boolean)[] {
292
+ const bibInfo = this.app.bibDB.db[id as number]
249
293
  const bibauthors = bibInfo.fields.author || bibInfo.fields.editor
250
294
  const cats = bibInfo.cats.map(cat => `cat_${cat}`)
251
295
  return [
252
- id,
296
+ id as number,
253
297
  false, // checkbox
254
298
  `<span class="fw-data-table-title ${cats.join(" ")}">
255
299
  <i class="fa fa-book"></i>
256
300
  <span class="edit-bib fw-link-text fw-searchable" data-id="${id}">
257
- ${bibInfo.fields.title?.length ? escapeText(litToText(bibInfo.fields.title)) : gettext("Untitled")}
301
+ ${(bibInfo.fields.title as NodeArray | undefined)?.length ? escapeText(litToText(bibInfo.fields.title as NodeArray)) : gettext("Untitled")}
258
302
  </span>
259
303
  ${bibInfo.entry_key ? `<small class="bib-entry-key">${escapeText(bibInfo.entry_key)}</small>` : ""}
260
304
  </span>`, // title
261
305
  getBibTypeTitle(bibInfo.bib_type), // sourcetype
262
- bibauthors ? nameToText(bibauthors) : "", // author
263
- `<span class="fw-date">${bibInfo.fields.date ? bibInfo.fields.date.replace("/", " ") : ""}</span>`, // published,
306
+ bibauthors ? nameToText(bibauthors as NameDictObject[]) : "", // author
307
+ `<span class="fw-date">${bibInfo.fields.date ? (bibInfo.fields.date as string).replace("/", " ") : ""}</span>`, // published,
264
308
  `<span class="delete-bib fw-link-text" data-id="${id}"><i class="fa fa-trash-alt"> </i></span>` // delete icon
265
309
  ]
266
310
  }
267
311
 
268
- removeTableRows(ids) {
269
- const existingRows = this.table.data.data
312
+ removeTableRows(ids: number[]): void {
313
+ const existingRows = this.table!.data.data
270
314
  .map((row, index) => {
271
- const id = row.cells[0].data
315
+ const id = row.cells[0].data as number
272
316
  if (ids.includes(id)) {
273
317
  return index
274
318
  } else {
@@ -278,14 +322,14 @@ export class BibliographyOverview {
278
322
  .filter(rowIndex => rowIndex !== false)
279
323
 
280
324
  if (existingRows.length) {
281
- this.table.rows.remove(existingRows)
325
+ this.table!.rows.remove(existingRows as number[])
282
326
  }
283
327
  }
284
328
 
285
329
  /** Opens a dialog for editing categories.
286
330
  * @function editCategoriesDialog
287
331
  */
288
- editCategoriesDialog() {
332
+ editCategoriesDialog(): void {
289
333
  if (this.app.isOffline()) {
290
334
  addAlert(
291
335
  "info",
@@ -295,20 +339,23 @@ export class BibliographyOverview {
295
339
  )
296
340
  return
297
341
  }
298
- const buttons = [
342
+ const buttons: DialogButtonSpec[] = [
299
343
  {
300
344
  text: gettext("Submit"),
301
345
  classes: "fw-dark",
302
346
  click: () => {
303
- const cats = {ids: [], titles: []}
347
+ const cats: {ids: number[]; titles: string[]} = {
348
+ ids: [],
349
+ titles: []
350
+ }
304
351
  this.dom
305
352
  .querySelectorAll("#edit-categories .category-form")
306
353
  .forEach(el => {
307
- const title = el.value.trim()
354
+ const title = (el as HTMLInputElement).value.trim()
308
355
  if (title.length) {
309
356
  cats.ids.push(
310
357
  Number.parseInt(
311
- el.getAttribute("data-id") || 0
358
+ el.getAttribute("data-id") || "0"
312
359
  )
313
360
  )
314
361
  cats.titles.push(title)
@@ -349,8 +396,8 @@ export class BibliographyOverview {
349
396
  * @function deleteBibEntryDialog
350
397
  * @param ids Ids of items that are to be deleted.
351
398
  */
352
- deleteBibEntryDialog(ids) {
353
- const buttons = [
399
+ deleteBibEntryDialog(ids: number[]): void {
400
+ const buttons: DialogButtonSpec[] = [
354
401
  {
355
402
  text: gettext("Delete"),
356
403
  classes: "fw-dark",
@@ -375,13 +422,13 @@ export class BibliographyOverview {
375
422
  }
376
423
 
377
424
  // get IDs of selected bib entries
378
- getSelected() {
425
+ getSelected(): number[] {
379
426
  return Array.from(
380
427
  this.dom.querySelectorAll(".entry-select:checked:not(:disabled)")
381
- ).map(el => Number.parseInt(el.getAttribute("data-id")))
428
+ ).map(el => Number.parseInt(el.getAttribute("data-id") || ""))
382
429
  }
383
430
 
384
- activatePlugins() {
431
+ activatePlugins(): Promise<unknown> | void {
385
432
  if (this.plugins) {
386
433
  // Plugins have been activated already
387
434
  return
@@ -390,18 +437,18 @@ export class BibliographyOverview {
390
437
  this.plugins = {}
391
438
 
392
439
  return Promise.all(
393
- plugins.map(([app, plugin]) => {
440
+ this.bibPlugins.map(([app, plugin]) => {
394
441
  if (!this.app.settings.APPS.includes(app)) {
395
442
  return Promise.resolve()
396
443
  }
397
444
  return Promise.all(
398
445
  Object.values(plugin).map(pluginExport => {
399
446
  if (typeof pluginExport === "function") {
400
- this.plugins[pluginExport.name] = new pluginExport(
447
+ this.plugins![pluginExport.name] = new pluginExport(
401
448
  this
402
449
  )
403
450
  return (
404
- this.plugins[pluginExport.name].init() ||
451
+ this.plugins![pluginExport.name].init() ||
405
452
  Promise.resolve()
406
453
  )
407
454
  }
@@ -415,7 +462,7 @@ export class BibliographyOverview {
415
462
  /** Initialize the bibliography table and bind interactive parts.
416
463
  * @function bibEvents
417
464
  */
418
- bindEvents() {
465
+ bindEvents(): void {
419
466
  this.dom.addEventListener("click", event =>
420
467
  this.handleActivation(event)
421
468
  )
@@ -425,58 +472,77 @@ export class BibliographyOverview {
425
472
 
426
473
  // Allow pasting of bibtex data.
427
474
  this.dom.addEventListener("paste", event => {
428
- if (event.target.nodeName === "INPUT") {
475
+ if ((event.target as Element).nodeName === "INPUT") {
429
476
  // We are inside of an input element, cancel.
430
477
  return false
431
478
  }
479
+ if (!event.clipboardData) {
480
+ return false
481
+ }
432
482
  const text = event.clipboardData.getData("text")
433
483
  return this.getBibtex(text)
434
484
  })
435
485
 
436
486
  // The two drag events are needed to allow dropping
437
487
  this.dom.addEventListener("dragover", event => {
438
- if (event.dataTransfer.types.includes("text/plain")) {
488
+ if (
489
+ event.dataTransfer &&
490
+ event.dataTransfer.types.includes("text/plain")
491
+ ) {
439
492
  event.preventDefault()
440
493
  }
441
494
  })
442
495
 
443
496
  this.dom.addEventListener("dragenter", event => {
444
- if (event.dataTransfer.types.includes("text/plain")) {
497
+ if (
498
+ event.dataTransfer &&
499
+ event.dataTransfer.types.includes("text/plain")
500
+ ) {
445
501
  event.preventDefault()
446
502
  }
447
503
  })
448
504
 
449
505
  // Allow dropping of bibtex data
450
506
  this.dom.addEventListener("drop", event => {
451
- if (event.target.nodeName === "INPUT") {
507
+ if ((event.target as Element).nodeName === "INPUT") {
452
508
  // We are inside of an input element, cancel.
453
509
  return false
454
510
  }
511
+ if (!event.dataTransfer) {
512
+ return false
513
+ }
455
514
  const text = fixUTF8(event.dataTransfer.getData("text"))
456
515
  return this.getBibtex(text)
457
516
  })
458
517
  }
459
518
 
460
- handleActivation(event) {
519
+ handleActivation(event: Event): void {
461
520
  if (!isActivationEvent(event)) {
462
521
  return
463
522
  }
464
- const el = {}
523
+ const el: {target?: Element | null} = {}
465
524
  switch (true) {
466
525
  case findTarget(event, ".delete-bib", el): {
467
- const bibId = Number.parseInt(el.target.dataset.id)
526
+ const bibId = Number.parseInt(
527
+ (el.target as HTMLElement).dataset.id || ""
528
+ )
468
529
  this.deleteBibEntryDialog([bibId])
469
530
  break
470
531
  }
471
532
  case findTarget(event, ".edit-bib", el): {
472
- const bibId = Number.parseInt(el.target.dataset.id)
533
+ const bibId = Number.parseInt(
534
+ (el.target as HTMLElement).dataset.id || ""
535
+ )
473
536
  import("../form/index.js").then(({BibEntryForm}) => {
474
537
  const form = new BibEntryForm(
475
538
  this.app.bibDB,
476
539
  this.app,
477
540
  bibId
478
541
  )
479
- form.init().then(idTranslations => {
542
+ form.init().then((idTranslations: IdTranslation[] | void) => {
543
+ if (!idTranslations) {
544
+ return
545
+ }
480
546
  const ids = idTranslations.map(idTrans => idTrans[1])
481
547
  return this.updateTable(ids)
482
548
  })
@@ -484,7 +550,10 @@ export class BibliographyOverview {
484
550
  break
485
551
  }
486
552
  case findTarget(event, ".fw-add-input", el): {
487
- const itemEl = el.target.closest(".fw-list-input")
553
+ const itemEl = (el.target as HTMLElement).closest(".fw-list-input")
554
+ if (!itemEl) {
555
+ break
556
+ }
488
557
  if (!itemEl.nextElementSibling) {
489
558
  itemEl.insertAdjacentHTML(
490
559
  "afterend",
@@ -496,7 +565,7 @@ export class BibliographyOverview {
496
565
  </tr>`
497
566
  )
498
567
  } else {
499
- itemEl.parentElement.removeChild(itemEl)
568
+ itemEl.parentElement!.removeChild(itemEl)
500
569
  }
501
570
  break
502
571
  }
@@ -506,7 +575,7 @@ export class BibliographyOverview {
506
575
  }
507
576
 
508
577
  // find bibtex in pasted or dropped data.
509
- getBibtex(text) {
578
+ getBibtex(text: string): boolean {
510
579
  import("../import/index.js").then(({BibliographyImporter}) => {
511
580
  const importer = new BibliographyImporter(
512
581
  text,
@@ -519,30 +588,30 @@ export class BibliographyOverview {
519
588
  return true
520
589
  }
521
590
 
522
- saveCategories(cats) {
591
+ saveCategories(cats: {ids: number[]; titles: string[]}): void {
523
592
  this.app.bibDB
524
593
  .saveCategories(cats)
525
594
  .then(bibCats => this.setBibCategoryList(bibCats))
526
595
  }
527
596
 
528
- deleteBibEntries(ids) {
597
+ deleteBibEntries(ids: number[]): void {
529
598
  this.app.bibDB
530
599
  .deleteBibEntries(ids)
531
600
  .then(ids => this.removeTableRows(ids))
532
601
  }
533
602
 
534
- close() {
603
+ close(): void {
535
604
  if (this.table) {
536
605
  this.table.destroy()
537
- this.table = null
606
+ this.table = undefined
538
607
  }
539
608
  if (this.dtBulk) {
540
609
  this.dtBulk.destroy()
541
- this.dtBulk = null
610
+ this.dtBulk = undefined
542
611
  }
543
612
  if (this.menu) {
544
613
  this.menu.destroy()
545
- this.menu = null
614
+ this.menu = undefined
546
615
  }
547
616
  }
548
617
  }
@@ -1,26 +1,28 @@
1
1
  import {BibLatexFileExporter} from "../export/index.js"
2
2
  import {BibliographyFileImportDialog} from "../import/index.js"
3
+ import type {IdTranslation} from "../types/biblio.js"
4
+ import type {BibliographyOverview} from "./index.js"
3
5
 
4
6
  export const bulkMenuModel = () => ({
5
7
  content: [
6
8
  {
7
9
  title: gettext("Delete selected"),
8
10
  tooltip: gettext("Delete selected bibliography entries."),
9
- action: overview => {
11
+ action: (overview: BibliographyOverview) => {
10
12
  const ids = overview
11
13
  .getSelected()
12
- .map(id => Number.parseInt(id))
14
+ .map(id => Number.parseInt(String(id)))
13
15
  if (ids.length) {
14
16
  overview.deleteBibEntryDialog(ids)
15
17
  }
16
18
  },
17
- disabled: overview =>
19
+ disabled: (overview: BibliographyOverview) =>
18
20
  !overview.getSelected().length || overview.app.isOffline()
19
21
  },
20
22
  {
21
23
  title: gettext("Export selected"),
22
24
  tooltip: gettext("Export selected bibliography entries."),
23
- action: overview => {
25
+ action: (overview: BibliographyOverview) => {
24
26
  const ids = overview.getSelected()
25
27
  if (ids.length) {
26
28
  const exporter = new BibLatexFileExporter(
@@ -30,7 +32,7 @@ export const bulkMenuModel = () => ({
30
32
  exporter.init()
31
33
  }
32
34
  },
33
- disabled: overview =>
35
+ disabled: (overview: BibliographyOverview) =>
34
36
  !overview.getSelected().length || overview.app.isOffline()
35
37
  }
36
38
  ]
@@ -45,11 +47,11 @@ export const menuModel = () => ({
45
47
  content: [
46
48
  {
47
49
  title: gettext("All categories"),
48
- action: _overview => {
50
+ action: (_overview: BibliographyOverview) => {
49
51
  const trs = document.querySelectorAll(
50
52
  "#bibliography > tbody > tr"
51
53
  )
52
- trs.forEach(tr => (tr.style.display = ""))
54
+ trs.forEach(tr => ((tr as HTMLElement).style.display = ""))
53
55
  }
54
56
  }
55
57
  ],
@@ -59,20 +61,23 @@ export const menuModel = () => ({
59
61
  type: "text",
60
62
  title: gettext("Edit categories"),
61
63
  keys: "Alt-e",
62
- action: overview => overview.editCategoriesDialog(),
64
+ action: (overview: BibliographyOverview) => overview.editCategoriesDialog(),
63
65
  order: 2
64
66
  },
65
67
  {
66
68
  type: "text",
67
69
  title: gettext("Register new source"),
68
70
  keys: "Alt-n",
69
- action: overview => {
71
+ action: (overview: BibliographyOverview) => {
70
72
  import("../form/index.js").then(({BibEntryForm}) => {
71
73
  const form = new BibEntryForm(
72
74
  overview.app.bibDB,
73
75
  overview.app
74
76
  )
75
- form.init().then(idTranslations => {
77
+ form.init().then((idTranslations: IdTranslation[] | void) => {
78
+ if (!idTranslations) {
79
+ return
80
+ }
76
81
  const ids = idTranslations.map(idTrans => idTrans[1])
77
82
  return overview.updateTable(ids)
78
83
  })
@@ -84,7 +89,7 @@ export const menuModel = () => ({
84
89
  type: "text",
85
90
  title: gettext("Import bibliography"),
86
91
  keys: "Alt-u",
87
- action: overview => {
92
+ action: (overview: BibliographyOverview) => {
88
93
  const fileImporter = new BibliographyFileImportDialog(
89
94
  overview.app.bibDB,
90
95
  ids => overview.updateTable(ids),
@@ -99,7 +104,8 @@ export const menuModel = () => ({
99
104
  icon: "search",
100
105
  title: gettext("Search bibliography"),
101
106
  keys: "Alt-s",
102
- input: (overview, text) => overview.table.search(text),
107
+ input: (overview: BibliographyOverview, text: string) =>
108
+ overview.table!.search(text),
103
109
  order: 5
104
110
  }
105
111
  ]
@@ -1,7 +1,8 @@
1
1
  import {escapeText} from "fwtoolkit"
2
+ import type {BibCategory} from "../types/biblio.js"
2
3
 
3
4
  /** A template for each category in the category list edit of the bibliography categories list. */
4
- const categoryFormsTemplate = ({categories}) =>
5
+ const categoryFormsTemplate = ({categories}: {categories: BibCategory[]}) =>
5
6
  `${categories
6
7
  .map(
7
8
  cat =>
@@ -22,7 +23,7 @@ const categoryFormsTemplate = ({categories}) =>
22
23
  </tr>`
23
24
 
24
25
  /** A template for the editing of bibliography categories list. */
25
- export const editCategoriesTemplate = ({categories}) =>
26
+ export const editCategoriesTemplate = ({categories}: {categories: BibCategory[]}) =>
26
27
  `<table id="editCategoryList" class="fw-dialog-table">
27
28
  <tbody>
28
29
  ${categoryFormsTemplate({categories})}
@@ -0,0 +1 @@
1
+ export const plugins: unknown[] = []