Skip to content

Commit 4229354

Browse files
committed
docs: simplify README and improve readability
1 parent 940d8f2 commit 4229354

File tree

1 file changed

+65
-164
lines changed

1 file changed

+65
-164
lines changed

README.md

Lines changed: 65 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -11,202 +11,114 @@
1111
<a href="https://deepwiki.com/johnsoncodehk/tsslint"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
1212
</p>
1313

14-
TSSLint is probably the smallest linter implementation ever. Built on the TypeScript Language Server (`tsserver`), it provides a minimalist diagnostic extension interface with zero default rules, allowing developers to implement custom rules with minimal overhead.
14+
A linter that runs inside `tsserver`. No separate process, no re-parsing, no ESTree conversion. It uses the TypeChecker your editor already has.
1515

16-
## Motivation
16+
Zero built-in rules. You write what you need with the full TypeScript compiler API.
1717

18-
TSSLint is the **spiritual successor to TSLint**. We believe that **direct integration with native TypeScript APIs** is the most efficient way to lint TypeScript code.
18+
## Why?
1919

20-
General-purpose linters like ESLint, while powerful, operate as separate processes and often need to re-initialize type-checking context. This leads to a significant pain point in large-scale projects: **editor lag during "Auto Fix on Save"**.
20+
ESLint works, but it runs separately and sets up its own type-checking. On large projects, "Auto Fix on Save" gets laggy.
2121

22-
TSSLint solves this by running directly as a `tsserver` plugin. By sharing the existing `TypeChecker` and operating on the native TypeScript AST (without ESTree/ES parser conversion), TSSLint provides **near-instant diagnostics and fixes**.
23-
24-
## Key Features
25-
26-
* **Project-Centric**: Treats the **Project (tsconfig)** as a first-class citizen, enabling efficient cross-file type analysis and superior Monorepo support.
27-
* **High Performance**: Runs as a `tsserver` plugin, sharing the existing `TypeChecker` to provide near-instant diagnostics without redundant parsing.
28-
* **Minimalist Implementation**: Probably the smallest linter ever. Zero built-in rules and minimal code overhead by leveraging native TypeScript infrastructure.
29-
* **Rule Traceability**: Built-in debugging support. Jump from a reported error directly to the exact line in your **rule's source code** that triggered it.
30-
31-
## How It Works
32-
33-
TSSLint integrates into `tsserver` via the TypeScript plugin system, leveraging the semantic information already computed by your editor. Operating at the project level ensures accurate and performant diagnostics.
34-
35-
<p align="center">
36-
<img src="architecture.png" alt="TSSLint Architecture Diagram" width="700">
37-
</p>
38-
39-
### Framework Support (Vue, MDX, Astro, etc.)
40-
41-
Since TSSLint operates directly within `tsserver`, it supports any framework that integrates with the TypeScript plugin system.
42-
43-
Tools like **Vue Official (Volar)**, **MDX**, or **Astro** virtualize non-TypeScript files into virtual TypeScript source files for `tsserver`. TSSLint seamlessly accesses and lints the TypeScript code within these virtual files without any additional configuration.
22+
TSSLint avoids this by running as a `tsserver` plugin. It reuses the existing TypeChecker, works on native TypeScript AST, and skips the parser conversion layer.
4423

4524
<p align="center">
46-
<img src="architecture_v2.png" alt="TSSLint Framework Support Diagram" width="700">
25+
<img src="architecture.png" alt="TSSLint Architecture" width="700">
4726
</p>
4827

49-
## Getting Started
50-
51-
### 1. Install
28+
## Setup
5229

5330
```bash
5431
npm install @tsslint/config --save-dev
5532
```
5633

