-
Notifications
You must be signed in to change notification settings - Fork 7
/
index.js
63 lines (54 loc) · 1.49 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
* @typedef Options
* Configuration (optional).
* @property {boolean} [keepSpaces=false]
* Keep superfluous whitespace.
* Whitespace is turned into a space by default.
* @property {Array<string>} [stopwords]
* List of stopwords.
* When a lowercased word is included in this list, it will be used as
* lowercase.
* Otherwise words are capitalized.
*/
const stopwords = 'a an and at but by for in nor of on or so the to up yet'
const defaults = stopwords.split(' ')
/**
* Convert a value to AP/APA title case.
*
* @param {string} [value]
* Short text of unknown casing.
* @param {Options} [options]
* Configuration (optional).
* @returns {string}
* Title-cased version of `value`.
*/
export function apStyleTitleCase(value, options) {
const configuration = options || {}
if (!value) return ''
const stop = configuration.stopwords || defaults
const keep = configuration.keepSpaces
const splitter = /(\s+|[-‑–—,:;!?()])/
return value
.split(splitter)
.map((word, index, all) => {
// The splitter:
if (index % 2) {
if (/\s+/.test(word)) return keep ? word : ' '
return word
}
const lower = word.toLowerCase()
if (index !== 0 && index !== all.length - 1 && stop.includes(lower)) {
return lower
}
return capitalize(word)
})
.join('')
}
/**
*
* @param {string} value
* @returns {string}
*/
function capitalize(value) {
return value.charAt(0).toUpperCase() + value.slice(1)
}