diff --git a/package.json b/package.json index 5632e02..c15b41b 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "dev": "vite", "build": "vite build", "build:icons": "node scripts/generate-icons.js", + "screenshot": "node scripts/make-screenshot.js", "zip": "node scripts/build-zip.js", "test": "node --test" }, diff --git a/public/screenshot1.png b/public/screenshot1.png new file mode 100644 index 0000000..a03ea73 Binary files /dev/null and b/public/screenshot1.png differ diff --git a/public/store-screenshot-1280x800.png b/public/store-screenshot-1280x800.png new file mode 100644 index 0000000..696c32a Binary files /dev/null and b/public/store-screenshot-1280x800.png differ diff --git a/public/store-screenshot-640x400.png b/public/store-screenshot-640x400.png new file mode 100644 index 0000000..f94ac7f Binary files /dev/null and b/public/store-screenshot-640x400.png differ diff --git a/scripts/build-zip.js b/scripts/build-zip.js index 1518f91..8b4d0c1 100644 --- a/scripts/build-zip.js +++ b/scripts/build-zip.js @@ -6,8 +6,15 @@ console.log('Building OpenScript extension...'); fs.rmSync('dist', { recursive: true, force: true }); execSync('npx vite build', { stdio: 'inherit' }); -// Remove unneeded master images from dist package -['dist/icons/OpenScript_v1.png', 'dist/icons/OpenScript_v2.png', 'dist/icons/logo.png'].forEach(f => { +// Remove unneeded master images and screenshots from dist package +[ + 'dist/icons/OpenScript_v1.png', + 'dist/icons/OpenScript_v2.png', + 'dist/icons/logo.png', + 'dist/screenshot1.png', + 'dist/store-screenshot-1280x800.png', + 'dist/store-screenshot-640x400.png' +].forEach(f => { if (fs.existsSync(f)) fs.unlinkSync(f); }); diff --git a/scripts/make-screenshot.js b/scripts/make-screenshot.js new file mode 100644 index 0000000..77c77e5 --- /dev/null +++ b/scripts/make-screenshot.js @@ -0,0 +1,138 @@ +import sharp from 'sharp'; +import fs from 'fs'; + +async function generate() { + const popupSrc = 'public/screenshot1.png'; + const meta = await sharp(popupSrc).metadata(); + + const canvasW = 1280; + const canvasH = 800; + + // Scale popup card to 690px height + const targetH = 690; + const targetW = Math.round((meta.width / meta.height) * targetH); + const rx = 14; + + const maskSvg = Buffer.from(` + + + + `); + + const roundedPopup = await sharp(popupSrc) + .resize(targetW, targetH, { fit: 'fill' }) + .composite([{ input: maskSvg, blend: 'dest-in' }]) + .png() + .toBuffer(); + + const x = Math.round((canvasW - targetW) / 2); + const y = Math.round((canvasH - targetH) / 2); + + // Rounded icon badge for top-left + const iconRx = 8; + const iconMask = Buffer.from(` + + + + `); + + const logoBuf = await sharp('public/icons/icon-48.png') + .resize(40, 40) + .composite([{ input: iconMask, blend: 'dest-in' }]) + .png() + .toBuffer(); + + const bgSvg = Buffer.from(` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OpenScript + + + Lightweight MV3 User Script Manager + + + + + + + + Manifest V3 + + + + + + Sync Secrets + + + + `); + + const borderSvg = Buffer.from(` + + + + `); + + const final1280 = await sharp(bgSvg) + .composite([ + { input: logoBuf, top: 40, left: 56 }, + { input: roundedPopup, top: y, left: x }, + { input: borderSvg, top: y, left: x } + ]) + .png() + .toBuffer(); + + await sharp(final1280).toFile('public/store-screenshot-1280x800.png'); + console.log('✓ Generated public/store-screenshot-1280x800.png (1280x800)'); + + await sharp(final1280) + .resize(640, 400) + .png() + .toFile('public/store-screenshot-640x400.png'); + console.log('✓ Generated public/store-screenshot-640x400.png (640x400)'); +} + +generate();