From 126518c66fccd6ab6a2ae60106752412dbeffe76 Mon Sep 17 00:00:00 2001 From: gitgrimbo Date: Wed, 19 Sep 2018 12:24:52 +0100 Subject: [PATCH 1/8] remove mocha dependency. it is not used --- package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/package.json b/package.json index e499402..50f8e64 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,5 @@ "os-homedir": "^1.0.1", "yargs": "git+https://github.com/sgentle/yargs.git#config-booleans" }, - "devDependencies": { - "mocha": "^2.2.1" - } + "devDependencies": {} } From b30d90cb5093786903a929e03538d9dd99e3d8d3 Mon Sep 17 00:00:00 2001 From: gitgrimbo Date: Wed, 19 Sep 2018 10:42:00 +0100 Subject: [PATCH 2/8] convert from coffee-script to js This commit contains two variations of conversion. The most appropriate one should be used in a refactored PR. decaffeinate: https://github.com/decaffeinate/decaffeinate - pros - retains comments - uses es6 - let and const - template strings - lists recommendations for further conversion improvements - uses one declaration per line (personal preference) - cons - compact object literals on one line (personal preference) - e.g. current = {version, support, usage: 0}; - ifs on one line (personal preference) - e.g. if (nums == null) { nums = {}; } js2coffee: https://github.com/js2coffee/js2coffee - pros - TODO - cons - TODO --- caniuse.decaffeinate.js | 317 ++++++++++++++++++++++++++++++++++ caniuse.js2coffee.js | 371 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 688 insertions(+) create mode 100644 caniuse.decaffeinate.js create mode 100644 caniuse.js2coffee.js diff --git a/caniuse.decaffeinate.js b/caniuse.decaffeinate.js new file mode 100644 index 0000000..93ac82b --- /dev/null +++ b/caniuse.decaffeinate.js @@ -0,0 +1,317 @@ +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS103: Rewrite code to no longer use __guard__ + * DS104: Avoid inline assignments + * DS204: Change includes calls to have a more natural evaluation order + * DS205: Consider reworking code to avoid use of IIFEs + * DS207: Consider shorter variations of null checks + * DS209: Avoid top-level return + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const data = require('caniuse-db/data.json'); +const colors = require('colors'); +const linewrap = require('linewrap'); +const open = require('open'); +const path = require('path'); +const osHomedir = require('os-homedir'); +const os = require('os'); + +const { argv } = require('yargs') + .option('short', { + alias: 's', + type: 'boolean', + default: undefined, + describe: "Short output: show browsers on one line and don't display notes or description (default when displaying multiple results)" + }).option('long', { + alias: 'l', + type: 'boolean', + default: undefined, + describe: "Long output: show more information (default when displaying a single result)" + }).option('oneline', { + alias: '1', + type: 'boolean', + default: false, + describe: "One-line output: just global percentages, no per-browser info" + }).option('oneline-browser', { + alias: '2', + type: 'boolean', + default: false, + describe: "One-line output with browser info, implies --abbrev and --current" + }).option('abbrev', { + alias: 'a', + type: 'boolean', + default: false, + describe: "Abbreviate browser names" + }).option('percentages', { + alias: 'p', + type: 'boolean', + default: false, + describe: "Include browser version usage percentages" + }).option('future', { + alias: 'f', + type: 'boolean', + default: false, + describe: "Include future browser versions" + }).option('current', { + alias: 'c', + type: 'boolean', + default: false, + describe: "Don't include old browser versions, equivalent to --era e0" + }).option('era', { + alias: 'e', + type: 'string', + describe: `How many versions back to go, e0 to ${Object.keys(data.eras)[0]}` + }).option('mobile', { + alias: 'm', + type: 'boolean', + default: false, + describe: "Include mobile browsers" + }).option('desktop', { + alias: 'd', + type: 'boolean', + default: true, + describe: "Include desktop browsers" + }).option('browser', { + alias: 'b', + type: 'string', + describe: `Show results for these browsers, comma-separated (${Object.keys(data.agents)})` + }).option('ascii', { + alias: 'A', + type: 'boolean', + default: false, + describe: "UTF-8 symbols replacement with ASCII description" + }).option('web', { + alias: 'w', + type: 'boolean', + default: false, + describe: "Go to the search page on caniuse.com" + }).option('config', { + alias: 'C', + type: 'string', + default: path.join(osHomedir(), '.caniuse.json'), + describe: "Specify a config file with default options" + }).config('config') + .help('help') + ; + +let resultmap = {y: "✔", n: "✘", a: "◒", u: "‽", i: "ⓘ", w: "⚠"}; +const supernums = "⁰¹²³⁴⁵⁶⁷⁸⁹"; + +if (os.platform() === 'win32') { + resultmap = {y: "\u221A", n: "\u00D7", a: "\u0398", u: "\u203D", i: "\u24D8", w: "\u26A0"}; +} + +if (argv["ascii"]) { + resultmap = {y: "[Yes]", n: "[No]", a: "[Partly]", u: "[?!]", i: "[Info]", w: "[Warning]"}; +} + +if (((Date.now()/1000) - data.updated) > (30*60*60*24)) { + console.warn(`\ +${resultmap.w} Caniuse data is more than 30 days out of date! + Consider updating: npm install -g caniuse-cmd +\ +`.yellow + ); +} + +if (argv.web) { + return open(`http://caniuse.com/#search=${encodeURIComponent(argv._.join(' '))}`); +} + +const searchkey = argv._.join('').toLowerCase().replace(/\W*/g, ''); +const { agents } = data; + +const xwrap = linewrap((process.stdout.columns || 80), { + skipScheme: 'ansi-color', + whitespace: 'line', + tabWidth: 2, + wrapLineIndent: 0, + wrapLineIndentBase: /\S/ +} +); + +// Replace our scary braille spaces with real spaces +const wrap = str => xwrap(str).replace(/\u2800/g, ' '); + +if (argv["oneline-browser"]) { + argv.abbrev = true; + argv.short = true; + argv.current = true; +} + + +const types = []; +if (argv.desktop) { types.push('desktop'); } +if (argv.mobile) { types.push('mobile'); } + +const eras = Object.keys(data.eras); +const currentVersion = eras.indexOf("e0"); +const versionrange = [0, currentVersion]; +if (argv.future) { versionrange[1] = Infinity; } +if (argv.current) { versionrange[0] = currentVersion; } +if (argv.era) { versionrange[0] = eras.indexOf(argv.era); } + +// Generate the text for a single version result +// FIXME: gross output parameter +const makeResult = function(result, nums) { + let note; + if (nums == null) { nums = {}; } + const support = result.support[0]; + let out = ''; + // \u2800 is a braille space - the only kind of space I could find that + // doesn't get split by the word wrapper + out += (resultmap[support] || support) + "\u2800"; + if (result.version) { out += result.version; } + if (Array.from(result.support).includes("x")) { out += "ᵖ"; } + if (note = __guard__(result.support.match(/#(\d+)/), x => x[1])) { + nums[note] = true; + out += supernums[note]; + } + + if (argv.percentages && result.usage) { + if (out.slice(-1) !== "\u2800") { out += " "; } + out += `(${Math.round(result.usage*1)/1}%)`; + } + out += ' '; + switch (support) { + case "y": return out.green; + case "n": return out.red; + case "a": return out.yellow; + default: return out; + } +}; + +// Generate an array of version results for a browser +const makeResults = function(browser, stats) { + const results = []; + let current = {}; + for (let i = 0; i < browser.versions.length; i++) { + let version = browser.versions[i]; + if (version && (versionrange[0] <= i && i <= versionrange[1])) { + let support = stats[version]; + const usage = browser.usage_global[version] || 0; + if (browser.versions[i + 1]) { version += '+'; } + + // 'p' means no-but-polyfill-available, which we can treat as no + if (support[0] === "p") { + support = `n${support.slice(1)}`; + } + + // Only add a new version result when browser support changes + if (!current.version || (current.support !== support)) { + current = {version, support, usage: 0}; + results.push(current); + } + + current.usage += usage; + } + } + + return results; +}; + +// Display a single feature's browser support +const showFeature = function(result, opts) { + if (opts == null) { opts = {}; } + if (opts.long == null) { opts.long = !opts.short; } + if (opts.short == null) { opts.short = !opts.long; } + + let percentages = []; + if (result.usage_perc_y) { percentages.push(resultmap.y + ` ${result.usage_perc_y}%`.green); } + if (result.usage_perc_a) { percentages.push(resultmap.a + ` ${result.usage_perc_a}%`.yellow); } + percentages = percentages.join(' '); + + const status = opts.long ? ` [${data.statuses[result.status]}]` : ''; + const headerSep = opts["oneline-browser"] ? ": " : "\n"; + process.stdout.write(`${result.title.bold} ${percentages}${status}` + headerSep); + + if (opts.oneline) { return; } + + if (opts.long) { + const tags = result.categories.map(x => `#${x.replace(/\W/g,'')}`).join(' '); + console.log(wrap(`\t${result.description.trim()} ${tags}\n`)); + } + + const out = []; + // console.log "columns", process.stdout.columns + if (opts.short && !opts["oneline-browser"]) { out.push('\t'); } + + const filter = function(browser) { + if (opts.browser) { + let needle; + return (needle = browser, Array.from(opts.browser.split(',')).includes(needle)); + } else { + return Array.from(types).includes(agents[browser].type); + } + }; + + // Store which notes have been used in a result + const need_note = {}; + + for (let browser in result.stats) { + const stats = result.stats[browser]; + if (filter(browser)) { + if (!opts.short) { out.push("\t"); } + if (opts.abbrev) { + out.push(`${agents[browser].abbr} `); + } else { + out.push(`${agents[browser].browser} `); + } + + const results = makeResults(agents[browser], stats); + if (results.length === 1) { + results[0].version = null; + } + + for (let res of Array.from(results)) { out.push(`${makeResult(res, need_note)}`); } + if (!opts.short) { out.push("\n"); } + } + } + + console.log(wrap(out.join(''))); + + if (!opts.short) { + for (let num in result.notes_by_num) { + const note = result.notes_by_num[num]; + if (need_note[num]) { + console.log(wrap(`\t\t${supernums[num].yellow}${note}`)); + } + } + if (result.notes) { return console.log(wrap(`\t ${resultmap.i}${` ${result.notes.replace(/[\r\n]+/g, ' ')}`}`)); } + } +}; + + +const slowFind = function(query) { + const results = []; + for (let key in data.data) { + const {title, description, keywords, categories} = data.data[key]; + const matcher = (key + title + description + keywords + categories).toLowerCase().replace(/\W*/g, ''); + if (matcher.match(query)) { results.push(key); } + } + return results; +}; + + +(function() { + let feat, features; + if (feat = data.data[searchkey]) { + return showFeature(feat, argv); + } else if ((features = slowFind(searchkey)).length > 0) { + if (argv.short == null) { argv.short = features.length > 1; } + return (() => { + const result = []; + for (feat of Array.from(features)) { result.push(showFeature(data.data[feat], argv)); + } + return result; + })(); + } else { + return console.error(`${searchkey}: not found`); + } +})(); + +function __guard__(value, transform) { + return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined; +} \ No newline at end of file diff --git a/caniuse.js2coffee.js b/caniuse.js2coffee.js new file mode 100644 index 0000000..c733bba --- /dev/null +++ b/caniuse.js2coffee.js @@ -0,0 +1,371 @@ +var agents, argv, colors, currentVersion, data, eras, linewrap, makeResult, makeResults, open, os, osHomedir, path, resultmap, searchkey, showFeature, slowFind, supernums, types, versionrange, wrap, xwrap, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + +data = require('caniuse-db/data.json'); + +colors = require('colors'); + +linewrap = require('linewrap'); + +open = require('open'); + +path = require('path'); + +osHomedir = require('os-homedir'); + +os = require('os'); + +argv = require('yargs').option('short', { + alias: 's', + type: 'boolean', + "default": void 0, + describe: "Short output: show browsers on one line and don't display notes or description (default when displaying multiple results)" +}).option('long', { + alias: 'l', + type: 'boolean', + "default": void 0, + describe: "Long output: show more information (default when displaying a single result)" +}).option('oneline', { + alias: '1', + type: 'boolean', + "default": false, + describe: "One-line output: just global percentages, no per-browser info" +}).option('oneline-browser', { + alias: '2', + type: 'boolean', + "default": false, + describe: "One-line output with browser info, implies --abbrev and --current" +}).option('abbrev', { + alias: 'a', + type: 'boolean', + "default": false, + describe: "Abbreviate browser names" +}).option('percentages', { + alias: 'p', + type: 'boolean', + "default": false, + describe: "Include browser version usage percentages" +}).option('future', { + alias: 'f', + type: 'boolean', + "default": false, + describe: "Include future browser versions" +}).option('current', { + alias: 'c', + type: 'boolean', + "default": false, + describe: "Don't include old browser versions, equivalent to --era e0" +}).option('era', { + alias: 'e', + type: 'string', + describe: "How many versions back to go, e0 to " + (Object.keys(data.eras)[0]) +}).option('mobile', { + alias: 'm', + type: 'boolean', + "default": false, + describe: "Include mobile browsers" +}).option('desktop', { + alias: 'd', + type: 'boolean', + "default": true, + describe: "Include desktop browsers" +}).option('browser', { + alias: 'b', + type: 'string', + describe: "Show results for these browsers, comma-separated (" + (Object.keys(data.agents)) + ")" +}).option('ascii', { + alias: 'A', + type: 'boolean', + "default": false, + describe: "UTF-8 symbols replacement with ASCII description" +}).option('web', { + alias: 'w', + type: 'boolean', + "default": false, + describe: "Go to the search page on caniuse.com" +}).option('config', { + alias: 'C', + type: 'string', + "default": path.join(osHomedir(), '.caniuse.json'), + describe: "Specify a config file with default options" +}).config('config').help('help').argv; + +resultmap = { + y: "✔", + n: "✘", + a: "◒", + u: "‽", + i: "ⓘ", + w: "⚠" +}; + +supernums = "⁰¹²³⁴⁵⁶⁷⁸⁹"; + +if (os.platform() === 'win32') { + resultmap = { + y: "\u221A", + n: "\u00D7", + a: "\u0398", + u: "\u203D", + i: "\u24D8", + w: "\u26A0" + }; +} + +if (argv["ascii"]) { + resultmap = { + y: "[Yes]", + n: "[No]", + a: "[Partly]", + u: "[?!]", + i: "[Info]", + w: "[Warning]" + }; +} + +if ((Date.now() / 1000 - data.updated) > 30 * 60 * 60 * 24) { + console.warn((resultmap.w + " Caniuse data is more than 30 days out of date!\n Consider updating: npm install -g caniuse-cmd\n").yellow); +} + +if (argv.web) { + return open("http://caniuse.com/#search=" + (encodeURIComponent(argv._.join(' ')))); +} + +searchkey = argv._.join('').toLowerCase().replace(/\W*/g, ''); + +agents = data.agents; + +xwrap = linewrap(process.stdout.columns || 80, { + skipScheme: 'ansi-color', + whitespace: 'line', + tabWidth: 2, + wrapLineIndent: 0, + wrapLineIndentBase: /\S/ +}); + +wrap = function(str) { + return xwrap(str).replace(/\u2800/g, ' '); +}; + +if (argv["oneline-browser"]) { + argv.abbrev = true; + argv.short = true; + argv.current = true; +} + +types = []; + +if (argv.desktop) { + types.push('desktop'); +} + +if (argv.mobile) { + types.push('mobile'); +} + +eras = Object.keys(data.eras); + +currentVersion = eras.indexOf("e0"); + +versionrange = [0, currentVersion]; + +if (argv.future) { + versionrange[1] = Infinity; +} + +if (argv.current) { + versionrange[0] = currentVersion; +} + +if (argv.era) { + versionrange[0] = eras.indexOf(argv.era); +} + +makeResult = function(result, nums) { + var note, out, ref, support; + if (nums == null) { + nums = {}; + } + support = result.support[0]; + out = ''; + out += (resultmap[support] || support) + "\u2800"; + if (result.version) { + out += result.version; + } + if (indexOf.call(result.support, "x") >= 0) { + out += "ᵖ"; + } + if (note = (ref = result.support.match(/#(\d+)/)) != null ? ref[1] : void 0) { + nums[note] = true; + out += supernums[note]; + } + if (argv.percentages && result.usage) { + if (out.slice(-1) !== "\u2800") { + out += " "; + } + out += "(" + (Math.round(result.usage * 1) / 1) + "%)"; + } + out += ' '; + switch (support) { + case "y": + return out.green; + case "n": + return out.red; + case "a": + return out.yellow; + default: + return out; + } +}; + +makeResults = function(browser, stats) { + var current, i, j, len, ref, results, support, usage, version; + results = []; + current = {}; + ref = browser.versions; + for (i = j = 0, len = ref.length; j < len; i = ++j) { + version = ref[i]; + if (!(version && (versionrange[0] <= i && i <= versionrange[1]))) { + continue; + } + support = stats[version]; + usage = browser.usage_global[version] || 0; + if (browser.versions[i + 1]) { + version += '+'; + } + if (support[0] === "p") { + support = "n" + support.slice(1); + } + if (!current.version || current.support !== support) { + current = { + version: version, + support: support, + usage: 0 + }; + results.push(current); + } + current.usage += usage; + } + return results; +}; + +showFeature = function(result, opts) { + var browser, filter, headerSep, j, len, need_note, note, num, out, percentages, ref, ref1, res, results, stats, status, tags; + if (opts == null) { + opts = {}; + } + if (opts.long == null) { + opts.long = !opts.short; + } + if (opts.short == null) { + opts.short = !opts.long; + } + percentages = []; + if (result.usage_perc_y) { + percentages.push(resultmap.y + (" " + result.usage_perc_y + "%").green); + } + if (result.usage_perc_a) { + percentages.push(resultmap.a + (" " + result.usage_perc_a + "%").yellow); + } + percentages = percentages.join(' '); + status = opts.long ? " [" + data.statuses[result.status] + "]" : ''; + headerSep = opts["oneline-browser"] ? ": " : "\n"; + process.stdout.write((result.title.bold + " " + percentages + status) + headerSep); + if (opts.oneline) { + return; + } + if (opts.long) { + tags = result.categories.map(function(x) { + return '#' + x.replace(/\W/g, ''); + }).join(' '); + console.log(wrap('\t' + result.description.trim() + ' ' + tags + '\n')); + } + out = []; + if (opts.short && !opts["oneline-browser"]) { + out.push('\t'); + } + filter = function(browser) { + var ref; + if (opts.browser) { + return indexOf.call(opts.browser.split(','), browser) >= 0; + } else { + return ref = agents[browser].type, indexOf.call(types, ref) >= 0; + } + }; + need_note = {}; + ref = result.stats; + for (browser in ref) { + stats = ref[browser]; + if (!(filter(browser))) { + continue; + } + if (!opts.short) { + out.push("\t"); + } + if (opts.abbrev) { + out.push(agents[browser].abbr + " "); + } else { + out.push(agents[browser].browser + " "); + } + results = makeResults(agents[browser], stats); + if (results.length === 1) { + results[0].version = null; + } + for (j = 0, len = results.length; j < len; j++) { + res = results[j]; + out.push("" + (makeResult(res, need_note))); + } + if (!opts.short) { + out.push("\n"); + } + } + console.log(wrap(out.join(''))); + if (!opts.short) { + ref1 = result.notes_by_num; + for (num in ref1) { + note = ref1[num]; + if (need_note[num]) { + console.log(wrap("\t\t" + supernums[num].yellow + note)); + } + } + if (result.notes) { + return console.log(wrap("\t " + resultmap.i + (" " + (result.notes.replace(/[\r\n]+/g, ' '))))); + } + } +}; + +slowFind = function(query) { + var categories, description, key, keywords, matcher, ref, ref1, results, title; + results = []; + ref = data.data; + for (key in ref) { + ref1 = ref[key], title = ref1.title, description = ref1.description, keywords = ref1.keywords, categories = ref1.categories; + matcher = (key + title + description + keywords + categories).toLowerCase().replace(/\W*/g, ''); + if (matcher.match(query)) { + results.push(key); + } + } + return results; +}; + +(function() { + var feat, features, j, len, results1; + if (feat = data.data[searchkey]) { + return showFeature(feat, argv); + } else if ((features = slowFind(searchkey)).length > 0) { + if (argv.short == null) { + argv.short = features.length > 1; + } + results1 = []; + for (j = 0, len = features.length; j < len; j++) { + feat = features[j]; + results1.push(showFeature(data.data[feat], argv)); + } + return results1; + } else { + return console.error(searchkey + ": not found"); + } +})(); + +// --- +// generated by coffee-script 1.9.2 \ No newline at end of file From b4c4f82f954ceb49d5afb212f75302e2cde2a512 Mon Sep 17 00:00:00 2001 From: gitgrimbo Date: Wed, 19 Sep 2018 14:36:02 +0100 Subject: [PATCH 3/8] remove coffee-script file and dependency --- caniuse.coffee | 252 ------------------------------------------------- package.json | 1 - 2 files changed, 253 deletions(-) delete mode 100644 caniuse.coffee diff --git a/caniuse.coffee b/caniuse.coffee deleted file mode 100644 index d37a97f..0000000 --- a/caniuse.coffee +++ /dev/null @@ -1,252 +0,0 @@ -data = require 'caniuse-db/data.json' -colors = require 'colors' -linewrap = require 'linewrap' -open = require 'open' -path = require 'path' -osHomedir = require 'os-homedir' -os = require 'os' - -argv = require 'yargs' - .option 'short', - alias: 's' - type: 'boolean' - default: undefined - describe: "Short output: show browsers on one line and don't display notes or description (default when displaying multiple results)" - .option 'long', - alias: 'l' - type: 'boolean' - default: undefined - describe: "Long output: show more information (default when displaying a single result)" - .option 'oneline', - alias: '1' - type: 'boolean' - default: false - describe: "One-line output: just global percentages, no per-browser info" - .option 'oneline-browser', - alias: '2' - type: 'boolean' - default: false - describe: "One-line output with browser info, implies --abbrev and --current" - .option 'abbrev', - alias: 'a' - type: 'boolean' - default: false - describe: "Abbreviate browser names" - .option 'percentages', - alias: 'p' - type: 'boolean' - default: false - describe: "Include browser version usage percentages" - .option 'future', - alias: 'f' - type: 'boolean' - default: false - describe: "Include future browser versions" - .option 'current', - alias: 'c' - type: 'boolean' - default: false - describe: "Don't include old browser versions, equivalent to --era e0" - .option 'era', - alias: 'e' - type: 'string' - describe: "How many versions back to go, e0 to #{Object.keys(data.eras)[0]}" - .option 'mobile', - alias: 'm' - type: 'boolean' - default: false - describe: "Include mobile browsers" - .option 'desktop', - alias: 'd' - type: 'boolean' - default: true - describe: "Include desktop browsers" - .option 'browser', - alias: 'b' - type: 'string' - describe: "Show results for these browsers, comma-separated (#{Object.keys(data.agents)})" - .option 'ascii', - alias: 'A' - type: 'boolean' - default: false - describe: "UTF-8 symbols replacement with ASCII description" - .option 'web', - alias: 'w' - type: 'boolean' - default: false - describe: "Go to the search page on caniuse.com" - .option 'config', - alias: 'C' - type: 'string' - default: path.join(osHomedir(), '.caniuse.json') - describe: "Specify a config file with default options" - .config 'config' - .help 'help' - .argv - -resultmap = y: "✔", n: "✘", a: "◒", u: "‽", i: "ⓘ", w: "⚠" -supernums = "⁰¹²³⁴⁵⁶⁷⁸⁹" - -if (os.platform() == 'win32') - resultmap = y: "\u221A", n: "\u00D7", a: "\u0398", u: "\u203D", i: "\u24D8", w: "\u26A0" - -if argv["ascii"] - resultmap = y: "[Yes]", n: "[No]", a: "[Partly]", u: "[?!]", i: "[Info]", w: "[Warning]" - -if (Date.now()/1000 - data.updated) > 30*60*60*24 - console.warn """ - #{resultmap.w} Caniuse data is more than 30 days out of date! - Consider updating: npm install -g caniuse-cmd - - """.yellow - -if argv.web - return open "http://caniuse.com/#search=#{encodeURIComponent argv._.join ' '}" - -searchkey = argv._.join('').toLowerCase().replace(/\W*/g, '') -agents = data.agents - -xwrap = linewrap (process.stdout.columns or 80), - skipScheme: 'ansi-color' - whitespace: 'line' - tabWidth: 2 - wrapLineIndent: 0 - wrapLineIndentBase: /\S/ - -# Replace our scary braille spaces with real spaces -wrap = (str) -> xwrap(str).replace(/\u2800/g, ' ') - -if argv["oneline-browser"] - argv.abbrev = true - argv.short = true - argv.current = true - - -types = [] -types.push 'desktop' if argv.desktop -types.push 'mobile' if argv.mobile - -eras = Object.keys(data.eras) -currentVersion = eras.indexOf("e0") -versionrange = [0, currentVersion] -versionrange[1] = Infinity if argv.future -versionrange[0] = currentVersion if argv.current -versionrange[0] = eras.indexOf(argv.era) if argv.era - -# Generate the text for a single version result -# FIXME: gross output parameter -makeResult = (result, nums={}) -> - support = result.support[0] - out = '' - # \u2800 is a braille space - the only kind of space I could find that - # doesn't get split by the word wrapper - out += (resultmap[support] || support) + "\u2800" - out += result.version if result.version - out += "ᵖ" if "x" in result.support - if note = result.support.match(/#(\d+)/)?[1] - nums[note] = true - out += supernums[note] - - if argv.percentages and result.usage - out += " " unless out.slice(-1) is "\u2800" - out += "(#{Math.round(result.usage*1)/1}%)" - out += ' ' - switch support - when "y" then out.green - when "n" then out.red - when "a" then out.yellow - else out - -# Generate an array of version results for a browser -makeResults = (browser, stats) -> - results = [] - current = {} - for version, i in browser.versions when version and versionrange[0] <= i <= versionrange[1] - support = stats[version] - usage = browser.usage_global[version] || 0 - version += '+' if browser.versions[i + 1] - - # 'p' means no-but-polyfill-available, which we can treat as no - if support[0] == "p" - support = "n" + support.slice(1) - - # Only add a new version result when browser support changes - if !current.version || current.support != support - current = version: version, support: support, usage: 0 - results.push current - - current.usage += usage - - results - -# Display a single feature's browser support -showFeature = (result, opts={}) -> - opts.long ?= !opts.short - opts.short ?= !opts.long - - percentages = [] - percentages.push resultmap.y + " #{result.usage_perc_y}%".green if result.usage_perc_y - percentages.push resultmap.a + " #{result.usage_perc_a}%".yellow if result.usage_perc_a - percentages = percentages.join(' ') - - status = if opts.long then " [#{data.statuses[result.status]}]" else '' - headerSep = if opts["oneline-browser"] then ": " else "\n" - process.stdout.write "#{result.title.bold} #{percentages}#{status}" + headerSep - - return if opts.oneline - - if opts.long - tags = result.categories.map((x) -> '#'+x.replace(/\W/g,'')).join(' ') - console.log wrap '\t' + result.description.trim() + ' ' + tags + '\n' - - out = [] - # console.log "columns", process.stdout.columns - out.push '\t' if opts.short && !opts["oneline-browser"] - - filter = (browser) -> - if opts.browser - browser in opts.browser.split(',') - else - agents[browser].type in types - - # Store which notes have been used in a result - need_note = {} - - for browser, stats of result.stats when filter browser - out.push "\t" unless opts.short - if opts.abbrev - out.push "#{agents[browser].abbr} " - else - out.push "#{agents[browser].browser} " - - results = makeResults(agents[browser], stats) - if results.length == 1 - results[0].version = null - - out.push "#{makeResult res, need_note}" for res in results - out.push "\n" unless opts.short - - console.log wrap out.join('') - - unless opts.short - for num, note of result.notes_by_num when need_note[num] - console.log wrap "\t\t#{supernums[num].yellow}#{note}" - console.log wrap "\t " + resultmap.i + " #{result.notes.replace(/[\r\n]+/g, ' ')}" if result.notes - - -slowFind = (query) -> - results = [] - for key, {title, description, keywords, categories} of data.data - matcher = (key + title + description + keywords + categories).toLowerCase().replace(/\W*/g, '') - results.push key if matcher.match(query) - results - - -do -> - if feat = data.data[searchkey] - showFeature feat, argv - else if (features = slowFind searchkey).length > 0 - argv.short ?= features.length > 1 - showFeature data.data[feat], argv for feat in features - else - console.error "#{searchkey}: not found" diff --git a/package.json b/package.json index 50f8e64..d1a20b6 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "homepage": "https://github.com/sgentle/caniuse-cmd", "dependencies": { "caniuse-db": "~1.0.0", - "coffee-script": "=1.9.1", "colors": "^1.0.3", "linewrap": "^0.2.1", "open": "0.0.5", From 10c7c7b948fedd9d4cc620b03309a8d6d1139d47 Mon Sep 17 00:00:00 2001 From: gitgrimbo Date: Wed, 19 Sep 2018 10:43:01 +0100 Subject: [PATCH 4/8] formatted using js-beautify js-beautify -r --indent-size 2 INPUT-FILE --- caniuse.decaffeinate.js | 172 +++++++++++++++++++++++++++++----------- caniuse.js2coffee.js | 7 +- 2 files changed, 133 insertions(+), 46 deletions(-) diff --git a/caniuse.decaffeinate.js b/caniuse.decaffeinate.js index 93ac82b..aa417c9 100644 --- a/caniuse.decaffeinate.js +++ b/caniuse.decaffeinate.js @@ -18,7 +18,9 @@ const path = require('path'); const osHomedir = require('os-homedir'); const os = require('os'); -const { argv } = require('yargs') +const { + argv +} = require('yargs') .option('short', { alias: 's', type: 'boolean', @@ -93,27 +95,46 @@ const { argv } = require('yargs') default: path.join(osHomedir(), '.caniuse.json'), describe: "Specify a config file with default options" }).config('config') - .help('help') - ; - -let resultmap = {y: "✔", n: "✘", a: "◒", u: "‽", i: "ⓘ", w: "⚠"}; + .help('help'); + +let resultmap = { + y: "✔", + n: "✘", + a: "◒", + u: "‽", + i: "ⓘ", + w: "⚠" +}; const supernums = "⁰¹²³⁴⁵⁶⁷⁸⁹"; if (os.platform() === 'win32') { - resultmap = {y: "\u221A", n: "\u00D7", a: "\u0398", u: "\u203D", i: "\u24D8", w: "\u26A0"}; + resultmap = { + y: "\u221A", + n: "\u00D7", + a: "\u0398", + u: "\u203D", + i: "\u24D8", + w: "\u26A0" + }; } if (argv["ascii"]) { - resultmap = {y: "[Yes]", n: "[No]", a: "[Partly]", u: "[?!]", i: "[Info]", w: "[Warning]"}; + resultmap = { + y: "[Yes]", + n: "[No]", + a: "[Partly]", + u: "[?!]", + i: "[Info]", + w: "[Warning]" + }; } -if (((Date.now()/1000) - data.updated) > (30*60*60*24)) { +if (((Date.now() / 1000) - data.updated) > (30 * 60 * 60 * 24)) { console.warn(`\ ${resultmap.w} Caniuse data is more than 30 days out of date! Consider updating: npm install -g caniuse-cmd \ -`.yellow - ); +`.yellow); } if (argv.web) { @@ -121,7 +142,9 @@ if (argv.web) { } const searchkey = argv._.join('').toLowerCase().replace(/\W*/g, ''); -const { agents } = data; +const { + agents +} = data; const xwrap = linewrap((process.stdout.columns || 80), { skipScheme: 'ansi-color', @@ -129,8 +152,7 @@ const xwrap = linewrap((process.stdout.columns || 80), { tabWidth: 2, wrapLineIndent: 0, wrapLineIndentBase: /\S/ -} -); +}); // Replace our scary braille spaces with real spaces const wrap = str => xwrap(str).replace(/\u2800/g, ' '); @@ -143,43 +165,65 @@ if (argv["oneline-browser"]) { const types = []; -if (argv.desktop) { types.push('desktop'); } -if (argv.mobile) { types.push('mobile'); } +if (argv.desktop) { + types.push('desktop'); +} +if (argv.mobile) { + types.push('mobile'); +} const eras = Object.keys(data.eras); const currentVersion = eras.indexOf("e0"); const versionrange = [0, currentVersion]; -if (argv.future) { versionrange[1] = Infinity; } -if (argv.current) { versionrange[0] = currentVersion; } -if (argv.era) { versionrange[0] = eras.indexOf(argv.era); } +if (argv.future) { + versionrange[1] = Infinity; +} +if (argv.current) { + versionrange[0] = currentVersion; +} +if (argv.era) { + versionrange[0] = eras.indexOf(argv.era); +} // Generate the text for a single version result // FIXME: gross output parameter const makeResult = function(result, nums) { let note; - if (nums == null) { nums = {}; } + if (nums == null) { + nums = {}; + } const support = result.support[0]; let out = ''; // \u2800 is a braille space - the only kind of space I could find that // doesn't get split by the word wrapper out += (resultmap[support] || support) + "\u2800"; - if (result.version) { out += result.version; } - if (Array.from(result.support).includes("x")) { out += "ᵖ"; } + if (result.version) { + out += result.version; + } + if (Array.from(result.support).includes("x")) { + out += "ᵖ"; + } if (note = __guard__(result.support.match(/#(\d+)/), x => x[1])) { nums[note] = true; out += supernums[note]; } if (argv.percentages && result.usage) { - if (out.slice(-1) !== "\u2800") { out += " "; } - out += `(${Math.round(result.usage*1)/1}%)`; + if (out.slice(-1) !== "\u2800") { + out += " "; + } + out += `(${Math.round(result.usage * 1) / 1}%)`; } out += ' '; switch (support) { - case "y": return out.green; - case "n": return out.red; - case "a": return out.yellow; - default: return out; + case "y": + return out.green; + case "n": + return out.red; + case "a": + return out.yellow; + default: + return out; } }; @@ -192,7 +236,9 @@ const makeResults = function(browser, stats) { if (version && (versionrange[0] <= i && i <= versionrange[1])) { let support = stats[version]; const usage = browser.usage_global[version] || 0; - if (browser.versions[i + 1]) { version += '+'; } + if (browser.versions[i + 1]) { + version += '+'; + } // 'p' means no-but-polyfill-available, which we can treat as no if (support[0] === "p") { @@ -201,7 +247,11 @@ const makeResults = function(browser, stats) { // Only add a new version result when browser support changes if (!current.version || (current.support !== support)) { - current = {version, support, usage: 0}; + current = { + version, + support, + usage: 0 + }; results.push(current); } @@ -214,29 +264,43 @@ const makeResults = function(browser, stats) { // Display a single feature's browser support const showFeature = function(result, opts) { - if (opts == null) { opts = {}; } - if (opts.long == null) { opts.long = !opts.short; } - if (opts.short == null) { opts.short = !opts.long; } + if (opts == null) { + opts = {}; + } + if (opts.long == null) { + opts.long = !opts.short; + } + if (opts.short == null) { + opts.short = !opts.long; + } let percentages = []; - if (result.usage_perc_y) { percentages.push(resultmap.y + ` ${result.usage_perc_y}%`.green); } - if (result.usage_perc_a) { percentages.push(resultmap.a + ` ${result.usage_perc_a}%`.yellow); } + if (result.usage_perc_y) { + percentages.push(resultmap.y + ` ${result.usage_perc_y}%`.green); + } + if (result.usage_perc_a) { + percentages.push(resultmap.a + ` ${result.usage_perc_a}%`.yellow); + } percentages = percentages.join(' '); const status = opts.long ? ` [${data.statuses[result.status]}]` : ''; const headerSep = opts["oneline-browser"] ? ": " : "\n"; process.stdout.write(`${result.title.bold} ${percentages}${status}` + headerSep); - if (opts.oneline) { return; } + if (opts.oneline) { + return; + } if (opts.long) { - const tags = result.categories.map(x => `#${x.replace(/\W/g,'')}`).join(' '); + const tags = result.categories.map(x => `#${x.replace(/\W/g, '')}`).join(' '); console.log(wrap(`\t${result.description.trim()} ${tags}\n`)); } const out = []; // console.log "columns", process.stdout.columns - if (opts.short && !opts["oneline-browser"]) { out.push('\t'); } + if (opts.short && !opts["oneline-browser"]) { + out.push('\t'); + } const filter = function(browser) { if (opts.browser) { @@ -253,7 +317,9 @@ const showFeature = function(result, opts) { for (let browser in result.stats) { const stats = result.stats[browser]; if (filter(browser)) { - if (!opts.short) { out.push("\t"); } + if (!opts.short) { + out.push("\t"); + } if (opts.abbrev) { out.push(`${agents[browser].abbr} `); } else { @@ -265,8 +331,12 @@ const showFeature = function(result, opts) { results[0].version = null; } - for (let res of Array.from(results)) { out.push(`${makeResult(res, need_note)}`); } - if (!opts.short) { out.push("\n"); } + for (let res of Array.from(results)) { + out.push(`${makeResult(res, need_note)}`); + } + if (!opts.short) { + out.push("\n"); + } } } @@ -279,7 +349,9 @@ const showFeature = function(result, opts) { console.log(wrap(`\t\t${supernums[num].yellow}${note}`)); } } - if (result.notes) { return console.log(wrap(`\t ${resultmap.i}${` ${result.notes.replace(/[\r\n]+/g, ' ')}`}`)); } + if (result.notes) { + return console.log(wrap(`\t ${resultmap.i}${` ${result.notes.replace(/[\r\n]+/g, ' ')}`}`)); + } } }; @@ -287,9 +359,16 @@ const showFeature = function(result, opts) { const slowFind = function(query) { const results = []; for (let key in data.data) { - const {title, description, keywords, categories} = data.data[key]; + const { + title, + description, + keywords, + categories + } = data.data[key]; const matcher = (key + title + description + keywords + categories).toLowerCase().replace(/\W*/g, ''); - if (matcher.match(query)) { results.push(key); } + if (matcher.match(query)) { + results.push(key); + } } return results; }; @@ -300,10 +379,13 @@ const slowFind = function(query) { if (feat = data.data[searchkey]) { return showFeature(feat, argv); } else if ((features = slowFind(searchkey)).length > 0) { - if (argv.short == null) { argv.short = features.length > 1; } + if (argv.short == null) { + argv.short = features.length > 1; + } return (() => { const result = []; - for (feat of Array.from(features)) { result.push(showFeature(data.data[feat], argv)); + for (feat of Array.from(features)) { + result.push(showFeature(data.data[feat], argv)); } return result; })(); diff --git a/caniuse.js2coffee.js b/caniuse.js2coffee.js index c733bba..a6a73cc 100644 --- a/caniuse.js2coffee.js +++ b/caniuse.js2coffee.js @@ -1,5 +1,10 @@ var agents, argv, colors, currentVersion, data, eras, linewrap, makeResult, makeResults, open, os, osHomedir, path, resultmap, searchkey, showFeature, slowFind, supernums, types, versionrange, wrap, xwrap, - indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + indexOf = [].indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (i in this && this[i] === item) return i; + } + return -1; + }; data = require('caniuse-db/data.json'); From 83c91f1e7cbbba17ba64d10f1720affed1e59ba4 Mon Sep 17 00:00:00 2001 From: gitgrimbo Date: Wed, 19 Sep 2018 12:16:20 +0100 Subject: [PATCH 5/8] split caniuse into library and cli bin.js now requires caniuse-cli.js, and not the coffee-script files. The new caniuse-cli.js file is a CLI-only file that requires caniuser.decaffeinate.js caniuse.decaffeinate.js now provides two main functions: - toStreams() which will output to either default stdout and stderr, or two streams of your choice. - asString() which will return the output as a string. This separation will make it simple for other JS code to use the module to extract the output and use it in other situations, e.g. converting to HTML. --- bin.js | 3 +- caniuse-cli.js | 101 +++++++++++++++++++++++++++++++++ caniuse.decaffeinate.js | 121 ++++++++++------------------------------ package.json | 1 + 4 files changed, 134 insertions(+), 92 deletions(-) create mode 100644 caniuse-cli.js diff --git a/bin.js b/bin.js index 0f7c912..34bb6ee 100755 --- a/bin.js +++ b/bin.js @@ -1,3 +1,2 @@ #!/usr/bin/env node -require('coffee-script/register'); -require('./caniuse.coffee'); \ No newline at end of file +require('./caniuse-cli.js'); \ No newline at end of file diff --git a/caniuse-cli.js b/caniuse-cli.js new file mode 100644 index 0000000..6bad51f --- /dev/null +++ b/caniuse-cli.js @@ -0,0 +1,101 @@ +/* + * decaffeinate suggestions: + * DS101: Remove unnecessary use of Array.from + * DS102: Remove unnecessary code created because of implicit returns + * DS103: Rewrite code to no longer use __guard__ + * DS104: Avoid inline assignments + * DS204: Change includes calls to have a more natural evaluation order + * DS205: Consider reworking code to avoid use of IIFEs + * DS207: Consider shorter variations of null checks + * DS209: Avoid top-level return + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const data = require('caniuse-db/data.json'); +const path = require('path'); +const osHomedir = require('os-homedir'); +const caniuse = require('./caniuse.decaffeinate'); + +const { + argv +} = require('yargs') + .option('short', { + alias: 's', + type: 'boolean', + default: undefined, + describe: "Short output: show browsers on one line and don't display notes or description (default when displaying multiple results)" + }).option('long', { + alias: 'l', + type: 'boolean', + default: undefined, + describe: "Long output: show more information (default when displaying a single result)" + }).option('oneline', { + alias: '1', + type: 'boolean', + default: false, + describe: "One-line output: just global percentages, no per-browser info" + }).option('oneline-browser', { + alias: '2', + type: 'boolean', + default: false, + describe: "One-line output with browser info, implies --abbrev and --current" + }).option('abbrev', { + alias: 'a', + type: 'boolean', + default: false, + describe: "Abbreviate browser names" + }).option('percentages', { + alias: 'p', + type: 'boolean', + default: false, + describe: "Include browser version usage percentages" + }).option('future', { + alias: 'f', + type: 'boolean', + default: false, + describe: "Include future browser versions" + }).option('current', { + alias: 'c', + type: 'boolean', + default: false, + describe: "Don't include old browser versions, equivalent to --era e0" + }).option('era', { + alias: 'e', + type: 'string', + describe: `How many versions back to go, e0 to ${Object.keys(data.eras)[0]}` + }).option('mobile', { + alias: 'm', + type: 'boolean', + default: false, + describe: "Include mobile browsers" + }).option('desktop', { + alias: 'd', + type: 'boolean', + default: true, + describe: "Include desktop browsers" + }).option('browser', { + alias: 'b', + type: 'string', + describe: `Show results for these browsers, comma-separated (${Object.keys(data.agents)})` + }).option('ascii', { + alias: 'A', + type: 'boolean', + default: false, + describe: "UTF-8 symbols replacement with ASCII description" + }).option('web', { + alias: 'w', + type: 'boolean', + default: false, + describe: "Go to the search page on caniuse.com" + }).option('config', { + alias: 'C', + type: 'string', + default: path.join(osHomedir(), '.caniuse.json'), + describe: "Specify a config file with default options" + }).config('config') + .help('help'); + +if (argv.web) { + return open(`http://caniuse.com/#search=${encodeURIComponent(argv._.join(' '))}`); +} + +caniuse.toStreams(argv); diff --git a/caniuse.decaffeinate.js b/caniuse.decaffeinate.js index aa417c9..9083b44 100644 --- a/caniuse.decaffeinate.js +++ b/caniuse.decaffeinate.js @@ -13,89 +13,19 @@ const data = require('caniuse-db/data.json'); const colors = require('colors'); const linewrap = require('linewrap'); -const open = require('open'); -const path = require('path'); -const osHomedir = require('os-homedir'); const os = require('os'); +const { WritableStreamBuffer } = require('stream-buffers'); -const { - argv -} = require('yargs') - .option('short', { - alias: 's', - type: 'boolean', - default: undefined, - describe: "Short output: show browsers on one line and don't display notes or description (default when displaying multiple results)" - }).option('long', { - alias: 'l', - type: 'boolean', - default: undefined, - describe: "Long output: show more information (default when displaying a single result)" - }).option('oneline', { - alias: '1', - type: 'boolean', - default: false, - describe: "One-line output: just global percentages, no per-browser info" - }).option('oneline-browser', { - alias: '2', - type: 'boolean', - default: false, - describe: "One-line output with browser info, implies --abbrev and --current" - }).option('abbrev', { - alias: 'a', - type: 'boolean', - default: false, - describe: "Abbreviate browser names" - }).option('percentages', { - alias: 'p', - type: 'boolean', - default: false, - describe: "Include browser version usage percentages" - }).option('future', { - alias: 'f', - type: 'boolean', - default: false, - describe: "Include future browser versions" - }).option('current', { - alias: 'c', - type: 'boolean', - default: false, - describe: "Don't include old browser versions, equivalent to --era e0" - }).option('era', { - alias: 'e', - type: 'string', - describe: `How many versions back to go, e0 to ${Object.keys(data.eras)[0]}` - }).option('mobile', { - alias: 'm', - type: 'boolean', - default: false, - describe: "Include mobile browsers" - }).option('desktop', { - alias: 'd', - type: 'boolean', - default: true, - describe: "Include desktop browsers" - }).option('browser', { - alias: 'b', - type: 'string', - describe: `Show results for these browsers, comma-separated (${Object.keys(data.agents)})` - }).option('ascii', { - alias: 'A', - type: 'boolean', - default: false, - describe: "UTF-8 symbols replacement with ASCII description" - }).option('web', { - alias: 'w', - type: 'boolean', - default: false, - describe: "Go to the search page on caniuse.com" - }).option('config', { - alias: 'C', - type: 'string', - default: path.join(osHomedir(), '.caniuse.json'), - describe: "Specify a config file with default options" - }).config('config') - .help('help'); +function toStreams(argv, stdout, stderr) { + +stdout = stdout || process.stdout; +stderr = stderr || process.stderr; + +const console = { + log: (s) => stdout.write(s + '\n'), + warn: (s) => stderr.write(s + '\n'), + error: (s) => stderr.write(s + '\n'), +}; let resultmap = { y: "✔", @@ -137,10 +67,6 @@ ${resultmap.w} Caniuse data is more than 30 days out of date! `.yellow); } -if (argv.web) { - return open(`http://caniuse.com/#search=${encodeURIComponent(argv._.join(' '))}`); -} - const searchkey = argv._.join('').toLowerCase().replace(/\W*/g, ''); const { agents @@ -285,7 +211,7 @@ const showFeature = function(result, opts) { const status = opts.long ? ` [${data.statuses[result.status]}]` : ''; const headerSep = opts["oneline-browser"] ? ": " : "\n"; - process.stdout.write(`${result.title.bold} ${percentages}${status}` + headerSep); + stdout.write(`${result.title.bold} ${percentages}${status}` + headerSep); if (opts.oneline) { return; @@ -373,8 +299,11 @@ const slowFind = function(query) { return results; }; +function __guard__(value, transform) { + return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined; +} -(function() { +return (function() { let feat, features; if (feat = data.data[searchkey]) { return showFeature(feat, argv); @@ -394,6 +323,18 @@ const slowFind = function(query) { } })(); -function __guard__(value, transform) { - return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined; -} \ No newline at end of file +} + +function asString(argv) { + const stdout = new WritableStreamBuffer(); + const stderr = new WritableStreamBuffer(); + + toStreams(argv, stdout, stderr); + + return stdout.getContentsAsString('utf8'); +}; + +module.exports = { + asString, + toStreams, +}; diff --git a/package.json b/package.json index d1a20b6..cd7d255 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "linewrap": "^0.2.1", "open": "0.0.5", "os-homedir": "^1.0.1", + "stream-buffers": "^3.0.2", "yargs": "git+https://github.com/sgentle/yargs.git#config-booleans" }, "devDependencies": {} From e26ccbcb7b3877ad5f5fa527de3eb03db4fe37dd Mon Sep 17 00:00:00 2001 From: gitgrimbo Date: Wed, 19 Sep 2018 15:13:11 +0100 Subject: [PATCH 6/8] add index so require('caniuse-cmd') can work --- index.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 index.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..396cef8 --- /dev/null +++ b/index.js @@ -0,0 +1,8 @@ +const { toStreams, asString } = require('./caniuse.decaffeinate'); +const argsParser = require('./args-parser'); + +module.exports = { + toStreams, + asString, + argsParser, +}; From 7ca27df6081e766fa2f7bc3b6cddc261951492d4 Mon Sep 17 00:00:00 2001 From: gitgrimbo Date: Wed, 19 Sep 2018 15:28:44 +0100 Subject: [PATCH 7/8] split out args parser from cli So we can use the args parser (and more importantly, the default argument values it provides) in other code, e.g.: ```js const caniuse = require("caniuse-cmd"); const args = process.argv.slice(2); console.log(caniuse.asString(args)); ``` --- args-parser.js | 81 ++++++++++++++++++++++++++++++++++ caniuse-cli.js | 97 ++--------------------------------------- caniuse.decaffeinate.js | 19 ++++++++ 3 files changed, 104 insertions(+), 93 deletions(-) create mode 100644 args-parser.js diff --git a/args-parser.js b/args-parser.js new file mode 100644 index 0000000..1125024 --- /dev/null +++ b/args-parser.js @@ -0,0 +1,81 @@ +const data = require('caniuse-db/data.json'); +const path = require('path'); +const osHomedir = require('os-homedir'); +const yargs = require('yargs'); + +module.exports = yargs + .option('short', { + alias: 's', + type: 'boolean', + default: undefined, + describe: "Short output: show browsers on one line and don't display notes or description (default when displaying multiple results)" + }).option('long', { + alias: 'l', + type: 'boolean', + default: undefined, + describe: "Long output: show more information (default when displaying a single result)" + }).option('oneline', { + alias: '1', + type: 'boolean', + default: false, + describe: "One-line output: just global percentages, no per-browser info" + }).option('oneline-browser', { + alias: '2', + type: 'boolean', + default: false, + describe: "One-line output with browser info, implies --abbrev and --current" + }).option('abbrev', { + alias: 'a', + type: 'boolean', + default: false, + describe: "Abbreviate browser names" + }).option('percentages', { + alias: 'p', + type: 'boolean', + default: false, + describe: "Include browser version usage percentages" + }).option('future', { + alias: 'f', + type: 'boolean', + default: false, + describe: "Include future browser versions" + }).option('current', { + alias: 'c', + type: 'boolean', + default: false, + describe: "Don't include old browser versions, equivalent to --era e0" + }).option('era', { + alias: 'e', + type: 'string', + describe: `How many versions back to go, e0 to ${Object.keys(data.eras)[0]}` + }).option('mobile', { + alias: 'm', + type: 'boolean', + default: false, + describe: "Include mobile browsers" + }).option('desktop', { + alias: 'd', + type: 'boolean', + default: true, + describe: "Include desktop browsers" + }).option('browser', { + alias: 'b', + type: 'string', + describe: `Show results for these browsers, comma-separated (${Object.keys(data.agents)})` + }).option('ascii', { + alias: 'A', + type: 'boolean', + default: false, + describe: "UTF-8 symbols replacement with ASCII description" + }).option('web', { + alias: 'w', + type: 'boolean', + default: false, + describe: "Go to the search page on caniuse.com" + }).option('config', { + alias: 'C', + type: 'string', + default: path.join(osHomedir(), '.caniuse.json'), + describe: "Specify a config file with default options" + }).config('config') + .help('help'); diff --git a/caniuse-cli.js b/caniuse-cli.js index 6bad51f..ac7f496 100644 --- a/caniuse-cli.js +++ b/caniuse-cli.js @@ -1,101 +1,12 @@ -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS103: Rewrite code to no longer use __guard__ - * DS104: Avoid inline assignments - * DS204: Change includes calls to have a more natural evaluation order - * DS205: Consider reworking code to avoid use of IIFEs - * DS207: Consider shorter variations of null checks - * DS209: Avoid top-level return - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md - */ -const data = require('caniuse-db/data.json'); -const path = require('path'); -const osHomedir = require('os-homedir'); -const caniuse = require('./caniuse.decaffeinate'); +const argsParser = require('./args-parser'); +const { toStreams } = require('./caniuse.decaffeinate'); const { argv -} = require('yargs') - .option('short', { - alias: 's', - type: 'boolean', - default: undefined, - describe: "Short output: show browsers on one line and don't display notes or description (default when displaying multiple results)" - }).option('long', { - alias: 'l', - type: 'boolean', - default: undefined, - describe: "Long output: show more information (default when displaying a single result)" - }).option('oneline', { - alias: '1', - type: 'boolean', - default: false, - describe: "One-line output: just global percentages, no per-browser info" - }).option('oneline-browser', { - alias: '2', - type: 'boolean', - default: false, - describe: "One-line output with browser info, implies --abbrev and --current" - }).option('abbrev', { - alias: 'a', - type: 'boolean', - default: false, - describe: "Abbreviate browser names" - }).option('percentages', { - alias: 'p', - type: 'boolean', - default: false, - describe: "Include browser version usage percentages" - }).option('future', { - alias: 'f', - type: 'boolean', - default: false, - describe: "Include future browser versions" - }).option('current', { - alias: 'c', - type: 'boolean', - default: false, - describe: "Don't include old browser versions, equivalent to --era e0" - }).option('era', { - alias: 'e', - type: 'string', - describe: `How many versions back to go, e0 to ${Object.keys(data.eras)[0]}` - }).option('mobile', { - alias: 'm', - type: 'boolean', - default: false, - describe: "Include mobile browsers" - }).option('desktop', { - alias: 'd', - type: 'boolean', - default: true, - describe: "Include desktop browsers" - }).option('browser', { - alias: 'b', - type: 'string', - describe: `Show results for these browsers, comma-separated (${Object.keys(data.agents)})` - }).option('ascii', { - alias: 'A', - type: 'boolean', - default: false, - describe: "UTF-8 symbols replacement with ASCII description" - }).option('web', { - alias: 'w', - type: 'boolean', - default: false, - describe: "Go to the search page on caniuse.com" - }).option('config', { - alias: 'C', - type: 'string', - default: path.join(osHomedir(), '.caniuse.json'), - describe: "Specify a config file with default options" - }).config('config') - .help('help'); +} = argsParser; if (argv.web) { return open(`http://caniuse.com/#search=${encodeURIComponent(argv._.join(' '))}`); } -caniuse.toStreams(argv); +toStreams(argv); diff --git a/caniuse.decaffeinate.js b/caniuse.decaffeinate.js index 9083b44..c60466e 100644 --- a/caniuse.decaffeinate.js +++ b/caniuse.decaffeinate.js @@ -15,9 +15,26 @@ const colors = require('colors'); const linewrap = require('linewrap'); const os = require('os'); const { WritableStreamBuffer } = require('stream-buffers'); +const argsParser = require('./args-parser'); + +function prepareArgv(argv) { + // allow for asString/toStreams('Service Workers'), for example. + if (typeof argv === 'string') { + return argsParser.parse([argv]); + } + + // allow for asString/toStreams(['Service Workers', 'URL API']), for example. + if (Array.isArray(argv)) { + return argsParser.parse(argv); + } + + return argv; +} function toStreams(argv, stdout, stderr) { +argv = prepareArgv(argv); + stdout = stdout || process.stdout; stderr = stderr || process.stderr; @@ -326,6 +343,8 @@ return (function() { } function asString(argv) { + argv = prepareArgv(argv); + const stdout = new WritableStreamBuffer(); const stderr = new WritableStreamBuffer(); From 40fce54158273b74067cb41c0286c9051f446797 Mon Sep 17 00:00:00 2001 From: gitgrimbo Date: Wed, 19 Sep 2018 16:15:42 +0100 Subject: [PATCH 8/8] update deps --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index cd7d255..639c66d 100644 --- a/package.json +++ b/package.json @@ -23,11 +23,11 @@ }, "homepage": "https://github.com/sgentle/caniuse-cmd", "dependencies": { - "caniuse-db": "~1.0.0", - "colors": "^1.0.3", + "caniuse-db": "~1.0.30000885", + "colors": "^1.3.2", "linewrap": "^0.2.1", "open": "0.0.5", - "os-homedir": "^1.0.1", + "os-homedir": "^1.0.2", "stream-buffers": "^3.0.2", "yargs": "git+https://github.com/sgentle/yargs.git#config-booleans" },