@@ -30,24 +30,18 @@ export async function extractVariables(
3030 const contentReplacers : ContentReplacer [ ] = [ ] ;
3131 const fileReplacerVars = new Set < string > ( ) ;
3232 const contentReplacerVars = new Set < string > ( ) ;
33-
33+
3434 const projectQuestions = await loadProjectQuestions ( templateDir ) ;
35- const ignoredPathPatterns = new Set < string > ( projectQuestions ?. ignore ?? [ ] ) ;
36- const ignoredContentTokens = buildIgnoredContentTokens ( projectQuestions ) ;
37-
3835 await walkDirectory ( templateDir , async ( filePath ) => {
3936 const relativePath = path . relative ( templateDir , filePath ) ;
40- if ( shouldIgnore ( relativePath , ignoredPathPatterns ) ) {
41- return ;
42- }
43-
37+
4438 if (
4539 relativePath === ".questions.json" ||
4640 relativePath === ".questions.js"
4741 ) {
4842 return ;
4943 }
50-
44+
5145 const matches = relativePath . matchAll ( VARIABLE_PATTERN ) ;
5246 for ( const match of matches ) {
5347 const varName = match [ 1 ] ;
@@ -62,11 +56,8 @@ export async function extractVariables(
6256 } ) ;
6357 }
6458 }
65-
66- const contentVars = await extractFromFileContent (
67- filePath ,
68- ignoredContentTokens
69- ) ;
59+
60+ const contentVars = await extractFromFileContent ( filePath ) ;
7061 for ( const varName of contentVars ) {
7162 if ( ! contentReplacerVars . has ( varName ) ) {
7263 contentReplacerVars . add ( varName ) ;
@@ -94,41 +85,36 @@ export async function extractVariables(
9485 * @returns Set of variable names found in the file
9586 */
9687async function extractFromFileContent (
97- filePath : string ,
98- ignoredTokens : Set < string >
88+ filePath : string
9989) : Promise < Set < string > > {
10090 const variables = new Set < string > ( ) ;
101-
91+
10292 return new Promise ( ( resolve ) => {
10393 const stream = fs . createReadStream ( filePath , { encoding : "utf8" } ) ;
10494 let buffer = "" ;
105-
95+
10696 stream . on ( "data" , ( chunk : string | Buffer ) => {
10797 buffer += chunk . toString ( ) ;
108-
98+
10999 const lines = buffer . split ( "\n" ) ;
110100 buffer = lines . pop ( ) || "" ; // Keep the last incomplete line in buffer
111-
101+
112102 for ( const line of lines ) {
113103 const matches = line . matchAll ( VARIABLE_PATTERN ) ;
114104 for ( const match of matches ) {
115- if ( ! shouldIgnoreContent ( match [ 0 ] , ignoredTokens ) ) {
116105 variables . add ( match [ 1 ] ) ;
117- }
118106 }
119107 }
120108 } ) ;
121-
109+
122110 stream . on ( "end" , ( ) => {
123111 const matches = buffer . matchAll ( VARIABLE_PATTERN ) ;
124112 for ( const match of matches ) {
125- if ( ! shouldIgnoreContent ( match [ 0 ] , ignoredTokens ) ) {
126113 variables . add ( match [ 1 ] ) ;
127- }
128114 }
129115 resolve ( variables ) ;
130116 } ) ;
131-
117+
132118 stream . on ( "error" , ( ) => {
133119 resolve ( variables ) ;
134120 } ) ;
@@ -145,10 +131,10 @@ async function walkDirectory(
145131 callback : ( filePath : string ) => Promise < void >
146132) : Promise < void > {
147133 const entries = fs . readdirSync ( dir , { withFileTypes : true } ) ;
148-
134+
149135 for ( const entry of entries ) {
150136 const fullPath = path . join ( dir , entry . name ) ;
151-
137+
152138 if ( entry . isDirectory ( ) ) {
153139 await walkDirectory ( fullPath , callback ) ;
154140 } else if ( entry . isFile ( ) ) {
@@ -194,98 +180,6 @@ async function loadProjectQuestions(
194180 return null ;
195181}
196182
197- function shouldIgnore (
198- relativePath : string ,
199- ignoredPatterns : Set < string >
200- ) : boolean {
201- if ( ignoredPatterns . size === 0 ) {
202- return false ;
203- }
204- const normalized = relativePath . split ( path . sep ) . join ( "/" ) ;
205- const segments = normalized . split ( "/" ) ;
206-
207- for ( const pattern of ignoredPatterns ) {
208- const normalizedPattern = pattern . split ( path . sep ) . join ( "/" ) ;
209-
210- if ( normalizedPattern === normalized ) {
211- return true ;
212- }
213-
214- if ( ! normalizedPattern . includes ( "/" ) ) {
215- if ( segments . includes ( normalizedPattern ) ) {
216- return true ;
217- }
218- continue ;
219- }
220-
221- if ( normalizedPattern . startsWith ( "**/" ) ) {
222- const suffix = normalizedPattern . slice ( 3 ) ;
223- if ( normalized . endsWith ( suffix ) ) {
224- return true ;
225- }
226- continue ;
227- }
228-
229- if ( normalizedPattern . endsWith ( "/**" ) ) {
230- const prefix = normalizedPattern . slice ( 0 , - 3 ) ;
231- if ( normalized === prefix || normalized . startsWith ( `${ prefix } /` ) ) {
232- return true ;
233- }
234- continue ;
235- }
236-
237- if ( normalized . startsWith ( `${ normalizedPattern } /` ) ) {
238- return true ;
239- }
240- }
241- return false ;
242- }
243-
244- const DEFAULT_IGNORED_CONTENT_TOKENS = [ "tests" , "snapshots" ] ;
245-
246- function shouldIgnoreContent (
247- match : string ,
248- ignoredTokens : Set < string >
249- ) : boolean {
250- if ( ignoredTokens . size === 0 ) {
251- return false ;
252- }
253- const token = match . slice (
254- PLACEHOLDER_BOUNDARY . length ,
255- - PLACEHOLDER_BOUNDARY . length
256- ) ;
257- return ignoredTokens . has ( token ) ;
258- }
259-
260- function buildIgnoredContentTokens ( projectQuestions : Questions | null ) : Set < string > {
261- const tokens = new Set < string > ( DEFAULT_IGNORED_CONTENT_TOKENS ) ;
262- if ( projectQuestions ?. ignore ) {
263- for ( const entry of projectQuestions . ignore ) {
264- const normalized = normalizePlaceholder ( entry ) ;
265- if ( normalized ) {
266- tokens . add ( normalized ) ;
267- }
268- }
269- }
270- return tokens ;
271- }
272-
273- function normalizePlaceholder ( entry : string ) : string | null {
274- if (
275- entry . startsWith ( PLACEHOLDER_BOUNDARY ) &&
276- entry . endsWith ( PLACEHOLDER_BOUNDARY )
277- ) {
278- return entry . slice (
279- PLACEHOLDER_BOUNDARY . length ,
280- - PLACEHOLDER_BOUNDARY . length
281- ) ;
282- }
283- if ( entry . startsWith ( "__" ) && entry . endsWith ( "__" ) ) {
284- return entry . slice ( 2 , - 2 ) ;
285- }
286- return entry || null ;
287- }
288-
289183/**
290184 * Normalize questions by ensuring all required fields have default values
291185 * @param questions - Questions object to normalize
0 commit comments