shots: app titles get the weights the templates use (variable axis, used range or static weights; font-weight warning), palette.bg as one colour or a CSS gradient string (validated; contrast guard in shots check), photo backgrounds (palette.image, shots.feature.background) with overlay and cover crop

This commit is contained in:
CRTkafa 2026-10-20 13:37:37 +07:00
parent 2ba8278ab7
commit 3a11682a37
21 changed files with 713 additions and 44 deletions

View file

@ -5,6 +5,8 @@ import { join } from 'node:path';
import { spawnSync } from 'node:child_process';
import { boxOutside, type DeviceBox, marginViolations, PLAY_TABLET_SIZES, SIZES, type TextBox } from './lib';
import { fontIssues, type FontUsage } from './glyphs';
import { type ContrastSample, contrastIssues } from './palette';
import { type WeightSample, weightIssues } from './weights';
import { pulledEntry, readPulled } from '../lib/art-pull';
import { checkCount, checkImage, checkVideo, type ImageInfo, imageInfo, type Issue, IMAGE_SPECS, parseProbe, PREVIEW_RULES, type ProbeInfo, VIDEO_TARGETS } from './spec';
@ -14,7 +16,9 @@ export type RenderReport = Record<string, { overflow: string[]; missing?: string
/** Device frames' bounding boxes (the rotated outline, from the page's layout) in image px; bleed = cropped on purpose. */
devices?: DeviceBox[]; bleed?: boolean;
/** Text and logo boxes in image px (from the page's layout), for the safe-margin rule (lib.ts marginViolations). */
boxes?: TextBox[] }>;
boxes?: TextBox[];
/** Title weight asked vs. served (weights.ts), and title ink contrast over the pixels behind it (palette.ts). */
weights?: WeightSample[]; contrast?: ContrastSample[] }>;
/** Text or logo closer to an edge than the safe margin: an error (stores crop and round corners; it reads cramped). */
export function marginIssues(entry: RenderReport[string] | undefined, W: number, H: number): Issue[] {
@ -88,6 +92,7 @@ export function scanRenders(dir: string, o: { langs: string[]; variants?: string
issues.push(...fontIssues(entry?.fonts));
issues.push(...deviceIssues(entry, size, info.w, info.h));
issues.push(...marginIssues(entry, info.w, info.h));
issues.push(...weightIssues(entry?.weights), ...contrastIssues(entry?.contrast));
if (entry && !entry.fonts) issues.push({ level: 'warn', code: 'fonts', msg: 'font usage not recorded (rendered by an older storebound): run shots fonts + shots render again so missing glyphs are caught' });
out.images.push({ rel, lang, variant, size, file, info, issues });
}