import glob from 'fast-glob'; import { getRepoRoot } from '../base-client/base-client.js'; import type { Message, Resource } from '@fluent/syntax'; import { FluentParser } from '@fluent/syntax'; import { readFileSync } from 'node:fs'; import { DEFAULT_LOCALE, SCREENSHOT_CHECK_EXCEPTIONS } from '../constants.js'; async function listFtlFiles() { const pattern = `**/${DEFAULT_LOCALE}.ftl`; // Matches all and only default locale .ftl files const gitRoot = getRepoRoot(); const options = { cwd: gitRoot, absolute: true, // Return absolute paths ignore: [ '**/node_modules/**', '**/dist/**', ...SCREENSHOT_CHECK_EXCEPTIONS.map( (exceptionPath) => `**/${exceptionPath}`, ), ], // Ignore node_modules and dist directories }; const files = await glob(pattern, options); return files; } async function getFtlKeysFromFile(filePath: string) { const parser = new FluentParser(); const data = readFileSync(filePath, 'utf8'); const resource: Resource = parser.parse(data); const keys = resource.body .filter((entry): entry is Message => entry.type === 'Message') .map((message: Message) => message.id.name); return keys; } // eslint-disable-next-line max-statements export async function checkScreenshots(): Promise { const files = await listFtlFiles(); const gitRootPath = getRepoRoot(); const missingScreenshots = []; for (const filePath of files) { const keys = await getFtlKeysFromFile(filePath); for (const key of keys) { const screenshotPath = filePath.replace( `${DEFAULT_LOCALE}.ftl`, `context-screenshots/${key}.png`, ); // Fail if screenshot doesn't exist try { readFileSync(screenshotPath); } catch { const relativePath = screenshotPath.replace(gitRootPath, ''); missingScreenshots.push(relativePath); } } } if (missingScreenshots.length > 0) { console.error('The following screenshots are missing:'); console.error(missingScreenshots); throw new Error('Screenshots are missing.'); } else { console.log('All screenshots are present.'); } }