shots: feature rotate, per-language frame fallback, layout-aware capture selectors

This commit is contained in:
CRTkafa 2026-10-24 13:00:48 +08:00
parent 2e1c7cdc3c
commit 61b5fa0623
15 changed files with 355 additions and 17 deletions

View file

@ -15,7 +15,7 @@ import type { ShipConfig } from '../lib/config';
import type { Ctx } from '../lib/ctx';
import { log, printJson } from '../lib/log';
import { checkFrames, type FrameIssue } from './devices';
import { defaultSizes, frameDims, renderDims, SIZES } from './lib';
import { defaultSizes, frameDims, frameLangs, langHasFrames, renderDims, SIZES } from './lib';
import type { LocalIssue, RendersCheck } from '../lib/validate-rules';
import { allIssues, requiredSets, type RendersScan, resolvedTablets, scanRenders, storeOf } from './report';
import { imageInfo } from './spec';
@ -125,9 +125,13 @@ export async function run(ctx: Ctx): Promise<void> {
const tablets = resolvedTablets(config, resolve(ctx.args.get('src') ?? config.renders ?? config.shots?.out ?? 'store/renders'));
const issues = [...allIssues(scan), ...localFontIssues(readManifest(fontsDirOf(root))).map(issue => ({ where: '.storebound/fonts/fonts.json', issue })),
...backgroundIssues(config, resolve, tablets)];
const frameIssues = cap?.source === 'folder' ? checkFrameFolder(config, resolve(cap.folder ?? config.shots!.frames), scan.langs, tablets) : [];
// languages with copy but no frames use the default language's (shots.perLanguageFrames: true requires them per language)
const framesRoot = resolve(cap?.folder ?? config.shots!.frames), def = config.play?.defaultLanguage ?? config.languages[0]!.id;
const fl = frameLangs(scan.langs, l => langHasFrames(framesRoot, l), def, config.shots?.perLanguageFrames);
const frameIssues = cap?.source === 'folder' ? checkFrameFolder(config, framesRoot, scan.langs.filter(l => !fl.borrowed.includes(l)), tablets) : [];
if (fl.borrowed.length && !ctx.args.has('json')) console.log(`info frames: no frames for ${fl.borrowed.join(', ')}; they use the ${def} frames (shots.perLanguageFrames: true requires per-language frames)`);
if (ctx.args.has('json')) {
printJson({ images: scan.images.length, videos: scan.videos.length, issues, frames: frameIssues });
printJson({ images: scan.images.length, videos: scan.videos.length, issues, frames: frameIssues, info: fl.borrowed.map(l => ({ lang: l, framesFrom: def })) });
} else {
for (const { where, issue } of issues) console.log(`${issue.level === 'error' ? 'ERROR' : 'warn '} ${where}: ${issue.msg}`);
for (const f of frameIssues) console.log(`ERROR frames/${f.file}: ${f.msg}`);