diff --git a/.browserslistrc b/.browserslistrc index 7c8f0e2..de55567 100644 --- a/.browserslistrc +++ b/.browserslistrc @@ -1,2 +1 @@ -> 5% -IE 11 \ No newline at end of file +> 1% diff --git a/.eslintrc b/.eslintrc.json similarity index 64% rename from .eslintrc rename to .eslintrc.json index 861656d..5055cc4 100644 --- a/.eslintrc +++ b/.eslintrc.json @@ -2,13 +2,18 @@ "parserOptions": { "ecmaVersion": 2020 }, - "extends": ["airbnb-base", "plugin:prettier/recommended"], + "extends": [ + "airbnb-base", + "plugin:prettier/recommended", + "plugin:compat/recommended" + ], "plugins": ["prettier"], "env": { "es6": true, "browser": true }, "rules": { + "import/prefer-default-export": "off", "import/no-extraneous-dependencies": [ "error", { @@ -41,7 +46,8 @@ "mocha": true }, "rules": { - "no-restricted-syntax": "off" + "no-restricted-syntax": "off", + "compat/compat": "off" } }, { @@ -51,5 +57,18 @@ "cypress/globals": true } } - ] + ], + "settings": { + "polyfills": [ + "Array.from", + "Array.prototype.find", + "Array.prototype.includes", + "Symbol", + "Symbol.iterator", + "Object.assign", + "CustomEvent", + "Element.prototype.classList", + "Element.prototype.closest" + ] + } } diff --git a/.github/actions-scripts/polyfills-sync.js b/.github/actions-scripts/polyfills-sync.js new file mode 100644 index 0000000..824a930 --- /dev/null +++ b/.github/actions-scripts/polyfills-sync.js @@ -0,0 +1,14 @@ +const { readFileSync } = require('fs'); +const path = require('path'); +const assert = require('assert'); + +const readme = readFileSync(path.resolve(__dirname, '../../README.md'), 'utf8'); + +const polyfillsFromDocs = /^```polyfills\s*\n([^`]+)\n^```/m + .exec(readme)[1] + .split('\n') + .map(v => v.trim()) + .sort(); +// @ts-ignore +const polyfillsFromSettings = require('../../.eslintrc.json').settings.polyfills.sort(); +assert.deepStrictEqual(polyfillsFromDocs, polyfillsFromSettings); diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 3fe5e90..0588e96 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -31,3 +31,8 @@ jobs: if [[ -z $(sed -e 's/[[:space:]]*$//' <<<${CHANGED_JS}) ]]; then CHANGED_JS="src/scripts"; fi echo $CHANGED_JS node node_modules/eslint/bin/eslint.js $CHANGED_JS + + - name: Lint JS bundle + run: | + npm run js:build + npx eslint --no-ignore ./public/assets/scripts/*.js diff --git a/.github/workflows/polyfills-sync.yml b/.github/workflows/polyfills-sync.yml new file mode 100644 index 0000000..819e4a6 --- /dev/null +++ b/.github/workflows/polyfills-sync.yml @@ -0,0 +1,23 @@ +name: Polyfills documentation + +on: + pull_request: + paths: + - 'README.md' + - '.browserslistrc' + - '.eslintrc.json' + +jobs: + sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - uses: actions/setup-node@v1 + with: + node-version: 12 + + - name: Check Polyfills documentation and settings sync + run: node .github/actions-scripts/polyfills-sync.js diff --git a/README.md b/README.md index cb87c7c..a414ed1 100644 --- a/README.md +++ b/README.md @@ -1029,29 +1029,30 @@ example.setChoiceByValue('Two'); // Choice with value of 'Two' has now been sele ## Browser compatibility -Choices is compiled using [Babel](https://babeljs.io/) to enable support for [ES5 browsers](http://caniuse.com/#feat=es5). If you need to support a browser that does not support one of the features listed below, I suggest including a polyfill from the very good [polyfill.io](https://cdn.polyfill.io/v2/docs/): +Choices is compiled using [Babel](https://babeljs.io/) targeting browsers [with more that 1% of global usage](https://github.com/jshjohnson/Choices/blob/master/.browserslistrc) and expecting that features [listed below](https://github.com/jshjohnson/Choices/blob/master/.eslintrc.json#L62) are available or polyfilled in browser. +You may see exact list of target browsers by running `npx browserslist` withing this repository folder. +If you need to support a browser that does not have one of the features listed below, +I suggest including a polyfill from the very good [polyfill.io](https://polyfill.io/v3/): **Polyfill example used for the demo:** ```html - + ``` **Features used in Choices:** -- Array.prototype.forEach -- Array.prototype.map -- Array.prototype.find -- Array.prototype.some -- Array.prototype.includes -- Array.from -- Array.prototype.reduce -- Array.prototype.indexOf -- Object.assign -- Element.prototype.classList -- Element.prototype.closest -- window.requestAnimationFrame -- CustomEvent +```polyfills +Array.from +Array.prototype.find +Array.prototype.includes +Symbol +Symbol.iterator +Object.assign +CustomEvent +Element.prototype.classList +Element.prototype.closest +``` ## Development diff --git a/package-lock.json b/package-lock.json index 64f0e10..9fe0740 100644 --- a/package-lock.json +++ b/package-lock.json @@ -753,6 +753,15 @@ "source-map-support": "^0.5.9" } }, + "@babel/runtime": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz", + "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, "@babel/template": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", @@ -1539,6 +1548,12 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "ast-metadata-inferer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.1.1.tgz", + "integrity": "sha512-hc9w8Qrgg9Lf9iFcZVhNjUnhrd2BBpTlyCnegPVvCe6O0yMrF57a6Cmh7k+xUsfUOMh9wajOL5AsGOBNEyTCcw==", + "dev": true + }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -2214,6 +2229,12 @@ } } }, + "caniuse-db": { + "version": "1.0.30001004", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001004.tgz", + "integrity": "sha512-VBTptWLoxsIhIGFZOEvtHhdRyhh+6JARUnVy2debGRNmrKfunVAa9cRuAvOnrQk4z/SDiNm5S2d6h32eIHZMoA==", + "dev": true + }, "caniuse-lite": { "version": "1.0.30001002", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001002.tgz", @@ -3882,6 +3903,29 @@ } } }, + "eslint-plugin-compat": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.3.0.tgz", + "integrity": "sha512-QCgYy3pZ+zH10dkBJus1xER0359h1UhJjufhQRqp9Owm6BEoLZeSqxf2zINwL1OGao9Yc96xPYIW3nQj5HUryg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.4.5", + "ast-metadata-inferer": "^0.1.1", + "browserslist": "^4.6.3", + "caniuse-db": "^1.0.30000977", + "lodash.memoize": "4.1.2", + "mdn-browser-compat-data": "^0.0.84", + "semver": "^6.1.2" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "eslint-plugin-cypress": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.7.0.tgz", @@ -7971,6 +8015,12 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -8099,6 +8149,15 @@ "safe-buffer": "^5.1.2" } }, + "mdn-browser-compat-data": { + "version": "0.0.84", + "resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-0.0.84.tgz", + "integrity": "sha512-fAznuGNaQMQiWLVf+gyp33FaABTglYWqMT7JqvH+4RZn2UQPD12gbMqxwP9m0lj8AAbNpu5/kD6n4Ox1SOffpw==", + "dev": true, + "requires": { + "extend": "3.0.2" + } + }, "mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -11391,6 +11450,12 @@ "regenerate": "^1.4.0" } }, + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "dev": true + }, "regenerator-transform": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", diff --git a/package.json b/package.json index 4cbf8e0..34a475d 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "eslint-config-airbnb-base": "^14.0.0", "eslint-config-prettier": "^6.4.0", "eslint-loader": "^3.0.2", + "eslint-plugin-compat": "3.3.0", "eslint-plugin-cypress": "^2.7.0", "eslint-plugin-import": "^2.18.2", "eslint-plugin-prettier": "^3.1.1", diff --git a/public/assets/scripts/.eslintrc.js b/public/assets/scripts/.eslintrc.js new file mode 100644 index 0000000..00f2747 --- /dev/null +++ b/public/assets/scripts/.eslintrc.js @@ -0,0 +1,24 @@ + +// get polyfill settings from top level config +// @ts-ignore +const { settings } = require('../../../.eslintrc.json'); + +// Adding non-polyfilable Symbol-related functions as they are most probably +// behind the flag + +settings.polyfills.push('Symbol.toStringTag', 'Symbol.for', 'Object.getOwnPropertySymbols', 'Object.getOwnPropertyDescriptors') + +module.exports = /** @type {import('eslint').Linter.Config} */({ + root: true, + extends: [ + "plugin:compat/recommended" + ], + parserOptions: { + // ensure that it's compatible with ES5 browsers, so, no `const`, etc + ecmaVersion: 5 + }, + env: { + browser: true + }, + settings +}) diff --git a/public/index.html b/public/index.html index 4a30614..e7a3581 100644 --- a/public/index.html +++ b/public/index.html @@ -47,7 +47,7 @@ - + diff --git a/src/scripts/actions/general.js b/src/scripts/actions/general.js index e41217c..06e59a3 100644 --- a/src/scripts/actions/general.js +++ b/src/scripts/actions/general.js @@ -1,5 +1,3 @@ -/* eslint-disable import/prefer-default-export */ - export const setIsLoading = isLoading => ({ type: 'SET_IS_LOADING', isLoading, diff --git a/src/scripts/actions/groups.js b/src/scripts/actions/groups.js index 8862b7f..2b29679 100644 --- a/src/scripts/actions/groups.js +++ b/src/scripts/actions/groups.js @@ -1,6 +1,5 @@ import { ACTION_TYPES } from '../constants'; -/* eslint-disable import/prefer-default-export */ export const addGroup = (value, id, active, disabled) => ({ type: ACTION_TYPES.ADD_GROUP, value,