shellfie 2.0.18 → 2.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -46
- package/dist/highlight/index.d.ts +41 -0
- package/dist/highlight/index.d.ts.map +1 -0
- package/dist/highlight/index.js +309 -0
- package/dist/highlight/index.js.map +1 -0
- package/dist/highlight/languages/bash.d.ts +3 -0
- package/dist/highlight/languages/bash.d.ts.map +1 -0
- package/dist/highlight/languages/bash.js +78 -0
- package/dist/highlight/languages/bash.js.map +1 -0
- package/dist/highlight/languages/c.d.ts +4 -0
- package/dist/highlight/languages/c.d.ts.map +1 -0
- package/dist/highlight/languages/c.js +101 -0
- package/dist/highlight/languages/c.js.map +1 -0
- package/dist/highlight/languages/csharp.d.ts +3 -0
- package/dist/highlight/languages/csharp.d.ts.map +1 -0
- package/dist/highlight/languages/csharp.js +78 -0
- package/dist/highlight/languages/csharp.js.map +1 -0
- package/dist/highlight/languages/go.d.ts +3 -0
- package/dist/highlight/languages/go.d.ts.map +1 -0
- package/dist/highlight/languages/go.js +47 -0
- package/dist/highlight/languages/go.js.map +1 -0
- package/dist/highlight/languages/html.d.ts +3 -0
- package/dist/highlight/languages/html.d.ts.map +1 -0
- package/dist/highlight/languages/html.js +44 -0
- package/dist/highlight/languages/html.js.map +1 -0
- package/dist/highlight/languages/index.d.ts +26 -0
- package/dist/highlight/languages/index.d.ts.map +1 -0
- package/dist/highlight/languages/index.js +65 -0
- package/dist/highlight/languages/index.js.map +1 -0
- package/dist/highlight/languages/java.d.ts +3 -0
- package/dist/highlight/languages/java.d.ts.map +1 -0
- package/dist/highlight/languages/java.js +57 -0
- package/dist/highlight/languages/java.js.map +1 -0
- package/dist/highlight/languages/javascript.d.ts +3 -0
- package/dist/highlight/languages/javascript.d.ts.map +1 -0
- package/dist/highlight/languages/javascript.js +53 -0
- package/dist/highlight/languages/javascript.js.map +1 -0
- package/dist/highlight/languages/json.d.ts +3 -0
- package/dist/highlight/languages/json.d.ts.map +1 -0
- package/dist/highlight/languages/json.js +25 -0
- package/dist/highlight/languages/json.js.map +1 -0
- package/dist/highlight/languages/python.d.ts +3 -0
- package/dist/highlight/languages/python.d.ts.map +1 -0
- package/dist/highlight/languages/python.js +80 -0
- package/dist/highlight/languages/python.js.map +1 -0
- package/dist/highlight/languages/rust.d.ts +3 -0
- package/dist/highlight/languages/rust.d.ts.map +1 -0
- package/dist/highlight/languages/rust.js +68 -0
- package/dist/highlight/languages/rust.js.map +1 -0
- package/dist/highlight/languages/typescript.d.ts +3 -0
- package/dist/highlight/languages/typescript.d.ts.map +1 -0
- package/dist/highlight/languages/typescript.js +77 -0
- package/dist/highlight/languages/typescript.js.map +1 -0
- package/dist/highlight/tokenizer.d.ts +41 -0
- package/dist/highlight/tokenizer.d.ts.map +1 -0
- package/dist/highlight/tokenizer.js +147 -0
- package/dist/highlight/tokenizer.js.map +1 -0
- package/dist/highlight/types.d.ts +47 -0
- package/dist/highlight/types.d.ts.map +1 -0
- package/dist/highlight/types.js +27 -0
- package/dist/highlight/types.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -3
- package/dist/index.js.map +1 -1
- package/dist/renderer/customGlyphs.d.ts +1 -0
- package/dist/renderer/customGlyphs.d.ts.map +1 -1
- package/dist/renderer/customGlyphs.js +179 -90
- package/dist/renderer/customGlyphs.js.map +1 -1
- package/dist/renderer/index.d.ts.map +1 -1
- package/dist/renderer/index.js +11 -4
- package/dist/renderer/index.js.map +1 -1
- package/dist/renderer/text.d.ts.map +1 -1
- package/dist/renderer/text.js +10 -3
- package/dist/renderer/text.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -9,6 +9,62 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.isCustomGlyph = isCustomGlyph;
|
|
10
10
|
exports.containsCustomGlyphs = containsCustomGlyphs;
|
|
11
11
|
exports.renderCustomGlyph = renderCustomGlyph;
|
|
12
|
+
/**
|
|
13
|
+
* Round a coordinate value to 2 decimal places to eliminate floating-point precision artifacts
|
|
14
|
+
* (e.g., 19.599999999999998 → 19.6) while preserving enough precision to avoid gaps between blocks.
|
|
15
|
+
*/
|
|
16
|
+
function r(value) {
|
|
17
|
+
return Math.round(value * 100) / 100;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Parse a color string (hex, rgb, rgba) and return [r, g, b] components (0-255).
|
|
21
|
+
*/
|
|
22
|
+
function parseColor(color) {
|
|
23
|
+
// Handle hex colors
|
|
24
|
+
if (color.startsWith('#')) {
|
|
25
|
+
const hex = color.slice(1);
|
|
26
|
+
if (hex.length === 3) {
|
|
27
|
+
return [
|
|
28
|
+
parseInt(hex[0] + hex[0], 16),
|
|
29
|
+
parseInt(hex[1] + hex[1], 16),
|
|
30
|
+
parseInt(hex[2] + hex[2], 16),
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
if (hex.length >= 6) {
|
|
34
|
+
return [
|
|
35
|
+
parseInt(hex.slice(0, 2), 16),
|
|
36
|
+
parseInt(hex.slice(2, 4), 16),
|
|
37
|
+
parseInt(hex.slice(4, 6), 16),
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Handle rgb/rgba colors
|
|
42
|
+
const rgbMatch = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
|
43
|
+
if (rgbMatch) {
|
|
44
|
+
return [
|
|
45
|
+
parseInt(rgbMatch[1], 10),
|
|
46
|
+
parseInt(rgbMatch[2], 10),
|
|
47
|
+
parseInt(rgbMatch[3], 10),
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
// Fallback to black
|
|
51
|
+
return [0, 0, 0];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Blend foreground color with background color at given opacity.
|
|
55
|
+
* Returns a solid hex color that looks like the foreground at the given opacity over the background.
|
|
56
|
+
*/
|
|
57
|
+
function blendColors(fg, bg, opacity) {
|
|
58
|
+
const [fgR, fgG, fgB] = parseColor(fg);
|
|
59
|
+
const [bgR, bgG, bgB] = parseColor(bg);
|
|
60
|
+
// Blend: result = fg * opacity + bg * (1 - opacity)
|
|
61
|
+
const r = Math.round(fgR * opacity + bgR * (1 - opacity));
|
|
62
|
+
const g = Math.round(fgG * opacity + bgG * (1 - opacity));
|
|
63
|
+
const b = Math.round(fgB * opacity + bgB * (1 - opacity));
|
|
64
|
+
// Return as hex
|
|
65
|
+
const toHex = (n) => n.toString(16).padStart(2, '0');
|
|
66
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
67
|
+
}
|
|
12
68
|
function isCustomGlyph(codePoint) {
|
|
13
69
|
return ((codePoint >= 0x2500 && codePoint <= 0x257f) ||
|
|
14
70
|
(codePoint >= 0x2580 && codePoint <= 0x259f) ||
|
|
@@ -39,10 +95,10 @@ function renderCustomGlyph(char, ctx) {
|
|
|
39
95
|
// Black Square (U+25A0) - render as cell-width square, vertically centered
|
|
40
96
|
if (codePoint === 0x25a0) {
|
|
41
97
|
const { cellWidth, cellHeight, x, y, color } = ctx;
|
|
42
|
-
const size = cellWidth;
|
|
43
|
-
const squareY = y + (cellHeight -
|
|
98
|
+
const size = r(cellWidth);
|
|
99
|
+
const squareY = r(y + (cellHeight - cellWidth) / 2);
|
|
44
100
|
return {
|
|
45
|
-
svg: `<rect x="${x}" y="${squareY}" width="${size}" height="${size}" fill="${color}" shape-rendering="crispEdges"/>`,
|
|
101
|
+
svg: `<rect x="${r(x)}" y="${squareY}" width="${size}" height="${size}" fill="${color}" shape-rendering="crispEdges"/>`,
|
|
46
102
|
handled: true,
|
|
47
103
|
};
|
|
48
104
|
}
|
|
@@ -202,8 +258,13 @@ function renderBoxDrawing(codePoint, ctx) {
|
|
|
202
258
|
return { svg: '', handled: false };
|
|
203
259
|
}
|
|
204
260
|
const { cellWidth, cellHeight, x, y, color, lineWidth, heavyLineWidth } = ctx;
|
|
205
|
-
|
|
206
|
-
const
|
|
261
|
+
// Pre-compute rounded values
|
|
262
|
+
const rx = r(x);
|
|
263
|
+
const ry = r(y);
|
|
264
|
+
const rBottom = r(y + cellHeight);
|
|
265
|
+
const rRight = r(x + cellWidth);
|
|
266
|
+
const centerX = r(x + cellWidth / 2);
|
|
267
|
+
const centerY = r(y + cellHeight / 2);
|
|
207
268
|
const getWidth = (type) => {
|
|
208
269
|
if (type === 0)
|
|
209
270
|
return 0;
|
|
@@ -213,7 +274,7 @@ function renderBoxDrawing(codePoint, ctx) {
|
|
|
213
274
|
return heavyLineWidth;
|
|
214
275
|
return lineWidth;
|
|
215
276
|
};
|
|
216
|
-
const doubleOffset = lineWidth * 1.5;
|
|
277
|
+
const doubleOffset = r(lineWidth * 1.5);
|
|
217
278
|
const hasDoubleUp = segments.up === 3;
|
|
218
279
|
const hasDoubleDown = segments.down === 3;
|
|
219
280
|
const hasDoubleLeft = segments.left === 3;
|
|
@@ -224,240 +285,268 @@ function renderBoxDrawing(codePoint, ctx) {
|
|
|
224
285
|
const paths = [];
|
|
225
286
|
if (segments.up > 0) {
|
|
226
287
|
if (segments.up === 3) {
|
|
227
|
-
paths.push(`<line x1="${centerX - doubleOffset}" y1="${
|
|
288
|
+
paths.push(`<line x1="${r(centerX - doubleOffset)}" y1="${ry}" x2="${r(centerX - doubleOffset)}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${r(centerX + doubleOffset)}" y1="${ry}" x2="${r(centerX + doubleOffset)}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
228
289
|
}
|
|
229
290
|
else {
|
|
230
291
|
const w = getWidth(segments.up);
|
|
231
|
-
paths.push(`<line x1="${centerX}" y1="${
|
|
292
|
+
paths.push(`<line x1="${centerX}" y1="${ry}" x2="${centerX}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
|
|
232
293
|
}
|
|
233
294
|
}
|
|
234
295
|
if (segments.down > 0) {
|
|
235
296
|
if (segments.down === 3) {
|
|
236
|
-
paths.push(`<line x1="${centerX - doubleOffset}" y1="${centerY}" x2="${centerX - doubleOffset}" y2="${
|
|
297
|
+
paths.push(`<line x1="${r(centerX - doubleOffset)}" y1="${centerY}" x2="${r(centerX - doubleOffset)}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${r(centerX + doubleOffset)}" y1="${centerY}" x2="${r(centerX + doubleOffset)}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
237
298
|
}
|
|
238
299
|
else {
|
|
239
300
|
const w = getWidth(segments.down);
|
|
240
|
-
paths.push(`<line x1="${centerX}" y1="${centerY}" x2="${centerX}" y2="${
|
|
301
|
+
paths.push(`<line x1="${centerX}" y1="${centerY}" x2="${centerX}" y2="${rBottom}" stroke="${color}" stroke-width="${w}"/>`);
|
|
241
302
|
}
|
|
242
303
|
}
|
|
243
304
|
if (segments.left > 0) {
|
|
244
305
|
if (segments.left === 3) {
|
|
245
|
-
paths.push(`<line x1="${
|
|
306
|
+
paths.push(`<line x1="${rx}" y1="${r(centerY - doubleOffset)}" x2="${centerX}" y2="${r(centerY - doubleOffset)}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${rx}" y1="${r(centerY + doubleOffset)}" x2="${centerX}" y2="${r(centerY + doubleOffset)}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
246
307
|
}
|
|
247
308
|
else {
|
|
248
309
|
const w = getWidth(segments.left);
|
|
249
|
-
paths.push(`<line x1="${
|
|
310
|
+
paths.push(`<line x1="${rx}" y1="${centerY}" x2="${centerX}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
|
|
250
311
|
}
|
|
251
312
|
}
|
|
252
313
|
if (segments.right > 0) {
|
|
253
314
|
if (segments.right === 3) {
|
|
254
|
-
paths.push(`<line x1="${centerX}" y1="${centerY - doubleOffset}" x2="${
|
|
315
|
+
paths.push(`<line x1="${centerX}" y1="${r(centerY - doubleOffset)}" x2="${rRight}" y2="${r(centerY - doubleOffset)}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${centerX}" y1="${r(centerY + doubleOffset)}" x2="${rRight}" y2="${r(centerY + doubleOffset)}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
255
316
|
}
|
|
256
317
|
else {
|
|
257
318
|
const w = getWidth(segments.right);
|
|
258
|
-
paths.push(`<line x1="${centerX}" y1="${centerY}" x2="${
|
|
319
|
+
paths.push(`<line x1="${centerX}" y1="${centerY}" x2="${rRight}" y2="${centerY}" stroke="${color}" stroke-width="${w}"/>`);
|
|
259
320
|
}
|
|
260
321
|
}
|
|
261
322
|
return { svg: paths.join(''), handled: true };
|
|
262
323
|
}
|
|
263
324
|
function renderDoubleLineCorner(segments, ctx, doubleOffset) {
|
|
264
325
|
const { cellWidth, cellHeight, x, y, color, lineWidth } = ctx;
|
|
265
|
-
|
|
266
|
-
const
|
|
326
|
+
// Pre-compute rounded values
|
|
327
|
+
const rx = r(x);
|
|
328
|
+
const ry = r(y);
|
|
329
|
+
const rBottom = r(y + cellHeight);
|
|
330
|
+
const rRight = r(x + cellWidth);
|
|
331
|
+
const centerX = r(x + cellWidth / 2);
|
|
332
|
+
const centerY = r(y + cellHeight / 2);
|
|
267
333
|
const paths = [];
|
|
268
334
|
const hasUp = segments.up === 3;
|
|
269
335
|
const hasDown = segments.down === 3;
|
|
270
336
|
const hasLeft = segments.left === 3;
|
|
271
337
|
const hasRight = segments.right === 3;
|
|
272
|
-
const outerLeft = centerX - doubleOffset;
|
|
273
|
-
const outerRight = centerX + doubleOffset;
|
|
274
|
-
const outerTop = centerY - doubleOffset;
|
|
275
|
-
const outerBottom = centerY + doubleOffset;
|
|
338
|
+
const outerLeft = r(centerX - doubleOffset);
|
|
339
|
+
const outerRight = r(centerX + doubleOffset);
|
|
340
|
+
const outerTop = r(centerY - doubleOffset);
|
|
341
|
+
const outerBottom = r(centerY + doubleOffset);
|
|
276
342
|
if (hasUp && hasRight && !hasDown && !hasLeft) {
|
|
277
|
-
paths.push(`<path d="M ${outerLeft} ${
|
|
278
|
-
paths.push(`<path d="M ${outerRight} ${
|
|
343
|
+
paths.push(`<path d="M ${outerLeft} ${ry} L ${outerLeft} ${outerBottom} L ${rRight} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
344
|
+
paths.push(`<path d="M ${outerRight} ${ry} L ${outerRight} ${outerTop} L ${rRight} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
279
345
|
}
|
|
280
346
|
else if (hasDown && hasRight && !hasUp && !hasLeft) {
|
|
281
|
-
paths.push(`<path d="M ${outerLeft} ${
|
|
282
|
-
paths.push(`<path d="M ${outerRight} ${
|
|
347
|
+
paths.push(`<path d="M ${outerLeft} ${rBottom} L ${outerLeft} ${outerTop} L ${rRight} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
348
|
+
paths.push(`<path d="M ${outerRight} ${rBottom} L ${outerRight} ${outerBottom} L ${rRight} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
283
349
|
}
|
|
284
350
|
else if (hasDown && hasLeft && !hasUp && !hasRight) {
|
|
285
|
-
paths.push(`<path d="M ${outerRight} ${
|
|
286
|
-
paths.push(`<path d="M ${outerLeft} ${
|
|
351
|
+
paths.push(`<path d="M ${outerRight} ${rBottom} L ${outerRight} ${outerTop} L ${rx} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
352
|
+
paths.push(`<path d="M ${outerLeft} ${rBottom} L ${outerLeft} ${outerBottom} L ${rx} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
287
353
|
}
|
|
288
354
|
else if (hasUp && hasLeft && !hasDown && !hasRight) {
|
|
289
|
-
paths.push(`<path d="M ${outerRight} ${
|
|
290
|
-
paths.push(`<path d="M ${outerLeft} ${
|
|
355
|
+
paths.push(`<path d="M ${outerRight} ${ry} L ${outerRight} ${outerBottom} L ${rx} ${outerBottom}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
356
|
+
paths.push(`<path d="M ${outerLeft} ${ry} L ${outerLeft} ${outerTop} L ${rx} ${outerTop}" fill="none" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
291
357
|
}
|
|
292
358
|
else if (hasUp && hasDown && hasRight && !hasLeft) {
|
|
293
|
-
paths.push(`<line x1="${outerLeft}" y1="${
|
|
294
|
-
paths.push(`<line x1="${outerRight}" y1="${
|
|
295
|
-
paths.push(`<line x1="${outerRight}" y1="${outerTop}" x2="${
|
|
359
|
+
paths.push(`<line x1="${outerLeft}" y1="${ry}" x2="${outerLeft}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
360
|
+
paths.push(`<line x1="${outerRight}" y1="${ry}" x2="${outerRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${outerRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
361
|
+
paths.push(`<line x1="${outerRight}" y1="${outerTop}" x2="${rRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${rRight}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
296
362
|
}
|
|
297
363
|
else if (hasUp && hasDown && hasLeft && !hasRight) {
|
|
298
|
-
paths.push(`<line x1="${outerRight}" y1="${
|
|
299
|
-
paths.push(`<line x1="${outerLeft}" y1="${
|
|
300
|
-
paths.push(`<line x1="${
|
|
364
|
+
paths.push(`<line x1="${outerRight}" y1="${ry}" x2="${outerRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
365
|
+
paths.push(`<line x1="${outerLeft}" y1="${ry}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerLeft}" y1="${outerBottom}" x2="${outerLeft}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
366
|
+
paths.push(`<line x1="${rx}" y1="${outerTop}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${rx}" y1="${outerBottom}" x2="${outerLeft}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
301
367
|
}
|
|
302
368
|
else if (hasDown && hasLeft && hasRight && !hasUp) {
|
|
303
|
-
paths.push(`<line x1="${
|
|
304
|
-
paths.push(`<line x1="${
|
|
305
|
-
paths.push(`<line x1="${outerLeft}" y1="${outerBottom}" x2="${outerLeft}" y2="${
|
|
369
|
+
paths.push(`<line x1="${rx}" y1="${outerTop}" x2="${rRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
370
|
+
paths.push(`<line x1="${rx}" y1="${outerBottom}" x2="${outerLeft}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${rRight}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
371
|
+
paths.push(`<line x1="${outerLeft}" y1="${outerBottom}" x2="${outerLeft}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${outerRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
306
372
|
}
|
|
307
373
|
else if (hasUp && hasLeft && hasRight && !hasDown) {
|
|
308
|
-
paths.push(`<line x1="${
|
|
309
|
-
paths.push(`<line x1="${
|
|
310
|
-
paths.push(`<line x1="${outerLeft}" y1="${
|
|
374
|
+
paths.push(`<line x1="${rx}" y1="${outerBottom}" x2="${rRight}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
375
|
+
paths.push(`<line x1="${rx}" y1="${outerTop}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerTop}" x2="${rRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
376
|
+
paths.push(`<line x1="${outerLeft}" y1="${ry}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${ry}" x2="${outerRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
311
377
|
}
|
|
312
378
|
else if (hasUp && hasDown && hasLeft && hasRight) {
|
|
313
|
-
paths.push(`<line x1="${outerLeft}" y1="${
|
|
314
|
-
paths.push(`<line x1="${
|
|
379
|
+
paths.push(`<line x1="${outerLeft}" y1="${ry}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerLeft}" y1="${outerBottom}" x2="${outerLeft}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${ry}" x2="${outerRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${outerRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
380
|
+
paths.push(`<line x1="${rx}" y1="${outerTop}" x2="${outerLeft}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerTop}" x2="${rRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${rx}" y1="${outerBottom}" x2="${outerLeft}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${outerBottom}" x2="${rRight}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
315
381
|
}
|
|
316
382
|
else {
|
|
317
383
|
if (hasUp) {
|
|
318
|
-
paths.push(`<line x1="${outerLeft}" y1="${
|
|
384
|
+
paths.push(`<line x1="${outerLeft}" y1="${ry}" x2="${outerLeft}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${ry}" x2="${outerRight}" y2="${centerY}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
319
385
|
}
|
|
320
386
|
if (hasDown) {
|
|
321
|
-
paths.push(`<line x1="${outerLeft}" y1="${centerY}" x2="${outerLeft}" y2="${
|
|
387
|
+
paths.push(`<line x1="${outerLeft}" y1="${centerY}" x2="${outerLeft}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${outerRight}" y1="${centerY}" x2="${outerRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
322
388
|
}
|
|
323
389
|
if (hasLeft) {
|
|
324
|
-
paths.push(`<line x1="${
|
|
390
|
+
paths.push(`<line x1="${rx}" y1="${outerTop}" x2="${centerX}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${rx}" y1="${outerBottom}" x2="${centerX}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
325
391
|
}
|
|
326
392
|
if (hasRight) {
|
|
327
|
-
paths.push(`<line x1="${centerX}" y1="${outerTop}" x2="${
|
|
393
|
+
paths.push(`<line x1="${centerX}" y1="${outerTop}" x2="${rRight}" y2="${outerTop}" stroke="${color}" stroke-width="${lineWidth}"/>`, `<line x1="${centerX}" y1="${outerBottom}" x2="${rRight}" y2="${outerBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
328
394
|
}
|
|
329
395
|
}
|
|
330
396
|
return { svg: paths.join(''), handled: true };
|
|
331
397
|
}
|
|
332
398
|
function renderDiagonalLine(codePoint, ctx) {
|
|
333
399
|
const { cellWidth, cellHeight, x, y, color, lineWidth } = ctx;
|
|
400
|
+
const rx = r(x);
|
|
401
|
+
const ry = r(y);
|
|
402
|
+
const rBottom = r(y + cellHeight);
|
|
403
|
+
const rRight = r(x + cellWidth);
|
|
334
404
|
const paths = [];
|
|
335
405
|
if (codePoint === 0x2571 || codePoint === 0x2573) {
|
|
336
|
-
paths.push(`<line x1="${
|
|
406
|
+
paths.push(`<line x1="${rx}" y1="${rBottom}" x2="${rRight}" y2="${ry}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
337
407
|
}
|
|
338
408
|
if (codePoint === 0x2572 || codePoint === 0x2573) {
|
|
339
|
-
paths.push(`<line x1="${
|
|
409
|
+
paths.push(`<line x1="${rx}" y1="${ry}" x2="${rRight}" y2="${rBottom}" stroke="${color}" stroke-width="${lineWidth}"/>`);
|
|
340
410
|
}
|
|
341
411
|
return { svg: paths.join(''), handled: true };
|
|
342
412
|
}
|
|
343
413
|
// Block Elements (U+2580-U+259F)
|
|
344
414
|
function renderBlockElement(codePoint, ctx) {
|
|
345
|
-
const { cellWidth, cellHeight, x, y, color } = ctx;
|
|
415
|
+
const { cellWidth, cellHeight, x, y, color, backgroundColor } = ctx;
|
|
346
416
|
const crisp = ' shape-rendering="crispEdges"';
|
|
417
|
+
// Pre-compute rounded values for common fractions
|
|
418
|
+
const w = r(cellWidth);
|
|
419
|
+
const h = r(cellHeight);
|
|
420
|
+
const w2 = r(cellWidth / 2);
|
|
421
|
+
const w4 = r(cellWidth / 4);
|
|
422
|
+
const w8 = r(cellWidth / 8);
|
|
423
|
+
const w38 = r(cellWidth * 3 / 8);
|
|
424
|
+
const w58 = r(cellWidth * 5 / 8);
|
|
425
|
+
const w34 = r(cellWidth * 3 / 4);
|
|
426
|
+
const w78 = r(cellWidth * 7 / 8);
|
|
427
|
+
const h2 = r(cellHeight / 2);
|
|
428
|
+
const h4 = r(cellHeight / 4);
|
|
429
|
+
const h8 = r(cellHeight / 8);
|
|
430
|
+
const h38 = r(cellHeight * 3 / 8);
|
|
431
|
+
const h58 = r(cellHeight * 5 / 8);
|
|
432
|
+
const h34 = r(cellHeight * 3 / 4);
|
|
433
|
+
const h78 = r(cellHeight * 7 / 8);
|
|
434
|
+
const rx = r(x);
|
|
435
|
+
const ry = r(y);
|
|
347
436
|
let svg = '';
|
|
348
437
|
switch (codePoint) {
|
|
349
438
|
case 0x2580: // Upper half block
|
|
350
|
-
svg = `<rect x="${
|
|
439
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`;
|
|
351
440
|
break;
|
|
352
441
|
case 0x2581: // Lower 1/8
|
|
353
|
-
svg = `<rect x="${
|
|
442
|
+
svg = `<rect x="${rx}" y="${r(y + h78)}" width="${w}" height="${h8}" fill="${color}"${crisp}/>`;
|
|
354
443
|
break;
|
|
355
444
|
case 0x2582: // Lower 1/4
|
|
356
|
-
svg = `<rect x="${
|
|
445
|
+
svg = `<rect x="${rx}" y="${r(y + h34)}" width="${w}" height="${h4}" fill="${color}"${crisp}/>`;
|
|
357
446
|
break;
|
|
358
447
|
case 0x2583: // Lower 3/8
|
|
359
|
-
svg = `<rect x="${
|
|
448
|
+
svg = `<rect x="${rx}" y="${r(y + h58)}" width="${w}" height="${h38}" fill="${color}"${crisp}/>`;
|
|
360
449
|
break;
|
|
361
450
|
case 0x2584: // Lower half
|
|
362
|
-
svg = `<rect x="${
|
|
451
|
+
svg = `<rect x="${rx}" y="${r(y + h2)}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`;
|
|
363
452
|
break;
|
|
364
453
|
case 0x2585: // Lower 5/8
|
|
365
|
-
svg = `<rect x="${
|
|
454
|
+
svg = `<rect x="${rx}" y="${r(y + h38)}" width="${w}" height="${h58}" fill="${color}"${crisp}/>`;
|
|
366
455
|
break;
|
|
367
456
|
case 0x2586: // Lower 3/4
|
|
368
|
-
svg = `<rect x="${
|
|
457
|
+
svg = `<rect x="${rx}" y="${r(y + h4)}" width="${w}" height="${h34}" fill="${color}"${crisp}/>`;
|
|
369
458
|
break;
|
|
370
459
|
case 0x2587: // Lower 7/8
|
|
371
|
-
svg = `<rect x="${
|
|
460
|
+
svg = `<rect x="${rx}" y="${r(y + h8)}" width="${w}" height="${h78}" fill="${color}"${crisp}/>`;
|
|
372
461
|
break;
|
|
373
462
|
case 0x2588: // Full block
|
|
374
|
-
svg = `<rect x="${
|
|
463
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h}" fill="${color}"${crisp}/>`;
|
|
375
464
|
break;
|
|
376
465
|
case 0x2589: // Left 7/8
|
|
377
|
-
svg = `<rect x="${
|
|
466
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w78}" height="${h}" fill="${color}"${crisp}/>`;
|
|
378
467
|
break;
|
|
379
468
|
case 0x258a: // Left 3/4
|
|
380
|
-
svg = `<rect x="${
|
|
469
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w34}" height="${h}" fill="${color}"${crisp}/>`;
|
|
381
470
|
break;
|
|
382
471
|
case 0x258b: // Left 5/8
|
|
383
|
-
svg = `<rect x="${
|
|
472
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w58}" height="${h}" fill="${color}"${crisp}/>`;
|
|
384
473
|
break;
|
|
385
474
|
case 0x258c: // Left half
|
|
386
|
-
svg = `<rect x="${
|
|
475
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w2}" height="${h}" fill="${color}"${crisp}/>`;
|
|
387
476
|
break;
|
|
388
477
|
case 0x258d: // Left 3/8
|
|
389
|
-
svg = `<rect x="${
|
|
478
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w38}" height="${h}" fill="${color}"${crisp}/>`;
|
|
390
479
|
break;
|
|
391
480
|
case 0x258e: // Left 1/4
|
|
392
|
-
svg = `<rect x="${
|
|
481
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w4}" height="${h}" fill="${color}"${crisp}/>`;
|
|
393
482
|
break;
|
|
394
483
|
case 0x258f: // Left 1/8
|
|
395
|
-
svg = `<rect x="${
|
|
484
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w8}" height="${h}" fill="${color}"${crisp}/>`;
|
|
396
485
|
break;
|
|
397
486
|
case 0x2590: // Right half block
|
|
398
|
-
svg = `<rect x="${x +
|
|
487
|
+
svg = `<rect x="${r(x + w2)}" y="${ry}" width="${w2}" height="${h}" fill="${color}"${crisp}/>`;
|
|
399
488
|
break;
|
|
400
|
-
case 0x2591: // Light shade (25%)
|
|
401
|
-
svg = `<rect x="${
|
|
489
|
+
case 0x2591: // Light shade (25%) - pre-blend to avoid subpixel seams on high-DPI
|
|
490
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h}" fill="${blendColors(color, backgroundColor, 0.25)}"${crisp}/>`;
|
|
402
491
|
break;
|
|
403
|
-
case 0x2592: // Medium shade (50%)
|
|
404
|
-
svg = `<rect x="${
|
|
492
|
+
case 0x2592: // Medium shade (50%) - pre-blend to avoid subpixel seams on high-DPI
|
|
493
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h}" fill="${blendColors(color, backgroundColor, 0.5)}"${crisp}/>`;
|
|
405
494
|
break;
|
|
406
|
-
case 0x2593: // Dark shade (75%)
|
|
407
|
-
svg = `<rect x="${
|
|
495
|
+
case 0x2593: // Dark shade (75%) - pre-blend to avoid subpixel seams on high-DPI
|
|
496
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h}" fill="${blendColors(color, backgroundColor, 0.75)}"${crisp}/>`;
|
|
408
497
|
break;
|
|
409
498
|
case 0x2594: // Upper 1/8 block
|
|
410
|
-
svg = `<rect x="${
|
|
499
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w}" height="${h8}" fill="${color}"${crisp}/>`;
|
|
411
500
|
break;
|
|
412
501
|
case 0x2595: // Right 1/8 block
|
|
413
|
-
svg = `<rect x="${x +
|
|
502
|
+
svg = `<rect x="${r(x + w78)}" y="${ry}" width="${w8}" height="${h}" fill="${color}"${crisp}/>`;
|
|
414
503
|
break;
|
|
415
504
|
case 0x2596: // Lower left
|
|
416
|
-
svg = `<rect x="${
|
|
505
|
+
svg = `<rect x="${rx}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`;
|
|
417
506
|
break;
|
|
418
507
|
case 0x2597: // Lower right
|
|
419
|
-
svg = `<rect x="${x +
|
|
508
|
+
svg = `<rect x="${r(x + w2)}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`;
|
|
420
509
|
break;
|
|
421
510
|
case 0x2598: // Upper left
|
|
422
|
-
svg = `<rect x="${
|
|
511
|
+
svg = `<rect x="${rx}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`;
|
|
423
512
|
break;
|
|
424
513
|
case 0x2599: // Upper left, lower left, lower right
|
|
425
514
|
svg = [
|
|
426
|
-
`<rect x="${
|
|
427
|
-
`<rect x="${
|
|
515
|
+
`<rect x="${rx}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
516
|
+
`<rect x="${rx}" y="${r(y + h2)}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
428
517
|
].join('');
|
|
429
518
|
break;
|
|
430
519
|
case 0x259a: // Upper left, lower right
|
|
431
520
|
svg = [
|
|
432
|
-
`<rect x="${
|
|
433
|
-
`<rect x="${x +
|
|
521
|
+
`<rect x="${rx}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
522
|
+
`<rect x="${r(x + w2)}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
434
523
|
].join('');
|
|
435
524
|
break;
|
|
436
525
|
case 0x259b: // Upper left, upper right, lower left
|
|
437
526
|
svg = [
|
|
438
|
-
`<rect x="${
|
|
439
|
-
`<rect x="${
|
|
527
|
+
`<rect x="${rx}" y="${ry}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
528
|
+
`<rect x="${rx}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
440
529
|
].join('');
|
|
441
530
|
break;
|
|
442
531
|
case 0x259c: // Upper left, upper right, lower right
|
|
443
532
|
svg = [
|
|
444
|
-
`<rect x="${
|
|
445
|
-
`<rect x="${x +
|
|
533
|
+
`<rect x="${rx}" y="${ry}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
534
|
+
`<rect x="${r(x + w2)}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
446
535
|
].join('');
|
|
447
536
|
break;
|
|
448
537
|
case 0x259d: // Upper right
|
|
449
|
-
svg = `<rect x="${x +
|
|
538
|
+
svg = `<rect x="${r(x + w2)}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`;
|
|
450
539
|
break;
|
|
451
540
|
case 0x259e: // Upper right, lower left
|
|
452
541
|
svg = [
|
|
453
|
-
`<rect x="${x +
|
|
454
|
-
`<rect x="${
|
|
542
|
+
`<rect x="${r(x + w2)}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
543
|
+
`<rect x="${rx}" y="${r(y + h2)}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
455
544
|
].join('');
|
|
456
545
|
break;
|
|
457
546
|
case 0x259f: // Upper right, lower left, lower right
|
|
458
547
|
svg = [
|
|
459
|
-
`<rect x="${x +
|
|
460
|
-
`<rect x="${
|
|
548
|
+
`<rect x="${r(x + w2)}" y="${ry}" width="${w2}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
549
|
+
`<rect x="${rx}" y="${r(y + h2)}" width="${w}" height="${h2}" fill="${color}"${crisp}/>`,
|
|
461
550
|
].join('');
|
|
462
551
|
break;
|
|
463
552
|
default:
|