Skip to content

Commit efbc040

Browse files
committed
Improve markdown formatting and line length consistency in writing-rules.md
- Removed unnecessary markdownlint-disable comment - Fixed inconsistent indentation in nested lists (changed 2-space to 4-space indentation) - Wrapped long lines to improve readability - Added blank lines before nested lists for better markdown structure - Split long message template strings across multiple lines - Improved consistency in formatting throughout the document
1 parent dde0aee commit efbc040

1 file changed

Lines changed: 35 additions & 26 deletions

File tree

docs/writing-rules.md

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
<!-- markdownlint-disable -->
21
# Writing Linter Rules
32

43
This guide explains how to write custom linter rules for AGLint. AGLint uses a visitor pattern similar to ESLint,
@@ -78,21 +77,21 @@ The `meta` object contains information about the rule:
7877
### Required Fields
7978

8079
- **`type`**: One of:
81-
- `LinterRuleType.Problem` - Identifies code that will cause errors or confusing behavior
82-
- `LinterRuleType.Suggestion` - Identifies code that could be improved but isn't necessarily wrong
83-
- `LinterRuleType.Layout` - Concerns formatting and whitespace
80+
- `LinterRuleType.Problem` - Identifies code that will cause errors or confusing behavior
81+
- `LinterRuleType.Suggestion` - Identifies code that could be improved but isn't necessarily wrong
82+
- `LinterRuleType.Layout` - Concerns formatting and whitespace
8483

8584
- **`docs`**: Documentation object with:
86-
- `name` - The rule name (kebab-case)
87-
- `description` - Short description of what the rule checks
88-
- `recommended` - Whether the rule is enabled in the recommended config
89-
- `url` - (Optional) Link to full documentation
85+
- `name` - The rule name (kebab-case)
86+
- `description` - Short description of what the rule checks
87+
- `recommended` - Whether the rule is enabled in the recommended config
88+
- `url` - (Optional) Link to full documentation
9089

9190
### Optional Fields
9291

9392
- **`messages`**: Object mapping message IDs to template strings
94-
- Use `{{placeholder}}` syntax for dynamic values
95-
- Provides type-safe message references in `context.report()`
93+
- Use `{{placeholder}}` syntax for dynamic values
94+
- Provides type-safe message references in `context.report()`
9695

9796
- **`hasFix`**: Set to `true` if the rule can automatically fix problems
9897

