@@ -13,6 +13,7 @@ import {
1313import { execProcess } from "../../../core/process.ts" ;
1414import { basename , dirname , extname , join } from "../../../deno_ral/path.ts" ;
1515import { existsSync } from "../../../deno_ral/fs.ts" ;
16+ import { expandGlobSync } from "../../../core/deno/expand-glob.ts" ;
1617
1718interface DenoConfig {
1819 compilerOptions ?: Record < string , unknown > ;
@@ -184,23 +185,60 @@ function inferOutputPath(entryPoint: string): string {
184185 // Get the base name without extension
185186 const fileName = basename ( entryPoint , extname ( entryPoint ) ) ;
186187
187- // Try to determine extension name from directory structure or use filename
188- let extensionName = fileName ;
188+ // Find the extension directory by looking for _extension.yml
189+ const extensionsDir = "_extensions" ;
190+ if ( ! existsSync ( extensionsDir ) ) {
191+ error ( "Error: No _extensions/ directory found." ) ;
192+ error ( "" ) ;
193+ error (
194+ "Extension projects must have an _extensions/ directory with _extension.yml." ,
195+ ) ;
196+ error ( "Create the extension structure:" ) ;
197+ error ( ` mkdir -p _extensions/${ fileName } ` ) ;
198+ error ( ` touch _extensions/${ fileName } /_extension.yml` ) ;
199+ Deno . exit ( 1 ) ;
200+ }
189201
190- // Check if _extension.yml exists to get extension name
191- const extensionYml = "_extension.yml" ;
192- if ( existsSync ( extensionYml ) ) {
193- try {
194- // Simple extraction - look for extension name in path or use filename
195- // For MVP, we'll just use the filename
196- } catch {
197- // Ignore errors, use filename
198- }
202+ // Find all _extension.yml files using glob pattern
203+ const extensionYmlFiles : string [ ] = [ ] ;
204+ for ( const entry of expandGlobSync ( "_extensions/**/_extension.yml" ) ) {
205+ extensionYmlFiles . push ( dirname ( entry . path ) ) ;
206+ }
207+
208+ if ( extensionYmlFiles . length === 0 ) {
209+ error ( "Error: No _extension.yml found in _extensions/ subdirectories." ) ;
210+ error ( "" ) ;
211+ error (
212+ "Extension projects must have _extension.yml in a subdirectory of _extensions/." ,
213+ ) ;
214+ error ( "Create the extension metadata:" ) ;
215+ error ( ` touch _extensions/${ fileName } /_extension.yml` ) ;
216+ Deno . exit ( 1 ) ;
217+ }
218+
219+ if ( extensionYmlFiles . length > 1 ) {
220+ const extensionNames = extensionYmlFiles . map ( ( path ) =>
221+ path . replace ( "_extensions/" , "" )
222+ ) ;
223+ error (
224+ `Error: Multiple extension directories found: ${
225+ extensionNames . join ( ", " )
226+ } `,
227+ ) ;
228+ error ( "" ) ;
229+ error ( "Specify the output path in deno.json:" ) ;
230+ error ( " {" ) ;
231+ error ( ' "quartoExtension": {' ) ;
232+ error (
233+ ` "outputFile": "${ extensionYmlFiles [ 0 ] } /${ fileName } .js"` ,
234+ ) ;
235+ error ( " }" ) ;
236+ error ( " }" ) ;
237+ Deno . exit ( 1 ) ;
199238 }
200239
201- // Output to _extensions/<name>/<name>.js
202- const outputDir = join ( "_extensions" , extensionName ) ;
203- return join ( outputDir , `${ fileName } .js` ) ;
240+ // Use the single extension directory found
241+ return join ( extensionYmlFiles [ 0 ] , `${ fileName } .js` ) ;
204242}
205243
206244async function bundle (
0 commit comments