Skip to content

Commit 8f0db65

Browse files
authored
Merge pull request #160
feat: allow i, j, k as idiomatic variable names (v0.7.11)
2 parents fe2ab27 + 2f03578 commit 8f0db65

File tree

5 files changed

+93
-2
lines changed

5 files changed

+93
-2
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
## [0.7.11] - 2025-07-02
8+
9+
### Changed
10+
11+
- **unicorn/prevent-abbreviations**: Allow `i`, `j`, `k` as idiomatic variable names
12+
for loop counters and array indices
13+
714
## [0.7.10] - 2025-07-02
815

916
### Documentation

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ custom rules:
227227
### General JavaScript Rules
228228

229229
* Enforces camelCase naming convention
230+
* Allows `i`, `j`, `k` as loop counters and array indices
230231
* Requires explicit radix in `parseInt`
231232
* Prevents console statements in production code
232233

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@poupe/eslint-config",
3-
"version": "0.7.10",
3+
"version": "0.7.11",
44
"type": "module",
55
"description": "Sharable ESLint configuration preset for Poupe UI projects with TypeScript, Vue.js, and Tailwind CSS support",
66
"author": "Alejandro Mery <[email protected]>",
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { poupeUnicornRules } from '../unicorn';
4+
5+
interface PreventAbbreviationsOptions {
6+
allowList: Record<string, boolean>
7+
replacements: Record<string, boolean | string | string[]>
8+
}
9+
10+
interface FilenameCaseOptions {
11+
case: string
12+
ignore?: string[]
13+
}
14+
15+
describe('unicorn configuration', () => {
16+
describe('prevent-abbreviations rule', () => {
17+
it('should have correct configuration', () => {
18+
const rule = poupeUnicornRules['unicorn/prevent-abbreviations'];
19+
expect(rule).toBeDefined();
20+
expect(Array.isArray(rule)).toBe(true);
21+
if (Array.isArray(rule)) {
22+
expect(rule[0]).toBe('error');
23+
}
24+
});
25+
26+
it('should allow i, j, k as variable names', () => {
27+
const rule = poupeUnicornRules['unicorn/prevent-abbreviations'];
28+
expect(Array.isArray(rule)).toBe(true);
29+
if (Array.isArray(rule) && rule.length > 1) {
30+
const options = rule[1] as PreventAbbreviationsOptions;
31+
expect(options.allowList).toBeDefined();
32+
expect(options.allowList.i).toBe(true);
33+
expect(options.allowList.j).toBe(true);
34+
expect(options.allowList.k).toBe(true);
35+
}
36+
});
37+
38+
it('should not suggest replacements for i, j, k', () => {
39+
const rule = poupeUnicornRules['unicorn/prevent-abbreviations'];
40+
expect(Array.isArray(rule)).toBe(true);
41+
if (Array.isArray(rule) && rule.length > 1) {
42+
const options = rule[1] as PreventAbbreviationsOptions;
43+
expect(options.replacements).toBeDefined();
44+
// i, j, k should not be in replacements object since they're in omitReplacementList
45+
expect(options.replacements.i).toBeUndefined();
46+
expect(options.replacements.j).toBeUndefined();
47+
expect(options.replacements.k).toBeUndefined();
48+
}
49+
});
50+
51+
it('should allow other common abbreviations', () => {
52+
const rule = poupeUnicornRules['unicorn/prevent-abbreviations'];
53+
expect(Array.isArray(rule)).toBe(true);
54+
if (Array.isArray(rule) && rule.length > 1) {
55+
const options = rule[1] as PreventAbbreviationsOptions;
56+
const commonAbbreviations = ['env', 'err', 'fn', 'pkg', 'props', 'utils'];
57+
58+
for (const abbr of commonAbbreviations) {
59+
expect(options.allowList[abbr]).toBe(true);
60+
}
61+
}
62+
});
63+
});
64+
65+
describe('filename-case rule', () => {
66+
it('should enforce kebab-case with exceptions for uppercase markdown files', () => {
67+
const rule = poupeUnicornRules['unicorn/filename-case'];
68+
expect(rule).toBeDefined();
69+
expect(Array.isArray(rule)).toBe(true);
70+
71+
if (Array.isArray(rule) && rule.length > 1) {
72+
const severity = rule[0];
73+
const options = rule[1] as FilenameCaseOptions;
74+
expect(severity).toBe('error');
75+
expect(options.case).toBe('kebabCase');
76+
expect(options.ignore).toBeDefined();
77+
expect(options.ignore?.[0]).toBe(String.raw`^[A-Z][A-Z0-9\-_]*\.md$`);
78+
}
79+
});
80+
});
81+
});

src/configs/unicorn.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const abbreviations = [
1717
'err',
1818
'fn',
1919
'i',
20+
'j',
21+
'k',
2022
'msg',
2123
'opt',
2224
'opts',
@@ -29,7 +31,7 @@ const abbreviations = [
2931
'vars',
3032
] as const;
3133

32-
const omitReplacementList = new Set(['i']);
34+
const omitReplacementList = new Set(['i', 'j', 'k']);
3335

3436
const allowList = Object.fromEntries(
3537
abbreviations.map(s => [s, true]),

0 commit comments

Comments
 (0)