@@ -166,29 +166,52 @@ function validateFiles(
166166 }
167167}
168168
169+ // Categories that require an "audio" frontmatter field
170+ const AUDIO_REQUIRED_CATEGORIES : readonly Category [ ] = [
171+ "locksounds" ,
172+ "hornsounds" ,
173+ "boombox" ,
174+ "lightshows" ,
175+ ] ;
176+
177+ // Categories that require a "thumbnail" frontmatter field
178+ const THUMBNAIL_REQUIRED_CATEGORIES : readonly Category [ ] = [ "wraps" ] ;
179+
169180function validateFilesField (
170181 meta : Record < string , unknown > ,
171182 category : string ,
172183 slug : string ,
173184 itemDir : string
174185) : void {
175- if ( meta . files === undefined ) return ;
186+ if ( meta . files === undefined ) {
187+ error ( `${ category } /${ slug } .md: missing required field "files"` ) ;
188+ return ;
189+ }
176190
177191 if ( ! Array . isArray ( meta . files ) ) {
178192 error ( `${ category } /${ slug } .md: "files" must be an array` ) ;
179193 return ;
180194 }
181195
196+ if ( meta . files . length === 0 ) {
197+ error ( `${ category } /${ slug } .md: "files" must contain at least one entry` ) ;
198+ return ;
199+ }
200+
182201 for ( const entry of meta . files ) {
183202 if ( ! entry || typeof entry !== "object" ) {
184- error ( `${ category } /${ slug } .md: each entry in "files" must be an object with a "name" field ` ) ;
203+ error ( `${ category } /${ slug } .md: each entry in "files" must be an object with "name" and "label" fields ` ) ;
185204 continue ;
186205 }
187206 const fileEntry = entry as Record < string , unknown > ;
188207 if ( ! fileEntry . name || typeof fileEntry . name !== "string" || fileEntry . name . trim ( ) === "" ) {
189208 error ( `${ category } /${ slug } .md: each entry in "files" must have a non-empty "name" string` ) ;
190209 continue ;
191210 }
211+ if ( ! fileEntry . label || typeof fileEntry . label !== "string" || fileEntry . label . trim ( ) === "" ) {
212+ error ( `${ category } /${ slug } .md: each entry in "files" must have a non-empty "label" string` ) ;
213+ continue ;
214+ }
192215 const filePath = path . join ( itemDir , String ( fileEntry . name ) ) ;
193216 if ( ! fs . existsSync ( filePath ) ) {
194217 error (
@@ -198,6 +221,45 @@ function validateFilesField(
198221 }
199222}
200223
224+ function validateAudioField (
225+ meta : Record < string , unknown > ,
226+ category : string ,
227+ slug : string ,
228+ itemDir : string
229+ ) : void {
230+ if ( ! AUDIO_REQUIRED_CATEGORIES . includes ( category as Category ) ) return ;
231+
232+ if ( meta . audio === undefined ) {
233+ error ( `${ category } /${ slug } .md: missing required field "audio"` ) ;
234+ return ;
235+ }
236+
237+ if ( typeof meta . audio !== "string" || meta . audio . trim ( ) === "" ) {
238+ error ( `${ category } /${ slug } .md: "audio" must be a non-empty string` ) ;
239+ return ;
240+ }
241+
242+ const audioPath = path . join ( itemDir , String ( meta . audio ) ) ;
243+ if ( ! fs . existsSync ( audioPath ) ) {
244+ error ( `${ category } /${ slug } .md: audio file "${ meta . audio } " not found` ) ;
245+ }
246+ }
247+
248+ function validateThumbnailRequired (
249+ meta : Record < string , unknown > ,
250+ category : string ,
251+ slug : string ,
252+ itemDir : string
253+ ) : void {
254+ if ( ! THUMBNAIL_REQUIRED_CATEGORIES . includes ( category as Category ) ) return ;
255+
256+ if ( meta . thumbnail === undefined ) {
257+ error ( `${ category } /${ slug } .md: missing required field "thumbnail"` ) ;
258+ return ;
259+ }
260+ // Actual thumbnail format/existence validation is handled in validateMeta
261+ }
262+
201263function parseArgs ( ) : { collection ?: Category } {
202264 const args = process . argv . slice ( 2 ) ;
203265 const collectionIdx = args . indexOf ( "--collection" ) ;
@@ -270,6 +332,8 @@ function main(): void {
270332 validateMeta ( meta , category , slug , knownTags , itemDir ) ;
271333 validateFiles ( itemDir , category , slug ) ;
272334 validateFilesField ( meta , category , slug , itemDir ) ;
335+ validateAudioField ( meta , category , slug , itemDir ) ;
336+ validateThumbnailRequired ( meta , category , slug , itemDir ) ;
273337 }
274338 }
275339
0 commit comments