source: imaps-frontend/node_modules/browserslist/node.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 11.4 KB
RevLine 
[d565449]1var feature = require('caniuse-lite/dist/unpacker/feature').default
2var region = require('caniuse-lite/dist/unpacker/region').default
3var path = require('path')
4var fs = require('fs')
5
6var BrowserslistError = require('./error')
7
8var IS_SECTION = /^\s*\[(.+)]\s*$/
9var CONFIG_PATTERN = /^browserslist-config-/
10var SCOPED_CONFIG__PATTERN = /@[^/]+(?:\/[^/]+)?\/browserslist-config(?:-|$|\/)/
11var TIME_TO_UPDATE_CANIUSE = 6 * 30 * 24 * 60 * 60 * 1000
12var FORMAT =
13 'Browserslist config should be a string or an array ' +
14 'of strings with browser queries'
15
16var dataTimeChecked = false
17var filenessCache = {}
18var configCache = {}
19function checkExtend(name) {
20 var use = ' Use `dangerousExtend` option to disable.'
21 if (!CONFIG_PATTERN.test(name) && !SCOPED_CONFIG__PATTERN.test(name)) {
22 throw new BrowserslistError(
23 'Browserslist config needs `browserslist-config-` prefix. ' + use
24 )
25 }
26 if (name.replace(/^@[^/]+\//, '').indexOf('.') !== -1) {
27 throw new BrowserslistError(
28 '`.` not allowed in Browserslist config name. ' + use
29 )
30 }
31 if (name.indexOf('node_modules') !== -1) {
32 throw new BrowserslistError(
33 '`node_modules` not allowed in Browserslist config.' + use
34 )
35 }
36}
37
38function isFile(file) {
39 if (file in filenessCache) {
40 return filenessCache[file]
41 }
42 var result = fs.existsSync(file) && fs.statSync(file).isFile()
43 if (!process.env.BROWSERSLIST_DISABLE_CACHE) {
44 filenessCache[file] = result
45 }
46 return result
47}
48
49function eachParent(file, callback) {
50 var dir = isFile(file) ? path.dirname(file) : file
51 var loc = path.resolve(dir)
52 do {
53 if (!pathInRoot(loc)) break
54 var result = callback(loc)
55 if (typeof result !== 'undefined') return result
56 } while (loc !== (loc = path.dirname(loc)))
57 return undefined
58}
59
60function pathInRoot(p) {
61 if (!process.env.BROWSERSLIST_ROOT_PATH) return true
62 var rootPath = path.resolve(process.env.BROWSERSLIST_ROOT_PATH)
63 if (path.relative(rootPath, p).substring(0, 2) === '..') {
64 return false
65 }
66 return true
67}
68
69function check(section) {
70 if (Array.isArray(section)) {
71 for (var i = 0; i < section.length; i++) {
72 if (typeof section[i] !== 'string') {
73 throw new BrowserslistError(FORMAT)
74 }
75 }
76 } else if (typeof section !== 'string') {
77 throw new BrowserslistError(FORMAT)
78 }
79}
80
81function pickEnv(config, opts) {
82 if (typeof config !== 'object') return config
83
84 var name
85 if (typeof opts.env === 'string') {
86 name = opts.env
87 } else if (process.env.BROWSERSLIST_ENV) {
88 name = process.env.BROWSERSLIST_ENV
89 } else if (process.env.NODE_ENV) {
90 name = process.env.NODE_ENV
91 } else {
92 name = 'production'
93 }
94
95 if (opts.throwOnMissing) {
96 if (name && name !== 'defaults' && !config[name]) {
97 throw new BrowserslistError(
98 'Missing config for Browserslist environment `' + name + '`'
99 )
100 }
101 }
102
103 return config[name] || config.defaults
104}
105
106function parsePackage(file) {
107 var config = JSON.parse(
108 fs
109 .readFileSync(file)
110 .toString()
111 .replace(/^\uFEFF/m, '')
112 )
113 if (config.browserlist && !config.browserslist) {
114 throw new BrowserslistError(
115 '`browserlist` key instead of `browserslist` in ' + file
116 )
117 }
118 var list = config.browserslist
119 if (Array.isArray(list) || typeof list === 'string') {
120 list = { defaults: list }
121 }
122 for (var i in list) {
123 check(list[i])
124 }
125
126 return list
127}
128
129function latestReleaseTime(agents) {
130 var latest = 0
131 for (var name in agents) {
132 var dates = agents[name].releaseDate || {}
133 for (var key in dates) {
134 if (latest < dates[key]) {
135 latest = dates[key]
136 }
137 }
138 }
139 return latest * 1000
140}
141
142function normalizeStats(data, stats) {
143 if (!data) {
144 data = {}
145 }
146 if (stats && 'dataByBrowser' in stats) {
147 stats = stats.dataByBrowser
148 }
149
150 if (typeof stats !== 'object') return undefined
151
152 var normalized = {}
153 for (var i in stats) {
154 var versions = Object.keys(stats[i])
155 if (versions.length === 1 && data[i] && data[i].versions.length === 1) {
156 var normal = data[i].versions[0]
157 normalized[i] = {}
158 normalized[i][normal] = stats[i][versions[0]]
159 } else {
160 normalized[i] = stats[i]
161 }
162 }
163
164 return normalized
165}
166
167function normalizeUsageData(usageData, data) {
168 for (var browser in usageData) {
169 var browserUsage = usageData[browser]
170 // https://github.com/browserslist/browserslist/issues/431#issuecomment-565230615
171 // caniuse-db returns { 0: "percentage" } for `and_*` regional stats
172 if ('0' in browserUsage) {
173 var versions = data[browser].versions
174 browserUsage[versions[versions.length - 1]] = browserUsage[0]
175 delete browserUsage[0]
176 }
177 }
178}
179
180module.exports = {
181 loadQueries: function loadQueries(ctx, name) {
182 if (!ctx.dangerousExtend && !process.env.BROWSERSLIST_DANGEROUS_EXTEND) {
183 checkExtend(name)
184 }
185 var queries = require(require.resolve(name, { paths: ['.', ctx.path] }))
186 if (queries) {
187 if (Array.isArray(queries)) {
188 return queries
189 } else if (typeof queries === 'object') {
190 if (!queries.defaults) queries.defaults = []
191 return pickEnv(queries, ctx, name)
192 }
193 }
194 throw new BrowserslistError(
195 '`' +
196 name +
197 '` config exports not an array of queries' +
198 ' or an object of envs'
199 )
200 },
201
202 loadStat: function loadStat(ctx, name, data) {
203 if (!ctx.dangerousExtend && !process.env.BROWSERSLIST_DANGEROUS_EXTEND) {
204 checkExtend(name)
205 }
206 var stats = require(require.resolve(
207 path.join(name, 'browserslist-stats.json'),
208 { paths: ['.'] }
209 ))
210 return normalizeStats(data, stats)
211 },
212
213 getStat: function getStat(opts, data) {
214 var stats
215 if (opts.stats) {
216 stats = opts.stats
217 } else if (process.env.BROWSERSLIST_STATS) {
218 stats = process.env.BROWSERSLIST_STATS
219 } else if (opts.path && path.resolve && fs.existsSync) {
220 stats = eachParent(opts.path, function (dir) {
221 var file = path.join(dir, 'browserslist-stats.json')
222 return isFile(file) ? file : undefined
223 })
224 }
225 if (typeof stats === 'string') {
226 try {
227 stats = JSON.parse(fs.readFileSync(stats))
228 } catch (e) {
229 throw new BrowserslistError("Can't read " + stats)
230 }
231 }
232 return normalizeStats(data, stats)
233 },
234
235 loadConfig: function loadConfig(opts) {
236 if (process.env.BROWSERSLIST) {
237 return process.env.BROWSERSLIST
238 } else if (opts.config || process.env.BROWSERSLIST_CONFIG) {
239 var file = opts.config || process.env.BROWSERSLIST_CONFIG
240 if (path.basename(file) === 'package.json') {
241 return pickEnv(parsePackage(file), opts)
242 } else {
243 return pickEnv(module.exports.readConfig(file), opts)
244 }
245 } else if (opts.path) {
246 return pickEnv(module.exports.findConfig(opts.path), opts)
247 } else {
248 return undefined
249 }
250 },
251
252 loadCountry: function loadCountry(usage, country, data) {
253 var code = country.replace(/[^\w-]/g, '')
254 if (!usage[code]) {
255 var compressed
256 try {
257 compressed = require('caniuse-lite/data/regions/' + code + '.js')
258 } catch (e) {
259 throw new BrowserslistError('Unknown region name `' + code + '`.')
260 }
261 var usageData = region(compressed)
262 normalizeUsageData(usageData, data)
263 usage[country] = {}
264 for (var i in usageData) {
265 for (var j in usageData[i]) {
266 usage[country][i + ' ' + j] = usageData[i][j]
267 }
268 }
269 }
270 },
271
272 loadFeature: function loadFeature(features, name) {
273 name = name.replace(/[^\w-]/g, '')
274 if (features[name]) return
275 var compressed
276 try {
277 compressed = require('caniuse-lite/data/features/' + name + '.js')
278 } catch (e) {
279 throw new BrowserslistError('Unknown feature name `' + name + '`.')
280 }
281 var stats = feature(compressed).stats
282 features[name] = {}
283 for (var i in stats) {
284 features[name][i] = {}
285 for (var j in stats[i]) {
286 features[name][i][j] = stats[i][j]
287 }
288 }
289 },
290
291 parseConfig: function parseConfig(string) {
292 var result = { defaults: [] }
293 var sections = ['defaults']
294
295 string
296 .toString()
297 .replace(/#[^\n]*/g, '')
298 .split(/\n|,/)
299 .map(function (line) {
300 return line.trim()
301 })
302 .filter(function (line) {
303 return line !== ''
304 })
305 .forEach(function (line) {
306 if (IS_SECTION.test(line)) {
307 sections = line.match(IS_SECTION)[1].trim().split(' ')
308 sections.forEach(function (section) {
309 if (result[section]) {
310 throw new BrowserslistError(
311 'Duplicate section ' + section + ' in Browserslist config'
312 )
313 }
314 result[section] = []
315 })
316 } else {
317 sections.forEach(function (section) {
318 result[section].push(line)
319 })
320 }
321 })
322
323 return result
324 },
325
326 readConfig: function readConfig(file) {
327 if (!isFile(file)) {
328 throw new BrowserslistError("Can't read " + file + ' config')
329 }
330 return module.exports.parseConfig(fs.readFileSync(file))
331 },
332
333 findConfig: function findConfig(from) {
334 from = path.resolve(from)
335
336 var passed = []
337 var resolved = eachParent(from, function (dir) {
338 if (dir in configCache) {
339 return configCache[dir]
340 }
341
342 passed.push(dir)
343
344 var config = path.join(dir, 'browserslist')
345 var pkg = path.join(dir, 'package.json')
346 var rc = path.join(dir, '.browserslistrc')
347
348 var pkgBrowserslist
349 if (isFile(pkg)) {
350 try {
351 pkgBrowserslist = parsePackage(pkg)
352 } catch (e) {
353 if (e.name === 'BrowserslistError') throw e
354 console.warn(
355 '[Browserslist] Could not parse ' + pkg + '. Ignoring it.'
356 )
357 }
358 }
359
360 if (isFile(config) && pkgBrowserslist) {
361 throw new BrowserslistError(
362 dir + ' contains both browserslist and package.json with browsers'
363 )
364 } else if (isFile(rc) && pkgBrowserslist) {
365 throw new BrowserslistError(
366 dir + ' contains both .browserslistrc and package.json with browsers'
367 )
368 } else if (isFile(config) && isFile(rc)) {
369 throw new BrowserslistError(
370 dir + ' contains both .browserslistrc and browserslist'
371 )
372 } else if (isFile(config)) {
373 return module.exports.readConfig(config)
374 } else if (isFile(rc)) {
375 return module.exports.readConfig(rc)
376 } else {
377 return pkgBrowserslist
378 }
379 })
380 if (!process.env.BROWSERSLIST_DISABLE_CACHE) {
381 passed.forEach(function (dir) {
382 configCache[dir] = resolved
383 })
384 }
385 return resolved
386 },
387
388 clearCaches: function clearCaches() {
389 dataTimeChecked = false
390 filenessCache = {}
391 configCache = {}
392
393 this.cache = {}
394 },
395
396 oldDataWarning: function oldDataWarning(agentsObj) {
397 if (dataTimeChecked) return
398 dataTimeChecked = true
399 if (process.env.BROWSERSLIST_IGNORE_OLD_DATA) return
400
401 var latest = latestReleaseTime(agentsObj)
402 var halfYearAgo = Date.now() - TIME_TO_UPDATE_CANIUSE
403
404 if (latest !== 0 && latest < halfYearAgo) {
405 console.warn(
406 'Browserslist: caniuse-lite is outdated. Please run:\n' +
407 ' npx update-browserslist-db@latest\n' +
408 ' Why you should do it regularly: ' +
409 'https://github.com/browserslist/update-db#readme'
410 )
411 }
412 },
413
414 currentNode: function currentNode() {
415 return 'node ' + process.versions.node
416 },
417
418 env: process.env
419}
Note: See TracBrowser for help on using the repository browser.