@@ -120,7 +119,8 @@ export default defineRule({
120119
recommended: true,
121120
},
122121
messages: {
123-
tooShortRule: 'Rule is too short, its length is {{length}}, but at least {{minLength}} characters are required',
122+
tooShortRule: 'Rule is too short, its length is {{length}}, '
123+
+ 'but at least {{minLength}} characters are required',
124124
},
125125
configSchema: v.tuple([
126126
v.strictObject({
@@ -189,7 +189,8 @@ create: (context) => {
189189

190190
## Writing Visitors with Selectors
191191

192-
AGLint uses **esquery** for selecting AST nodes, similar to how CSS selectors work with DOM elements. The `create` function returns an object mapping selectors to visitor functions.
192+
AGLint uses **esquery** for selecting AST nodes, similar to how CSS selectors work with DOM elements.
193+
The `create` function returns an object mapping selectors to visitor functions.
193194

194195
### Exploring the AST
195196

@@ -198,13 +199,14 @@ To understand the structure of the AST and what node types are available, use th
198199
**[https://scripthunter7.github.io/agtree-astexplorer/](https://scripthunter7.github.io/agtree-astexplorer/)**
199200

200201
This interactive tool lets you:
202+
201203
- Input adblock filter rules and see their parsed AST
202204
- Explore node types, properties, and structure
203205
- Test selectors to see which nodes they match
204206
- Understand the hierarchy and relationships between nodes
205207

206-
For example, entering `example.com##.ad` shows you the `ElementHidingRule` node with its children,
207-
helping you write accurate selectors for your rules.
208+
For example, entering `example.com##.ad` shows you the `ElementHidingRule` node with its children, helping you
209+
write accurate selectors for your rules.
208210

209211
### Basic Node Type Selectors
210212

@@ -342,8 +344,10 @@ create: (context) => {
342344
Here are some frequently used node types in adblock filter rules:
343345

344346
- **Network Rules**: `NetworkRule`, `HostRule`
345-
- **Cosmetic Rules**: `CssInjectionRule`, `ElementHidingRule`, `ScriptletInjectionRule`, `HtmlFilteringRule`, `JsInjectionRule`
346-
- **Comment Rules**: `CommentRule`, `HintCommentRule`, `ConfigCommentRule`, `MetadataCommentRule`, `PreProcessorCommentRule`
347+
- **Cosmetic Rules**: `CssInjectionRule`, `ElementHidingRule`, `ScriptletInjectionRule`, `HtmlFilteringRule`,
348+
`JsInjectionRule`
349+
- **Comment Rules**: `CommentRule`, `HintCommentRule`, `ConfigCommentRule`, `MetadataCommentRule`,
350+
`PreProcessorCommentRule`
347351
- **CSS Selectors**: `SelectorList`, `Selector`, `PseudoClassSelector`, `AttributeSelector`
348352
- **Hints**: `Hint`, `HintValue`
349353
- **Others**: `Value`, `ParameterList`, `Modifier`, `ModifierList`
@@ -372,6 +376,7 @@ create: (context) => {
372376
```
373377

374378
Available helpers:
379+
375380
- `createVisitorsForAnyNetworkRule(handler)` - Network and host rules
376381
- `createVisitorsForAnyCosmeticRule(handler)` - All cosmetic rules
377382
- `createVisitorsForAnyCommentRule(handler)` - All comment rules
@@ -429,8 +434,8 @@ context.report({
429434
});
430435
```
431436

432-
**Note:** If a report contains both `messageId` and `message`, the (direct) `message` takes precedence. The `messageId` will be
433-
ignored in this case. However, you should never provide both in practice—choose one approach and stick with it.
437+
**Note:** If a report contains both `messageId` and `message`, the (direct) `message` takes precedence. The `messageId`
438+
will be ignored in this case. However, you should never provide both in practice—choose one approach and stick with it.
434439

435440
### With Custom Position
436441

@@ -479,16 +484,16 @@ export default defineRule({
479484
});
480485
```
481486

482-
**Important:** The `hasFix` property is mandatory for fixable rules. If you provide a `fix` function in `context.report()`
483-
without setting `meta.hasFix: true`, the linter will throw an error.
487+
**Important:** The `hasFix` property is mandatory for fixable rules. If you provide a `fix` function in
488+
`context.report()` without setting `meta.hasFix: true`, the linter will throw an error.
484489

485490
### Fixer Methods
486491

487492
The `fixer` object provides:
488493

489494
- **`replaceWithText(range, text)`**: Replace text at the given offset range
490-
- `range`: `[start, end]` offset array
491-
- `text`: New text to insert
495+
- `range`: `[start, end]` offset array
496+
- `text`: New text to insert
492497

493498
Example from `scriptlet-quotes` rule:
494499

@@ -545,8 +550,8 @@ export default defineRule({
545550
});
546551
```
547552

548-
**Important:** The `hasSuggestions` property is mandatory for rules that provide suggestions. If you provide a `suggest`
549-
array in `context.report()` without setting `meta.hasSuggestions: true`, the linter will throw an error.
553+
**Important:** The `hasSuggestions` property is mandatory for rules that provide suggestions. If you provide a
554+
`suggest` array in `context.report()` without setting `meta.hasSuggestions: true`, the linter will throw an error.
550555

551556
## Rule Configuration
552557

@@ -660,7 +665,8 @@ export default defineRule({
660665
recommended: true,
661666
},
662667
messages: {
663-
tooShortRule: 'Rule is too short, its length is {{length}}, but at least {{minLength}} characters are required',
668+
tooShortRule: 'Rule is too short, its length is {{length}}, '
669+
+ 'but at least {{minLength}} characters are required',
664670
},
665671
configSchema: v.tuple([
666672
v.strictObject({
@@ -1064,6 +1070,7 @@ fix(fixer) {
10641070
### 10. Test Thoroughly
10651071

10661072
Test various scenarios:
1073+
10671074
- Valid code that should pass
10681075
- Invalid code that should fail
10691076
- Edge cases (empty strings, special characters, etc.)
@@ -1079,11 +1086,13 @@ pnpm run rules:update
10791086
```
10801087

10811088
This script executes three tasks:
1089+
10821090
- **generate-rule-exports.ts** - Updates rule exports for the package
10831091
- **generate-rules-readme.ts** - Regenerates the rules documentation with up-to-date information
10841092
- **generate-presets.ts** - Updates preset configurations (e.g., recommended rules)
10851093

1086-
Running this script ensures that rule documentation, exports, and presets stay synchronized with your rule implementation.
1094+
Running this script ensures that rule documentation, exports, and presets stay synchronized with your rule
1095+
implementation.
10871096

10881097
## Additional Resources
10891098

0 commit comments

Comments
 (0)