Skip to content

Commit 772b5ca

Browse files
author
DavidQ
committed
new preview images
1 parent f8875cf commit 772b5ca

19 files changed

Lines changed: 498 additions & 148 deletions

File tree

docs/dev/codex_commands.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Codex Commands - PR_26126_025-preview-generator-v2-phase-wildcard-support
2+
3+
```bash
4+
codex run "Create PR_26126_025-preview-generator-v2-phase-wildcard-support. Update Preview Generator V2 to support phase-wide sample generation. Add \"samples/phase-xx\" to the Samples examples as a valid input pattern meaning generate previews for all sample images in that phase folder. Implement supporting code so when the Paths or IDs input receives a phase folder pattern such as samples/phase-01 or samples/phase-xx, the tool resolves all eligible sample index.html entries/images under that phase and processes them using the existing preview generation behavior. Preserve existing single sample and game behavior. Do not modify samples. Do not add schema. Produce review artifacts."
5+
```
6+
7+
## Validation Commands
8+
9+
```bash
10+
git diff --check -- tools/preview-generator-v2/index.html docs/dev/codex_commands.md docs/dev/commit_comment.txt
11+
git diff --cached --name-only -- samples games start_of_day tools/shared tools/schemas
12+
npm run test:workspace-v2
13+
npm run codex:review-artifacts
14+
```
15+
16+
```powershell
17+
@'
18+
import { chromium } from '@playwright/test';
19+
import { startRepoServer } from './tests/helpers/playwrightRepoServer.mjs';
20+
21+
const server = await startRepoServer();
22+
const browser = await chromium.launch({ headless: true });
23+
const page = await browser.newPage({ viewport: { width: 1366, height: 900 } });
24+
const errors = [];
25+
const consoleErrors = [];
26+
page.on('pageerror', (error) => errors.push(error.message));
27+
page.on('console', (message) => {
28+
if (message.type() === 'error') consoleErrors.push(message.text());
29+
});
30+
await page.route('https://cdn.jsdelivr.net/**', async (route) => {
31+
await route.fulfill({ status: 200, contentType: 'text/javascript', body: 'window.html2canvas = window.html2canvas || undefined;' });
32+
});
33+
await page.route('**/samples/phase-01/**/index.html', async (route) => {
34+
await route.fulfill({
35+
status: 200,
36+
contentType: 'text/html',
37+
body: '<!doctype html><html><body><canvas id="c" width="12" height="12"></canvas><script>const c=document.getElementById("c");const ctx=c.getContext("2d");ctx.fillStyle="#00ff00";ctx.fillRect(0,0,12,12);</script></body></html>'
38+
});
39+
});
40+
await page.addInitScript(() => {
41+
const writes = [];
42+
class FakeFile {
43+
constructor(text) { this._text = text; }
44+
async text() { return this._text; }
45+
}
46+
class FakeFileHandle {
47+
constructor(name, path, text = '') { this.kind = 'file'; this.name = name; this.path = path; this._text = text; }
48+
async getFile() { return new FakeFile(this._text); }
49+
async createWritable() {
50+
const handle = this;
51+
return {
52+
async write(content) {
53+
handle._text = String(content);
54+
writes.push({ path: handle.path, content: String(content) });
55+
},
56+
async close() {}
57+
};
58+
}
59+
}
60+
class FakeDirectoryHandle {
61+
constructor(name = 'HTML-JavaScript-Gaming', path = '') { this.kind = 'directory'; this.name = name; this.path = path; this.children = new Map(); }
62+
async getDirectoryHandle(name, options = {}) {
63+
const key = `dir:${name}`;
64+
if (!this.children.has(key)) {
65+
if (!options.create) throw new DOMException('Not found', 'NotFoundError');
66+
const nextPath = this.path ? `${this.path}/${name}` : name;
67+
this.children.set(key, new FakeDirectoryHandle(name, nextPath));
68+
}
69+
return this.children.get(key);
70+
}
71+
async getFileHandle(name, options = {}) {
72+
const key = `file:${name}`;
73+
if (!this.children.has(key)) {
74+
if (!options.create) throw new DOMException('Not found', 'NotFoundError');
75+
const nextPath = this.path ? `${this.path}/${name}` : name;
76+
this.children.set(key, new FakeFileHandle(name, nextPath));
77+
}
78+
return this.children.get(key);
79+
}
80+
async *entries() {
81+
const sorted = Array.from(this.children.values()).sort((a, b) => b.name.localeCompare(a.name));
82+
for (const child of sorted) yield [child.name, child];
83+
}
84+
}
85+
async function addFile(root, path, text = '') {
86+
const parts = path.split('/').filter(Boolean);
87+
let current = root;
88+
for (const part of parts.slice(0, -1)) current = await current.getDirectoryHandle(part, { create: true });
89+
const fileHandle = await current.getFileHandle(parts.at(-1), { create: true });
90+
fileHandle._text = text;
91+
}
92+
async function addDir(root, path) {
93+
const parts = path.split('/').filter(Boolean);
94+
let current = root;
95+
for (const part of parts) current = await current.getDirectoryHandle(part, { create: true });
96+
}
97+
window.__previewGeneratorV2Writes = writes;
98+
window.__previewGeneratorV2Root = new FakeDirectoryHandle();
99+
window.__previewGeneratorV2Ready = (async () => {
100+
await addFile(window.__previewGeneratorV2Root, 'samples/phase-01/0101/index.html');
101+
await addFile(window.__previewGeneratorV2Root, 'samples/phase-01/0102/index.html');
102+
await addDir(window.__previewGeneratorV2Root, 'samples/phase-01/0199');
103+
})();
104+
window.showDirectoryPicker = async () => {
105+
await window.__previewGeneratorV2Ready;
106+
return window.__previewGeneratorV2Root;
107+
};
108+
});
109+
110+
await page.goto(`${server.baseUrl}/tools/preview-generator-v2/index.html`, { waitUntil: 'domcontentloaded' });
111+
await page.waitForSelector('#sampleList');
112+
const placeholder = await page.locator('#sampleList').getAttribute('placeholder');
113+
if (!placeholder.includes('samples/phase-xx')) throw new Error('Phase-wide sample example is missing.');
114+
await page.fill('#baseUrl', server.baseUrl);
115+
await page.fill('#waitMs', '1');
116+
await page.fill('#sampleList', 'samples/phase-01');
117+
await page.check('#targetTypeSamples');
118+
await page.click('#pickRepoBtn');
119+
await page.waitForFunction(() => !document.getElementById('executeBtn').disabled);
120+
await page.click('#executeBtn');
121+
await page.waitForFunction(() => document.getElementById('log').textContent.includes('Done.'), null, { timeout: 20000 });
122+
const logText = await page.locator('#log').innerText();
123+
if (!logText.includes('Resolved 2 samples from samples/phase-01.')) throw new Error(`Missing phase resolution log: ${logText}`);
124+
if (!logText.includes('OK 0101') || !logText.includes('OK 0102')) throw new Error(`Expected both phase samples to process: ${logText}`);
125+
if (logText.includes('0199')) throw new Error(`Sample folder without index.html should be skipped: ${logText}`);
126+
const writes = await page.evaluate(() => window.__previewGeneratorV2Writes || []);
127+
const paths = writes.map((write) => write.path).sort();
128+
const expectedPaths = [
129+
'samples/phase-01/0101/assets/images/preview.svg',
130+
'samples/phase-01/0102/assets/images/preview.svg'
131+
];
132+
if (JSON.stringify(paths) !== JSON.stringify(expectedPaths)) throw new Error(`Unexpected writes: ${paths.join(' | ')}`);
133+
if (errors.length || consoleErrors.length) throw new Error([...errors, ...consoleErrors].join(' | '));
134+
await browser.close();
135+
await server.close();
136+
console.log('preview-generator-v2 phase-wide sample generation smoke valid');
137+
'@ | node --input-type=module -
138+
```
139+
140+
## Notes
141+
142+
The targeted Playwright smoke validates that the `samples/phase-xx` example is present, `samples/phase-01` expands through the selected repo folder into indexed sample entries, non-indexed folders are skipped, and the existing preview generation path writes `preview.svg` for each resolved sample.
143+
144+
`npm run test:workspace-v2` was attempted, but the script is not defined in this checkout.
145+
146+
Full samples smoke test was skipped because this PR is scoped to Preview Generator V2 phase-folder resolution and uses targeted browser coverage instead.

