diff options
| author | Bobby <[email protected]> | 2025-11-05 21:01:53 +0530 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-11-05 21:01:53 +0530 |
| commit | 24828d90e04a4fdbdf43d5e8400d86bf4404316a (patch) | |
| tree | ec7229b4a851994382ae8c779a63c5385b1be3d3 | |
| parent | dd24efb436a67b8d18734184d0456446749e184f (diff) | |
| download | unwordled-24828d90e04a4fdbdf43d5e8400d86bf4404316a.tar.xz unwordled-24828d90e04a4fdbdf43d5e8400d86bf4404316a.zip | |
Implement OG image generation for Wordle data
| -rw-r--r-- | og-generator.js | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/og-generator.js b/og-generator.js new file mode 100644 index 0000000..2fab20e --- /dev/null +++ b/og-generator.js @@ -0,0 +1,141 @@ +/** + * @typedef {Object} WordleData + * @property {number} id + * @property {string} solution + * @property {string} print_date + * @property {number} days_since_launch + * @property {string} editor + */ + +/** + * @param {WordleData} data + * @param {Date} date + * @returns {Promise<string>} + */ +async function generateOGImage(data, date) { + const canvas = document.getElementById('ogCanvas'); + const ctx = canvas.getContext('2d'); + + canvas.width = 1200; + canvas.height = 630; + + const isDark = document.documentElement.getAttribute('data-theme') === 'dark'; + + const bgColor = isDark ? '#121213' : '#e8e4d9'; + const cardBg = isDark ? '#2a2a2b' : '#f9f7f0'; + const textColor = isDark ? '#d7dadc' : '#2c2416'; + const accentColor = isDark ? '#538d4e' : '#6aaa64'; + const accentDark = isDark ? '#6aaa64' : '#538d4e'; + + ctx.fillStyle = bgColor; + ctx.fillRect(0, 0, 1200, 630); + + drawCard(ctx, 100, 100, 1000, 430, cardBg, isDark); + + ctx.fillStyle = textColor; + ctx.font = 'bold 48px Poppins, sans-serif'; + ctx.textAlign = 'center'; + ctx.fillText('🎯 Unwordled', 600, 180); + + ctx.font = '28px Poppins, sans-serif'; + ctx.fillStyle = isDark ? '#818384' : '#6b5d4f'; + const dateStr = date.toLocaleDateString('en-US', { + month: 'long', + day: 'numeric', + year: 'numeric' + }); + ctx.fillText(dateStr, 600, 220); + + const letters = data.solution.toUpperCase().split(''); + const boxSize = 100; + const gap = 12; + const totalWidth = letters.length * boxSize + (letters.length - 1) * gap; + const startX = (1200 - totalWidth) / 2; + const startY = 280; + + letters.forEach((letter, i) => { + const x = startX + i * (boxSize + gap); + drawLetterBox(ctx, x, startY, boxSize, letter, accentColor, accentDark, isDark); + }); + + ctx.fillStyle = isDark ? '#818384' : '#6b5d4f'; + ctx.font = '20px Poppins, sans-serif'; + ctx.fillText(`Puzzle #${data.id}`, 600, 460); + + return canvas.toDataURL('image/png'); +} + +/** + * @param {CanvasRenderingContext2D} ctx + * @param {number} x + * @param {number} y + * @param {number} w + * @param {number} h + * @param {string} bgColor + * @param {boolean} isDark + */ +function drawCard(ctx, x, y, w, h, bgColor, isDark) { + ctx.save(); + + if (!isDark) { + ctx.shadowColor = 'rgba(0, 0, 0, 0.2)'; + ctx.shadowBlur = 16; + ctx.shadowOffsetX = 8; + ctx.shadowOffsetY = 8; + } + + ctx.fillStyle = bgColor; + ctx.beginPath(); + ctx.roundRect(x, y, w, h, 20); + ctx.fill(); + + if (!isDark) { + ctx.shadowColor = 'rgba(255, 255, 255, 0.8)'; + ctx.shadowOffsetX = -8; + ctx.shadowOffsetY = -8; + ctx.fill(); + } + + ctx.restore(); +} + +/** + * @param {CanvasRenderingContext2D} ctx + * @param {number} x + * @param {number} y + * @param {number} size + * @param {string} letter + * @param {string} color + * @param {string} borderColor + * @param {boolean} isDark + */ +function drawLetterBox(ctx, x, y, size, letter, color, borderColor, isDark) { + ctx.save(); + + ctx.shadowColor = isDark ? 'rgba(0, 0, 0, 0.5)' : 'rgba(0, 0, 0, 0.3)'; + ctx.shadowBlur = 10; + ctx.shadowOffsetX = 4; + ctx.shadowOffsetY = 4; + + ctx.fillStyle = color; + ctx.strokeStyle = borderColor; + ctx.lineWidth = 3; + ctx.beginPath(); + ctx.roundRect(x, y, size, size, 8); + ctx.fill(); + ctx.stroke(); + + ctx.shadowColor = 'transparent'; + + ctx.fillStyle = 'white'; + ctx.font = `bold ${size * 0.5}px Poppins, sans-serif`; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(letter, x + size / 2, y + size / 2); + + ctx.restore(); +} + +if (typeof window !== 'undefined') { + window.generateOGImage = generateOGImage; +} |
