import QRCode from 'qrcode' self.onmessage = async (e) => { const { id, text, ecc, isBgTransparent, bgType, bgColor1, bgColor2, bgGradPos, fgType, fgColor1, fgColor2, fgGradPos } = e.data if (!text) { self.postMessage({ id, svgContent: '' }) return } try { let svgContent = await QRCode.toString(text, { type: 'svg', errorCorrectionLevel: ecc, margin: 1, color: { dark: fgType === 'solid' ? fgColor1 : '#000000', light: isBgTransparent ? '#00000000' : (bgType === 'solid' ? bgColor1 : '#00000000') } }) let defsHtml = '' if (fgType !== 'solid') { const isLinear = fgType === 'linear' const pos = fgGradPos || { x1: 0, y1: 0, x2: 100, y2: 100 } const r = Math.sqrt(Math.pow(pos.x2 - pos.x1, 2) + Math.pow(pos.y2 - pos.y1, 2)) defsHtml += isLinear ? `` : `` } if (!isBgTransparent && bgType !== 'solid') { const isLinear = bgType === 'linear' const pos = bgGradPos || { x1: 0, y1: 0, x2: 100, y2: 100 } const r = Math.sqrt(Math.pow(pos.x2 - pos.x1, 2) + Math.pow(pos.y2 - pos.y1, 2)) defsHtml += isLinear ? `` : `` } if (defsHtml) { svgContent = svgContent.replace('shape-rendering="crispEdges">', `shape-rendering="crispEdges">${defsHtml}`) } if (fgType !== 'solid') { // qrcode outputs so it's safe to replace svgContent = svgContent.replace(/stroke="#000000"/g, 'stroke="url(#qr-fg-grad)"') } if (!isBgTransparent && bgType !== 'solid') { // Find viewBox to inject background rect const viewBoxMatch = svgContent.match(/viewBox="0 0 (\d+) (\d+)"/) if (viewBoxMatch) { const w = viewBoxMatch[1] const h = viewBoxMatch[2] // Inject a rect immediately inside the svg svgContent = svgContent.replace('', ``) } } self.postMessage({ id, svgContent }) } catch (err) { self.postMessage({ id, error: err.message }) } }