forked from little-core-labs/little-media-box
-
Notifications
You must be signed in to change notification settings - Fork 1
/
extensions.js
172 lines (150 loc) · 4.17 KB
/
extensions.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
const binary = new Set(Array.from(require('binary-extensions')).sort())
const audio = new Set(Array.from(require('audio-extensions')).sort())
const image = new Set(Array.from(require('image-extensions')).sort())
const video = new Set(Array.from(require('video-extensions')).sort())
const text = new Set(Array.from(require('text-extensions')).sort())
text.add('ass') // Aegisub Advanced Substation Alpha File
text.add('m3u8') // UTF-8 M3U
text.add('mpd') // MPEG-DASH manifest file
text.add('srt') // SubRip Subtitle File
text.add('vtt') // Web Video Text Tracks File
video.add('264') // Ripped Video Data File
video.add('3gp') // 3GPP Multimedia File
video.add('3gp2') // 3GPP Multimedia File
video.add('3gpp') // 3GPP Media File
video.add('3gpp2') // 3GPP2 Multimedia File
video.add('h264') // H.264 Encoded Video File
video.add('hevc') // High Efficiency Video Coding File
video.add('m1v') // MPEG-1 Video File
video.add('ts') // Video Transport Stream File (also `.mpeg`) - by adding this we overload `.ts` over TypeScript files
/**
* The `Extensions` class represents an extended `Array` that contains a
* set of lexicographically sorted unique file extension names. The class
* provides various methods like checking the file type for an extension.
* @public
* @class
* @extends Array
*/
class Extensions extends Array {
/**
* The known file types that extension names could map to.
* The order in which they appear in this array is the order
* in which the extension name to file type resolution occurs.
* @static
* @protected
*/
static get types() {
return [
'video',
'audio',
'image',
'binary',
'text'
]
}
/**
* `Extensions` class constructor.
* @private
*/
constructor() {
const all = Extensions.types
.map((type) => Extensions.prototype[type])
.reduce((all, extensions) => all.concat(...extensions), [])
super(...new Set(all))
}
/**
* The known file types that extension names could map to.
* @accessor
*/
get types() {
return Extensions.types
}
/**
* An array of all binary file extension names.
* @accessor
*/
get binary() {
return Array.from(binary)
}
/**
* An array of all image file extension names.
* @accessor
*/
get image() {
return Array.from(image)
}
/**
* An array of all audio file extension names.
* @accessor
*/
get audio() {
return Array.from(audio)
}
/**
* An array of all video file extension names.
* @accessor
*/
get video() {
return Array.from(video)
}
/**
* An array of all text file extension names.
* @accessor
*/
get text() {
return Array.from(text)
}
/**
* Determines the file type of an extension. If the type
* cannot be resolved, then 'unknown' is returned. The file
* type resolution precedence can be set by setting the type
* order in a `precedence` array. The default file type resolution
* order is the order in which the types appear in `extensions.types`.
* @param {String} extname
* @param {?(Array<String>)} precedence
* @return {String}
* @throws TypeError
*/
typeof(extname, precedence) {
if ('string' !== typeof extname) {
throw new TypeError('Extension name must be a string.')
}
if ('.' === extname[0]) {
extname = extname.slice(1)
}
extname = extname.toLowerCase()
if (false === Array.isArray(precedence)) {
precedence = []
}
const types = Array.from(Extensions.types)
.sort((prev, current) => {
const left = precedence.indexOf(prev)
const right = precedence.indexOf(current)
if (-1 !== left && -1 === right) {
return -1
} else if (-1 === left && -1 !== right) {
return 1
} else if (-1 === left && -1 === right) {
return 0
} else if (left === right) {
return 0
} else if (left < right) {
return -1
} else {
return 1
}
})
for (const type of types) {
if (this[type].includes(extname)) {
return type
}
}
return 'unknown'
}
}
/**
* Module exports.
*/
module.exports = Object.assign(new Extensions(), {
Extensions
})