char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Aleksander Grygierui: ESLint config updates (#27700)f1357e499

char/aliceai-t5-moe
10.9 KiB336 linesraw
1// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format
2import svelteConfig from './svelte.config.js';
3import { includeIgnoreFile } from '@eslint/compat';
4import js from '@eslint/js';
5import prettier from 'eslint-config-prettier';
6import perfectionist from 'eslint-plugin-perfectionist';
7import simpleImportSort from 'eslint-plugin-simple-import-sort';
8import storybook from 'eslint-plugin-storybook';
9import svelte from 'eslint-plugin-svelte';
10import globals from 'globals';
11import { fileURLToPath } from 'node:url';
12import ts from 'typescript-eslint';
13
14const gitignorePath = fileURLToPath(new URL('./.gitignore', import.meta.url));
15// Require a blank line between sibling element-like nodes in a Svelte template
16// (elements, components, and the {#if} / {#each} / {#await} / {#snippet} /
17// {@render} blocks) that sit on separate lines at the same nesting level.
18// Whitespace between siblings is a whitespace-only SvelteText node; when it
19// holds a single newline (no blank line) the fix adds one, keeping the
20// indentation of the second sibling. Real text content (e.g. `foo\n\nbar`)
21// is left alone.
22const ELEMENT_LIKE_TYPES = new Set([
23	'SvelteAwaitBlock',
24	'SvelteComponent',
25	'SvelteEachBlock',
26	'SvelteElement',
27	'SvelteIfBlock',
28	'SvelteKeyBlock',
29	'SvelteRenderTag',
30	'SvelteSelf',
31	'SvelteSnippetBlock'
32]);
33const paddingLineBetweenElements = {
34	create(context) {
35		// Check one list of template children. Each children array holds the
36		// element-like nodes plus the whitespace/comment text between them.
37		function checkChildren(children) {
38			if (!Array.isArray(children)) return;
39
40			let lastElement = null;
41			let lastWhitespace = null;
42
43			for (const child of children) {
44				if (child.type === 'SvelteText' && /^\s*$/.test(child.value)) {
45					lastWhitespace = child;
46
47					continue;
48				}
49
50				if (!ELEMENT_LIKE_TYPES.has(child.type)) continue;
51
52				if (
53					lastElement &&
54					lastWhitespace &&
55					child.loc.start.line - lastElement.loc.end.line === 1
56				) {
57					const textNode = lastWhitespace;
58
59					context.report({
60						fix(fixer) {
61							// Add a second newline so the two siblings are separated by a
62							// blank line, keeping the trailing indentation.
63							return fixer.replaceText(textNode, textNode.value.replace(/\n/, '\n\n'));
64						},
65						message: 'Expected a blank line between sibling elements.',
66						node: child
67					});
68				}
69
70				lastElement = child;
71				lastWhitespace = null;
72			}
73		}
74
75		return {
76			SvelteAwaitBlock(node) {
77				checkChildren(node.children);
78				checkChildren(node.then?.children);
79				checkChildren(node.else?.children);
80			},
81			SvelteComponent(node) {
82				checkChildren(node.children);
83			},
84			SvelteEachBlock(node) {
85				checkChildren(node.children);
86				checkChildren(node.else?.children);
87			},
88			SvelteElement(node) {
89				checkChildren(node.children);
90			},
91			SvelteFragment(node) {
92				checkChildren(node.children);
93			},
94			SvelteIfBlock(node) {
95				checkChildren(node.children);
96				checkChildren(node.else?.children);
97			},
98			SvelteKeyBlock(node) {
99				checkChildren(node.children);
100			},
101			SvelteProgram(node) {
102				checkChildren(node.children);
103			},
104			SvelteSnippetBlock(node) {
105				checkChildren(node.children);
106			}
107		};
108	},
109	meta: {
110		docs: { description: 'Require a blank line between sibling elements in a Svelte template.' },
111		fixable: 'whitespace',
112		schema: [],
113		type: 'layout'
114	}
115};
116// Require a blank line between consecutive class accessors (get/set). The core
117// `padding-line-between-statements` rule only handles statements, not class
118// members, so this is enforced with a small custom rule.
119const blankLineBetweenAccessors = {
120	create(context) {
121		return {
122			MethodDefinition(node) {
123				if (node.kind !== 'get' && node.kind !== 'set') return;
124
125				const body = node.parent;
126
127				if (!body || body.type !== 'ClassBody') return;
128
129				const index = body.body.indexOf(node);
130
131				if (index <= 0) return;
132
133				const prev = body.body[index - 1];
134
135				if (prev.type !== 'MethodDefinition' || (prev.kind !== 'get' && prev.kind !== 'set'))
136					return;
137
138				if (node.loc.start.line - prev.loc.end.line <= 1) {
139					context.report({
140						fix(fixer) {
141							// Insert after the previous accessor's closing brace so the blank
142							// line keeps the current accessor's indentation.
143							return fixer.insertTextAfter(prev, '\n');
144						},
145						message: 'Expected a blank line between class accessors (get/set).',
146						node
147					});
148				}
149			}
150		};
151	},
152	meta: {
153		docs: { description: 'Require a blank line between consecutive class accessors (get/set).' },
154		fixable: 'whitespace',
155		schema: [],
156		type: 'layout'
157	}
158};
159
160export default ts.config(
161	includeIgnoreFile(gitignorePath),
162	js.configs.recommended,
163	...ts.configs.recommended,
164	...svelte.configs.recommended,
165	prettier,
166	...svelte.configs.prettier,
167	{
168		languageOptions: { globals: { ...globals.browser, ...globals.node } },
169		plugins: {
170			local: {
171				rules: {
172					'blank-line-between-accessors': blankLineBetweenAccessors,
173					'padding-line-between-elements': paddingLineBetweenElements
174				}
175			},
176			perfectionist,
177			'simple-import-sort': simpleImportSort
178		},
179		rules: {
180			// Snippet bodies often ignore one or more of the parent's params
181			// (e.g. `{#snippet children(_meta, ctx)}` when only ctx is read).
182			'@typescript-eslint/no-unused-vars': [
183				'error',
184				{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' }
185			],
186
187			// Enforce empty line at end of file
188			'eol-last': 'error',
189			// Enforce a blank line between consecutive get/set accessors
190			'local/blank-line-between-accessors': 'error',
191			// Require a blank line between sibling elements in a Svelte template
192			'local/padding-line-between-elements': 'error',
193			// typescript-eslint strongly recommend that you do not use the no-undef lint rule on TypeScript projects.
194			// see: https://typescript-eslint.io/troubleshooting/faqs/eslint/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors
195			'no-undef': 'off',
196
197			'padding-line-between-statements': [
198				'error',
199				// Blank line between function/class declarations.
200				{ blankLine: 'always', next: ['function', 'class'], prev: ['function', 'class'] },
201				// Blank line around if blocks (if/else and else if stay one statement).
202				{ blankLine: 'always', next: '*', prev: 'if' },
203				{ blankLine: 'always', next: 'if', prev: '*' },
204				// Blank line after the last declaration in a group. Because the 'never'
205				// rules below are scoped per declaration kind, a const group and a let
206				// group get separated by a blank line, while same-kind declarations stay
207				// together.
208				{ blankLine: 'always', next: '*', prev: ['const', 'let', 'var'] },
209				// No blank line between consecutive declarations of the same kind (kept
210				// last so each takes precedence over the always rule above for matching
211				// declaration pairs).
212				{ blankLine: 'never', next: 'const', prev: 'const' },
213				{ blankLine: 'never', next: 'let', prev: 'let' },
214				{ blankLine: 'never', next: 'var', prev: 'var' },
215				// Blank line before a statement that follows another statement in the block
216				// (works for return/throw/break/continue). A blank line for a terminal
217				// statement that opens a block body can't be enforced here: Prettier removes
218				// the leading blank line of a block, so the two formatters would fight.
219				{ blankLine: 'always', next: ['return', 'throw', 'break', 'continue'], prev: '*' }
220			],
221
222			// Class member order: public fields -> private fields -> constructor -> getters
223			// -> setters -> public methods -> private methods, alphabetical within each.
224			// Svelte $derived fields must stay in dependency order (forward references are
225			// rejected), so the two stores that rely on that are exempted below.
226			'perfectionist/sort-classes': [
227				'error',
228				{
229					customGroups: [
230						{ groupName: 'public-field', modifiers: ['public'], selector: 'property' },
231						{ groupName: 'private-field', modifiers: ['private'], selector: 'property' },
232						{ groupName: 'get-method', selector: 'get-method' },
233						{ groupName: 'set-method', selector: 'set-method' },
234						{ groupName: 'public-method', modifiers: ['public'], selector: 'method' },
235						{ groupName: 'private-method', modifiers: ['private'], selector: 'method' }
236					],
237					groups: [
238						'public-field',
239						'private-field',
240						'constructor',
241						'get-method',
242						'set-method',
243						'public-method',
244						'private-method',
245						'unknown'
246					],
247					type: 'natural',
248					// Keep members in dependency order (Svelte rejects forward references in
249					// $derived fields), while still sorting the rest alphabetically.
250					useExperimentalDependencyDetection: true
251				}
252			],
253
254			// Alphabetical order for enum members
255			'perfectionist/sort-enums': ['error', { type: 'natural' }],
256
257			'perfectionist/sort-objects': ['error', { type: 'natural' }],
258
259			// Alphabetical order for variable declarations and object keys
260			'perfectionist/sort-variable-declarations': ['error', { type: 'natural' }],
261
262			// Sort imports alphabetically by module path, and sort named members within
263			// each statement. A single catch-all group keeps the list flat (no blank-line
264			// grouping); Prettier normalizes comma spacing afterwards.
265			'simple-import-sort/imports': ['error', { groups: [['.*']] }],
266			'svelte/no-at-html-tags': 'off',
267			// This app uses hash-based routing (#/) where resolve() from $app/paths does not apply
268			'svelte/no-navigation-without-resolve': 'off',
269
270			// Sort HTML attributes alphabetically in the markup. The Svelte directives
271			// (bind:/use:/animate:/style:/in:/out:/transition:/class:) sort first,
272			// alphabetically among themselves, then all remaining attributes sort
273			// alphabetically. The rule keeps spread attributes in place and does not cross
274			// them. `this` stays first on <svelte:element> because Prettier forces it there
275			// - reordering it alphabetically would fight the formatter.
276			'svelte/sort-attributes': [
277				'error',
278				{
279					order: [
280						'this',
281						{
282							match: [
283								'/^bind:/u',
284								'/^use:/u',
285								'/^animate:/u',
286								'/^style:/u',
287								'/^in:/u',
288								'/^out:/u',
289								'/^transition:/u',
290								'/^class:/u'
291							],
292							sort: 'alphabetical'
293						},
294						{
295							match: [
296								'!/^bind:/u',
297								'!/^use:/u',
298								'!/^animate:/u',
299								'!/^style:/u',
300								'!/^in:/u',
301								'!/^out:/u',
302								'!/^transition:/u',
303								'!/^class:/u'
304							],
305							sort: 'alphabetical'
306						}
307					]
308				}
309			]
310		}
311	},
312	{
313		files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'],
314		languageOptions: {
315			parserOptions: {
316				extraFileExtensions: ['.svelte'],
317				parser: ts.parser,
318				projectService: true,
319				svelteConfig
320			}
321		}
322	},
323	{
324		// Exclude generated build output and Storybook files from ESLint
325		ignores: [
326			'dist/**',
327			'build/**',
328			'.svelte-kit/**',
329			'test-results/**',
330			'.storybook/**/*',
331			'src/lib/services/sandbox-worker.js',
332			'src/lib/vendors/**'
333		]
334	},
335	storybook.configs['flat/recommended']
336);