-
Notifications
You must be signed in to change notification settings - Fork 12
/
index.js
128 lines (112 loc) · 3.32 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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
const fs = require('fs')
const defaultOptions = {
iconSrc: 'blizzard'
}
/**
* Main Database class
*/
class Database extends Array {
constructor (fileName, options) {
let data = JSON.parse(fs.readFileSync(`${__dirname}/data/json/${fileName}.json`, 'utf8'))
const opts = { ...defaultOptions, ...options } // Merge options
// Parse icons to URL
if (opts.iconSrc === 'blizzard') {
data = data.map((x) => {
x.icon = `https://render-classic-us.worldofwarcraft.com/icons/56/${x.icon}.jpg`
return x
})
} else if (opts.iconSrc === 'wowhead') {
data = data.map((x) => {
x.icon = `https://wow.zamimg.com/images/wow/icons/large/${x.icon}.jpg`
return x
})
}
super(...data)
}
/**
* Override Array.prototype.filter
*
* This roughly implements Mozilla's builtin for `Array.prototype.filter`[1].
* V8 passes the prototype of the original Array into `ArraySpeciesCreate`[2][3],
* which is the Array that gets returned from `filter()`. However, they don't
* pass the arguments passed to the constructor of the original Array (this Class),
* which means that it will always return a new Array with ALL items, even when
* different categories are specified.[4]
*
* [1] https://hg.mozilla.org/mozilla-central/file/tip/js/src/builtin/Array.js#l320
* [2] https://github.com/v8/v8/blob/master/src/builtins/array-filter.tq#L193
* [3] https://www.ecma-international.org/ecma-262/7.0/#sec-arrayspeciescreate
* [4] https://runkit.com/kaptard/5c9daf33090ab900120465fe
*/
filter (fn) {
const A = []
for (const el of this) {
if (fn(el)) A.push(el)
}
return A
}
}
/**
* Item Database
*/
class Items extends Database {
constructor (options) {
super('data', options)
}
/**
* Converts the item link into an ingame parse-able string.
*/
getItemLink (itemId) {
const link = this.find((p) => p.itemId === itemId).itemLink.replace(/\|/g, '\\124')
return `/script DEFAULT_CHAT_FRAME:AddMessage("${link}");`
}
}
/**
* Professions Database
*/
class Professions extends Database {
constructor (options) {
super('professions', options)
}
/**
* Really small wrapper class to make professions accessible via .get('professionName')
*/
get (name) {
return this.find((p) => p.name === name)
}
}
/**
* Zone Database
*/
class Zones extends Database {
constructor (options) {
options = { ...options, iconSrc: false } // Disable icons because zones don't have one
super('zones', options)
}
}
/**
* Class Database
*/
class Classes extends Database {
constructor (options) {
const opts = { ...defaultOptions, ...options } // Merge options
if (opts.iconSrc === 'blizzard') opts.iconSrc = 'wowhead' // Change Blizzard source to Wowhead because Blizzard doesn't expose these icons (to my knowledge)
super('classes', opts)
// Spec icons
if (opts.iconSrc === 'wowhead') {
for (const el of this) {
el.specs = el.specs.map((x) => {
x.icon = `https://wow.zamimg.com/images/wow/icons/large/${x.icon}.jpg`
return x
})
}
}
}
/**
* Really small wrapper class to make classes accessible via .get('className')
*/
get (name) {
return this.find((p) => p.name === name)
}
}
module.exports = { Items, Professions, Zones, Classes }