Skip to content

Commit d28ce54

Browse files
a-tokyoclaude
andcommitted
feat(eslint): exempt .d.ts from no-var/vars-on-top (ambient globalThis typing) — 0.1.1
Ambient `declare var X` is the only construct that augments `typeof globalThis` (const/let don't merge; an interface Window augmentation types window.X not globalThis.X, which unicorn/prefer-global-this steers toward). no-var/vars-on-top therefore only ever false-positive on .d.ts; a new declarationFileOverrides() block (appended last in every preset, before consumer overrides) turns them off for **/*.d.ts. Consuming projects (e.g. fluxo) can drop their local .d.ts override. Tests 11/11, self-lint + format clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent fa15f26 commit d28ce54

9 files changed

Lines changed: 62 additions & 11 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Sonar issues before they reach CI. Five stack presets — **plain JS/TS**, **Rea
2929
Distributed via GitHub URL, pinned to a tag (no build step runs on install — raw ESM):
3030

3131
```bash
32-
npm i -D "github:zoldytech/javascript#v0.1.0"
32+
npm i -D "github:zoldytech/javascript#0.1.1"
3333
```
3434

3535
## Usage

docs/react-native.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ with no extra ESLint config:
4949
**Native-only** projects (no web target) can drop the DOM lib to catch
5050
accidental DOM usage on native, by overriding `lib` in their own tsconfig:
5151
`"compilerOptions": { "lib": ["ES2022"] }`.
52+
5253
- The bundler alias (`react-native$``react-native-web`) is a build-tool concern
5354
(webpack/Metro/Vite), out of scope for this package.
5455

@@ -63,11 +64,11 @@ which this package requires (peer `eslint >=10.4`).
6364

6465
**Verified against ESLint 10.7 (2026-07):**
6566

66-
| Rule | Status on ESLint 10 |
67-
| --- | --- |
67+
| Rule | Status on ESLint 10 |
68+
| -------------------------------------------------------------------------- | ----------------------------------------------------------------- |
6869
| `no-unused-styles`, `no-inline-styles`, `no-color-literals`, `sort-styles` | **crash** — call `context.getSourceCode()` (removed in ESLint 10) |
69-
| `split-platform-components` | **crash** — calls `context.getFilename()` (removed in ESLint 10) |
70-
| `no-raw-text`, `no-single-element-style-arrays` | load but are the least useful rules |
70+
| `split-platform-components` | **crash** — calls `context.getFilename()` (removed in ESLint 10) |
71+
| `no-raw-text`, `no-single-element-style-arrays` | load but are the least useful rules |
7172

7273
`eslint-plugin-react-native@5.0.0` is the latest release and declares peer
7374
`eslint ^3 … ^9`. `@react-native/eslint-plugin` ships no style rules
@@ -114,6 +115,7 @@ When `eslint-plugin-react-native` publishes an ESLint-10-compatible release (dro
114115
```
115116

116117
(Omit `sort-styles` — pure ordering, Prettier's domain.)
118+
117119
3. Add a `dirty.tsx` case to `test/fixtures/react-native/` that trips a couple of
118120
the style rules and extend the `presetSuite('react-native', …)` expected-rules
119121
list in `test/presets.test.js` accordingly.

eslint/_shared.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,23 @@ export function sonarTestOff(testGlobs = DEFAULT_TEST_GLOBS) {
140140
export function antfuTypescript({ typeChecked = false, tsconfigPath = 'tsconfig.json' } = {}) {
141141
return typeChecked ? { tsconfigPath } : true;
142142
}
143+
144+
/**
145+
* Declaration-file (.d.ts) overrides. A `.d.ts` can only carry ambient `declare var` for
146+
* `globalThis` augmentation — TypeScript does NOT merge `const`/`let` into `typeof globalThis`,
147+
* and an `interface Window` augmentation types `window.X`, not `globalThis.X` (which
148+
* unicorn/prefer-global-this steers code toward). So `no-var`/`vars-on-top` can only ever
149+
* false-positive on ambient declarations; turn them off for `.d.ts`. Appended last in each
150+
* preset so it wins over antfu/sonar, before the consumer's own `overrides`.
151+
* @returns {import('eslint').Linter.Config} the `.d.ts` override block (no-var/vars-on-top off).
152+
*/
153+
export function declarationFileOverrides() {
154+
return {
155+
name: 'zoldytech/declaration-files',
156+
files: ['**/*.d.ts'],
157+
rules: {
158+
'no-var': 'off',
159+
'vars-on-top': 'off',
160+
},
161+
};
162+
}

eslint/base.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import antfu from '@antfu/eslint-config';
66
import prettier from 'eslint-config-prettier/flat';
7-
import { antfuTypescript, sonarLayer, sonarTestOff } from './_shared.js';
7+
import { antfuTypescript, declarationFileOverrides, sonarLayer, sonarTestOff } from './_shared.js';
88

99
/**
1010
* @typedef {object} BaseOptions
@@ -47,6 +47,7 @@ export function base(options = {}) {
4747
...sonarLayer({ tsdoc }),
4848
sonarTestOff(testGlobs),
4949
prettier,
50+
declarationFileOverrides(),
5051
...overrides
5152
);
5253
}

eslint/nest.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44

55
import antfu from '@antfu/eslint-config';
66
import prettier from 'eslint-config-prettier/flat';
7-
import { antfuTypescript, sonarLayer, sonarTestOff, TS_GLOBS } from './_shared.js';
7+
import {
8+
antfuTypescript,
9+
declarationFileOverrides,
10+
sonarLayer,
11+
sonarTestOff,
12+
TS_GLOBS,
13+
} from './_shared.js';
814

915
/**
1016
* @typedef {object} NestOptions
@@ -69,6 +75,7 @@ export function nest(options = {}) {
6975
...nestRules,
7076
sonarTestOff(testGlobs),
7177
prettier,
78+
declarationFileOverrides(),
7279
...overrides
7380
);
7481
}

eslint/next.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
import antfu from '@antfu/eslint-config';
77
import nextPlugin from '@next/eslint-plugin-next';
88
import prettier from 'eslint-config-prettier/flat';
9-
import { antfuTypescript, sonarLayer, sonarReactRules, sonarTestOff } from './_shared.js';
9+
import {
10+
antfuTypescript,
11+
declarationFileOverrides,
12+
sonarLayer,
13+
sonarReactRules,
14+
sonarTestOff,
15+
} from './_shared.js';
1016

1117
/**
1218
* Flat-config block registering @next/eslint-plugin-next with its core-web-vitals
@@ -61,6 +67,7 @@ export function next(options = {}) {
6167
sonarReactRules(),
6268
sonarTestOff(testGlobs),
6369
prettier,
70+
declarationFileOverrides(),
6471
...overrides
6572
);
6673
}

eslint/react-native.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515

1616
import antfu from '@antfu/eslint-config';
1717
import prettier from 'eslint-config-prettier/flat';
18-
import { antfuTypescript, sonarLayer, sonarReactRules, sonarTestOff } from './_shared.js';
18+
import {
19+
antfuTypescript,
20+
declarationFileOverrides,
21+
sonarLayer,
22+
sonarReactRules,
23+
sonarTestOff,
24+
} from './_shared.js';
1925

2026
/**
2127
* RN runtime globals that antfu's browser+node globals don't already cover.
@@ -74,6 +80,7 @@ export function reactNative(options = {}) {
7480
sonarReactRules(),
7581
sonarTestOff(testGlobs),
7682
prettier,
83+
declarationFileOverrides(),
7784
...overrides
7885
);
7986
}

eslint/react.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44

55
import antfu from '@antfu/eslint-config';
66
import prettier from 'eslint-config-prettier/flat';
7-
import { antfuTypescript, sonarLayer, sonarReactRules, sonarTestOff } from './_shared.js';
7+
import {
8+
antfuTypescript,
9+
declarationFileOverrides,
10+
sonarLayer,
11+
sonarReactRules,
12+
sonarTestOff,
13+
} from './_shared.js';
814

915
/**
1016
* @typedef {object} ReactOptions
@@ -45,6 +51,7 @@ export function react(options = {}) {
4551
sonarReactRules(),
4652
sonarTestOff(testGlobs),
4753
prettier,
54+
declarationFileOverrides(),
4855
...overrides
4956
);
5057
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@zoldytech/javascript",
33
"type": "module",
4-
"version": "0.1.0",
4+
"version": "0.1.1",
55
"private": true,
66
"description": "Zoldytech's JavaScript/TypeScript standards: SonarQube-compatible ESLint presets (Next.js, NestJS, React+Vite, plain JS/TS) plus shared Prettier and tsconfig configs.",
77
"license": "MIT",

0 commit comments

Comments
 (0)