From 43a25f873872a7281563d62f4f6f3ad3a3ace263 Mon Sep 17 00:00:00 2001 From: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com> Date: Tue, 3 Jan 2023 13:19:41 -0500 Subject: [PATCH] update linters & add stylelint (#3023) * update linters, add stylelint, switch from sass to scss * remove unused babel-eslint module * fix spacing in scss files * dont use npm in script calls * dont error for `:deep` selector in css --- .eslintrc.js | 32 +- .stylelintignore | 7 + .stylelintrc.json | 34 + _scripts/webpack.renderer.config.js | 8 +- _scripts/webpack.web.config.js | 8 +- lefthook.yml | 3 - package.json | 31 +- src/main/ImageCache.js | 2 +- src/main/index.js | 12 +- .../components/data-settings/data-settings.js | 12 +- .../download-settings/download-settings.sass | 2 - .../download-settings/download-settings.scss | 3 + .../download-settings/download-settings.vue | 2 +- .../ft-age-restricted/ft-age-restricted.sass | 14 - .../ft-age-restricted/ft-age-restricted.scss | 19 + .../ft-age-restricted/ft-age-restricted.vue | 2 +- .../components/ft-auto-grid/ft-auto-grid.sass | 10 - .../components/ft-auto-grid/ft-auto-grid.scss | 13 + .../components/ft-auto-grid/ft-auto-grid.vue | 2 +- .../ft-icon-button/ft-icon-button.sass | 103 -- .../ft-icon-button/ft-icon-button.scss | 127 +++ .../ft-icon-button/ft-icon-button.vue | 2 +- .../ft-list-channel/ft-list-channel.sass | 1 - .../ft-list-channel/ft-list-channel.scss | 1 + .../ft-list-channel/ft-list-channel.vue | 2 +- .../ft-list-playlist/ft-list-playlist.sass | 1 - .../ft-list-playlist/ft-list-playlist.scss | 1 + .../ft-list-playlist/ft-list-playlist.vue | 2 +- .../ft-list-video/ft-list-video.sass | 4 - .../ft-list-video/ft-list-video.scss | 5 + .../ft-list-video/ft-list-video.vue | 2 +- .../ft-settings-section.sass | 82 -- .../ft-settings-section.scss | 116 +++ .../ft-settings-section.vue | 2 +- .../ft-share-button/ft-share-button.sass | 64 -- .../ft-share-button/ft-share-button.scss | 82 ++ .../ft-share-button/ft-share-button.vue | 2 +- .../ft-sponsor-block-category.js | 2 +- .../ft-sponsor-block-category.sass | 7 - .../ft-sponsor-block-category.scss | 12 + .../ft-sponsor-block-category.vue | 2 +- .../ft-timestamp-catcher.js | 2 +- .../ft-toggle-switch/ft-toggle-switch.sass | 81 -- .../ft-toggle-switch/ft-toggle-switch.scss | 88 ++ .../ft-toggle-switch/ft-toggle-switch.vue | 2 +- .../general-settings/general-settings.sass | 8 - .../general-settings/general-settings.scss | 9 + .../general-settings/general-settings.vue | 2 +- .../player-settings/player-settings.sass | 12 - .../player-settings/player-settings.scss | 19 + .../player-settings/player-settings.vue | 2 +- .../playlist-info/playlist-info.sass | 45 - .../playlist-info/playlist-info.scss | 55 + .../playlist-info/playlist-info.vue | 2 +- .../theme-settings/theme-settings.js | 2 +- src/renderer/components/top-nav/top-nav.sass | 166 --- src/renderer/components/top-nav/top-nav.scss | 210 ++++ src/renderer/components/top-nav/top-nav.vue | 2 +- .../watch-video-description.js | 36 +- .../watch-video-info/watch-video-info.js | 2 +- .../watch-video-info/watch-video-info.sass | 97 -- .../watch-video-info/watch-video-info.scss | 119 +++ .../watch-video-info/watch-video-info.vue | 2 +- src/renderer/helpers/accessibility.js | 2 +- src/renderer/helpers/utils.js | 10 +- src/renderer/i18n/index.js | 2 +- src/renderer/sass-partials/_ft-list-item.sass | 225 ---- src/renderer/scss-partials/_ft-list-item.scss | 292 ++++++ src/renderer/store/modules/index.js | 2 +- src/renderer/store/modules/utils.js | 2 +- src/renderer/views/About/About.sass | 50 - src/renderer/views/About/About.scss | 62 ++ src/renderer/views/About/About.vue | 2 +- .../SubscribedChannels/SubscribedChannels.js | 4 +- src/renderer/views/Watch/Watch.js | 16 +- src/renderer/views/Watch/Watch.sass | 109 -- src/renderer/views/Watch/Watch.scss | 149 +++ src/renderer/views/Watch/Watch.vue | 2 +- static/geolocations/bg/countries.json | 2 - static/geolocations/uk/countries.json | 2 +- yarn.lock | 961 ++++++++++++++---- 81 files changed, 2309 insertions(+), 1386 deletions(-) create mode 100644 .stylelintignore create mode 100644 .stylelintrc.json delete mode 100644 src/renderer/components/download-settings/download-settings.sass create mode 100644 src/renderer/components/download-settings/download-settings.scss delete mode 100644 src/renderer/components/ft-age-restricted/ft-age-restricted.sass create mode 100644 src/renderer/components/ft-age-restricted/ft-age-restricted.scss delete mode 100644 src/renderer/components/ft-auto-grid/ft-auto-grid.sass create mode 100644 src/renderer/components/ft-auto-grid/ft-auto-grid.scss delete mode 100644 src/renderer/components/ft-icon-button/ft-icon-button.sass create mode 100644 src/renderer/components/ft-icon-button/ft-icon-button.scss delete mode 100644 src/renderer/components/ft-list-channel/ft-list-channel.sass create mode 100644 src/renderer/components/ft-list-channel/ft-list-channel.scss delete mode 100644 src/renderer/components/ft-list-playlist/ft-list-playlist.sass create mode 100644 src/renderer/components/ft-list-playlist/ft-list-playlist.scss delete mode 100644 src/renderer/components/ft-list-video/ft-list-video.sass create mode 100644 src/renderer/components/ft-list-video/ft-list-video.scss delete mode 100644 src/renderer/components/ft-settings-section/ft-settings-section.sass create mode 100644 src/renderer/components/ft-settings-section/ft-settings-section.scss delete mode 100644 src/renderer/components/ft-share-button/ft-share-button.sass create mode 100644 src/renderer/components/ft-share-button/ft-share-button.scss delete mode 100644 src/renderer/components/ft-sponsor-block-category/ft-sponsor-block-category.sass create mode 100644 src/renderer/components/ft-sponsor-block-category/ft-sponsor-block-category.scss delete mode 100644 src/renderer/components/ft-toggle-switch/ft-toggle-switch.sass create mode 100644 src/renderer/components/ft-toggle-switch/ft-toggle-switch.scss delete mode 100644 src/renderer/components/general-settings/general-settings.sass create mode 100644 src/renderer/components/general-settings/general-settings.scss delete mode 100644 src/renderer/components/player-settings/player-settings.sass create mode 100644 src/renderer/components/player-settings/player-settings.scss delete mode 100644 src/renderer/components/playlist-info/playlist-info.sass create mode 100644 src/renderer/components/playlist-info/playlist-info.scss delete mode 100644 src/renderer/components/top-nav/top-nav.sass create mode 100644 src/renderer/components/top-nav/top-nav.scss delete mode 100644 src/renderer/components/watch-video-info/watch-video-info.sass create mode 100644 src/renderer/components/watch-video-info/watch-video-info.scss delete mode 100644 src/renderer/sass-partials/_ft-list-item.sass create mode 100644 src/renderer/scss-partials/_ft-list-item.scss delete mode 100644 src/renderer/views/About/About.sass create mode 100644 src/renderer/views/About/About.scss delete mode 100644 src/renderer/views/Watch/Watch.sass create mode 100644 src/renderer/views/Watch/Watch.scss diff --git a/.eslintrc.js b/.eslintrc.js index e97ae69e6..510e38e06 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -11,13 +11,24 @@ module.exports = { // https://eslint.org/docs/user-guide/configuring#specifying-parser parser: 'vue-eslint-parser', - // https://vuejs.github.io/eslint-plugin-vue/user-guide/#faq + // https://eslint.vuejs.org/user-guide/#faq parserOptions: { - parser: 'babel-eslint', - ecmaVersion: 2018, + parser: '@babel/eslint-parser', + ecmaVersion: 2022, sourceType: 'module' }, + overrides: [ + { + files: ['*.json'], + parser: 'jsonc-eslint-parser', + rules: { + 'no-tabs': 'off', + 'comma-spacing': 'off' + } + } + ], + // https://eslint.org/docs/user-guide/configuring#extending-configuration-files // order matters: from least important to most important in terms of overriding // Prettier + Vue: https://medium.com/@gogl.alex/how-to-properly-set-up-eslint-with-prettier-for-vue-or-nuxt-in-vscode-e42532099a9c @@ -25,12 +36,13 @@ module.exports = { 'prettier', 'eslint:recommended', 'plugin:vue/recommended', - 'standard' + 'standard', + 'plugin:jsonc/recommended-with-json', // 'plugin:vuejs-accessibility/recommended' // uncomment once issues are fixed ], // https://eslint.org/docs/user-guide/configuring#configuring-plugins - plugins: ['vue', 'vuejs-accessibility'], + plugins: ['vue', 'vuejs-accessibility', 'n', 'unicorn'], rules: { 'space-before-function-paren': 'off', @@ -39,6 +51,7 @@ module.exports = { 'no-console': ['error', { allow: ['warn', 'error'] }], 'no-unused-vars': 'warn', 'no-undef': 'warn', + 'object-shorthand': 'off', 'vue/no-template-key': 'warn', 'vue/no-useless-template-attributes': 'off', 'vue/multi-word-component-names': 'off', @@ -47,6 +60,13 @@ module.exports = { required: { some: ['nesting', 'id'] } - }] + }], + 'n/no-callback-literal': 'warn', + 'n/no-path-concat': 'warn', + 'unicorn/better-regex': 'error', + 'unicorn/no-array-push-push': 'error', + 'unicorn/prefer-keyboard-event-key': 'error', + 'unicorn/prefer-regexp-test': 'error', + 'unicorn/prefer-string-replace-all': 'error' } } diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 000000000..18256bd0f --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,7 @@ +src/data/ +src/datastores/ +src/main/ +src/renderer/videoJS.css +dist/ +static/ +node_modules/ diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 000000000..ea45b8ebd --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,34 @@ +{ + "plugins": ["stylelint-high-performance-animation", "@double-great/stylelint-a11y"], + "extends": ["stylelint-config-standard", "stylelint-config-sass-guidelines"], + "overrides": [ + { + "files": ["**/*.scss"], + "customSyntax": "postcss-scss", + "rules": { + "max-nesting-depth": null, + "selector-max-compound-selectors": null + } + }, + { + "files": ["**/*.css"], + "rules": { + "a11y/media-prefers-reduced-motion": true, + "a11y/no-outline-none": true, + "a11y/selector-pseudo-class-focus": true, + "a11y/font-size-is-readable": true + } + } + ], + "rules": { + "selector-class-pattern": null, + "selector-id-pattern": null, + "plugin/no-low-performance-animation-properties": true, + "selector-pseudo-class-no-unknown": [ + true, + { + "ignorePseudoClasses": ["deep"] + } + ] + } +} diff --git a/_scripts/webpack.renderer.config.js b/_scripts/webpack.renderer.config.js index ecf1249ad..723661f8a 100644 --- a/_scripts/webpack.renderer.config.js +++ b/_scripts/webpack.renderer.config.js @@ -48,7 +48,7 @@ const config = { loader: 'vue-loader', }, { - test: /\.s(c|a)ss$/, + test: /\.scss$/, use: [ { loader: MiniCssExtractPlugin.loader, @@ -62,11 +62,7 @@ const config = { { loader: 'sass-loader', options: { - // eslint-disable-next-line - implementation: require('sass'), - sassOptions: { - indentedSyntax: true - } + implementation: require('sass') } }, ], diff --git a/_scripts/webpack.web.config.js b/_scripts/webpack.web.config.js index a18115e95..ac1567542 100644 --- a/_scripts/webpack.web.config.js +++ b/_scripts/webpack.web.config.js @@ -39,7 +39,7 @@ const config = { loader: 'vue-loader' }, { - test: /\.s(c|a)ss$/, + test: /\.scss$/, use: [ { loader: MiniCssExtractPlugin.loader, @@ -53,11 +53,7 @@ const config = { { loader: 'sass-loader', options: { - // eslint-disable-next-line - implementation: require('sass'), - sassOptions: { - indentedSyntax: true - } + implementation: require('sass') } }, ], diff --git a/lefthook.yml b/lefthook.yml index 7f6f4e3d6..6a09c9530 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -1,4 +1,3 @@ - # Refer for explanation to following link: # https://github.com/evilmartians/lefthook/blob/master/docs/full_guide.md pre-commit: @@ -12,8 +11,6 @@ pre-commit: skip: - rebase - - # EXAMPLE USAGE # # pre-push: diff --git a/package.json b/package.json index b427cb1aa..8184e4c69 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,15 @@ "dev": "run-s rebuild:electron dev-runner", "dev:web": "node _scripts/dev-runner.js --web", "dev-runner": "node _scripts/dev-runner.js", + "lint-all": "run-p lint lint-json lint-style", "lint-fix": "eslint --fix --ext .js,.vue ./", "lint": "eslint --ext .js,.vue ./", + "lint-json": "eslint --ext .json ./", + "lint-style": "run-p lint-style:scss lint-style:css", + "lint-style:scss": "stylelint \"**/*.scss\"", + "lint-style:css": "stylelint \"**/*.css\"", + "lint-style-fix:scss": "stylelint --fix \"**/*.scss\"", + "lint-style-fix:css": "stylelint --fix \"**/*.css\"", "pack": "run-p pack:main pack:renderer", "pack:main": "webpack --mode=production --node-env=production --config _scripts/webpack.main.config.js", "pack:renderer": "webpack --mode=production --node-env=production --config _scripts/webpack.renderer.config.js", @@ -81,23 +88,25 @@ }, "devDependencies": { "@babel/core": "^7.20.7", + "@babel/eslint-parser": "^7.19.1", "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/preset-env": "^7.20.2", - "babel-eslint": "^10.1.0", + "@double-great/stylelint-a11y": "^2.0.2", "babel-loader": "^9.1.0", "copy-webpack-plugin": "^11.0.0", "css-loader": "^6.7.3", "css-minimizer-webpack-plugin": "^4.2.2", "electron": "^22.0.0", "electron-builder": "^23.6.0", - "eslint": "^7.32.0", - "eslint-config-prettier": "^8.3.0", - "eslint-config-standard": "^16.0.3", - "eslint-plugin-import": "^2.24.2", - "eslint-plugin-node": "^11.1.0", + "eslint": "^8.31.0", + "eslint-config-prettier": "^8.6.0", + "eslint-config-standard": "^17.0.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jsonc": "^2.5.0", + "eslint-plugin-n": "^15.6.0", "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-promise": "^5.1.0", - "eslint-plugin-standard": "^5.0.0", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-unicorn": "^45.0.2", "eslint-plugin-vue": "^9.8.0", "eslint-plugin-vuejs-accessibility": "^2.0.0", "html-webpack-plugin": "^5.3.2", @@ -106,10 +115,16 @@ "lefthook": "^1.2.4", "mini-css-extract-plugin": "^2.7.2", "npm-run-all": "^4.1.5", + "postcss": "^8.4.20", + "postcss-scss": "^4.0.6", "prettier": "^2.8.1", "rimraf": "^3.0.2", "sass": "^1.57.1", "sass-loader": "^13.2.0", + "stylelint": "^14.16.1", + "stylelint-config-sass-guidelines": "^9.0.1", + "stylelint-config-standard": "^29.0.0", + "stylelint-high-performance-animation": "^1.7.0", "tree-kill": "1.2.2", "vue-devtools": "^5.1.4", "vue-eslint-parser": "^9.1.0", diff --git a/src/main/ImageCache.js b/src/main/ImageCache.js index 4a635b7d9..8228f38dc 100644 --- a/src/main/ImageCache.js +++ b/src/main/ImageCache.js @@ -51,7 +51,7 @@ export class ImageCache { * @returns a timestamp in seconds */ export function extractExpiryTimestamp(headers) { - const maxAgeRegex = /max-age=([0-9]+)/ + const maxAgeRegex = /max-age=(\d+)/ const cacheControl = headers['cache-control'] if (cacheControl && maxAgeRegex.test(cacheControl)) { diff --git a/src/main/index.js b/src/main/index.js index c6ca1a703..b911fef6f 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -283,7 +283,7 @@ function runApp() { session.defaultSession.webRequest.onBeforeSendHeaders(innertubeRequestFilter, ({ requestHeaders }, callback) => { requestHeaders.referer = 'https://www.youtube.com' - // eslint-disable-next-line node/no-callback-literal + // eslint-disable-next-line n/no-callback-literal callback({ requestHeaders }) }) @@ -298,7 +298,7 @@ function runApp() { if (imageCache.has(url)) { const cached = imageCache.get(url) - // eslint-disable-next-line node/no-callback-literal + // eslint-disable-next-line n/no-callback-literal callback({ mimeType: cached.mimeType, data: cached.data @@ -336,7 +336,7 @@ function runApp() { imageCache.add(url, mimeType, data, expiryTimestamp) - // eslint-disable-next-line node/no-callback-literal + // eslint-disable-next-line n/no-callback-literal callback({ mimeType, data: data @@ -364,7 +364,7 @@ function runApp() { return value }) - // eslint-disable-next-line node/no-callback-literal + // eslint-disable-next-line n/no-callback-literal callback({ statusCode: response.statusCode ?? 400, mimeType: 'application/json', @@ -385,12 +385,12 @@ function runApp() { // the requests made by the imagecache:// handler to fetch the image, // are allowed through, as their resourceType is 'other' if (details.resourceType === 'image') { - // eslint-disable-next-line node/no-callback-literal + // eslint-disable-next-line n/no-callback-literal callback({ redirectURL: `imagecache://${encodeURIComponent(details.url)}` }) } else { - // eslint-disable-next-line node/no-callback-literal + // eslint-disable-next-line n/no-callback-literal callback({}) } }) diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js index ceac3eea4..14b7ad982 100644 --- a/src/renderer/components/data-settings/data-settings.js +++ b/src/renderer/components/data-settings/data-settings.js @@ -228,7 +228,7 @@ export default Vue.extend({ let count = 0 const ytsubs = youtubeSubscriptions.slice(1).map(yt => { - const splitCSVRegex = /(?:,|\n|^)("(?:(?:"")*[^"]*)*"|[^",\n]*|(?:\n|$))/g + const splitCSVRegex = /(?:,|\n|^)("(?:(?:"")*[^"]*)*"|[^\n",]*|(?:\n|$))/g return [...yt.matchAll(splitCSVRegex)].map(s => { let newVal = s[1] if (newVal.startsWith('"')) { @@ -623,11 +623,11 @@ export default Vue.extend({ this.profileList[0].subscriptions.forEach((channel) => { const escapedName = channel.name - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, ''') + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll('\'', ''') const channelOpmlString = `` opmlData += channelOpmlString diff --git a/src/renderer/components/download-settings/download-settings.sass b/src/renderer/components/download-settings/download-settings.sass deleted file mode 100644 index 5d475ff88..000000000 --- a/src/renderer/components/download-settings/download-settings.sass +++ /dev/null @@ -1,2 +0,0 @@ -.folderDisplay - width: 50vh diff --git a/src/renderer/components/download-settings/download-settings.scss b/src/renderer/components/download-settings/download-settings.scss new file mode 100644 index 000000000..0c5ccdad0 --- /dev/null +++ b/src/renderer/components/download-settings/download-settings.scss @@ -0,0 +1,3 @@ +.folderDisplay { + width: 50vh; +} diff --git a/src/renderer/components/download-settings/download-settings.vue b/src/renderer/components/download-settings/download-settings.vue index 1620a2134..b4cd9dc11 100644 --- a/src/renderer/components/download-settings/download-settings.vue +++ b/src/renderer/components/download-settings/download-settings.vue @@ -44,4 +44,4 @@