diff --git a/static/share.js b/static/share.js index 7591233..e3df474 100644 --- a/static/share.js +++ b/static/share.js @@ -25,11 +25,110 @@ async function screenshotDOM(el, opts = {}) { if (background !== 'transparent') clone.style.background = background; if (!clone.getAttribute('xmlns')) clone.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml'); + const word = el.querySelector("h3").textContent.trim(); + const phonetic = el.querySelector(".pronun").textContent.trim(); + const [types, ...defs] = [...el.querySelectorAll("ol.defs li")].map(node => node.textContent.trim()); - const xhtml = new XMLSerializer().serializeToString(clone); - const svg = ` - ${xhtml} - `; + function charsPerLine(text, maxWidth) { + const fontSize = Math.round(width * 0.025); + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); + ctx.font = `${fontSize}px Helvetica Neue, Segoe UI, Helvetica, sans-serif`; + + return Math.floor(maxWidth / (ctx.measureText(text).width / text.length)); + } + + const renderDefs = (defs, x, y) => { + let yOffset = y; + const offset = 20; + const maxLength = charsPerLine(defs[0], width - 60); + + return defs.map((def, idx) => { + if (idx > 0) { + yOffset += vOffset; + } + + let part = ''; + const parts = []; + const words = def.split(' '); + + for (const word of words) { + if ((part + ' ' + word).trim().length <= maxLength) { + part = (part + ' ' + word).trim(); + } else { + if (part) parts.push(part); + part = word; + } + } + + if (part) parts.push(part); + + return ` + ${idx + 1}. + + ${parts.map((part, idx) => { + if (idx > 0) { + yOffset += offset; + } + return `${part}` + }).join('')} + + `; + }).join(''); + } + + const vOffset = 25; + const svg = ` + + + + + + + + + + ${word} + + + ${phonetic} + + + ${types} + + + ${renderDefs(defs, 24, 75)} + + + `; const svgBlob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' }); const url = URL.createObjectURL(svgBlob);