66 type StoredDesignSystem ,
77} from '@open-codesign/shared' ;
88
9- const IGNORED_DIRS = new Set ( [
9+ export const IGNORED_DESIGN_SYSTEM_DIRS = new Set ( [
1010 '.git' ,
1111 '.idea' ,
1212 '.next' ,
@@ -19,7 +19,7 @@ const IGNORED_DIRS = new Set([
1919 'out' ,
2020] ) ;
2121
22- const CANDIDATE_EXTS = new Set ( [
22+ export const DESIGN_SYSTEM_CANDIDATE_EXTS = new Set ( [
2323 '.css' ,
2424 '.scss' ,
2525 '.sass' ,
@@ -53,6 +53,11 @@ interface CandidateFile {
5353 score : number ;
5454}
5555
56+ export interface DesignSystemSourceFile {
57+ relativePath : string ;
58+ content : string ;
59+ }
60+
5661function pushUnique ( target : string [ ] , value : string , max : number ) : void {
5762 if ( ! value || target . includes ( value ) || target . length >= max ) return ;
5863 target . push ( value ) ;
@@ -65,7 +70,7 @@ function cleanValue(value: string): string {
6570 . trim ( ) ;
6671}
6772
68- function scoreCandidate ( relativePath : string ) : number {
73+ export function scoreDesignSystemCandidate ( relativePath : string ) : number {
6974 const fileName = basename ( relativePath ) ;
7075 let score = 1 ;
7176 for ( const pattern of PRIORITY_PATTERNS ) {
@@ -77,6 +82,11 @@ function scoreCandidate(relativePath: string): number {
7782 return score ;
7883}
7984
85+ export function isDesignSystemCandidateFile ( fileName : string ) : boolean {
86+ const extension = extname ( fileName ) . toLowerCase ( ) ;
87+ return DESIGN_SYSTEM_CANDIDATE_EXTS . has ( extension ) || / t a i l w i n d \. c o n f i g / i. test ( fileName ) ;
88+ }
89+
8090async function collectCandidateFiles (
8191 rootPath : string ,
8292 dirPath : string ,
@@ -95,16 +105,15 @@ async function collectCandidateFiles(
95105 if ( files . length >= MAX_FILES ) return ;
96106 const fullPath = join ( dirPath , entry . name ) ;
97107 if ( entry . isDirectory ( ) ) {
98- if ( ! IGNORED_DIRS . has ( entry . name ) ) {
108+ if ( ! IGNORED_DESIGN_SYSTEM_DIRS . has ( entry . name ) ) {
99109 await collectCandidateFiles ( rootPath , fullPath , files ) ;
100110 }
101111 continue ;
102112 }
103113 if ( ! entry . isFile ( ) ) continue ;
104- const extension = extname ( entry . name ) . toLowerCase ( ) ;
105- if ( ! CANDIDATE_EXTS . has ( extension ) && ! / t a i l w i n d \. c o n f i g / i. test ( entry . name ) ) continue ;
114+ if ( ! isDesignSystemCandidateFile ( entry . name ) ) continue ;
106115 const relativePath = relative ( rootPath , fullPath ) . replace ( / \\ / g, '/' ) ;
107- files . push ( { fullPath, relativePath, score : scoreCandidate ( relativePath ) } ) ;
116+ files . push ( { fullPath, relativePath, score : scoreDesignSystemCandidate ( relativePath ) } ) ;
108117 }
109118}
110119
@@ -184,35 +193,33 @@ function buildSummary(
184193 return parts . join ( ' ' ) ;
185194}
186195
187- export async function scanDesignSystem ( rootPath : string ) : Promise < StoredDesignSystem > {
188- const candidates : CandidateFile [ ] = [ ] ;
189- await collectCandidateFiles ( rootPath , rootPath , candidates ) ;
190-
191- const selected = candidates
192- . sort ( ( a , b ) => b . score - a . score || a . relativePath . localeCompare ( b . relativePath ) )
193- . slice ( 0 , MAX_SELECTED_FILES ) ;
194-
196+ export function buildDesignSystemSnapshot (
197+ rootPath : string ,
198+ files : DesignSystemSourceFile [ ] ,
199+ extra : Partial <
200+ Pick < StoredDesignSystem , 'sourceKind' | 'sshProfileId' | 'sshHost' | 'sshPort' | 'sshUsername' >
201+ > = { } ,
202+ ) : StoredDesignSystem {
195203 const colors : string [ ] = [ ] ;
196204 const fonts : string [ ] = [ ] ;
197205 const spacing : string [ ] = [ ] ;
198206 const radius : string [ ] = [ ] ;
199207 const shadows : string [ ] = [ ] ;
200208
201- for ( const file of selected ) {
202- let raw = '' ;
203- try {
204- raw = await readFile ( file . fullPath , 'utf8' ) ;
205- } catch {
206- continue ;
207- }
208- const snippet = raw . slice ( 0 , MAX_FILE_CHARS ) ;
209+ for ( const file of files ) {
210+ const snippet = file . content . slice ( 0 , MAX_FILE_CHARS ) ;
209211 collectCssVarValues ( snippet , colors , spacing , radius , shadows ) ;
210212 collectLooseValues ( snippet , colors , fonts , spacing , radius , shadows ) ;
211213 }
212214
213215 const baseSnapshot = {
214216 rootPath,
215- sourceFiles : selected . map ( ( file ) => file . relativePath ) ,
217+ sourceKind : extra . sourceKind ?? 'local' ,
218+ ...( extra . sshProfileId !== undefined ? { sshProfileId : extra . sshProfileId } : { } ) ,
219+ ...( extra . sshHost !== undefined ? { sshHost : extra . sshHost } : { } ) ,
220+ ...( extra . sshPort !== undefined ? { sshPort : extra . sshPort } : { } ) ,
221+ ...( extra . sshUsername !== undefined ? { sshUsername : extra . sshUsername } : { } ) ,
222+ sourceFiles : files . map ( ( file ) => file . relativePath ) ,
216223 colors,
217224 fonts,
218225 spacing,
@@ -227,3 +234,24 @@ export async function scanDesignSystem(rootPath: string): Promise<StoredDesignSy
227234 extractedAt : new Date ( ) . toISOString ( ) ,
228235 } ;
229236}
237+
238+ export async function scanDesignSystem ( rootPath : string ) : Promise < StoredDesignSystem > {
239+ const candidates : CandidateFile [ ] = [ ] ;
240+ await collectCandidateFiles ( rootPath , rootPath , candidates ) ;
241+
242+ const selected = candidates
243+ . sort ( ( a , b ) => b . score - a . score || a . relativePath . localeCompare ( b . relativePath ) )
244+ . slice ( 0 , MAX_SELECTED_FILES ) ;
245+
246+ const files : DesignSystemSourceFile [ ] = [ ] ;
247+ for ( const file of selected ) {
248+ try {
249+ files . push ( {
250+ relativePath : file . relativePath ,
251+ content : await readFile ( file . fullPath , 'utf8' ) ,
252+ } ) ;
253+ } catch { }
254+ }
255+
256+ return buildDesignSystemSnapshot ( rootPath , files ) ;
257+ }
0 commit comments