chess2img 0.1.4 → 0.2.1
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 +64 -1
- package/dist/index.cjs +327 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +325 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -55,8 +55,10 @@ function createEmptyBoardPosition() {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// src/core/validators.ts
|
|
58
|
+
import { createCanvas } from "canvas";
|
|
58
59
|
var SQUARE_PATTERN = /^[a-h][1-8]$/;
|
|
59
60
|
var PIECE_PATTERN = /^[prnbqkPRNBQK]$/;
|
|
61
|
+
var colorValidationContext = createCanvas(1, 1).getContext("2d");
|
|
60
62
|
function validateSize(size) {
|
|
61
63
|
if (!Number.isFinite(size) || size <= 0) {
|
|
62
64
|
throw new ValidationError(`Invalid board size: ${size}`);
|
|
@@ -109,6 +111,88 @@ function validateThemeName(name) {
|
|
|
109
111
|
}
|
|
110
112
|
return normalized;
|
|
111
113
|
}
|
|
114
|
+
function validateBorderSize(borderSize, size) {
|
|
115
|
+
const normalizedSize = validateSize(size);
|
|
116
|
+
const normalizedBorderSize = Math.round(borderSize);
|
|
117
|
+
const maxBorderSize = Math.floor(normalizedSize / 8);
|
|
118
|
+
if (!Number.isFinite(borderSize) || normalizedBorderSize < 0) {
|
|
119
|
+
throw new ValidationError(`Invalid borderSize: ${borderSize}`);
|
|
120
|
+
}
|
|
121
|
+
if (normalizedBorderSize > maxBorderSize) {
|
|
122
|
+
throw new ValidationError(
|
|
123
|
+
`Invalid borderSize: ${borderSize}. Maximum allowed for size ${normalizedSize} is ${maxBorderSize}`
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return normalizedBorderSize;
|
|
127
|
+
}
|
|
128
|
+
function validateColorString(color, label = "color") {
|
|
129
|
+
if (typeof color !== "string" || color.trim() === "") {
|
|
130
|
+
throw new ValidationError(`Invalid ${label}: ${String(color)}`);
|
|
131
|
+
}
|
|
132
|
+
const normalized = color.trim();
|
|
133
|
+
colorValidationContext.fillStyle = "#010203";
|
|
134
|
+
colorValidationContext.fillStyle = normalized;
|
|
135
|
+
const firstPass = String(colorValidationContext.fillStyle);
|
|
136
|
+
colorValidationContext.fillStyle = "#fefefe";
|
|
137
|
+
colorValidationContext.fillStyle = normalized;
|
|
138
|
+
const secondPass = String(colorValidationContext.fillStyle);
|
|
139
|
+
if (firstPass !== secondPass) {
|
|
140
|
+
throw new ValidationError(`Invalid ${label}: ${color}`);
|
|
141
|
+
}
|
|
142
|
+
return normalized;
|
|
143
|
+
}
|
|
144
|
+
function validateBoardColors(colors) {
|
|
145
|
+
if (!colors) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (colors.lightSquare !== void 0) {
|
|
149
|
+
validateColorString(colors.lightSquare, "lightSquare color");
|
|
150
|
+
}
|
|
151
|
+
if (colors.darkSquare !== void 0) {
|
|
152
|
+
validateColorString(colors.darkSquare, "darkSquare color");
|
|
153
|
+
}
|
|
154
|
+
if (colors.highlight !== void 0) {
|
|
155
|
+
validateColorString(colors.highlight, "highlight color");
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function isCoordinatesOptions(value) {
|
|
159
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
160
|
+
}
|
|
161
|
+
function isCoordinatesPosition(value) {
|
|
162
|
+
return value === "border" || value === "inside";
|
|
163
|
+
}
|
|
164
|
+
function validateCoordinatesOption(coordinates, borderSize) {
|
|
165
|
+
if (coordinates === void 0 || typeof coordinates === "boolean") {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (isCoordinatesPosition(coordinates)) {
|
|
169
|
+
if (coordinates === "border" && borderSize === 0) {
|
|
170
|
+
throw new ValidationError(
|
|
171
|
+
"coordinates position 'border' requires borderSize > 0"
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (!isCoordinatesOptions(coordinates)) {
|
|
177
|
+
throw new ValidationError(
|
|
178
|
+
"coordinates must be false, true, 'border', 'inside', or an options object"
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
if (coordinates.enabled !== void 0 && typeof coordinates.enabled !== "boolean") {
|
|
182
|
+
throw new ValidationError("coordinates.enabled must be a boolean");
|
|
183
|
+
}
|
|
184
|
+
if (coordinates.position !== void 0 && !isCoordinatesPosition(coordinates.position)) {
|
|
185
|
+
throw new ValidationError("coordinates.position must be 'border' or 'inside'");
|
|
186
|
+
}
|
|
187
|
+
if (coordinates.enabled !== false && coordinates.position === "border" && borderSize === 0) {
|
|
188
|
+
throw new ValidationError(
|
|
189
|
+
"coordinates position 'border' requires borderSize > 0"
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
if (coordinates.color !== void 0) {
|
|
193
|
+
validateColorString(coordinates.color, "coordinates.color");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
112
196
|
|
|
113
197
|
// src/core/parsers.ts
|
|
114
198
|
var PIECE_SYMBOL_TO_KEY = {
|
|
@@ -178,32 +262,103 @@ function normalizeHighlights(input) {
|
|
|
178
262
|
}
|
|
179
263
|
|
|
180
264
|
// src/render/canvas-renderer.ts
|
|
181
|
-
import { createCanvas as
|
|
265
|
+
import { createCanvas as createCanvas3 } from "canvas";
|
|
182
266
|
|
|
183
267
|
// src/core/geometry.ts
|
|
184
268
|
function createBoardGeometry({
|
|
185
269
|
size,
|
|
186
270
|
padding,
|
|
271
|
+
borderSize,
|
|
187
272
|
flipped
|
|
188
273
|
}) {
|
|
189
274
|
const [top, right, bottom, left] = padding;
|
|
190
|
-
const
|
|
275
|
+
const boardOuterSize = size;
|
|
276
|
+
const boardOuterX = left;
|
|
277
|
+
const boardOuterY = top;
|
|
278
|
+
const boardX = left + borderSize;
|
|
279
|
+
const boardY = top + borderSize;
|
|
280
|
+
const boardSize = size - borderSize * 2;
|
|
281
|
+
const squareSize = boardSize / 8;
|
|
191
282
|
const squares = Object.fromEntries(
|
|
192
283
|
SQUARES.map((square, index) => {
|
|
193
284
|
const fileIndex = index % 8;
|
|
194
285
|
const rankIndex = Math.floor(index / 8);
|
|
195
|
-
const x =
|
|
196
|
-
const y =
|
|
286
|
+
const x = boardX + (flipped ? 7 - fileIndex : fileIndex) * squareSize;
|
|
287
|
+
const y = boardY + (flipped ? 7 - rankIndex : rankIndex) * squareSize;
|
|
197
288
|
return [square, { x, y, size: squareSize }];
|
|
198
289
|
})
|
|
199
290
|
);
|
|
291
|
+
const displayedFiles = flipped ? [...FILES].reverse() : [...FILES];
|
|
292
|
+
const displayedRanks = flipped ? [...RANKS].reverse() : [...RANKS];
|
|
293
|
+
const bottomEdgeRank = flipped ? "8" : "1";
|
|
294
|
+
const leftEdgeFile = flipped ? "h" : "a";
|
|
295
|
+
const borderFileLabels = borderSize ? displayedFiles.map((file, fileIndex) => ({
|
|
296
|
+
text: file,
|
|
297
|
+
x: boardX + fileIndex * squareSize + squareSize / 2,
|
|
298
|
+
y: boardOuterY + boardOuterSize - borderSize / 2,
|
|
299
|
+
square: `${file}${bottomEdgeRank}`,
|
|
300
|
+
textAlign: "center",
|
|
301
|
+
textBaseline: "middle"
|
|
302
|
+
})) : [];
|
|
303
|
+
const borderRankLabels = borderSize ? displayedRanks.map((rank, rankIndex) => ({
|
|
304
|
+
text: rank,
|
|
305
|
+
x: boardOuterX + borderSize / 2,
|
|
306
|
+
y: boardY + rankIndex * squareSize + squareSize / 2,
|
|
307
|
+
square: `${leftEdgeFile}${rank}`,
|
|
308
|
+
textAlign: "center",
|
|
309
|
+
textBaseline: "middle"
|
|
310
|
+
})) : [];
|
|
311
|
+
const insideFileInsetX = squareSize * 0.14;
|
|
312
|
+
const insideFileInsetY = squareSize * 0.1;
|
|
313
|
+
const insideRankInsetX = squareSize * 0.14;
|
|
314
|
+
const insideRankInsetY = squareSize * 0.1;
|
|
315
|
+
const insideLabelMaxWidth = squareSize * 0.26;
|
|
316
|
+
const insideLabelMaxHeight = squareSize * 0.24;
|
|
317
|
+
const insideFileLabels = displayedFiles.map((file) => {
|
|
318
|
+
const square = `${file}${bottomEdgeRank}`;
|
|
319
|
+
const squareGeometry = squares[square];
|
|
320
|
+
return {
|
|
321
|
+
text: file,
|
|
322
|
+
x: squareGeometry.x + insideFileInsetX,
|
|
323
|
+
y: squareGeometry.y + squareGeometry.size - insideFileInsetY,
|
|
324
|
+
square,
|
|
325
|
+
textAlign: "left",
|
|
326
|
+
textBaseline: "bottom"
|
|
327
|
+
};
|
|
328
|
+
});
|
|
329
|
+
const insideRankLabels = displayedRanks.map((rank) => {
|
|
330
|
+
const square = `${leftEdgeFile}${rank}`;
|
|
331
|
+
const squareGeometry = squares[square];
|
|
332
|
+
return {
|
|
333
|
+
text: rank,
|
|
334
|
+
x: squareGeometry.x + insideRankInsetX,
|
|
335
|
+
y: squareGeometry.y + insideRankInsetY,
|
|
336
|
+
square,
|
|
337
|
+
textAlign: "left",
|
|
338
|
+
textBaseline: "top"
|
|
339
|
+
};
|
|
340
|
+
});
|
|
200
341
|
return {
|
|
201
342
|
imageWidth: left + size + right,
|
|
202
343
|
imageHeight: top + size + bottom,
|
|
203
344
|
squareSize,
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
345
|
+
borderSize,
|
|
346
|
+
boardOuterX,
|
|
347
|
+
boardOuterY,
|
|
348
|
+
boardOuterSize,
|
|
349
|
+
boardX,
|
|
350
|
+
boardY,
|
|
351
|
+
boardSize,
|
|
352
|
+
borderFileLabels,
|
|
353
|
+
borderRankLabels,
|
|
354
|
+
insideFileLabels,
|
|
355
|
+
insideRankLabels,
|
|
356
|
+
insideFileInsetX,
|
|
357
|
+
insideFileInsetY,
|
|
358
|
+
insideRankInsetX,
|
|
359
|
+
insideRankInsetY,
|
|
360
|
+
insideLabelMaxWidth,
|
|
361
|
+
insideLabelMaxHeight,
|
|
207
362
|
squares
|
|
208
363
|
};
|
|
209
364
|
}
|
|
@@ -233,7 +388,7 @@ var SourceAssetCache = class {
|
|
|
233
388
|
|
|
234
389
|
// src/render/rasterizer.ts
|
|
235
390
|
import { readFile } from "fs/promises";
|
|
236
|
-
import { createCanvas, loadImage } from "canvas";
|
|
391
|
+
import { createCanvas as createCanvas2, loadImage } from "canvas";
|
|
237
392
|
import { Resvg } from "@resvg/resvg-js";
|
|
238
393
|
var svgSourceCache = new SourceAssetCache();
|
|
239
394
|
var imageBufferCache = new SourceAssetCache();
|
|
@@ -274,7 +429,7 @@ async function rasterizeSvgAsset(filePath, squareSize) {
|
|
|
274
429
|
});
|
|
275
430
|
const pngBuffer = resvg.render().asPng();
|
|
276
431
|
const image = await loadImage(pngBuffer);
|
|
277
|
-
const canvas =
|
|
432
|
+
const canvas = createCanvas2(squareSize, squareSize);
|
|
278
433
|
const context = canvas.getContext("2d");
|
|
279
434
|
context.drawImage(image, 0, 0, squareSize, squareSize);
|
|
280
435
|
return canvas;
|
|
@@ -286,7 +441,7 @@ async function rasterizePngAsset(filePath, squareSize) {
|
|
|
286
441
|
try {
|
|
287
442
|
const pngSource = await readBinaryAsset(filePath);
|
|
288
443
|
const image = await loadImage(pngSource);
|
|
289
|
-
const canvas =
|
|
444
|
+
const canvas = createCanvas2(squareSize, squareSize);
|
|
290
445
|
const context = canvas.getContext("2d");
|
|
291
446
|
context.drawImage(image, 0, 0, squareSize, squareSize);
|
|
292
447
|
return canvas;
|
|
@@ -303,6 +458,13 @@ async function rasterizeThemeAsset(asset, squareSize) {
|
|
|
303
458
|
|
|
304
459
|
// src/render/canvas-renderer.ts
|
|
305
460
|
var pieceRasterCache = new RasterAssetCache();
|
|
461
|
+
var MIN_COORDINATE_FONT_SIZE = 8;
|
|
462
|
+
var MAX_FILE_LABEL_WIDTH_RATIO = 0.75;
|
|
463
|
+
var MAX_RANK_LABEL_WIDTH_RATIO = 0.7;
|
|
464
|
+
var MAX_LABEL_HEIGHT_RATIO = 0.7;
|
|
465
|
+
var INSIDE_COORDINATE_MAX_FONT_RATIO = 0.34;
|
|
466
|
+
var INSIDE_LIGHT_LABEL_COLOR = "rgba(255,255,255,0.6)";
|
|
467
|
+
var INSIDE_DARK_LABEL_COLOR = "rgba(0,0,0,0.45)";
|
|
306
468
|
function isDarkSquare(square) {
|
|
307
469
|
const fileIndex = square.charCodeAt(0) - 97;
|
|
308
470
|
const rankNumber = Number(square[1]);
|
|
@@ -318,15 +480,118 @@ async function getPieceRaster(themeName, pieceKey, asset, squareSize) {
|
|
|
318
480
|
pieceRasterCache.set(cacheKey, raster);
|
|
319
481
|
return raster;
|
|
320
482
|
}
|
|
483
|
+
function resolveInsideLabelColor(request, square) {
|
|
484
|
+
if (request.coordinates.color) {
|
|
485
|
+
return request.coordinates.color;
|
|
486
|
+
}
|
|
487
|
+
return isDarkSquare(square) ? INSIDE_LIGHT_LABEL_COLOR : INSIDE_DARK_LABEL_COLOR;
|
|
488
|
+
}
|
|
489
|
+
function resolveBorderCoordinateFontSize(context, geometry) {
|
|
490
|
+
const maxFontSize = Math.floor(
|
|
491
|
+
Math.min(geometry.squareSize * 0.6, geometry.borderSize * 0.65)
|
|
492
|
+
);
|
|
493
|
+
let fontSize = null;
|
|
494
|
+
for (let candidate = maxFontSize; candidate >= MIN_COORDINATE_FONT_SIZE; candidate -= 1) {
|
|
495
|
+
context.font = `${candidate}px sans-serif`;
|
|
496
|
+
const filesFit = geometry.borderFileLabels.every((label) => {
|
|
497
|
+
const metrics = context.measureText(label.text);
|
|
498
|
+
const textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
|
499
|
+
return metrics.width <= geometry.squareSize * MAX_FILE_LABEL_WIDTH_RATIO && textHeight <= geometry.borderSize * MAX_LABEL_HEIGHT_RATIO;
|
|
500
|
+
});
|
|
501
|
+
const ranksFit = geometry.borderRankLabels.every((label) => {
|
|
502
|
+
const metrics = context.measureText(label.text);
|
|
503
|
+
const textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
|
504
|
+
return metrics.width <= geometry.borderSize * MAX_RANK_LABEL_WIDTH_RATIO && textHeight <= geometry.squareSize * MAX_LABEL_HEIGHT_RATIO;
|
|
505
|
+
});
|
|
506
|
+
if (filesFit && ranksFit) {
|
|
507
|
+
fontSize = candidate;
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return fontSize;
|
|
512
|
+
}
|
|
513
|
+
function resolveInsideCoordinateFontSize(context, geometry) {
|
|
514
|
+
const maxFontSize = Math.floor(
|
|
515
|
+
geometry.squareSize * INSIDE_COORDINATE_MAX_FONT_RATIO
|
|
516
|
+
);
|
|
517
|
+
let fontSize = null;
|
|
518
|
+
for (let candidate = maxFontSize; candidate >= MIN_COORDINATE_FONT_SIZE; candidate -= 1) {
|
|
519
|
+
context.font = `${candidate}px sans-serif`;
|
|
520
|
+
const filesFit = geometry.insideFileLabels.every((label) => {
|
|
521
|
+
const metrics = context.measureText(label.text);
|
|
522
|
+
const textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
|
523
|
+
return metrics.width <= geometry.insideLabelMaxWidth && textHeight <= geometry.insideLabelMaxHeight;
|
|
524
|
+
});
|
|
525
|
+
const ranksFit = geometry.insideRankLabels.every((label) => {
|
|
526
|
+
const metrics = context.measureText(label.text);
|
|
527
|
+
const textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
|
528
|
+
return metrics.width <= geometry.insideLabelMaxWidth && textHeight <= geometry.insideLabelMaxHeight;
|
|
529
|
+
});
|
|
530
|
+
if (filesFit && ranksFit) {
|
|
531
|
+
fontSize = candidate;
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return fontSize;
|
|
536
|
+
}
|
|
537
|
+
function drawBorderCoordinates(context, request, geometry) {
|
|
538
|
+
if (geometry.borderSize === 0) {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
const fontSize = resolveBorderCoordinateFontSize(context, geometry);
|
|
542
|
+
if (fontSize === null) {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
context.fillStyle = request.coordinates.color ?? "#333";
|
|
546
|
+
context.font = `${fontSize}px sans-serif`;
|
|
547
|
+
context.textAlign = "center";
|
|
548
|
+
context.textBaseline = "middle";
|
|
549
|
+
for (const label of geometry.borderFileLabels) {
|
|
550
|
+
context.fillText(label.text, label.x, label.y);
|
|
551
|
+
}
|
|
552
|
+
for (const label of geometry.borderRankLabels) {
|
|
553
|
+
context.fillText(label.text, label.x, label.y);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
function drawInsideCoordinates(context, request, geometry) {
|
|
557
|
+
const fontSize = resolveInsideCoordinateFontSize(context, geometry);
|
|
558
|
+
if (fontSize === null) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
context.font = `${fontSize}px sans-serif`;
|
|
562
|
+
for (const label of geometry.insideFileLabels) {
|
|
563
|
+
context.fillStyle = resolveInsideLabelColor(request, label.square);
|
|
564
|
+
context.textAlign = label.textAlign;
|
|
565
|
+
context.textBaseline = label.textBaseline;
|
|
566
|
+
context.fillText(label.text, label.x, label.y);
|
|
567
|
+
}
|
|
568
|
+
for (const label of geometry.insideRankLabels) {
|
|
569
|
+
context.fillStyle = resolveInsideLabelColor(request, label.square);
|
|
570
|
+
context.textAlign = label.textAlign;
|
|
571
|
+
context.textBaseline = label.textBaseline;
|
|
572
|
+
context.fillText(label.text, label.x, label.y);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
function drawCoordinates(context, request, geometry) {
|
|
576
|
+
if (!request.coordinates.enabled) {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (request.coordinates.position === "border") {
|
|
580
|
+
drawBorderCoordinates(context, request, geometry);
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
drawInsideCoordinates(context, request, geometry);
|
|
584
|
+
}
|
|
321
585
|
var CanvasPngRenderer = class {
|
|
322
586
|
async render(request) {
|
|
323
587
|
try {
|
|
324
588
|
const geometry = createBoardGeometry({
|
|
325
589
|
size: request.size,
|
|
326
590
|
padding: request.padding,
|
|
591
|
+
borderSize: request.borderSize,
|
|
327
592
|
flipped: request.flipped
|
|
328
593
|
});
|
|
329
|
-
const canvas =
|
|
594
|
+
const canvas = createCanvas3(geometry.imageWidth, geometry.imageHeight);
|
|
330
595
|
const context = canvas.getContext("2d");
|
|
331
596
|
context.fillStyle = request.colors.lightSquare;
|
|
332
597
|
context.fillRect(0, 0, geometry.imageWidth, geometry.imageHeight);
|
|
@@ -366,6 +631,7 @@ var CanvasPngRenderer = class {
|
|
|
366
631
|
squareGeometry.size
|
|
367
632
|
);
|
|
368
633
|
}
|
|
634
|
+
drawCoordinates(context, request, geometry);
|
|
369
635
|
return canvas.toBuffer("image/png");
|
|
370
636
|
} catch (error) {
|
|
371
637
|
if (error instanceof RenderError) {
|
|
@@ -528,11 +794,16 @@ function resolveTheme({ theme, style }) {
|
|
|
528
794
|
// src/utils/normalization.ts
|
|
529
795
|
var DEFAULT_SIZE = 480;
|
|
530
796
|
var DEFAULT_PADDING = [0, 0, 0, 0];
|
|
797
|
+
var DEFAULT_BORDER_SIZE = 0;
|
|
531
798
|
var DEFAULT_COLORS = {
|
|
532
799
|
lightSquare: "#f0d9b5",
|
|
533
800
|
darkSquare: "#b58863",
|
|
534
801
|
highlight: "rgba(255, 206, 0, 0.45)"
|
|
535
802
|
};
|
|
803
|
+
var DEFAULT_COORDINATES = {
|
|
804
|
+
enabled: false,
|
|
805
|
+
position: "inside"
|
|
806
|
+
};
|
|
536
807
|
function normalizeColors(colors) {
|
|
537
808
|
return {
|
|
538
809
|
lightSquare: colors?.lightSquare ?? DEFAULT_COLORS.lightSquare,
|
|
@@ -540,17 +811,52 @@ function normalizeColors(colors) {
|
|
|
540
811
|
highlight: colors?.highlight ?? DEFAULT_COLORS.highlight
|
|
541
812
|
};
|
|
542
813
|
}
|
|
814
|
+
function normalizeCoordinates(coordinates, borderSize) {
|
|
815
|
+
if (coordinates === void 0 || coordinates === false) {
|
|
816
|
+
return { ...DEFAULT_COORDINATES };
|
|
817
|
+
}
|
|
818
|
+
const defaultPosition = borderSize > 0 ? "border" : "inside";
|
|
819
|
+
if (coordinates === true) {
|
|
820
|
+
return {
|
|
821
|
+
enabled: true,
|
|
822
|
+
position: defaultPosition,
|
|
823
|
+
color: defaultPosition === "border" ? "#333" : void 0
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
if (coordinates === "border" || coordinates === "inside") {
|
|
827
|
+
return {
|
|
828
|
+
enabled: true,
|
|
829
|
+
position: coordinates,
|
|
830
|
+
color: coordinates === "border" ? "#333" : void 0
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
const position = coordinates.position ?? defaultPosition;
|
|
834
|
+
return {
|
|
835
|
+
enabled: coordinates.enabled ?? true,
|
|
836
|
+
position,
|
|
837
|
+
color: coordinates.color ?? (position === "border" ? "#333" : void 0)
|
|
838
|
+
};
|
|
839
|
+
}
|
|
543
840
|
function normalizeRenderInputs(options) {
|
|
841
|
+
const size = validateSize(options.size ?? DEFAULT_SIZE);
|
|
842
|
+
const borderSize = validateBorderSize(
|
|
843
|
+
options.borderSize ?? DEFAULT_BORDER_SIZE,
|
|
844
|
+
size
|
|
845
|
+
);
|
|
846
|
+
validateBoardColors(options.colors);
|
|
847
|
+
validateCoordinatesOption(options.coordinates, borderSize);
|
|
544
848
|
return {
|
|
545
|
-
size
|
|
849
|
+
size,
|
|
546
850
|
padding: normalizePadding(options.padding ?? DEFAULT_PADDING),
|
|
851
|
+
borderSize,
|
|
547
852
|
flipped: options.flipped ?? false,
|
|
548
853
|
theme: resolveTheme({
|
|
549
854
|
theme: options.theme,
|
|
550
855
|
style: options.style
|
|
551
856
|
}),
|
|
552
857
|
highlightSquares: normalizeHighlights(options.highlightSquares ?? []),
|
|
553
|
-
colors: normalizeColors(options.colors)
|
|
858
|
+
colors: normalizeColors(options.colors),
|
|
859
|
+
coordinates: normalizeCoordinates(options.coordinates, borderSize)
|
|
554
860
|
};
|
|
555
861
|
}
|
|
556
862
|
|
|
@@ -599,8 +905,10 @@ var ChessImageGenerator = class {
|
|
|
599
905
|
highlights: normalized.highlightSquares,
|
|
600
906
|
size: normalized.size,
|
|
601
907
|
padding: normalized.padding,
|
|
908
|
+
borderSize: normalized.borderSize,
|
|
602
909
|
flipped: normalized.flipped,
|
|
603
|
-
colors: normalized.colors
|
|
910
|
+
colors: normalized.colors,
|
|
911
|
+
coordinates: normalized.coordinates
|
|
604
912
|
});
|
|
605
913
|
}
|
|
606
914
|
async toFile(filePath) {
|
|
@@ -640,8 +948,10 @@ async function renderChess(options) {
|
|
|
640
948
|
highlights: normalized.highlightSquares,
|
|
641
949
|
size: normalized.size,
|
|
642
950
|
padding: normalized.padding,
|
|
951
|
+
borderSize: normalized.borderSize,
|
|
643
952
|
flipped: normalized.flipped,
|
|
644
|
-
colors: normalized.colors
|
|
953
|
+
colors: normalized.colors,
|
|
954
|
+
coordinates: normalized.coordinates
|
|
645
955
|
});
|
|
646
956
|
}
|
|
647
957
|
export {
|