@@ -3,184 +3,185 @@ const path = require("path");
33const matter = require ( "gray-matter" ) ;
44const { execSync } = require ( "child_process" ) ;
55
6- /**
7- * Convert git remote URL to HTTP URL
8- */
9- function convertGitToHttpUrl ( gitUrl ) {
10- if ( gitUrl . startsWith ( "git@github.com:" ) ) {
11- return gitUrl . replace ( "git@github.com:" , "https://github.com/" ) ;
12- }
13- return gitUrl ;
14- }
15-
16- /**
17- * Get GitHub remote URLs in HTTP and SSH format
18- */
19- function getGithubRemoteUrls ( filePath ) {
6+ function getGitHubRemoteUrl ( ) {
207 try {
21- const remoteUrl = execSync ( "git config --get remote.origin.url" ) . toString ( ) . trim ( ) . replace ( / h t t p s ? : \/ \/ .* ?@ g i t h u b \. c o m \/ / , "https://github.com/" ) ;
22- const httpUrl = convertGitToHttpUrl ( remoteUrl ) . replace (
23- / \. g i t $ / ,
24- `/tree/main/modules${ filePath . replace ( path . resolve ( __dirname , 'modules' ) , '' ) . replace ( / \/ R E A D M E \. m d $ / , '' ) } `
25- ) ;
26- return {
27- ssh : remoteUrl ,
28- https : httpUrl
29- } ;
8+ const remoteUrl = execSync ( "git config --get remote.origin.url" )
9+ . toString ( )
10+ . trim ( )
11+ . replace ( / h t t p s ? : \/ \/ .* ?@ g i t h u b \. c o m \/ / , "https://github.com/" ) ;
12+ return remoteUrl . replace ( / \. g i t $ / , "" ) ;
3013 } catch ( error ) {
3114 console . error ( "Error getting GitHub remote URL:" , error . message ) ;
3215 return null ;
3316 }
3417}
3518
36- /**
37- * Recursively find all README.md files in “buildingblock” folders, excluding .github
38- */
39- function findReadmes ( dir ) {
40- let results = [ ] ;
41- const files = fs . readdirSync ( dir , { withFileTypes : true } ) ;
19+ function getBuildingBlockFolderUrl ( filePath ) {
20+ const remoteUrl = getGitHubRemoteUrl ( ) ;
21+ if ( ! remoteUrl ) return null ;
4222
43- for ( const file of files ) {
44- const fullPath = path . join ( dir , file . name ) ;
23+ const relativePath = filePath
24+ . replace ( path . resolve ( __dirname , "modules" ) , "" )
25+ . replace ( / \/ R E A D M E \. m d $ / , "" ) ;
26+ return `${ remoteUrl } /tree/main/modules${ relativePath } ` ;
27+ }
4528
29+ function findReadmes ( dir ) {
30+ return fs . readdirSync ( dir , { withFileTypes : true } ) . flatMap ( ( file ) => {
31+ const fullPath = path . join ( dir , file . name ) ;
4632 if ( file . isDirectory ( ) ) {
47- if ( file . name === ".github" ) continue ;
48- results = results . concat ( findReadmes ( fullPath ) ) ;
49- } else if ( file . name === "README.md" && dir . includes ( "buildingblock" ) ) {
50- results . push ( fullPath ) ;
33+ return file . name === ".github" ? [ ] : findReadmes ( fullPath ) ;
5134 }
52- }
53-
54- return results ;
35+ return file . name === "README.md" && dir . includes ( "buildingblock" )
36+ ? [ fullPath ]
37+ : [ ] ;
38+ } ) ;
5539}
5640
57- /**
58- * Path to platform logo image, excluding .github
59- */
60- function findPlatformLogos ( ) {
61- const platformLogos = { } ;
62- const modulesDir = path . resolve ( __dirname , 'modules' ) ;
63- const assetsDir = path . resolve ( __dirname , 'website/public/assets/logos' ) ;
64- const dirs = fs . readdirSync ( modulesDir , { withFileTypes : true } )
65- . filter ( dirent => dirent . isDirectory ( ) && dirent . name !== ".github" ) ;
66-
67- dirs . forEach ( ( dir ) => {
68- const platformDir = path . join ( modulesDir , dir . name ) ;
69- const files = fs . readdirSync ( platformDir ) ;
70-
71- files . forEach ( ( file ) => {
72- if ( file . endsWith ( ".png" ) || file . endsWith ( ".svg" ) ) {
73- const sourcePath = path . join ( platformDir , file ) ;
74- const destinationPath = path . join ( assetsDir , `${ dir . name } ${ path . extname ( file ) } ` ) ;
75-
76- fs . mkdirSync ( assetsDir , { recursive : true } ) ;
77-
78- fs . copyFileSync ( sourcePath , destinationPath ) ;
79-
80- platformLogos [ dir . name ] = destinationPath . replace ( path . resolve ( __dirname , 'website/public' ) , "" ) . replace ( / ^ \/ + / g, "" ) ;
81- }
41+ function copyFilesToAssets (
42+ sourceDir ,
43+ destinationDir ,
44+ fileFilter
45+ ) {
46+ const copiedFiles = { } ;
47+
48+ fs . readdirSync ( sourceDir , { withFileTypes : true } )
49+ . filter ( ( dirent ) => dirent . isDirectory ( ) && dirent . name !== ".github" )
50+ . forEach ( ( dir ) => {
51+ const platformDir = path . join ( sourceDir , dir . name ) ;
52+ fs . readdirSync ( platformDir )
53+ . filter ( fileFilter )
54+ . forEach ( ( file ) => {
55+ const sourcePath = path . join ( platformDir , file ) ;
56+ const destinationPath = path . join (
57+ destinationDir ,
58+ `${ dir . name } ${ path . extname ( file ) } `
59+ ) ;
60+
61+ fs . mkdirSync ( destinationDir , { recursive : true } ) ;
62+ fs . copyFileSync ( sourcePath , destinationPath ) ;
63+
64+ copiedFiles [ dir . name ] = destinationPath
65+ . replace ( path . resolve ( __dirname , "website/public" ) , "" )
66+ . replace ( / ^ \/ + / g, "" ) ;
67+ } ) ;
8268 } ) ;
83- } ) ;
8469
85- return platformLogos ;
70+ return copiedFiles ;
8671}
8772
88- /**
89- * Path to buildingblock logo image in the same directory as README.md
90- */
91- function findBuildingBlockLogo ( buildingBlockDir ) {
92- const logoFiles = [ ] ;
93- const assetsDir = path . resolve ( __dirname , 'website/public/assets/building-block-logos' ) ;
94- const files = fs . readdirSync ( buildingBlockDir ) ;
73+ function copyPlatformLogosToAssets ( ) {
74+ const modulesDir = path . resolve ( __dirname , "modules" ) ;
75+ const assetsDir = path . resolve ( __dirname , "website/public/assets/logos" ) ;
76+ return copyFilesToAssets ( modulesDir , assetsDir , ( file ) =>
77+ file . endsWith ( ".png" ) || file . endsWith ( ".svg" )
78+ ) ;
79+ }
9580
96- files . forEach ( ( file ) => {
97- if ( file . endsWith ( ".png" ) || file . endsWith ( ".svg" ) ) {
98- const { id , platform } = getIdAndPlatform ( buildingBlockDir ) ;
99- const sourcePath = path . join ( buildingBlockDir , file ) ;
100- const destinationPath = path . join ( assetsDir , ` ${ id } ${ path . extname ( file ) } ` ) ;
81+ function copyBuildingBlockLogoToAssets ( buildingBlockDir ) {
82+ const assetsDir = path . resolve (
83+ __dirname ,
84+ "website/public/assets/building-block-logos"
85+ ) ;
10186
102- fs . mkdirSync ( assetsDir , { recursive : true } ) ;
103- fs . copyFileSync ( sourcePath , destinationPath ) ;
87+ const logoFile = fs
88+ . readdirSync ( buildingBlockDir )
89+ . find ( ( file ) => file . endsWith ( ".png" ) ) ;
10490
105- logoFiles . push ( destinationPath . replace ( path . resolve ( __dirname , 'website/public' ) , "" ) . replace ( / ^ \/ + / g, "" ) ) ;
106- }
107- } ) ;
91+ if ( ! logoFile ) return null ;
10892
109- return logoFiles . length > 0 ? logoFiles [ 0 ] : null ;
93+ const { id } = getIdAndPlatform ( buildingBlockDir ) ;
94+ const sourcePath = path . join ( buildingBlockDir , logoFile ) ;
95+ const destinationPath = path . join ( assetsDir , `${ id } ${ path . extname ( logoFile ) } ` ) ;
96+
97+ fs . mkdirSync ( assetsDir , { recursive : true } ) ;
98+ fs . copyFileSync ( sourcePath , destinationPath ) ;
99+
100+ return destinationPath
101+ . replace ( path . resolve ( __dirname , "website/public" ) , "" )
102+ . replace ( / ^ \/ + / g, "" ) ;
110103}
111104
112- /**
113- * Parse README.md and extract relevant data
114- */
115105function parseReadme ( filePath ) {
116106 const buildingBlockDir = path . dirname ( filePath ) ;
117107 const content = fs . readFileSync ( filePath , "utf-8" ) ;
118108 const { data, content : body } = matter ( content ) ;
119109 const { id, platform } = getIdAndPlatform ( buildingBlockDir ) ;
120- const howToMatch = body . match ( / # # H o w t o U s e ( [ \s \S ] * ?) ( # # | $ ) / ) ;
121- const resourcesMatch = body . match ( / # # R e s o u r c e s ( [ \s \S ] * ) / ) ;
122- const inputsMatch = body . match ( / # # I n p u t s ( [ \s \S ] * ?) # # O u t p u t s / ) ;
123- const outputsMatch = body . match ( / # # O u t p u t s ( [ \s \S ] * ) / ) ;
110+
111+ const extractSection = ( regex ) =>
112+ body . match ( regex ) ?. [ 1 ] ?. trim ( ) || null ;
124113
125114 const parseTable = ( match ) =>
126115 match
127116 ? match [ 1 ]
128- . split ( "\n" )
129- . filter ( ( line ) => line . startsWith ( "| <a name" ) )
130- . map ( ( line ) => line . split ( "|" ) . map ( ( s ) => s . trim ( ) ) )
131- . map ( ( [ name , description , type , _default , required ] ) => ( {
132- name : name . replace ( / < a n a m e = " .* ?_ ( .* ?) " .* ?> / , "$1" ) ,
133- description,
134- type,
135- required : required === "yes" ,
136- } ) )
117+ . split ( "\n" )
118+ . filter ( ( line ) => line . startsWith ( "| <a name" ) )
119+ . map ( ( line ) => line . split ( "|" ) . map ( ( s ) => s . trim ( ) ) )
120+ . map ( ( [ name , description , type , _default , required ] ) => ( {
121+ name : name . replace ( / < a n a m e = " .* ?_ ( .* ?) " .* ?> / , "$1" ) ,
122+ description,
123+ type,
124+ required : required === "yes" ,
125+ } ) )
137126 : [ ] ;
138127
139- const githubUrls = getGithubRemoteUrls ( filePath ) ;
140- console . log ( `🔗 GitHub remote URLs: ${ JSON . stringify ( githubUrls ) } ` ) ;
141- console . log ( `🔗 File path: ${ filePath } ` ) ;
128+ const buildingBlockUrl = getBuildingBlockFolderUrl ( filePath ) ;
129+ const buildingBlockLogoPath = copyBuildingBlockLogoToAssets ( buildingBlockDir ) ;
142130
143- const buildingBlockLogoPath = findBuildingBlockLogo ( buildingBlockDir ) ;
131+ const backplaneDir = path . join ( buildingBlockDir , "../backplane" ) ;
132+ const backplaneUrl =
133+ fs . existsSync ( backplaneDir ) && fs . statSync ( backplaneDir ) . isDirectory ( )
134+ ? getBuildingBlockFolderUrl ( backplaneDir )
135+ : null ;
144136
145137 return {
146- id : id ,
138+ id,
147139 platformType : platform ,
148140 logo : buildingBlockLogoPath ,
149- githubUrls,
141+ buildingBlockUrl,
142+ backplaneUrl,
150143 ...data ,
151- howToUse : howToMatch ? howToMatch [ 1 ] . trim ( ) : null ,
152- resources : parseTable ( resourcesMatch ) ,
153- inputs : parseTable ( inputsMatch ) ,
154- outputs : parseTable ( outputsMatch ) ,
144+ howToUse : extractSection ( / # # H o w t o U s e ( [ \s \S ] * ?) ( # # | $ ) / ) ,
145+ resources : parseTable ( body . match ( / # # R e s o u r c e s ( [ \s \S ] * ) / ) ) ,
146+ inputs : parseTable ( body . match ( / # # I n p u t s ( [ \s \S ] * ?) # # O u t p u t s / ) ) ,
147+ outputs : parseTable ( body . match ( / # # O u t p u t s ( [ \s \S ] * ) / ) ) ,
148+
155149 } ;
156150}
157151
158- /**
159- * This returns the id and platform type from the file path.
160- *
161- * @param filePath The buildingblock directory
162- */
163152function getIdAndPlatform ( filePath ) {
164- const relativePath = filePath . replace ( process . cwd ( ) , "" ) . replace ( / \\ / g, "/" ) ;
153+ const relativePath = filePath
154+ . replace ( process . cwd ( ) , "" )
155+ . replace ( / \\ / g, "/" ) ;
165156 const pathParts = relativePath . split ( path . sep ) . filter ( Boolean ) ;
166- // pathParts = [modules, <platform>, <module-name>, buildingblock]
167157 const id = pathParts . slice ( 1 , pathParts . length - 1 ) . join ( "-" ) ;
168- const platform = pathParts . length > 1 ? pathParts [ 1 ] : "unknown" ;
158+ const platform = pathParts [ 1 ] || "unknown" ;
169159
170160 return { id, platform } ;
171161}
172162
173- const repoRoot = path . resolve ( __dirname , 'modules' ) ;
174- const platformLogos = findPlatformLogos ( ) ;
175- const readmeFiles = findReadmes ( repoRoot ) ;
176- const jsonData = readmeFiles . map ( ( file ) => parseReadme ( file ) ) ;
177-
178- const templatesData = {
179- templates : jsonData ,
180- } ;
181-
182- fs . writeFileSync ( "website/public/assets/templates.json" , JSON . stringify ( templatesData , null , 2 ) ) ;
183- console . log ( `✅ Successfully processed ${ readmeFiles . length } README.md files. Output saved to templates.json` ) ;
163+ // Main execution
164+ function main ( ) {
165+ const repoRoot = path . resolve ( __dirname , "modules" ) ;
166+
167+ const platformLogos = copyPlatformLogosToAssets ( ) ;
168+ fs . writeFileSync (
169+ "website/public/assets/platform-logos.json" ,
170+ JSON . stringify ( platformLogos , null , 2 )
171+ ) ;
172+ console . log (
173+ `✅ Successfully processed ${ Object . entries ( platformLogos ) . length } platform logos. Output saved to platform-logos.json`
174+ ) ;
175+
176+ const readmeFiles = findReadmes ( repoRoot ) ;
177+ const jsonData = readmeFiles . map ( parseReadme ) ;
178+ fs . writeFileSync (
179+ "website/public/assets/templates.json" ,
180+ JSON . stringify ( { templates : jsonData } , null , 2 )
181+ ) ;
182+ console . log (
183+ `✅ Successfully processed ${ readmeFiles . length } README.md files. Output saved to templates.json`
184+ ) ;
185+ }
184186
185- fs . writeFileSync ( "website/public/assets/platform-logos.json" , JSON . stringify ( platformLogos , null , 2 ) ) ;
186- console . log ( `✅ Successfully processed ${ Object . entries ( platformLogos ) . length } platform logos. Output saved to platform-logos.json` ) ;
187+ main ( ) ;
0 commit comments