@fiduswriter/bibliography-manager 0.1.0
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.
- package/LICENSE +661 -0
- package/README.md +20 -0
- package/dist/database/index.js +172 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/server_connector.js +47 -0
- package/dist/database/server_connector.js.map +1 -0
- package/dist/export/index.js +23 -0
- package/dist/export/index.js.map +1 -0
- package/dist/form/cats.js +22 -0
- package/dist/form/cats.js.map +1 -0
- package/dist/form/fields/date.js +28 -0
- package/dist/form/fields/date.js.map +1 -0
- package/dist/form/fields/key.js +100 -0
- package/dist/form/fields/key.js.map +1 -0
- package/dist/form/fields/key_list.js +37 -0
- package/dist/form/fields/key_list.js.map +1 -0
- package/dist/form/fields/literal.js +43 -0
- package/dist/form/fields/literal.js.map +1 -0
- package/dist/form/fields/literal_list.js +36 -0
- package/dist/form/fields/literal_list.js.map +1 -0
- package/dist/form/fields/literal_long.js +42 -0
- package/dist/form/fields/literal_long.js.map +1 -0
- package/dist/form/fields/name.js +121 -0
- package/dist/form/fields/name.js.map +1 -0
- package/dist/form/fields/name_list.js +36 -0
- package/dist/form/fields/name_list.js.map +1 -0
- package/dist/form/fields/range.js +89 -0
- package/dist/form/fields/range.js.map +1 -0
- package/dist/form/fields/range_list.js +36 -0
- package/dist/form/fields/range_list.js.map +1 -0
- package/dist/form/fields/tag_list.js +30 -0
- package/dist/form/fields/tag_list.js.map +1 -0
- package/dist/form/fields/title.js +46 -0
- package/dist/form/fields/title.js.map +1 -0
- package/dist/form/fields/uri.js +40 -0
- package/dist/form/fields/uri.js.map +1 -0
- package/dist/form/fields/verbatim.js +19 -0
- package/dist/form/fields/verbatim.js.map +1 -0
- package/dist/form/index.js +344 -0
- package/dist/form/index.js.map +1 -0
- package/dist/form/strings.js +89 -0
- package/dist/form/strings.js.map +1 -0
- package/dist/form/templates.js +59 -0
- package/dist/form/templates.js.map +1 -0
- package/dist/import/bibliography_import.js +83 -0
- package/dist/import/bibliography_import.js.map +1 -0
- package/dist/import/dialog.js +71 -0
- package/dist/import/dialog.js.map +1 -0
- package/dist/import/index.js +3 -0
- package/dist/import/index.js.map +1 -0
- package/dist/import/templates.js +12 -0
- package/dist/import/templates.js.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/overview/index.js +453 -0
- package/dist/overview/index.js.map +1 -0
- package/dist/overview/menu.js +91 -0
- package/dist/overview/menu.js.map +1 -0
- package/dist/overview/templates.js +24 -0
- package/dist/overview/templates.js.map +1 -0
- package/dist/plugins/bibliography_overview/index.js +2 -0
- package/dist/plugins/bibliography_overview/index.js.map +1 -0
- package/dist/schema/literal.js +24 -0
- package/dist/schema/literal.js.map +1 -0
- package/dist/schema/literal_long.js +40 -0
- package/dist/schema/literal_long.js.map +1 -0
- package/dist/schema/title.js +31 -0
- package/dist/schema/title.js.map +1 -0
- package/dist/tools.js +53 -0
- package/dist/tools.js.map +1 -0
- package/package.json +55 -0
- package/src/database/index.js +234 -0
- package/src/database/server_connector.js +57 -0
- package/src/export/index.js +27 -0
- package/src/form/cats.js +24 -0
- package/src/form/fields/date.js +31 -0
- package/src/form/fields/key.js +113 -0
- package/src/form/fields/key_list.js +45 -0
- package/src/form/fields/literal.js +48 -0
- package/src/form/fields/literal_list.js +42 -0
- package/src/form/fields/literal_long.js +47 -0
- package/src/form/fields/name.js +152 -0
- package/src/form/fields/name_list.js +42 -0
- package/src/form/fields/range.js +104 -0
- package/src/form/fields/range_list.js +42 -0
- package/src/form/fields/tag_list.js +33 -0
- package/src/form/fields/title.js +51 -0
- package/src/form/fields/uri.js +43 -0
- package/src/form/fields/verbatim.js +21 -0
- package/src/form/index.js +424 -0
- package/src/form/strings.js +122 -0
- package/src/form/templates.js +70 -0
- package/src/import/bibliography_import.js +104 -0
- package/src/import/dialog.js +95 -0
- package/src/import/index.js +2 -0
- package/src/import/templates.js +12 -0
- package/src/index.js +5 -0
- package/src/overview/index.js +548 -0
- package/src/overview/menu.js +106 -0
- package/src/overview/templates.js +30 -0
- package/src/plugins/bibliography_overview/index.js +1 -0
- package/src/schema/literal.js +34 -0
- package/src/schema/literal_long.js +50 -0
- package/src/schema/title.js +42 -0
- package/src/tools.js +58 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BibFieldTypes,
|
|
3
|
+
BibTypes,
|
|
4
|
+
getFieldHelp,
|
|
5
|
+
getFieldTitle,
|
|
6
|
+
getLangidTitle,
|
|
7
|
+
getLocale,
|
|
8
|
+
getOtherOptionTitle,
|
|
9
|
+
getTypeTitle
|
|
10
|
+
} from "bibliojson"
|
|
11
|
+
|
|
12
|
+
// Cache for the current locale to avoid repeated lookups
|
|
13
|
+
let cachedLocale = null
|
|
14
|
+
let cachedLang = null
|
|
15
|
+
|
|
16
|
+
function getCachedLocale() {
|
|
17
|
+
const lang = document.documentElement.lang || "en"
|
|
18
|
+
if (lang !== cachedLang) {
|
|
19
|
+
cachedLocale = getLocale(lang)
|
|
20
|
+
cachedLang = lang
|
|
21
|
+
}
|
|
22
|
+
return cachedLocale
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Dynamic field title getter that uses bibliojson's i18n
|
|
26
|
+
export function getBibFieldTitle(fieldKey, bibType = null) {
|
|
27
|
+
const locale = getCachedLocale()
|
|
28
|
+
if (bibType && BibTypes[bibType]) {
|
|
29
|
+
return getFieldTitle(locale, bibType, fieldKey)
|
|
30
|
+
}
|
|
31
|
+
// Fallback to generic field title
|
|
32
|
+
const fieldType = BibFieldTypes[fieldKey]
|
|
33
|
+
if (fieldType && fieldType.title) {
|
|
34
|
+
return fieldType.title
|
|
35
|
+
}
|
|
36
|
+
return fieldKey
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Dynamic type title getter
|
|
40
|
+
export function getBibTypeTitle(typeKey) {
|
|
41
|
+
const locale = getCachedLocale()
|
|
42
|
+
return getTypeTitle(locale, typeKey)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Dynamic field help getter
|
|
46
|
+
export function getBibFieldHelp(fieldKey) {
|
|
47
|
+
const locale = getCachedLocale()
|
|
48
|
+
return getFieldHelp(locale, fieldKey)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Dynamic option title getter (for editortype, pagination, pubstate, etc.)
|
|
52
|
+
export function getBibOptionTitle(optionKey) {
|
|
53
|
+
const locale = getCachedLocale()
|
|
54
|
+
return getOtherOptionTitle(locale, optionKey)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Dynamic langid title getter
|
|
58
|
+
export function getBibLangidTitle(langidKey) {
|
|
59
|
+
const locale = getCachedLocale()
|
|
60
|
+
return getLangidTitle(locale, langidKey)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// For backward compatibility, create proxy objects that dynamically return translations
|
|
64
|
+
// These should be used sparingly - prefer using the function versions above
|
|
65
|
+
export const BibFieldTitles = new Proxy(
|
|
66
|
+
{},
|
|
67
|
+
{
|
|
68
|
+
get(_target, prop) {
|
|
69
|
+
return getBibFieldTitle(prop)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
export const BibTypeTitles = new Proxy(
|
|
75
|
+
{},
|
|
76
|
+
{
|
|
77
|
+
get(_target, prop) {
|
|
78
|
+
return getBibTypeTitle(prop)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
export const BibFieldHelp = new Proxy(
|
|
84
|
+
{},
|
|
85
|
+
{
|
|
86
|
+
get(_target, prop) {
|
|
87
|
+
return getBibFieldHelp(prop)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
export const BibOptionTitles = new Proxy(
|
|
93
|
+
{},
|
|
94
|
+
{
|
|
95
|
+
get(_target, prop) {
|
|
96
|
+
return getBibOptionTitle(prop)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
// Export a function to get all type titles as an object (for templates that need to map all types)
|
|
102
|
+
export function getAllTypeTitles() {
|
|
103
|
+
const locale = getCachedLocale()
|
|
104
|
+
const titles = {}
|
|
105
|
+
Object.keys(BibTypes).forEach(typeKey => {
|
|
106
|
+
titles[typeKey] = getTypeTitle(locale, typeKey)
|
|
107
|
+
})
|
|
108
|
+
return titles
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Export a function to get all field help texts
|
|
112
|
+
export function getAllFieldHelp() {
|
|
113
|
+
const locale = getCachedLocale()
|
|
114
|
+
const help = {}
|
|
115
|
+
Object.keys(BibFieldTypes).forEach(fieldKey => {
|
|
116
|
+
const helpText = getFieldHelp(locale, fieldKey)
|
|
117
|
+
if (helpText) {
|
|
118
|
+
help[fieldKey] = helpText
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
return help
|
|
122
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** A template for the bibliography item edit dialog. */
|
|
2
|
+
import {DialogTabs} from "fwtoolkit"
|
|
3
|
+
import {getAllTypeTitles} from "./strings"
|
|
4
|
+
|
|
5
|
+
const requiredFieldsTemplate = () =>
|
|
6
|
+
`<table class="fw-dialog-table"><tbody id="eo-fields"></tbody></table>
|
|
7
|
+
<table class="fw-dialog-table"><tbody id="req-fields"></tbody></table>`
|
|
8
|
+
|
|
9
|
+
const optionalFieldsTemplate = () =>
|
|
10
|
+
`<table class="fw-dialog-table"><tbody id="opt-fields"></tbody></table>`
|
|
11
|
+
|
|
12
|
+
const categoriesTemplate = () =>
|
|
13
|
+
`<table class="fw-dialog-table">
|
|
14
|
+
<tbody>
|
|
15
|
+
<tr>
|
|
16
|
+
<th><h4 class="fw-tablerow-title">${gettext("Categories")}</h4></th>
|
|
17
|
+
<td id="categories-field"></td>
|
|
18
|
+
</tr>
|
|
19
|
+
</tbody>
|
|
20
|
+
</table>`
|
|
21
|
+
|
|
22
|
+
export const bibDialog = ({bib_type, BibTypes, hasCats}) => {
|
|
23
|
+
const typeTitles = getAllTypeTitles()
|
|
24
|
+
const tabs = [
|
|
25
|
+
{
|
|
26
|
+
id: "req-fields-tab",
|
|
27
|
+
title: gettext("Required Fields"),
|
|
28
|
+
template: requiredFieldsTemplate
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
id: "opt-fields-tab",
|
|
32
|
+
title: gettext("Optional Fields"),
|
|
33
|
+
template: optionalFieldsTemplate
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
if (hasCats) {
|
|
37
|
+
tabs.push({
|
|
38
|
+
id: "categories-tab",
|
|
39
|
+
title: gettext("Categories"),
|
|
40
|
+
template: categoriesTemplate
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
const dialogTabs = new DialogTabs(tabs, {containerId: "bib-dialog-tabs"})
|
|
44
|
+
return `<div class="bib-dialog-header">
|
|
45
|
+
<div class="fw-select-container">
|
|
46
|
+
<select id="select-bibtype" class="fw-button fw-light fw-large" required>
|
|
47
|
+
${
|
|
48
|
+
bib_type === false
|
|
49
|
+
? `<option class="fw-placeholder" selected disabled value="">${gettext("Select source type")}</option>`
|
|
50
|
+
: ""
|
|
51
|
+
}
|
|
52
|
+
${Object.keys(BibTypes)
|
|
53
|
+
.map(
|
|
54
|
+
key =>
|
|
55
|
+
`<option value="${key}"
|
|
56
|
+
${key === bib_type ? "selected" : ""}>
|
|
57
|
+
${typeTitles[key]}
|
|
58
|
+
</option>`
|
|
59
|
+
)
|
|
60
|
+
.join("")}
|
|
61
|
+
</select>
|
|
62
|
+
<div class="fw-select-arrow fa fa-caret-down"></div>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="entry-key-input-container">
|
|
65
|
+
<input type="text" id="entry-key" class="fw-button fw-light" value="" placeholder="${gettext("Citation key")}" />
|
|
66
|
+
<div id="entry-key-warning" class="entry-key-warning"></div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
${dialogTabs.render()}`
|
|
70
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {sniffFormat} from "bibliojson"
|
|
2
|
+
import {addAlert, makeWorker} from "fwtoolkit"
|
|
3
|
+
|
|
4
|
+
const ERROR_MSG = {
|
|
5
|
+
no_entries: gettext(
|
|
6
|
+
"No bibliography entries could be found in import file."
|
|
7
|
+
),
|
|
8
|
+
entry_error: gettext("An error occured while reading a bibliography entry"),
|
|
9
|
+
unknown_field: gettext(
|
|
10
|
+
"Field cannot not be saved. Fidus Writer does not support the field."
|
|
11
|
+
),
|
|
12
|
+
unknown_type: gettext(
|
|
13
|
+
'Entry has been saved as "misc". Fidus Writer does not support the entry type.'
|
|
14
|
+
),
|
|
15
|
+
unknown_date: gettext("Field does not contain a valid EDTF string."),
|
|
16
|
+
server_save: gettext("The bibliography could not be updated"),
|
|
17
|
+
unsupported_format: gettext("The file format could not be recognized.")
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class BibliographyImporter {
|
|
21
|
+
constructor(
|
|
22
|
+
fileContents,
|
|
23
|
+
bibDB,
|
|
24
|
+
addToListCall,
|
|
25
|
+
callback,
|
|
26
|
+
showAlerts = true
|
|
27
|
+
) {
|
|
28
|
+
this.fileContents = fileContents
|
|
29
|
+
this.bibDB = bibDB
|
|
30
|
+
this.addToListCall = addToListCall
|
|
31
|
+
this.callback = callback
|
|
32
|
+
this.showAlerts = showAlerts
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
init() {
|
|
36
|
+
// Detect the format of the input file
|
|
37
|
+
const format = sniffFormat(this.fileContents)
|
|
38
|
+
|
|
39
|
+
if (!format) {
|
|
40
|
+
if (this.showAlerts) {
|
|
41
|
+
addAlert("error", ERROR_MSG.unsupported_format)
|
|
42
|
+
}
|
|
43
|
+
if (this.callback) {
|
|
44
|
+
this.callback()
|
|
45
|
+
}
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Use the worker for the detected format
|
|
50
|
+
const importWorker = makeWorker(
|
|
51
|
+
staticUrl("js/bibliography_import_worker.js")
|
|
52
|
+
)
|
|
53
|
+
importWorker.onmessage = message => this.onMessage(message.data)
|
|
54
|
+
importWorker.postMessage({
|
|
55
|
+
fileContents: this.fileContents,
|
|
56
|
+
format: format
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
onMessage(message) {
|
|
61
|
+
let errorMsg, data
|
|
62
|
+
switch (message.type) {
|
|
63
|
+
case "error":
|
|
64
|
+
case "warning":
|
|
65
|
+
errorMsg = ERROR_MSG[message.errorCode]
|
|
66
|
+
if (!errorMsg) {
|
|
67
|
+
errorMsg = gettext(
|
|
68
|
+
"There was an issue with the bibliography import"
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
if (message.errorType) {
|
|
72
|
+
errorMsg += `, error_type: ${message.errorType}`
|
|
73
|
+
}
|
|
74
|
+
if (message.key) {
|
|
75
|
+
errorMsg += `, key: ${message.key}`
|
|
76
|
+
}
|
|
77
|
+
if (message.type_name) {
|
|
78
|
+
errorMsg += `, entry: ${message.type_name}`
|
|
79
|
+
}
|
|
80
|
+
if (message.field_name) {
|
|
81
|
+
errorMsg += `, field_name: ${message.field_name}`
|
|
82
|
+
}
|
|
83
|
+
if (message.entry) {
|
|
84
|
+
errorMsg += `, entry: ${message.entry}`
|
|
85
|
+
}
|
|
86
|
+
if (this.showAlerts) {
|
|
87
|
+
addAlert(message.type, errorMsg)
|
|
88
|
+
}
|
|
89
|
+
break
|
|
90
|
+
case "data":
|
|
91
|
+
data = message.data
|
|
92
|
+
this.bibDB.saveBibEntries(data, true).then(idTranslations => {
|
|
93
|
+
const newIds = idTranslations.map(idTrans => idTrans[1])
|
|
94
|
+
this.addToListCall(newIds)
|
|
95
|
+
})
|
|
96
|
+
break
|
|
97
|
+
default:
|
|
98
|
+
break
|
|
99
|
+
}
|
|
100
|
+
if (message.done && this.callback) {
|
|
101
|
+
this.callback()
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {Dialog, activateWait, addAlert, deactivateWait} from "fwtoolkit"
|
|
2
|
+
import {importBibFileTemplate} from "./templates"
|
|
3
|
+
/** First step of the bibliography file import. Creates a dialog box to specify upload file.
|
|
4
|
+
* Supports multiple formats: BibTeX/BibLaTeX, CSL-JSON, RIS, EndNote, Citavi, NBIB, ODT/DOCX citations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export class BibliographyFileImportDialog {
|
|
8
|
+
constructor(bibDB, addToListCall, app) {
|
|
9
|
+
this.bibDB = bibDB
|
|
10
|
+
this.addToListCall = addToListCall
|
|
11
|
+
this.tmpDB = false
|
|
12
|
+
this.app = app
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
init() {
|
|
16
|
+
if (this.app.isOffline()) {
|
|
17
|
+
addAlert(
|
|
18
|
+
"info",
|
|
19
|
+
gettext(
|
|
20
|
+
"You are currently offline. Please try again when you are back online."
|
|
21
|
+
)
|
|
22
|
+
)
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
const buttons = [
|
|
26
|
+
{
|
|
27
|
+
text: gettext("Import"),
|
|
28
|
+
classes: "fw-dark submit-import",
|
|
29
|
+
click: () => {
|
|
30
|
+
let bibFile = document.getElementById("bib-uploader").files
|
|
31
|
+
if (0 === bibFile.length) {
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
bibFile = bibFile[0]
|
|
35
|
+
if (10485760 < bibFile.size) {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
if (this.app.isOffline()) {
|
|
39
|
+
addAlert(
|
|
40
|
+
"info",
|
|
41
|
+
gettext(
|
|
42
|
+
"You are currently offline. Please try again when you are back online."
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
dialog.close()
|
|
46
|
+
return false
|
|
47
|
+
}
|
|
48
|
+
activateWait()
|
|
49
|
+
const reader = new window.FileReader()
|
|
50
|
+
reader.onload = event => {
|
|
51
|
+
import("./bibliography_import").then(
|
|
52
|
+
({BibliographyImporter}) => {
|
|
53
|
+
const importer = new BibliographyImporter(
|
|
54
|
+
event.target.result,
|
|
55
|
+
this.bibDB,
|
|
56
|
+
this.addToListCall,
|
|
57
|
+
() => deactivateWait()
|
|
58
|
+
)
|
|
59
|
+
importer.init()
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
reader.readAsText(bibFile)
|
|
64
|
+
dialog.close()
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
type: "cancel"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
const dialog = new Dialog({
|
|
72
|
+
id: "importbibtex",
|
|
73
|
+
title: gettext("Import a bibliography"),
|
|
74
|
+
body: importBibFileTemplate(),
|
|
75
|
+
height: 200,
|
|
76
|
+
buttons
|
|
77
|
+
})
|
|
78
|
+
dialog.open()
|
|
79
|
+
document
|
|
80
|
+
.getElementById("bib-uploader")
|
|
81
|
+
.addEventListener(
|
|
82
|
+
"change",
|
|
83
|
+
() =>
|
|
84
|
+
(document.getElementById("import-bib-name").innerHTML =
|
|
85
|
+
document
|
|
86
|
+
.getElementById("bib-uploader")
|
|
87
|
+
.value.replace(/C:\\fakepath\\/i, ""))
|
|
88
|
+
)
|
|
89
|
+
document
|
|
90
|
+
.getElementById("import-bib-btn")
|
|
91
|
+
.addEventListener("click", () =>
|
|
92
|
+
document.getElementById("bib-uploader").click()
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** a template for the bibliography file import dialog */
|
|
2
|
+
export const importBibFileTemplate = () =>
|
|
3
|
+
`<form id="import-bib-form" method="post" enctype="multipart/form-data" class="ajax-upload">
|
|
4
|
+
<input type="file" id="bib-uploader" name="bib" required />
|
|
5
|
+
<span id="import-bib-btn" class="fw-button fw-light fw-large">
|
|
6
|
+
${gettext("Select a file")}
|
|
7
|
+
</span>
|
|
8
|
+
<label id="import-bib-name" class="ajax-upload-label"></label>
|
|
9
|
+
<div class="import-format-info" style="margin-top: 10px; font-size: 0.9em; color: #666;">
|
|
10
|
+
${gettext("Supported formats: BibTeX/BibLaTeX, CSL-JSON, RIS, EndNote XML, EndNote Tagged, Citavi XML, Citavi JSON, NBIB/PubMed, ODT citations, DOCX citations")}
|
|
11
|
+
</div>
|
|
12
|
+
</form>`
|
package/src/index.js
ADDED