Skip to content

Commit

Permalink
Release 1.0.0 (#35)
Browse files Browse the repository at this point in the history
* Fixed bugs related to package.json resolution

* Removed unnecessary deps

* 1.0.0-1

* Improved clarity of readme examples

* Moved browserslist from devDeps to deps

* 1.0.0-2

* Updated video demo to reflect config changes

* Updated yarn.lock

* 1.0.0
  • Loading branch information
amilajack authored Jan 9, 2017
1 parent 400b839 commit aa2c4b4
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 107 deletions.
35 changes: 19 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ eslint-plugin-compat
- [x] Allow configuration of target browser/s
- [x] Use [caniuse](http://caniuse.com) and [@kangax's compat table](http://kangax.github.io/compat-table/es6/) for determining coverage
- [x] Enable config using `.eslintrc`
- [ ] Babel integration (using `babel-preset-env` config)
- [x] `browserslist` integration (using `package.json`)

See the [Road Map](https://github.com/amilajack/eslint-plugin-compat/wiki) for more details

Expand Down Expand Up @@ -48,29 +48,32 @@ If you use **typescript**, see [typescript-eslint-parser](https://github.com/esl
and Safari 8 😢
```

**Targeting Browsers**
## Targeting Browsers
`eslint-plugin-compat` uses the browserslist configuration in `package.json`

See [ai/browserslist](https://github.com/ai/browserslist) for configuration. Here's some examples:

```js
// .eslintrc
// Simple configuration (package.json)
{
// ...
"browserslist": ["last 1 versions", "not ie <= 8"],
}
```

```js
// Use development and production configurations (package.json)
{
// ...
settings: {
targets: ['chrome >= 50', 'firefox', 'edge', 'safari >= 9'], // Determine target env's
polyfills: ['simd', 'fetch'], // Indicate features to be ignored
coverage: false, // Show the global coverage of the feature
compiler: 'babel' // Warn against usage of API's unsupported by compiler
"browserslist": {
"development": ["last 2 versions"],
"production": ["last 4 versions"]
}
}
```

## Adding Polyfills
[See wiki](https://github.com/amilajack/eslint-plugin-compat/wiki/Adding-polyfills)

**Explicit Error Messages**
```
91: const some = () => true
^^^^^^^^^^ Arrow Functions are not supported by your babel preset
(using .babelrc)
```
[See wiki polyfills section](https://github.com/amilajack/eslint-plugin-compat/wiki/Adding-polyfills)

## Inspiration
Toolchains for native platforms, like iOS and Android, have had API linting from the start. It's about time that the web had similar tooling.
Expand Down
Binary file modified eslint-plugin-compat-demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified img/eslint-plugin-compat-demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-plugin-compat",
"version": "1.0.0-0",
"version": "1.0.0",
"description": "Lint browser compatibility of API used",
"main": "lib/index.js",
"repository": {
Expand All @@ -27,7 +27,7 @@
],
"homepage": "https://github.com/amilajack/eslint-plugin-compat#readme",
"scripts": {
"build": "cross-env NODE_ENV=production babel src --out-dir lib && cp -r src/providers/caniuse lib/providers/caniuse",
"build": "cross-env NODE_ENV=production rm -rf lib && babel src --out-dir lib && cp -r src/providers/caniuse lib/providers/caniuse",
"lint": "eslint --cache --ignore-path .gitignore --format=node_modules/eslint-formatter-pretty .",
"clone-caniuse": "wget https://raw.githubusercontent.com/Fyrd/caniuse/master/fulldata-json/data-2.0.json && mkdir -p src/providers/caniuse/fulldata-json && mv data-2.0.json src/providers/caniuse/fulldata-json/data-2.0.json",
"spec": "jest",
Expand All @@ -51,29 +51,29 @@
"babel-preset-es2015": "^6.18.0",
"babel-preset-stage-0": "^6.16.0",
"babel-register": "^6.18.0",
"browserslist": "^1.5.2",
"cross-env": "^3.1.4",
"eslint": "^3.12.2",
"eslint-config-airbnb": "^13.0.0",
"eslint": "^3.13.0",
"eslint-config-airbnb": "^14.0.0",
"eslint-formatter-pretty": "^1.1.0",
"eslint-plugin-flowtype": "^2.29.2",
"eslint-plugin-flowtype-errors": "^2.0.3",
"eslint-plugin-fp": "^2.3.0",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^2.0.2",
"eslint-plugin-jsx-a11y": "^3.0.2",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-react": "^6.8.0",
"eslint-plugin-react": "^6.9.0",
"flow-bin": "^0.37.4",
"flow-typed": "latest",
"jest-cli": "^18.1.0",
"tcomb": "^3.2.16"
},
"dependencies": {
"babel-runtime": "^6.20.0",
"browserslist": "^1.5.2",
"requireindex": "^1.1.0"
},
"peerDependencies": {
"eslint": "^3.12.2"
"eslint": "^3.0.0"
},
"engines": {
"node": ">=4.x",
Expand Down
25 changes: 14 additions & 11 deletions src/Versioning.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import type { BrowserListConfig } from './rules/compat';

type TargetListItem = {
target: string,
version: number | string | 'all'
parsedVersion: number,
version: string | 'all'
};

/**
* Determine the targets based on the browserslist config object
*/
export default function DetermineTargetsFromConfig(config: BrowserListConfig): Array<string> {
export default function DetermineTargetsFromConfig(config?: BrowserListConfig): Array<string> {
if (Array.isArray(config)) {
return browserslist(config);
}
Expand All @@ -23,7 +24,7 @@ export default function DetermineTargetsFromConfig(config: BrowserListConfig): A
]);
}

return browserslist(['last 2 versions']);
return browserslist();
}

/**
Expand All @@ -32,15 +33,17 @@ export default function DetermineTargetsFromConfig(config: BrowserListConfig): A
*/
export function Versioning(targetslist: Array<string>): Array<TargetListItem> {
return targetslist
// Sort the targets by target name and then version number in ascending order
.map((e: string): TargetListItem => {
const [target, version] = e.split(' ');
return {
target,
version: version === 'all'
? 'all'
: version.includes('-')
? parseFloat(version.split('-')[0])
: parseFloat(version, 10)
version,
parsedVersion: version === 'all'
? 0
: version.includes('-')
? parseFloat(version.split('-')[0])
: parseFloat(version, 10)
};
})
// Sort the targets by target name and then version number in ascending order
Expand All @@ -49,11 +52,11 @@ export function Versioning(targetslist: Array<string>): Array<TargetListItem> {
// If any version === 'all', return 0. The only version of op_mini is 'all'
// Otherwise, compare the versions
return (
typeof b.version === 'string' ||
typeof a.version === 'string'
typeof b.parsedVersion === 'string' ||
typeof a.parsedVersion === 'string'
)
? 0
: b.version - a.version;
: b.parsedVersion - a.parsedVersion;
}
return b.target > a.target ? 1 : -1;
})
Expand Down
2 changes: 1 addition & 1 deletion src/providers/CanIUseProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export function getUnsupportedTargets(node: Node, targets: Targets): Array<strin

return targets
.filter(
(target: Target): bool => stats[target.target][`${target.version}`].includes('n')
(target: Target): bool => stats[target.target][target.version].includes('n')
)
.map(formatTargetNames);
}
Expand Down
24 changes: 5 additions & 19 deletions src/rules/compat.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// @flow
import path from 'path';
import Lint, { generateErrorName } from '../Lint';
import DetermineTargetsFromConfig, { Versioning } from '../Versioning';
import type { ESLintNode, Node } from '../LintTypes'; // eslint-disable-line
Expand All @@ -12,9 +11,10 @@ type ESLint = {
type Context = {
node: ESLintNode,
settings: {
targets: Array<string>,
browsers: Array<string>,
polyfills: Array<string>
},
getFilename: () => string,
report: () => void
};

Expand All @@ -38,26 +38,12 @@ export default {
schema: []
},
create(context: Context): ESLint {
// FIXME: lint() creates a new Set on every invocation. Fix this by removing
// creating a single set and passing a refrence lint() a reference
// to it
//
// FIXME: Another performance enhancement includes collecting all the rules
// into a single list. As of now, every call to lint() must find
// all the corresponding AST node rules.

// Get the path to user's package.json
const packageJSON = require(path.join(__dirname, '../../package.json')) || {}; // eslint-disable-line

// Attempt to set the config
// Determine lowest targets from browserslist config, which reads user's
// package.json config section. Use config from eslintrc for testing purposes
const browserslistConfig: BrowserListConfig =
packageJSON.browsers ||
packageJSON.targets ||
context.settings.browsers ||
context.settings.targets ||
['last 2 versions'];
context.settings.targets;

// Determine lowest targets from browserslist config
const browserslistTargets = Versioning(DetermineTargetsFromConfig(browserslistConfig));

function lint(node: ESLintNode) {
Expand Down
69 changes: 36 additions & 33 deletions test/Versioning.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ describe('Versioning', () => {
const result = Versioning(config);

expect(result).toEqual([
{ target: 'samsung', version: 4 },
{ target: 'safari', version: 8 },
{ target: 'opera', version: 39 },
{ target: 'op_mini', version: 'all' },
{ target: 'ios_saf', version: 8.1 },
{ target: 'ie_mob', version: 10 },
{ target: 'ie', version: 9 },
{ target: 'firefox', version: 45 },
{ target: 'edge', version: 12 },
{ target: 'chrome', version: 49 },
{ target: 'android', version: 4.4 },
{ target: 'and_uc', version: 11 },
{ target: 'and_chr', version: 55 }
{ target: 'samsung', version: '4', parsedVersion: 4 },
{ target: 'safari', version: '8', parsedVersion: 8 },
{ target: 'opera', version: '39', parsedVersion: 39 },
{ target: 'op_mini', version: 'all', parsedVersion: 0 },
{ target: 'ios_saf', version: '8.1-8.4', parsedVersion: 8.1 },
{ target: 'ie_mob', version: '10', parsedVersion: 10 },
{ target: 'ie', version: '9', parsedVersion: 9 },
{ target: 'firefox', version: '45', parsedVersion: 45 },
{ target: 'edge', version: '12', parsedVersion: 12 },
{ target: 'chrome', version: '49', parsedVersion: 49 },
{ target: 'android', version: '4.4', parsedVersion: 4.4 },
{ target: 'and_uc', version: '11', parsedVersion: 11 },
{ target: 'and_chr', version: '55', parsedVersion: 55 }
]);
});

Expand All @@ -31,19 +31,19 @@ describe('Versioning', () => {
const result = Versioning(config);

expect(result).toEqual([
{ target: 'samsung', version: 4 },
{ target: 'safari', version: 8 },
{ target: 'opera', version: 39 },
{ target: 'op_mini', version: 'all' },
{ target: 'ios_saf', version: 8.1 },
{ target: 'ie_mob', version: 10 },
{ target: 'ie', version: 9 },
{ target: 'firefox', version: 45 },
{ target: 'edge', version: 12 },
{ target: 'chrome', version: 46 },
{ target: 'android', version: 4.4 },
{ target: 'and_uc', version: 11 },
{ target: 'and_chr', version: 55 }
{ target: 'samsung', version: '4', parsedVersion: 4 },
{ target: 'safari', version: '8', parsedVersion: 8 },
{ target: 'opera', version: '39', parsedVersion: 39 },
{ target: 'op_mini', version: 'all', parsedVersion: 0 },
{ target: 'ios_saf', version: '8.1-8.4', parsedVersion: 8.1 },
{ target: 'ie_mob', version: '10', parsedVersion: 10 },
{ target: 'ie', version: '9', parsedVersion: 9 },
{ target: 'firefox', version: '45', parsedVersion: 45 },
{ target: 'edge', version: '12', parsedVersion: 12 },
{ target: 'chrome', version: '46', parsedVersion: 46 },
{ target: 'android', version: '4.4', parsedVersion: 4.4 },
{ target: 'and_uc', version: '11', parsedVersion: 11 },
{ target: 'and_chr', version: '55', parsedVersion: 55 }
]);
});

Expand All @@ -52,10 +52,10 @@ describe('Versioning', () => {
const result = Versioning(config);

expect(result).toEqual([
{ target: 'safari', version: 9 },
{ target: 'ie', version: 9 },
{ target: 'firefox', version: 20 },
{ target: 'chrome', version: 32 }
{ target: 'safari', version: '9', parsedVersion: 9 },
{ target: 'ie', version: '9', parsedVersion: 9 },
{ target: 'firefox', version: '20', parsedVersion: 20 },
{ target: 'chrome', version: '32', parsedVersion: 32 }
]);
});

Expand All @@ -71,15 +71,18 @@ describe('Versioning', () => {
expect(Versioning(versions)).toEqual([
{
target: 'node',
version: 7
version: '7',
parsedVersion: 7
},
{
target: 'firefox',
version: 50.5
version: '50.5',
parsedVersion: 50.5
},
{
target: 'chrome',
version: 20
version: '20',
parsedVersion: 20
}
]);
});
Expand Down
4 changes: 4 additions & 0 deletions test/e2e.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,23 @@ ruleTester.run('compat', rule, {
// },
{
code: 'new ServiceWorker()',
settings: { browsers: ['last 2 versions'] },
errors: [{
message: 'ServiceWorker is not supported in Safari 9.1, iOS Safari 9.3, IE Mobile 10, IE 10, Edge 13',
type: 'NewExpression'
}]
},
{
code: 'new IntersectionObserver(() => {}, {});',
settings: { browsers: ['last 2 versions'] },
errors: [{
message: 'IntersectionObserver is not supported in Safari 9.1, iOS Safari 9.3, IE Mobile 10, IE 10, Firefox 49, Edge 13',
type: 'NewExpression'
}]
},
{
code: 'WebAssembly.compile()',
settings: { browsers: ['last 2 versions'] },
errors: [{
message: 'WebAssembly is not supported in Safari 9.1, Opera 41, iOS Safari 9.3, IE Mobile 10, IE 10, Firefox 49, Edge 13, Chrome 54',
type: 'MemberExpression'
Expand All @@ -86,6 +89,7 @@ ruleTester.run('compat', rule, {
},
{
code: 'navigator.serviceWorker',
settings: { browsers: ['last 2 versions'] },
errors: [{
message: 'navigator.serviceWorker() is not supported in Safari 9.1, iOS Safari 9.3, IE Mobile 10, IE 10, Edge 13',
type: 'MemberExpression'
Expand Down
Loading

0 comments on commit aa2c4b4

Please sign in to comment.