docs/dev/commit_comment.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Reorder Preview Generator V2 examples - PR_26126_024-preview-generator-v2-examples-order
1+
Support phase-wide Preview Generator V2 samples - PR_26126_025-preview-generator-v2-phase-wildcard-support
Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,35 @@
1-
# git status --short
2-
M docs/dev/codex_commands.md
1+
# intended PR_26126_025 delta files
2+
A docs/dev/codex_commands.md
33
M docs/dev/commit_comment.txt
4+
M docs/dev/reports/codex_changed_files.txt
5+
M docs/dev/reports/codex_review.diff
46
M tools/preview-generator-v2/index.html
57

6-
# git diff --stat
7-
(no output)
8+
# implementation diff source
9+
git diff HEAD^ HEAD -- tools/preview-generator-v2/index.html
10+
git diff --cached -- docs/dev/codex_commands.md docs/dev/commit_comment.txt
11+
12+
# scoped validation: staged changes under samples/games/start_of_day/tools/shared/tools/schemas
13+
(none)
14+
15+
# unstaged sample preview SVG changes present in worktree and excluded from this PR package
16+
M samples/phase-01/0106/assets/images/preview.svg
17+
M samples/phase-01/0108/assets/images/preview.svg
18+
M samples/phase-01/0109/assets/images/preview.svg
19+
M samples/phase-01/0111/assets/images/preview.svg
20+
M samples/phase-01/0112/assets/images/preview.svg
21+
M samples/phase-01/0113/assets/images/preview.svg
22+
M samples/phase-01/0114/assets/images/preview.svg
23+
M samples/phase-01/0115/assets/images/preview.svg
24+
M samples/phase-01/0116/assets/images/preview.svg
25+
M samples/phase-01/0118/assets/images/preview.svg
26+
M samples/phase-01/0119/assets/images/preview.svg
27+
M samples/phase-01/0120/assets/images/preview.svg
28+
M samples/phase-01/0121/assets/images/preview.svg
29+
M samples/phase-01/0122/assets/images/preview.svg
30+
M samples/phase-01/0123/assets/images/preview.svg
31+
M samples/phase-01/0124/assets/images/preview.svg
32+
33+
# tool diff stat
34+
tools/preview-generator-v2/index.html | 86 ++++++++++++++++++++++++++++++++---
35+
1 file changed, 80 insertions(+), 6 deletions(-)

0 commit comments

Comments
 (0)