@gost-kit/eslint-config-svelte 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @gost-kit/eslint-config-svelte
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 11af11e: Introduce an independently versioned Svelte 5 ESLint configuration with the
8
+ shared JavaScript/TypeScript baseline and explicit component/rune policies.
9
+
10
+ ### Patch Changes
11
+
12
+ - Updated dependencies [656024a]
13
+ - @gost-kit/eslint-config@0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anton Smolko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,97 @@
1
- # Temporary Holding Version
1
+ # @gost-kit/eslint-config-svelte
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Shared Svelte 5 ESLint configuration, including the complete
4
+ `@gost-kit/eslint-config` JavaScript/TypeScript baseline. Independently versioned;
5
+ consult package.json and CHANGELOG.md for the version. Install alongside
6
+ the required peer dependencies.
7
+
8
+ Requires Node ^26.0.0, ESLint ^10.14.0, TypeScript ^5.9.3 and Svelte ^5.57.2.
9
+ The pinned tested combination uses ESLint 10.14.0, TypeScript 5.9.3, Svelte
10
+ 5.57.2, eslint-plugin-svelte 3.24.0 and svelte-eslint-parser 1.10.1.
11
+
12
+ ## Usage
13
+
14
+ Install this package, ESLint, TypeScript and Svelte as development dependencies.
15
+ The common config comes through this package's dependency. In `eslint.config.mjs`:
16
+
17
+ ```js
18
+ import { createSvelteConfig } from '@gost-kit/eslint-config-svelte';
19
+ import globals from 'globals';
20
+
21
+ export default [
22
+ ...(await createSvelteConfig({ tsconfigRootDir: import.meta.dirname })),
23
+ {
24
+ files: ['src/**/*.ts', 'src/**/*.svelte'],
25
+ languageOptions: { globals: globals.browser },
26
+ },
27
+ ];
28
+ ```
29
+
30
+ Install `globals` explicitly if using it. The root must be an absolute consumer
31
+ project path. Supply a tsconfig covering authored TypeScript and Svelte files.
32
+ Type-aware checks report missing/incompatible projects; plain JavaScript does
33
+ not require a tsconfig. Component scripts use TypeScript (`lang="ts"`); components
34
+ without a script are permitted. TS/JS rune modules are supported. Globals are
35
+ not supplied for browser, Node or test environments: scope them in the consumer.
36
+
37
+ The asynchronous factory calculates the shared TypeScript policy using public
38
+ ESLint APIs. It writes no files, invokes no application code and does not require
39
+ a placeholder source file. Config/compiler options remain consumer overrides,
40
+ for example `languageOptions.parserOptions.svelteConfig` for component files.
41
+ Do not append the common factory again: it is already included.
42
+
43
+ ## Rules and boundaries
44
+
45
+ The [Svelte rule inventory](RULES.md) records every enabled framework rule and
46
+ its options. The [shared inventory](../eslint-config/RULES.md) describes inherited
47
+ JS/TS checks; in an installed package consult the README/RULES of
48
+ `@gost-kit/eslint-config`. All enabled checks are errors, including in tests.
49
+ No blanket test exception or SvelteKit-only rule set is enabled.
50
+
51
+ Keys are required for each blocks, but upstream `valid-each-key` does not prove
52
+ uniqueness/stability or ban index keys. `no-unused-props` supports spread/forwarding;
53
+ fixtures verify that forwarding declared props does not produce false positives.
54
+ Simple derived suggestions do not establish equivalence of arbitrary effects.
55
+ The `no-ignored-unsubscribe` check is syntactic: an ignored direct `.subscribe()`
56
+ call is reported even when it belongs to another API with that method name.
57
+ Use a documented targeted exception when that API needs no cleanup; the rule does
58
+ not establish actual cleanup/lifecycle correctness. `no-store-async` concerns
59
+ standard Svelte store callbacks, not application API effects.
60
+
61
+ Framework-independent correctness, arrow bodies, imports and spacing apply inside
62
+ component scripts. Svelte formatting is delegated to Prettier; this config does
63
+ not execute the formatter. Use `@gost-kit/prettier-config` with
64
+ `prettier-plugin-svelte` in the consuming project's Prettier config.
65
+
66
+ Architecture policies are separate work: component state ownership (#16),
67
+ UI dispatch (#17), boolean conditions (#18), derived calculations (#19) and
68
+ feature-state selection (#6). This package does not claim to enforce those
69
+ contracts yet. Existing `$state.raw` shell bindings and feature selectors remain
70
+ valid; the Svelte compiler/type checker still verifies compilation/accessibility.
71
+
72
+ ## Overrides and verification
73
+
74
+ Append project overrides after the factory result:
75
+
76
+ ```js
77
+ {
78
+ files: ['src/content/RichText.svelte'],
79
+ rules: { 'svelte/no-at-html-tags': 'off' },
80
+ }
81
+ ```
82
+
83
+ An HTML exception still needs a trusted/sanitized source. The rule itself bans
84
+ syntax and does not validate a sanitizer. Keep formatter and linter separate:
85
+
86
+ ```sh
87
+ eslint . --fix
88
+ prettier . --write
89
+ eslint . --max-warnings=0
90
+ prettier . --check
91
+ ```
92
+
93
+ Some lint errors require manual changes. Upgrade deliberately: inspect changes
94
+ in both inherited common policies and the Svelte inventory, run type/component
95
+ checks and tests, and review any output diff. Configuration releases remain
96
+ independent of runtime package versions. Tests and helper fixtures are excluded
97
+ from package artifacts; Svelte is a peer, not an automatically selected UI framework.
package/RULES.md ADDED
@@ -0,0 +1,46 @@
1
+ # Svelte rule inventory
2
+
3
+ Pinned baseline: eslint-plugin-svelte 3.24.0, svelte-eslint-parser 1.10.1,
4
+ Svelte 5.57.2. All selected rules are errors on components and rune modules.
5
+ Common JS/TS policies are inherited, not duplicated here.
6
+
7
+ | Policy | Rule | Level/options |
8
+ | ------ | ---------------------------------------------- | ---------------------------------------------------------- |
9
+ | S01 | `svelte/no-dupe-else-if-blocks` | `["error"]` |
10
+ | S02 | `svelte/no-not-function-handler` | `["error"]` |
11
+ | S03 | `svelte/no-object-in-text-mustaches` | `["error"]` |
12
+ | S04 | `svelte/require-each-key` | `["error"]` |
13
+ | S04 | `svelte/valid-each-key` | `["error"]` |
14
+ | S05 | `svelte/button-has-type` | `["error"]` |
15
+ | S06 | `svelte/no-bind-value-on-checkable-inputs` | `["error"]` |
16
+ | S07 | `svelte/no-dupe-style-properties` | `["error"]` |
17
+ | S07 | `svelte/no-shorthand-style-property-overrides` | `["error"]` |
18
+ | S07 | `svelte/no-unknown-style-directive-property` | `["error"]` |
19
+ | S08 | `svelte/no-conflicting-module-names` | `["error"]` |
20
+ | S09 | `svelte/no-svelte-internal` | `["error"]` |
21
+ | S10 | `svelte/no-at-debug-tags` | `["error"]` |
22
+ | S10 | `svelte/no-inspect` | `["error"]` |
23
+ | S11 | `svelte/no-unused-svelte-ignore` | `["error"]` |
24
+ | S11 | `svelte/no-unused-props` | `["error"]` |
25
+ | S12 | `svelte/no-unnecessary-state-wrap` | `["error"]` |
26
+ | S13 | `svelte/prefer-derived-over-derived-by` | `["error"]` |
27
+ | S14 | `svelte/prefer-writable-derived` | `["error"]` |
28
+ | AS01 | `svelte/no-at-html-tags` | `["error"]` |
29
+ | AS02 | `svelte/block-lang` | `["error", {"script":"ts", "enforceScriptPresent":false}]` |
30
+ | AS03 | `svelte/no-store-async` | `["error"]` |
31
+ | AS03 | `svelte/no-ignored-unsubscribe` | `["error"]` |
32
+
33
+ Infrastructure rules `svelte/comment-directive` and `svelte/system` are inherited
34
+ from Svelte base. The base and Prettier compatibility layers do not implicitly
35
+ activate the recommended Svelte/Kit policy set. Ordinary JS/TS files keep the
36
+ common baseline; selected framework rules target `**/*.svelte`, `**/*.svelte.ts`
37
+ and `**/*.svelte.js` where the upstream rule supports the corresponding syntax.
38
+
39
+ Not enabled: AS04 DOM/listener restrictions, AS05 SSR browser-global restrictions,
40
+ AS06 prefer-svelte-reactivity, legacy recommended/experimental rules and SvelteKit
41
+ routing rules. Prettier owns HTML/CSS formatting. Custom architecture checks #6
42
+ and #16–#19 are separate outcomes and are not bundled here.
43
+
44
+ Sources: [rule catalog](https://sveltejs.github.io/eslint-plugin-svelte/rules/),
45
+ [configuration boundaries](https://sveltejs.github.io/eslint-plugin-svelte/user-guide/).
46
+ Recalculate configs and review selected/inherited rule changes when upgrading.
@@ -0,0 +1,3 @@
1
+ import { type Linter } from 'eslint';
2
+ import { type ConfigOptions } from '@gost-kit/eslint-config';
3
+ export declare const createSvelteConfig: ({ tsconfigRootDir, }: ConfigOptions) => Promise<Linter.Config[]>;
@@ -0,0 +1,53 @@
1
+ import { ESLint } from 'eslint';
2
+ import { createConfig } from '@gost-kit/eslint-config';
3
+ import svelte from 'eslint-plugin-svelte';
4
+ import ts from 'typescript-eslint';
5
+ import { join } from 'node:path';
6
+ import { svelteRules } from './rules.js';
7
+ export const createSvelteConfig = async ({ tsconfigRootDir, }) => {
8
+ const shared = createConfig({ tsconfigRootDir });
9
+ const eslint = new ESLint({
10
+ cwd: tsconfigRootDir,
11
+ overrideConfigFile: true,
12
+ overrideConfig: shared,
13
+ });
14
+ const policy = await eslint.calculateConfigForFile(join(tsconfigRootDir, '__gost_svelte_policy__.ts'));
15
+ return [
16
+ { name: 'gost-svelte/ignores', ignores: ['**/.svelte-kit/**'] },
17
+ ...shared,
18
+ ...svelte.configs.base,
19
+ ...svelte.configs.prettier,
20
+ {
21
+ name: 'gost-svelte/typescript-project',
22
+ files: ['**/*.{ts,mts,cts}', '**/*.svelte'],
23
+ languageOptions: { parserOptions: { extraFileExtensions: ['.svelte'] } },
24
+ },
25
+ {
26
+ name: 'gost-svelte/typescript-runes',
27
+ files: ['**/*.svelte.ts'],
28
+ languageOptions: { parser: ts.parser },
29
+ },
30
+ {
31
+ name: 'gost-svelte/component-typescript',
32
+ files: ['**/*.svelte'],
33
+ plugins: Object.fromEntries(Object.entries(policy.plugins ?? {}).filter(([name]) => {
34
+ // ESLint owns this plugin; distinct consumer instances have different identities.
35
+ return name !== '@';
36
+ })),
37
+ rules: policy.rules,
38
+ languageOptions: {
39
+ parserOptions: {
40
+ parser: ts.parser,
41
+ projectService: true,
42
+ tsconfigRootDir,
43
+ extraFileExtensions: ['.svelte'],
44
+ },
45
+ },
46
+ },
47
+ {
48
+ name: 'gost-svelte/selected-rules',
49
+ files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'],
50
+ rules: svelteRules,
51
+ },
52
+ ];
53
+ };
@@ -0,0 +1,2 @@
1
+ export { createSvelteConfig } from './create-svelte-config.js';
2
+ export type { ConfigOptions } from '@gost-kit/eslint-config';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { createSvelteConfig } from './create-svelte-config.js';
@@ -0,0 +1,28 @@
1
+ export declare const svelteRules: {
2
+ 'svelte/no-dupe-else-if-blocks': "error";
3
+ 'svelte/no-not-function-handler': "error";
4
+ 'svelte/no-object-in-text-mustaches': "error";
5
+ 'svelte/require-each-key': "error";
6
+ 'svelte/valid-each-key': "error";
7
+ 'svelte/button-has-type': "error";
8
+ 'svelte/no-bind-value-on-checkable-inputs': "error";
9
+ 'svelte/no-dupe-style-properties': "error";
10
+ 'svelte/no-shorthand-style-property-overrides': "error";
11
+ 'svelte/no-unknown-style-directive-property': "error";
12
+ 'svelte/no-conflicting-module-names': "error";
13
+ 'svelte/no-svelte-internal': "error";
14
+ 'svelte/no-at-debug-tags': "error";
15
+ 'svelte/no-inspect': "error";
16
+ 'svelte/no-unused-svelte-ignore': "error";
17
+ 'svelte/no-unused-props': "error";
18
+ 'svelte/no-unnecessary-state-wrap': "error";
19
+ 'svelte/prefer-derived-over-derived-by': "error";
20
+ 'svelte/prefer-writable-derived': "error";
21
+ 'svelte/no-at-html-tags': "error";
22
+ 'svelte/block-lang': ["error", {
23
+ script: string;
24
+ enforceScriptPresent: boolean;
25
+ }];
26
+ 'svelte/no-store-async': "error";
27
+ 'svelte/no-ignored-unsubscribe': "error";
28
+ };
package/dist/rules.js ADDED
@@ -0,0 +1,25 @@
1
+ export const svelteRules = {
2
+ 'svelte/no-dupe-else-if-blocks': 'error',
3
+ 'svelte/no-not-function-handler': 'error',
4
+ 'svelte/no-object-in-text-mustaches': 'error',
5
+ 'svelte/require-each-key': 'error',
6
+ 'svelte/valid-each-key': 'error',
7
+ 'svelte/button-has-type': 'error',
8
+ 'svelte/no-bind-value-on-checkable-inputs': 'error',
9
+ 'svelte/no-dupe-style-properties': 'error',
10
+ 'svelte/no-shorthand-style-property-overrides': 'error',
11
+ 'svelte/no-unknown-style-directive-property': 'error',
12
+ 'svelte/no-conflicting-module-names': 'error',
13
+ 'svelte/no-svelte-internal': 'error',
14
+ 'svelte/no-at-debug-tags': 'error',
15
+ 'svelte/no-inspect': 'error',
16
+ 'svelte/no-unused-svelte-ignore': 'error',
17
+ 'svelte/no-unused-props': 'error',
18
+ 'svelte/no-unnecessary-state-wrap': 'error',
19
+ 'svelte/prefer-derived-over-derived-by': 'error',
20
+ 'svelte/prefer-writable-derived': 'error',
21
+ 'svelte/no-at-html-tags': 'error',
22
+ 'svelte/block-lang': ['error', { script: 'ts', enforceScriptPresent: false }],
23
+ 'svelte/no-store-async': 'error',
24
+ 'svelte/no-ignored-unsubscribe': 'error',
25
+ };
package/package.json CHANGED
@@ -1,6 +1,59 @@
1
1
  {
2
2
  "name": "@gost-kit/eslint-config-svelte",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Shared Svelte 5 ESLint configuration with the GOST JavaScript and TypeScript baseline.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "engines": {
8
+ "node": "^26.0.0"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "CHANGELOG.md",
13
+ "RULES.md"
14
+ ],
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js",
19
+ "default": "./dist/index.js"
20
+ }
21
+ },
22
+ "scripts": {
23
+ "build": "npm run clean && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json",
24
+ "check": "tsc -p tsconfig.json",
25
+ "test": "vitest run",
26
+ "prepack": "npm run build",
27
+ "clean": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true });\""
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/antonsmolko/gost-kit.git",
32
+ "directory": "packages/eslint-config-svelte"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "26.6.5",
39
+ "typescript": "5.9.3",
40
+ "tsc-alias": "1.9.9",
41
+ "vitest": "5.0.5",
42
+ "eslint": "10.14.0",
43
+ "prettier": "3.9.10",
44
+ "@gost-kit/prettier-config": "0.1.0",
45
+ "svelte": "5.57.2",
46
+ "prettier-plugin-svelte": "4.1.1"
47
+ },
48
+ "dependencies": {
49
+ "@gost-kit/eslint-config": "0.1.0",
50
+ "eslint-plugin-svelte": "3.24.0",
51
+ "svelte-eslint-parser": "1.10.1",
52
+ "typescript-eslint": "8.72.1"
53
+ },
54
+ "peerDependencies": {
55
+ "eslint": "^10.14.0",
56
+ "typescript": "^5.9.3",
57
+ "svelte": "^5.57.2"
58
+ }
59
+ }