UNPKG

5.75 kBJavaScriptView Raw
1'use strict';
2
3var es5 = require('../caniuse/es5');
4var es6 = require('../caniuse/es6');
5
6function parseId(entryId) {
7 // Parse browser name and version
8 var m = /^([^0-9_]+)([0-9_]+)?$/.exec(entryId);
9 // If it is not compliant we move on
10 if (!m) {
11 return null;
12 }
13
14 var browser = m[1];
15 var vers = String(m[2] || -1);
16
17 // Some version indicator are structured like 413 for version 4.13, so we try to parse that here
18 if (['safari', 'konq', 'ios'].indexOf(browser) > -1 && vers.length > 1) {
19 var dec = vers.substr(1).replace('_', '');
20 vers = vers[0] + '.' + ('0' + dec).substr(-2);
21 }
22
23 // Some have a '_' instead of the '.' in the version numeber. We correct that here.
24 if (browser === 'opera' || browser === 'firefox') {
25 vers = vers.replace('_', '.');
26 }
27
28 return { browser: browser, version: Number(vers) };
29}
30
31// Map browsers from the DB
32function mapBrowsers(browsers) {
33 return Object.keys(browsers).reduce(function (map, name) {
34 var current = browsers[name];
35
36 // Skip non client and unstable browsers
37 if (current.platformtype && current.platformtype !== 'mobile' || current.unstable) {
38 return map;
39 }
40
41 var parsed = parseId(name);
42
43 if (!parsed) {
44 return map;
45 }
46
47 var list = map.get(parsed.browser) || new Set();
48 var all = allBrowsers.get(parsed.browser) || new Set();
49
50 // We combine the parsed version with the name, to have the correct DB name reference
51 var vers = { version: parsed.version, id: name };
52
53 // Update browser in the global
54 all.add(vers);
55 allBrowsers.set(parsed.browser, all);
56
57 // Update the current browser (and return it)
58 list.add(vers);
59 return map.set(parsed.browser, list);
60 }, new Map());
61}
62
63// Sort the browser version decending (newest first)
64function sortVersions(map) {
65 var _iteratorNormalCompletion = true;
66 var _didIteratorError = false;
67 var _iteratorError = undefined;
68
69 try {
70 for (var _iterator = map.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
71 var entry = _step.value;
72
73 map.set(entry[0], Array.from(entry[1]).sort(function (a, b) {
74 return b.version - a.version;
75 }));
76 }
77 } catch (err) {
78 _didIteratorError = true;
79 _iteratorError = err;
80 } finally {
81 try {
82 if (!_iteratorNormalCompletion && _iterator.return) {
83 _iterator.return();
84 }
85 } finally {
86 if (_didIteratorError) {
87 throw _iteratorError;
88 }
89 }
90 }
91
92 return map;
93}
94
95// Determine the available browsers from the DB
96var allBrowsers = new Map();
97var es5browsers = sortVersions(mapBrowsers(es5.browsers));
98var es6browsers = sortVersions(mapBrowsers(es6.browsers));
99allBrowsers = sortVersions(allBrowsers);
100
101module.exports.parseId = parseId;
102
103module.exports.getVersions = function getVersions(versions) {
104 if (!Array.isArray(versions)) {
105 versions = [versions];
106 }
107
108 // Loop through each browser version phrase
109 var parsed = versions.reduce(function (map, versionExp) {
110 var m = void 0;
111
112 // Phrase like 'last 2 versions' or 'latest version'
113 if (m = /(?:last|latest)( \d+)? versions?/.exec(versionExp)) {
114 var i = Math.max(0, Number(m[1] || 0) - 1);
115
116 // Loop through all the browsers
117 var _iteratorNormalCompletion2 = true;
118 var _didIteratorError2 = false;
119 var _iteratorError2 = undefined;
120
121 try {
122 for (var _iterator2 = allBrowsers.entries()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
123 var entry = _step2.value;
124
125 var browser = entry[0];
126 var list = entry[1];
127
128 // Grab the version from the defined index
129 var vers = list[i];
130 // Or the last if it doesn't have a version list that long
131 if (!vers) {
132 vers = list[list.length - 1];
133 }
134
135 // We go for lowest version, so only update entry if the found version
136 // is lower than the currently stored one
137 var curr = map.get(browser);
138 if (!curr || curr.version > vers.version) {
139 map.set(browser, vers);
140 }
141 }
142
143 // Exact browser like 'ie 8' or 'FireFox 30'
144 } catch (err) {
145 _didIteratorError2 = true;
146 _iteratorError2 = err;
147 } finally {
148 try {
149 if (!_iteratorNormalCompletion2 && _iterator2.return) {
150 _iterator2.return();
151 }
152 } finally {
153 if (_didIteratorError2) {
154 throw _iteratorError2;
155 }
156 }
157 }
158 } else if (m = /(\w+)\s+([0-9.]+)/.exec(versionExp)) {
159 var _browser = m[1];
160 var target = Number(m[2]);
161 var _list = allBrowsers.get(_browser);
162
163 // Just stop here if there were no browser stored with that name
164 if (!_list) {
165 return map;
166 }
167
168 var _vers = void 0;
169
170 // Search for a matching version
171 // - should be the same or the first that is lower
172 _list.some(function (item) {
173 if (item.version <= target) {
174 _vers = item;
175 return true;
176 }
177 });
178
179 // Take the lowest version if the defined version was too low
180 if (!_vers) {
181 _vers = _list[_list.length - 1];
182 }
183
184 // We go for lowest version, so only update entry if the found version
185 // is lower than the currently stored one
186 var _curr = map.get(_browser);
187 if (!_curr || _curr.version > _vers.version) {
188 map.set(_browser, _vers);
189 }
190 }
191
192 // Return the findings
193 return map;
194 }, new Map());
195
196 return {
197 all: allBrowsers,
198 es5: es5browsers,
199 es6: es6browsers,
200 parsed: parsed
201 };
202};