food-market/src/food-market.public/scripts/optimize-screenshots.mjs
nns f7f92261ca
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Public / Build + push Public (test + latest) (push) Waiting to run
Docker Public / Deploy :test → test.food-market.kz (push) Blocked by required conditions
feat(site): свежие скриншоты ALL MARKET на витринных данных
Пересняты скриншоты публичного сайта в интерфейсе ALL MARKET на витринной
организации «Магазин у дома» (200 товаров, ~30 дней продаж, чистые данные
без e2e/test-мусора). Светлая тема, 1440×900 @2x, WebP + srcset, alt по-русски.

- screenshots.mjs: стенд + витринный владелец, 14 экранов (дашборд/каталог/
  карточка/приёмки/остатки/инвентаризация/деньги/отчёты/контрагенты), скрытие
  баннеров стенда/«что нового»/MoM-дельты, резолв AsyncSelect-подписей
- optimize-screenshots.mjs: PNG→WebP (1x 1440w / 2x 2880w) через canvas, все ≤300КБ
- pos-mockup/pos-mockup.html: светлая касса ALL MARKET «Магазин у дома» (продажа+оплата)
- index.astro: hero-дашборд + каталог + новый блок «Касса»; pos.astro: продажа+оплата
- ShowcaseSeeder: стартовый завоз всех товаров (нет отрицательных остатков)
- deploy/showcase-seed.sh: RESET=1 пересоздаёт витрину с нуля
- исходные PNG не коммитятся (.gitignore), доставка — только WebP

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-08 22:19:46 +05:00

59 lines
2.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Оптимизация скриншотов для сайта: PNG (2880×1800 @2x) → WebP с ресайзом и srcset.
// Без внешних зависимостей (sharp/cwebp недоступны на dev-vm) — кодируем через
// canvas.toDataURL('image/webp') в headless-Chromium (Playwright уже установлен).
//
// Для каждого исходного PNG из public/screenshots делает:
// <name>.webp — 1440w (служит 2x для ~720px-слота), качество 0.86
// <name>@2x.webp — 2880w (для srcset на крупных экранах), качество 0.82
// Все файлы ≤ 300 КБ (UI-скриншоты сжимаются отлично).
//
// Запуск: node scripts/optimize-screenshots.mjs
import { chromium } from 'playwright'
import path from 'node:path'
import fs from 'node:fs'
import { fileURLToPath, pathToFileURL } from 'node:url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const DIR = path.resolve(__dirname, '..', 'public', 'screenshots')
const CHROME = process.env.CHROME ?? '/usr/bin/google-chrome'
const pngs = fs.readdirSync(DIR).filter((f) => f.endsWith('.png'))
const browser = await chromium.launch({
headless: true, executablePath: CHROME, args: ['--no-sandbox', '--disable-dev-shm-usage'],
})
const page = await browser.newPage()
async function encode(srcPng, outName, targetW, quality) {
const dataUrl = 'data:image/png;base64,' + fs.readFileSync(path.join(DIR, srcPng)).toString('base64')
const b64 = await page.evaluate(async ({ url, targetW, quality }) => {
const img = new Image()
await new Promise((res, rej) => { img.onload = res; img.onerror = rej; img.src = url })
const scale = Math.min(1, targetW / img.naturalWidth)
const w = Math.round(img.naturalWidth * scale)
const h = Math.round(img.naturalHeight * scale)
const c = document.createElement('canvas')
c.width = w; c.height = h
const ctx = c.getContext('2d')
ctx.imageSmoothingEnabled = true
ctx.imageSmoothingQuality = 'high'
ctx.drawImage(img, 0, 0, w, h)
return c.toDataURL('image/webp', quality).split(',')[1]
}, { url: dataUrl, targetW, quality })
const buf = Buffer.from(b64, 'base64')
fs.writeFileSync(path.join(DIR, outName), buf)
return buf.length
}
for (const png of pngs) {
const base = png.replace(/\.png$/, '')
const s1 = await encode(png, `${base}.webp`, 1440, 0.86)
const s2 = await encode(png, `${base}@2x.webp`, 2880, 0.82)
const kb = (n) => (n / 1024).toFixed(0) + 'KB'
const warn = (s1 > 300 * 1024 || s2 > 300 * 1024) ? ' ⚠ >300KB' : ''
console.log(`${base}: 1x ${kb(s1)}, 2x ${kb(s2)}${warn}`)
}
await browser.close()
console.log('done')