@uniweb/scholar 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 +201 -0
- package/README.md +297 -0
- package/package.json +49 -0
- package/src/bibliography/formatters/apa.js +352 -0
- package/src/bibliography/formatters/chicago.js +339 -0
- package/src/bibliography/formatters/ieee.js +332 -0
- package/src/bibliography/formatters/index.js +56 -0
- package/src/bibliography/formatters/mla.js +335 -0
- package/src/bibliography/index.js +42 -0
- package/src/bibliography/parsers/bibtex.js +405 -0
- package/src/bibliography/parsers/index.js +7 -0
- package/src/bibliography/utils/authors.js +277 -0
- package/src/bibliography/utils/dates.js +228 -0
- package/src/bibliography/utils/index.js +8 -0
- package/src/citations/Bibliography.jsx +129 -0
- package/src/citations/Citation.jsx +196 -0
- package/src/citations/CitationProvider.jsx +147 -0
- package/src/citations/index.js +16 -0
- package/src/components/AuthorList.jsx +147 -0
- package/src/components/BibtexBlock.jsx +160 -0
- package/src/components/CiteButton.jsx +175 -0
- package/src/components/DoiLink.jsx +97 -0
- package/src/components/index.js +12 -0
- package/src/index.js +35 -0
- package/src/math/Equation.jsx +163 -0
- package/src/math/EquationRef.jsx +63 -0
- package/src/math/Math.jsx +115 -0
- package/src/math/index.js +12 -0
- package/src/math/katex-loader.js +105 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IEEE Reference Formatter
|
|
3
|
+
*
|
|
4
|
+
* Formats references according to IEEE citation style.
|
|
5
|
+
*
|
|
6
|
+
* @module @uniweb/scholar/bibliography/formatters/ieee
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { formatIeeeAuthors, parseAuthorString } from '../utils/authors.js'
|
|
10
|
+
import { formatIeeeDate, getYear } from '../utils/dates.js'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Format a journal article in IEEE style
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} pub - Publication data
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
function formatArticle(pub) {
|
|
19
|
+
const parts = []
|
|
20
|
+
|
|
21
|
+
// Authors
|
|
22
|
+
const authors = Array.isArray(pub.authors)
|
|
23
|
+
? pub.authors
|
|
24
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
25
|
+
if (authors.length) {
|
|
26
|
+
parts.push(`${formatIeeeAuthors(authors)},`)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Title in quotes
|
|
30
|
+
if (pub.title) {
|
|
31
|
+
parts.push(`"${pub.title},"`)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Journal (italicized)
|
|
35
|
+
if (pub.journal) {
|
|
36
|
+
let journalPart = pub.journal
|
|
37
|
+
if (pub.volume) {
|
|
38
|
+
journalPart += `, vol. ${pub.volume}`
|
|
39
|
+
}
|
|
40
|
+
if (pub.issue) {
|
|
41
|
+
journalPart += `, no. ${pub.issue}`
|
|
42
|
+
}
|
|
43
|
+
if (pub.pages) {
|
|
44
|
+
journalPart += `, pp. ${pub.pages}`
|
|
45
|
+
}
|
|
46
|
+
// Date
|
|
47
|
+
const date = formatIeeeDate(pub.date || pub.year)
|
|
48
|
+
if (date) {
|
|
49
|
+
journalPart += `, ${date}`
|
|
50
|
+
}
|
|
51
|
+
parts.push(`${journalPart}.`)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// DOI
|
|
55
|
+
if (pub.doi) {
|
|
56
|
+
parts.push(`doi: ${pub.doi.replace(/^https?:\/\/doi\.org\//, '')}.`)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return parts.join(' ')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Format a book in IEEE style
|
|
64
|
+
*
|
|
65
|
+
* @param {Object} pub - Publication data
|
|
66
|
+
* @returns {string}
|
|
67
|
+
*/
|
|
68
|
+
function formatBook(pub) {
|
|
69
|
+
const parts = []
|
|
70
|
+
|
|
71
|
+
// Authors or editors
|
|
72
|
+
const authors = Array.isArray(pub.authors)
|
|
73
|
+
? pub.authors
|
|
74
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
75
|
+
const editors = Array.isArray(pub.editors)
|
|
76
|
+
? pub.editors
|
|
77
|
+
: parseAuthorString(pub.editors || pub.editor)
|
|
78
|
+
|
|
79
|
+
if (authors.length) {
|
|
80
|
+
parts.push(`${formatIeeeAuthors(authors)},`)
|
|
81
|
+
} else if (editors.length) {
|
|
82
|
+
parts.push(`${formatIeeeAuthors(editors)}, Ed${editors.length > 1 ? 's' : ''}.,`)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Title (italicized)
|
|
86
|
+
if (pub.title) {
|
|
87
|
+
let title = pub.title
|
|
88
|
+
if (pub.edition && pub.edition !== '1') {
|
|
89
|
+
title += `, ${pub.edition} ed`
|
|
90
|
+
}
|
|
91
|
+
parts.push(`${title}.`)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Place and publisher
|
|
95
|
+
if (pub.address && pub.publisher) {
|
|
96
|
+
parts.push(`${pub.address}: ${pub.publisher},`)
|
|
97
|
+
} else if (pub.publisher) {
|
|
98
|
+
parts.push(`${pub.publisher},`)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Year
|
|
102
|
+
const year = getYear(pub.year || pub.date)
|
|
103
|
+
if (year) {
|
|
104
|
+
parts.push(`${year}.`)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return parts.join(' ')
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Format a book chapter in IEEE style
|
|
112
|
+
*
|
|
113
|
+
* @param {Object} pub - Publication data
|
|
114
|
+
* @returns {string}
|
|
115
|
+
*/
|
|
116
|
+
function formatInBook(pub) {
|
|
117
|
+
const parts = []
|
|
118
|
+
|
|
119
|
+
// Chapter authors
|
|
120
|
+
const authors = Array.isArray(pub.authors)
|
|
121
|
+
? pub.authors
|
|
122
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
123
|
+
if (authors.length) {
|
|
124
|
+
parts.push(`${formatIeeeAuthors(authors)},`)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Chapter title in quotes
|
|
128
|
+
if (pub.title) {
|
|
129
|
+
parts.push(`"${pub.title},"`)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Book title
|
|
133
|
+
if (pub.bookTitle) {
|
|
134
|
+
let bookPart = `in ${pub.bookTitle}`
|
|
135
|
+
const editors = Array.isArray(pub.editors)
|
|
136
|
+
? pub.editors
|
|
137
|
+
: parseAuthorString(pub.editors || pub.editor)
|
|
138
|
+
if (editors.length) {
|
|
139
|
+
bookPart += `, ${formatIeeeAuthors(editors)}, Ed${editors.length > 1 ? 's' : ''}.`
|
|
140
|
+
}
|
|
141
|
+
parts.push(bookPart)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Place and publisher
|
|
145
|
+
if (pub.address && pub.publisher) {
|
|
146
|
+
parts.push(`${pub.address}: ${pub.publisher},`)
|
|
147
|
+
} else if (pub.publisher) {
|
|
148
|
+
parts.push(`${pub.publisher},`)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Year and pages
|
|
152
|
+
const year = getYear(pub.year || pub.date)
|
|
153
|
+
if (year) {
|
|
154
|
+
if (pub.pages) {
|
|
155
|
+
parts.push(`${year}, pp. ${pub.pages}.`)
|
|
156
|
+
} else {
|
|
157
|
+
parts.push(`${year}.`)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return parts.join(' ')
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Format conference proceedings in IEEE style
|
|
166
|
+
*
|
|
167
|
+
* @param {Object} pub - Publication data
|
|
168
|
+
* @returns {string}
|
|
169
|
+
*/
|
|
170
|
+
function formatConference(pub) {
|
|
171
|
+
const parts = []
|
|
172
|
+
|
|
173
|
+
// Authors
|
|
174
|
+
const authors = Array.isArray(pub.authors)
|
|
175
|
+
? pub.authors
|
|
176
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
177
|
+
if (authors.length) {
|
|
178
|
+
parts.push(`${formatIeeeAuthors(authors)},`)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Title in quotes
|
|
182
|
+
if (pub.title) {
|
|
183
|
+
parts.push(`"${pub.title},"`)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Conference
|
|
187
|
+
if (pub.booktitle || pub.conference) {
|
|
188
|
+
let confPart = `in ${pub.booktitle || pub.conference}`
|
|
189
|
+
if (pub.address || pub.location) {
|
|
190
|
+
confPart += `, ${pub.address || pub.location}`
|
|
191
|
+
}
|
|
192
|
+
// Year
|
|
193
|
+
const year = getYear(pub.year || pub.date)
|
|
194
|
+
if (year) {
|
|
195
|
+
confPart += `, ${year}`
|
|
196
|
+
}
|
|
197
|
+
if (pub.pages) {
|
|
198
|
+
confPart += `, pp. ${pub.pages}`
|
|
199
|
+
}
|
|
200
|
+
parts.push(`${confPart}.`)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// DOI
|
|
204
|
+
if (pub.doi) {
|
|
205
|
+
parts.push(`doi: ${pub.doi.replace(/^https?:\/\/doi\.org\//, '')}.`)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return parts.join(' ')
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Format a website/webpage in IEEE style
|
|
213
|
+
*
|
|
214
|
+
* @param {Object} pub - Publication data
|
|
215
|
+
* @returns {string}
|
|
216
|
+
*/
|
|
217
|
+
function formatWebsite(pub) {
|
|
218
|
+
const parts = []
|
|
219
|
+
|
|
220
|
+
// Authors or organization
|
|
221
|
+
const authors = Array.isArray(pub.authors)
|
|
222
|
+
? pub.authors
|
|
223
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
224
|
+
if (authors.length) {
|
|
225
|
+
parts.push(`${formatIeeeAuthors(authors)}.`)
|
|
226
|
+
} else if (pub.organization) {
|
|
227
|
+
parts.push(`${pub.organization}.`)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Title in quotes
|
|
231
|
+
if (pub.title) {
|
|
232
|
+
parts.push(`"${pub.title}."`)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Site name (italicized)
|
|
236
|
+
if (pub.siteName) {
|
|
237
|
+
parts.push(`${pub.siteName}.`)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// URL and access date
|
|
241
|
+
if (pub.url) {
|
|
242
|
+
let urlPart = pub.url
|
|
243
|
+
if (pub.accessDate) {
|
|
244
|
+
urlPart += ` (accessed ${formatIeeeDate(pub.accessDate)})`
|
|
245
|
+
}
|
|
246
|
+
parts.push(`${urlPart}.`)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return parts.join(' ')
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Format a thesis/dissertation in IEEE style
|
|
254
|
+
*
|
|
255
|
+
* @param {Object} pub - Publication data
|
|
256
|
+
* @returns {string}
|
|
257
|
+
*/
|
|
258
|
+
function formatThesis(pub) {
|
|
259
|
+
const parts = []
|
|
260
|
+
|
|
261
|
+
// Author
|
|
262
|
+
const authors = Array.isArray(pub.authors)
|
|
263
|
+
? pub.authors
|
|
264
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
265
|
+
if (authors.length) {
|
|
266
|
+
parts.push(`${formatIeeeAuthors(authors)},`)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Title in quotes
|
|
270
|
+
if (pub.title) {
|
|
271
|
+
parts.push(`"${pub.title},"`)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Type
|
|
275
|
+
const type = pub.type === 'mastersthesis' ? 'M.S. thesis' : 'Ph.D. dissertation'
|
|
276
|
+
parts.push(type + ',')
|
|
277
|
+
|
|
278
|
+
// Institution
|
|
279
|
+
if (pub.school || pub.institution) {
|
|
280
|
+
parts.push(`${pub.school || pub.institution},`)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Location and year
|
|
284
|
+
if (pub.address) {
|
|
285
|
+
parts.push(`${pub.address},`)
|
|
286
|
+
}
|
|
287
|
+
const year = getYear(pub.year || pub.date)
|
|
288
|
+
if (year) {
|
|
289
|
+
parts.push(`${year}.`)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
return parts.join(' ')
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Format a reference in IEEE style
|
|
297
|
+
*
|
|
298
|
+
* @param {Object} pub - Publication data
|
|
299
|
+
* @param {Object} [options] - Formatting options
|
|
300
|
+
* @returns {string}
|
|
301
|
+
*/
|
|
302
|
+
export function formatIeee(pub, options = {}) {
|
|
303
|
+
const type = (pub.type || pub.entryType || 'article').toLowerCase()
|
|
304
|
+
|
|
305
|
+
switch (type) {
|
|
306
|
+
case 'article':
|
|
307
|
+
case 'journal':
|
|
308
|
+
return formatArticle(pub)
|
|
309
|
+
case 'book':
|
|
310
|
+
return formatBook(pub)
|
|
311
|
+
case 'inbook':
|
|
312
|
+
case 'incollection':
|
|
313
|
+
case 'chapter':
|
|
314
|
+
return formatInBook(pub)
|
|
315
|
+
case 'inproceedings':
|
|
316
|
+
case 'conference':
|
|
317
|
+
case 'proceedings':
|
|
318
|
+
return formatConference(pub)
|
|
319
|
+
case 'webpage':
|
|
320
|
+
case 'website':
|
|
321
|
+
case 'online':
|
|
322
|
+
return formatWebsite(pub)
|
|
323
|
+
case 'thesis':
|
|
324
|
+
case 'phdthesis':
|
|
325
|
+
case 'mastersthesis':
|
|
326
|
+
return formatThesis(pub)
|
|
327
|
+
default:
|
|
328
|
+
return formatArticle(pub)
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export default formatIeee
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bibliography Formatters
|
|
3
|
+
*
|
|
4
|
+
* @module @uniweb/scholar/bibliography/formatters
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { formatApa } from './apa.js'
|
|
8
|
+
export { formatMla } from './mla.js'
|
|
9
|
+
export { formatChicago } from './chicago.js'
|
|
10
|
+
export { formatIeee } from './ieee.js'
|
|
11
|
+
|
|
12
|
+
import { formatApa } from './apa.js'
|
|
13
|
+
import { formatMla } from './mla.js'
|
|
14
|
+
import { formatChicago } from './chicago.js'
|
|
15
|
+
import { formatIeee } from './ieee.js'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Available citation style formatters
|
|
19
|
+
*/
|
|
20
|
+
export const formatters = {
|
|
21
|
+
apa: formatApa,
|
|
22
|
+
mla: formatMla,
|
|
23
|
+
chicago: formatChicago,
|
|
24
|
+
ieee: formatIeee,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Format a reference in a specific style
|
|
29
|
+
*
|
|
30
|
+
* @param {Object} publication - Publication data
|
|
31
|
+
* @param {Object} [options]
|
|
32
|
+
* @param {string} [options.style='apa'] - Citation style (apa, mla, chicago, ieee)
|
|
33
|
+
* @returns {string} Formatted reference string
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* const ref = formatReference({
|
|
37
|
+
* type: 'article',
|
|
38
|
+
* authors: [{ family: 'Smith', given: 'John' }],
|
|
39
|
+
* year: 2024,
|
|
40
|
+
* title: 'A Study of Something',
|
|
41
|
+
* journal: 'Journal of Studies',
|
|
42
|
+
* volume: '10',
|
|
43
|
+
* pages: '1-10',
|
|
44
|
+
* doi: '10.1234/example'
|
|
45
|
+
* }, { style: 'apa' })
|
|
46
|
+
*/
|
|
47
|
+
export function formatReference(publication, options = {}) {
|
|
48
|
+
const { style = 'apa' } = options
|
|
49
|
+
|
|
50
|
+
const formatter = formatters[style.toLowerCase()]
|
|
51
|
+
if (!formatter) {
|
|
52
|
+
throw new Error(`Unknown citation style: ${style}. Available: ${Object.keys(formatters).join(', ')}`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return formatter(publication, options)
|
|
56
|
+
}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MLA 9th Edition Reference Formatter
|
|
3
|
+
*
|
|
4
|
+
* Formats references according to MLA 9th edition guidelines.
|
|
5
|
+
*
|
|
6
|
+
* @module @uniweb/scholar/bibliography/formatters/mla
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { formatMlaAuthors, parseAuthorString } from '../utils/authors.js'
|
|
10
|
+
import { formatMlaDate, getYear } from '../utils/dates.js'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Format a journal article in MLA style
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} pub - Publication data
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
function formatArticle(pub) {
|
|
19
|
+
const parts = []
|
|
20
|
+
|
|
21
|
+
// Authors
|
|
22
|
+
const authors = Array.isArray(pub.authors)
|
|
23
|
+
? pub.authors
|
|
24
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
25
|
+
if (authors.length) {
|
|
26
|
+
parts.push(`${formatMlaAuthors(authors)}.`)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Title in quotes
|
|
30
|
+
if (pub.title) {
|
|
31
|
+
parts.push(`"${pub.title}."`)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Container (journal name, italicized)
|
|
35
|
+
if (pub.journal) {
|
|
36
|
+
let container = pub.journal
|
|
37
|
+
if (pub.volume) {
|
|
38
|
+
container += `, vol. ${pub.volume}`
|
|
39
|
+
}
|
|
40
|
+
if (pub.issue) {
|
|
41
|
+
container += `, no. ${pub.issue}`
|
|
42
|
+
}
|
|
43
|
+
// Date
|
|
44
|
+
const year = getYear(pub.year || pub.date)
|
|
45
|
+
if (year) {
|
|
46
|
+
container += `, ${year}`
|
|
47
|
+
}
|
|
48
|
+
// Pages
|
|
49
|
+
if (pub.pages) {
|
|
50
|
+
container += `, pp. ${pub.pages}`
|
|
51
|
+
}
|
|
52
|
+
parts.push(`${container}.`)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// DOI
|
|
56
|
+
if (pub.doi) {
|
|
57
|
+
const doi = pub.doi.startsWith('http')
|
|
58
|
+
? pub.doi
|
|
59
|
+
: `https://doi.org/${pub.doi}`
|
|
60
|
+
parts.push(doi)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return parts.join(' ')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Format a book in MLA style
|
|
68
|
+
*
|
|
69
|
+
* @param {Object} pub - Publication data
|
|
70
|
+
* @returns {string}
|
|
71
|
+
*/
|
|
72
|
+
function formatBook(pub) {
|
|
73
|
+
const parts = []
|
|
74
|
+
|
|
75
|
+
// Authors or editors
|
|
76
|
+
const authors = Array.isArray(pub.authors)
|
|
77
|
+
? pub.authors
|
|
78
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
79
|
+
const editors = Array.isArray(pub.editors)
|
|
80
|
+
? pub.editors
|
|
81
|
+
: parseAuthorString(pub.editors || pub.editor)
|
|
82
|
+
|
|
83
|
+
if (authors.length) {
|
|
84
|
+
parts.push(`${formatMlaAuthors(authors)}.`)
|
|
85
|
+
} else if (editors.length) {
|
|
86
|
+
parts.push(
|
|
87
|
+
`${formatMlaAuthors(editors)}, editor${editors.length > 1 ? 's' : ''}.`
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Title (italicized)
|
|
92
|
+
if (pub.title) {
|
|
93
|
+
parts.push(`${pub.title}.`)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Edition
|
|
97
|
+
if (pub.edition && pub.edition !== '1') {
|
|
98
|
+
parts.push(`${pub.edition} ed.,`)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Publisher
|
|
102
|
+
if (pub.publisher) {
|
|
103
|
+
parts.push(`${pub.publisher},`)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Year
|
|
107
|
+
const year = getYear(pub.year || pub.date)
|
|
108
|
+
if (year) {
|
|
109
|
+
parts.push(`${year}.`)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return parts.join(' ')
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Format a book chapter in MLA style
|
|
117
|
+
*
|
|
118
|
+
* @param {Object} pub - Publication data
|
|
119
|
+
* @returns {string}
|
|
120
|
+
*/
|
|
121
|
+
function formatInBook(pub) {
|
|
122
|
+
const parts = []
|
|
123
|
+
|
|
124
|
+
// Chapter authors
|
|
125
|
+
const authors = Array.isArray(pub.authors)
|
|
126
|
+
? pub.authors
|
|
127
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
128
|
+
if (authors.length) {
|
|
129
|
+
parts.push(`${formatMlaAuthors(authors)}.`)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Chapter title in quotes
|
|
133
|
+
if (pub.title) {
|
|
134
|
+
parts.push(`"${pub.title}."`)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Book title (italicized)
|
|
138
|
+
if (pub.bookTitle) {
|
|
139
|
+
parts.push(`${pub.bookTitle},`)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Editors
|
|
143
|
+
const editors = Array.isArray(pub.editors)
|
|
144
|
+
? pub.editors
|
|
145
|
+
: parseAuthorString(pub.editors || pub.editor)
|
|
146
|
+
if (editors.length) {
|
|
147
|
+
parts.push(
|
|
148
|
+
`edited by ${formatMlaAuthors(editors)},`
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Publisher
|
|
153
|
+
if (pub.publisher) {
|
|
154
|
+
parts.push(`${pub.publisher},`)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Year
|
|
158
|
+
const year = getYear(pub.year || pub.date)
|
|
159
|
+
if (year) {
|
|
160
|
+
parts.push(`${year},`)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Pages
|
|
164
|
+
if (pub.pages) {
|
|
165
|
+
parts.push(`pp. ${pub.pages}.`)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return parts.join(' ')
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Format conference proceedings in MLA style
|
|
173
|
+
*
|
|
174
|
+
* @param {Object} pub - Publication data
|
|
175
|
+
* @returns {string}
|
|
176
|
+
*/
|
|
177
|
+
function formatConference(pub) {
|
|
178
|
+
const parts = []
|
|
179
|
+
|
|
180
|
+
// Authors
|
|
181
|
+
const authors = Array.isArray(pub.authors)
|
|
182
|
+
? pub.authors
|
|
183
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
184
|
+
if (authors.length) {
|
|
185
|
+
parts.push(`${formatMlaAuthors(authors)}.`)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Title in quotes
|
|
189
|
+
if (pub.title) {
|
|
190
|
+
parts.push(`"${pub.title}."`)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Conference/Proceedings (italicized)
|
|
194
|
+
if (pub.booktitle || pub.conference) {
|
|
195
|
+
parts.push(`${pub.booktitle || pub.conference},`)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Year
|
|
199
|
+
const year = getYear(pub.year || pub.date)
|
|
200
|
+
if (year) {
|
|
201
|
+
parts.push(`${year},`)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Pages
|
|
205
|
+
if (pub.pages) {
|
|
206
|
+
parts.push(`pp. ${pub.pages}.`)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// DOI
|
|
210
|
+
if (pub.doi) {
|
|
211
|
+
const doi = pub.doi.startsWith('http')
|
|
212
|
+
? pub.doi
|
|
213
|
+
: `https://doi.org/${pub.doi}`
|
|
214
|
+
parts.push(doi)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return parts.join(' ')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Format a website/webpage in MLA style
|
|
222
|
+
*
|
|
223
|
+
* @param {Object} pub - Publication data
|
|
224
|
+
* @returns {string}
|
|
225
|
+
*/
|
|
226
|
+
function formatWebsite(pub) {
|
|
227
|
+
const parts = []
|
|
228
|
+
|
|
229
|
+
// Authors
|
|
230
|
+
const authors = Array.isArray(pub.authors)
|
|
231
|
+
? pub.authors
|
|
232
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
233
|
+
if (authors.length) {
|
|
234
|
+
parts.push(`${formatMlaAuthors(authors)}.`)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Title in quotes
|
|
238
|
+
if (pub.title) {
|
|
239
|
+
parts.push(`"${pub.title}."`)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Site name (italicized)
|
|
243
|
+
if (pub.siteName) {
|
|
244
|
+
parts.push(`${pub.siteName},`)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Date
|
|
248
|
+
const date = formatMlaDate(pub.date || pub.year)
|
|
249
|
+
if (date) {
|
|
250
|
+
parts.push(`${date},`)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// URL
|
|
254
|
+
if (pub.url) {
|
|
255
|
+
parts.push(`${pub.url}.`)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return parts.join(' ')
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Format a thesis/dissertation in MLA style
|
|
263
|
+
*
|
|
264
|
+
* @param {Object} pub - Publication data
|
|
265
|
+
* @returns {string}
|
|
266
|
+
*/
|
|
267
|
+
function formatThesis(pub) {
|
|
268
|
+
const parts = []
|
|
269
|
+
|
|
270
|
+
// Author
|
|
271
|
+
const authors = Array.isArray(pub.authors)
|
|
272
|
+
? pub.authors
|
|
273
|
+
: parseAuthorString(pub.authors || pub.author)
|
|
274
|
+
if (authors.length) {
|
|
275
|
+
parts.push(`${formatMlaAuthors(authors)}.`)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Title (italicized)
|
|
279
|
+
if (pub.title) {
|
|
280
|
+
parts.push(`${pub.title}.`)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Year
|
|
284
|
+
const year = getYear(pub.year || pub.date)
|
|
285
|
+
if (year) {
|
|
286
|
+
parts.push(`${year}.`)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Institution and type
|
|
290
|
+
if (pub.school || pub.institution) {
|
|
291
|
+
const type = pub.type === 'mastersthesis' ? 'MA thesis' : 'PhD dissertation'
|
|
292
|
+
parts.push(`${pub.school || pub.institution}, ${type}.`)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return parts.join(' ')
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Format a reference in MLA 9th edition style
|
|
300
|
+
*
|
|
301
|
+
* @param {Object} pub - Publication data
|
|
302
|
+
* @param {Object} [options] - Formatting options
|
|
303
|
+
* @returns {string}
|
|
304
|
+
*/
|
|
305
|
+
export function formatMla(pub, options = {}) {
|
|
306
|
+
const type = (pub.type || pub.entryType || 'article').toLowerCase()
|
|
307
|
+
|
|
308
|
+
switch (type) {
|
|
309
|
+
case 'article':
|
|
310
|
+
case 'journal':
|
|
311
|
+
return formatArticle(pub)
|
|
312
|
+
case 'book':
|
|
313
|
+
return formatBook(pub)
|
|
314
|
+
case 'inbook':
|
|
315
|
+
case 'incollection':
|
|
316
|
+
case 'chapter':
|
|
317
|
+
return formatInBook(pub)
|
|
318
|
+
case 'inproceedings':
|
|
319
|
+
case 'conference':
|
|
320
|
+
case 'proceedings':
|
|
321
|
+
return formatConference(pub)
|
|
322
|
+
case 'webpage':
|
|
323
|
+
case 'website':
|
|
324
|
+
case 'online':
|
|
325
|
+
return formatWebsite(pub)
|
|
326
|
+
case 'thesis':
|
|
327
|
+
case 'phdthesis':
|
|
328
|
+
case 'mastersthesis':
|
|
329
|
+
return formatThesis(pub)
|
|
330
|
+
default:
|
|
331
|
+
return formatArticle(pub)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export default formatMla
|