Skip to content

Instantly share code, notes, and snippets.

@Refzlund
Last active May 19, 2025 17:09
Show Gist options
  • Save Refzlund/37a3b3f0446b6f92a7814985347470cf to your computer and use it in GitHub Desktop.
Save Refzlund/37a3b3f0446b6f92a7814985347470cf to your computer and use it in GitHub Desktop.
ESLint
/*
bun add -D @eslint/compat @eslint/js eslint-plugin-svelte eslint globals typescript-eslint @stylistic/eslint-plugin eslint-plugin-unused-imports eslint-plugin-import-no-duplicates-prefix-resolved-path eslint-plugin-import-x eslint-import-resolver-typescript @sveltejs/vite-plugin-svelte eslint-module-utils
*/
import { includeIgnoreFile } from '@eslint/compat'
import js from '@eslint/js'
import svelte from 'eslint-plugin-svelte'
import { globalIgnores } from 'eslint/config'
import globals from 'globals'
import { fileURLToPath } from 'node:url'
import ts from 'typescript-eslint'
import svelteConfig from './sveltekit-app/svelte.config.js'
import stylistic from '@stylistic/eslint-plugin'
import unusedImports from 'eslint-plugin-unused-imports'
// @ts-expect-error Is not typed but works fine! Replaces import-x/no-duplicates issue
import importPrefix from 'eslint-plugin-import-no-duplicates-prefix-resolved-path'
import importX from 'eslint-plugin-import-x'
import 'eslint-import-resolver-typescript' // required for eslint-plugin-import-x
const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url))
// Improved ignore patterns to exclude problematic files and directories
const ignorePatterns = [
'**/eslint.config.js',
'**/svelte.config.js',
'**/.svelte-kit/*',
'**/node_modules/**',
'**/node_modules/zod/**',
'**/node_modules/zod/lib/**',
'**/node_modules/zod/lib/index.mjs',
'**/.wrangler/*',
'**/.git/*',
'**/.mongodb/*',
'**/.cloudflare/*',
'**/lang/src/paraglide/*',
'**/src-tauri/target/*',
'**/dist/**',
'**/build/**',
'**/.turbo/**'
]
export default ts.config(
globalIgnores(ignorePatterns),
includeIgnoreFile(gitignorePath),
js.configs.recommended,
...ts.configs.recommended,
...svelte.configs.recommended,
{
files: ['**/*.{js,mjs,cjs,ts,svelte}'],
extends: [importX.flatConfigs.recommended, importX.flatConfigs.typescript],
ignores: ['**/node_modules/**'],
languageOptions: {
globals: {
...globals.browser,
...globals.node
},
parserOptions: {
projectService: true,
extraFileExtensions: ['.svelte'],
parser: ts.parser,
svelteConfig,
// Optimizing for performance
cacheLifetime: {
glob: 'Infinity'
},
// Add cache strategy for better performance
tsconfigRootDir: '.',
project: ['./tsconfig.json', './*/tsconfig.json', './apps/*/tsconfig.json'],
cache: true
}
},
plugins: {
'@stylistic': stylistic,
'unused-imports': unusedImports,
'import-no-duplicates-prefix-resolved-path': importPrefix
},
rules: {
// Disabling rules that might slow down the linting process
'no-undef': 'off',
'no-empty-pattern': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'no-inner-declarations': 'off', // 700 ms
'svelte/require-store-reactive-access': 'off', // 1000 ms
'import-x/namespace': 'off', // 2000 ms
'import-x/no-unresolved': 'off', // 80 ms
'import-x/no-duplicates': 'off', // doesn't work with module declarations
'import-no-duplicates-prefix-resolved-path/no-duplicates': [
'warn',
{
'prefixResolvedPathWithImportName': true,
'prefer-inline': true,
},
],
'unused-imports/no-unused-imports': 'warn',
'unused-imports/no-unused-vars': [
'warn',
{
'vars': 'all',
'varsIgnorePattern': '^_',
'args': 'after-used',
'argsIgnorePattern': '^_',
},
],
// TypeScript Rules
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/no-empty-object-type': 'off',
'@stylistic/member-delimiter-style': ['error',
{
'multiline': {
'delimiter': 'none',
'requireLast': false
},
'singleline': {
'delimiter': 'comma',
'requireLast': false
}
}],
'@stylistic/type-annotation-spacing': ['error',
{
'before': false,
'after': true,
'overrides': {
'arrow': {
'before': true,
'after': true
}
}
}],
'@stylistic/type-generic-spacing': 'error',
'@typescript-eslint/naming-convention': [
'error',
{
'selector': 'interface',
'format': ['PascalCase'],
'custom': {
'regex': '^I[A-Z]',
'match': false
}
}
],
// @stylistic - https://eslint.style/packages/default
'@stylistic/quotes': ['error',
'single',
{ allowTemplateLiterals: 'always' }],
'@stylistic/semi': ['error', 'never'],
'@stylistic/comma-dangle': ['error', 'never'],
'@stylistic/object-curly-spacing': ['error', 'always'],
'@stylistic/space-before-function-paren': ['error',
{
'anonymous': 'never',
'named': 'never',
'asyncArrow': 'always'
}],
'@stylistic/space-before-blocks': ['error', 'always'],
'@stylistic/indent': [
'error',
'tab',
{ 'ignoredNodes': ['ConditionalExpression'] }
],
'@stylistic/indent-binary-ops': ['error', 'tab'],
'@stylistic/array-bracket-newline': ['error', 'consistent'],
'@stylistic/array-element-newline': ['error',
{
multiline: true,
minItems: 3
}],
'@stylistic/space-infix-ops': ['error'],
'@stylistic/comma-spacing': ['error',
{
'before': false,
'after': true
}],
'@stylistic/function-call-argument-newline': ['error', 'consistent'],
'@stylistic/function-paren-newline': ['error', 'multiline'],
'@stylistic/key-spacing': ['error',
{
'beforeColon': false,
'afterColon': true,
'mode': 'strict'
}],
'@stylistic/block-spacing': ['error', 'always'],
'@stylistic/no-multi-spaces': ['error', { 'ignoreEOLComments': true }],
'@stylistic/object-curly-newline': [
'error',
{ multiline: true }
],
'@stylistic/object-property-newline': ['error', { allowAllPropertiesOnSameLine: false }],
// Svelte Rules
'svelte/html-quotes': ['error', { 'prefer': 'single' }],
'svelte/max-attributes-per-line': [
'error',
{
'multiline': 1,
'singleline': 2
}
],
'svelte/indent': ['error', { 'indent': 'tab' }],
'svelte/shorthand-attribute': 'error',
'svelte/shorthand-directive': 'error',
'svelte/sort-attributes': 'error',
'svelte/spaced-html-comment': 'error',
'svelte/no-spaces-around-equal-signs-in-attribute': 'error',
'svelte/first-attribute-linebreak': [
'error',
{
'multiline': 'below',
'singleline': 'beside'
}
],
'svelte/html-closing-bracket-new-line': [
'error',
{
'singleline': 'never',
'multiline': 'always',
'selfClosingTag': {
'singleline': 'never',
'multiline': 'always'
}
}
],
'svelte/html-closing-bracket-spacing': [
'error',
{
'startTag': 'never',
'endTag': 'never',
'selfClosingTag': 'always'
}
]
}
}
)
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
/** @type {import('@sveltejs/kit').Config} */
const config = {
preprocess: [ vitePreprocess() ],
compilerOptions: { runes: true },
kit: {}
}
export default config
{
"compilerOptions": {
"lib": ["ESNext", "DOM", "DOM.Iterable", "DOM.AsyncIterable"],
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler",
"module": "ESNext",
"target": "ESNext",
"verbatimModuleSyntax": true,
"isolatedModules": true,
"noImplicitAny": false,
},
"include": [
"**/*"
],
"exclude": [
"./**/*.config.js",
"./**/*.config.ts",
"./**/*.config.cjs",
"./node_modules"
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment