@@ -480,6 +480,7 @@ <h2 id="pathsOrIdsTitle" class="preview-generator-v2__section-heading">Paths or
480480<gamename>
481481
482482Samples examples:
483+ samples/phase-xx
483484samples/phase-01/0102/index.html
484485samples/phase-13/1303/index.html
4854860107
@@ -897,8 +898,13 @@ <h2 id="lastGeneratedImageTitle" class="preview-generator-v2__section-heading">L
897898 }
898899
899900 try {
900- const entry = await resolveEntry ( lines [ 0 ] ) ;
901- writeFolderActualValueEl . textContent = getWriteFolderDisplayPath ( entry ) ;
901+ const entries = await resolveEntries ( lines [ 0 ] ) ;
902+ if ( entries . length > 1 && entries [ 0 ] . targetType === "samples" ) {
903+ writeFolderActualValueEl . textContent = normalizeSlashes ( `samples/phase-${ entries [ 0 ] . phase } /*/${ getAssetFolderRelativePath ( ) } ` ) ;
904+ return ;
905+ }
906+
907+ writeFolderActualValueEl . textContent = entries . length ? getWriteFolderDisplayPath ( entries [ 0 ] ) : "not available yet" ;
902908 } catch {
903909 writeFolderActualValueEl . textContent = "not available yet" ;
904910 }
@@ -917,6 +923,54 @@ <h2 id="lastGeneratedImageTitle" class="preview-generator-v2__section-heading">L
917923 return await parentHandle . getFileHandle ( name , { create } ) ;
918924 }
919925
926+ function getSamplePhaseFolderMatch ( inputLine ) {
927+ return String ( inputLine || "" )
928+ . trim ( )
929+ . replaceAll ( "\\" , "/" )
930+ . replace ( / ^ \/ + | \/ + $ / g, "" )
931+ . match ( / ^ s a m p l e s \/ p h a s e - ? ( \d { 2 } ) $ / i) ;
932+ }
933+
934+ async function hasIndexHtml ( directoryHandle ) {
935+ try {
936+ await getFileHandle ( directoryHandle , "index.html" , false ) ;
937+ return true ;
938+ } catch {
939+ return false ;
940+ }
941+ }
942+
943+ async function resolveSamplePhase ( phase ) {
944+ if ( ! repoDirHandle ) {
945+ throw new Error ( "Pick the repo folder before using a phase folder input." ) ;
946+ }
947+
948+ const samplesDir = await getDirectoryHandle ( repoDirHandle , "samples" ) ;
949+ const phaseDir = await getDirectoryHandle ( samplesDir , `phase-${ phase } ` ) ;
950+ if ( typeof phaseDir . entries !== "function" ) {
951+ throw new Error ( `Cannot list samples/phase-${ phase } .` ) ;
952+ }
953+
954+ const sampleEntries = [ ] ;
955+ for await ( const [ name , handle ] of phaseDir . entries ( ) ) {
956+ if ( ! handle || handle . kind !== "directory" || ! / ^ \d { 4 } $ / . test ( name ) ) continue ;
957+ if ( ! ( await hasIndexHtml ( handle ) ) ) continue ;
958+ sampleEntries . push ( {
959+ targetType : "samples" ,
960+ id : name ,
961+ phase,
962+ samplePath : `samples/phase-${ phase } /${ name } /index.html`
963+ } ) ;
964+ }
965+
966+ sampleEntries . sort ( ( a , b ) => a . id . localeCompare ( b . id , undefined , { numeric : true } ) ) ;
967+ if ( ! sampleEntries . length ) {
968+ throw new Error ( `No sample index.html entries found in samples/phase-${ phase } .` ) ;
969+ }
970+
971+ return sampleEntries ;
972+ }
973+
920974 async function resolveSample ( inputLine ) {
921975 const raw = inputLine . trim ( ) ;
922976 if ( ! raw ) return null ;
@@ -1013,6 +1067,16 @@ <h2 id="lastGeneratedImageTitle" class="preview-generator-v2__section-heading">L
10131067 throw new Error ( `Unsupported target type: ${ targetType } ` ) ;
10141068 }
10151069
1070+ async function resolveEntries ( inputLine ) {
1071+ const phaseMatch = getSamplePhaseFolderMatch ( inputLine ) ;
1072+ if ( phaseMatch ) {
1073+ return await resolveSamplePhase ( phaseMatch [ 1 ] ) ;
1074+ }
1075+
1076+ const entry = await resolveEntry ( inputLine ) ;
1077+ return entry ? [ entry ] : [ ] ;
1078+ }
1079+
10161080 async function getTargetDirHandle ( repoHandle , entry ) {
10171081 if ( entry . targetType === "samples" ) {
10181082 const samplesDir = await getDirectoryHandle ( repoHandle , "samples" ) ;
@@ -1469,10 +1533,20 @@ <h2 id="lastGeneratedImageTitle" class="preview-generator-v2__section-heading">L
14691533 }
14701534
14711535 try {
1472- const entry = await resolveEntry ( line ) ;
1473- if ( ! entry ) continue ;
1474- const result = await processOne ( entry , baseUrl , waitMs ) ;
1475- results . push ( result ) ;
1536+ const entries = await resolveEntries ( line ) ;
1537+ if ( entries . length > 1 ) {
1538+ log ( `Resolved ${ entries . length } samples from ${ line } .` ) ;
1539+ }
1540+
1541+ for ( const entry of entries ) {
1542+ if ( stopRequested ) {
1543+ log ( "Stop requested. Ending run." ) ;
1544+ break ;
1545+ }
1546+
1547+ const result = await processOne ( entry , baseUrl , waitMs ) ;
1548+ results . push ( result ) ;
1549+ }
14761550 } catch ( error ) {
14771551 log ( `FAIL INPUT ${ line } (${ error . message } )` ) ;
14781552 log ( "" ) ;
0 commit comments