docs: add screenshots of the studio and the script that takes them
fbeea9c parent: 09565f0 added
media/screenshots/angle.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/media/screenshots/angle.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/media/screenshots/angle.png differ | Binary files /dev/null and b/media/screenshots/angle.png differ | ||
added
media/screenshots/derush.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/media/screenshots/derush.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/media/screenshots/derush.png differ | Binary files /dev/null and b/media/screenshots/derush.png differ | ||
added
media/screenshots/details.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/media/screenshots/details.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/media/screenshots/details.png differ | Binary files /dev/null and b/media/screenshots/details.png differ | ||
added
media/screenshots/editing.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/media/screenshots/editing.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/media/screenshots/editing.png differ | Binary files /dev/null and b/media/screenshots/editing.png differ | ||
added
media/screenshots/overview.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/media/screenshots/overview.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/media/screenshots/overview.png differ | Binary files /dev/null and b/media/screenshots/overview.png differ | ||
added
media/screenshots/projects.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/media/screenshots/projects.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/media/screenshots/projects.png differ | Binary files /dev/null and b/media/screenshots/projects.png differ | ||
added
media/screenshots/script.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/media/screenshots/script.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/media/screenshots/script.png differ | Binary files /dev/null and b/media/screenshots/script.png differ | ||
added
media/screenshots/storyboard.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/media/screenshots/storyboard.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/media/screenshots/storyboard.png differ | Binary files /dev/null and b/media/screenshots/storyboard.png differ | ||
added
media/screenshots/thumbnail.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/media/screenshots/thumbnail.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/media/screenshots/thumbnail.png differ | Binary files /dev/null and b/media/screenshots/thumbnail.png differ | ||
added
media/screenshots/titles.png +0 -0 | new file mode 100644 | ||
| Binary files /dev/null and b/media/screenshots/titles.png differ | ||
| new file mode 100644 | |||
| Binary files /dev/null and b/media/screenshots/titles.png differ | Binary files /dev/null and b/media/screenshots/titles.png differ | ||
modified
web/package.json +3 -1 | @@ -7,7 +7,8 @@ | ||
| 7 | 7 | "scripts": { |
| 8 | 8 | "dev": "vite", |
| 9 | 9 | "build": "vue-tsc --noEmit && vite build", |
| 10 | - "typecheck": "vue-tsc --noEmit" | |
| 10 | + "typecheck": "vue-tsc --noEmit", | |
| 11 | + "screenshots": "node scripts/screenshots.mjs" | |
| 11 | 12 | }, |
| 12 | 13 | "dependencies": { |
| 13 | 14 | "@tiptap/core": "^3.31.4", |
| @@ -24,6 +25,7 @@ | ||
| 24 | 25 | "devDependencies": { |
| 25 | 26 | "@types/node": "^26.6.4", |
| 26 | 27 | "@vitejs/plugin-vue": "^6.0.9", |
| 28 | + "playwright": "1.65.0", | |
| 27 | 29 | "typescript": "^5.9.3", |
| 28 | 30 | "vite": "^8.3.2", |
| 29 | 31 | "vue-tsc": "^3.3.12" |
| @@ -7,7 +7,8 @@ | |||
| 7 | "scripts": { | 7 | "scripts": { |
| 8 | "dev": "vite", | 8 | "dev": "vite", |
| 9 | "build": "vue-tsc --noEmit && vite build", | 9 | "build": "vue-tsc --noEmit && vite build", |
| 10 | - "typecheck": "vue-tsc --noEmit" | 10 | + "typecheck": "vue-tsc --noEmit", |
| 11 | + "screenshots": "node scripts/screenshots.mjs" | ||
| 11 | }, | 12 | }, |
| 12 | "dependencies": { | 13 | "dependencies": { |
| 13 | "@tiptap/core": "^3.31.4", | 14 | "@tiptap/core": "^3.31.4", |
| @@ -24,6 +25,7 @@ | |||
| 24 | "devDependencies": { | 25 | "devDependencies": { |
| 25 | "@types/node": "^26.6.4", | 26 | "@types/node": "^26.6.4", |
| 26 | "@vitejs/plugin-vue": "^6.0.9", | 27 | "@vitejs/plugin-vue": "^6.0.9", |
| 28 | + "playwright": "1.65.0", | ||
| 27 | "typescript": "^5.9.3", | 29 | "typescript": "^5.9.3", |
| 28 | "vite": "^8.3.2", | 30 | "vite": "^8.3.2", |
| 29 | "vue-tsc": "^3.3.12" | 31 | "vue-tsc": "^3.3.12" |
modified
web/pnpm-lock.yaml +19 -0 | @@ -45,6 +45,9 @@ importers: | ||
| 45 | 45 | '@vitejs/plugin-vue': |
| 46 | 46 | specifier: ^6.0.9 |
| 47 | 47 | version: 6.0.9(vite@8.3.2(@types/node@26.6.4))(vue@3.5.43(typescript@5.9.3)) |
| 48 | + playwright: | |
| 49 | + specifier: 1.65.0 | |
| 50 | + version: 1.65.0 | |
| 48 | 51 | typescript: |
| 49 | 52 | specifier: ^5.9.3 |
| 50 | 53 | version: 5.9.3 |
| @@ -636,6 +639,16 @@ packages: | ||
| 636 | 639 | pkg-types@2.3.3: |
| 637 | 640 | resolution: {integrity: sha512-j/lCFdcppV0JxWpCEITdbDltBxPP6cHT+yNJ6Go2OgoSA9518X847X9z0p6LtA4Nc16+eQzCZjRrWanTGvHJ5w==} |
| 638 | 641 | |
| 642 | + playwright-core@1.65.0: | |
| 643 | + resolution: {integrity: sha512-vNSKgH6YqtN7cdT/L334zo0a+YwkrpicyrHJlWWPIm/Q+Nn2SWInil01oT0mbu96U4GgoRtCYQD9CzJQgju+lA==} | |
| 644 | + engines: {node: '>=20'} | |
| 645 | + hasBin: true | |
| 646 | + | |
| 647 | + playwright@1.65.0: | |
| 648 | + resolution: {integrity: sha512-F3AMWcR44qMBt4kq+6Kb6mX7bjGXshktKFOPULd7reED6ZJWevjbNRqysP7q+AATE9kdPEZBibex1BYsvpVoeA==} | |
| 649 | + engines: {node: '>=20'} | |
| 650 | + hasBin: true | |
| 651 | + | |
| 639 | 652 | postcss@8.5.28: |
| 640 | 653 | resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==} |
| 641 | 654 | engines: {node: ^10 || ^12 || >=14} |
| @@ -1395,6 +1408,12 @@ snapshots: | ||
| 1395 | 1408 | exsolve: 1.1.1 |
| 1396 | 1409 | pathe: 2.0.3 |
| 1397 | 1410 | |
| 1411 | + playwright-core@1.65.0: {} | |
| 1412 | + | |
| 1413 | + playwright@1.65.0: | |
| 1414 | + dependencies: | |
| 1415 | + playwright-core: 1.65.0 | |
| 1416 | + | |
| 1398 | 1417 | postcss@8.5.28: |
| 1399 | 1418 | dependencies: |
| 1400 | 1419 | nanoid: 3.3.19 |
| @@ -45,6 +45,9 @@ importers: | |||
| 45 | '@vitejs/plugin-vue': | 45 | '@vitejs/plugin-vue': |
| 46 | specifier: ^6.0.9 | 46 | specifier: ^6.0.9 |
| 47 | version: 6.0.9(vite@8.3.2(@types/node@26.6.4))(vue@3.5.43(typescript@5.9.3)) | 47 | version: 6.0.9(vite@8.3.2(@types/node@26.6.4))(vue@3.5.43(typescript@5.9.3)) |
| 48 | + playwright: | ||
| 49 | + specifier: 1.65.0 | ||
| 50 | + version: 1.65.0 | ||
| 48 | typescript: | 51 | typescript: |
| 49 | specifier: ^5.9.3 | 52 | specifier: ^5.9.3 |
| 50 | version: 5.9.3 | 53 | version: 5.9.3 |
| @@ -636,6 +639,16 @@ packages: | |||
| 636 | pkg-types@2.3.3: | 639 | pkg-types@2.3.3: |
| 637 | resolution: {integrity: sha512-j/lCFdcppV0JxWpCEITdbDltBxPP6cHT+yNJ6Go2OgoSA9518X847X9z0p6LtA4Nc16+eQzCZjRrWanTGvHJ5w==} | 640 | resolution: {integrity: sha512-j/lCFdcppV0JxWpCEITdbDltBxPP6cHT+yNJ6Go2OgoSA9518X847X9z0p6LtA4Nc16+eQzCZjRrWanTGvHJ5w==} |
| 638 | 641 | ||
| 642 | + playwright-core@1.65.0: | ||
| 643 | + resolution: {integrity: sha512-vNSKgH6YqtN7cdT/L334zo0a+YwkrpicyrHJlWWPIm/Q+Nn2SWInil01oT0mbu96U4GgoRtCYQD9CzJQgju+lA==} | ||
| 644 | + engines: {node: '>=20'} | ||
| 645 | + hasBin: true | ||
| 646 | + | ||
| 647 | + playwright@1.65.0: | ||
| 648 | + resolution: {integrity: sha512-F3AMWcR44qMBt4kq+6Kb6mX7bjGXshktKFOPULd7reED6ZJWevjbNRqysP7q+AATE9kdPEZBibex1BYsvpVoeA==} | ||
| 649 | + engines: {node: '>=20'} | ||
| 650 | + hasBin: true | ||
| 651 | + | ||
| 639 | postcss@8.5.28: | 652 | postcss@8.5.28: |
| 640 | resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==} | 653 | resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==} |
| 641 | engines: {node: ^10 || ^12 || >=14} | 654 | engines: {node: ^10 || ^12 || >=14} |
| @@ -1395,6 +1408,12 @@ snapshots: | |||
| 1395 | exsolve: 1.1.1 | 1408 | exsolve: 1.1.1 |
| 1396 | pathe: 2.0.3 | 1409 | pathe: 2.0.3 |
| 1397 | 1410 | ||
| 1411 | + playwright-core@1.65.0: {} | ||
| 1412 | + | ||
| 1413 | + playwright@1.65.0: | ||
| 1414 | + dependencies: | ||
| 1415 | + playwright-core: 1.65.0 | ||
| 1416 | + | ||
| 1398 | postcss@8.5.28: | 1417 | postcss@8.5.28: |
| 1399 | dependencies: | 1418 | dependencies: |
| 1400 | nanoid: 3.3.19 | 1419 | nanoid: 3.3.19 |
added
web/scripts/screenshots.mjs +51 -0 | new file mode 100644 | ||
| @@ -0,0 +1,51 @@ | ||
| 1 | +// Captures the screens shown in the README and on the site (media/screenshots), from a running studio. | |
| 2 | +// | |
| 3 | +// cd web; node scripts/screenshots.mjs [baseUrl] [--only name,name] | |
| 4 | +// | |
| 5 | +// baseUrl defaults to https://localhost:4400 (python -m studio dev). The shots use your own projects: | |
| 6 | +// change the ids in SHOTS. The interface is forced to English for the capture, without touching your setting. | |
| 7 | +import { mkdir } from 'node:fs/promises' | |
| 8 | +import { fileURLToPath } from 'node:url' | |
| 9 | +import { chromium } from 'playwright' | |
| 10 | + | |
| 11 | +const args = process.argv.slice(2) | |
| 12 | +const base = (args.find((a) => !a.startsWith('--')) ?? 'https://localhost:4400').replace(/\/$/, '') | |
| 13 | +const onlyArg = args.indexOf('--only') | |
| 14 | +const only = onlyArg >= 0 ? args[onlyArg + 1].split(',') : null | |
| 15 | +const out = fileURLToPath(new URL('../../media/screenshots/', import.meta.url)) | |
| 16 | + | |
| 17 | +/** [file name, path, extra wait in ms] */ | |
| 18 | +const SHOTS = [ | |
| 19 | + ['projects', '/'], | |
| 20 | + ['overview', '/p/509402e9a5'], | |
| 21 | + ['angle', '/p/f728f85ffb/angle'], | |
| 22 | + ['titles', '/p/f728f85ffb/titre'], | |
| 23 | + ['thumbnail', '/p/fa848779b9/vignette'], | |
| 24 | + ['script', '/p/509402e9a5/script'], | |
| 25 | + ['derush', '/p/509402e9a5/derush'], | |
| 26 | + ['storyboard', '/p/619afee567/storyboard', 1500], | |
| 27 | + ['editing', '/p/509402e9a5/montage', 2500], | |
| 28 | + ['details', '/p/f728f85ffb/description'], | |
| 29 | +] | |
| 30 | + | |
| 31 | +await mkdir(out, { recursive: true }) | |
| 32 | +const browser = await chromium.launch() | |
| 33 | +const context = await browser.newContext({ | |
| 34 | + viewport: { width: 1440, height: 900 }, | |
| 35 | + deviceScaleFactor: 2, | |
| 36 | + ignoreHTTPSErrors: true, | |
| 37 | + locale: 'en-US', | |
| 38 | +}) | |
| 39 | +await context.addInitScript(() => localStorage.setItem('studio.locale', 'en')) | |
| 40 | +const page = await context.newPage() | |
| 41 | + | |
| 42 | +for (const [name, path, wait = 0] of SHOTS) { | |
| 43 | + if (only && !only.includes(name)) continue | |
| 44 | + await page.goto(base + path, { waitUntil: 'networkidle' }) | |
| 45 | + await page.evaluate(() => document.fonts.ready) | |
| 46 | + await page.waitForTimeout(800 + wait) | |
| 47 | + await page.screenshot({ path: `${out}${name}.png` }) | |
| 48 | + console.log(`${name}.png ${path}`) | |
| 49 | +} | |
| 50 | + | |
| 51 | +await browser.close() | |
| new file mode 100644 | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | +// Captures the screens shown in the README and on the site (media/screenshots), from a running studio. | ||
| 2 | +// | ||
| 3 | +// cd web; node scripts/screenshots.mjs [baseUrl] [--only name,name] | ||
| 4 | +// | ||
| 5 | +// baseUrl defaults to https://localhost:4400 (python -m studio dev). The shots use your own projects: | ||
| 6 | +// change the ids in SHOTS. The interface is forced to English for the capture, without touching your setting. | ||
| 7 | +import { mkdir } from 'node:fs/promises' | ||
| 8 | +import { fileURLToPath } from 'node:url' | ||
| 9 | +import { chromium } from 'playwright' | ||
| 10 | + | ||
| 11 | +const args = process.argv.slice(2) | ||
| 12 | +const base = (args.find((a) => !a.startsWith('--')) ?? 'https://localhost:4400').replace(/\/$/, '') | ||
| 13 | +const onlyArg = args.indexOf('--only') | ||
| 14 | +const only = onlyArg >= 0 ? args[onlyArg + 1].split(',') : null | ||
| 15 | +const out = fileURLToPath(new URL('../../media/screenshots/', import.meta.url)) | ||
| 16 | + | ||
| 17 | +/** [file name, path, extra wait in ms] */ | ||
| 18 | +const SHOTS = [ | ||
| 19 | + ['projects', '/'], | ||
| 20 | + ['overview', '/p/509402e9a5'], | ||
| 21 | + ['angle', '/p/f728f85ffb/angle'], | ||
| 22 | + ['titles', '/p/f728f85ffb/titre'], | ||
| 23 | + ['thumbnail', '/p/fa848779b9/vignette'], | ||
| 24 | + ['script', '/p/509402e9a5/script'], | ||
| 25 | + ['derush', '/p/509402e9a5/derush'], | ||
| 26 | + ['storyboard', '/p/619afee567/storyboard', 1500], | ||
| 27 | + ['editing', '/p/509402e9a5/montage', 2500], | ||
| 28 | + ['details', '/p/f728f85ffb/description'], | ||
| 29 | +] | ||
| 30 | + | ||
| 31 | +await mkdir(out, { recursive: true }) | ||
| 32 | +const browser = await chromium.launch() | ||
| 33 | +const context = await browser.newContext({ | ||
| 34 | + viewport: { width: 1440, height: 900 }, | ||
| 35 | + deviceScaleFactor: 2, | ||
| 36 | + ignoreHTTPSErrors: true, | ||
| 37 | + locale: 'en-US', | ||
| 38 | +}) | ||
| 39 | +await context.addInitScript(() => localStorage.setItem('studio.locale', 'en')) | ||
| 40 | +const page = await context.newPage() | ||
| 41 | + | ||
| 42 | +for (const [name, path, wait = 0] of SHOTS) { | ||
| 43 | + if (only && !only.includes(name)) continue | ||
| 44 | + await page.goto(base + path, { waitUntil: 'networkidle' }) | ||
| 45 | + await page.evaluate(() => document.fonts.ready) | ||
| 46 | + await page.waitForTimeout(800 + wait) | ||
| 47 | + await page.screenshot({ path: `${out}${name}.png` }) | ||
| 48 | + console.log(`${name}.png ${path}`) | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +await browser.close() | ||