Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions packages/adders/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export function addEslintConfigPrettier({ ast }: ScriptFileEditor<Record<string,

const fallbackConfig = common.expressionFromString('[]');
const defaultExport = exports.defaultExport(ast, fallbackConfig);
const array = defaultExport.value;
if (array.type !== 'ArrayExpression') return;
const eslintConfig = defaultExport.value;
if (eslintConfig.type !== 'ArrayExpression' && eslintConfig.type !== 'CallExpression') return;

const prettier = common.expressionFromString('prettier');
const sveltePrettierConfig = common.expressionFromString(
Expand All @@ -35,11 +35,13 @@ export function addEslintConfigPrettier({ ast }: ScriptFileEditor<Record<string,
const configSpread = common.createSpreadElement(sveltePrettierConfig);

const nodesToInsert = [];
if (!common.hasNode(array, prettier)) nodesToInsert.push(prettier);
if (!common.hasNode(array, configSpread)) nodesToInsert.push(configSpread);
if (!common.hasNode(eslintConfig, prettier)) nodesToInsert.push(prettier);
if (!common.hasNode(eslintConfig, configSpread)) nodesToInsert.push(configSpread);

const elements =
eslintConfig.type == 'ArrayExpression' ? eslintConfig.elements : eslintConfig.arguments;
// finds index of `...svelte.configs["..."]`
const idx = array.elements.findIndex(
const idx = elements.findIndex(
(el) =>
el?.type === 'SpreadElement' &&
el.argument.type === 'MemberExpression' &&
Expand All @@ -51,9 +53,9 @@ export function addEslintConfigPrettier({ ast }: ScriptFileEditor<Record<string,
);

if (idx !== -1) {
array.elements.splice(idx + 1, 0, ...nodesToInsert);
elements.splice(idx + 1, 0, ...nodesToInsert);
} else {
// append to the end as a fallback
array.elements.push(...nodesToInsert);
elements.push(...nodesToInsert);
}
}
38 changes: 26 additions & 12 deletions packages/adders/eslint/config/adder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import fs from 'node:fs';
import path from 'node:path';
import { options } from './options.ts';
import { addEslintConfigPrettier } from '../../common.ts';
import { defineAdderConfig, log } from '@svelte-cli/core';
import { array, common, exports, imports, object } from '@svelte-cli/core/js';
import { defineAdderConfig, log, type AstKinds, type AstTypes } from '@svelte-cli/core';
import { array, common, exports, functions, imports, object } from '@svelte-cli/core/js';

export const adder = defineAdderConfig({
metadata: {
Expand Down Expand Up @@ -65,18 +65,20 @@ export const adder = defineAdderConfig({
name: () => 'eslint.config.js',
contentType: 'script',
content: ({ ast, typescript }) => {
const eslintConfigs = array.createEmpty();
const eslintConfigs: Array<
AstKinds.ExpressionKind | AstTypes.SpreadElement | AstTypes.ObjectExpression
> = [];

const jsConfig = common.expressionFromString('js.configs.recommended');
array.push(eslintConfigs, jsConfig);
eslintConfigs.push(jsConfig);

if (typescript) {
const tsConfig = common.expressionFromString('ts.configs.recommended');
array.push(eslintConfigs, common.createSpreadElement(tsConfig));
eslintConfigs.push(common.createSpreadElement(tsConfig));
}

const svelteConfig = common.expressionFromString('svelte.configs["flat/recommended"]');
array.push(eslintConfigs, common.createSpreadElement(svelteConfig));
eslintConfigs.push(common.createSpreadElement(svelteConfig));

const globalsBrowser = common.createSpreadElement(
common.expressionFromString('globals.browser')
Expand All @@ -89,7 +91,7 @@ export const adder = defineAdderConfig({
globals: globalsObjLiteral
})
});
array.push(eslintConfigs, globalsConfig);
eslintConfigs.push(globalsConfig);

if (typescript) {
const svelteTSParserConfig = object.create({
Expand All @@ -100,23 +102,35 @@ export const adder = defineAdderConfig({
})
})
});
array.push(eslintConfigs, svelteTSParserConfig);
eslintConfigs.push(svelteTSParserConfig);
}

const ignoresConfig = object.create({
ignores: common.expressionFromString('["build/", ".svelte-kit/", "dist/"]')
});
array.push(eslintConfigs, ignoresConfig);
eslintConfigs.push(ignoresConfig);

const defaultExport = exports.defaultExport(ast, eslintConfigs);
let exportExpression: AstTypes.ArrayExpression | AstTypes.CallExpression;
if (typescript) {
const tsConfigCall = functions.call('ts.config', []);
tsConfigCall.arguments.push(...eslintConfigs);
exportExpression = tsConfigCall;
} else {
const eslintArray = array.createEmpty();
eslintConfigs.map((x) => array.push(eslintArray, x));
exportExpression = eslintArray;
}

const defaultExport = exports.defaultExport(ast, exportExpression);
// if it's not the config we created, then we'll leave it alone and exit out
if (defaultExport.value !== eslintConfigs) {
if (defaultExport.value !== exportExpression) {
log.warn('An eslint config is already defined. Skipping initialization.');
return;
}

// type annotate config
common.addJsDocTypeComment(defaultExport.astNode, "import('eslint').Linter.Config[]");
if (!typescript)
common.addJsDocTypeComment(defaultExport.astNode, "import('eslint').Linter.Config[]");

// imports
if (typescript) imports.addDefault(ast, 'typescript-eslint', 'ts');
Expand Down