57-
### 2. Configure `tsslint.config.ts`
58-
59-
A minimal configuration looks like this. For a complete example, see the [vuejs/language-tools tsslint.config.ts](https://github.com/vuejs/language-tools/blob/master/tsslint.config.ts).
34+
Create `tsslint.config.ts`:
6035

6136
```ts
6237
import { defineConfig } from '@tsslint/config';
6338

6439
export default defineConfig({
6540
rules: {
66-
// Define or import your rules here
41+
// your rules here
6742
},
6843
});
6944
```
7045

71-
### 3. Editor Integration
72-
73-
* **VSCode**:
74-
1. Install the [TSSLint extension](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.vscode-tsslint).
75-
2. (Optional) If you encounter issues importing `tsslint.config.ts` due to Node.js version mismatches, you can configure `typescript.tsserver.nodePath` to point to a Node.js 23.6.0+ executable.
76-
* **Other Editors**: Configure TSSLint as a plugin in your `tsconfig.json`:
77-
```json
78-
{
79-
"compilerOptions": {
80-
"plugins": [{ "name": "@tsslint/typescript-plugin" }]
81-
}
82-
}
83-
```
46+
**VSCode**: Install the [TSSLint extension](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.vscode-tsslint).
8447

85-
## Rule Authoring
48+
**Other editors**: Add the plugin to `tsconfig.json`:
8649

87-
### Rule Example
50+
```json
51+
{
52+
"compilerOptions": {
53+
"plugins": [{ "name": "@tsslint/typescript-plugin" }]
54+
}
55+
}
56+
```
57+
58+
## Writing Rules
8859

8960
```ts
90-
// rules/no-debugger.ts
9161
import { defineRule } from '@tsslint/config';
9262

9363
export default defineRule(({ typescript: ts, file, report }) => {
9464
ts.forEachChild(file, function cb(node) {
9565
if (node.kind === ts.SyntaxKind.DebuggerStatement) {
96-
report(
97-
'Debugger statement is not allowed.',
98-
node.getStart(file),
99-
node.getEnd()
100-
);
66+
report('Debugger statement is not allowed.', node.getStart(file), node.getEnd());
10167
}
10268
ts.forEachChild(node, cb);
10369
});
10470
});
10571
```
10672

107-
### Rule Caching Mechanism
108-
109-
110-
TSSLint's high performance comes from its intelligent caching strategy, which automatically distinguishes between **Syntax-Aware** and **Type-Aware** rules.
111-
112-
All rule diagnostics are cached by default. The cache is automatically disabled for a rule in two scenarios:
73+
For a real-world example, see [vuejs/language-tools tsslint.config.ts](https://github.com/vuejs/language-tools/blob/master/tsslint.config.ts).
11374

114-
1. **Type-Aware Detection**: If a rule accesses `RuleContext.program` (e.g., to check types), TSSLint detects it as Type-Aware. The cache for this rule is then automatically managed and invalidated to ensure accuracy.
115-
2. **Manual Exclusion**: A rule can explicitly prevent a specific diagnostic from being cached by calling `report().withoutCache()`.
75+
### Caching
11676

117-
This automatic differentiation maximizes performance for simple syntax rules while maintaining correctness for complex type-aware rules.
77+
Diagnostics are cached by default. The cache invalidates automatically when:
11878

119-
### Rule Debugging & Traceability (The `.at()` Magic)
79+
1. A rule accesses `RuleContext.program` (type-aware rules)
80+
2. A rule calls `report().withoutCache()`
12081

121-
TSSLint is designed to make rule debugging trivial. Every time you call `report()`, TSSLint automatically captures the current JavaScript stack trace and attaches it to the diagnostic as **Related Information**.
82+
### Debugging
12283

123-
This means: **You can click on the diagnostic in your editor and jump directly to the line in your rule's source code that triggered the report.**
84+
Every `report()` captures a stack trace. Click the diagnostic in your editor to jump to the exact line in your rule that triggered it.
12485

12586
<p align="center">
126-
<img src="traceability.png" alt="TSSLint Rule Traceability Demo" width="700">
87+
<img src="traceability.png" alt="Rule Traceability" width="700">
12788
</p>
12889

129-
The `.at()` method is generally not needed, but is provided for advanced scenarios where you wrap `report()` in a helper function and need to adjust the stack depth to point to the correct logic:
130-
131-
```ts
132-
// Example of advanced usage to adjust stack depth
133-
report('message', start, end)
134-
.at(new Error(), 2) // Adjusts the stack index to skip the helper function's frame
135-
.withFix(...);
136-
```
137-
138-
## CLI Usage
139-
140-
The `@tsslint/cli` package provides a command-line tool for CI/CD and build processes.
90+
## CLI
14191

14292
```bash
143-
# Lint a project
144-
npx tsslint --project path/to/tsconfig.json
145-
146-
# Auto-fix violations
147-
npx tsslint --project path/to/tsconfig.json --fix
148-
149-
# Lint multiple projects
150-
npx tsslint --project packages/*/tsconfig.json --vue-project apps/web/tsconfig.json
151-
152-
# Using brace expansion for multiple patterns
153-
npx tsslint --project {tsconfig.json,packages/*/tsconfig.json,extensions/*/tsconfig.json}
93+
npx tsslint --project tsconfig.json
94+
npx tsslint --project tsconfig.json --fix
95+
npx tsslint --project packages/*/tsconfig.json
15496
```
15597

156-
> [!TIP]
157-
> TSSLint focuses on diagnostic fixes and does not include a built-in formatter. It is recommended to run a dedicated formatter like **Prettier**, **dprint**, or **oxfmt** after running TSSLint with `--fix`.
158-
159-
## Extensions & Ecosystem
98+
Run `npx tsslint --help` for all options.
16099

161-
### Ignoring Rules
162-
```ts
163-
import { defineConfig, createIgnorePlugin } from '@tsslint/config';
100+
TSSLint only does diagnostics and fixes. Run Prettier or dprint after `--fix`.
164101

165-
export default defineConfig({
166-
rules: {
167-
...
168-
},
169-
plugins: [
170-
createIgnorePlugin('tsslint-ignore', true)
171-
],
172-
});
173-
```
174-
*Usage: Use `// tsslint-ignore` comments in your code.*
102+
## Framework Support
175103

176-
### Ecosystem Integration
104+
TSSLint works with Vue, MDX, Astro, and anything else that plugs into tsserver. These tools virtualize their files as TypeScript for tsserver. TSSLint just sees and lints that TypeScript.
177105

178-
TSSLint provides compatibility layers for existing linter ecosystems (ESLint, TSLint, and TSL). These integrations are coordinated through `@tsslint/config`, which acts as a bridge to load rules from other linters.
179-
180-
To use a compatibility layer, you must install the corresponding TSSLint compatibility package. If you wish to use the original linter's built-in rules, you must also install the original linter package itself.
106+
<p align="center">
107+
<img src="architecture_v2.png" alt="Framework Support" width="700">
108+
</p>
181109

182-
#### 1. ESLint
110+
## Using ESLint/TSLint Rules
183111

184-
**Installation:**
112+
You can load rules from ESLint and TSLint through compatibility layers.
185113

186-
First, install the TSSLint compatibility package for ESLint.
114+
### ESLint
187115

188116
```bash
189117
npm install @tsslint/compat-eslint --save-dev
118+
npm install eslint --save-dev # optional, for built-in rules
119+
npx tsslint-docgen # generates JSDoc for IDE support
190120
```
191121

192-
If you want to use ESLint's built-in rules (e.g., `no-unused-vars`), you must also install `eslint` (optional):
193-
194-
```bash
195-
npm install eslint --save-dev
196-
```
197-
198-
**Type Definition Update:**
199-
200-
After installing the original linter package, run the following command to update JSDoc for built-in rules, enabling better IDE support:
201-
202-
```bash
203-
npx tsslint-docgen
204-
```
205-
206-
**Usage in `tsslint.config.ts`:**
207-
208-
Use `importESLintRules` to load rules. This function automatically resolves and loads rules from ESLint plugins (e.g., `@typescript-eslint/eslint-plugin`) by searching your `node_modules`. Plugin rules are identified by their prefix (e.g., `@typescript-eslint/`).
209-
210122
```ts
211123
import { defineConfig, importESLintRules } from '@tsslint/config';
212124

@@ -220,68 +132,57 @@ export default defineConfig({
220132
});
221133
```
222134

223-
#### 2. TSLint
224-
225-
**Installation:**
226-
227-
If you want to use TSLint's built-in rules, you need to install `tslint` (optional):
228-
229-
```bash
230-
npm install tslint --save-dev
231-
```
232-
233-
**Type Definition Update:**
234-
235-
After installing `tslint`, run the following command to update JSDoc for built-in rules:
135+
### TSLint
236136

237137
```bash
138+
npm install tslint --save-dev # optional, for built-in rules
238139
npx tsslint-docgen
239140
```
240141

241-
**Usage in `tsslint.config.ts`:**
242-
243-
Use `importTSLintRules` to load rules. This function automatically reads `rulesDirectory` from your `tslint.json` to support third-party TSLint plugins.
244-
245142
```ts
246143
import { defineConfig, importTSLintRules } from '@tsslint/config';
247144

248145
export default defineConfig({
249146
rules: {
250147
...await importTSLintRules({
251148
'no-console': true,
252-
'member-ordering': [true, { order: 'fields-first' }],
253149
}),
254150
},
255151
});
256152
```
257153

258-
#### 3. TSL
259-
260-
**Installation:**
261-
262-
TSL rules are imported directly from the `tsl` package.
154+
### TSL
263155

264156
```bash
265157
npm install tsl --save-dev
266158
```
267159

268-
**Usage in `tsslint.config.ts`:**
269-
270-
Use `fromTSLRules` to load TSL rules.
271-
272160
```ts
273161
import { defineConfig, fromTSLRules } from '@tsslint/config';
274162
import { core } from 'tsl';
275163

276164
export default defineConfig({
277-
rules: fromTSLRules(core.all()),
165+
rules: fromTSLRules(core.all()),
278166
});
279167
```
280168

281-
## Technical Notes
169+
## Ignoring Rules
170+
171+
```ts
172+
import { defineConfig, createIgnorePlugin } from '@tsslint/config';
173+
174+
export default defineConfig({
175+
rules: { ... },
176+
plugins: [createIgnorePlugin('tsslint-ignore', true)],
177+
});
178+
```
179+
180+
Then use `// tsslint-ignore` comments in your code.
181+
182+
## Notes
282183

283-
* **Node.js**: Requires 22.6.0+ (v3.0+).
284-
* **TypeScript**: Incompatible with `typescript-go` (v7) as it does not support Language Service Plugins.
184+
- Requires Node.js 22.6.0+
185+
- Not compatible with typescript-go (v7) - it doesn't support Language Service Plugins
285186

286187
## License
287188

0 commit comments

Comments
 (0)