Skip to content

Commit f8875cf

Browse files
author
DavidQ
committed
Add phase-wide sample preview generation support to Preview Generator V2 - PR_26126_025-preview-generator-v2-phase-wildcard-support
1 parent 6013519 commit f8875cf

6 files changed

Lines changed: 92 additions & 76 deletions

File tree

docs/dev/codex_commands.md

Lines changed: 0 additions & 58 deletions
This file was deleted.

samples/phase-01/0101/assets/images/preview.svg

Lines changed: 3 additions & 3 deletions
Loading

samples/phase-01/0103/assets/images/preview.svg

Lines changed: 3 additions & 3 deletions
Loading

samples/phase-01/0104/assets/images/preview.svg

Lines changed: 3 additions & 3 deletions
Loading

samples/phase-01/0105/assets/images/preview.svg

Lines changed: 3 additions & 3 deletions
Loading

tools/preview-generator-v2/index.html

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ <h2 id="pathsOrIdsTitle" class="preview-generator-v2__section-heading">Paths or
480480
&lt;gamename&gt;
481481
482482
Samples examples:
483+
samples/phase-xx
483484
samples/phase-01/0102/index.html
484485
samples/phase-13/1303/index.html
485486
0107
@@ -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(/^samples\/phase-?(\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

Comments
 (0)