2525import { readFileSync } from 'node:fs'
2626import { readdir , readFile } from 'node:fs/promises'
2727import path from 'node:path'
28+ import { fileURLToPath } from 'node:url'
2829
29- const ROOT = path . resolve ( import . meta. dir , '..' )
30+ const ROOT = path . resolve ( path . dirname ( fileURLToPath ( import . meta. url ) ) , '..' )
3031
3132const SCAN_DIRS = [ path . join ( ROOT , 'apps' ) , path . join ( ROOT , 'packages' ) ]
3233
@@ -293,6 +294,51 @@ function es2023LibViolations(): Violation[] {
293294 return violations
294295}
295296
297+ /** Every banned-pattern hit in one file; `file` is repo-relative, which decides its exemptions. */
298+ export function findViolations ( file : string , content : string ) : Violation [ ] {
299+ const violations : Violation [ ] = [ ]
300+ const helperSource = file . startsWith ( UTILS_SOURCE ) || ALLOWLISTED_FILES . has ( file )
301+
302+ const matches : Array < {
303+ index : number
304+ description : string
305+ suggestion : string
306+ } > = [ ]
307+
308+ const prefilterHits = new Map < RegExp , boolean > ( )
309+ for ( const { pattern, description, suggestion, prefilter, replacesHelper } of BANNED_PATTERNS ) {
310+ if ( helperSource && replacesHelper ) continue
311+ if ( prefilter ) {
312+ let hit = prefilterHits . get ( prefilter )
313+ if ( hit === undefined ) {
314+ hit = prefilter . test ( content )
315+ prefilterHits . set ( prefilter , hit )
316+ }
317+ if ( ! hit ) continue
318+ }
319+ pattern . lastIndex = 0
320+ for ( let match = pattern . exec ( content ) ; match !== null ; match = pattern . exec ( content ) ) {
321+ matches . push ( { index : match . index , description, suggestion } )
322+ }
323+ }
324+ if ( matches . length === 0 ) return [ ]
325+
326+ const lines = content . split ( '\n' )
327+ const lineStarts = buildLineStarts ( content )
328+ for ( const match of matches ) {
329+ const line = lineAt ( lineStarts , match . index )
330+ if ( hasAllow ( lines , line ) ) continue
331+ violations . push ( {
332+ file,
333+ line,
334+ description : match . description ,
335+ suggestion : match . suggestion ,
336+ snippet : ( lines [ line - 1 ] ?? '' ) . trim ( ) ,
337+ } )
338+ }
339+ return violations
340+ }
341+
296342async function main ( ) {
297343 const allFiles : string [ ] = [ ]
298344 for ( const dir of SCAN_DIRS ) {
@@ -303,46 +349,7 @@ async function main() {
303349
304350 for ( const file of allFiles ) {
305351 const rel = path . relative ( ROOT , file )
306- const helperSource = rel . startsWith ( UTILS_SOURCE ) || ALLOWLISTED_FILES . has ( rel )
307-
308- const content = await readFile ( file , 'utf8' )
309- const matches : Array < {
310- index : number
311- description : string
312- suggestion : string
313- } > = [ ]
314-
315- const prefilterHits = new Map < RegExp , boolean > ( )
316- for ( const { pattern, description, suggestion, prefilter, replacesHelper } of BANNED_PATTERNS ) {
317- if ( helperSource && replacesHelper ) continue
318- if ( prefilter ) {
319- let hit = prefilterHits . get ( prefilter )
320- if ( hit === undefined ) {
321- hit = prefilter . test ( content )
322- prefilterHits . set ( prefilter , hit )
323- }
324- if ( ! hit ) continue
325- }
326- pattern . lastIndex = 0
327- for ( let match = pattern . exec ( content ) ; match !== null ; match = pattern . exec ( content ) ) {
328- matches . push ( { index : match . index , description, suggestion } )
329- }
330- }
331- if ( matches . length === 0 ) continue
332-
333- const lines = content . split ( '\n' )
334- const lineStarts = buildLineStarts ( content )
335- for ( const match of matches ) {
336- const line = lineAt ( lineStarts , match . index )
337- if ( hasAllow ( lines , line ) ) continue
338- violations . push ( {
339- file : rel ,
340- line,
341- description : match . description ,
342- suggestion : match . suggestion ,
343- snippet : ( lines [ line - 1 ] ?? '' ) . trim ( ) ,
344- } )
345- }
352+ violations . push ( ...findViolations ( rel , await readFile ( file , 'utf8' ) ) )
346353 }
347354
348355 violations . push ( ...es2023LibViolations ( ) )
@@ -361,4 +368,4 @@ async function main() {
361368 process . exit ( 1 )
362369}
363370
364- main ( )
371+ if ( import . meta . main ) main ( )
0 commit comments