diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..34af3774f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +build/*.js +config/*.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..361cff5f2 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,27 @@ +module.exports = { + root: true, + parserOptions: { + parser: '@babel/eslint-parser', + sourceType: 'module' + }, + // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style + extends: [ + 'standard', + 'plugin:vue/recommended' + ], + // required to lint *.vue files + plugins: [ + 'vue' + ], + // add your custom rules here + rules: { + // allow paren-less arrow functions + 'arrow-parens': 0, + // allow async-await + 'generator-star-spacing': 0, + // allow debugger during development + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, + 'vue/require-prop-types': 0, + 'vue/multi-word-component-names': 0 + } +} diff --git a/build/utils.js b/build/utils.js index 02fa2f724..c094c3c87 100644 --- a/build/utils.js +++ b/build/utils.js @@ -34,18 +34,26 @@ exports.cssLoaders = function (options) { use: generateLoaders(['css-loader', 'postcss-loader', 'less-loader']), }, { - test: /\.scss$/, + test: /\.sass$/, use: generateLoaders([ 'css-loader', 'postcss-loader', { loader: 'sass-loader', options: { - api: 'modern' + indentedSyntax: true } } ]) - } + }, + { + test: /\.scss$/, + use: generateLoaders(['css-loader', 'postcss-loader', 'sass-loader']) + }, + { + test: /\.styl(us)?$/, + use: generateLoaders(['css-loader', 'postcss-loader', 'stylus-loader']), + }, ] } diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js index 72b4ac0a6..7e69352a6 100644 --- a/build/webpack.base.conf.js +++ b/build/webpack.base.conf.js @@ -108,9 +108,8 @@ module.exports = { filename: 'sw-pleroma.js' }), new ESLintPlugin({ - formatter: require('eslint-formatter-friendly'), - overrideConfigFile: path.resolve(__dirname, '..', 'eslint.config.mjs'), - configType: 'flat' + extensions: ['js', 'vue'], + formatter: require('eslint-formatter-friendly') }), new StylelintPlugin({}), new VueLoaderPlugin(), diff --git a/eslint.config.mjs b/eslint.config.mjs deleted file mode 100644 index c103904aa..000000000 --- a/eslint.config.mjs +++ /dev/null @@ -1,37 +0,0 @@ -import vue from "eslint-plugin-vue"; -import js from "@eslint/js"; -import globals from "globals"; - - -export default [ - ...vue.configs['flat/recommended'], - js.configs.recommended, - { - files: ["**/*.js", "**/*.mjs", "**/*.vue"], - ignores: ["build/*.js", "config/*.js"], - - languageOptions: { - ecmaVersion: 2024, - sourceType: "module", - - parserOptions: { - parser: "@babel/eslint-parser", - }, - globals: { - ...globals.browser, - ...globals.mocha, - ...globals.chai, - ...globals.commonjs, - ...globals.serviceworker - } - }, - - rules: { - 'arrow-parens': 0, - 'generator-star-spacing': 0, - 'no-debugger': 0, - 'vue/require-prop-types': 0, - 'vue/multi-word-component-names': 0, - } - } -] diff --git a/package.json b/package.json index 7b33218ac..8cb74ce40 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "e2e": "node test/e2e/runner.js", "test": "yarn run unit && yarn run e2e", "stylelint": "yarn exec stylelint '**/*.scss' '**/*.vue'", - "lint": "eslint src test/unit/specs test/e2e/specs", - "lint-fix": "eslint --fix src test/unit/specs test/e2e/specs" + "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs", + "lint-fix": "eslint --fix --ext .js,.vue src test/unit/specs test/e2e/specs" }, "dependencies": { "@babel/runtime": "7.26.7", @@ -32,10 +32,10 @@ "click-outside-vue3": "4.0.1", "cropperjs": "1.6.2", "escape-html": "1.0.3", - "globals": "^15.14.0", "hash-sum": "^2.0.0", "js-cookie": "3.0.5", "localforage": "1.10.0", + "pako": "^2.1.0", "parse-link-header": "2.0.0", "phoenix": "1.7.19", "pinia": "^2.0.33", @@ -74,14 +74,14 @@ "css-loader": "7.1.2", "css-minimizer-webpack-plugin": "7.0.0", "custom-event-polyfill": "1.0.7", - "eslint": "9.19.0", + "eslint": "8.57.1", "eslint-config-standard": "17.1.0", "eslint-formatter-friendly": "7.0.0", "eslint-plugin-import": "2.31.0", "eslint-plugin-n": "15.7.0", "eslint-plugin-promise": "6.6.0", "eslint-plugin-vue": "9.32.0", - "eslint-webpack-plugin": "4.2.0", + "eslint-webpack-plugin": "3.2.0", "eventsource-polyfill": "0.9.6", "express": "4.21.2", "function-bind": "1.1.2", diff --git a/src/App.js b/src/App.js index 1c1b3a8c2..ca218cfff 100644 --- a/src/App.js +++ b/src/App.js @@ -47,10 +47,10 @@ export default { mobileActivePanel: 'timeline' }), watch: { - themeApplied () { + themeApplied (value) { this.removeSplash() }, - layoutType () { + layoutType (value) { document.getElementById('modal').classList = ['-' + this.layoutType] } }, diff --git a/src/boot/after_store.js b/src/boot/after_store.js index dbbbdb2e4..680aec14d 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -79,7 +79,7 @@ const getInstanceConfig = async ({ store }) => { } } -const getBackendProvidedConfig = async () => { +const getBackendProvidedConfig = async ({ store }) => { try { const res = await window.fetch('/api/pleroma/frontend_configurations') if (res.ok) { diff --git a/src/boot/routes.js b/src/boot/routes.js index da87c6c61..66d937c8e 100644 --- a/src/boot/routes.js +++ b/src/boot/routes.js @@ -43,7 +43,7 @@ export default (store) => { { name: 'root', path: '/', - redirect: () => { + redirect: _to => { return (store.state.users.currentUser ? store.state.instance.redirectRootLogin : store.state.instance.redirectRootNoLogin) || '/main/all' diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js index 21d793930..2bf6b846f 100644 --- a/src/components/attachment/attachment.js +++ b/src/components/attachment/attachment.js @@ -145,7 +145,7 @@ const Attachment = { window.open(target.href, '_blank') } }, - openModal () { + openModal (event) { if (this.useModal) { this.$emit('setMedia') useMediaViewerStore().setCurrentMedia(this.attachment) @@ -153,7 +153,7 @@ const Attachment = { window.open(this.attachment.url) } }, - openModalForce () { + openModalForce (event) { this.$emit('setMedia') useMediaViewerStore().setCurrentMedia(this.attachment) }, diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 3ab7040ef..9abc26271 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -238,8 +238,8 @@ ref="flash" class="flash" :src="attachment.large_thumb_url || attachment.url" - @player-opened="setFlashLoaded(true)" - @player-closed="setFlashLoaded(false)" + @playerOpened="setFlashLoaded(true)" + @playerClosed="setFlashLoaded(false)" /> diff --git a/src/components/chat_list_item/chat_list_item.js b/src/components/chat_list_item/chat_list_item.js index 8f8c491f5..e5032176f 100644 --- a/src/components/chat_list_item/chat_list_item.js +++ b/src/components/chat_list_item/chat_list_item.js @@ -52,7 +52,7 @@ const ChatListItem = { } }, methods: { - openChat () { + openChat (_e) { if (this.chat.id) { this.$router.push({ name: 'chat', diff --git a/src/components/checkbox/checkbox.vue b/src/components/checkbox/checkbox.vue index e447595f2..1e502f5a5 100644 --- a/src/components/checkbox/checkbox.vue +++ b/src/components/checkbox/checkbox.vue @@ -53,7 +53,7 @@ export default { } }, methods: { - onTransitionEnd () { + onTransitionEnd (e) { if (!this.indeterminate) { this.indeterminateTransitionFix = false } diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue index 26b67cfe8..418fb18c4 100644 --- a/src/components/color_input/color_input.vue +++ b/src/components/color_input/color_input.vue @@ -15,7 +15,7 @@ :model-value="present" :disabled="disabled" class="opt" - @update:model-value="updateValue(typeof modelValue === 'undefined' ? fallback : undefined)" + @update:modelValue="updateValue(typeof modelValue === 'undefined' ? fallback : undefined)" />
- - + diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index b339dfd3f..aed8a7ebc 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -114,7 +114,7 @@ const conversation = { suspendable () { if (this.isTreeView) { return Object.entries(this.statusContentProperties) - .every(([, prop]) => !prop.replying && prop.mediaPlaying.length === 0) + .every(([k, prop]) => !prop.replying && prop.mediaPlaying.length === 0) } if (this.$refs.statusComponent && this.$refs.statusComponent[0]) { return this.$refs.statusComponent.every(s => s.suspendable) @@ -272,8 +272,11 @@ const conversation = { }, replies () { let i = 1 - - return reduce(this.conversation, (result, { id, in_reply_to_status_id: irid }) => { + // eslint-disable-next-line camelcase + return reduce(this.conversation, (result, { id, in_reply_to_status_id }) => { + /* eslint-disable camelcase */ + const irid = in_reply_to_status_id + /* eslint-enable camelcase */ if (irid) { result[irid] = result[irid] || [] result[irid].push({ @@ -378,7 +381,7 @@ const conversation = { this.resetDisplayState() } }, - virtualHidden () { + virtualHidden (value) { this.$store.dispatch( 'setVirtualHeight', { statusId: this.statusId, height: `${this.$el.clientHeight}px` } @@ -474,7 +477,7 @@ const conversation = { // nothing found, fall back to toplevel return this.topLevel[0] ? this.topLevel[0].id : undefined }, - diveIntoStatus (id) { + diveIntoStatus (id, preventScroll) { this.tryScrollTo(id) }, diveToTopLevel () { diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue index f1206e644..51c016323 100644 --- a/src/components/conversation/conversation.vue +++ b/src/components/conversation/conversation.vue @@ -123,7 +123,7 @@ :controlled-set-media-playing="(newVal) => toggleStatusContentProperty(status.id, 'mediaPlaying', newVal)" @goto="setHighlight" - @toggle-expanded="toggleExpanded" + @toggleExpanded="toggleExpanded" />
diff --git a/src/components/edit_status_modal/edit_status_modal.vue b/src/components/edit_status_modal/edit_status_modal.vue index 3d192b1ee..a53caf4ec 100644 --- a/src/components/edit_status_modal/edit_status_modal.vue +++ b/src/components/edit_status_modal/edit_status_modal.vue @@ -2,7 +2,7 @@
diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index f3b6dfe9b..09d44b0bd 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -265,7 +265,7 @@ const EmojiInput = { } }, watch: { - showSuggestions: function (newValue) { + showSuggestions: function (newValue, oldValue) { this.$emit('shown', newValue) if (newValue) { this.$refs.suggestorPopover.showPopover() diff --git a/src/components/emoji_input/suggestor.js b/src/components/emoji_input/suggestor.js index f2daf2f46..e746dcd76 100644 --- a/src/components/emoji_input/suggestor.js +++ b/src/components/emoji_input/suggestor.js @@ -116,6 +116,7 @@ export const suggestUsers = ({ dispatch, state }) => { const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1 return diff + nameAlphabetically + screenNameAlphabetically + /* eslint-disable camelcase */ }).map((user) => ({ user, displayText: user.screen_name_ui, @@ -123,6 +124,7 @@ export const suggestUsers = ({ dispatch, state }) => { imageUrl: user.profile_image_url_original, replacement: '@' + user.screen_name + ' ' })) + /* eslint-enable camelcase */ suggestions = newSuggestions || [] return suggestions diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js index 17a317a4d..48532d3e7 100644 --- a/src/components/emoji_picker/emoji_picker.js +++ b/src/components/emoji_picker/emoji_picker.js @@ -352,7 +352,7 @@ const EmojiPicker = { }, allEmojiGroups () { return Object.entries(this.allCustomGroups) - .map(([, v]) => v) + .map(([_, v]) => v) .concat(this.unicodeEmojiGroups) }, stickerPickerEnabled () { diff --git a/src/components/emoji_reactions/emoji_reactions.js b/src/components/emoji_reactions/emoji_reactions.js index d71dcbc4d..861fbe542 100644 --- a/src/components/emoji_reactions/emoji_reactions.js +++ b/src/components/emoji_reactions/emoji_reactions.js @@ -71,7 +71,7 @@ const EmojiReactions = { unreact (emoji) { this.$store.dispatch('unreactWithEmoji', { id: this.status.id, emoji }) }, - async emojiOnClick (emoji) { + async emojiOnClick (emoji, event) { if (!this.loggedIn) return await this.fetchEmojiReactionsByIfMissing() diff --git a/src/components/font_control/font_control.vue b/src/components/font_control/font_control.vue index 5f4ed105c..ecf217fb4 100644 --- a/src/components/font_control/font_control.vue +++ b/src/components/font_control/font_control.vue @@ -86,7 +86,7 @@ :id="name + '-local-font-switcher'" :model-value="modelValue?.family" class="custom-font" - @update:model-value="v => $emit('update:modelValue', { ...(modelValue || {}), family: v })" + @update:modelValue="v => $emit('update:modelValue', { ...(modelValue || {}), family: v })" >
diff --git a/src/components/interface_language_switcher/interface_language_switcher.vue b/src/components/interface_language_switcher/interface_language_switcher.vue index ad11589b0..e6a0c1617 100644 --- a/src/components/interface_language_switcher/interface_language_switcher.vue +++ b/src/components/interface_language_switcher/interface_language_switcher.vue @@ -13,7 +13,7 @@