forked from dict/alar.ink
update: make changes to support text wrapping in multi line defs
This commit is contained in:
@@ -29,6 +29,54 @@ async function screenshotDOM(el, opts = {}) {
|
||||
const phonetic = el.querySelector(".pronun").textContent.trim();
|
||||
const [types, ...defs] = [...el.querySelectorAll("ol.defs li")].map(node => node.textContent.trim());
|
||||
|
||||
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 `
|
||||
<text class="num" x="0" y="${yOffset}">${idx + 1}.</text>
|
||||
<text class="def" x="${x}" y="${yOffset}">
|
||||
${parts.map((part, idx) => {
|
||||
if (idx > 0) {
|
||||
yOffset += offset;
|
||||
}
|
||||
return `<tspan x="${x}" y="${yOffset}">${part}</tspan>`
|
||||
}).join('')}
|
||||
</text>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
const vOffset = 25;
|
||||
const svg = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
||||
@@ -61,6 +109,10 @@ async function screenshotDOM(el, opts = {}) {
|
||||
font-size: ${Math.round(width * 0.025)}px;
|
||||
fill: #6b7280;
|
||||
}
|
||||
|
||||
text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Card background -->
|
||||
@@ -78,10 +130,7 @@ async function screenshotDOM(el, opts = {}) {
|
||||
<text class="pos" x="13" y="45">${types}</text>
|
||||
|
||||
<!-- Definition 1 -->
|
||||
${defs.map((def, idx) => `
|
||||
<text class="num" x="0" y="${75 + idx * vOffset}">${idx + 1}.</text>
|
||||
<text class="def" x="24" y="${75 + idx * vOffset}">${def}</text>
|
||||
`)}
|
||||
${renderDefs(defs, 24, 75)}
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user