Feature graphic fits the phone: shots.feature.fit 'contain' (default) sizes the device so its rotated box stays inside 1024x500 with a 24 px margin in both templates, 'bleed' keeps the crop, scale 0.5-1.5, config validated; shots render records measured device boxes (report.json devices) and shots check fails a feature graphic whose device leaves the canvas (warns for a screenshot's front device off a side or the top); tests/feature-fit.test.ts (rotated-box geometry, both templates rendered at 1024x500, bleeding fixture) (pitfall 55)
This commit is contained in:
parent
6e2dbf03cc
commit
19d34286d5
15 changed files with 239 additions and 12 deletions
|
|
@ -153,7 +153,11 @@ export interface ShotsConfig {
|
|||
* ['Noto Sans Display'] or a local file); a render that needs an automatic fallback is an ERROR in `shots check`. */
|
||||
fonts?: { title?: FontSpec; body?: FontSpec; fallback?: FontSpec[] };
|
||||
scenes: ShotScene[];
|
||||
feature?: { frame: string; palette?: string | Palette };
|
||||
/** Play feature graphic (1024 x 500): `frame` in the phone, `palette`. `fit` 'contain' (default) sizes the phone so
|
||||
* its rotated outline stays inside the canvas with a 24 px margin; 'bleed' keeps the larger phone cropped by the
|
||||
* bottom edge on purpose (shots check then allows it). `scale` (0.5-1.5, default 1) multiplies the phone's width
|
||||
* (still clamped to the canvas with 'contain'). */
|
||||
feature?: { frame: string; palette?: string | Palette; fit?: 'contain' | 'bleed'; scale?: number };
|
||||
/** Phone screen size of the raw frames in CSS px (default 440 x 902 @3x, iPhone 6.9" minus the 54 px status bar).
|
||||
* `bar` = status bar height the template draws above the frame (and that capture crops off). */
|
||||
phone?: { w: number; h: number; dpr?: number; bar?: number };
|
||||
|
|
@ -1133,6 +1137,11 @@ export function validateConfig(c: unknown): string[] {
|
|||
for (const k of ['copy', 'frames', 'out'] as const) if (!s[k]) e.push(`shots.${k}: missing`);
|
||||
if (s.style !== undefined && s.style !== 'game' && s.style !== 'app') e.push('shots.style: game | app');
|
||||
if (!s.scenes?.length) e.push('shots.scenes: at least one scene');
|
||||
if (s.feature !== undefined) {
|
||||
if (!s.feature || typeof s.feature.frame !== 'string' || !s.feature.frame) e.push('shots.feature.frame: a frame name');
|
||||
if (s.feature?.fit !== undefined && s.feature.fit !== 'contain' && s.feature.fit !== 'bleed') e.push("shots.feature.fit: 'contain' | 'bleed'");
|
||||
if (s.feature?.scale !== undefined && !(typeof s.feature.scale === 'number' && s.feature.scale >= 0.5 && s.feature.scale <= 1.5)) e.push('shots.feature.scale: a number from 0.5 to 1.5');
|
||||
}
|
||||
const fontKeys: [string, unknown][] = [['title', s.fonts?.title], ['body', s.fonts?.body], ...(Array.isArray(s.fonts?.fallback) ? s.fonts!.fallback! : s.fonts?.fallback !== undefined ? [s.fonts.fallback] : []).map((f, i) => [`fallback[${i}]`, f] as [string, unknown])];
|
||||
if (s.fonts?.fallback !== undefined && !Array.isArray(s.fonts.fallback)) e.push('shots.fonts.fallback: a list');
|
||||
for (const [k, f] of fontKeys) {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue