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
Пересняты скриншоты публичного сайта в интерфейсе 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>
59 lines
2.7 KiB
JavaScript
59 lines
2.7 KiB
JavaScript
// Оптимизация скриншотов для сайта: 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')
|