diff --git a/packages/oxlint-config/function-verb.js b/packages/oxlint-config/function-verb.js index 3244904..bd8267b 100644 --- a/packages/oxlint-config/function-verb.js +++ b/packages/oxlint-config/function-verb.js @@ -105,7 +105,8 @@ function isVerbMatch(name, verb, bareAllowed) { return bareAllowed; } - return name.startsWith(verb) && /[A-Z]/u.test(name.charAt(verb.length)); + // a digit also ends the verb: acronyms like 2FA start camelCase segments + return name.startsWith(verb) && /[A-Z0-9]/u.test(name.charAt(verb.length)); } function findAllowedVerb(name, verbs) { diff --git a/packages/oxlint-config/plugin.test.ts b/packages/oxlint-config/plugin.test.ts index e34892d..73036f8 100644 --- a/packages/oxlint-config/plugin.test.ts +++ b/packages/oxlint-config/plugin.test.ts @@ -215,6 +215,30 @@ test('it matches a verb only at a camelCase boundary', async () => { expect(result.exitCode).toBe(1); }); +test('it accepts a digit as the boundary after a verb', async () => { + const source = [ + 'export function run2FA(): void {}', + '', + 'export function get2FAVerificationURI(): string {', + " return '';", + '}', + '', + ].join('\n'); + + const result = await runLint(source, false, { 'zgeoff/function-verb': 'error' }); + + expect(result.exitCode).toBe(0); +}); + +test('it flags a banned verb at a digit boundary', async () => { + const source = 'export function save2FABackupCodes(): void {}\n'; + + const result = await runLint(source, false, { 'zgeoff/function-verb': 'error' }); + + expect(result.exitCode).toBe(1); + expect(result.stdout).toInclude("banned verb 'save'"); +}); + test('it skips PascalCase names, object-literal properties, getters, and setters', async () => { const source = [ 'export function Component(): null {',