diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 943f80f503..0000000000
--- a/.eslintignore
+++ /dev/null
@@ -1,21 +0,0 @@
-node_modules/*
-*/dist/*
-*.user.js
-build/**/*.js
-docs/.vuepress/*.js
-docs/.vuepress/.cache
-docs/.vuepress/.temp
-docs/.vuepress/dist
-docs/.vuepress/node_modules
-docs/.vuepress/components/.temp
-prebuild/*.js
-scripts/**/*.js
-src/userscript.js
-src/config.js
-
-static/fontawesome_*.min.js
-static/missions/*
-static/releasenotes/*
-
-src/modules/support/*
-src/modules/renameFz/*
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0a738402d9..a2ed5d0fa3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -146,7 +146,6 @@ jobs:
./src/ \
./scripts/ \
./typings/ \
- --ext .js,.ts,.vue,.md \
--no-error-on-unmatched-pattern \
--exit-on-fatal-error \
--report-unused-disable-directives \
diff --git a/build/build.ps1 b/build/build.ps1
index 9df4b70805..65649b6d25 100644
--- a/build/build.ps1
+++ b/build/build.ps1
@@ -377,7 +377,7 @@ if ($_RUN_STEP_ESLINT) {
$start_time = now
print_start_message "[🚨] run ESLint"
enable_debugging
- yarn eslint ./docs/.vuepress/ ./static/ ./prebuild/ ./build/ ./src/ ./scripts/ ./typings/ --ext .js, .ts, .vue, .md --no-error-on-unmatched-pattern --exit-on-fatal-error --report-unused-disable-directives --cache --cache-strategy content --fix
+ yarn eslint ./docs/.vuepress/ ./static/ ./prebuild/ ./build/ ./src/ ./scripts/ ./typings/ --no-error-on-unmatched-pattern --exit-on-fatal-error --report-unused-disable-directives --cache --cache-strategy content --fix
if (!$?) {
exit 1
}
diff --git a/build/build.sh b/build/build.sh
index 7f05590be7..7970e938a8 100755
--- a/build/build.sh
+++ b/build/build.sh
@@ -260,7 +260,7 @@ if [[ $_RUN_STEP_ENV = true ]]; then
enable_debugging
ref="$REF"
BRANCH="dummy"
-
+
if [[ $ref == "refs/heads/master" ]]; then
BRANCH="stable"
elif [[ $ref == "refs/heads/dev" ]]; then
@@ -310,7 +310,6 @@ if [[ $_RUN_STEP_ESLINT = true ]]; then
./src/ \
./scripts/ \
./typings/ \
- --ext .js,.ts,.vue,.md \
--no-error-on-unmatched-pattern \
--exit-on-fatal-error \
--report-unused-disable-directives \
@@ -407,4 +406,4 @@ fi
print_end_message "Total" "$total_start_time"
-exit 0
\ No newline at end of file
+exit 0
diff --git a/docs/.vuepress/.eslintrc.json b/docs/.vuepress/.eslintrc.json
deleted file mode 100644
index 79c5f6baa0..0000000000
--- a/docs/.vuepress/.eslintrc.json
+++ /dev/null
@@ -1 +0,0 @@
-{ "globals": { "__VAR__": "readonly" } }
\ No newline at end of file
diff --git a/docs/.vuepress/theme/components/Page.vue b/docs/.vuepress/theme/components/Page.vue
index c046141e14..b27a7a7c91 100644
--- a/docs/.vuepress/theme/components/Page.vue
+++ b/docs/.vuepress/theme/components/Page.vue
@@ -1,3 +1,4 @@
+
diff --git a/eslint.config.cjs b/eslint.config.cjs
new file mode 100644
index 0000000000..b224efa6c3
--- /dev/null
+++ b/eslint.config.cjs
@@ -0,0 +1,488 @@
+const { fixupConfigRules, fixupPluginRules } = require('@eslint/compat');
+
+const typescriptEslint = require('@typescript-eslint/eslint-plugin');
+const _import = require('eslint-plugin-import');
+const jsdoc = require('eslint-plugin-jsdoc');
+const prettier = require('eslint-plugin-prettier');
+const tsdoc = require('eslint-plugin-tsdoc');
+const unicorn = require('eslint-plugin-unicorn');
+const regexp = require('eslint-plugin-regexp');
+const vue = require('eslint-plugin-vue');
+const globals = require('globals');
+const markdownlint = require('eslint-plugin-markdownlint');
+const parser = require('eslint-plugin-markdownlint/parser');
+const js = require('@eslint/js');
+
+const { FlatCompat } = require('@eslint/eslintrc');
+
+const compat = new FlatCompat({
+ baseDirectory: __dirname,
+ recommendedConfig: js.configs.recommended,
+ allConfig: js.configs.all,
+});
+
+module.exports = [
+ {
+ files: ['./src/**/*.+(js|ts|vue|md)'],
+ ignores: [
+ 'node_modules/*',
+ 'dist/*',
+ 'typings/dist/*',
+ '**/*.user.js',
+ 'build/**/*.js',
+ 'docs/.vuepress/*.js',
+ 'docs/.vuepress/.cache',
+ 'docs/.vuepress/.temp',
+ 'docs/.vuepress/dist',
+ 'docs/.vuepress/node_modules',
+ 'docs/.vuepress/components/.temp',
+ 'prebuild/*.js',
+ 'scripts/**/*.js',
+ 'src/userscript.js',
+ 'src/config.js',
+ 'static/fontawesome_*.min.js',
+ 'static/missions/*',
+ 'static/releasenotes/*',
+ 'static/lssm-v4.user.js',
+ 'src/modules/support/*',
+ 'src/modules/renameFz/*',
+ ],
+ },
+ ...fixupConfigRules(
+ compat.extends(
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:compat/recommended',
+ 'plugin:import/typescript',
+ 'plugin:jsdoc/recommended',
+ 'plugin:regexp/recommended',
+ 'plugin:vue/essential',
+ 'prettier'
+ )
+ ),
+ {
+ files: ['docs/.vuepress/**/*.+(ts|vue)'],
+ languageOptions: {
+ globals: {
+ __VAR__: 'readonly',
+ }
+ }
+ },
+ {
+ plugins: {
+ '@typescript-eslint': fixupPluginRules(typescriptEslint),
+ //compat,
+ 'import': fixupPluginRules(_import),
+ 'jsdoc': fixupPluginRules(jsdoc),
+ prettier,
+ tsdoc,
+ unicorn,
+ 'regexp': fixupPluginRules(regexp),
+ 'vue': fixupPluginRules(vue),
+ },
+
+ languageOptions: {
+ globals: {
+ ...globals.browser,
+ ...globals.commonjs,
+ Atomics: 'readonly',
+ SharedArrayBuffer: 'readonly',
+ process: 'readonly',
+ __dirname: 'readonly',
+ PREFIX: 'readonly',
+ MODE: 'readonly',
+ VERSION: 'readonly',
+ BRANCH: 'readonly',
+ LOADSCRIPT_EVENT_START: 'readonly',
+ LOADSCRIPT_EVENT_END: 'readonly',
+ },
+
+ ecmaVersion: 2018,
+ sourceType: 'module',
+
+ parserOptions: {
+ parser: '@typescript-eslint/parser',
+
+ project: [
+ './tsconfig.json',
+ './build/tsconfig.json',
+ './docs/.vuepress/tsconfig.json',
+ './prebuild/tsconfig.json',
+ './scripts/tsconfig.json',
+ './src/tsconfig.userscript.json',
+ ],
+
+ extraFileExtensions: ['.vue'],
+ },
+ },
+
+ settings: {
+ jsdoc: {
+ mode: 'typescript',
+ },
+ },
+
+ rules: {
+ '@typescript-eslint/array-type': ['error'],
+ '@typescript-eslint/consistent-indexed-object-style': [
+ 'error',
+ 'record',
+ ],
+ '@typescript-eslint/consistent-type-definitions': [
+ 'error',
+ 'interface',
+ ],
+ '@typescript-eslint/consistent-type-imports': ['error'],
+ '@typescript-eslint/method-signature-style': ['error', 'method'],
+ '@typescript-eslint/no-duplicate-enum-values': ['off'],
+ '@typescript-eslint/sort-type-constituents': ['error'],
+ 'array-callback-return': ['error'],
+ 'block-scoped-var': 'warn',
+ 'curly': ['error', 'multi-or-nest', 'consistent'],
+ 'default-case-last': 'error',
+ 'guard-for-in': 'error',
+
+ 'import/order': [
+ 'error',
+ {
+ 'groups': [
+ ['builtin'],
+ ['external'],
+ ['internal'],
+ ['parent', 'sibling'],
+ ['index'],
+ ['object'],
+ ['type'],
+ ],
+
+ 'pathGroups': [
+ {
+ pattern: 'vue',
+ group: 'builtin',
+ position: 'before',
+ },
+ ],
+
+ 'pathGroupsExcludedImportTypes': ['vue'],
+ 'newlines-between': 'always',
+ },
+ ],
+
+ 'jsdoc/check-syntax': ['error'],
+
+ 'jsdoc/check-tag-names': [
+ 'error',
+ {
+ definedTags: ['alpha', 'beta'],
+ },
+ ],
+
+ 'jsdoc/no-types': ['error'],
+ 'jsdoc/require-asterisk-prefix': ['error'],
+ 'jsdoc/require-description': ['error'],
+ 'jsdoc/require-description-complete-sentence': ['error'],
+ 'jsdoc/require-hyphen-before-param-description': ['error'],
+ 'jsdoc/require-param-type': ['off'],
+ 'jsdoc/require-returns-type': ['off'],
+ 'no-constant-binary-expression': 'error',
+
+ 'no-duplicate-imports': [
+ 'error',
+ {
+ includeExports: true,
+ },
+ ],
+
+ 'no-eval': 'error',
+ 'no-floating-decimal': 'warn',
+
+ 'no-implicit-coercion': [
+ 'error',
+ {
+ allow: ['!!'],
+ },
+ ],
+
+ 'no-loop-func': 'error',
+ 'no-loss-of-precision': 'error',
+ 'no-multi-str': 'warn',
+ 'no-new-native-nonconstructor': 'error',
+ 'no-param-reassign': 'error',
+ 'no-prototype-builtins': 'off',
+ 'no-self-compare': 'error',
+ 'no-sequences': 'error',
+ 'no-template-curly-in-string': 'warn',
+ 'no-unmodified-loop-condition': 'error',
+ 'no-unreachable-loop': 'error',
+ 'no-unsafe-optional-chaining': 'error',
+ 'no-unused-expressions': 'error',
+ 'no-useless-concat': 'warn',
+ 'no-useless-rename': 'error',
+ 'no-useless-return': 'warn',
+ 'no-var': 'error',
+
+ 'object-shorthand': [
+ 'error',
+ 'always',
+ {
+ avoidQuotes: true,
+ },
+ ],
+
+ 'prefer-arrow-callback': 'error',
+ 'prefer-const': 'error',
+
+ 'prefer-regex-literals': [
+ 'error',
+ {
+ disallowRedundantWrapping: true,
+ },
+ ],
+
+ 'prefer-rest-params': 'error',
+ 'prefer-spread': 'error',
+ 'prefer-template': 'error',
+ 'prettier/prettier': 'error',
+ 'regexp/hexadecimal-escape': ['error', 'never'],
+ 'regexp/letter-case': ['error'],
+ 'regexp/no-control-character': ['error'],
+ 'regexp/no-empty-character-class': ['error'],
+ 'regexp/no-extra-lookaround-assertions': ['error'],
+ 'regexp/no-misleading-unicode-character': ['error'],
+ 'regexp/no-missing-g-flag': ['error'],
+ 'regexp/no-octal': ['error'],
+ 'regexp/no-standalone-backslash': ['error'],
+ 'regexp/prefer-escape-replacement-dollar-char': ['error'],
+ 'regexp/prefer-lookaround': ['error'],
+ 'regexp/prefer-named-backreference': ['error'],
+ 'regexp/prefer-named-replacement': ['error'],
+ 'regexp/prefer-result-array-groups': ['error'],
+ 'regexp/prefer-regexp-test': ['error'],
+ 'regexp/require-unicode-regexp': ['error'],
+ 'regexp/sort-alternatives': ['error'],
+ 'regexp/sort-character-class-elements': ['error'],
+ 'regexp/unicode-escape': ['error', 'unicodeEscape'],
+ 'regexp/use-ignore-case': ['error'],
+ 'semi': ['error', 'always'],
+
+ 'sort-imports': [
+ 'warn',
+ {
+ allowSeparatedGroups: true,
+ ignoreCase: true,
+ memberSyntaxSortOrder: [
+ 'none',
+ 'all',
+ 'single',
+ 'multiple',
+ ],
+ },
+ ],
+
+ 'template-curly-spacing': 'error',
+ 'tsdoc/syntax': 'warn',
+ 'unicorn/consistent-destructuring': ['error'],
+ 'unicorn/no-array-push-push': ['error'],
+ 'unicorn/no-for-loop': ['error'],
+ 'unicorn/no-unnecessary-await': ['error'],
+ 'unicorn/no-unreadable-iife': ['error'],
+ 'unicorn/no-useless-switch-case': ['error'],
+ 'unicorn/no-zero-fractions': ['error'],
+ 'unicorn/numeric-separators-style': ['error'],
+ 'unicorn/prefer-add-event-listener': ['error'],
+ 'unicorn/prefer-array-index-of': ['error'],
+
+ 'unicorn/prefer-array-find': [
+ 'error',
+ {
+ checkFromLast: true,
+ },
+ ],
+
+ 'unicorn/prefer-array-flat': ['error'],
+ 'unicorn/prefer-array-flat-map': ['error'],
+ 'unicorn/prefer-array-some': ['error'],
+ 'unicorn/prefer-at': ['error'],
+ 'unicorn/prefer-dom-node-append': ['error'],
+ 'unicorn/prefer-dom-node-remove': ['error'],
+ 'unicorn/prefer-dom-node-text-content': ['error'],
+ 'unicorn/prefer-keyboard-event-key': ['error'],
+ 'unicorn/prefer-modern-dom-apis': ['error'],
+ 'unicorn/prefer-modern-math-apis': ['error'],
+ 'unicorn/prefer-native-coercion-functions': ['error'],
+ 'unicorn/prefer-negative-index': ['error'],
+ 'unicorn/prefer-object-from-entries': ['error'],
+ 'unicorn/prefer-query-selector': ['off'],
+ 'unicorn/switch-case-braces': ['error', 'avoid'],
+ 'vue/no-unused-refs': 'warn',
+ 'vue/prefer-true-attribute-shorthand': 'warn',
+
+ 'yoda': [
+ 'error',
+ 'never',
+ {
+ exceptRange: true,
+ },
+ ],
+ },
+ },
+ {
+ files: ['./src/**/*'],
+
+ rules: {
+ 'no-console': 'warn',
+ },
+ },
+ {
+ files: ['**/*.md'],
+
+ plugins: {
+ markdownlint,
+ },
+
+ languageOptions: {
+ parser: parser,
+ },
+
+ rules: {
+ 'prettier/prettier': ['off'],
+ 'markdownlint/md001': ['error'],
+
+ 'markdownlint/md003': [
+ 'error',
+ {
+ style: 'atx',
+ },
+ ],
+
+ 'markdownlint/md004': [
+ 'error',
+ {
+ style: 'asterisk',
+ },
+ ],
+
+ 'markdownlint/md005': ['error'],
+
+ 'markdownlint/md007': [
+ 'error',
+ {
+ indent: 4,
+ },
+ ],
+
+ 'markdownlint/md009': ['error'],
+
+ 'markdownlint/md010': [
+ 'error',
+ {
+ spaces_per_tab: 4,
+ },
+ ],
+
+ 'markdownlint/md011': ['error'],
+ 'markdownlint/md012': ['error'],
+ 'markdownlint/md014': ['error'],
+ 'markdownlint/md018': ['error'],
+ 'markdownlint/md019': ['error'],
+ 'markdownlint/md020': ['error'],
+ 'markdownlint/md021': ['error'],
+
+ 'markdownlint/md022': [
+ 'error',
+ {
+ lines_above: 1,
+ lines_below: 0,
+ },
+ ],
+
+ 'markdownlint/md023': ['error'],
+
+ 'markdownlint/md024': [
+ 'error',
+ {
+ siblings_only: true,
+ },
+ ],
+
+ 'markdownlint/md025': ['off'],
+ 'markdownlint/md026': ['error'],
+ 'markdownlint/md027': ['error'],
+ 'markdownlint/md028': ['error'],
+
+ 'markdownlint/md029': [
+ 'error',
+ {
+ style: 'ordered',
+ },
+ ],
+
+ 'markdownlint/md030': ['error'],
+ 'markdownlint/md031': ['error'],
+ 'markdownlint/md032': ['error'],
+
+ 'markdownlint/md033': [
+ 'error',
+ {
+ allowed_elements: ['discord', 'a'],
+ },
+ ],
+
+ 'markdownlint/md034': ['error'],
+
+ 'markdownlint/md035': [
+ 'error',
+ {
+ style: '***',
+ },
+ ],
+
+ 'markdownlint/md036': ['error'],
+ 'markdownlint/md037': ['error'],
+ 'markdownlint/md038': ['error'],
+ 'markdownlint/md039': ['error'],
+ 'markdownlint/md040': ['error'],
+ 'markdownlint/md041': ['off'],
+ 'markdownlint/md042': ['error'],
+
+ 'markdownlint/md044': [
+ 'error',
+ {
+ names: ['LSSM'],
+ },
+ ],
+
+ 'markdownlint/md045': ['error'],
+
+ 'markdownlint/md046': [
+ 'error',
+ {
+ style: 'fenced',
+ },
+ ],
+
+ 'markdownlint/md047': ['error'],
+
+ 'markdownlint/md048': [
+ 'error',
+ {
+ style: 'backtick',
+ },
+ ],
+
+ 'markdownlint/md049': [
+ 'error',
+ {
+ style: 'asterisk',
+ },
+ ],
+
+ 'markdownlint/md050': [
+ 'error',
+ {
+ style: 'asterisk',
+ },
+ ],
+ },
+ },
+];
diff --git a/package.json b/package.json
index 1b5211ebdb..68b8f74be2 100644
--- a/package.json
+++ b/package.json
@@ -50,6 +50,9 @@
"vue-slim-tabs": "0.4.0"
},
"devDependencies": {
+ "@eslint/compat": "1.0.3",
+ "@eslint/eslintrc": "3.1.0",
+ "@eslint/js": "9.4.0",
"@types/he": "1.2.3",
"@types/i18n-js": "3.8.9",
"@types/jquery": "3.5.30",
@@ -71,7 +74,7 @@
"all-contributors-cli": "6.26.1",
"copy-dir": "1.3.0",
"css-loader": "7.1.2",
- "eslint": "8.57.0",
+ "eslint": "9.6.0",
"eslint-config-prettier": "9.1.0",
"eslint-import-resolver-typescript": "3.6.1",
"eslint-plugin-compat": "5.0.0",
@@ -83,6 +86,7 @@
"eslint-plugin-tsdoc": "0.3.0",
"eslint-plugin-unicorn": "54.0.0",
"eslint-plugin-vue": "9.27.0",
+ "globals": "15.3.0",
"html-loader": "5.0.0",
"husky": "9.0.11",
"js-yaml": "4.1.0",
@@ -128,4 +132,4 @@
"author": "The LSSM-Team: Sanni, Jan (jxn_30), Ron31, Crazycake",
"description": "LSSM V4 is a Script-Collection for Leitstellenspiel, Missionchief, Meldkamerspel and its other language versions."
}
-}
\ No newline at end of file
+}
diff --git a/src/modules/support/components/chat.vue b/src/modules/support/components/chat.vue
index 47e5d83767..d7f6e8ad4d 100644
--- a/src/modules/support/components/chat.vue
+++ b/src/modules/support/components/chat.vue
@@ -12,15 +12,11 @@
:class="message.self ? 'pull-right' : 'pull-left'"
>
@@ -73,8 +69,9 @@