@@ -79,35 +79,45 @@ const inferMetadata = (
79
79
* @param currentPath - The current path of the object being processed.
80
80
* @param isRoot - Indicates whether the current object is the root object.
81
81
*/
82
+ /**
83
+ * Recursively maps block references in an object and updates the `usedBy` property of the corresponding blocks.
84
+ *
85
+ * @param obj - The object to inspect for block references.
86
+ * @param blockMetadata - A map of block paths to block metadata.
87
+ * @param blockPathByName - A map of block names to their corresponding file paths.
88
+ * @param currentPath - The path of the current block being processed.
89
+ * @param isRoot - Indicates whether the current object is the root object.
90
+ */
82
91
const mapBlockReferences = (
83
92
obj : unknown ,
84
- blocks : Map < string , Metadata > ,
93
+ blockMetadata : Map < string , Metadata > ,
94
+ blockPathByName : Map < string , string > ,
85
95
currentPath : string ,
86
- isRoot = true ,
96
+ isRoot = true
87
97
) : void => {
88
- if ( typeof obj !== " object" || obj === null ) return ;
98
+ if ( typeof obj !== ' object' || obj === null ) return ;
89
99
90
100
if ( Array . isArray ( obj ) ) {
91
- obj . forEach ( ( item ) => mapBlockReferences ( item , blocks , currentPath , false ) ) ;
92
- } else {
93
- for ( const [ key , value ] of Object . entries ( obj ) ) {
94
- if ( key === "__resolveType" && typeof value === "string" && ! isRoot ) {
95
- const blockName = value . split ( "/" ) . pop ( ) ;
96
- if ( blockName ) {
97
- const blockPath = Array . from ( blocks . keys ( ) ) . find ( ( path ) =>
98
- decodeURIComponent ( path . split ( "/" ) . pop ( ) ?? "" ) ===
99
- ` ${ blockName } .json`
100
- ) ;
101
- if ( blockPath && blockPath !== currentPath ) {
102
- const block = blocks . get ( blockPath ) ;
103
- if ( block && ! block . usedBy . includes ( currentPath ) ) {
104
- block . usedBy . push ( currentPath ) ;
105
- }
101
+ for ( const item of obj ) {
102
+ mapBlockReferences ( item , blockMetadata , blockPathByName , currentPath , false ) ;
103
+ }
104
+ return ;
105
+ }
106
+
107
+ for ( const [ key , value ] of Object . entries ( obj ) ) {
108
+ if ( key === '__resolveType' && ! isRoot ) {
109
+ const blockName = value . split ( '/' ) . pop ( ) ;
110
+ if ( blockName ) {
111
+ const referencedBlockPath = blockPathByName . get ( blockName ) ;
112
+ if ( referencedBlockPath && referencedBlockPath !== currentPath ) {
113
+ const blockMeta = blockMetadata . get ( referencedBlockPath ) ;
114
+ if ( blockMeta && ! blockMeta . usedBy . includes ( currentPath ) ) {
115
+ blockMeta . usedBy . push ( currentPath ) ;
106
116
}
107
117
}
108
- } else if ( typeof value === "object" && value !== null ) {
109
- mapBlockReferences ( value , blocks , currentPath , false ) ;
110
118
}
119
+ } else if ( typeof value === 'object' && value !== null ) {
120
+ mapBlockReferences ( value , blockMetadata , blockPathByName , currentPath , false ) ;
111
121
}
112
122
}
113
123
} ;
@@ -116,7 +126,7 @@ const mapBlockReferences = (
116
126
export const genMetadata = async ( ) => {
117
127
try {
118
128
const knownBlockTypes = new Set ( getBlocks ( ) . map ( ( x ) => x . type ) ) ;
119
- const paths : string [ ] = [ ] ;
129
+ const blockPaths : string [ ] = [ ] ;
120
130
121
131
const walker = walk ( join ( DECO_FOLDER , BLOCKS_FOLDER ) , {
122
132
includeDirs : false ,
@@ -125,34 +135,39 @@ export const genMetadata = async () => {
125
135
} ) ;
126
136
127
137
for await ( const entry of walker ) {
128
- paths . push ( entry . path ) ;
138
+ blockPaths . push ( entry . path ) ;
129
139
}
130
140
131
- const entries = await Promise . all (
132
- paths . map ( async ( path ) =>
141
+ const blockEntries = await Promise . all (
142
+ blockPaths . map ( async ( path ) =>
133
143
[
134
144
`/${ path . replaceAll ( "\\" , "/" ) } ` ,
135
145
JSON . parse ( await Deno . readTextFile ( path ) ) ,
136
146
] as [ string , unknown ]
137
147
) ,
138
148
) ;
139
149
140
- const metadata = new Map (
141
- entries . map ( ( [ path , content ] ) => [
142
- path ,
143
- inferMetadata ( content , knownBlockTypes ) ,
144
- ] ) . filter ( ( [ , meta ] ) => meta !== null ) as [ string , Metadata ] [ ] ,
145
- ) ;
150
+ const blockMetadata : Map < string , Metadata > = new Map ( ) ;
151
+ const blockPathByName = new Map < string , string > ( ) ;
152
+
153
+ for ( const [ path , content ] of blockEntries ) {
154
+ const meta = inferMetadata ( content , knownBlockTypes ) ;
155
+ if ( meta !== null ) {
156
+ blockMetadata . set ( path , meta ) ;
157
+ const blockName = parseBlockId ( basename ( path ) ) ;
158
+ blockPathByName . set ( blockName , path ) ;
159
+ }
160
+ }
146
161
147
- for ( const [ path , content ] of entries ) {
148
- mapBlockReferences ( content , metadata , path ) ;
162
+ for ( const [ path , content ] of blockEntries ) {
163
+ mapBlockReferences ( content , blockMetadata , blockPathByName , path ) ;
149
164
}
150
165
151
- const pathname = join ( Deno . cwd ( ) , METADATA_PATH ) ;
152
- await ensureFile ( pathname ) ;
166
+ const metadataPath = join ( Deno . cwd ( ) , METADATA_PATH ) ;
167
+ await ensureFile ( metadataPath ) ;
153
168
await Deno . writeTextFile (
154
- pathname ,
155
- JSON . stringify ( Object . fromEntries ( metadata ) ) ,
169
+ metadataPath ,
170
+ JSON . stringify ( Object . fromEntries ( blockMetadata ) ) ,
156
171
) ;
157
172
} catch ( error ) {
158
173
console . error ( "Error while auto-generating blocks.json" , error ) ;
0 commit comments